Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@j0hanz/code-assistant

Package Overview
Dependencies
Maintainers
1
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@j0hanz/code-assistant - npm Package Compare versions

Comparing version
0.9.3
to
1.0.0
+2
-1
dist/lib/gemini/config.d.ts
import { HarmBlockThreshold, HarmCategory, ThinkingLevel } from '@google/genai';
export declare const DEFAULT_MODEL = "gemini-3-flash-preview";
export declare const MODEL_FALLBACK_TARGET = "gemini-2.5-flash";
export declare function getDefaultModel(): string;

@@ -9,2 +8,4 @@ /** Test-only: reset cached model so env changes take effect. */

export declare const DEFAULT_TIMEOUT_MS = 90000;
export declare const DEFAULT_TOP_K = 40;
export declare const DEFAULT_TOP_P = 0.95;
export declare const CANCELLED_REQUEST_MESSAGE = "Gemini request was cancelled.";

@@ -11,0 +12,0 @@ declare const UNKNOWN_REQUEST_CONTEXT_VALUE_STR = "unknown";

@@ -9,3 +9,2 @@ import { HarmBlockThreshold, HarmCategory, ThinkingLevel } from '@google/genai';

export const DEFAULT_MODEL = 'gemini-3-flash-preview';
export const MODEL_FALLBACK_TARGET = 'gemini-2.5-flash';
const GEMINI_MODEL_ENV_VAR = 'GEMINI_MODEL';

@@ -25,2 +24,4 @@ export function getDefaultModel() {

export const DEFAULT_TIMEOUT_MS = 90_000;
export const DEFAULT_TOP_K = 40;
export const DEFAULT_TOP_P = 0.95;
export const CANCELLED_REQUEST_MESSAGE = 'Gemini request was cancelled.';

@@ -27,0 +28,0 @@ const UNKNOWN_REQUEST_CONTEXT_VALUE_STR = 'unknown';

@@ -9,4 +9,4 @@ import { performance } from 'node:perf_hooks';

import { emitGeminiLog, geminiContext, getClient, nextRequestId, safeCallOnLog, } from './client.js';
import { batchPollIntervalMsConfig, batchTimeoutMsConfig, CANCELLED_REQUEST_MESSAGE, concurrencyWaitMsConfig, DEFAULT_MAX_RETRIES, DEFAULT_MODEL, DEFAULT_TIMEOUT_MS, getDefaultBatchMode, getDefaultIncludeThoughts, getDefaultModel, getSafetySettings, getSafetyThreshold, getThinkingConfig, maxConcurrentBatchCallsConfig, maxConcurrentCallsConfig, MODEL_FALLBACK_TARGET, } from './config.js';
import { canRetryAttempt, getNumericErrorCode, getRetryDelayMs, toUpperStringCode, } from './retry.js';
import { batchPollIntervalMsConfig, batchTimeoutMsConfig, CANCELLED_REQUEST_MESSAGE, concurrencyWaitMsConfig, DEFAULT_MAX_RETRIES, DEFAULT_TIMEOUT_MS, DEFAULT_TOP_K, DEFAULT_TOP_P, getDefaultBatchMode, getDefaultIncludeThoughts, getDefaultModel, getSafetySettings, getSafetyThreshold, getThinkingConfig, maxConcurrentBatchCallsConfig, maxConcurrentCallsConfig, } from './config.js';
import { canRetryAttempt, getRetryDelayMs, toUpperStringCode, } from './retry.js';
// ---------------------------------------------------------------------------

@@ -17,2 +17,3 @@ // Constants

const JSON_CODE_BLOCK_PATTERN = /```(?:json)?\n?([\s\S]*?)(?=\n?```)/u;
const MAX_BATCH_POLL_RETRIES = 2;
// ---------------------------------------------------------------------------

@@ -46,2 +47,4 @@ // Concurrency limiters

temperature: request.temperature ?? 1.0,
topK: request.topK ?? DEFAULT_TOP_K,
topP: request.topP ?? DEFAULT_TOP_P,
maxOutputTokens: request.maxOutputTokens ?? DEFAULT_MAX_OUTPUT_TOKENS,

@@ -222,2 +225,21 @@ safetySettings: getSafetySettings(getSafetyThreshold()),

// ---------------------------------------------------------------------------
function handleExecutionResponse(request, response) {
if (request.useCodeExecution) {
return extractCodeExecutionResponse(response);
}
if (request.useGrounding) {
return {
text: response.text,
groundingMetadata: response.candidates?.[0]?.groundingMetadata,
};
}
if (request.fileSearchStoreNames && request.fileSearchStoreNames.length > 0) {
const parts = (response.candidates?.[0]?.content?.parts ?? []);
return {
text: response.text ?? '',
parts,
};
}
return parseStructuredResponse(response.text);
}
async function executeAttempt(request, model, timeoutMs, attempt, onLog) {

@@ -243,19 +265,3 @@ const startedAt = performance.now();

}
if (request.useCodeExecution) {
return extractCodeExecutionResponse(response);
}
if (request.useGrounding) {
return {
text: response.text,
groundingMetadata: response.candidates?.[0]?.groundingMetadata,
};
}
if (request.fileSearchStoreNames && request.fileSearchStoreNames.length > 0) {
const parts = (response.candidates?.[0]?.content?.parts ?? []);
return {
text: response.text ?? '',
parts,
};
}
return parseStructuredResponse(response.text);
return handleExecutionResponse(request, response);
}

@@ -296,33 +302,2 @@ // ---------------------------------------------------------------------------

}
// ---------------------------------------------------------------------------
// Model fallback
// ---------------------------------------------------------------------------
function shouldUseModelFallback(error, model) {
return getNumericErrorCode(error) === 404 && model === DEFAULT_MODEL;
}
function omitThinkingLevel(request) {
const copy = { ...request };
Reflect.deleteProperty(copy, 'thinkingLevel');
return copy;
}
async function applyModelFallback(request, onLog, reason) {
await emitGeminiLog(onLog, 'warning', {
event: 'gemini_model_fallback',
details: {
from: DEFAULT_MODEL,
to: MODEL_FALLBACK_TARGET,
reason,
},
});
return {
model: MODEL_FALLBACK_TARGET,
request: omitThinkingLevel(request),
};
}
async function tryApplyModelFallback(error, model, request, onLog, reason) {
if (!shouldUseModelFallback(error, model)) {
return undefined;
}
return applyModelFallback(request, onLog, reason);
}
function countAttemptsMade(attempt) {

@@ -333,16 +308,8 @@ return attempt + 1;

let lastError;
let currentModel = model;
let effectiveRequest = request;
for (let attempt = 0; attempt <= maxRetries; attempt += 1) {
try {
return await executeAttempt(effectiveRequest, currentModel, timeoutMs, attempt, onLog);
return await executeAttempt(request, model, timeoutMs, attempt, onLog);
}
catch (error) {
lastError = error;
const fallback = await tryApplyModelFallback(error, currentModel, request, onLog, 'Model not found (404)');
if (fallback) {
currentModel = fallback.model;
effectiveRequest = fallback.request;
continue;
}
if (!canRetryAttempt(attempt, maxRetries, error)) {

@@ -454,4 +421,3 @@ return throwGeminiFailure(countAttemptsMade(attempt), lastError, onLog);

async function pollBatchStatusWithRetries(batches, batchName, onLog, requestSignal) {
const maxPollRetries = 2;
for (let attempt = 0; attempt <= maxPollRetries; attempt += 1) {
for (let attempt = 0; attempt <= MAX_BATCH_POLL_RETRIES; attempt += 1) {
try {

@@ -461,3 +427,3 @@ return await batches.get({ name: batchName });

catch (error) {
if (!canRetryAttempt(attempt, maxPollRetries, error)) {
if (!canRetryAttempt(attempt, MAX_BATCH_POLL_RETRIES, error)) {
throw error;

@@ -495,32 +461,13 @@ }

}
async function createBatchJobWithFallback(request, batches, model, onLog) {
let currentModel = model;
let effectiveRequest = request;
const createSignal = request.signal;
for (let attempt = 0; attempt <= 1; attempt += 1) {
try {
const createPayload = {
model: currentModel,
src: [
{
contents: [
{ role: 'user', parts: [{ text: effectiveRequest.prompt }] },
],
config: buildGenerationConfig(effectiveRequest, createSignal),
},
],
};
return await batches.create(createPayload);
}
catch (error) {
if (attempt === 0 && shouldUseModelFallback(error, currentModel)) {
const fallback = await applyModelFallback(request, onLog, 'Model not found (404) during batch create');
currentModel = fallback.model;
effectiveRequest = fallback.request;
continue;
}
throw error;
}
}
throw new Error('Unexpected state: batch creation loop exited without returning or throwing.');
async function createBatchJob(request, batches, model) {
const createPayload = {
model,
src: [
{
contents: [{ role: 'user', parts: [{ text: request.prompt }] }],
config: buildGenerationConfig(request, request.signal),
},
],
};
return await batches.create(createPayload);
}

@@ -559,3 +506,3 @@ async function pollBatchForCompletion(batches, batchName, onLog, requestSignal) {

try {
const createdJob = await createBatchJobWithFallback(request, batches, model, onLog);
const createdJob = await createBatchJob(request, batches, model);
const createdRecord = toRecord(createdJob);

@@ -562,0 +509,0 @@ batchName =

@@ -8,2 +8,4 @@ export type JsonObject = Record<string, unknown>;

temperature?: number;
topK?: number;
topP?: number;
maxOutputTokens?: number;

@@ -10,0 +12,0 @@ thinkingLevel?: GeminiThinkingLevel;

{
"name": "@j0hanz/code-assistant",
"version": "0.9.3",
"version": "1.0.0",
"mcpName": "io.github.j0hanz/code-assistant",

@@ -5,0 +5,0 @@ "description": "Gemini-powered MCP server for code analysis.",