@esankhan3/anvil-agent-core 0.2.0 → 0.4.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 +1 -1
- package/dist/__tests__/fetch-pool.integration.test.d.ts +15 -0
- package/dist/__tests__/fetch-pool.integration.test.d.ts.map +1 -0
- package/dist/__tests__/fetch-pool.integration.test.js +109 -0
- package/dist/__tests__/fetch-pool.integration.test.js.map +1 -0
- package/dist/__tests__/fetch-pool.test.d.ts +15 -0
- package/dist/__tests__/fetch-pool.test.d.ts.map +1 -0
- package/dist/__tests__/fetch-pool.test.js +115 -0
- package/dist/__tests__/fetch-pool.test.js.map +1 -0
- package/dist/__tests__/gemini-adapter-recording.test.d.ts +11 -0
- package/dist/__tests__/gemini-adapter-recording.test.d.ts.map +1 -0
- package/dist/__tests__/gemini-adapter-recording.test.js +108 -0
- package/dist/__tests__/gemini-adapter-recording.test.js.map +1 -0
- package/dist/__tests__/legacy-adapter-language-model.test.d.ts +11 -0
- package/dist/__tests__/legacy-adapter-language-model.test.d.ts.map +1 -0
- package/dist/__tests__/legacy-adapter-language-model.test.js +102 -0
- package/dist/__tests__/legacy-adapter-language-model.test.js.map +1 -0
- package/dist/__tests__/ollama-adapter-recording.test.d.ts +15 -0
- package/dist/__tests__/ollama-adapter-recording.test.d.ts.map +1 -0
- package/dist/__tests__/ollama-adapter-recording.test.js +128 -0
- package/dist/__tests__/ollama-adapter-recording.test.js.map +1 -0
- package/dist/__tests__/openrouter-prefill.integration.test.d.ts +19 -0
- package/dist/__tests__/openrouter-prefill.integration.test.d.ts.map +1 -0
- package/dist/__tests__/openrouter-prefill.integration.test.js +410 -0
- package/dist/__tests__/openrouter-prefill.integration.test.js.map +1 -0
- package/dist/__tests__/prefill-truncate.test.d.ts +8 -0
- package/dist/__tests__/prefill-truncate.test.d.ts.map +1 -0
- package/dist/__tests__/prefill-truncate.test.js +75 -0
- package/dist/__tests__/prefill-truncate.test.js.map +1 -0
- package/dist/__tests__/router-circuit-breaker.test.js +1 -1
- package/dist/__tests__/router-circuit-breaker.test.js.map +1 -1
- package/dist/__tests__/router-classify-unified.test.d.ts +12 -0
- package/dist/__tests__/router-classify-unified.test.d.ts.map +1 -0
- package/dist/__tests__/router-classify-unified.test.js +108 -0
- package/dist/__tests__/router-classify-unified.test.js.map +1 -0
- package/dist/__tests__/router-fallback.test.js +1 -1
- package/dist/__tests__/router-fallback.test.js.map +1 -1
- package/dist/__tests__/router-model-registry.test.js +24 -0
- package/dist/__tests__/router-model-registry.test.js.map +1 -1
- package/dist/__tests__/router-retry.test.js +3 -5
- package/dist/__tests__/router-retry.test.js.map +1 -1
- package/dist/__tests__/router-runagent.test.d.ts +14 -0
- package/dist/__tests__/router-runagent.test.d.ts.map +1 -0
- package/dist/__tests__/router-runagent.test.js +95 -0
- package/dist/__tests__/router-runagent.test.js.map +1 -0
- package/dist/__tests__/router-scaffold.test.js +2 -1
- package/dist/__tests__/router-scaffold.test.js.map +1 -1
- package/dist/__tests__/router-spend-ledger.test.js +1 -1
- package/dist/__tests__/router-spend-ledger.test.js.map +1 -1
- package/dist/__tests__/router-stream-fallback.test.d.ts +13 -0
- package/dist/__tests__/router-stream-fallback.test.d.ts.map +1 -0
- package/dist/__tests__/router-stream-fallback.test.js +129 -0
- package/dist/__tests__/router-stream-fallback.test.js.map +1 -0
- package/dist/__tests__/router-telemetry.test.js +3 -1
- package/dist/__tests__/router-telemetry.test.js.map +1 -1
- package/dist/__tests__/util/mock-upstream.d.ts +77 -0
- package/dist/__tests__/util/mock-upstream.d.ts.map +1 -0
- package/dist/__tests__/util/mock-upstream.js +219 -0
- package/dist/__tests__/util/mock-upstream.js.map +1 -0
- package/dist/adk-adapter.d.ts.map +1 -1
- package/dist/adk-adapter.js +51 -0
- package/dist/adk-adapter.js.map +1 -1
- package/dist/adk-anthropic-llm.d.ts.map +1 -1
- package/dist/adk-anthropic-llm.js +23 -10
- package/dist/adk-anthropic-llm.js.map +1 -1
- package/dist/agent/session/adapter.d.ts +25 -0
- package/dist/agent/session/adapter.d.ts.map +1 -1
- package/dist/agent/session/adapter.js +4 -0
- package/dist/agent/session/adapter.js.map +1 -1
- package/dist/agent/session/index.d.ts +1 -0
- package/dist/agent/session/index.d.ts.map +1 -1
- package/dist/agent/session/index.js +1 -0
- package/dist/agent/session/index.js.map +1 -1
- package/dist/agent/session/language-model-bridge.d.ts.map +1 -1
- package/dist/agent/session/language-model-bridge.js +30 -2
- package/dist/agent/session/language-model-bridge.js.map +1 -1
- package/dist/agent/session/legacy-adapter-language-model.d.ts +27 -0
- package/dist/agent/session/legacy-adapter-language-model.d.ts.map +1 -0
- package/dist/agent/session/legacy-adapter-language-model.js +221 -0
- package/dist/agent/session/legacy-adapter-language-model.js.map +1 -0
- package/dist/agent/session/types.d.ts +32 -0
- package/dist/agent/session/types.d.ts.map +1 -1
- package/dist/agent/session/types.js.map +1 -1
- package/dist/claude-adapter.d.ts.map +1 -1
- package/dist/claude-adapter.js +27 -0
- package/dist/claude-adapter.js.map +1 -1
- package/dist/fetch-pool.d.ts +47 -0
- package/dist/fetch-pool.d.ts.map +1 -0
- package/dist/fetch-pool.js +132 -0
- package/dist/fetch-pool.js.map +1 -0
- package/dist/gemini-adapter.d.ts.map +1 -1
- package/dist/gemini-adapter.js +65 -6
- package/dist/gemini-adapter.js.map +1 -1
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/ollama-adapter.d.ts.map +1 -1
- package/dist/ollama-adapter.js +145 -15
- package/dist/ollama-adapter.js.map +1 -1
- package/dist/openrouter-adapter.d.ts.map +1 -1
- package/dist/openrouter-adapter.js +296 -15
- package/dist/openrouter-adapter.js.map +1 -1
- package/dist/prefill/strip.d.ts +49 -0
- package/dist/prefill/strip.d.ts.map +1 -0
- package/dist/prefill/strip.js +93 -0
- package/dist/prefill/strip.js.map +1 -0
- package/dist/prefill/translate.d.ts +55 -0
- package/dist/prefill/translate.d.ts.map +1 -0
- package/dist/prefill/translate.js +162 -0
- package/dist/prefill/translate.js.map +1 -0
- package/dist/prefill/truncate.d.ts +62 -0
- package/dist/prefill/truncate.d.ts.map +1 -0
- package/dist/prefill/truncate.js +77 -0
- package/dist/prefill/truncate.js.map +1 -0
- package/dist/provider-liveness.d.ts.map +1 -1
- package/dist/provider-liveness.js +17 -6
- package/dist/provider-liveness.js.map +1 -1
- package/dist/router/errors.d.ts +24 -7
- package/dist/router/errors.d.ts.map +1 -1
- package/dist/router/errors.js +71 -14
- package/dist/router/errors.js.map +1 -1
- package/dist/router/index.d.ts +3 -2
- package/dist/router/index.d.ts.map +1 -1
- package/dist/router/index.js +2 -1
- package/dist/router/index.js.map +1 -1
- package/dist/router/local-executor.d.ts.map +1 -1
- package/dist/router/local-executor.js +19 -6
- package/dist/router/local-executor.js.map +1 -1
- package/dist/router/model-registry.d.ts +22 -0
- package/dist/router/model-registry.d.ts.map +1 -1
- package/dist/router/model-registry.js +64 -1
- package/dist/router/model-registry.js.map +1 -1
- package/dist/router/provider-registry-resolver.d.ts +25 -0
- package/dist/router/provider-registry-resolver.d.ts.map +1 -0
- package/dist/router/provider-registry-resolver.js +84 -0
- package/dist/router/provider-registry-resolver.js.map +1 -0
- package/dist/router/retry.d.ts +3 -0
- package/dist/router/retry.d.ts.map +1 -1
- package/dist/router/retry.js +4 -1
- package/dist/router/retry.js.map +1 -1
- package/dist/router/router.d.ts +79 -1
- package/dist/router/router.d.ts.map +1 -1
- package/dist/router/router.js +256 -2
- package/dist/router/router.js.map +1 -1
- package/dist/router/types.d.ts +1 -1
- package/dist/router/types.d.ts.map +1 -1
- package/dist/router/types.js +1 -0
- package/dist/router/types.js.map +1 -1
- package/dist/single-shot.d.ts.map +1 -1
- package/dist/single-shot.js +26 -1
- package/dist/single-shot.js.map +1 -1
- package/dist/tools/builtin.d.ts +19 -0
- package/dist/tools/builtin.d.ts.map +1 -1
- package/dist/tools/builtin.js +51 -0
- package/dist/tools/builtin.js.map +1 -1
- package/dist/turn-recorder/__tests__/turn-recorder.test.d.ts +20 -0
- package/dist/turn-recorder/__tests__/turn-recorder.test.d.ts.map +1 -0
- package/dist/turn-recorder/__tests__/turn-recorder.test.js +282 -0
- package/dist/turn-recorder/__tests__/turn-recorder.test.js.map +1 -0
- package/dist/turn-recorder/hash.d.ts +10 -0
- package/dist/turn-recorder/hash.d.ts.map +1 -0
- package/dist/turn-recorder/hash.js +35 -0
- package/dist/turn-recorder/hash.js.map +1 -0
- package/dist/turn-recorder/index.d.ts +119 -0
- package/dist/turn-recorder/index.d.ts.map +1 -0
- package/dist/turn-recorder/index.js +326 -0
- package/dist/turn-recorder/index.js.map +1 -0
- package/dist/turn-recorder/types.d.ts +227 -0
- package/dist/turn-recorder/types.d.ts.map +1 -0
- package/dist/turn-recorder/types.js +20 -0
- package/dist/turn-recorder/types.js.map +1 -0
- package/dist/types.d.ts +35 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -3
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-provider fetch dispatcher pool.
|
|
3
|
+
*
|
|
4
|
+
* Each upstream provider gets its own bounded-keep-alive `undici.Agent`.
|
|
5
|
+
* Adapters pass `dispatcher: getFetchPool(provider)` to every fetch.
|
|
6
|
+
* On a network-layer failure (TypeError: fetch failed / ECONNRESET / EPIPE),
|
|
7
|
+
* adapters call `recycleFetchPoolOnFailure(provider, err)` so the next
|
|
8
|
+
* fetch to the same provider lands on a fresh socket pool.
|
|
9
|
+
*
|
|
10
|
+
* Why: Node's default global undici dispatcher can retain zombie sockets
|
|
11
|
+
* after OS sleep/wake or VPN flips. One poisoned global pool burns every
|
|
12
|
+
* provider at once. Per-provider pools + heal-on-failure isolate the blast
|
|
13
|
+
* radius and self-recover without process restart.
|
|
14
|
+
*/
|
|
15
|
+
import { Agent } from 'undici';
|
|
16
|
+
const POOL_OPTS = {
|
|
17
|
+
keepAliveTimeout: 4_000,
|
|
18
|
+
keepAliveMaxTimeout: 10_000,
|
|
19
|
+
connections: 32,
|
|
20
|
+
pipelining: 1,
|
|
21
|
+
// No dispatcher-level I/O timeouts — every caller already owns its
|
|
22
|
+
// own per-call AbortSignal (run()'s AbortController for agentic
|
|
23
|
+
// adapters; AbortSignal.timeout(...) for short probes). The previous
|
|
24
|
+
// 30s headers / 60s body ceilings were appropriate for short REST
|
|
25
|
+
// calls but hostile to LLM streaming: premium reasoning models can
|
|
26
|
+
// take >30s to first byte and pause >60s between SSE chunks, both
|
|
27
|
+
// of which manifest as `TypeError: fetch failed` that the chain
|
|
28
|
+
// walker can't distinguish from a real network failure.
|
|
29
|
+
// 0 = no timeout; the per-call signal is the single source of truth.
|
|
30
|
+
bodyTimeout: 0,
|
|
31
|
+
headersTimeout: 0,
|
|
32
|
+
};
|
|
33
|
+
const pools = new Map();
|
|
34
|
+
function makeEntry() {
|
|
35
|
+
return {
|
|
36
|
+
agent: new Agent(POOL_OPTS),
|
|
37
|
+
createdAt: new Date().toISOString(),
|
|
38
|
+
recycleCount: 0,
|
|
39
|
+
lastRecycleAt: null,
|
|
40
|
+
lastRecycleReason: null,
|
|
41
|
+
recycling: null,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Get the dispatcher for a provider. Lazily constructs on first call.
|
|
46
|
+
* Always returns a non-recycling Agent — callers pass it via fetch options.
|
|
47
|
+
*/
|
|
48
|
+
export function getFetchPool(provider) {
|
|
49
|
+
let entry = pools.get(provider);
|
|
50
|
+
if (!entry) {
|
|
51
|
+
entry = makeEntry();
|
|
52
|
+
pools.set(provider, entry);
|
|
53
|
+
}
|
|
54
|
+
return entry.agent;
|
|
55
|
+
}
|
|
56
|
+
const POISONED_PATTERNS = /fetch\s+failed|ECONNRESET|socket\s+hang\s+up|other\s+side\s+closed|EPIPE|ETIMEDOUT|UND_ERR_SOCKET/i;
|
|
57
|
+
/**
|
|
58
|
+
* Recycle the dispatcher for a provider when a fetch failure indicates pool
|
|
59
|
+
* poisoning. Idempotent under concurrent calls — multiple in-flight failures
|
|
60
|
+
* coalesce to one recycle. The promise resolves once the new pool is ready.
|
|
61
|
+
* Safe to fire-and-forget — the throw site re-throws the original error to
|
|
62
|
+
* feed the chain walker.
|
|
63
|
+
*/
|
|
64
|
+
export function recycleFetchPoolOnFailure(provider, err) {
|
|
65
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
66
|
+
const causeMsg = err instanceof Error && 'cause' in err && err.cause
|
|
67
|
+
? err.cause instanceof Error
|
|
68
|
+
? err.cause.message
|
|
69
|
+
: String(err.cause)
|
|
70
|
+
: '';
|
|
71
|
+
const haystack = `${msg} ${causeMsg}`;
|
|
72
|
+
if (!POISONED_PATTERNS.test(haystack))
|
|
73
|
+
return Promise.resolve();
|
|
74
|
+
let entry = pools.get(provider);
|
|
75
|
+
if (!entry) {
|
|
76
|
+
entry = makeEntry();
|
|
77
|
+
pools.set(provider, entry);
|
|
78
|
+
return Promise.resolve();
|
|
79
|
+
}
|
|
80
|
+
if (entry.recycling)
|
|
81
|
+
return entry.recycling;
|
|
82
|
+
const reason = (msg + (causeMsg ? ` :: ${causeMsg}` : '')).slice(0, 200);
|
|
83
|
+
const old = entry.agent;
|
|
84
|
+
const newAgent = new Agent(POOL_OPTS);
|
|
85
|
+
entry.agent = newAgent;
|
|
86
|
+
entry.recycleCount += 1;
|
|
87
|
+
entry.lastRecycleAt = new Date().toISOString();
|
|
88
|
+
entry.lastRecycleReason = reason;
|
|
89
|
+
const recycling = (async () => {
|
|
90
|
+
try {
|
|
91
|
+
await old.close();
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
// Old pool was already broken — that's why we're recycling.
|
|
95
|
+
}
|
|
96
|
+
})().finally(() => {
|
|
97
|
+
if (entry.recycling === recycling)
|
|
98
|
+
entry.recycling = null;
|
|
99
|
+
});
|
|
100
|
+
entry.recycling = recycling;
|
|
101
|
+
return recycling;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Diagnostic: read-only snapshot of every pool's state.
|
|
105
|
+
*/
|
|
106
|
+
export function getPoolMetrics() {
|
|
107
|
+
const out = [];
|
|
108
|
+
for (const [provider, entry] of pools) {
|
|
109
|
+
out.push({
|
|
110
|
+
provider,
|
|
111
|
+
createdAt: entry.createdAt,
|
|
112
|
+
recycleCount: entry.recycleCount,
|
|
113
|
+
lastRecycleAt: entry.lastRecycleAt,
|
|
114
|
+
lastRecycleReason: entry.lastRecycleReason,
|
|
115
|
+
active: entry.recycling === null,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
return out;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Test utility — drops every pool and resets counters. Not exported via
|
|
122
|
+
* the package barrel; tests import from the subpath.
|
|
123
|
+
*/
|
|
124
|
+
export async function resetAllPools() {
|
|
125
|
+
const closes = [];
|
|
126
|
+
for (const entry of pools.values()) {
|
|
127
|
+
closes.push(entry.agent.close().catch(() => { }));
|
|
128
|
+
}
|
|
129
|
+
pools.clear();
|
|
130
|
+
await Promise.all(closes);
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=fetch-pool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch-pool.js","sourceRoot":"","sources":["../src/fetch-pool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAoB/B,MAAM,SAAS,GAAkB;IAC/B,gBAAgB,EAAE,KAAK;IACvB,mBAAmB,EAAE,MAAM;IAC3B,WAAW,EAAE,EAAE;IACf,UAAU,EAAE,CAAC;IACb,mEAAmE;IACnE,gEAAgE;IAChE,qEAAqE;IACrE,kEAAkE;IAClE,mEAAmE;IACnE,kEAAkE;IAClE,gEAAgE;IAChE,wDAAwD;IACxD,qEAAqE;IACrE,WAAW,EAAE,CAAC;IACd,cAAc,EAAE,CAAC;CAClB,CAAC;AAEF,MAAM,KAAK,GAAG,IAAI,GAAG,EAAyB,CAAC;AAE/C,SAAS,SAAS;IAChB,OAAO;QACL,KAAK,EAAE,IAAI,KAAK,CAAC,SAAS,CAAC;QAC3B,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,YAAY,EAAE,CAAC;QACf,aAAa,EAAE,IAAI;QACnB,iBAAiB,EAAE,IAAI;QACvB,SAAS,EAAE,IAAI;KAChB,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,QAAoB;IAC/C,IAAI,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAChC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,KAAK,GAAG,SAAS,EAAE,CAAC;QACpB,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC7B,CAAC;IACD,OAAO,KAAK,CAAC,KAAK,CAAC;AACrB,CAAC;AAED,MAAM,iBAAiB,GACrB,oGAAoG,CAAC;AAEvG;;;;;;GAMG;AACH,MAAM,UAAU,yBAAyB,CACvC,QAAoB,EACpB,GAAY;IAEZ,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC7D,MAAM,QAAQ,GACZ,GAAG,YAAY,KAAK,IAAI,OAAO,IAAI,GAAG,IAAI,GAAG,CAAC,KAAK;QACjD,CAAC,CAAC,GAAG,CAAC,KAAK,YAAY,KAAK;YAC1B,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO;YACnB,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC;QACrB,CAAC,CAAC,EAAE,CAAC;IACT,MAAM,QAAQ,GAAG,GAAG,GAAG,IAAI,QAAQ,EAAE,CAAC;IACtC,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC;QAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAEhE,IAAI,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAChC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,KAAK,GAAG,SAAS,EAAE,CAAC;QACpB,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAC3B,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAED,IAAI,KAAK,CAAC,SAAS;QAAE,OAAO,KAAK,CAAC,SAAS,CAAC;IAE5C,MAAM,MAAM,GAAG,CAAC,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACzE,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC;IACxB,MAAM,QAAQ,GAAG,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC;IACtC,KAAK,CAAC,KAAK,GAAG,QAAQ,CAAC;IACvB,KAAK,CAAC,YAAY,IAAI,CAAC,CAAC;IACxB,KAAK,CAAC,aAAa,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC/C,KAAK,CAAC,iBAAiB,GAAG,MAAM,CAAC;IAEjC,MAAM,SAAS,GAAG,CAAC,KAAK,IAAI,EAAE;QAC5B,IAAI,CAAC;YACH,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;QACpB,CAAC;QAAC,MAAM,CAAC;YACP,4DAA4D;QAC9D,CAAC;IACH,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE;QAChB,IAAI,KAAM,CAAC,SAAS,KAAK,SAAS;YAAE,KAAM,CAAC,SAAS,GAAG,IAAI,CAAC;IAC9D,CAAC,CAAC,CAAC;IAEH,KAAK,CAAC,SAAS,GAAG,SAAS,CAAC;IAC5B,OAAO,SAAS,CAAC;AACnB,CAAC;AAWD;;GAEG;AACH,MAAM,UAAU,cAAc;IAC5B,MAAM,GAAG,GAAkB,EAAE,CAAC;IAC9B,KAAK,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,KAAK,EAAE,CAAC;QACtC,GAAG,CAAC,IAAI,CAAC;YACP,QAAQ;YACR,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,YAAY,EAAE,KAAK,CAAC,YAAY;YAChC,aAAa,EAAE,KAAK,CAAC,aAAa;YAClC,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;YAC1C,MAAM,EAAE,KAAK,CAAC,SAAS,KAAK,IAAI;SACjC,CAAC,CAAC;IACL,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,MAAM,GAAoB,EAAE,CAAC;IACnC,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;QACnC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC,CAAC;IACnD,CAAC;IACD,KAAK,CAAC,KAAK,EAAE,CAAC;IACd,MAAM,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AAC5B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gemini-adapter.d.ts","sourceRoot":"","sources":["../src/gemini-adapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,EACrB,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"gemini-adapter.d.ts","sourceRoot":"","sources":["../src/gemini-adapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,EACrB,MAAM,YAAY,CAAC;AA8BpB,qBAAa,aAAc,YAAW,YAAY;IAChD,QAAQ,CAAC,QAAQ,EAAG,QAAQ,CAAU;IAEtC,QAAQ,CAAC,YAAY,EAAE,oBAAoB,CAczC;IAEF,OAAO,CAAC,eAAe,CAAgC;IAEvD,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAIvC,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAInD,iBAAiB,IAAI,OAAO,CAAC;QAAE,SAAS,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAQ5F,IAAI,IAAI,IAAI;IAON,GAAG,CACP,MAAM,EAAE,kBAAkB,EAC1B,MAAM,EAAE,MAAM,CAAC,cAAc,GAC5B,OAAO,CAAC,kBAAkB,CAAC;CAuN/B"}
|
package/dist/gemini-adapter.js
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { emitContent, emitThinking, emitResult } from './stream-format.js';
|
|
8
8
|
import { UpstreamError } from './upstream-error.js';
|
|
9
|
+
import { getFetchPool, recycleFetchPoolOnFailure } from './fetch-pool.js';
|
|
10
|
+
import { createNullTurnRecorder } from './turn-recorder/index.js';
|
|
9
11
|
const API_BASE = 'https://generativelanguage.googleapis.com/v1beta/models';
|
|
10
12
|
const PRICING = {
|
|
11
13
|
'gemini-2.5-pro': [1.25, 10.0],
|
|
@@ -78,6 +80,47 @@ export class GeminiAdapter {
|
|
|
78
80
|
if (projectPrompt) {
|
|
79
81
|
body.systemInstruction = { parts: [{ text: projectPrompt }] };
|
|
80
82
|
}
|
|
83
|
+
// §H4 cross-vendor turn recording. Records this single-shot exchange so
|
|
84
|
+
// a later (possibly different-provider) resume can reconstruct prior
|
|
85
|
+
// turns via `reconstructSessionHistory`. NullTurnRecorder no-ops when
|
|
86
|
+
// the pipeline didn't inject a durable recorder.
|
|
87
|
+
const recorder = config.turnRecorder ?? createNullTurnRecorder({
|
|
88
|
+
runId: config.sessionId,
|
|
89
|
+
stepId: config.stage,
|
|
90
|
+
});
|
|
91
|
+
const { turn, replayed } = await recorder.startTurn({
|
|
92
|
+
model,
|
|
93
|
+
provider: 'gemini',
|
|
94
|
+
system: projectPrompt,
|
|
95
|
+
messages: body.contents,
|
|
96
|
+
userPrompt,
|
|
97
|
+
});
|
|
98
|
+
// Same-runId replay (Fix A): the turn already ran on a prior process —
|
|
99
|
+
// skip the upstream call and re-present the recorded result verbatim.
|
|
100
|
+
if (replayed) {
|
|
101
|
+
const u = replayed.usage;
|
|
102
|
+
const replayCost = computeCost(model, u.inputTokens, u.outputTokens);
|
|
103
|
+
if (replayed.text)
|
|
104
|
+
emitContent(output, replayed.text);
|
|
105
|
+
emitResult(output, {
|
|
106
|
+
text: replayed.text,
|
|
107
|
+
costUsd: replayCost,
|
|
108
|
+
inputTokens: u.inputTokens,
|
|
109
|
+
outputTokens: u.outputTokens,
|
|
110
|
+
durationMs: 0,
|
|
111
|
+
});
|
|
112
|
+
return {
|
|
113
|
+
output: replayed.text,
|
|
114
|
+
inputTokens: u.inputTokens,
|
|
115
|
+
outputTokens: u.outputTokens,
|
|
116
|
+
costUsd: replayCost,
|
|
117
|
+
durationMs: 0,
|
|
118
|
+
provider: 'gemini',
|
|
119
|
+
model,
|
|
120
|
+
cacheReadTokens: u.cacheReadTokens ?? 0,
|
|
121
|
+
reasoningTokens: 0,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
81
124
|
this.abortController = new AbortController();
|
|
82
125
|
const startMs = Date.now();
|
|
83
126
|
let fullText = '';
|
|
@@ -85,12 +128,24 @@ export class GeminiAdapter {
|
|
|
85
128
|
let outputTokens = 0;
|
|
86
129
|
let thinkingTokens = 0;
|
|
87
130
|
let cacheReadTokens = 0;
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
131
|
+
let response;
|
|
132
|
+
try {
|
|
133
|
+
response = await fetch(url, {
|
|
134
|
+
method: 'POST',
|
|
135
|
+
headers: { 'Content-Type': 'application/json' },
|
|
136
|
+
body: JSON.stringify(body),
|
|
137
|
+
signal: this.abortController.signal,
|
|
138
|
+
// @ts-expect-error — undici dispatcher accepted by Node fetch at runtime
|
|
139
|
+
dispatcher: getFetchPool('gemini'),
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
catch (err) {
|
|
143
|
+
if (this.abortController.signal.aborted)
|
|
144
|
+
throw err;
|
|
145
|
+
void recycleFetchPoolOnFailure('gemini', err);
|
|
146
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
147
|
+
throw new UpstreamError(0, `fetch failed: ${msg}`, { provider: 'gemini', retryable: true });
|
|
148
|
+
}
|
|
94
149
|
if (!response.ok) {
|
|
95
150
|
const errBody = await response.text();
|
|
96
151
|
throw new UpstreamError(response.status, errBody, { provider: 'gemini' });
|
|
@@ -172,6 +227,10 @@ export class GeminiAdapter {
|
|
|
172
227
|
this.abortController = null;
|
|
173
228
|
throw new UpstreamError(503, `gemini model "${model}" returned empty final text (outputTokens=${outputTokens})`, { provider: 'gemini', retryable: true });
|
|
174
229
|
}
|
|
230
|
+
// §H4 — record the completed turn (assistant-end) so a later resume can
|
|
231
|
+
// reconstruct it. Only on success: an empty/burned turn threw above, so
|
|
232
|
+
// we never persist an empty assistant-end.
|
|
233
|
+
await recorder.endTurn(turn, fullText, 'end_turn', { inputTokens, outputTokens, cacheReadTokens }, { segments: [{ model, provider: 'gemini', range: [0, fullText.length], source: 'live' }] });
|
|
175
234
|
emitResult(output, {
|
|
176
235
|
text: fullText,
|
|
177
236
|
costUsd,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gemini-adapter.js","sourceRoot":"","sources":["../src/gemini-adapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"gemini-adapter.js","sourceRoot":"","sources":["../src/gemini-adapter.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -40,5 +40,16 @@ export { DEFAULT_SPEC, getModelSpec, getContextWindow, getMaxOutput, } from './m
|
|
|
40
40
|
export type { ModelSpec } from './model-catalog.js';
|
|
41
41
|
export { resolveModelByTier, setDiscoveryResult, invalidateResolverCache, } from './model-tier-resolver.js';
|
|
42
42
|
export type { ResolverTier, ResolverCapability, ResolverModelWeight, ResolverModel, ResolverDiscoveryResult, } from './model-tier-resolver.js';
|
|
43
|
+
export { getFetchPool, recycleFetchPoolOnFailure, getPoolMetrics, } from './fetch-pool.js';
|
|
44
|
+
export type { ProviderId as FetchPoolProviderId, PoolMetrics as FetchPoolMetrics, } from './fetch-pool.js';
|
|
45
|
+
export { TurnRecorder, createNullTurnRecorder, createNullEffectRuntime, createNullPartialSink, } from './turn-recorder/index.js';
|
|
46
|
+
export type { AssistantPartial, AssistantStartRequest, AssistantTurn, EffectRuntimeLike, EffectInvokeOptions, NeutralToolResult, PartialReason, PartialSink, Prefill, PrefillToolUse, PrefillTurn, Provenance, ProvenanceSegment, RecordedToolUse, TurnRecorderDeps, TurnTokenUsage, } from './turn-recorder/types.js';
|
|
47
|
+
export { contentHashFromArgs } from './turn-recorder/hash.js';
|
|
48
|
+
export { stripForTarget } from './prefill/strip.js';
|
|
49
|
+
export type { StripContext } from './prefill/strip.js';
|
|
50
|
+
export { translateToolResult } from './prefill/translate.js';
|
|
51
|
+
export type { TranslatedToolResult } from './prefill/translate.js';
|
|
52
|
+
export { truncatePrefillForBudget, DEFAULT_MAX_INPUT_TOKENS, DEFAULT_MARGIN_TOKENS, } from './prefill/truncate.js';
|
|
53
|
+
export type { TruncatePrefillArgs } from './prefill/truncate.js';
|
|
43
54
|
export { VERSION } from './version.js';
|
|
44
55
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,WAAW,CAAC;AAC1B,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,uBAAuB,EACvB,2BAA2B,EAC3B,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,YAAY,GACb,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,YAAY,EACZ,kBAAkB,EAClB,mBAAmB,EACnB,aAAa,EACb,uBAAuB,GACxB,MAAM,0BAA0B,CAAC;AAKlC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,WAAW,CAAC;AAC1B,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,uBAAuB,EACvB,2BAA2B,EAC3B,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,YAAY,GACb,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,YAAY,EACZ,kBAAkB,EAClB,mBAAmB,EACnB,aAAa,EACb,uBAAuB,GACxB,MAAM,0BAA0B,CAAC;AAKlC,OAAO,EACL,YAAY,EACZ,yBAAyB,EACzB,cAAc,GACf,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACV,UAAU,IAAI,mBAAmB,EACjC,WAAW,IAAI,gBAAgB,GAChC,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,YAAY,EACZ,sBAAsB,EACtB,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,gBAAgB,EAChB,qBAAqB,EACrB,aAAa,EACb,iBAAiB,EACjB,mBAAmB,EACnB,iBAAiB,EACjB,aAAa,EACb,WAAW,EACX,OAAO,EACP,cAAc,EACd,WAAW,EACX,UAAU,EACV,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,cAAc,GACf,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,YAAY,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,EACL,wBAAwB,EACxB,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -42,5 +42,11 @@ export { resolveModelByTier, setDiscoveryResult, invalidateResolverCache, } from
|
|
|
42
42
|
// NOT re-exported here to avoid colliding with `router/model-registry.ts`'s
|
|
43
43
|
// `ModelTier` (different vocabulary). Reach the alias via the subpath
|
|
44
44
|
// import `@esankhan3/anvil-agent-core/model-tier-resolver.js` if needed.
|
|
45
|
+
export { getFetchPool, recycleFetchPoolOnFailure, getPoolMetrics, } from './fetch-pool.js';
|
|
46
|
+
export { TurnRecorder, createNullTurnRecorder, createNullEffectRuntime, createNullPartialSink, } from './turn-recorder/index.js';
|
|
47
|
+
export { contentHashFromArgs } from './turn-recorder/hash.js';
|
|
48
|
+
export { stripForTarget } from './prefill/strip.js';
|
|
49
|
+
export { translateToolResult } from './prefill/translate.js';
|
|
50
|
+
export { truncatePrefillForBudget, DEFAULT_MAX_INPUT_TOKENS, DEFAULT_MARGIN_TOKENS, } from './prefill/truncate.js';
|
|
45
51
|
export { VERSION } from './version.js';
|
|
46
52
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,WAAW,CAAC;AAC1B,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,uBAAuB,EACvB,2BAA2B,EAC3B,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,YAAY,GACb,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,0BAA0B,CAAC;AAQlC,qEAAqE;AACrE,4EAA4E;AAC5E,sEAAsE;AACtE,yEAAyE;AACzE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,WAAW,CAAC;AAC1B,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,uBAAuB,EACvB,2BAA2B,EAC3B,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,YAAY,GACb,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,0BAA0B,CAAC;AAQlC,qEAAqE;AACrE,4EAA4E;AAC5E,sEAAsE;AACtE,yEAAyE;AACzE,OAAO,EACL,YAAY,EACZ,yBAAyB,EACzB,cAAc,GACf,MAAM,iBAAiB,CAAC;AAKzB,OAAO,EACL,YAAY,EACZ,sBAAsB,EACtB,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,0BAA0B,CAAC;AAmBlC,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAE7D,OAAO,EACL,wBAAwB,EACxB,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ollama-adapter.d.ts","sourceRoot":"","sources":["../src/ollama-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAGH,OAAO,KAAK,EACV,YAAY,EACZ,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,EAIrB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,aAAa,EAAiB,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"ollama-adapter.d.ts","sourceRoot":"","sources":["../src/ollama-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAGH,OAAO,KAAK,EACV,YAAY,EACZ,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,EAIrB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,aAAa,EAAiB,MAAM,4BAA4B,CAAC;AAuB1E;;;wBAGwB;AACxB,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;gBACnB,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM;CAUjE;AAuBD,UAAU,cAAc;IACtB,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC;KAC7C,CAAC;CACH;AAWD,UAAU,WAAW;IACnB,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,WAAW,GAAG,MAAM,CAAC;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,cAAc,EAAE,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAMD,qBAAa,aAAc,YAAW,YAAY;IA+BpC,OAAO,CAAC,QAAQ,CAAC,QAAQ;IA9BrC,QAAQ,CAAC,QAAQ,EAAG,QAAQ,CAAU;IAEtC,QAAQ,CAAC,YAAY,EAAE,oBAAoB,CAUzC;IAEF;;;;;;;;OAQG;IACH,OAAO,CAAC,iBAAiB,CAA8B;IAEvD;;;;OAIG;gBAC0B,QAAQ,GAAE,aAA6B;IAEpE,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAKxC,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAIpD,iBAAiB,IAAI,OAAO,CAAC;QAAE,SAAS,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAmB5F,IAAI,IAAI,IAAI;IAON,GAAG,CACP,MAAM,EAAE,kBAAkB,EAC1B,MAAM,EAAE,MAAM,CAAC,cAAc,GAC5B,OAAO,CAAC,kBAAkB,CAAC;YAOhB,QAAQ;IA6PtB;;;;OAIG;YACW,UAAU;CAiHzB;AAwED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,WAAW,EAAE,EACvB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACZ,IAAI,CAgBN"}
|
package/dist/ollama-adapter.js
CHANGED
|
@@ -25,6 +25,9 @@ import { randomUUID } from 'node:crypto';
|
|
|
25
25
|
import { emitContent, emitResult, emitToolResult, emitToolUse } from './stream-format.js';
|
|
26
26
|
import { localExecutor } from './router/local-executor.js';
|
|
27
27
|
import { UpstreamError } from './upstream-error.js';
|
|
28
|
+
import { getFetchPool, recycleFetchPoolOnFailure } from './fetch-pool.js';
|
|
29
|
+
import { createNullTurnRecorder } from './turn-recorder/index.js';
|
|
30
|
+
import { contentHashFromArgs } from './turn-recorder/hash.js';
|
|
28
31
|
const DEFAULT_MAX_ITERATIONS = 32;
|
|
29
32
|
const DEFAULT_CONTEXT_WINDOW = 16_384;
|
|
30
33
|
/**
|
|
@@ -105,12 +108,19 @@ export class OllamaAdapter {
|
|
|
105
108
|
async checkAvailability() {
|
|
106
109
|
const baseUrl = getBaseUrl();
|
|
107
110
|
try {
|
|
108
|
-
const res = await fetch(`${baseUrl}/api/tags`, {
|
|
111
|
+
const res = await fetch(`${baseUrl}/api/tags`, {
|
|
112
|
+
method: 'GET',
|
|
113
|
+
// @ts-expect-error — undici dispatcher accepted by Node fetch at runtime
|
|
114
|
+
dispatcher: getFetchPool('ollama'),
|
|
115
|
+
});
|
|
109
116
|
if (res.ok)
|
|
110
117
|
return { available: true };
|
|
111
118
|
return { available: false, error: `Ollama returned ${res.status}` };
|
|
112
119
|
}
|
|
113
120
|
catch (err) {
|
|
121
|
+
// Probe failures are tolerated, but still recycle the pool so the
|
|
122
|
+
// next real request lands on fresh sockets.
|
|
123
|
+
void recycleFetchPoolOnFailure('ollama', err);
|
|
114
124
|
const msg = err instanceof Error ? err.message : String(err);
|
|
115
125
|
return { available: false, error: `Cannot reach Ollama at ${baseUrl}: ${msg}` };
|
|
116
126
|
}
|
|
@@ -146,6 +156,22 @@ export class OllamaAdapter {
|
|
|
146
156
|
let totalOut = 0;
|
|
147
157
|
let totalDurMs = 0;
|
|
148
158
|
let stopReason;
|
|
159
|
+
// §H4 cross-vendor turn recording — mirrors the OpenRouter agentic port
|
|
160
|
+
// (startTurn → replay-skip → live tool-loop with runTool → endTurn, plus a
|
|
161
|
+
// burned-sentinel on a mid-turn upstream burn). Records every turn so a
|
|
162
|
+
// later resume can reconstruct history; HONORS `replayed` on a same-runId
|
|
163
|
+
// resume so the recorded tool effects re-issue in order (exec never fires)
|
|
164
|
+
// instead of re-running live and tripping a DeterminismViolation. NullTurn-
|
|
165
|
+
// Recorder no-ops without a durable recorder.
|
|
166
|
+
const recorder = config.turnRecorder ?? createNullTurnRecorder({
|
|
167
|
+
runId: config.sessionId,
|
|
168
|
+
stepId: config.stage,
|
|
169
|
+
});
|
|
170
|
+
let activeTurnIdx = -1;
|
|
171
|
+
// false while runOneTurn is streaming → a throw here is a mid-stream burn
|
|
172
|
+
// (record a sentinel). true once it returns → a later throw (endTurn /
|
|
173
|
+
// determinism) must propagate untouched, never get a spurious sentinel.
|
|
174
|
+
let activeTurnComplete = true;
|
|
149
175
|
try {
|
|
150
176
|
for (let iter = 0; iter < maxIter; iter++) {
|
|
151
177
|
// Bound conversation history before each turn. Drops oldest
|
|
@@ -153,22 +179,90 @@ export class OllamaAdapter {
|
|
|
153
179
|
// them once) keeping the system + user + recent turns intact.
|
|
154
180
|
// If trimming can't bring history below num_ctx, escalate.
|
|
155
181
|
trimHistoryIfNeeded(messages, numCtx, config.model);
|
|
182
|
+
const { turn: turnIdx, replayed } = await recorder.startTurn({
|
|
183
|
+
model: config.model,
|
|
184
|
+
provider: 'ollama',
|
|
185
|
+
system: config.projectPrompt,
|
|
186
|
+
messages: messages.slice(),
|
|
187
|
+
userPrompt: config.userPrompt,
|
|
188
|
+
});
|
|
189
|
+
activeTurnIdx = turnIdx;
|
|
190
|
+
// ── H3 replay-skip ────────────────────────────────────────────
|
|
191
|
+
// This turn's assistant-end is already in the durable log. Skip the
|
|
192
|
+
// upstream call; re-append the EXACT recorded native history (so the
|
|
193
|
+
// first live turn past the replay frontier continues from coherent
|
|
194
|
+
// context) and re-issue runTool in order so the replay cursor advances
|
|
195
|
+
// (exec never fires — recorded tool_results return verbatim).
|
|
196
|
+
if (replayed) {
|
|
197
|
+
// Burned sentinel: this turn burned mid-stream live. Re-issue its
|
|
198
|
+
// recorded sub-effects (none for ollama — burns happen before any
|
|
199
|
+
// runTool), re-record the sentinel, then re-throw a retryable
|
|
200
|
+
// upstream error so the chain walker re-derives the SAME model→turn
|
|
201
|
+
// mapping it had live, independent of whether the error cleared.
|
|
202
|
+
if (replayed.stopReason === 'burned') {
|
|
203
|
+
for (const m of replayed.historyDelta)
|
|
204
|
+
messages.push(m);
|
|
205
|
+
for (const tu of replayed.toolUses) {
|
|
206
|
+
await recorder.runTool(turnIdx, tu.name, tu.arguments, tu.idempotencyKey, async () => { throw new Error(`replay invariant: exec ran for recorded burned-turn tool ${tu.name}`); });
|
|
207
|
+
}
|
|
208
|
+
await recorder.endTurn(turnIdx, replayed.text, 'burned', replayed.usage, replayed.provenance, replayed.historyDelta);
|
|
209
|
+
throw new UpstreamError(503, `ollama replayed burn for "${config.model}" (deterministic chain re-derivation)`, { provider: 'ollama', retryable: true });
|
|
210
|
+
}
|
|
211
|
+
aggregatedText += replayed.text;
|
|
212
|
+
totalIn += replayed.usage.inputTokens;
|
|
213
|
+
totalOut += replayed.usage.outputTokens;
|
|
214
|
+
if (replayed.text)
|
|
215
|
+
emitContent(output, replayed.text);
|
|
216
|
+
if (replayed.toolUses.length === 0 || !config.toolExecutor) {
|
|
217
|
+
stopReason = replayed.stopReason;
|
|
218
|
+
await recorder.endTurn(turnIdx, replayed.text, replayed.stopReason, replayed.usage, replayed.provenance, replayed.historyDelta);
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
221
|
+
for (const m of replayed.historyDelta)
|
|
222
|
+
messages.push(m);
|
|
223
|
+
for (const tu of replayed.toolUses) {
|
|
224
|
+
emitToolUse(output, tu.name, tu.arguments, tu.id);
|
|
225
|
+
const r = await recorder.runTool(turnIdx, tu.name, tu.arguments, tu.idempotencyKey, async () => { throw new Error(`replay invariant: exec ran for recorded tool ${tu.name}`); });
|
|
226
|
+
const rc = typeof r.content === 'string' ? r.content : JSON.stringify(r.content);
|
|
227
|
+
emitToolResult(output, { toolUseId: tu.id, content: rc, isError: !r.ok });
|
|
228
|
+
}
|
|
229
|
+
await recorder.endTurn(turnIdx, replayed.text, replayed.stopReason, replayed.usage, replayed.provenance, replayed.historyDelta);
|
|
230
|
+
if (abortController.signal.aborted) {
|
|
231
|
+
stopReason = 'aborted';
|
|
232
|
+
break;
|
|
233
|
+
}
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
236
|
+
// ── live ──────────────────────────────────────────────────────
|
|
237
|
+
activeTurnComplete = false;
|
|
156
238
|
const turn = await this.runOneTurn(messages, tools, numCtx, config, output, abortController.signal);
|
|
239
|
+
activeTurnComplete = true;
|
|
157
240
|
aggregatedText += turn.text;
|
|
158
241
|
totalIn += turn.inputTokens;
|
|
159
242
|
totalOut += turn.outputTokens;
|
|
160
243
|
totalDurMs += turn.durationMs;
|
|
244
|
+
const usage = { inputTokens: turn.inputTokens, outputTokens: turn.outputTokens };
|
|
245
|
+
const provenance = {
|
|
246
|
+
segments: [{ model: config.model, provider: 'ollama', range: [0, turn.text.length], source: 'live' }],
|
|
247
|
+
};
|
|
161
248
|
if (turn.toolCalls.length === 0 || !config.toolExecutor) {
|
|
162
249
|
stopReason = turn.toolCalls.length === 0 ? 'end_turn' : 'tools_unsupported';
|
|
250
|
+
await recorder.endTurn(turnIdx, turn.text, stopReason, usage, provenance);
|
|
163
251
|
break;
|
|
164
252
|
}
|
|
165
253
|
// Append the assistant's tool-call turn to history so the model
|
|
166
|
-
// sees its own request when we re-prompt with results.
|
|
167
|
-
messages
|
|
254
|
+
// sees its own request when we re-prompt with results. Track the
|
|
255
|
+
// exact native messages appended this turn as `historyDelta` so
|
|
256
|
+
// crash-resume re-appends them verbatim (order: assistant, then each
|
|
257
|
+
// tool-result — mirroring the live push order).
|
|
258
|
+
const historyDelta = [];
|
|
259
|
+
const assistantMsg = {
|
|
168
260
|
role: 'assistant',
|
|
169
261
|
content: turn.text,
|
|
170
262
|
tool_calls: turn.toolCalls,
|
|
171
|
-
}
|
|
263
|
+
};
|
|
264
|
+
messages.push(assistantMsg);
|
|
265
|
+
historyDelta.push(assistantMsg);
|
|
172
266
|
// Execute every tool call. Sequential — parallel exec via the
|
|
173
267
|
// builtin executor is safe today (each tool is independent),
|
|
174
268
|
// but bash/edit ordering matters when the model chains them,
|
|
@@ -178,14 +272,24 @@ export class OllamaAdapter {
|
|
|
178
272
|
const args = normalizeArgs(toolCall.function.arguments);
|
|
179
273
|
const call = { id: callId, name: toolCall.function.name, arguments: args };
|
|
180
274
|
emitToolUse(output, call.name, args, callId);
|
|
181
|
-
const
|
|
182
|
-
|
|
183
|
-
|
|
275
|
+
const idempotencyKey = contentHashFromArgs({ name: call.name, arguments: args });
|
|
276
|
+
const neutralResult = await recorder.runTool(turnIdx, call.name, args, idempotencyKey, async () => {
|
|
277
|
+
const r = await invokeTool(config.toolExecutor, call, config.workingDir, abortController.signal);
|
|
278
|
+
return { toolUseId: callId, toolName: call.name, ok: !r.isError, content: r.content };
|
|
279
|
+
});
|
|
280
|
+
const resultContent = typeof neutralResult.content === 'string'
|
|
281
|
+
? neutralResult.content
|
|
282
|
+
: JSON.stringify(neutralResult.content);
|
|
283
|
+
emitToolResult(output, { toolUseId: callId, content: resultContent, isError: !neutralResult.ok });
|
|
284
|
+
const toolMsg = {
|
|
184
285
|
role: 'tool',
|
|
185
|
-
content:
|
|
286
|
+
content: resultContent,
|
|
186
287
|
tool_call_id: callId,
|
|
187
|
-
}
|
|
288
|
+
};
|
|
289
|
+
messages.push(toolMsg);
|
|
290
|
+
historyDelta.push(toolMsg);
|
|
188
291
|
}
|
|
292
|
+
await recorder.endTurn(turnIdx, turn.text, 'tool_use', usage, provenance, historyDelta);
|
|
189
293
|
if (abortController.signal.aborted) {
|
|
190
294
|
stopReason = 'aborted';
|
|
191
295
|
break;
|
|
@@ -194,6 +298,20 @@ export class OllamaAdapter {
|
|
|
194
298
|
if (stopReason === undefined)
|
|
195
299
|
stopReason = 'iteration_limit';
|
|
196
300
|
}
|
|
301
|
+
catch (err) {
|
|
302
|
+
// §H3 burn sentinel: a mid-stream upstream burn (runOneTurn threw before
|
|
303
|
+
// returning). Record a `stopReason:'burned'` assistant-end for the
|
|
304
|
+
// active turn so a same-runId resume replays it deterministically
|
|
305
|
+
// (re-throws here) and the chain walker re-derives the identical
|
|
306
|
+
// model→turn mapping. ollama records no tool effects until runOneTurn
|
|
307
|
+
// returns, so the burned turn carries empty historyDelta + toolUses.
|
|
308
|
+
// Only genuine mid-stream burns (NOT aborts, NOT post-turn throws like a
|
|
309
|
+
// DeterminismViolation) get a sentinel.
|
|
310
|
+
if (activeTurnIdx >= 0 && !activeTurnComplete && !abortController.signal.aborted) {
|
|
311
|
+
await recorder.endTurn(activeTurnIdx, '', 'burned', { inputTokens: 0, outputTokens: 0 }, { segments: [] }, []);
|
|
312
|
+
}
|
|
313
|
+
throw err;
|
|
314
|
+
}
|
|
197
315
|
finally {
|
|
198
316
|
this.activeControllers.delete(abortController);
|
|
199
317
|
}
|
|
@@ -247,12 +365,24 @@ export class OllamaAdapter {
|
|
|
247
365
|
if (typeof config.maxOutputTokens === 'number' && config.maxOutputTokens > 0) {
|
|
248
366
|
body.options.num_predict = config.maxOutputTokens;
|
|
249
367
|
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
368
|
+
let response;
|
|
369
|
+
try {
|
|
370
|
+
response = await fetch(`${baseUrl}/api/chat`, {
|
|
371
|
+
method: 'POST',
|
|
372
|
+
headers: { 'Content-Type': 'application/json' },
|
|
373
|
+
body: JSON.stringify(body),
|
|
374
|
+
signal,
|
|
375
|
+
// @ts-expect-error — undici dispatcher accepted by Node fetch at runtime
|
|
376
|
+
dispatcher: getFetchPool('ollama'),
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
catch (err) {
|
|
380
|
+
if (signal?.aborted)
|
|
381
|
+
throw err;
|
|
382
|
+
void recycleFetchPoolOnFailure('ollama', err);
|
|
383
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
384
|
+
throw new UpstreamError(0, `fetch failed: ${msg}`, { provider: 'ollama', retryable: true });
|
|
385
|
+
}
|
|
256
386
|
if (!response.ok) {
|
|
257
387
|
const errBody = await response.text();
|
|
258
388
|
throw new UpstreamError(response.status, errBody, { provider: 'ollama' });
|