dsh-lcx-codex 0.4.2 → 0.4.3-pre.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 +75 -224
- package/THIRD_PARTY_NOTICES.md +64 -0
- package/cordis.patch.yml +3 -20
- package/lib/auxiliary-usage.js +63 -0
- package/lib/client.js +1398 -167
- package/lib/compact-v2.js +218 -199
- package/lib/dsh-compat.js +294 -100
- package/lib/dsh-responses.js +512 -277
- package/lib/grok-native-search.js +391 -0
- package/lib/index.js +1066 -758
- package/lib/invocation-policy-scope.js +261 -0
- package/lib/json-store.js +57 -31
- package/lib/native-checkpoint.js +520 -194
- package/lib/pi-responses-runtime.js +1571 -0
- package/lib/responses-request.js +109 -121
- package/lib/responses-stream.js +1280 -447
- package/lib/route.js +425 -369
- package/lib/search-accounting.js +86 -0
- package/lib/search-usage.js +86 -0
- package/lib/service-mutex.js +73 -64
- package/lib/token-budget.js +176 -108
- package/lib/transport.js +308 -68
- package/lib/types/client/index.d.ts +18 -0
- package/lib/types/client/search-media.d.ts +16 -0
- package/lib/types/index.d.ts +83 -0
- package/lib/web-run-output.js +189 -18
- package/lib/web-search-alpha.js +1067 -163
- package/lib/web-search-capability.js +80 -65
- package/lib/web-search-hosted.js +321 -33
- package/lib/web-search-ref-store.js +145 -60
- package/package.json +112 -32
- package/ARCHITECTURE.md +0 -117
- package/CHANGELOG.md +0 -224
- package/README_EN.md +0 -277
- package/assets/dsh-lcx-codex-banner.jpg +0 -0
- package/lib/legacy-v3.js +0 -20
- package/lib/responses-replay.js +0 -68
- package/scripts/probe-alpha.mjs +0 -43
- package/scripts/validate-dsh-schema.mjs +0 -31
package/lib/responses-request.js
CHANGED
|
@@ -1,145 +1,133 @@
|
|
|
1
1
|
// @ts-check
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const OPENAI_RESPONSES_MIN_OUTPUT_TOKENS = 16
|
|
7
|
-
|
|
8
|
-
/** @typedef {'none' | 'short' | 'long'} CacheRetention */
|
|
9
|
-
/** @typedef {Record<string, unknown>} UnknownRecord */
|
|
10
|
-
/**
|
|
11
|
-
* @typedef {object} ResponsesCompat
|
|
12
|
-
* @property {boolean} [supportsLongCacheRetention]
|
|
13
|
-
* @property {boolean} [supportsExplicitPromptCacheMode]
|
|
14
|
-
*/
|
|
15
|
-
/**
|
|
16
|
-
* @typedef {object} PiResponsesModel
|
|
17
|
-
* @property {string} id
|
|
18
|
-
* @property {string} provider
|
|
19
|
-
* @property {boolean} [reasoning]
|
|
20
|
-
* @property {Record<string, string | null>} [thinkingLevelMap]
|
|
21
|
-
* @property {ResponsesCompat} [compat]
|
|
22
|
-
*/
|
|
23
|
-
/**
|
|
24
|
-
* @typedef {object} GenerationControls
|
|
25
|
-
* @property {unknown} [reasoningEffort]
|
|
26
|
-
* @property {unknown} [temperature]
|
|
27
|
-
* @property {unknown} [maxTokens]
|
|
28
|
-
*/
|
|
29
|
-
/**
|
|
30
|
-
* @typedef {object} BuildResponsesBodyOptions
|
|
31
|
-
* @property {PiResponsesModel | string} model
|
|
32
|
-
* @property {unknown[]} input
|
|
33
|
-
* @property {string} [instructions]
|
|
34
|
-
* @property {unknown} [tools]
|
|
35
|
-
* @property {string} [sessionId]
|
|
36
|
-
* @property {string} [promptCacheKey]
|
|
37
|
-
* @property {string} [promptCacheRetention]
|
|
38
|
-
* @property {CacheRetention} [cacheRetention]
|
|
39
|
-
* @property {unknown} [reasoningEffort]
|
|
40
|
-
* @property {unknown} [temperature]
|
|
41
|
-
* @property {unknown} [maxTokens]
|
|
42
|
-
* @property {UnknownRecord} [samplingParams]
|
|
43
|
-
*/
|
|
44
|
-
|
|
2
|
+
import { clampOpenAIPromptCacheKey } from "./pi-responses-runtime.js";
|
|
3
|
+
import { responsesTools } from "./dsh-responses.js";
|
|
4
|
+
const OPENAI_RESPONSES_MIN_OUTPUT_TOKENS = 16;
|
|
45
5
|
/** @param {unknown} value */
|
|
46
|
-
function isObject(value) {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
function modelId(model) {
|
|
50
|
-
|
|
51
|
-
|
|
6
|
+
function isObject(value) {
|
|
7
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
8
|
+
}
|
|
9
|
+
function modelId(model) {
|
|
10
|
+
return typeof model === "string" ? model : model.id;
|
|
11
|
+
}
|
|
52
12
|
function modelRecord(model) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
13
|
+
return typeof model === "string"
|
|
14
|
+
? /** @type {PiResponsesModel} */ {
|
|
15
|
+
id: model,
|
|
16
|
+
provider: "lcx",
|
|
17
|
+
reasoning: true,
|
|
18
|
+
}
|
|
19
|
+
: model;
|
|
56
20
|
}
|
|
57
|
-
|
|
58
21
|
/** @param {unknown} value */
|
|
59
22
|
function normalizeCacheRetention(value) {
|
|
60
|
-
|
|
23
|
+
const normalized = String(value);
|
|
24
|
+
return normalized === "none" || normalized === "short" || normalized === "long"
|
|
25
|
+
? normalized
|
|
26
|
+
: "short";
|
|
61
27
|
}
|
|
62
|
-
|
|
63
28
|
/**
|
|
64
29
|
* Pi-parity generation controls for OpenAI Responses.
|
|
65
30
|
* @param {GenerationControls & { model?: PiResponsesModel | string, includeDefaultReasoning?: boolean }} [controls]
|
|
66
31
|
*/
|
|
67
|
-
export function responsesGenerationEnvelope({ model =
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
32
|
+
export function responsesGenerationEnvelope({ model = "unknown", reasoningEffort, temperature, maxTokens, includeDefaultReasoning = false, } = {}) {
|
|
33
|
+
const descriptor = modelRecord(model);
|
|
34
|
+
const result = {};
|
|
35
|
+
if (descriptor.reasoning !== false) {
|
|
36
|
+
if (descriptor.provider === "xai" ||
|
|
37
|
+
descriptor.includeEncryptedReasoning === true)
|
|
38
|
+
result.include = ["reasoning.encrypted_content"];
|
|
39
|
+
if (reasoningEffort !== undefined && reasoningEffort !== "off") {
|
|
40
|
+
const requested = String(reasoningEffort);
|
|
41
|
+
const wire = descriptor.thinkingLevelMap?.[requested] ?? requested;
|
|
42
|
+
if (wire !== null) {
|
|
43
|
+
result.reasoning = { effort: wire, summary: "auto" };
|
|
44
|
+
result.include = ["reasoning.encrypted_content"];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
else if (includeDefaultReasoning &&
|
|
48
|
+
descriptor.provider !== "github-copilot" &&
|
|
49
|
+
descriptor.thinkingLevelMap?.off !== null) {
|
|
50
|
+
result.reasoning = { effort: descriptor.thinkingLevelMap?.off ?? "none" };
|
|
51
|
+
}
|
|
81
52
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
53
|
+
if (temperature !== undefined) {
|
|
54
|
+
if (!Number.isFinite(temperature))
|
|
55
|
+
throw Object.assign(new Error("Responses temperature must be finite"), {
|
|
56
|
+
code: "LCX_RESPONSES_INVALID_INPUT",
|
|
57
|
+
});
|
|
58
|
+
result.temperature = Number(temperature);
|
|
59
|
+
}
|
|
60
|
+
if (maxTokens !== undefined) {
|
|
61
|
+
if (!Number.isSafeInteger(maxTokens) || Number(maxTokens) <= 0)
|
|
62
|
+
throw Object.assign(new Error("Responses maxTokens must be a positive safe integer"), { code: "LCX_RESPONSES_INVALID_INPUT" });
|
|
63
|
+
if (descriptor.compat?.supportsMaxOutputTokens !== false)
|
|
64
|
+
result.max_output_tokens = Math.max(OPENAI_RESPONSES_MIN_OUTPUT_TOKENS, Number(maxTokens));
|
|
65
|
+
}
|
|
66
|
+
return result;
|
|
92
67
|
}
|
|
93
|
-
|
|
94
68
|
/**
|
|
95
|
-
* Build the shared LCX-owned request envelope while retaining Pi 0.
|
|
69
|
+
* Build the shared LCX-owned request envelope while retaining Pi 0.85.1 Responses semantics.
|
|
96
70
|
* Production LCX ordinary/compact/replay construction places the DSH system prompt in canonical input.
|
|
97
|
-
* `instructions` remains accepted only for the exported low-level helper's backward-compatible callers.
|
|
98
71
|
* @param {BuildResponsesBodyOptions} options
|
|
99
72
|
*/
|
|
100
|
-
export function buildResponsesBody({ model, input,
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
73
|
+
export function buildResponsesBody({ model, input, tools, sessionId, promptCacheKey, promptCacheRetention, cacheRetention, reasoningEffort, temperature, maxTokens, samplingParams, }) {
|
|
74
|
+
if (!Array.isArray(input))
|
|
75
|
+
throw Object.assign(new Error("Responses input must be an array"), {
|
|
76
|
+
code: "LCX_RESPONSES_INVALID_INPUT",
|
|
77
|
+
});
|
|
78
|
+
const descriptor = modelRecord(model);
|
|
79
|
+
const retention = normalizeCacheRetention(cacheRetention);
|
|
80
|
+
const compat = descriptor.compat ?? {};
|
|
81
|
+
const cacheKey = retention === "none"
|
|
82
|
+
? undefined
|
|
83
|
+
: (promptCacheKey ?? clampOpenAIPromptCacheKey(sessionId));
|
|
84
|
+
const longRetention = retention === "long" && compat.supportsExplicitPromptCacheMode !== true
|
|
85
|
+
? promptCacheRetention ?? (compat.supportsLongCacheRetention === true ? "24h" : undefined)
|
|
86
|
+
: undefined;
|
|
87
|
+
// Pi 0.85.1 uses explicit 30m only for long retention; short is implicit.
|
|
88
|
+
const currentCache = retention === "long" && compat.supportsLongCacheRetention === true && compat.supportsExplicitPromptCacheMode === true;
|
|
89
|
+
const explicitCache = retention === "none" && compat.supportsExplicitPromptCacheMode === true;
|
|
90
|
+
const promptCacheOptions = currentCache
|
|
91
|
+
? { ttl: "30m" }
|
|
92
|
+
: explicitCache
|
|
93
|
+
? { mode: "explicit" }
|
|
94
|
+
: undefined;
|
|
95
|
+
const nativeTools = responsesTools(Array.isArray(tools) ? tools : undefined);
|
|
96
|
+
const body = {
|
|
97
|
+
model: modelId(model),
|
|
98
|
+
input: structuredClone(input),
|
|
99
|
+
stream: true,
|
|
100
|
+
store: false,
|
|
101
|
+
...(nativeTools !== undefined && nativeTools.length > 0
|
|
102
|
+
? { tools: nativeTools }
|
|
103
|
+
: {}),
|
|
104
|
+
...(cacheKey ? { prompt_cache_key: cacheKey } : {}),
|
|
105
|
+
...(longRetention ? { prompt_cache_retention: longRetention } : {}),
|
|
106
|
+
...(promptCacheOptions ? { prompt_cache_options: promptCacheOptions } : {}),
|
|
107
|
+
...responsesGenerationEnvelope({
|
|
108
|
+
model: descriptor,
|
|
109
|
+
reasoningEffort,
|
|
110
|
+
temperature,
|
|
111
|
+
maxTokens,
|
|
112
|
+
includeDefaultReasoning: true,
|
|
113
|
+
}),
|
|
114
|
+
};
|
|
115
|
+
if (isObject(samplingParams))
|
|
116
|
+
Object.assign(body, structuredClone(samplingParams));
|
|
117
|
+
return body;
|
|
129
118
|
}
|
|
130
|
-
|
|
131
119
|
/**
|
|
132
120
|
* Compact is the standard request plus the one opaque-history transition patch.
|
|
133
121
|
* @param {BuildResponsesBodyOptions} options
|
|
134
122
|
*/
|
|
135
123
|
export function buildCompactionResponsesBody(options) {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
124
|
+
const body = buildResponsesBody(options);
|
|
125
|
+
if (body.input.some((item) => isObject(item) && item.type === "compaction_trigger")) {
|
|
126
|
+
throw Object.assign(new Error("native compaction input already contains compaction_trigger"), { code: "LCX_COMPACT_DUPLICATE_TRIGGER" });
|
|
127
|
+
}
|
|
128
|
+
body.input = [...body.input, { type: "compaction_trigger" }];
|
|
129
|
+
// Remote Compaction V2 has historically required these explicit controls.
|
|
130
|
+
body.tool_choice = "auto";
|
|
131
|
+
body.parallel_tool_calls = true;
|
|
132
|
+
return body;
|
|
145
133
|
}
|