zidane 5.6.11 → 5.6.13
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 +19 -2
- package/dist/{agent-C9AKTU_V.d.ts → agent-ClkpElCZ.d.ts} +540 -55
- package/dist/agent-ClkpElCZ.d.ts.map +1 -0
- package/dist/chat.d.ts +47 -17
- package/dist/chat.d.ts.map +1 -1
- package/dist/chat.js +3 -3
- package/dist/{index-6f4T7Gc0.d.ts → index-CTDMMdIy.d.ts} +348 -3
- package/dist/index-CTDMMdIy.d.ts.map +1 -0
- package/dist/{index-DPN7TcXK.d.ts → index-v3Tzobqr.d.ts} +2 -2
- package/dist/{index-DPN7TcXK.d.ts.map → index-v3Tzobqr.d.ts.map} +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +169 -8
- package/dist/index.js.map +1 -1
- package/dist/{login-BindcfKi.js → login-DS3sf6b5.js} +4 -4
- package/dist/{login-BindcfKi.js.map → login-DS3sf6b5.js.map} +1 -1
- package/dist/{mcp-0jRkIV0g.js → mcp-DGeB7-3D.js} +13 -2
- package/dist/mcp-DGeB7-3D.js.map +1 -0
- package/dist/mcp.d.ts +1 -1
- package/dist/mcp.js +1 -1
- package/dist/{messages-BfmXLDT4.js → messages-Dym8S_YH.js} +303 -8
- package/dist/messages-Dym8S_YH.js.map +1 -0
- package/dist/{presets-CmzMeWg2.js → presets-CZXS_87d.js} +2 -2
- package/dist/{presets-CmzMeWg2.js.map → presets-CZXS_87d.js.map} +1 -1
- package/dist/presets.d.ts +2 -2
- package/dist/presets.js +1 -1
- package/dist/{providers-C_ahnRBS.js → providers-beXyD9W9.js} +137 -21
- package/dist/providers-beXyD9W9.js.map +1 -0
- package/dist/providers.d.ts +2 -2
- package/dist/providers.js +3 -3
- package/dist/restate.d.ts +1 -1
- package/dist/session/sqlite.d.ts +1 -1
- package/dist/{session-PUzXZlG6.js → session-BRIsmBSY.js} +5 -2
- package/dist/session-BRIsmBSY.js.map +1 -0
- package/dist/session.d.ts +2 -2
- package/dist/session.js +3 -3
- package/dist/skills.d.ts +2 -2
- package/dist/{tools-CxOfTt3R.js → tools-DE9pR_NG.js} +515 -116
- package/dist/tools-DE9pR_NG.js.map +1 -0
- package/dist/tools.d.ts +3 -3
- package/dist/tools.js +1 -1
- package/dist/{transcript-anchors-DDCHSDdX.d.ts → transcript-anchors-D0TR6djV.d.ts} +4 -4
- package/dist/transcript-anchors-D0TR6djV.d.ts.map +1 -0
- package/dist/tui.d.ts +2 -2
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +12 -8
- package/dist/tui.js.map +1 -1
- package/dist/{turn-operations-CxE8BBau.js → turn-operations-6Yls2HuG.js} +907 -42
- package/dist/turn-operations-6Yls2HuG.js.map +1 -0
- package/dist/types-oKPBdCmL.js.map +1 -1
- package/dist/types.d.ts +3 -3
- package/docs/ARCHITECTURE.md +101 -20
- package/docs/CHAT.md +27 -5
- package/docs/RESTATE.md +1 -1
- package/docs/SKILL.md +39 -3
- package/package.json +5 -2
- package/dist/agent-C9AKTU_V.d.ts.map +0 -1
- package/dist/index-6f4T7Gc0.d.ts.map +0 -1
- package/dist/mcp-0jRkIV0g.js.map +0 -1
- package/dist/messages-BfmXLDT4.js.map +0 -1
- package/dist/providers-C_ahnRBS.js.map +0 -1
- package/dist/session-PUzXZlG6.js.map +0 -1
- package/dist/tools-CxOfTt3R.js.map +0 -1
- package/dist/transcript-anchors-DDCHSDdX.d.ts.map +0 -1
- package/dist/turn-operations-CxE8BBau.js.map +0 -1
|
@@ -1,5 +1,212 @@
|
|
|
1
1
|
import { c as errorMessage, l as matchesContextExceeded } from "./errors-DdZXnyXE.js";
|
|
2
|
-
import { getModel } from "@
|
|
2
|
+
import { getModel } from "@earendil-works/pi-ai";
|
|
3
|
+
//#region src/system-prompt.ts
|
|
4
|
+
/**
|
|
5
|
+
* System-prompt boundary marker — splits a system prompt into a stable static
|
|
6
|
+
* prefix (cached) and a per-turn dynamic suffix (NOT cached).
|
|
7
|
+
*
|
|
8
|
+
* Why this exists: providers attach `cache_control` markers on the last block
|
|
9
|
+
* of the system prompt, so the cached prefix covers the entire system text.
|
|
10
|
+
* Any byte change anywhere — including a per-turn `<env>` rewrite — busts the
|
|
11
|
+
* cache for the doctrine that sits below. A literal marker in the system
|
|
12
|
+
* string lets providers split it into:
|
|
13
|
+
*
|
|
14
|
+
* ┌──────────────┐ cache_control: ephemeral
|
|
15
|
+
* │ STATIC half │ — doctrine, skills catalog, tool catalog,
|
|
16
|
+
* │ │ user instructions
|
|
17
|
+
* ├──────────────┤ ← SYSTEM_PROMPT_BOUNDARY
|
|
18
|
+
* │ DYNAMIC half │ — env, cwd, mtimes, anything per-turn
|
|
19
|
+
* └──────────────┘ (no cache_control)
|
|
20
|
+
*
|
|
21
|
+
* The static prefix rides the prompt cache across turns/sessions; the dynamic
|
|
22
|
+
* suffix re-bills per turn. Net effect: a cwd change between turns no longer
|
|
23
|
+
* invalidates 4 KB of doctrine.
|
|
24
|
+
*
|
|
25
|
+
* Wire contract:
|
|
26
|
+
*
|
|
27
|
+
* - `splitSystemPrompt(s)` is pure; missing marker ⇒ entire string is static
|
|
28
|
+
* (current behavior — no caller is forced to opt in).
|
|
29
|
+
* - `renderSystemForWire(s)` strips the marker so it never reaches the model;
|
|
30
|
+
* used by every provider before the bytes hit the wire, including the
|
|
31
|
+
* cache-disabled path on providers that DO support `cache_control`.
|
|
32
|
+
* - The marker uses underscores rather than XML/punctuation so it's
|
|
33
|
+
* unambiguous when scanning prompts manually and unlikely to collide with
|
|
34
|
+
* model-written content.
|
|
35
|
+
* - Providers handle the split internally (Anthropic emits a 2-block array;
|
|
36
|
+
* OpenAI-compat splits the leading `system` message into multi-part text).
|
|
37
|
+
* Callers always pass a single `string` — no API break.
|
|
38
|
+
*/
|
|
39
|
+
/**
|
|
40
|
+
* Literal marker inserted in a system prompt to separate cacheable doctrine
|
|
41
|
+
* from per-turn dynamic content. Providers split on this token.
|
|
42
|
+
*
|
|
43
|
+
* Underscored on both sides for visual distinctiveness — a stray instance in
|
|
44
|
+
* model-written prose is implausible. Don't change the value without shipping
|
|
45
|
+
* a migration; existing sessions carry the old marker in their cached
|
|
46
|
+
* prompts.
|
|
47
|
+
*/
|
|
48
|
+
const SYSTEM_PROMPT_BOUNDARY = "__ZIDANE_SYSTEM_PROMPT_BOUNDARY__";
|
|
49
|
+
/**
|
|
50
|
+
* Split a system prompt around the first {@link SYSTEM_PROMPT_BOUNDARY}.
|
|
51
|
+
*
|
|
52
|
+
* Splits on the FIRST occurrence — subsequent markers are folded into the
|
|
53
|
+
* dynamic half. This way callers can append additional `<env>` style blocks
|
|
54
|
+
* with extra markers without each one creating a new cache layer (Anthropic
|
|
55
|
+
* caps breakpoints; we use the budget elsewhere). The marker itself is
|
|
56
|
+
* stripped from both sides — providers attach `cache_control` directly to
|
|
57
|
+
* the static half's text content.
|
|
58
|
+
*
|
|
59
|
+
* A single blank line (`\n\n`) immediately adjacent to the marker on each
|
|
60
|
+
* side is trimmed — callers conventionally write
|
|
61
|
+
* `<doctrine>\n\n<MARKER>\n\n<env>` and expect the rendered wire bytes to
|
|
62
|
+
* read as one logical paragraph. Blank lines beyond that immediate pair
|
|
63
|
+
* (e.g. `\n\n\n<env>`) are preserved verbatim so callers composing their
|
|
64
|
+
* own spacing don't lose intentional gaps.
|
|
65
|
+
*
|
|
66
|
+
* Pure / no I/O / no allocation when the marker is absent (returns the input
|
|
67
|
+
* verbatim on the static side and the empty string on the dynamic side).
|
|
68
|
+
*/
|
|
69
|
+
function splitSystemPrompt(system) {
|
|
70
|
+
if (system.length === 0) return {
|
|
71
|
+
static: "",
|
|
72
|
+
dynamic: ""
|
|
73
|
+
};
|
|
74
|
+
const idx = system.indexOf(SYSTEM_PROMPT_BOUNDARY);
|
|
75
|
+
if (idx < 0) return {
|
|
76
|
+
static: system,
|
|
77
|
+
dynamic: ""
|
|
78
|
+
};
|
|
79
|
+
const staticPart = system.slice(0, idx);
|
|
80
|
+
const dynamicPart = system.slice(idx + 33);
|
|
81
|
+
return {
|
|
82
|
+
static: trimTrailingBlankLine(staticPart),
|
|
83
|
+
dynamic: trimLeadingBlankLine(dynamicPart)
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Compose a system prompt from a static prefix and an optional dynamic
|
|
88
|
+
* suffix. Inserts {@link SYSTEM_PROMPT_BOUNDARY} between them only when the
|
|
89
|
+
* dynamic side is non-empty — single-block prompts stay marker-free, so
|
|
90
|
+
* callers that never opt in pay zero overhead and providers fall back to the
|
|
91
|
+
* existing whole-string caching path.
|
|
92
|
+
*
|
|
93
|
+
* Spacing is `\n\n` on both sides of the marker so doctrine fragments,
|
|
94
|
+
* which conventionally separate sections with a blank line, read cleanly
|
|
95
|
+
* around the boundary.
|
|
96
|
+
*/
|
|
97
|
+
function joinSystemPrompt(staticPart, dynamicPart) {
|
|
98
|
+
if (dynamicPart.length === 0) return staticPart;
|
|
99
|
+
if (staticPart.length === 0) return `${SYSTEM_PROMPT_BOUNDARY}\n\n${dynamicPart}`;
|
|
100
|
+
return `${staticPart}\n\n${SYSTEM_PROMPT_BOUNDARY}\n\n${dynamicPart}`;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Append `extra` to the STATIC half of a system prompt, preserving any
|
|
104
|
+
* existing dynamic suffix.
|
|
105
|
+
*
|
|
106
|
+
* Used by the agent to fold in run-stable content (skills catalog, lazy tool
|
|
107
|
+
* catalog) without bumping it into the dynamic half — both catalogs are
|
|
108
|
+
* built once per run and remain byte-stable for the duration, so they
|
|
109
|
+
* belong in the cached prefix.
|
|
110
|
+
*
|
|
111
|
+
* Returns a new string; the input is not mutated. When `extra` is empty,
|
|
112
|
+
* returns the input verbatim.
|
|
113
|
+
*/
|
|
114
|
+
function appendStaticSection(system, extra) {
|
|
115
|
+
if (extra.length === 0) return system;
|
|
116
|
+
const { static: staticPart, dynamic } = splitSystemPrompt(system);
|
|
117
|
+
return joinSystemPrompt(staticPart.length === 0 ? extra : `${staticPart}\n\n${extra}`, dynamic);
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Append `extra` to the DYNAMIC half of a system prompt. Inserts the boundary
|
|
121
|
+
* marker if the input didn't already carry one.
|
|
122
|
+
*
|
|
123
|
+
* Used by hosts (typically the TUI) to inject per-turn state — current cwd,
|
|
124
|
+
* IDE selection, project root — without forcing every caller to know the
|
|
125
|
+
* marker format. The host's `system:transform` hook rewrites the dynamic
|
|
126
|
+
* half each turn; the static doctrine above stays byte-stable and rides the
|
|
127
|
+
* cache.
|
|
128
|
+
*
|
|
129
|
+
* Returns a new string; the input is not mutated. When `extra` is empty,
|
|
130
|
+
* returns the input verbatim.
|
|
131
|
+
*/
|
|
132
|
+
function appendDynamicSection(system, extra) {
|
|
133
|
+
if (extra.length === 0) return system;
|
|
134
|
+
const { static: staticPart, dynamic } = splitSystemPrompt(system);
|
|
135
|
+
return joinSystemPrompt(staticPart, dynamic.length === 0 ? extra : `${dynamic}\n\n${extra}`);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Replace the entire dynamic half of a system prompt with `next`. Used by
|
|
139
|
+
* the TUI's `<env>` rewriter where the entire dynamic section is regenerated
|
|
140
|
+
* each turn rather than appended to.
|
|
141
|
+
*
|
|
142
|
+
* When `next` is empty, drops the dynamic half (and the marker) entirely.
|
|
143
|
+
*/
|
|
144
|
+
function replaceDynamicSection(system, next) {
|
|
145
|
+
const { static: staticPart } = splitSystemPrompt(system);
|
|
146
|
+
return joinSystemPrompt(staticPart, next);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Strip the boundary marker so it never reaches the wire — collapses
|
|
150
|
+
* `<static>${BOUNDARY}<dynamic>` into `<static>\n\n<dynamic>` for providers
|
|
151
|
+
* that can't honor `cache_control` (vanilla OpenAI Chat Completions, Codex,
|
|
152
|
+
* Cerebras, ...) or for the cache-disabled path on any provider.
|
|
153
|
+
*
|
|
154
|
+
* Cache-aware providers re-derive the split from the original (un-rendered)
|
|
155
|
+
* system string via `splitSystemPrompt` — `renderSystemForWire` is the
|
|
156
|
+
* marker-free counterpart used to build the actual wire bytes.
|
|
157
|
+
*
|
|
158
|
+
* No-op when the input has no marker. Pure / no I/O.
|
|
159
|
+
*/
|
|
160
|
+
function renderSystemForWire(system) {
|
|
161
|
+
if (system.length === 0) return system;
|
|
162
|
+
const parts = splitSystemPrompt(system);
|
|
163
|
+
if (parts.dynamic.length === 0) return parts.static;
|
|
164
|
+
if (parts.static.length === 0) return parts.dynamic;
|
|
165
|
+
return `${parts.static}\n\n${parts.dynamic}`;
|
|
166
|
+
}
|
|
167
|
+
/** True when `system` contains the boundary marker. */
|
|
168
|
+
function hasSystemPromptBoundary(system) {
|
|
169
|
+
return system.includes(SYSTEM_PROMPT_BOUNDARY);
|
|
170
|
+
}
|
|
171
|
+
/** Strip a single trailing `\n\n` (and any leftover trailing whitespace within that pair). */
|
|
172
|
+
function trimTrailingBlankLine(s) {
|
|
173
|
+
let end = s.length;
|
|
174
|
+
let newlines = 0;
|
|
175
|
+
while (end > 0 && newlines < 2) {
|
|
176
|
+
const ch = s.charCodeAt(end - 1);
|
|
177
|
+
if (ch === 10) {
|
|
178
|
+
newlines += 1;
|
|
179
|
+
end -= 1;
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
if (ch === 32 || ch === 9) {
|
|
183
|
+
end -= 1;
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
break;
|
|
187
|
+
}
|
|
188
|
+
return newlines > 0 ? s.slice(0, end) : s;
|
|
189
|
+
}
|
|
190
|
+
/** Strip a single leading `\n\n` (and any leftover leading whitespace within that pair). */
|
|
191
|
+
function trimLeadingBlankLine(s) {
|
|
192
|
+
let start = 0;
|
|
193
|
+
let newlines = 0;
|
|
194
|
+
while (start < s.length && newlines < 2) {
|
|
195
|
+
const ch = s.charCodeAt(start);
|
|
196
|
+
if (ch === 10) {
|
|
197
|
+
newlines += 1;
|
|
198
|
+
start += 1;
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
if (ch === 32 || ch === 9) {
|
|
202
|
+
start += 1;
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
break;
|
|
206
|
+
}
|
|
207
|
+
return newlines > 0 ? s.slice(start) : s;
|
|
208
|
+
}
|
|
209
|
+
//#endregion
|
|
3
210
|
//#region src/providers/cost.ts
|
|
4
211
|
/**
|
|
5
212
|
* Fill in `usage.cost` from pi-ai's bundled price registry when the
|
|
@@ -12,7 +219,7 @@ import { getModel } from "@mariozechner/pi-ai";
|
|
|
12
219
|
* than fabricating a $0.
|
|
13
220
|
*
|
|
14
221
|
* The number is an estimate: token counts come from the API, rates from
|
|
15
|
-
* the locally-bundled registry that refreshes with `@
|
|
222
|
+
* the locally-bundled registry that refreshes with `@earendil-works/pi-ai`
|
|
16
223
|
* version bumps. If a provider changes prices between bumps the figure
|
|
17
224
|
* will drift until the dep updates.
|
|
18
225
|
*/
|
|
@@ -545,7 +752,7 @@ function summarizeToolResultOutput(output) {
|
|
|
545
752
|
function toOAIMessages(system, messages, options = {}) {
|
|
546
753
|
const out = [{
|
|
547
754
|
role: "system",
|
|
548
|
-
content: system
|
|
755
|
+
content: renderSystemForWire(system)
|
|
549
756
|
}];
|
|
550
757
|
const nativeImageInTool = options.imageInToolResult === true;
|
|
551
758
|
const reasoningEnabled = options.supportsReasoning === true;
|
|
@@ -682,15 +889,62 @@ const EPHEMERAL = { type: "ephemeral" };
|
|
|
682
889
|
* - Assistant messages with no text (tool-call-only) — attaching a cache marker to a
|
|
683
890
|
* `tool_calls` block has no defined semantics, so we skip and let the prior
|
|
684
891
|
* system/tools breakpoints carry caching.
|
|
892
|
+
*
|
|
893
|
+
* System-prompt boundary handling: when `originalSystem` (the un-rendered
|
|
894
|
+
* system text passed to {@link toOAIMessages}) contains
|
|
895
|
+
* {@link SYSTEM_PROMPT_BOUNDARY}, the leading system message is rewritten as
|
|
896
|
+
* a two-part array — `cache_control` lands on the static prefix only, so
|
|
897
|
+
* per-turn churn in the dynamic suffix doesn't invalidate the cached
|
|
898
|
+
* doctrine above. `originalSystem` defaults to `undefined` for back-compat;
|
|
899
|
+
* omit it (or pass a marker-free string) for the single-block historic
|
|
900
|
+
* behavior.
|
|
685
901
|
*/
|
|
686
|
-
function applyOAICacheBreakpoints(messages) {
|
|
902
|
+
function applyOAICacheBreakpoints(messages, originalSystem) {
|
|
687
903
|
if (messages.length === 0) return;
|
|
688
904
|
const first = messages[0];
|
|
689
|
-
if (first.role === "system")
|
|
905
|
+
if (first.role === "system") markSystemMessage(first, originalSystem);
|
|
690
906
|
const lastIdx = messages.length - 1;
|
|
691
907
|
if (lastIdx > 0) markLastContentPart(messages[lastIdx]);
|
|
692
908
|
}
|
|
693
909
|
/**
|
|
910
|
+
* Place the cache marker on the static prefix of the system message. When
|
|
911
|
+
* `originalSystem` carried {@link SYSTEM_PROMPT_BOUNDARY}, the message becomes
|
|
912
|
+
* a two-part array — static (cached) then dynamic (uncached). Otherwise falls
|
|
913
|
+
* through to {@link markLastContentPart} for the historic single-block
|
|
914
|
+
* treatment.
|
|
915
|
+
*
|
|
916
|
+
* String-only branch — system messages produced by {@link toOAIMessages} are
|
|
917
|
+
* always plain strings (`{ role: 'system', content: <rendered> }`). Hosts
|
|
918
|
+
* that supply pre-built multi-part system messages bypass this branch and
|
|
919
|
+
* get the generic last-block treatment.
|
|
920
|
+
*/
|
|
921
|
+
function markSystemMessage(msg, originalSystem) {
|
|
922
|
+
if (typeof msg.content !== "string" || msg.content.length === 0) {
|
|
923
|
+
markLastContentPart(msg);
|
|
924
|
+
return;
|
|
925
|
+
}
|
|
926
|
+
const parts = splitSystemPrompt(originalSystem && originalSystem.length > 0 ? originalSystem : msg.content);
|
|
927
|
+
if (parts.dynamic.length === 0) {
|
|
928
|
+
msg.content = [{
|
|
929
|
+
type: "text",
|
|
930
|
+
text: parts.static,
|
|
931
|
+
cache_control: EPHEMERAL
|
|
932
|
+
}];
|
|
933
|
+
return;
|
|
934
|
+
}
|
|
935
|
+
const next = [];
|
|
936
|
+
if (parts.static.length > 0) next.push({
|
|
937
|
+
type: "text",
|
|
938
|
+
text: parts.static,
|
|
939
|
+
cache_control: EPHEMERAL
|
|
940
|
+
});
|
|
941
|
+
next.push({
|
|
942
|
+
type: "text",
|
|
943
|
+
text: parts.dynamic
|
|
944
|
+
});
|
|
945
|
+
msg.content = next;
|
|
946
|
+
}
|
|
947
|
+
/**
|
|
694
948
|
* Mark the last content part of an OAI message with `cache_control`. Normalizes
|
|
695
949
|
* string content into a `[{ type: 'text', text, cache_control }]` array so the
|
|
696
950
|
* marker has a block to attach to.
|
|
@@ -948,7 +1202,7 @@ function openaiCompat(params) {
|
|
|
948
1202
|
model: modelId
|
|
949
1203
|
});
|
|
950
1204
|
const shouldCache = cacheBreakpointsEnabled && options.cache !== false;
|
|
951
|
-
if (shouldCache) applyOAICacheBreakpoints(messages);
|
|
1205
|
+
if (shouldCache) applyOAICacheBreakpoints(messages, options.system);
|
|
952
1206
|
const maxTokens = options.thinkingBudget ? options.thinkingBudget + options.maxTokens : options.maxTokens;
|
|
953
1207
|
const body = {
|
|
954
1208
|
...params.extraBodyParams ?? {},
|
|
@@ -1737,6 +1991,47 @@ function ensureEndsWithUserMessage(messages, provider, directive = DEFAULT_USER_
|
|
|
1737
1991
|
if (messages[messages.length - 1].role === "user") return messages;
|
|
1738
1992
|
return [...messages, provider.userMessage(directive)];
|
|
1739
1993
|
}
|
|
1994
|
+
/**
|
|
1995
|
+
* Build a wire-ready `SessionMessage[]` from raw persisted `SessionTurn[]`.
|
|
1996
|
+
*
|
|
1997
|
+
* **The canonical "I want to send these to a provider" projection.** Use
|
|
1998
|
+
* this — not raw `session.turns` / `store.getTurns()` — when constructing a
|
|
1999
|
+
* provider request outside `agent.run()`. The agent's own wire pipeline
|
|
2000
|
+
* (`executeTurn` in `src/loop.ts`) applies the same repair just-in-time;
|
|
2001
|
+
* downstream consumers that bypass the loop hit `tool_result must be
|
|
2002
|
+
* preceded by a tool_call` 400s precisely because they shipped raw turns.
|
|
2003
|
+
*
|
|
2004
|
+
* Pipeline:
|
|
2005
|
+
* 1. Filter `system`-role turns (the wire only carries user/assistant).
|
|
2006
|
+
* 2. {@link ensureToolResultPairing} — repairs all six orphan / dup
|
|
2007
|
+
* corruption modes by inserting synthetic placeholders rather than
|
|
2008
|
+
* dropping (preserves the model's tool_use shape).
|
|
2009
|
+
* 3. {@link ensureEndsWithUserMessage} when `options.provider` is set —
|
|
2010
|
+
* guards against assistant-tail prefill rejection (opus 4.7, o-series).
|
|
2011
|
+
*
|
|
2012
|
+
* Pure + idempotent. Does not mutate the input turns. Re-running on the
|
|
2013
|
+
* output is a no-op.
|
|
2014
|
+
*
|
|
2015
|
+
* **Do not feed the result back into `session.setTurns` / `appendTurns`.**
|
|
2016
|
+
* The repair can insert `SYNTHETIC_TOOL_RESULT_PLACEHOLDER` / `[Orphaned
|
|
2017
|
+
* tool result removed …]` markers; round-tripping those into persisted
|
|
2018
|
+
* state contaminates the session's reasoning history and defeats the
|
|
2019
|
+
* "don't rewrite the past" invariant the wire-only repair was designed
|
|
2020
|
+
* around.
|
|
2021
|
+
*/
|
|
2022
|
+
function toWireMessages(turns, options = {}) {
|
|
2023
|
+
const messages = [];
|
|
2024
|
+
for (const t of turns) {
|
|
2025
|
+
if (t.role === "system") continue;
|
|
2026
|
+
messages.push({
|
|
2027
|
+
role: t.role,
|
|
2028
|
+
content: t.content
|
|
2029
|
+
});
|
|
2030
|
+
}
|
|
2031
|
+
const paired = ensureToolResultPairing(messages, options.onRepair ? { onRepair: options.onRepair } : {});
|
|
2032
|
+
if (!options.provider) return paired;
|
|
2033
|
+
return ensureEndsWithUserMessage(paired, options.provider, options.userTailDirective);
|
|
2034
|
+
}
|
|
1740
2035
|
function autoDetectAndConvert(msg) {
|
|
1741
2036
|
const c = msg.content;
|
|
1742
2037
|
if (c && typeof c === "object" && !Array.isArray(c)) {
|
|
@@ -1756,6 +2051,6 @@ function autoDetectAndConvert(msg) {
|
|
|
1756
2051
|
return fromAnthropic(msg);
|
|
1757
2052
|
}
|
|
1758
2053
|
//#endregion
|
|
1759
|
-
export { fillEstimatedCost as S,
|
|
2054
|
+
export { replaceDynamicSection as A, fillEstimatedCost as C, hasSystemPromptBoundary as D, appendStaticSection as E, joinSystemPrompt as O, sanitizeToolSpecs as S, appendDynamicSection as T, mapOAIFinishReason as _, detectTurnInterruption as a, userMessage as b, filterUnresolvedToolUses as c, toAnthropic as d, toOpenAI as f, classifyOpenAICompatError as g, assistantMessage as h, autoDetectAndConvert as i, splitSystemPrompt as j, renderSystemForWire as k, fromAnthropic as l, OpenAICompatHttpError as m, SYNTHETIC_TOOL_RESULT_PLACEHOLDER as n, ensureEndsWithUserMessage as o, toWireMessages as p, TOOL_USE_INTERRUPTED_MARKER as r, ensureToolResultPairing as s, ORPHANED_TOOL_RESULT_MARKER as t, fromOpenAI as u, openaiCompat as v, SYSTEM_PROMPT_BOUNDARY as w, sanitizeToolSchema as x, toolResultsMessage as y };
|
|
1760
2055
|
|
|
1761
|
-
//# sourceMappingURL=messages-
|
|
2056
|
+
//# sourceMappingURL=messages-Dym8S_YH.js.map
|