dsh-lcx-codex 0.4.3-pre.3 → 0.4.3
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 +68 -99
- package/THIRD_PARTY_NOTICES.md +64 -0
- package/lib/auxiliary-usage.js +63 -0
- package/lib/client.js +1363 -295
- package/lib/dsh-compat.js +80 -18
- package/lib/dsh-responses.js +75 -8
- package/lib/grok-native-search.js +153 -79
- package/lib/index.js +159 -101
- package/lib/invocation-policy-scope.js +261 -0
- package/lib/json-store.js +11 -4
- package/lib/pi-responses-runtime.js +1571 -0
- package/lib/responses-request.js +1 -1
- package/lib/responses-stream.js +163 -92
- package/lib/route.js +17 -3
- package/lib/search-accounting.js +86 -0
- package/lib/search-usage.js +86 -0
- package/lib/transport.js +38 -10
- package/lib/types/client/index.d.ts +12 -0
- package/lib/types/client/search-media.d.ts +16 -0
- package/lib/web-run-output.js +22 -0
- package/lib/web-search-alpha.js +230 -28
- package/lib/web-search-capability.js +26 -1
- package/lib/web-search-hosted.js +119 -9
- package/lib/web-search-ref-store.js +88 -7
- package/package.json +50 -26
- package/lib/types/compact-v2.d.ts +0 -104
- package/lib/types/dsh-compat.d.ts +0 -78
- package/lib/types/dsh-responses.d.ts +0 -82
- package/lib/types/grok-native-search.d.ts +0 -39
- package/lib/types/json-store.d.ts +0 -10
- package/lib/types/native-checkpoint.d.ts +0 -213
- package/lib/types/responses-request.d.ts +0 -59
- package/lib/types/responses-stream.d.ts +0 -64
- package/lib/types/route.d.ts +0 -153
- package/lib/types/service-mutex.d.ts +0 -14
- package/lib/types/token-budget.d.ts +0 -50
- package/lib/types/transport.d.ts +0 -21
- package/lib/types/web-run-output.d.ts +0 -29
- package/lib/types/web-search-alpha.d.ts +0 -286
- package/lib/types/web-search-capability.d.ts +0 -26
- package/lib/types/web-search-hosted.d.ts +0 -246
- package/lib/types/web-search-ref-store.d.ts +0 -22
package/lib/web-search-hosted.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { outputDomains, outputLineRange, parseWebRunOutput } from "./web-run-output.js";
|
|
2
2
|
export const HOSTED_SEARCH_PARAMETERS = { type: "object", properties: { query: { type: "string", description: "Advanced Responses Hosted Web Search query. Use DSH web_search for ordinary searches." }, searchContextSize: { type: "string", enum: ["low", "medium", "high"] }, allowedDomains: { type: "array", items: { type: "string" } }, blockedDomains: { type: "array", items: { type: "string" } }, userLocation: { type: "object", properties: { country: { type: "string" }, city: { type: "string" }, region: { type: "string" }, timezone: { type: "string" } }, additionalProperties: false }, externalWebAccess: { type: "boolean" }, returnTokenBudget: { type: "string", enum: ["default", "unlimited"] }, searchContentTypes: { type: "array", items: { type: "string", enum: ["text", "image"] } }, imageSettings: { type: "object", properties: { maxResults: { type: "integer" }, caption: { type: "boolean" } }, additionalProperties: false } }, required: ["query"], additionalProperties: false };
|
|
3
|
-
export const HOSTED_SEARCH_OUTPUT = { type: "object", properties: { mode: { type: "string", enum: ["hosted"] }, action: { type: "string" }, emulation: { type: "string", enum: ["native"] }, content: { type: "string" }, sources: { type: "array", items: { type: "object" } }, citations: { type: "array", items: { type: "object" } }, images: { type: "array", items: { type: "object" } }, warnings: { type: "array", items: { type: "string" } }, outputBlocks: { type: "array", items: { type: "object" } }, domains: { type: "array", items: { type: "string" } }, lineRange: { type: "object" }, requestId: { type: "string" }, responseId: { type: "string" }, retrievedAt: { type: "string" }, truncated: { type: "boolean" } }, required: ["mode", "action", "emulation", "content", "sources", "citations", "images", "warnings", "requestId", "retrievedAt", "truncated"], additionalProperties: false };
|
|
3
|
+
export const HOSTED_SEARCH_OUTPUT = { type: "object", properties: { mode: { type: "string", enum: ["hosted"] }, action: { type: "string" }, emulation: { type: "string", enum: ["native"] }, content: { type: "string" }, sources: { type: "array", items: { type: "object" } }, citations: { type: "array", items: { type: "object" } }, images: { type: "array", items: { type: "object" } }, warnings: { type: "array", items: { type: "string" } }, outputBlocks: { type: "array", items: { type: "object" } }, domains: { type: "array", items: { type: "string" } }, lineRange: { type: "object" }, requestId: { type: "string" }, responseId: { type: "string" }, retrievedAt: { type: "string" }, truncated: { type: "boolean" }, usage: { type: "object", properties: { inputTokens: { type: "number" }, outputTokens: { type: "number" }, totalTokens: { type: "number" }, cachedInputTokens: { type: "number" }, actionCount: { type: "number" }, serverWebSearchCalls: { type: "number" } }, additionalProperties: false } }, required: ["mode", "action", "emulation", "content", "sources", "citations", "images", "warnings", "requestId", "retrievedAt", "truncated"], additionalProperties: false };
|
|
4
4
|
function failure(message, code = "WEB_INVALID_REQUEST") { return Object.assign(new Error(message), { code }); }
|
|
5
5
|
function isRecord(value) { return value !== null && typeof value === "object" && !Array.isArray(value); }
|
|
6
6
|
function isStringArray(value) { return Array.isArray(value) && value.every((item) => typeof item === "string"); }
|
|
@@ -182,6 +182,59 @@ function uniqueByUrl(values) { const result = []; const seen = new Set(); for (c
|
|
|
182
182
|
seen.add(key);
|
|
183
183
|
result.push(value);
|
|
184
184
|
} return result; }
|
|
185
|
+
function nonNegativeInt(value) {
|
|
186
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : undefined;
|
|
187
|
+
}
|
|
188
|
+
function hostedUsageFrom(response, actionCount) {
|
|
189
|
+
const usage = isRecord(response) && isRecord(response.usage) ? response.usage : undefined;
|
|
190
|
+
const inputDetails = usage && isRecord(usage.input_tokens_details)
|
|
191
|
+
? usage.input_tokens_details
|
|
192
|
+
: usage && isRecord(usage.prompt_tokens_details)
|
|
193
|
+
? usage.prompt_tokens_details
|
|
194
|
+
: undefined;
|
|
195
|
+
const serverDetails = usage && isRecord(usage.server_side_tool_usage_details)
|
|
196
|
+
? usage.server_side_tool_usage_details
|
|
197
|
+
: undefined;
|
|
198
|
+
const result = {};
|
|
199
|
+
const inputTokens = usage ? nonNegativeInt(usage.input_tokens ?? usage.prompt_tokens) : undefined;
|
|
200
|
+
const outputTokens = usage ? nonNegativeInt(usage.output_tokens ?? usage.completion_tokens) : undefined;
|
|
201
|
+
const totalTokens = usage ? nonNegativeInt(usage.total_tokens) : undefined;
|
|
202
|
+
const cachedInputTokens = inputDetails ? nonNegativeInt(inputDetails.cached_tokens) : undefined;
|
|
203
|
+
const serverWebSearchCalls = serverDetails ? nonNegativeInt(serverDetails.web_search_calls) : undefined;
|
|
204
|
+
if (inputTokens !== undefined)
|
|
205
|
+
result.inputTokens = inputTokens;
|
|
206
|
+
if (outputTokens !== undefined)
|
|
207
|
+
result.outputTokens = outputTokens;
|
|
208
|
+
if (totalTokens !== undefined)
|
|
209
|
+
result.totalTokens = totalTokens;
|
|
210
|
+
// cachedInputTokens is a subset of inputTokens (cache hits), not an extra addend.
|
|
211
|
+
if (cachedInputTokens !== undefined)
|
|
212
|
+
result.cachedInputTokens = cachedInputTokens;
|
|
213
|
+
if (actionCount > 0)
|
|
214
|
+
result.actionCount = actionCount;
|
|
215
|
+
if (serverWebSearchCalls !== undefined)
|
|
216
|
+
result.serverWebSearchCalls = serverWebSearchCalls;
|
|
217
|
+
return Object.keys(result).length ? result : undefined;
|
|
218
|
+
}
|
|
219
|
+
function sourceLine(source) {
|
|
220
|
+
return `- [${String(source.title ?? source.url ?? "")}](${String(source.url ?? "")})${source.snippet ? ` — ${String(source.snippet)}` : ""}`;
|
|
221
|
+
}
|
|
222
|
+
function usageLine(usage) {
|
|
223
|
+
const parts = [];
|
|
224
|
+
if (usage.inputTokens !== undefined)
|
|
225
|
+
parts.push(`input=${String(usage.inputTokens)}`);
|
|
226
|
+
if (usage.outputTokens !== undefined)
|
|
227
|
+
parts.push(`output=${String(usage.outputTokens)}`);
|
|
228
|
+
if (usage.totalTokens !== undefined)
|
|
229
|
+
parts.push(`total=${String(usage.totalTokens)}`);
|
|
230
|
+
if (usage.cachedInputTokens !== undefined)
|
|
231
|
+
parts.push(`cachedInput=${String(usage.cachedInputTokens)}`);
|
|
232
|
+
if (usage.actionCount !== undefined)
|
|
233
|
+
parts.push(`actionCount=${String(usage.actionCount)}`);
|
|
234
|
+
if (usage.serverWebSearchCalls !== undefined)
|
|
235
|
+
parts.push(`serverWebSearchCalls=${String(usage.serverWebSearchCalls)}`);
|
|
236
|
+
return parts.length ? `用量:${parts.join(" ")}` : "";
|
|
237
|
+
}
|
|
185
238
|
export function parseHostedSearchResponse(response, requestId, maxResults = 8, retrievedAt = new Date().toISOString()) {
|
|
186
239
|
if (!isRecord(response))
|
|
187
240
|
throw failure("Hosted Web Search returned an invalid response", "WEB_RESPONSE_INCOMPLETE");
|
|
@@ -196,16 +249,73 @@ export function parseHostedSearchResponse(response, requestId, maxResults = 8, r
|
|
|
196
249
|
const artifacts = responseArtifacts(response);
|
|
197
250
|
if (!artifacts.actions.length)
|
|
198
251
|
throw failure("Hosted Web Search completed without web_search", "WEB_SEARCH_NOT_EXECUTED");
|
|
199
|
-
const sources = uniqueByUrl([...artifacts.sources, ...outputBlocks.flatMap((block) => block.url ? [{ url: block.url, ...(block.title ? { title: block.title } : {}) }] : [])]);
|
|
200
252
|
const citations = uniqueByUrl(artifacts.citations);
|
|
201
|
-
const
|
|
253
|
+
const discovered = uniqueByUrl([...artifacts.sources, ...outputBlocks.flatMap((block) => block.url ? [{ url: block.url, ...(block.title ? { title: block.title } : {}) }] : [])]);
|
|
254
|
+
const ranked = uniqueByUrl([...citations, ...discovered]);
|
|
255
|
+
const limited = ranked.slice(0, Math.max(1, maxResults));
|
|
202
256
|
const images = artifacts.images.slice(0, Math.max(1, maxResults));
|
|
257
|
+
const usage = hostedUsageFrom(response, artifacts.actions.length);
|
|
203
258
|
if (!output && !limited.length && !images.length)
|
|
204
259
|
throw failure("Hosted Web Search returned no output", "WEB_NO_SOURCES");
|
|
205
|
-
return { mode: "hosted", action: artifacts.actions[0], emulation: "native", content: output, sources: limited, citations, images, warnings: artifacts.actions.length > 1 ? [`Multiple hosted search actions were returned: ${artifacts.actions.join(", ")}`] : [], outputBlocks, domains: outputDomains(outputBlocks), ...(outputLineRange(outputBlocks) ? { lineRange: outputLineRange(outputBlocks) } : {}), requestId, ...(typeof response.id === "string" ? { responseId: response.id } : {}), retrievedAt, truncated:
|
|
260
|
+
return { mode: "hosted", action: artifacts.actions[0], emulation: "native", content: output, sources: limited, citations, images, warnings: artifacts.actions.length > 1 ? [`Multiple hosted search actions were returned: ${artifacts.actions.join(", ")}`] : [], outputBlocks, domains: outputDomains(outputBlocks), ...(outputLineRange(outputBlocks) ? { lineRange: outputLineRange(outputBlocks) } : {}), requestId, ...(typeof response.id === "string" ? { responseId: response.id } : {}), retrievedAt, truncated: ranked.length > limited.length || artifacts.images.length > images.length, ...(usage ? { usage } : {}) };
|
|
261
|
+
}
|
|
262
|
+
/** Project Hosted image results into LCX-owned, tool-private, replayable UI metadata. */
|
|
263
|
+
export function hostedMediaPresentationMeta(value, tool, base = {}) {
|
|
264
|
+
const inherited = base !== null && typeof base === "object" && !Array.isArray(base) ? base : {};
|
|
265
|
+
if (!isRecord(value) || !Array.isArray(value.images))
|
|
266
|
+
return inherited;
|
|
267
|
+
const candidates = value.images.flatMap((entry) => {
|
|
268
|
+
if (!isRecord(entry))
|
|
269
|
+
return [];
|
|
270
|
+
const imageUrl = httpUrl(entry.imageUrl);
|
|
271
|
+
if (!imageUrl)
|
|
272
|
+
return [];
|
|
273
|
+
const previewUrl = httpUrl(entry.thumbnailUrl);
|
|
274
|
+
const sourceUrl = httpUrl(entry.sourceWebsiteUrl);
|
|
275
|
+
return [{
|
|
276
|
+
kind: "image",
|
|
277
|
+
url: imageUrl.toString(),
|
|
278
|
+
...(previewUrl ? { previewUrl: previewUrl.toString() } : {}),
|
|
279
|
+
...(sourceUrl ? { sourceUrl: sourceUrl.toString() } : {}),
|
|
280
|
+
...(typeof entry.caption === "string" && entry.caption ? { caption: entry.caption } : {}),
|
|
281
|
+
structured: true,
|
|
282
|
+
}];
|
|
283
|
+
});
|
|
284
|
+
return candidates.length
|
|
285
|
+
? { ...inherited, lcxHostedMedia: { version: 1, tool, candidates } }
|
|
286
|
+
: inherited;
|
|
287
|
+
}
|
|
288
|
+
export function renderHostedSearchResult(value) {
|
|
289
|
+
const data = isRecord(value) ? value : {};
|
|
290
|
+
const parts = [];
|
|
291
|
+
if (typeof data.content === "string" && data.content)
|
|
292
|
+
parts.push(data.content);
|
|
293
|
+
const citations = Array.isArray(data.citations) ? data.citations.filter(isRecord) : [];
|
|
294
|
+
const citationUrls = new Set(citations.map((source) => String(source.url ?? "")).filter(Boolean));
|
|
295
|
+
if (citations.length)
|
|
296
|
+
parts.push(`引用:\n${citations.map(sourceLine).join("\n")}`);
|
|
297
|
+
const extraSources = Array.isArray(data.sources)
|
|
298
|
+
? data.sources.filter(isRecord).filter((source) => !citationUrls.has(String(source.url ?? "")))
|
|
299
|
+
: [];
|
|
300
|
+
if (extraSources.length)
|
|
301
|
+
parts.push(`来源:\n${extraSources.map(sourceLine).join("\n")}`);
|
|
302
|
+
if (Array.isArray(data.images) && data.images.length) {
|
|
303
|
+
parts.push(`图片:\n${data.images.filter(isRecord).map((image) => {
|
|
304
|
+
const caption = String(image.caption ?? image.imageUrl ?? "");
|
|
305
|
+
const imageUrl = String(image.imageUrl ?? "");
|
|
306
|
+
const sourcePage = typeof image.sourceWebsiteUrl === "string" && image.sourceWebsiteUrl
|
|
307
|
+
? ` 来源页: ${image.sourceWebsiteUrl}`
|
|
308
|
+
: "";
|
|
309
|
+
return `- [${caption}](${imageUrl})${sourcePage}`;
|
|
310
|
+
}).join("\n")}`);
|
|
311
|
+
}
|
|
312
|
+
if (Array.isArray(data.warnings) && data.warnings.length)
|
|
313
|
+
parts.push(data.warnings.map((warning) => `警告:${String(warning)}`).join("\n"));
|
|
314
|
+
if (isRecord(data.usage)) {
|
|
315
|
+
const renderedUsage = usageLine(data.usage);
|
|
316
|
+
if (renderedUsage)
|
|
317
|
+
parts.push(renderedUsage);
|
|
318
|
+
}
|
|
319
|
+
parts.push(`检索时间:${String(data.retrievedAt ?? "")}`);
|
|
320
|
+
return [{ type: "text", text: parts.filter(Boolean).join("\n\n") }];
|
|
206
321
|
}
|
|
207
|
-
export function renderHostedSearchResult(value) { const data = isRecord(value) ? value : {}; const parts = []; if (typeof data.content === "string" && data.content)
|
|
208
|
-
parts.push(data.content); if (Array.isArray(data.sources) && data.sources.length)
|
|
209
|
-
parts.push(`来源:\n${data.sources.filter(isRecord).map((source) => `- [${String(source.title ?? source.url ?? "")}](${String(source.url ?? "")})${source.snippet ? ` — ${String(source.snippet)}` : ""}`).join("\n")}`); if (Array.isArray(data.images) && data.images.length)
|
|
210
|
-
parts.push(`图片:\n${data.images.filter(isRecord).map((image) => `- [${String(image.caption ?? image.imageUrl ?? "")}](${String(image.imageUrl ?? "")})`).join("\n")}`); if (Array.isArray(data.warnings) && data.warnings.length)
|
|
211
|
-
parts.push(data.warnings.map((warning) => `警告:${String(warning)}`).join("\n")); parts.push(`检索时间:${String(data.retrievedAt ?? "")}`); return [{ type: "text", text: parts.filter(Boolean).join("\n\n") }]; }
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
1
2
|
import { JsonStore } from "./json-store.js";
|
|
2
|
-
const VERSION =
|
|
3
|
+
const VERSION = 2;
|
|
3
4
|
function isRecord(value) {
|
|
4
5
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
5
6
|
}
|
|
@@ -15,8 +16,18 @@ function validHttpUrl(value) {
|
|
|
15
16
|
return false;
|
|
16
17
|
}
|
|
17
18
|
}
|
|
19
|
+
function validFingerprint(value) {
|
|
20
|
+
return typeof value === "string" && /^[a-f0-9]{64}$/u.test(value);
|
|
21
|
+
}
|
|
22
|
+
function validProvenance(value) {
|
|
23
|
+
return isRecord(value) &&
|
|
24
|
+
typeof value.action === "string" && value.action.length > 0 &&
|
|
25
|
+
(value.originKind === "response" || value.originKind === "request" || value.originKind === "legacy-unattributed") &&
|
|
26
|
+
validFingerprint(value.originFingerprint) &&
|
|
27
|
+
(value.artifactFingerprint === undefined || validFingerprint(value.artifactFingerprint));
|
|
28
|
+
}
|
|
18
29
|
function validRef(refId, value) {
|
|
19
|
-
return isRecord(value) && value.refId === refId && validHttpUrl(value.url);
|
|
30
|
+
return isRecord(value) && value.refId === refId && validHttpUrl(value.url) && validProvenance(value.provenance);
|
|
20
31
|
}
|
|
21
32
|
function validSession(value) {
|
|
22
33
|
return isRecord(value) &&
|
|
@@ -28,15 +39,65 @@ function validData(data) {
|
|
|
28
39
|
return isRecord(data) && data.version === VERSION && isRecord(data.sessions) &&
|
|
29
40
|
Object.entries(data.sessions).every(([sessionId, session]) => sessionId.length > 0 && validSession(session));
|
|
30
41
|
}
|
|
42
|
+
function validLegacyRef(refId, value) {
|
|
43
|
+
return isRecord(value) && value.refId === refId && validHttpUrl(value.url);
|
|
44
|
+
}
|
|
45
|
+
function validLegacySession(value) {
|
|
46
|
+
return isRecord(value) &&
|
|
47
|
+
typeof value.routeFingerprint === "string" && value.routeFingerprint.length > 0 &&
|
|
48
|
+
typeof value.updatedAt === "string" && !Number.isNaN(Date.parse(value.updatedAt)) &&
|
|
49
|
+
isRecord(value.refs) && Object.entries(value.refs).every(([refId, ref]) => refId.length > 0 && validLegacyRef(refId, ref));
|
|
50
|
+
}
|
|
51
|
+
function validLegacyData(data) {
|
|
52
|
+
return isRecord(data) && data.version === 1 && isRecord(data.sessions) &&
|
|
53
|
+
Object.entries(data.sessions).every(([sessionId, session]) => sessionId.length > 0 && validLegacySession(session));
|
|
54
|
+
}
|
|
55
|
+
function legacyFingerprint(sessionId, routeFingerprint, ref) {
|
|
56
|
+
return createHash("sha256")
|
|
57
|
+
.update(JSON.stringify([sessionId, routeFingerprint, ref.refId, ref.url ?? null]))
|
|
58
|
+
.digest("hex");
|
|
59
|
+
}
|
|
60
|
+
function migrateLegacyData(data) {
|
|
61
|
+
if (!validLegacyData(data))
|
|
62
|
+
return undefined;
|
|
63
|
+
return {
|
|
64
|
+
version: VERSION,
|
|
65
|
+
sessions: Object.fromEntries(Object.entries(data.sessions).map(([sessionId, session]) => [sessionId, {
|
|
66
|
+
routeFingerprint: session.routeFingerprint,
|
|
67
|
+
updatedAt: session.updatedAt,
|
|
68
|
+
refs: Object.fromEntries(Object.entries(session.refs).map(([refId, ref]) => [refId, {
|
|
69
|
+
refId,
|
|
70
|
+
...(ref.url ? { url: ref.url } : {}),
|
|
71
|
+
provenance: {
|
|
72
|
+
action: "legacy-unattributed",
|
|
73
|
+
originKind: "legacy-unattributed",
|
|
74
|
+
originFingerprint: legacyFingerprint(sessionId, session.routeFingerprint, ref),
|
|
75
|
+
},
|
|
76
|
+
}])),
|
|
77
|
+
}])),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
31
80
|
function unavailable(refId) {
|
|
32
81
|
return Object.assign(new Error(`Alpha reference is unavailable in this session and route: ${refId}`), {
|
|
33
82
|
code: "LCX_ALPHA_REF_UNAVAILABLE",
|
|
34
83
|
});
|
|
35
84
|
}
|
|
85
|
+
function collision(refId) {
|
|
86
|
+
return Object.assign(new Error(`Alpha reference collision in this session and route: ${refId}`), {
|
|
87
|
+
code: "LCX_ALPHA_REF_COLLISION",
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
function sameObservation(left, right) {
|
|
91
|
+
return left.refId === right.refId && left.url === right.url &&
|
|
92
|
+
left.provenance.action === right.provenance.action &&
|
|
93
|
+
left.provenance.originKind === right.provenance.originKind &&
|
|
94
|
+
left.provenance.originFingerprint === right.provenance.originFingerprint &&
|
|
95
|
+
left.provenance.artifactFingerprint === right.provenance.artifactFingerprint;
|
|
96
|
+
}
|
|
36
97
|
export class AlphaRefStore {
|
|
37
98
|
store;
|
|
38
99
|
constructor(file) {
|
|
39
|
-
this.store = new JsonStore(file, () => ({ version: VERSION, sessions: {} }), validData, "LCX_ALPHA_REF_STORE_CORRUPT");
|
|
100
|
+
this.store = new JsonStore(file, () => ({ version: VERSION, sessions: {} }), validData, "LCX_ALPHA_REF_STORE_CORRUPT", migrateLegacyData);
|
|
40
101
|
}
|
|
41
102
|
record(sessionId, routeFingerprint, refs) {
|
|
42
103
|
if (typeof sessionId !== "string" || !sessionId || typeof routeFingerprint !== "string" || !routeFingerprint || !Array.isArray(refs)) {
|
|
@@ -44,13 +105,33 @@ export class AlphaRefStore {
|
|
|
44
105
|
}
|
|
45
106
|
this.store.update((current) => {
|
|
46
107
|
const previous = current.sessions[sessionId];
|
|
47
|
-
const
|
|
48
|
-
const nextRefs = { ...
|
|
108
|
+
const sameRoute = previous?.routeFingerprint === routeFingerprint;
|
|
109
|
+
const nextRefs = { ...(sameRoute ? previous.refs : {}) };
|
|
110
|
+
let changed = !sameRoute;
|
|
49
111
|
for (const value of refs) {
|
|
50
|
-
if (!isRecord(value) || typeof value.refId !== "string" || !value.refId
|
|
112
|
+
if (!isRecord(value) || typeof value.refId !== "string" || !value.refId)
|
|
113
|
+
throw unavailable("invalid-record");
|
|
114
|
+
const accepted = nextRefs[value.refId];
|
|
115
|
+
if (!validHttpUrl(value.url) || !validProvenance(value.provenance)) {
|
|
116
|
+
if (accepted)
|
|
117
|
+
throw collision(value.refId);
|
|
118
|
+
throw unavailable("invalid-record");
|
|
119
|
+
}
|
|
120
|
+
const observation = {
|
|
121
|
+
refId: value.refId,
|
|
122
|
+
...(value.url ? { url: value.url } : {}),
|
|
123
|
+
provenance: { ...value.provenance },
|
|
124
|
+
};
|
|
125
|
+
if (accepted) {
|
|
126
|
+
if (!sameObservation(accepted, observation))
|
|
127
|
+
throw collision(observation.refId);
|
|
51
128
|
continue;
|
|
52
|
-
|
|
129
|
+
}
|
|
130
|
+
nextRefs[observation.refId] = observation;
|
|
131
|
+
changed = true;
|
|
53
132
|
}
|
|
133
|
+
if (!changed && previous)
|
|
134
|
+
return current;
|
|
54
135
|
const sessions = {
|
|
55
136
|
...current.sessions,
|
|
56
137
|
[sessionId]: { routeFingerprint, refs: nextRefs, updatedAt: new Date().toISOString() },
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-lcx-codex",
|
|
3
|
-
"version": "0.4.3
|
|
4
|
-
"description": "DSH GPT Responses lifecycle
|
|
3
|
+
"version": "0.4.3",
|
|
4
|
+
"description": "Model-scoped DSH plugin: GPT Responses lifecycle, Native V2 compaction and Hosted/Alpha Search; Grok native Web/X Search",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"deepseek-harness",
|
|
7
7
|
"dsh",
|
|
@@ -11,7 +11,10 @@
|
|
|
11
11
|
"openai-responses",
|
|
12
12
|
"sub2api",
|
|
13
13
|
"newapi",
|
|
14
|
-
"compaction"
|
|
14
|
+
"compaction",
|
|
15
|
+
"grok",
|
|
16
|
+
"xai",
|
|
17
|
+
"x-search"
|
|
15
18
|
],
|
|
16
19
|
"repository": {
|
|
17
20
|
"type": "git",
|
|
@@ -38,8 +41,11 @@
|
|
|
38
41
|
},
|
|
39
42
|
"files": [
|
|
40
43
|
"lib/*.js",
|
|
41
|
-
"lib/types
|
|
42
|
-
"
|
|
44
|
+
"lib/types/index.d.ts",
|
|
45
|
+
"lib/types/client/index.d.ts",
|
|
46
|
+
"lib/types/client/search-media.d.ts",
|
|
47
|
+
"cordis.patch.yml",
|
|
48
|
+
"THIRD_PARTY_NOTICES.md"
|
|
43
49
|
],
|
|
44
50
|
"dsh": {
|
|
45
51
|
"bundle": {
|
|
@@ -48,39 +54,46 @@
|
|
|
48
54
|
"client": {
|
|
49
55
|
"platform": "web",
|
|
50
56
|
"inject": [
|
|
57
|
+
"@deepseek-ai/dsh-client-ui-chat",
|
|
58
|
+
"@deepseek-ai/dsh-client-ui-conversation",
|
|
51
59
|
"@deepseek-ai/dsh-client-ui-settings-plugins"
|
|
52
60
|
]
|
|
53
61
|
}
|
|
54
62
|
},
|
|
55
|
-
"dependencies": {
|
|
56
|
-
"@earendil-works/pi-ai": "0.85.1"
|
|
57
|
-
},
|
|
58
63
|
"devDependencies": {
|
|
64
|
+
"@deepseek-ai/dsh": "0.1.5-rc.1",
|
|
65
|
+
"@earendil-works/pi-ai": "0.85.1",
|
|
59
66
|
"@deepseek-ai/schemastery": "^3.18.2",
|
|
60
67
|
"@types/node": "^22.20.0",
|
|
61
68
|
"@types/react": "~18.3.1",
|
|
62
69
|
"esbuild": "^0.28.2",
|
|
70
|
+
"linkedom": "^0.18.13",
|
|
63
71
|
"typescript": "7.0.2"
|
|
64
72
|
},
|
|
65
73
|
"peerDependencies": {
|
|
66
74
|
"@deepseek-ai/cordis": "^4.0.2",
|
|
67
|
-
"@deepseek-ai/dsh-agent": "0.1.
|
|
68
|
-
"@deepseek-ai/dsh-attachment": "0.1.
|
|
69
|
-
"@deepseek-ai/dsh-client-locale": "0.1.
|
|
70
|
-
"@deepseek-ai/dsh-client-modules": "0.1.
|
|
71
|
-
"@deepseek-ai/dsh-client-store": "0.1.
|
|
72
|
-
"@deepseek-ai/dsh-client-ui-
|
|
73
|
-
"@deepseek-ai/dsh-
|
|
74
|
-
"@deepseek-ai/dsh-
|
|
75
|
-
"@deepseek-ai/dsh-
|
|
76
|
-
"@deepseek-ai/dsh-
|
|
77
|
-
"@deepseek-ai/dsh-
|
|
78
|
-
"@deepseek-ai/dsh-
|
|
79
|
-
"@deepseek-ai/dsh-
|
|
80
|
-
"@deepseek-ai/dsh-
|
|
81
|
-
"@deepseek-ai/dsh-web": "0.1.
|
|
75
|
+
"@deepseek-ai/dsh-agent": ">=0.1.5-rc.1 <0.1.6",
|
|
76
|
+
"@deepseek-ai/dsh-attachment": ">=0.1.5-rc.1 <0.1.6",
|
|
77
|
+
"@deepseek-ai/dsh-client-locale": ">=0.1.5-rc.1 <0.1.6",
|
|
78
|
+
"@deepseek-ai/dsh-client-modules": ">=0.1.5-rc.1 <0.1.6",
|
|
79
|
+
"@deepseek-ai/dsh-client-store": ">=0.1.5-rc.1 <0.1.6",
|
|
80
|
+
"@deepseek-ai/dsh-client-ui-chat": ">=0.1.5-rc.1 <0.1.6",
|
|
81
|
+
"@deepseek-ai/dsh-client-ui-conversation": ">=0.1.5-rc.1 <0.1.6",
|
|
82
|
+
"@deepseek-ai/dsh-client-ui-settings-plugins": ">=0.1.5-rc.1 <0.1.6",
|
|
83
|
+
"@deepseek-ai/dsh-compaction": ">=0.1.5-rc.1 <0.1.6",
|
|
84
|
+
"@deepseek-ai/dsh-credentials": ">=0.1.5-rc.1 <0.1.6",
|
|
85
|
+
"@deepseek-ai/dsh-fs": ">=0.1.5-rc.1 <0.1.6",
|
|
86
|
+
"@deepseek-ai/dsh-llm": ">=0.1.5-rc.1 <0.1.6",
|
|
87
|
+
"@deepseek-ai/dsh-session": ">=0.1.5-rc.1 <0.1.6",
|
|
88
|
+
"@deepseek-ai/dsh-settings": ">=0.1.5-rc.1 <0.1.6",
|
|
89
|
+
"@deepseek-ai/dsh-tool-web": ">=0.1.5-rc.1 <0.1.6",
|
|
90
|
+
"@deepseek-ai/dsh-tools": ">=0.1.5-rc.1 <0.1.6",
|
|
91
|
+
"@deepseek-ai/dsh-web": ">=0.1.5-rc.1 <0.1.6",
|
|
82
92
|
"@deepseek-ai/schemastery": "^3.18.2",
|
|
83
|
-
"react": "^18.2.0"
|
|
93
|
+
"react": "^18.2.0",
|
|
94
|
+
"@deepseek-ai/dsh-token-meter": ">=0.1.5-rc.1 <0.1.6",
|
|
95
|
+
"@deepseek-ai/dsh-session-projection": ">=0.1.5-rc.1 <0.1.6",
|
|
96
|
+
"zod": "^4.5.4"
|
|
84
97
|
},
|
|
85
98
|
"peerDependenciesMeta": {
|
|
86
99
|
"@deepseek-ai/dsh-client-locale": {
|
|
@@ -98,6 +111,12 @@
|
|
|
98
111
|
"@deepseek-ai/dsh-client-store": {
|
|
99
112
|
"optional": true
|
|
100
113
|
},
|
|
114
|
+
"@deepseek-ai/dsh-client-ui-chat": {
|
|
115
|
+
"optional": true
|
|
116
|
+
},
|
|
117
|
+
"@deepseek-ai/dsh-client-ui-conversation": {
|
|
118
|
+
"optional": true
|
|
119
|
+
},
|
|
101
120
|
"@deepseek-ai/dsh-client-ui-settings-plugins": {
|
|
102
121
|
"optional": true
|
|
103
122
|
},
|
|
@@ -131,7 +150,7 @@
|
|
|
131
150
|
},
|
|
132
151
|
"scripts": {
|
|
133
152
|
"build": "npm run build:host && npm run build:client",
|
|
134
|
-
"build:host": "tsc -p tsconfig.json",
|
|
153
|
+
"build:host": "tsc -p tsconfig.json && node scripts/build-pi-runtime.mjs",
|
|
135
154
|
"build:client": "tsc -p tsconfig.client.json && node scripts/build-client.mjs",
|
|
136
155
|
"test": "node --test tests/*.test.mjs",
|
|
137
156
|
"typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.client.json --noEmit",
|
|
@@ -145,5 +164,10 @@
|
|
|
145
164
|
"publishConfig": {
|
|
146
165
|
"access": "public"
|
|
147
166
|
},
|
|
148
|
-
"license": "MIT"
|
|
167
|
+
"license": "MIT",
|
|
168
|
+
"lcxCompatibility": {
|
|
169
|
+
"dshInstallRange": ">=0.1.5-rc.1 <0.1.6",
|
|
170
|
+
"verifiedDsh": "0.1.5-rc.1",
|
|
171
|
+
"verifiedHostPi": "0.85.1"
|
|
172
|
+
}
|
|
149
173
|
}
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import { buildCompactionResponsesBody } from "./responses-request.js";
|
|
2
|
-
type HeaderMap = Record<string, string>;
|
|
3
|
-
type CompactionItem = {
|
|
4
|
-
type: "compaction";
|
|
5
|
-
encrypted_content: string;
|
|
6
|
-
};
|
|
7
|
-
type FunctionCallItem = {
|
|
8
|
-
type: "function_call";
|
|
9
|
-
call_id: string;
|
|
10
|
-
};
|
|
11
|
-
type FunctionCallOutputItem = {
|
|
12
|
-
type: "function_call_output";
|
|
13
|
-
call_id: string;
|
|
14
|
-
};
|
|
15
|
-
type ValidatedOutputItem = CompactionItem | FunctionCallItem | FunctionCallOutputItem | {
|
|
16
|
-
type: string;
|
|
17
|
-
};
|
|
18
|
-
type CanonicalUsage = {
|
|
19
|
-
inputTokens: number;
|
|
20
|
-
outputTokens: number;
|
|
21
|
-
cacheReadTokens?: number;
|
|
22
|
-
cacheWriteTokens?: number;
|
|
23
|
-
reasoningTokens?: number;
|
|
24
|
-
};
|
|
25
|
-
type GenerationControls = {
|
|
26
|
-
reasoningEffort?: unknown;
|
|
27
|
-
temperature?: unknown;
|
|
28
|
-
maxTokens?: unknown;
|
|
29
|
-
};
|
|
30
|
-
type GenerationEnvelope = {
|
|
31
|
-
reasoning?: {
|
|
32
|
-
effort: string;
|
|
33
|
-
summary: "auto";
|
|
34
|
-
};
|
|
35
|
-
include?: string[];
|
|
36
|
-
temperature?: number;
|
|
37
|
-
max_output_tokens?: number;
|
|
38
|
-
};
|
|
39
|
-
type NativeCompactionBodyOptions = GenerationControls & {
|
|
40
|
-
model: string;
|
|
41
|
-
modelDescriptor?: Exclude<Parameters<typeof buildCompactionResponsesBody>[0]["model"], string>;
|
|
42
|
-
input: unknown[];
|
|
43
|
-
tools?: unknown;
|
|
44
|
-
promptCacheKey?: string;
|
|
45
|
-
promptCacheRetention?: string;
|
|
46
|
-
cacheRetention?: "none" | "short" | "long";
|
|
47
|
-
};
|
|
48
|
-
type NativeCompactionRequestOptions = NativeCompactionBodyOptions & {
|
|
49
|
-
baseURL: string;
|
|
50
|
-
idempotencyKey?: string;
|
|
51
|
-
headers?: HeaderMap;
|
|
52
|
-
signal?: AbortSignal;
|
|
53
|
-
timeoutMs?: number;
|
|
54
|
-
maxAttempts?: number;
|
|
55
|
-
maxResponseBytes?: number;
|
|
56
|
-
};
|
|
57
|
-
type SseParseOptions = {
|
|
58
|
-
signal?: AbortSignal;
|
|
59
|
-
maxResponseBytes?: number;
|
|
60
|
-
};
|
|
61
|
-
type NativeCompactionResult = {
|
|
62
|
-
object: unknown;
|
|
63
|
-
id?: string;
|
|
64
|
-
output: ValidatedOutputItem[];
|
|
65
|
-
compaction: CompactionItem;
|
|
66
|
-
usage?: CanonicalUsage;
|
|
67
|
-
};
|
|
68
|
-
export declare const REMOTE_COMPACTION_V2_FEATURE = "remote_compaction_v2";
|
|
69
|
-
/**
|
|
70
|
-
* @param {HeaderMap} [headers]
|
|
71
|
-
* @returns {HeaderMap}
|
|
72
|
-
*/
|
|
73
|
-
export declare function mergeFeatureHeader(headers?: HeaderMap): HeaderMap;
|
|
74
|
-
/**
|
|
75
|
-
* @param {GenerationControls} [controls]
|
|
76
|
-
* @returns {GenerationEnvelope}
|
|
77
|
-
*/
|
|
78
|
-
export declare function responsesGenerationEnvelope(controls?: GenerationControls): GenerationEnvelope;
|
|
79
|
-
/**
|
|
80
|
-
* @param {NativeCompactionBodyOptions} options
|
|
81
|
-
* @returns {NativeCompactionBody}
|
|
82
|
-
*/
|
|
83
|
-
export declare function buildNativeCompactionBody({ model, modelDescriptor, input, tools, promptCacheKey, promptCacheRetention, cacheRetention, reasoningEffort, temperature, maxTokens, }: NativeCompactionBodyOptions): {
|
|
84
|
-
[x: string]: unknown;
|
|
85
|
-
} & {
|
|
86
|
-
model: string;
|
|
87
|
-
input: unknown[];
|
|
88
|
-
stream: boolean;
|
|
89
|
-
store: boolean;
|
|
90
|
-
tool_choice?: string;
|
|
91
|
-
parallel_tool_calls?: boolean;
|
|
92
|
-
};
|
|
93
|
-
/**
|
|
94
|
-
* Provider SSE events enter as unknown; response.completed remains authoritative.
|
|
95
|
-
* @param {Response} response
|
|
96
|
-
* @param {SseParseOptions} [options]
|
|
97
|
-
* @returns {Promise<NativeCompactionResult>}
|
|
98
|
-
*/
|
|
99
|
-
export declare function parseNativeCompactionSse(response: Response, options?: SseParseOptions): Promise<NativeCompactionResult>;
|
|
100
|
-
/**
|
|
101
|
-
* @param {NativeCompactionRequestOptions} options
|
|
102
|
-
*/
|
|
103
|
-
export declare function requestNativeCompaction({ baseURL, model, modelDescriptor, input, tools, promptCacheKey, promptCacheRetention, cacheRetention, reasoningEffort, temperature, maxTokens, idempotencyKey, headers, signal, timeoutMs, maxAttempts, maxResponseBytes, }: NativeCompactionRequestOptions): Promise<NativeCompactionResult>;
|
|
104
|
-
export {};
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { Session, type SessionStore } from "@deepseek-ai/dsh-session";
|
|
2
|
-
import type { ToolRuntime } from "@deepseek-ai/dsh-tools";
|
|
3
|
-
import { ServiceMutex } from "./service-mutex.js";
|
|
4
|
-
type CompatMethod = (this: object, agent: unknown, trigger: string, signal: AbortSignal) => Promise<unknown>;
|
|
5
|
-
type PrunerMethod = (...args: unknown[]) => unknown;
|
|
6
|
-
type MutableService = Record<PropertyKey, unknown>;
|
|
7
|
-
interface CompactionService extends MutableService {
|
|
8
|
-
compactIfNeeded: CompatMethod;
|
|
9
|
-
}
|
|
10
|
-
export interface CompactionPatchRecord {
|
|
11
|
-
compaction: CompactionService;
|
|
12
|
-
original: CompatMethod;
|
|
13
|
-
wrapper: CompatMethod;
|
|
14
|
-
mutex: ServiceMutex;
|
|
15
|
-
lifecycle: AbortController;
|
|
16
|
-
}
|
|
17
|
-
export type CompactionPatchRecords = Map<object, CompactionPatchRecord>;
|
|
18
|
-
export type CompactionPatchBehavior = (agent: unknown, trigger: string, signal: AbortSignal, callOriginal: (signal: AbortSignal) => Promise<unknown>) => Promise<unknown>;
|
|
19
|
-
interface PrunerService extends MutableService {
|
|
20
|
-
pruneSession: unknown;
|
|
21
|
-
}
|
|
22
|
-
export interface PrunerPatchRecord {
|
|
23
|
-
pruner: PrunerService;
|
|
24
|
-
original: unknown;
|
|
25
|
-
replacement: PrunerMethod;
|
|
26
|
-
}
|
|
27
|
-
interface ConfigService extends MutableService {
|
|
28
|
-
config: unknown;
|
|
29
|
-
}
|
|
30
|
-
export interface ConfigPatchRecord {
|
|
31
|
-
service: ConfigService;
|
|
32
|
-
original: unknown;
|
|
33
|
-
installed: unknown;
|
|
34
|
-
}
|
|
35
|
-
export declare function agentSessionId(agent: unknown): string;
|
|
36
|
-
export declare function agentUsesSession(agent: unknown, session: Session): boolean;
|
|
37
|
-
export declare function sessionFromAgent(agent: unknown): Session | undefined;
|
|
38
|
-
export declare function readAgentRouteState(agent: unknown): {
|
|
39
|
-
requestConfig: unknown;
|
|
40
|
-
options: unknown;
|
|
41
|
-
sessionId: string;
|
|
42
|
-
};
|
|
43
|
-
export declare function scopedToolRuntime(agent: unknown): (Pick<ToolRuntime, "register"> & Partial<Pick<ToolRuntime, "get">>) | undefined;
|
|
44
|
-
export declare function tokenMeterTotal(value: unknown, session: Session): number | undefined;
|
|
45
|
-
export declare function sessionsService(ctx: unknown): Pick<SessionStore, "get"> | undefined;
|
|
46
|
-
export declare function sessionFor(ctx: unknown, sessionId: string): Session | undefined;
|
|
47
|
-
export declare function readWebSearchProvider(ctx: unknown): unknown;
|
|
48
|
-
export declare function writeWebSearchProvider(ctx: unknown, providerId: unknown): boolean;
|
|
49
|
-
export declare function contextService(ctx: unknown, name: string): unknown;
|
|
50
|
-
export declare function resolveContextService(ctx: unknown, name: string): unknown;
|
|
51
|
-
export declare function resolveScopedService(agent: unknown, name: string): unknown;
|
|
52
|
-
export declare function resolveAgentService(ctx: unknown, agent: unknown, name: string): unknown;
|
|
53
|
-
export declare function concreteService(value: unknown): unknown;
|
|
54
|
-
export declare function compactionPatchCandidate(value: unknown, records: ReadonlyMap<object, CompactionPatchRecord>): Pick<CompactionPatchRecord, "compaction" | "original"> | undefined;
|
|
55
|
-
export declare function installCompactionPatch(records: CompactionPatchRecords, candidate: Pick<CompactionPatchRecord, "compaction" | "original">, mutex: ServiceMutex, lifecycle: AbortController, behavior: CompactionPatchBehavior): boolean;
|
|
56
|
-
export declare function restoreCompactionPatches(records: Map<object, CompactionPatchRecord>, entries?: Iterable<CompactionPatchRecord>): void;
|
|
57
|
-
export declare function toolResultPrunerState(value: unknown): {
|
|
58
|
-
pruner: PrunerService | undefined;
|
|
59
|
-
original: unknown;
|
|
60
|
-
};
|
|
61
|
-
export declare function patchToolResultPruner(state: {
|
|
62
|
-
pruner: PrunerService | undefined;
|
|
63
|
-
original: unknown;
|
|
64
|
-
}, replacement: PrunerMethod): PrunerPatchRecord | undefined;
|
|
65
|
-
export declare function restoreToolResultPruner(record: PrunerPatchRecord | undefined): void;
|
|
66
|
-
export declare function compactionConfigState(service: unknown): {
|
|
67
|
-
service: ConfigService | undefined;
|
|
68
|
-
original: unknown;
|
|
69
|
-
};
|
|
70
|
-
export declare function patchCompactionConfig(state: {
|
|
71
|
-
service: ConfigService | undefined;
|
|
72
|
-
original: unknown;
|
|
73
|
-
}, createConfig: (originalConfig: unknown) => unknown): ConfigPatchRecord | undefined;
|
|
74
|
-
export declare function restoreCompactionConfig(record: ConfigPatchRecord | undefined): void;
|
|
75
|
-
export declare function patchVisibleWebSearchTimeout(agent: unknown, getTimeoutMs: () => number | undefined, patchedDefinitions: Map<MutableService, unknown>): void;
|
|
76
|
-
export declare function refreshVisibleWebSearchTimeouts(patchedDefinitions: ReadonlyMap<MutableService, unknown>, timeoutMs: number | undefined): void;
|
|
77
|
-
export declare function restoreVisibleWebSearchTimeouts(patchedDefinitions: Map<MutableService, unknown>): void;
|
|
78
|
-
export {};
|