@evomap/evolver 1.90.0 → 2.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -564
- package/bin/evolver-llm-proxy.js +3 -0
- package/bin/evolver-mcp.js +2 -0
- package/bin/evolver-proxy.js +3 -0
- package/bin/evolver.js +4 -0
- package/index.js +1 -3670
- package/package.json +32 -62
- package/CONTRIBUTING.md +0 -19
- package/LICENSE +0 -641
- package/README.ja-JP.md +0 -521
- package/README.ko-KR.md +0 -520
- package/README.zh-CN.md +0 -531
- package/SKILL.md +0 -365
- package/assets/cover.png +0 -0
- package/assets/gep/genes.seed.json +0 -496
- package/conformance/savings-core/constants.json +0 -30
- package/conformance/savings-core/golden-vectors.json +0 -333
- package/scripts/a2a_export.js +0 -63
- package/scripts/a2a_ingest.js +0 -79
- package/scripts/a2a_promote.js +0 -118
- package/scripts/analyze_by_skill.js +0 -121
- package/scripts/build_binaries.js +0 -479
- package/scripts/check-changelog.js +0 -166
- package/scripts/extract_log.js +0 -85
- package/scripts/generate_history.js +0 -75
- package/scripts/gep_append_event.js +0 -96
- package/scripts/gep_personality_report.js +0 -234
- package/scripts/human_report.js +0 -147
- package/scripts/recall-verify-report.js +0 -234
- package/scripts/recover_loop.js +0 -61
- package/scripts/refresh_stars_badge.js +0 -168
- package/scripts/seed-merchants.js +0 -91
- package/scripts/skill2recipes.js +0 -118
- package/scripts/suggest_version.js +0 -89
- package/scripts/validate-modules.js +0 -38
- package/scripts/validate-suite.js +0 -78
- package/src/adapters/claudeCode.js +0 -194
- package/src/adapters/codex.js +0 -216
- package/src/adapters/cursor.js +0 -91
- package/src/adapters/hookAdapter.js +0 -469
- package/src/adapters/kiro.js +0 -195
- package/src/adapters/opencode.js +0 -326
- package/src/adapters/scripts/_lockPaths.js +0 -74
- package/src/adapters/scripts/_memoryFiltering.js +0 -35
- package/src/adapters/scripts/_runtimePaths.js +0 -440
- package/src/adapters/scripts/evolver-session-end.js +0 -321
- package/src/adapters/scripts/evolver-session-start.js +0 -587
- package/src/adapters/scripts/evolver-signal-detect.js +0 -98
- package/src/adapters/scripts/evolver-task-recall.js +0 -173
- package/src/atp/atpExecute.js +0 -283
- package/src/atp/atpTaskPickup.js +0 -233
- package/src/atp/autoBuyer.js +0 -382
- package/src/atp/autoDeliver.js +0 -215
- package/src/atp/cli.js +0 -354
- package/src/atp/cliAutobuyPrompt.js +0 -154
- package/src/atp/consumerAgent.js +0 -157
- package/src/atp/defaultHandler.js +0 -69
- package/src/atp/heartbeatSignalsHandler.js +0 -254
- package/src/atp/hubClient.js +0 -317
- package/src/atp/index.js +0 -38
- package/src/atp/merchantAgent.js +0 -118
- package/src/atp/protocol.js +0 -41
- package/src/atp/questionComposer.js +0 -133
- package/src/atp/serviceHelper.js +0 -92
- package/src/canary.js +0 -13
- package/src/config.js +0 -351
- package/src/evolve/guards.js +0 -1
- package/src/evolve/pipeline/collect.js +0 -1
- package/src/evolve/pipeline/dispatch.js +0 -1
- package/src/evolve/pipeline/enrich.js +0 -1
- package/src/evolve/pipeline/hub.js +0 -1
- package/src/evolve/pipeline/select.js +0 -1
- package/src/evolve/pipeline/signals.js +0 -1
- package/src/evolve/utils.js +0 -1
- package/src/evolve.js +0 -1
- package/src/experiment/agentRunner.js +0 -229
- package/src/experiment/cli.js +0 -159
- package/src/experiment/comparison.js +0 -233
- package/src/experiment/metrics.js +0 -75
- package/src/forceUpdate.js +0 -991
- package/src/gep/a2a.js +0 -173
- package/src/gep/a2aProtocol.js +0 -1
- package/src/gep/analyzer.js +0 -35
- package/src/gep/antiAbuseTelemetry.js +0 -1
- package/src/gep/assetCallLog.js +0 -197
- package/src/gep/assetStore.js +0 -723
- package/src/gep/assets.js +0 -36
- package/src/gep/autoDistillConv.js +0 -1
- package/src/gep/autoDistillLlm.js +0 -1
- package/src/gep/bridge.js +0 -138
- package/src/gep/candidateEval.js +0 -1
- package/src/gep/candidates.js +0 -1
- package/src/gep/claimNudge.js +0 -121
- package/src/gep/cliContracts.js +0 -1190
- package/src/gep/contentHash.js +0 -1
- package/src/gep/conversationDistiller.js +0 -1
- package/src/gep/conversationSniffer.js +0 -1
- package/src/gep/crypto.js +0 -1
- package/src/gep/curriculum.js +0 -1
- package/src/gep/deviceId.js +0 -1
- package/src/gep/directoryClient.js +0 -115
- package/src/gep/envFingerprint.js +0 -1
- package/src/gep/epigenetics.js +0 -1
- package/src/gep/execBridge.js +0 -1
- package/src/gep/executionTrace.js +0 -291
- package/src/gep/explore.js +0 -1
- package/src/gep/featureFlags.js +0 -121
- package/src/gep/gitOps.js +0 -265
- package/src/gep/hash.js +0 -1
- package/src/gep/hostErrorClassifier.js +0 -34
- package/src/gep/hubFetch.js +0 -1
- package/src/gep/hubReview.js +0 -1
- package/src/gep/hubSearch.js +0 -1
- package/src/gep/hubVerify.js +0 -1
- package/src/gep/idleScheduler.js +0 -400
- package/src/gep/issueReporter.js +0 -416
- package/src/gep/learningSignals.js +0 -1
- package/src/gep/llmReview.js +0 -92
- package/src/gep/localStateAwareness.js +0 -243
- package/src/gep/mailboxTransport.js +0 -119
- package/src/gep/memoryGraph.js +0 -1
- package/src/gep/memoryGraphAdapter.js +0 -1
- package/src/gep/mutation.js +0 -1
- package/src/gep/narrativeMemory.js +0 -1
- package/src/gep/oauthLogin.js +0 -181
- package/src/gep/openPRRegistry.js +0 -1
- package/src/gep/paths.js +0 -522
- package/src/gep/personality.js +0 -1
- package/src/gep/policyCheck.js +0 -1
- package/src/gep/portable.js +0 -103
- package/src/gep/privacyClient.js +0 -235
- package/src/gep/prompt.js +0 -1
- package/src/gep/questionGenerator.js +0 -518
- package/src/gep/recallInject.js +0 -1
- package/src/gep/recallVerifier.js +0 -1
- package/src/gep/reflection.js +0 -1
- package/src/gep/sanitize.js +0 -264
- package/src/gep/savingsCore.js +0 -1
- package/src/gep/schemas/capsule.js +0 -170
- package/src/gep/schemas/gene.js +0 -154
- package/src/gep/schemas/index.js +0 -8
- package/src/gep/schemas/protocol.js +0 -51
- package/src/gep/schemas/task.js +0 -74
- package/src/gep/selector.js +0 -1
- package/src/gep/selfPR.js +0 -469
- package/src/gep/signals.js +0 -776
- package/src/gep/skill2gep.js +0 -1056
- package/src/gep/skill2gepAudit.js +0 -303
- package/src/gep/skill2recipes.js +0 -511
- package/src/gep/skillDistiller.js +0 -1
- package/src/gep/skillPublisher.js +0 -358
- package/src/gep/solidify.js +0 -1
- package/src/gep/strategy.js +0 -1
- package/src/gep/taskReceiver.js +0 -575
- package/src/gep/tokenSavings.js +0 -1
- package/src/gep/trajectoryExport.js +0 -1
- package/src/gep/validationReport.js +0 -55
- package/src/gep/validator/index.js +0 -411
- package/src/gep/validator/reporter.js +0 -210
- package/src/gep/validator/sandboxExecutor.js +0 -480
- package/src/gep/validator/stakeBootstrap.js +0 -357
- package/src/gep/workspaceKeychain.js +0 -1
- package/src/ops/cleanup.js +0 -80
- package/src/ops/commentary.js +0 -60
- package/src/ops/health_check.js +0 -104
- package/src/ops/index.js +0 -11
- package/src/ops/innovation.js +0 -67
- package/src/ops/lifecycle.js +0 -798
- package/src/ops/self_repair.js +0 -76
- package/src/ops/skills_monitor.js +0 -147
- package/src/ops/trigger.js +0 -33
- package/src/proxy/clientSettings.js +0 -405
- package/src/proxy/envelope.js +0 -59
- package/src/proxy/extensions/dmHandler.js +0 -45
- package/src/proxy/extensions/sessionHandler.js +0 -141
- package/src/proxy/extensions/skillUpdater.js +0 -64
- package/src/proxy/extensions/traceControl.js +0 -1
- package/src/proxy/index.js +0 -1395
- package/src/proxy/inject.js +0 -1
- package/src/proxy/lifecycle/manager.js +0 -1568
- package/src/proxy/mailbox/state.js +0 -207
- package/src/proxy/mailbox/store.js +0 -602
- package/src/proxy/router/cache_passthrough.js +0 -26
- package/src/proxy/router/features.js +0 -84
- package/src/proxy/router/gemini_route.js +0 -154
- package/src/proxy/router/messages_route.js +0 -535
- package/src/proxy/router/model_router.js +0 -113
- package/src/proxy/router/models_route.js +0 -52
- package/src/proxy/router/ollama_route.js +0 -103
- package/src/proxy/router/responses_route.js +0 -170
- package/src/proxy/router/vertex_route.js +0 -110
- package/src/proxy/server/http.js +0 -363
- package/src/proxy/server/routes.js +0 -558
- package/src/proxy/server/settings.js +0 -115
- package/src/proxy/sync/engine.js +0 -179
- package/src/proxy/sync/inbound.js +0 -211
- package/src/proxy/sync/outbound.js +0 -361
- package/src/proxy/task/monitor.js +0 -131
- package/src/proxy/trace/extractor.js +0 -1
- package/src/proxy/trace/usage.js +0 -1
- package/src/solo/breaker.js +0 -25
- package/src/solo/gitGuard.js +0 -65
- package/src/webui/client/clientJs/assets.js +0 -111
- package/src/webui/client/clientJs/bootstrap.js +0 -92
- package/src/webui/client/clientJs/common.js +0 -77
- package/src/webui/client/clientJs/i18n.js +0 -366
- package/src/webui/client/clientJs/index.js +0 -35
- package/src/webui/client/clientJs/interactions.js +0 -351
- package/src/webui/client/clientJs/overview.js +0 -152
- package/src/webui/client/clientJs/personality.js +0 -285
- package/src/webui/client/clientJs/pipelines.js +0 -330
- package/src/webui/client/indexHtml.js +0 -221
- package/src/webui/client/static.js +0 -23
- package/src/webui/client/stylesCss.js +0 -639
- package/src/webui/client/vendor/README.md +0 -15
- package/src/webui/client/vendor/echarts.min.js +0 -45
- package/src/webui/index.js +0 -14
- package/src/webui/observer/assets.js +0 -146
- package/src/webui/observer/index.js +0 -37
- package/src/webui/observer/interactions.js +0 -127
- package/src/webui/observer/jsonl.js +0 -75
- package/src/webui/observer/paths.js +0 -46
- package/src/webui/observer/personality.js +0 -43
- package/src/webui/observer/pipelineEvents.js +0 -58
- package/src/webui/observer/redact.js +0 -63
- package/src/webui/observer/runs.js +0 -356
- package/src/webui/observer/safety.js +0 -57
- package/src/webui/observer/skills.js +0 -70
- package/src/webui/observer/status.js +0 -71
- package/src/webui/server/http.js +0 -138
- package/src/webui/server/routes.js +0 -41
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
// Stateless feature extraction for the Anthropic /v1/messages request body.
|
|
4
|
-
// Mirrors the field shapes consumed by model_router.js so pickForTurn can
|
|
5
|
-
// classify without per-session state. Phase C's "empty history" mode means
|
|
6
|
-
// last_assistant_output_tokens / last_assistant_stop_reason are always 0 /
|
|
7
|
-
// null; the JS classifier never reads stop_reason anyway (verified in the
|
|
8
|
-
// fixture round-trip; documented in model_router.js).
|
|
9
|
-
|
|
10
|
-
const PLAN_RE = /\b(plan|design|architect|brainstorm|outline|think through|let'?s think)\b/i;
|
|
11
|
-
const SIMPLE_LOOKUP_MAX_CHARS = 80;
|
|
12
|
-
|
|
13
|
-
function lastMessageOfRole(messages, role) {
|
|
14
|
-
if (!Array.isArray(messages)) return null;
|
|
15
|
-
for (let i = messages.length - 1; i >= 0; i--) {
|
|
16
|
-
const m = messages[i];
|
|
17
|
-
if (m && m.role === role) return m;
|
|
18
|
-
}
|
|
19
|
-
return null;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function blocksOf(msg) {
|
|
23
|
-
if (!msg) return [];
|
|
24
|
-
const c = msg.content;
|
|
25
|
-
if (typeof c === 'string') return [{ type: 'text', text: c }];
|
|
26
|
-
return Array.isArray(c) ? c : [];
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function tailUserText(messages) {
|
|
30
|
-
if (!Array.isArray(messages) || messages.length === 0) return '';
|
|
31
|
-
const tail = messages[messages.length - 1];
|
|
32
|
-
if (!tail || tail.role !== 'user') return '';
|
|
33
|
-
return blocksOf(tail)
|
|
34
|
-
.filter((b) => b && b.type === 'text' && typeof b.text === 'string')
|
|
35
|
-
.map((b) => b.text)
|
|
36
|
-
.join('\n');
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function extractFeatures(body) {
|
|
40
|
-
const messages = Array.isArray(body && body.messages) ? body.messages : [];
|
|
41
|
-
|
|
42
|
-
const lastAssistant = lastMessageOfRole(messages, 'assistant');
|
|
43
|
-
const lastAssistantBlocks = blocksOf(lastAssistant);
|
|
44
|
-
const toolCallCount = lastAssistantBlocks.filter((b) => b && b.type === 'tool_use').length;
|
|
45
|
-
|
|
46
|
-
const tail = messages[messages.length - 1];
|
|
47
|
-
const tailIsUser = !!(tail && tail.role === 'user');
|
|
48
|
-
const tailBlocks = blocksOf(tail);
|
|
49
|
-
const lastUserIsToolResultOnly = tailIsUser
|
|
50
|
-
&& tailBlocks.length > 0
|
|
51
|
-
&& tailBlocks.every((b) => b && b.type === 'tool_result');
|
|
52
|
-
|
|
53
|
-
const userText = tailUserText(messages);
|
|
54
|
-
const userRequestedPlanning = userText.length > 0 && PLAN_RE.test(userText);
|
|
55
|
-
const userSimpleLookup = userText.length > 0
|
|
56
|
-
&& !lastUserIsToolResultOnly
|
|
57
|
-
&& !userRequestedPlanning
|
|
58
|
-
&& userText.trim().length <= SIMPLE_LOOKUP_MAX_CHARS;
|
|
59
|
-
|
|
60
|
-
// last_assistant_stop_reason is gated by the classifier's
|
|
61
|
-
// post_tool_result_synthesis branch (model_router.js parity invariant).
|
|
62
|
-
// We don't have the real Anthropic response on the request side, but the
|
|
63
|
-
// shape of the last assistant message lets us reconstruct it deterministically:
|
|
64
|
-
// an assistant message with any tool_use block must have ended with
|
|
65
|
-
// stop_reason: 'tool_use' (otherwise the API would not have returned that
|
|
66
|
-
// block); a text-only assistant message ended with 'end_turn' ('Stop' in the
|
|
67
|
-
// Rust enum). Only 'ToolUse' is read by the classifier.
|
|
68
|
-
let stopReason = null;
|
|
69
|
-
if (lastAssistant) {
|
|
70
|
-
stopReason = toolCallCount > 0 ? 'ToolUse' : 'Stop';
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
return {
|
|
74
|
-
last_assistant_tool_call_count: toolCallCount,
|
|
75
|
-
last_assistant_had_tool_call: toolCallCount > 0,
|
|
76
|
-
last_user_is_tool_result_only: lastUserIsToolResultOnly,
|
|
77
|
-
user_requested_planning: userRequestedPlanning,
|
|
78
|
-
user_simple_lookup: userSimpleLookup,
|
|
79
|
-
last_assistant_output_tokens: 0,
|
|
80
|
-
last_assistant_stop_reason: stopReason,
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
module.exports = { extractFeatures, PLAN_RE, SIMPLE_LOOKUP_MAX_CHARS };
|
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
// Gemini passthrough handler (format-aware routing, NO translation). A Gemini-shaped request — Google's native
|
|
4
|
-
// `/v1beta/models/<model>:generateContent` | `:streamGenerateContent` path, body `{contents, generationConfig,
|
|
5
|
-
// systemInstruction, tools}` — is forwarded verbatim to the Gemini upstream. The model + action live in the
|
|
6
|
-
// PATH (not the body), so we reconstruct the path (+ query like ?alt=sse) and pass it through. Trace capture
|
|
7
|
-
// mirrors the other providers (usage/finish/stream tee). Point the Gemini CLI/SDK's base URL at the proxy and
|
|
8
|
-
// it works unmodified — no Anthropic/OpenAI conversion (lossy translation is deliberately avoided).
|
|
9
|
-
|
|
10
|
-
const { createProxyTrace } = require('../trace/extractor');
|
|
11
|
-
|
|
12
|
-
const GEMINI_RESPONSE_HEADER_ALLOWLIST = new Set([
|
|
13
|
-
'content-type',
|
|
14
|
-
'retry-after',
|
|
15
|
-
'x-request-id',
|
|
16
|
-
]);
|
|
17
|
-
|
|
18
|
-
function hasGeminiUpstreamCredential() {
|
|
19
|
-
return !!(process.env.EVOMAP_GEMINI_API_KEY || process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function upstreamStatus(err, fallback = 502) {
|
|
23
|
-
const status = Number(err && err.statusCode);
|
|
24
|
-
return Number.isFinite(status) ? status : fallback;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function asUpstreamError(err, fallback = 502) {
|
|
28
|
-
if (err && err.statusCode && /^gemini upstream /.test(err.message || '')) return err;
|
|
29
|
-
const out = new Error('gemini upstream request failed');
|
|
30
|
-
out.statusCode = upstreamStatus(err, fallback);
|
|
31
|
-
out.cause = err;
|
|
32
|
-
return out;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function responseToBody(raw, status, headers, log) {
|
|
36
|
-
if (!raw) return {};
|
|
37
|
-
try {
|
|
38
|
-
return JSON.parse(raw);
|
|
39
|
-
} catch {
|
|
40
|
-
log.warn?.(JSON.stringify({
|
|
41
|
-
event: 'gemini_fallback',
|
|
42
|
-
reason: 'upstream_non_json',
|
|
43
|
-
upstream_status: status,
|
|
44
|
-
content_type: (headers && headers['content-type']) || '',
|
|
45
|
-
response_bytes: Buffer.byteLength(raw),
|
|
46
|
-
}));
|
|
47
|
-
return { error: raw };
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function copyGeminiResponseHeaders(headers = {}) {
|
|
52
|
-
const out = {};
|
|
53
|
-
for (const [name, value] of Object.entries(headers || {})) {
|
|
54
|
-
const lower = String(name || '').toLowerCase();
|
|
55
|
-
if (!GEMINI_RESPONSE_HEADER_ALLOWLIST.has(lower) && !lower.startsWith('x-goog-')) continue;
|
|
56
|
-
if (value === undefined || value === null) continue;
|
|
57
|
-
const headerValue = Array.isArray(value) ? value.join(', ') : String(value);
|
|
58
|
-
if (/[\r\n]/.test(headerValue)) continue;
|
|
59
|
-
out[lower] = headerValue;
|
|
60
|
-
}
|
|
61
|
-
return out;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// `<model>:<action>` — the model can contain dots/dashes; the action is the part after the LAST colon
|
|
65
|
-
// (generateContent | streamGenerateContent | countTokens | ...). Returns {model, action} (action '' if absent).
|
|
66
|
-
function parseModelAction(modelAction) {
|
|
67
|
-
const s = String(modelAction || '');
|
|
68
|
-
const idx = s.lastIndexOf(':');
|
|
69
|
-
if (idx === -1) return { model: s, action: '' };
|
|
70
|
-
return { model: s.slice(0, idx), action: s.slice(idx + 1) };
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function buildGeminiHandler({ geminiProxy, logger, traceStore, onTraceQueued } = {}) {
|
|
74
|
-
if (typeof geminiProxy !== 'function') {
|
|
75
|
-
throw new Error('buildGeminiHandler requires geminiProxy(path, body, opts)');
|
|
76
|
-
}
|
|
77
|
-
const log = logger || console;
|
|
78
|
-
|
|
79
|
-
return async ({ body, headers, params, query }) => {
|
|
80
|
-
const inboundHeaders = headers || {};
|
|
81
|
-
if (!hasGeminiUpstreamCredential()) {
|
|
82
|
-
throw Object.assign(new Error('gemini api key required'), { statusCode: 401 });
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
const modelAction = (params && params.modelAction) || '';
|
|
86
|
-
const { model, action } = parseModelAction(modelAction);
|
|
87
|
-
// Reconstruct the native Gemini path + query (e.g. ?alt=sse for streaming) and forward verbatim.
|
|
88
|
-
const qs = query && Object.keys(query).length ? '?' + new URLSearchParams(query).toString() : '';
|
|
89
|
-
const reqPath = `/v1beta/models/${modelAction}${qs}`;
|
|
90
|
-
|
|
91
|
-
let trace = null;
|
|
92
|
-
try {
|
|
93
|
-
trace = createProxyTrace({
|
|
94
|
-
route: `POST /v1beta/models/${modelAction}`,
|
|
95
|
-
headers: inboundHeaders,
|
|
96
|
-
body,
|
|
97
|
-
upstreamMode: 'gemini',
|
|
98
|
-
originalModel: model,
|
|
99
|
-
chosenModel: model,
|
|
100
|
-
store: traceStore,
|
|
101
|
-
logger: traceStore ? log : null,
|
|
102
|
-
onTraceQueued,
|
|
103
|
-
});
|
|
104
|
-
} catch (_) { /* best-effort trace; never break the request */ }
|
|
105
|
-
|
|
106
|
-
let upstream;
|
|
107
|
-
try {
|
|
108
|
-
upstream = await geminiProxy(reqPath, body, { inboundHeaders, upstreamMode: 'gemini' });
|
|
109
|
-
} catch (err) {
|
|
110
|
-
const wrapped = asUpstreamError(err, upstreamStatus(err));
|
|
111
|
-
trace?.record({ status: wrapped.statusCode, error: wrapped, upstreamMode: 'gemini', model });
|
|
112
|
-
throw wrapped;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
if (upstream.stream) {
|
|
116
|
-
const forwardHeaders = copyGeminiResponseHeaders(upstream.headers);
|
|
117
|
-
const ct = upstream.headers && upstream.headers['content-type'];
|
|
118
|
-
if (ct) forwardHeaders['Content-Type'] = ct;
|
|
119
|
-
trace?.recordStreamStart({ status: upstream.status, upstreamMode: 'gemini', model, headers: forwardHeaders });
|
|
120
|
-
return {
|
|
121
|
-
status: upstream.status,
|
|
122
|
-
// Tee the Gemini SSE body so the deferred trace captures usageMetadata + finishReason. Bytes unchanged.
|
|
123
|
-
stream: trace ? trace.observeStream(upstream.stream) : upstream.stream,
|
|
124
|
-
headers: forwardHeaders,
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
let raw = '';
|
|
129
|
-
if (upstream.text) {
|
|
130
|
-
try {
|
|
131
|
-
raw = await upstream.text();
|
|
132
|
-
} catch (err) {
|
|
133
|
-
const wrapped = asUpstreamError(err, upstreamStatus(err));
|
|
134
|
-
trace?.record({ status: wrapped.statusCode, error: wrapped, upstreamMode: 'gemini', model });
|
|
135
|
-
throw wrapped;
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
const respBody = responseToBody(raw, upstream.status, upstream.headers, log);
|
|
139
|
-
trace?.record({ status: upstream.status, responseBody: respBody, upstreamMode: 'gemini', model, headers: upstream.headers });
|
|
140
|
-
return {
|
|
141
|
-
status: upstream.status,
|
|
142
|
-
body: respBody,
|
|
143
|
-
headers: copyGeminiResponseHeaders(upstream.headers),
|
|
144
|
-
};
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
module.exports = {
|
|
149
|
-
buildGeminiHandler,
|
|
150
|
-
copyGeminiResponseHeaders,
|
|
151
|
-
hasGeminiUpstreamCredential,
|
|
152
|
-
responseToBody,
|
|
153
|
-
parseModelAction,
|
|
154
|
-
};
|