@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.
Files changed (175) hide show
  1. package/README.md +1 -1
  2. package/dist/__tests__/fetch-pool.integration.test.d.ts +15 -0
  3. package/dist/__tests__/fetch-pool.integration.test.d.ts.map +1 -0
  4. package/dist/__tests__/fetch-pool.integration.test.js +109 -0
  5. package/dist/__tests__/fetch-pool.integration.test.js.map +1 -0
  6. package/dist/__tests__/fetch-pool.test.d.ts +15 -0
  7. package/dist/__tests__/fetch-pool.test.d.ts.map +1 -0
  8. package/dist/__tests__/fetch-pool.test.js +115 -0
  9. package/dist/__tests__/fetch-pool.test.js.map +1 -0
  10. package/dist/__tests__/gemini-adapter-recording.test.d.ts +11 -0
  11. package/dist/__tests__/gemini-adapter-recording.test.d.ts.map +1 -0
  12. package/dist/__tests__/gemini-adapter-recording.test.js +108 -0
  13. package/dist/__tests__/gemini-adapter-recording.test.js.map +1 -0
  14. package/dist/__tests__/legacy-adapter-language-model.test.d.ts +11 -0
  15. package/dist/__tests__/legacy-adapter-language-model.test.d.ts.map +1 -0
  16. package/dist/__tests__/legacy-adapter-language-model.test.js +102 -0
  17. package/dist/__tests__/legacy-adapter-language-model.test.js.map +1 -0
  18. package/dist/__tests__/ollama-adapter-recording.test.d.ts +15 -0
  19. package/dist/__tests__/ollama-adapter-recording.test.d.ts.map +1 -0
  20. package/dist/__tests__/ollama-adapter-recording.test.js +128 -0
  21. package/dist/__tests__/ollama-adapter-recording.test.js.map +1 -0
  22. package/dist/__tests__/openrouter-prefill.integration.test.d.ts +19 -0
  23. package/dist/__tests__/openrouter-prefill.integration.test.d.ts.map +1 -0
  24. package/dist/__tests__/openrouter-prefill.integration.test.js +410 -0
  25. package/dist/__tests__/openrouter-prefill.integration.test.js.map +1 -0
  26. package/dist/__tests__/prefill-truncate.test.d.ts +8 -0
  27. package/dist/__tests__/prefill-truncate.test.d.ts.map +1 -0
  28. package/dist/__tests__/prefill-truncate.test.js +75 -0
  29. package/dist/__tests__/prefill-truncate.test.js.map +1 -0
  30. package/dist/__tests__/router-circuit-breaker.test.js +1 -1
  31. package/dist/__tests__/router-circuit-breaker.test.js.map +1 -1
  32. package/dist/__tests__/router-classify-unified.test.d.ts +12 -0
  33. package/dist/__tests__/router-classify-unified.test.d.ts.map +1 -0
  34. package/dist/__tests__/router-classify-unified.test.js +108 -0
  35. package/dist/__tests__/router-classify-unified.test.js.map +1 -0
  36. package/dist/__tests__/router-fallback.test.js +1 -1
  37. package/dist/__tests__/router-fallback.test.js.map +1 -1
  38. package/dist/__tests__/router-model-registry.test.js +24 -0
  39. package/dist/__tests__/router-model-registry.test.js.map +1 -1
  40. package/dist/__tests__/router-retry.test.js +3 -5
  41. package/dist/__tests__/router-retry.test.js.map +1 -1
  42. package/dist/__tests__/router-runagent.test.d.ts +14 -0
  43. package/dist/__tests__/router-runagent.test.d.ts.map +1 -0
  44. package/dist/__tests__/router-runagent.test.js +95 -0
  45. package/dist/__tests__/router-runagent.test.js.map +1 -0
  46. package/dist/__tests__/router-scaffold.test.js +2 -1
  47. package/dist/__tests__/router-scaffold.test.js.map +1 -1
  48. package/dist/__tests__/router-spend-ledger.test.js +1 -1
  49. package/dist/__tests__/router-spend-ledger.test.js.map +1 -1
  50. package/dist/__tests__/router-stream-fallback.test.d.ts +13 -0
  51. package/dist/__tests__/router-stream-fallback.test.d.ts.map +1 -0
  52. package/dist/__tests__/router-stream-fallback.test.js +129 -0
  53. package/dist/__tests__/router-stream-fallback.test.js.map +1 -0
  54. package/dist/__tests__/router-telemetry.test.js +3 -1
  55. package/dist/__tests__/router-telemetry.test.js.map +1 -1
  56. package/dist/__tests__/util/mock-upstream.d.ts +77 -0
  57. package/dist/__tests__/util/mock-upstream.d.ts.map +1 -0
  58. package/dist/__tests__/util/mock-upstream.js +219 -0
  59. package/dist/__tests__/util/mock-upstream.js.map +1 -0
  60. package/dist/adk-adapter.d.ts.map +1 -1
  61. package/dist/adk-adapter.js +51 -0
  62. package/dist/adk-adapter.js.map +1 -1
  63. package/dist/adk-anthropic-llm.d.ts.map +1 -1
  64. package/dist/adk-anthropic-llm.js +23 -10
  65. package/dist/adk-anthropic-llm.js.map +1 -1
  66. package/dist/agent/session/adapter.d.ts +25 -0
  67. package/dist/agent/session/adapter.d.ts.map +1 -1
  68. package/dist/agent/session/adapter.js +4 -0
  69. package/dist/agent/session/adapter.js.map +1 -1
  70. package/dist/agent/session/index.d.ts +1 -0
  71. package/dist/agent/session/index.d.ts.map +1 -1
  72. package/dist/agent/session/index.js +1 -0
  73. package/dist/agent/session/index.js.map +1 -1
  74. package/dist/agent/session/language-model-bridge.d.ts.map +1 -1
  75. package/dist/agent/session/language-model-bridge.js +30 -2
  76. package/dist/agent/session/language-model-bridge.js.map +1 -1
  77. package/dist/agent/session/legacy-adapter-language-model.d.ts +27 -0
  78. package/dist/agent/session/legacy-adapter-language-model.d.ts.map +1 -0
  79. package/dist/agent/session/legacy-adapter-language-model.js +221 -0
  80. package/dist/agent/session/legacy-adapter-language-model.js.map +1 -0
  81. package/dist/agent/session/types.d.ts +32 -0
  82. package/dist/agent/session/types.d.ts.map +1 -1
  83. package/dist/agent/session/types.js.map +1 -1
  84. package/dist/claude-adapter.d.ts.map +1 -1
  85. package/dist/claude-adapter.js +27 -0
  86. package/dist/claude-adapter.js.map +1 -1
  87. package/dist/fetch-pool.d.ts +47 -0
  88. package/dist/fetch-pool.d.ts.map +1 -0
  89. package/dist/fetch-pool.js +132 -0
  90. package/dist/fetch-pool.js.map +1 -0
  91. package/dist/gemini-adapter.d.ts.map +1 -1
  92. package/dist/gemini-adapter.js +65 -6
  93. package/dist/gemini-adapter.js.map +1 -1
  94. package/dist/index.d.ts +11 -0
  95. package/dist/index.d.ts.map +1 -1
  96. package/dist/index.js +6 -0
  97. package/dist/index.js.map +1 -1
  98. package/dist/ollama-adapter.d.ts.map +1 -1
  99. package/dist/ollama-adapter.js +145 -15
  100. package/dist/ollama-adapter.js.map +1 -1
  101. package/dist/openrouter-adapter.d.ts.map +1 -1
  102. package/dist/openrouter-adapter.js +296 -15
  103. package/dist/openrouter-adapter.js.map +1 -1
  104. package/dist/prefill/strip.d.ts +49 -0
  105. package/dist/prefill/strip.d.ts.map +1 -0
  106. package/dist/prefill/strip.js +93 -0
  107. package/dist/prefill/strip.js.map +1 -0
  108. package/dist/prefill/translate.d.ts +55 -0
  109. package/dist/prefill/translate.d.ts.map +1 -0
  110. package/dist/prefill/translate.js +162 -0
  111. package/dist/prefill/translate.js.map +1 -0
  112. package/dist/prefill/truncate.d.ts +62 -0
  113. package/dist/prefill/truncate.d.ts.map +1 -0
  114. package/dist/prefill/truncate.js +77 -0
  115. package/dist/prefill/truncate.js.map +1 -0
  116. package/dist/provider-liveness.d.ts.map +1 -1
  117. package/dist/provider-liveness.js +17 -6
  118. package/dist/provider-liveness.js.map +1 -1
  119. package/dist/router/errors.d.ts +24 -7
  120. package/dist/router/errors.d.ts.map +1 -1
  121. package/dist/router/errors.js +71 -14
  122. package/dist/router/errors.js.map +1 -1
  123. package/dist/router/index.d.ts +3 -2
  124. package/dist/router/index.d.ts.map +1 -1
  125. package/dist/router/index.js +2 -1
  126. package/dist/router/index.js.map +1 -1
  127. package/dist/router/local-executor.d.ts.map +1 -1
  128. package/dist/router/local-executor.js +19 -6
  129. package/dist/router/local-executor.js.map +1 -1
  130. package/dist/router/model-registry.d.ts +22 -0
  131. package/dist/router/model-registry.d.ts.map +1 -1
  132. package/dist/router/model-registry.js +64 -1
  133. package/dist/router/model-registry.js.map +1 -1
  134. package/dist/router/provider-registry-resolver.d.ts +25 -0
  135. package/dist/router/provider-registry-resolver.d.ts.map +1 -0
  136. package/dist/router/provider-registry-resolver.js +84 -0
  137. package/dist/router/provider-registry-resolver.js.map +1 -0
  138. package/dist/router/retry.d.ts +3 -0
  139. package/dist/router/retry.d.ts.map +1 -1
  140. package/dist/router/retry.js +4 -1
  141. package/dist/router/retry.js.map +1 -1
  142. package/dist/router/router.d.ts +79 -1
  143. package/dist/router/router.d.ts.map +1 -1
  144. package/dist/router/router.js +256 -2
  145. package/dist/router/router.js.map +1 -1
  146. package/dist/router/types.d.ts +1 -1
  147. package/dist/router/types.d.ts.map +1 -1
  148. package/dist/router/types.js +1 -0
  149. package/dist/router/types.js.map +1 -1
  150. package/dist/single-shot.d.ts.map +1 -1
  151. package/dist/single-shot.js +26 -1
  152. package/dist/single-shot.js.map +1 -1
  153. package/dist/tools/builtin.d.ts +19 -0
  154. package/dist/tools/builtin.d.ts.map +1 -1
  155. package/dist/tools/builtin.js +51 -0
  156. package/dist/tools/builtin.js.map +1 -1
  157. package/dist/turn-recorder/__tests__/turn-recorder.test.d.ts +20 -0
  158. package/dist/turn-recorder/__tests__/turn-recorder.test.d.ts.map +1 -0
  159. package/dist/turn-recorder/__tests__/turn-recorder.test.js +282 -0
  160. package/dist/turn-recorder/__tests__/turn-recorder.test.js.map +1 -0
  161. package/dist/turn-recorder/hash.d.ts +10 -0
  162. package/dist/turn-recorder/hash.d.ts.map +1 -0
  163. package/dist/turn-recorder/hash.js +35 -0
  164. package/dist/turn-recorder/hash.js.map +1 -0
  165. package/dist/turn-recorder/index.d.ts +119 -0
  166. package/dist/turn-recorder/index.d.ts.map +1 -0
  167. package/dist/turn-recorder/index.js +326 -0
  168. package/dist/turn-recorder/index.js.map +1 -0
  169. package/dist/turn-recorder/types.d.ts +227 -0
  170. package/dist/turn-recorder/types.d.ts.map +1 -0
  171. package/dist/turn-recorder/types.js +20 -0
  172. package/dist/turn-recorder/types.js.map +1 -0
  173. package/dist/types.d.ts +35 -2
  174. package/dist/types.d.ts.map +1 -1
  175. package/package.json +4 -3
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Cross-provider strip policy (v2 ADR §2.3.1).
3
+ *
4
+ * Vendor-specific message blocks DO NOT survive a chain-fallback swap
5
+ * across providers. `stripForTarget` removes fields the target provider
6
+ * would reject (or silently misinterpret) when the conversation
7
+ * originated on a different vendor.
8
+ *
9
+ * The matrix (§2.3.1):
10
+ * - reasoning_details[] / reasoning — OpenRouter reasoning models;
11
+ * strip when source !== target (Anthropic + OpenAI reject them).
12
+ * - cache_control — Anthropic; strip when target is non-Anthropic.
13
+ * - prompt_cache_key — OpenAI; strip when target is non-OpenAI.
14
+ *
15
+ * Same-vendor swaps short-circuit: nothing is stripped (hot path), and
16
+ * they additionally qualify for the §5.1 prefix-cache fast-path.
17
+ *
18
+ * The function is shape-agnostic: it walks each message object and
19
+ * deletes the known vendor keys (including inside content-block arrays
20
+ * for Anthropic's `cache_control`). It never mutates the input — every
21
+ * message is shallow-cloned before a key is removed.
22
+ */
23
+ import type { ProviderName } from '../types.js';
24
+ export interface StripContext {
25
+ sourceProvider: ProviderName;
26
+ targetProvider: ProviderName;
27
+ }
28
+ /** Anthropic family: native `messages` API consumers.
29
+ *
30
+ * NOTE on 'adk': ADK is provider-agnostic at runtime (claude-via-adk =
31
+ * Anthropic wire; gemini-via-adk = Google wire). Per ADR §2.8, ADK
32
+ * prefill is materialized via `Session.appendEvent`, NOT through
33
+ * `materializePrefill`/`stripForTarget` — so this predicate is NOT
34
+ * exercised for ADK targets in the H2 path. When ADK is ported (H4),
35
+ * its wire format must be detected from the underlying model id, not
36
+ * assumed Anthropic here. Kept in the Anthropic bucket only so the
37
+ * §5.1 same-vendor cache fast-path can recognise `claude`↔`claude`;
38
+ * revisit when ADK joins the prefill path. */
39
+ declare function isAnthropic(p: ProviderName): boolean;
40
+ /** OpenAI-compatible chat-completions consumers. */
41
+ declare function isOpenAICompat(p: ProviderName): boolean;
42
+ /**
43
+ * Return a new message array safe to send to `targetProvider` given it
44
+ * originated on `sourceProvider`. Same-vendor → returned as a shallow
45
+ * copy untouched.
46
+ */
47
+ export declare function stripForTarget(messages: readonly unknown[], ctx: StripContext): unknown[];
48
+ export { isAnthropic, isOpenAICompat };
49
+ //# sourceMappingURL=strip.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"strip.d.ts","sourceRoot":"","sources":["../../src/prefill/strip.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,WAAW,YAAY;IAC3B,cAAc,EAAE,YAAY,CAAC;IAC7B,cAAc,EAAE,YAAY,CAAC;CAC9B;AAED;;;;;;;;;;8CAU8C;AAC9C,iBAAS,WAAW,CAAC,CAAC,EAAE,YAAY,GAAG,OAAO,CAE7C;AAED,oDAAoD;AACpD,iBAAS,cAAc,CAAC,CAAC,EAAE,YAAY,GAAG,OAAO,CAEhD;AAID;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,EAAE,GAAG,EAAE,YAAY,GAAG,OAAO,EAAE,CAqCzF;AAcD,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,CAAC"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Cross-provider strip policy (v2 ADR §2.3.1).
3
+ *
4
+ * Vendor-specific message blocks DO NOT survive a chain-fallback swap
5
+ * across providers. `stripForTarget` removes fields the target provider
6
+ * would reject (or silently misinterpret) when the conversation
7
+ * originated on a different vendor.
8
+ *
9
+ * The matrix (§2.3.1):
10
+ * - reasoning_details[] / reasoning — OpenRouter reasoning models;
11
+ * strip when source !== target (Anthropic + OpenAI reject them).
12
+ * - cache_control — Anthropic; strip when target is non-Anthropic.
13
+ * - prompt_cache_key — OpenAI; strip when target is non-OpenAI.
14
+ *
15
+ * Same-vendor swaps short-circuit: nothing is stripped (hot path), and
16
+ * they additionally qualify for the §5.1 prefix-cache fast-path.
17
+ *
18
+ * The function is shape-agnostic: it walks each message object and
19
+ * deletes the known vendor keys (including inside content-block arrays
20
+ * for Anthropic's `cache_control`). It never mutates the input — every
21
+ * message is shallow-cloned before a key is removed.
22
+ */
23
+ /** Anthropic family: native `messages` API consumers.
24
+ *
25
+ * NOTE on 'adk': ADK is provider-agnostic at runtime (claude-via-adk =
26
+ * Anthropic wire; gemini-via-adk = Google wire). Per ADR §2.8, ADK
27
+ * prefill is materialized via `Session.appendEvent`, NOT through
28
+ * `materializePrefill`/`stripForTarget` — so this predicate is NOT
29
+ * exercised for ADK targets in the H2 path. When ADK is ported (H4),
30
+ * its wire format must be detected from the underlying model id, not
31
+ * assumed Anthropic here. Kept in the Anthropic bucket only so the
32
+ * §5.1 same-vendor cache fast-path can recognise `claude`↔`claude`;
33
+ * revisit when ADK joins the prefill path. */
34
+ function isAnthropic(p) {
35
+ return p === 'adk' || p === 'claude';
36
+ }
37
+ /** OpenAI-compatible chat-completions consumers. */
38
+ function isOpenAICompat(p) {
39
+ return p === 'openai' || p === 'openrouter' || p === 'opencode' || p === 'ollama';
40
+ }
41
+ /**
42
+ * Return a new message array safe to send to `targetProvider` given it
43
+ * originated on `sourceProvider`. Same-vendor → returned as a shallow
44
+ * copy untouched.
45
+ */
46
+ export function stripForTarget(messages, ctx) {
47
+ if (ctx.sourceProvider === ctx.targetProvider) {
48
+ return messages.slice();
49
+ }
50
+ const dropReasoning = !isOpenRouterFamily(ctx.targetProvider);
51
+ const dropCacheControl = !isAnthropic(ctx.targetProvider);
52
+ const dropPromptCacheKey = !isOpenAIExact(ctx.targetProvider);
53
+ return messages.map((raw) => {
54
+ if (!raw || typeof raw !== 'object')
55
+ return raw;
56
+ const msg = { ...raw };
57
+ if (dropReasoning) {
58
+ delete msg.reasoning;
59
+ delete msg.reasoning_details;
60
+ }
61
+ if (dropPromptCacheKey) {
62
+ delete msg.prompt_cache_key;
63
+ }
64
+ if (dropCacheControl) {
65
+ // top-level marker
66
+ delete msg.cache_control;
67
+ // Anthropic puts cache_control inside content-block arrays.
68
+ if (Array.isArray(msg.content)) {
69
+ msg.content = msg.content.map((block) => {
70
+ if (block && typeof block === 'object' && 'cache_control' in block) {
71
+ const clone = { ...block };
72
+ delete clone.cache_control;
73
+ return clone;
74
+ }
75
+ return block;
76
+ });
77
+ }
78
+ }
79
+ return msg;
80
+ });
81
+ }
82
+ /** OpenRouter (and OpenCode, which proxies OpenRouter-style models) are
83
+ * the only consumers that accept echoed reasoning_details. */
84
+ function isOpenRouterFamily(p) {
85
+ return p === 'openrouter' || p === 'opencode';
86
+ }
87
+ /** Exact OpenAI — the only consumer that honors `prompt_cache_key`. */
88
+ function isOpenAIExact(p) {
89
+ return p === 'openai';
90
+ }
91
+ // Re-export the family predicates for the translate layer + tests.
92
+ export { isAnthropic, isOpenAICompat };
93
+ //# sourceMappingURL=strip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"strip.js","sourceRoot":"","sources":["../../src/prefill/strip.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AASH;;;;;;;;;;8CAU8C;AAC9C,SAAS,WAAW,CAAC,CAAe;IAClC,OAAO,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,QAAQ,CAAC;AACvC,CAAC;AAED,oDAAoD;AACpD,SAAS,cAAc,CAAC,CAAe;IACrC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,YAAY,IAAI,CAAC,KAAK,UAAU,IAAI,CAAC,KAAK,QAAQ,CAAC;AACpF,CAAC;AAID;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,QAA4B,EAAE,GAAiB;IAC5E,IAAI,GAAG,CAAC,cAAc,KAAK,GAAG,CAAC,cAAc,EAAE,CAAC;QAC9C,OAAO,QAAQ,CAAC,KAAK,EAAE,CAAC;IAC1B,CAAC;IAED,MAAM,aAAa,GAAG,CAAC,kBAAkB,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAC9D,MAAM,gBAAgB,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAC1D,MAAM,kBAAkB,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAE9D,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QAC1B,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;YAAE,OAAO,GAAG,CAAC;QAChD,MAAM,GAAG,GAAG,EAAE,GAAI,GAAoB,EAAE,CAAC;QAEzC,IAAI,aAAa,EAAE,CAAC;YAClB,OAAO,GAAG,CAAC,SAAS,CAAC;YACrB,OAAO,GAAG,CAAC,iBAAiB,CAAC;QAC/B,CAAC;QACD,IAAI,kBAAkB,EAAE,CAAC;YACvB,OAAO,GAAG,CAAC,gBAAgB,CAAC;QAC9B,CAAC;QACD,IAAI,gBAAgB,EAAE,CAAC;YACrB,mBAAmB;YACnB,OAAO,GAAG,CAAC,aAAa,CAAC;YACzB,4DAA4D;YAC5D,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC/B,GAAG,CAAC,OAAO,GAAI,GAAG,CAAC,OAAqB,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;oBACrD,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,eAAe,IAAK,KAAgB,EAAE,CAAC;wBAC/E,MAAM,KAAK,GAAG,EAAE,GAAI,KAAiC,EAAE,CAAC;wBACxD,OAAO,KAAK,CAAC,aAAa,CAAC;wBAC3B,OAAO,KAAK,CAAC;oBACf,CAAC;oBACD,OAAO,KAAK,CAAC;gBACf,CAAC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC,CAAC,CAAC;AACL,CAAC;AAED;+DAC+D;AAC/D,SAAS,kBAAkB,CAAC,CAAe;IACzC,OAAO,CAAC,KAAK,YAAY,IAAI,CAAC,KAAK,UAAU,CAAC;AAChD,CAAC;AAED,uEAAuE;AACvE,SAAS,aAAa,CAAC,CAAe;IACpC,OAAO,CAAC,KAAK,QAAQ,CAAC;AACxB,CAAC;AAED,mEAAmE;AACnE,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,CAAC"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Tool-result + prefill shape translation (v2 ADR §2.3.2 / §2.3).
3
+ *
4
+ * The durable log stores tool results in a neutral shape
5
+ * (`NeutralToolResult`). When a chain-fallback swap re-injects a prior
6
+ * model's turn into a NEW provider, the adapter materializes that turn
7
+ * into the target provider's wire format. This module owns that
8
+ * translation.
9
+ *
10
+ * - Anthropic native:
11
+ * tool_use → { role: 'assistant', content: [{ type: 'tool_use', id, name, input }] }
12
+ * result → { role: 'user', content: [{ type: 'tool_result', tool_use_id, content, is_error }] }
13
+ * - OpenAI-compat (openrouter, opencode, openai, ollama):
14
+ * tool_use → { role: 'assistant', tool_calls: [{ id, type:'function', function:{ name, arguments } }] }
15
+ * result → { role: 'tool', tool_call_id, content: stringify }
16
+ * - ADK: materialized via Session.appendEvent inside the adk adapter
17
+ * (functionCall + functionResponse events) — NOT via this module.
18
+ *
19
+ * `materializePrefill` turns a `Prefill` into the ordered list of wire
20
+ * messages to splice into the request BEFORE the continuation: for each
21
+ * recorded tool use, an assistant(tool_call) + tool(result) pair, then
22
+ * a trailing assistant message carrying the partial text the prior
23
+ * model streamed. The target model continues from that trailing
24
+ * assistant message (verified empirically — Anthropic + OpenAI-compat
25
+ * both honor a trailing assistant message as a continuation prefix).
26
+ */
27
+ import type { ProviderName } from '../types.js';
28
+ import type { NeutralToolResult, Prefill, PrefillTurn } from '../turn-recorder/types.js';
29
+ export interface TranslatedToolResult {
30
+ /** Target-specific wire object the adapter appends to messages[]. */
31
+ message: unknown;
32
+ }
33
+ /** Convert a `NeutralToolResult` to the target provider's result message. */
34
+ export declare function translateToolResult(result: NeutralToolResult, target: ProviderName): TranslatedToolResult;
35
+ /**
36
+ * Build the ordered wire messages that re-present a `Prefill` to the
37
+ * target provider. The caller splices these onto the end of its
38
+ * `messages[]` (after system + user), then lets the model continue.
39
+ *
40
+ * Ordering: each recorded tool use becomes an assistant(tool_call) +
41
+ * result pair, in recorded order; finally a trailing assistant message
42
+ * carrying the partial text (only when non-empty — an empty trailing
43
+ * assistant message is rejected by some providers).
44
+ */
45
+ export declare function materializePrefill(prefill: Prefill, target: ProviderName): unknown[];
46
+ /**
47
+ * §Tier 2 — materialize a list of COMPLETED prior turns into the target
48
+ * provider's wire format, spliced BEFORE the new user message so a stateful
49
+ * (non-claude) session resume re-presents the full conversation. Each turn
50
+ * emits, in order: its opening user message (when `userPrompt` is set — the
51
+ * first turn of a phase), then one combined assistant(text+tool_calls), then
52
+ * its tool results. Empty list → [] (START phase / no prior turns).
53
+ */
54
+ export declare function materializePriorTurns(turns: PrefillTurn[], target: ProviderName): unknown[];
55
+ //# sourceMappingURL=translate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"translate.d.ts","sourceRoot":"","sources":["../../src/prefill/translate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,iBAAiB,EAAE,OAAO,EAAE,WAAW,EAAkB,MAAM,2BAA2B,CAAC;AAGzG,MAAM,WAAW,oBAAoB;IACnC,qEAAqE;IACrE,OAAO,EAAE,OAAO,CAAC;CAClB;AAMD,6EAA6E;AAC7E,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,iBAAiB,EACzB,MAAM,EAAE,YAAY,GACnB,oBAAoB,CA6BtB;AA6BD;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,EAAE,CAUpF;AAsCD;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,EAAE,CAe3F"}
@@ -0,0 +1,162 @@
1
+ /**
2
+ * Tool-result + prefill shape translation (v2 ADR §2.3.2 / §2.3).
3
+ *
4
+ * The durable log stores tool results in a neutral shape
5
+ * (`NeutralToolResult`). When a chain-fallback swap re-injects a prior
6
+ * model's turn into a NEW provider, the adapter materializes that turn
7
+ * into the target provider's wire format. This module owns that
8
+ * translation.
9
+ *
10
+ * - Anthropic native:
11
+ * tool_use → { role: 'assistant', content: [{ type: 'tool_use', id, name, input }] }
12
+ * result → { role: 'user', content: [{ type: 'tool_result', tool_use_id, content, is_error }] }
13
+ * - OpenAI-compat (openrouter, opencode, openai, ollama):
14
+ * tool_use → { role: 'assistant', tool_calls: [{ id, type:'function', function:{ name, arguments } }] }
15
+ * result → { role: 'tool', tool_call_id, content: stringify }
16
+ * - ADK: materialized via Session.appendEvent inside the adk adapter
17
+ * (functionCall + functionResponse events) — NOT via this module.
18
+ *
19
+ * `materializePrefill` turns a `Prefill` into the ordered list of wire
20
+ * messages to splice into the request BEFORE the continuation: for each
21
+ * recorded tool use, an assistant(tool_call) + tool(result) pair, then
22
+ * a trailing assistant message carrying the partial text the prior
23
+ * model streamed. The target model continues from that trailing
24
+ * assistant message (verified empirically — Anthropic + OpenAI-compat
25
+ * both honor a trailing assistant message as a continuation prefix).
26
+ */
27
+ import { isAnthropic } from './strip.js';
28
+ function stringifyContent(content) {
29
+ return typeof content === 'string' ? content : JSON.stringify(content ?? null);
30
+ }
31
+ /** Convert a `NeutralToolResult` to the target provider's result message. */
32
+ export function translateToolResult(result, target) {
33
+ // Defensive guard (review finding): an empty tool_use_id / tool_call_id
34
+ // makes the upstream reject with "tool_use_id does not reference a known
35
+ // tool_use". The ADK path can produce `id ?? ''`; fail loud here rather
36
+ // than ship a malformed request.
37
+ if (!result.toolUseId) {
38
+ throw new Error('translateToolResult: NeutralToolResult.toolUseId is empty — cannot bind tool result to a tool_use');
39
+ }
40
+ if (isAnthropic(target)) {
41
+ return {
42
+ message: {
43
+ role: 'user',
44
+ content: [{
45
+ type: 'tool_result',
46
+ tool_use_id: result.toolUseId,
47
+ content: stringifyContent(result.content),
48
+ is_error: !result.ok,
49
+ }],
50
+ },
51
+ };
52
+ }
53
+ // OpenAI-compatible default.
54
+ return {
55
+ message: {
56
+ role: 'tool',
57
+ tool_call_id: result.toolUseId,
58
+ content: stringifyContent(result.content),
59
+ },
60
+ };
61
+ }
62
+ /** The assistant message that re-presents a recorded tool_use to the
63
+ * target so the following tool-result message is well-formed. */
64
+ function translateToolUseAssistant(use, target) {
65
+ if (isAnthropic(target)) {
66
+ return {
67
+ role: 'assistant',
68
+ content: [{ type: 'tool_use', id: use.id, name: use.name, input: use.input ?? {} }],
69
+ };
70
+ }
71
+ return {
72
+ // Empty string, not null: an assistant message that only carries a
73
+ // tool_call has no text preamble. While most OpenAI-compat upstreams
74
+ // accept `content: null` here, `''` is universally valid and removes
75
+ // any ambiguity across the openai/openrouter/opencode/ollama set.
76
+ role: 'assistant',
77
+ content: '',
78
+ tool_calls: [{
79
+ id: use.id,
80
+ type: 'function',
81
+ function: { name: use.name, arguments: JSON.stringify(use.input ?? {}) },
82
+ }],
83
+ };
84
+ }
85
+ /**
86
+ * Build the ordered wire messages that re-present a `Prefill` to the
87
+ * target provider. The caller splices these onto the end of its
88
+ * `messages[]` (after system + user), then lets the model continue.
89
+ *
90
+ * Ordering: each recorded tool use becomes an assistant(tool_call) +
91
+ * result pair, in recorded order; finally a trailing assistant message
92
+ * carrying the partial text (only when non-empty — an empty trailing
93
+ * assistant message is rejected by some providers).
94
+ */
95
+ export function materializePrefill(prefill, target) {
96
+ const out = [];
97
+ for (const use of prefill.toolUses) {
98
+ out.push(translateToolUseAssistant({ id: use.id, name: use.name, input: use.input }, target));
99
+ out.push(translateToolResult(use.result, target).message);
100
+ }
101
+ if (prefill.text.length > 0) {
102
+ out.push({ role: 'assistant', content: prefill.text });
103
+ }
104
+ return out;
105
+ }
106
+ /**
107
+ * One COMPLETED prior turn as a single assistant message (text + tool_calls
108
+ * combined) followed by its tool-result messages. UNLIKE `materializePrefill`
109
+ * — which keeps the partial text as a separate TRAILING assistant message so
110
+ * the live model continues from it — a completed turn's text and tool calls
111
+ * belong to one wire message. Emitting them split would put a phase's
112
+ * tool-loop turns back-to-back as consecutive assistant messages (no
113
+ * intervening tool/user), which OpenAI-compat upstreams reject or silently
114
+ * merge. The combined shape reproduces the exact tool-loop wire sequence:
115
+ * assistant(text,tool_calls) → tool(result)* → (next turn).
116
+ */
117
+ function combinedAssistantMessage(text, toolUses, target) {
118
+ if (isAnthropic(target)) {
119
+ const content = [];
120
+ if (text.length > 0)
121
+ content.push({ type: 'text', text });
122
+ for (const u of toolUses) {
123
+ content.push({ type: 'tool_use', id: u.id, name: u.name, input: u.input ?? {} });
124
+ }
125
+ return { role: 'assistant', content };
126
+ }
127
+ // OpenAI-compat: text + tool_calls live on ONE assistant message.
128
+ const msg = { role: 'assistant', content: text };
129
+ if (toolUses.length > 0) {
130
+ msg.tool_calls = toolUses.map((u) => ({
131
+ id: u.id,
132
+ type: 'function',
133
+ function: { name: u.name, arguments: JSON.stringify(u.input ?? {}) },
134
+ }));
135
+ }
136
+ return msg;
137
+ }
138
+ /**
139
+ * §Tier 2 — materialize a list of COMPLETED prior turns into the target
140
+ * provider's wire format, spliced BEFORE the new user message so a stateful
141
+ * (non-claude) session resume re-presents the full conversation. Each turn
142
+ * emits, in order: its opening user message (when `userPrompt` is set — the
143
+ * first turn of a phase), then one combined assistant(text+tool_calls), then
144
+ * its tool results. Empty list → [] (START phase / no prior turns).
145
+ */
146
+ export function materializePriorTurns(turns, target) {
147
+ const out = [];
148
+ for (const turn of turns) {
149
+ if (typeof turn.userPrompt === 'string' && turn.userPrompt.length > 0) {
150
+ out.push({ role: 'user', content: turn.userPrompt });
151
+ }
152
+ // A completed turn always carries text and/or tools; guard the empty case.
153
+ if (turn.text.length > 0 || turn.toolUses.length > 0) {
154
+ out.push(combinedAssistantMessage(turn.text, turn.toolUses, target));
155
+ }
156
+ for (const use of turn.toolUses) {
157
+ out.push(translateToolResult(use.result, target).message);
158
+ }
159
+ }
160
+ return out;
161
+ }
162
+ //# sourceMappingURL=translate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"translate.js","sourceRoot":"","sources":["../../src/prefill/translate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * §2.3.3 context-window truncation policy.
3
+ *
4
+ * `prefill.text` (the partial assistant continuation) plus the recorded
5
+ * tool history may push the resuming request over the TARGET model's
6
+ * input window even though it fit on the source model. Before the chain
7
+ * walker hands a prefill to the next attempt, it runs this gate:
8
+ *
9
+ * budget = target.maxInputTokens − margin(8K) − baseTokens
10
+ * − sourceTokens − sum(toolUseTokens)
11
+ *
12
+ * 1. If the partial text alone won't fit (budget-before-tools < 0),
13
+ * the prefill CANNOT be served → return undefined. The walker then
14
+ * retries the next model WITHOUT a prefill (a clean re-run beats a
15
+ * failed run, per §2.3.3 step 3).
16
+ * 2. Otherwise drop the OLDEST tool_use/result pairs (from the start)
17
+ * until the tool history fits, preserving the most-recent tools and
18
+ * the trailing partial text. Those dropped tools already executed on
19
+ * the source model; the resuming model simply won't see them in its
20
+ * re-presented history.
21
+ *
22
+ * `maxInputTokens` comes from `cost.ts`'s model-prices table; a model
23
+ * missing from the table conservatively assumes 32K (§2.3.3 step 4).
24
+ *
25
+ * Token counts are estimates (default ~chars/4) — exact tokenization is
26
+ * deferred (§ ADR open question). The 8K margin absorbs the slack; if the
27
+ * estimate is too aggressive the walker just drops an extra tool pair,
28
+ * which is a slower chain walk, not a correctness loss.
29
+ */
30
+ import type { Prefill } from '../turn-recorder/types.js';
31
+ /** Conservative floor when the model is absent from the price table. */
32
+ export declare const DEFAULT_MAX_INPUT_TOKENS = 32000;
33
+ /** Headroom reserved below the model's max input window. */
34
+ export declare const DEFAULT_MARGIN_TOKENS = 8000;
35
+ export interface TruncatePrefillArgs {
36
+ prefill: Prefill;
37
+ /** Model id the prefill is about to be served to. */
38
+ targetModel: string;
39
+ /**
40
+ * Tokens already committed to the request before the prefill is
41
+ * spliced (system prompt + the user turn). Best-effort; default 0.
42
+ * Counted against the budget so a large system prompt + big prefill
43
+ * don't silently blow the window.
44
+ */
45
+ baseTokens?: number;
46
+ /** Headroom under the model's max input window. Default 8000. */
47
+ marginTokens?: number;
48
+ /** Estimator over an arbitrary string. Default ≈ chars/4. */
49
+ estimateTokens?: (text: string) => number;
50
+ /**
51
+ * Override the target's max-input-token lookup (tests / models the
52
+ * cost table can't price). Default reads `cost.ts`.
53
+ */
54
+ maxInputTokensFor?: (model: string) => number | undefined;
55
+ }
56
+ /**
57
+ * Returns the (possibly tool-trimmed) prefill that fits the target
58
+ * model's input budget, or `undefined` when even the bare partial text
59
+ * won't fit — signalling the walker to retry without a prefill.
60
+ */
61
+ export declare function truncatePrefillForBudget(args: TruncatePrefillArgs): Prefill | undefined;
62
+ //# sourceMappingURL=truncate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"truncate.d.ts","sourceRoot":"","sources":["../../src/prefill/truncate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AAEzD,wEAAwE;AACxE,eAAO,MAAM,wBAAwB,QAAS,CAAC;AAC/C,4DAA4D;AAC5D,eAAO,MAAM,qBAAqB,OAAQ,CAAC;AAE3C,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,qDAAqD;IACrD,WAAW,EAAE,MAAM,CAAC;IACpB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iEAAiE;IACjE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,6DAA6D;IAC7D,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAC1C;;;OAGG;IACH,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;CAC3D;AAeD;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,GAAG,SAAS,CAiCvF"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * §2.3.3 context-window truncation policy.
3
+ *
4
+ * `prefill.text` (the partial assistant continuation) plus the recorded
5
+ * tool history may push the resuming request over the TARGET model's
6
+ * input window even though it fit on the source model. Before the chain
7
+ * walker hands a prefill to the next attempt, it runs this gate:
8
+ *
9
+ * budget = target.maxInputTokens − margin(8K) − baseTokens
10
+ * − sourceTokens − sum(toolUseTokens)
11
+ *
12
+ * 1. If the partial text alone won't fit (budget-before-tools < 0),
13
+ * the prefill CANNOT be served → return undefined. The walker then
14
+ * retries the next model WITHOUT a prefill (a clean re-run beats a
15
+ * failed run, per §2.3.3 step 3).
16
+ * 2. Otherwise drop the OLDEST tool_use/result pairs (from the start)
17
+ * until the tool history fits, preserving the most-recent tools and
18
+ * the trailing partial text. Those dropped tools already executed on
19
+ * the source model; the resuming model simply won't see them in its
20
+ * re-presented history.
21
+ *
22
+ * `maxInputTokens` comes from `cost.ts`'s model-prices table; a model
23
+ * missing from the table conservatively assumes 32K (§2.3.3 step 4).
24
+ *
25
+ * Token counts are estimates (default ~chars/4) — exact tokenization is
26
+ * deferred (§ ADR open question). The 8K margin absorbs the slack; if the
27
+ * estimate is too aggressive the walker just drops an extra tool pair,
28
+ * which is a slower chain walk, not a correctness loss.
29
+ */
30
+ import { getDetailedPricing } from '../cost.js';
31
+ /** Conservative floor when the model is absent from the price table. */
32
+ export const DEFAULT_MAX_INPUT_TOKENS = 32_000;
33
+ /** Headroom reserved below the model's max input window. */
34
+ export const DEFAULT_MARGIN_TOKENS = 8_000;
35
+ const defaultEstimate = (text) => Math.ceil(text.length / 4);
36
+ /** Rough token cost of re-presenting one recorded tool_use/result pair. */
37
+ function toolUseTokens(tu, estimate) {
38
+ const content = typeof tu.result?.content === 'string'
39
+ ? tu.result.content
40
+ : JSON.stringify(tu.result?.content ?? '');
41
+ return estimate(`${tu.name}${JSON.stringify(tu.input ?? {})}${content}`);
42
+ }
43
+ /**
44
+ * Returns the (possibly tool-trimmed) prefill that fits the target
45
+ * model's input budget, or `undefined` when even the bare partial text
46
+ * won't fit — signalling the walker to retry without a prefill.
47
+ */
48
+ export function truncatePrefillForBudget(args) {
49
+ const estimate = args.estimateTokens ?? defaultEstimate;
50
+ const margin = args.marginTokens ?? DEFAULT_MARGIN_TOKENS;
51
+ const baseTokens = args.baseTokens ?? 0;
52
+ const maxInput = (args.maxInputTokensFor
53
+ ? args.maxInputTokensFor(args.targetModel)
54
+ : getDetailedPricing(args.targetModel)?.maxInputTokens)
55
+ ?? DEFAULT_MAX_INPUT_TOKENS;
56
+ // Budget remaining for the tool history AFTER the fixed costs (system +
57
+ // user + margin + the partial-text reinjection). If this is already
58
+ // negative the partial alone overflows the window → cannot serve.
59
+ const budgetForTools = maxInput - margin - baseTokens - args.prefill.sourceTokens;
60
+ if (budgetForTools < 0)
61
+ return undefined;
62
+ // Per-tool token estimates, oldest-first (prefill.toolUses preserves
63
+ // recording order). Drop from the FRONT until the sum fits.
64
+ const tools = args.prefill.toolUses.slice();
65
+ let toolSum = tools.reduce((acc, tu) => acc + toolUseTokens(tu, estimate), 0);
66
+ if (toolSum <= budgetForTools) {
67
+ return args.prefill; // fits as-is
68
+ }
69
+ while (tools.length > 0 && toolSum > budgetForTools) {
70
+ const dropped = tools.shift();
71
+ toolSum -= toolUseTokens(dropped, estimate);
72
+ }
73
+ // budgetForTools >= 0 guarantees the empty-tools case fits; return the
74
+ // trimmed prefill (which may have zero tools but always keeps the text).
75
+ return { ...args.prefill, toolUses: tools };
76
+ }
77
+ //# sourceMappingURL=truncate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"truncate.js","sourceRoot":"","sources":["../../src/prefill/truncate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAGhD,wEAAwE;AACxE,MAAM,CAAC,MAAM,wBAAwB,GAAG,MAAM,CAAC;AAC/C,4DAA4D;AAC5D,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,CAAC;AAwB3C,MAAM,eAAe,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AAE7E,2EAA2E;AAC3E,SAAS,aAAa,CACpB,EAA+B,EAC/B,QAA+B;IAE/B,MAAM,OAAO,GAAG,OAAO,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,QAAQ;QACpD,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO;QACnB,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC;IAC7C,OAAO,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,GAAG,OAAO,EAAE,CAAC,CAAC;AAC3E,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,wBAAwB,CAAC,IAAyB;IAChE,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,IAAI,eAAe,CAAC;IACxD,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,IAAI,qBAAqB,CAAC;IAC1D,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,CAAC,CAAC;IAExC,MAAM,QAAQ,GAAG,CAAC,IAAI,CAAC,iBAAiB;QACtC,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,WAAW,CAAC;QAC1C,CAAC,CAAC,kBAAkB,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,cAAc,CAAC;WACpD,wBAAwB,CAAC;IAE9B,wEAAwE;IACxE,oEAAoE;IACpE,kEAAkE;IAClE,MAAM,cAAc,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC;IAClF,IAAI,cAAc,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC;IAEzC,qEAAqE;IACrE,4DAA4D;IAC5D,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;IAC5C,IAAI,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,GAAG,aAAa,CAAC,EAAE,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;IAE9E,IAAI,OAAO,IAAI,cAAc,EAAE,CAAC;QAC9B,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,aAAa;IACpC,CAAC;IAED,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,GAAG,cAAc,EAAE,CAAC;QACpD,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,EAAG,CAAC;QAC/B,OAAO,IAAI,aAAa,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAC9C,CAAC;IAED,uEAAuE;IACvE,yEAAyE;IACzE,OAAO,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;AAC9C,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"provider-liveness.d.ts","sourceRoot":"","sources":["../src/provider-liveness.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAW1D;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAGpD;AAED,gEAAgE;AAChE,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,CAQ9E;AAED;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE,aAAa,EACpB,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,YAAY,GAC5C,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,YAAY,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAc3E;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,QAAQ,GAAG,eAAe,CAAC;CACpC;AAED,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,aAAa,EACpB,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,YAAY,EAC7C,aAAa,GAAE,WAAW,CAAC,MAAM,CAAa,GAC7C;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,YAAY,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,aAAa,EAAE,CAAA;CAAE,CAgC7F;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,SAAS,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/E;AAED,0EAA0E;AAC1E,wBAAgB,mBAAmB,IAAI,IAAI,CAG1C"}
1
+ {"version":3,"file":"provider-liveness.d.ts","sourceRoot":"","sources":["../src/provider-liveness.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAY1D;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAGpD;AAED,gEAAgE;AAChE,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,CAQ9E;AAED;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE,aAAa,EACpB,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,YAAY,GAC5C,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,YAAY,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAc3E;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,QAAQ,GAAG,eAAe,CAAC;CACpC;AAED,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,aAAa,EACpB,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,YAAY,EAC7C,aAAa,GAAE,WAAW,CAAC,MAAM,CAAa,GAC7C;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,YAAY,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,aAAa,EAAE,CAAA;CAAE,CAgC7F;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,SAAS,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/E;AAED,0EAA0E;AAC1E,wBAAgB,mBAAmB,IAAI,IAAI,CAG1C"}
@@ -12,6 +12,7 @@
12
12
  * (Ollama HTTP, env-var presence). Both cli and dashboard share the
13
13
  * same liveness state via the module-scoped cache.
14
14
  */
15
+ import { getFetchPool, recycleFetchPoolOnFailure } from './fetch-pool.js';
15
16
  const DEFAULT_TTL_MS = 30_000;
16
17
  let TTL_MS = DEFAULT_TTL_MS;
17
18
  const cache = new Map();
@@ -127,15 +128,25 @@ async function probe(provider) {
127
128
  }
128
129
  }
129
130
  async function probeOllama() {
130
- const baseUrl = (process.env.OLLAMA_HOST ?? 'http://localhost:11434').replace(/\/+$/, '');
131
+ // Default to 127.0.0.1 (not 'localhost') to skip macOS's IPv6→IPv4
132
+ // fallback, which can blow past the 2s timeout when Ollama only
133
+ // binds IPv4.
134
+ const baseUrl = (process.env.OLLAMA_HOST ?? 'http://127.0.0.1:11434').replace(/\/+$/, '');
131
135
  try {
132
- const ctrl = new AbortController();
133
- const timer = setTimeout(() => ctrl.abort(), 2000);
134
- const res = await fetch(`${baseUrl}/api/tags`, { signal: ctrl.signal });
135
- clearTimeout(timer);
136
+ const res = await fetch(`${baseUrl}/api/tags`, {
137
+ // AbortSignal.timeout is honored more reliably by undici than a
138
+ // manual AbortController + setTimeout, especially when a request
139
+ // is queued waiting for a pool slot or a stale keep-alive socket.
140
+ signal: AbortSignal.timeout(2000),
141
+ // @ts-expect-error — undici dispatcher accepted by Node fetch at runtime
142
+ dispatcher: getFetchPool('ollama'),
143
+ });
136
144
  return res.ok;
137
145
  }
138
- catch {
146
+ catch (err) {
147
+ // Probe failure isn't propagated, but it IS a signal the pool may
148
+ // be poisoned — heal so the next real request gets a fresh socket.
149
+ void recycleFetchPoolOnFailure('ollama', err);
139
150
  return false;
140
151
  }
141
152
  }
@@ -1 +1 @@
1
- {"version":3,"file":"provider-liveness.js","sourceRoot":"","sources":["../src/provider-liveness.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"provider-liveness.js","sourceRoot":"","sources":["../src/provider-liveness.ts"],"names":[],"mappings":"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"}