dsh-lcx-codex 0.4.3-pre.2 → 0.4.3-pre.4

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.
@@ -0,0 +1,319 @@
1
+ import { createHash } from "node:crypto";
2
+ export const GROK_NATIVE_SERVER_TOOL_TYPES = new Set([
3
+ "web_search_call",
4
+ "x_search_call",
5
+ ]);
6
+ const GROK_EXCLUDED_SEARCH_FUNCTIONS = new Set([
7
+ "web_search",
8
+ "websearch_gpt_advanced",
9
+ "websearch_alpha",
10
+ ]);
11
+ const GROK_NATIVE_VISIBLE_ITEM_TYPES = new Set([
12
+ "message",
13
+ "reasoning",
14
+ "function_call",
15
+ "custom_tool_call",
16
+ ]);
17
+ const GROK_NATIVE_REPLAY_MAX_ITEMS = 256;
18
+ const GROK_NATIVE_REPLAY_MAX_CHARS = 8 * 1024 * 1024;
19
+ function isRecord(value) {
20
+ return value !== null && typeof value === "object" && !Array.isArray(value);
21
+ }
22
+ function canonicalHeaders(headers) {
23
+ return Object.entries(headers ?? {})
24
+ .map(([name, value]) => [name.toLowerCase(), value])
25
+ .sort(([left], [right]) => left.localeCompare(right));
26
+ }
27
+ export function grokNativeReplayRouteFingerprint(route) {
28
+ return createHash("sha256")
29
+ .update(JSON.stringify({
30
+ provider: route.provider,
31
+ model: route.model,
32
+ sessionId: route.sessionId,
33
+ baseURL: route.baseURL.trim().replace(/\/+$/u, ""),
34
+ apiKeyEnv: route.apiKeyEnv,
35
+ headers: canonicalHeaders(route.headers),
36
+ }), "utf8")
37
+ .digest("hex");
38
+ }
39
+ export function grokNativeSearchEnabled(state) {
40
+ return state.web || state.x;
41
+ }
42
+ export function grokVisibleFunctionTools(tools, state = { web: false, x: false }) {
43
+ return tools?.filter((tool) => !GROK_EXCLUDED_SEARCH_FUNCTIONS.has(tool.name) &&
44
+ !(state.x && tool.name === "x_search"));
45
+ }
46
+ export function grokWireTools(tools, state) {
47
+ const nativeTypes = new Set(["web_search", "x_search"]);
48
+ const result = (tools ?? [])
49
+ .filter((tool) => {
50
+ if (!isRecord(tool))
51
+ return true;
52
+ if (nativeTypes.has(String(tool.type ?? "")))
53
+ return false;
54
+ return !(state.x && tool.type === "function" && tool.name === "x_search");
55
+ })
56
+ .map((tool) => structuredClone(tool))
57
+ .filter(isRecord);
58
+ if (state.web)
59
+ result.push({ type: "web_search" });
60
+ if (state.x)
61
+ result.push({ type: "x_search" });
62
+ return result;
63
+ }
64
+ function validVisibleItem(item) {
65
+ if (item.type === "message")
66
+ return typeof item.id === "string" && item.role === "assistant" &&
67
+ Array.isArray(item.content);
68
+ if (item.type === "reasoning")
69
+ return typeof item.id === "string" && Array.isArray(item.summary);
70
+ if (item.type === "function_call")
71
+ return typeof item.id === "string" && typeof item.call_id === "string" &&
72
+ typeof item.name === "string" && typeof item.arguments === "string";
73
+ if (item.type === "custom_tool_call")
74
+ return typeof item.id === "string" && typeof item.call_id === "string" &&
75
+ typeof item.name === "string" && typeof item.input === "string";
76
+ return false;
77
+ }
78
+ function textSha256(text) {
79
+ return createHash("sha256").update(text, "utf8").digest("hex");
80
+ }
81
+ function lcxCitationAddition(item) {
82
+ if (item.type !== "message" ||
83
+ typeof item.id !== "string" ||
84
+ !item.id.startsWith("msg_lcx_sources_"))
85
+ return undefined;
86
+ const text = itemText(item);
87
+ return text.startsWith("\n\nSources:\n")
88
+ ? { kind: "citation-sources", textSha256: textSha256(text) }
89
+ : undefined;
90
+ }
91
+ function validVisibleAdditions(value) {
92
+ if (!Array.isArray(value) || value.length > GROK_NATIVE_REPLAY_MAX_ITEMS)
93
+ return undefined;
94
+ const additions = [];
95
+ for (const candidate of value) {
96
+ if (!isRecord(candidate) ||
97
+ candidate.kind !== "citation-sources" ||
98
+ typeof candidate.textSha256 !== "string" ||
99
+ !/^[0-9a-f]{64}$/u.test(candidate.textSha256))
100
+ return undefined;
101
+ additions.push({ kind: "citation-sources", textSha256: candidate.textSha256 });
102
+ }
103
+ return additions;
104
+ }
105
+ function readGrokNativeReplayEnvelope(value, route) {
106
+ if (!isRecord(value) ||
107
+ value.kind !== "xai-responses-native-search" ||
108
+ (value.version !== 1 && value.version !== 2))
109
+ return undefined;
110
+ if (value.provider !== route.provider ||
111
+ value.model !== route.model ||
112
+ value.sourceSessionId !== route.sessionId ||
113
+ value.routeAuthorityFingerprint !== grokNativeReplayRouteFingerprint(route) ||
114
+ !Array.isArray(value.output) ||
115
+ value.output.length === 0 ||
116
+ value.output.length > GROK_NATIVE_REPLAY_MAX_ITEMS)
117
+ return undefined;
118
+ let encoded;
119
+ try {
120
+ encoded = JSON.stringify(value.output);
121
+ }
122
+ catch {
123
+ return undefined;
124
+ }
125
+ if (encoded === undefined || encoded.length > GROK_NATIVE_REPLAY_MAX_CHARS)
126
+ return undefined;
127
+ const output = [];
128
+ const itemKinds = new Map();
129
+ const callIds = new Set();
130
+ const migratedAdditions = [];
131
+ for (const candidate of value.output) {
132
+ if (!isRecord(candidate) || typeof candidate.type !== "string")
133
+ return undefined;
134
+ const item = candidate;
135
+ const legacyAddition = value.version === 1 ? lcxCitationAddition(item) : undefined;
136
+ if (legacyAddition) {
137
+ migratedAdditions.push(legacyAddition);
138
+ continue;
139
+ }
140
+ if (GROK_NATIVE_SERVER_TOOL_TYPES.has(item.type)) {
141
+ if (typeof item.id !== "string" || item.id.length === 0)
142
+ return undefined;
143
+ }
144
+ else if (!GROK_NATIVE_VISIBLE_ITEM_TYPES.has(item.type) || !validVisibleItem(item)) {
145
+ return undefined;
146
+ }
147
+ if (typeof item.id === "string") {
148
+ const previousKind = itemKinds.get(item.id);
149
+ // Compatible Grok gateways can repeat a reasoning ID around server tools.
150
+ // These are ordered opaque items, never executable client calls.
151
+ if (previousKind !== undefined &&
152
+ !(previousKind === "reasoning" && item.type === "reasoning"))
153
+ return undefined;
154
+ itemKinds.set(item.id, item.type);
155
+ }
156
+ if (item.type === "function_call" || item.type === "custom_tool_call") {
157
+ const callId = String(item.call_id);
158
+ if (callIds.has(callId))
159
+ return undefined;
160
+ callIds.add(callId);
161
+ }
162
+ output.push(structuredClone(item));
163
+ }
164
+ if (output.length === 0)
165
+ return undefined;
166
+ const visibleAdditions = value.version === 1
167
+ ? migratedAdditions
168
+ : validVisibleAdditions(value.visibleAdditions);
169
+ if (!visibleAdditions)
170
+ return undefined;
171
+ return {
172
+ kind: "xai-responses-native-search",
173
+ version: 2,
174
+ provider: route.provider,
175
+ model: route.model,
176
+ sourceSessionId: route.sessionId,
177
+ routeAuthorityFingerprint: grokNativeReplayRouteFingerprint(route),
178
+ output,
179
+ visibleAdditions,
180
+ };
181
+ }
182
+ export function createGrokNativeReplayEnvelope(output, route, visibleAdditions = []) {
183
+ if (!route || !Array.isArray(output))
184
+ return undefined;
185
+ const additions = visibleAdditions.map((candidate) => isRecord(candidate) && typeof candidate.type === "string"
186
+ ? lcxCitationAddition(candidate)
187
+ : undefined);
188
+ if (additions.some((addition) => addition === undefined))
189
+ return undefined;
190
+ return readGrokNativeReplayEnvelope({
191
+ kind: "xai-responses-native-search",
192
+ version: 2,
193
+ provider: route.provider,
194
+ model: route.model,
195
+ sourceSessionId: route.sessionId,
196
+ routeAuthorityFingerprint: grokNativeReplayRouteFingerprint(route),
197
+ output,
198
+ visibleAdditions: additions,
199
+ }, route);
200
+ }
201
+ function itemText(item) {
202
+ if (item.type === "message")
203
+ return (Array.isArray(item.content) ? item.content : [])
204
+ .map((part) => isRecord(part) ? String(part.text ?? part.refusal ?? "") : "")
205
+ .join("");
206
+ if (item.type === "reasoning") {
207
+ const parts = Array.isArray(item.summary) && item.summary.length > 0
208
+ ? item.summary
209
+ : Array.isArray(item.content) ? item.content : [];
210
+ return parts.map((part) => isRecord(part) ? String(part.text ?? "") : "").join("\n\n");
211
+ }
212
+ return "";
213
+ }
214
+ function visibleItemMatchesBlock(item, block) {
215
+ if (item.type === "message")
216
+ return block.type === "text" && block.text === itemText(item);
217
+ if (item.type === "reasoning")
218
+ return block.type === "reasoning" && block.text === itemText(item);
219
+ if (item.type === "function_call")
220
+ return block.type === "tool-call" && block.id === `${String(item.call_id)}|${String(item.id)}` &&
221
+ block.name === item.name && block.arguments === item.arguments;
222
+ if (item.type === "custom_tool_call")
223
+ return block.type === "tool-call" && block.id === `${String(item.call_id)}|${String(item.id)}` &&
224
+ block.name === item.name;
225
+ return false;
226
+ }
227
+ function visibleItemMatchesInput(item, candidate) {
228
+ if (!isRecord(candidate) || candidate.type !== item.type)
229
+ return false;
230
+ if (candidate.id !== item.id)
231
+ return false;
232
+ if (item.type === "function_call" || item.type === "custom_tool_call")
233
+ return candidate.call_id === item.call_id;
234
+ return true;
235
+ }
236
+ function additionMatchesBlock(addition, candidate) {
237
+ return isRecord(candidate) && candidate.type === "text" &&
238
+ typeof candidate.text === "string" &&
239
+ candidate.text.startsWith("\n\nSources:\n") &&
240
+ textSha256(candidate.text) === addition.textSha256;
241
+ }
242
+ function additionMatchesInput(addition, candidate) {
243
+ if (!isRecord(candidate) || candidate.type !== "message")
244
+ return false;
245
+ if (typeof candidate.id !== "string" || !candidate.id.startsWith("msg_lcx_sources_"))
246
+ return false;
247
+ return textSha256(itemText(candidate)) === addition.textSha256;
248
+ }
249
+ function replayForMessage(message, route) {
250
+ if (message.role !== "assistant" || message.source.kind !== "model")
251
+ return undefined;
252
+ if (message.source.provider !== route.provider || message.source.model !== route.model)
253
+ return undefined;
254
+ const replayState = message.source.replayState;
255
+ if (!isRecord(replayState))
256
+ return undefined;
257
+ const envelope = readGrokNativeReplayEnvelope(replayState.grokNative, route);
258
+ if (!envelope)
259
+ return undefined;
260
+ const visible = envelope.output.filter((item) => !GROK_NATIVE_SERVER_TOOL_TYPES.has(item.type));
261
+ if (visible.length === 0)
262
+ return undefined;
263
+ const reasoningCounts = new Map();
264
+ for (const item of visible)
265
+ if (item.type === "reasoning")
266
+ reasoningCounts.set(String(item.id), (reasoningCounts.get(String(item.id)) ?? 0) + 1);
267
+ const anchors = [];
268
+ let blockIndex = 0;
269
+ for (const item of visible) {
270
+ const block = message.content[blockIndex];
271
+ if (isRecord(block) && visibleItemMatchesBlock(item, block)) {
272
+ anchors.push(item);
273
+ blockIndex += 1;
274
+ }
275
+ else if (!(item.type === "reasoning" &&
276
+ (!itemText(item).trim() || (reasoningCounts.get(String(item.id)) ?? 0) > 1))) {
277
+ return undefined;
278
+ }
279
+ }
280
+ // Empty Grok reasoning has no UI block; older histories can still contain it.
281
+ // Pi can coalesce repeated reasoning IDs in terminal-only gateway responses.
282
+ // Match every provider-visible DSH block and only the hashed LCX additions.
283
+ if (anchors.length === 0)
284
+ return undefined;
285
+ for (const addition of envelope.visibleAdditions) {
286
+ if (!additionMatchesBlock(addition, message.content[blockIndex]))
287
+ return undefined;
288
+ blockIndex += 1;
289
+ }
290
+ if (blockIndex !== message.content.length)
291
+ return undefined;
292
+ return { envelope, visible: anchors, additions: envelope.visibleAdditions };
293
+ }
294
+ export function restoreGrokNativeReplay(input, messages, route) {
295
+ const restored = structuredClone(input);
296
+ if (!route)
297
+ return restored;
298
+ let cursor = 0;
299
+ for (const message of messages) {
300
+ const replay = replayForMessage(message, route);
301
+ if (!replay)
302
+ continue;
303
+ const { envelope, visible, additions } = replay;
304
+ const replacedLength = visible.length + additions.length;
305
+ let start = -1;
306
+ for (let index = cursor; index <= restored.length - replacedLength; index += 1) {
307
+ if (visible.every((item, offset) => visibleItemMatchesInput(item, restored[index + offset])) &&
308
+ additions.every((addition, offset) => additionMatchesInput(addition, restored[index + visible.length + offset]))) {
309
+ start = index;
310
+ break;
311
+ }
312
+ }
313
+ if (start < 0)
314
+ continue;
315
+ restored.splice(start, replacedLength, ...structuredClone(envelope.output));
316
+ cursor = start + envelope.output.length;
317
+ }
318
+ return restored;
319
+ }