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.
Files changed (39) hide show
  1. package/README.md +75 -224
  2. package/THIRD_PARTY_NOTICES.md +64 -0
  3. package/cordis.patch.yml +3 -20
  4. package/lib/auxiliary-usage.js +63 -0
  5. package/lib/client.js +1398 -167
  6. package/lib/compact-v2.js +218 -199
  7. package/lib/dsh-compat.js +294 -100
  8. package/lib/dsh-responses.js +512 -277
  9. package/lib/grok-native-search.js +391 -0
  10. package/lib/index.js +1066 -758
  11. package/lib/invocation-policy-scope.js +261 -0
  12. package/lib/json-store.js +57 -31
  13. package/lib/native-checkpoint.js +520 -194
  14. package/lib/pi-responses-runtime.js +1571 -0
  15. package/lib/responses-request.js +109 -121
  16. package/lib/responses-stream.js +1280 -447
  17. package/lib/route.js +425 -369
  18. package/lib/search-accounting.js +86 -0
  19. package/lib/search-usage.js +86 -0
  20. package/lib/service-mutex.js +73 -64
  21. package/lib/token-budget.js +176 -108
  22. package/lib/transport.js +308 -68
  23. package/lib/types/client/index.d.ts +18 -0
  24. package/lib/types/client/search-media.d.ts +16 -0
  25. package/lib/types/index.d.ts +83 -0
  26. package/lib/web-run-output.js +189 -18
  27. package/lib/web-search-alpha.js +1067 -163
  28. package/lib/web-search-capability.js +80 -65
  29. package/lib/web-search-hosted.js +321 -33
  30. package/lib/web-search-ref-store.js +145 -60
  31. package/package.json +112 -32
  32. package/ARCHITECTURE.md +0 -117
  33. package/CHANGELOG.md +0 -224
  34. package/README_EN.md +0 -277
  35. package/assets/dsh-lcx-codex-banner.jpg +0 -0
  36. package/lib/legacy-v3.js +0 -20
  37. package/lib/responses-replay.js +0 -68
  38. package/scripts/probe-alpha.mjs +0 -43
  39. package/scripts/validate-dsh-schema.mjs +0 -31
@@ -1,145 +1,133 @@
1
1
  // @ts-check
2
-
3
- import { clampOpenAIPromptCacheKey } from '@earendil-works/pi-ai/api/openai-prompt-cache'
4
- import { responsesTools } from './dsh-responses.js'
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) { return value !== null && typeof value === 'object' && !Array.isArray(value) }
47
-
48
- /** @param {PiResponsesModel | string} model */
49
- function modelId(model) { return typeof model === 'string' ? model : model.id }
50
-
51
- /** @param {PiResponsesModel | string} model */
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
- return typeof model === 'string'
54
- ? /** @type {PiResponsesModel} */ ({ id: model, provider: 'lcx', reasoning: true })
55
- : model
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
- return /** @type {CacheRetention} */ (['none', 'short', 'long'].includes(String(value)) ? value : 'short')
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 = 'unknown', reasoningEffort, temperature, maxTokens, includeDefaultReasoning = false } = {}) {
68
- const descriptor = modelRecord(model)
69
- /** @type {UnknownRecord} */
70
- const result = {}
71
- if (descriptor.reasoning !== false) {
72
- if (reasoningEffort !== undefined && reasoningEffort !== 'off') {
73
- const requested = String(reasoningEffort)
74
- const wire = descriptor.thinkingLevelMap?.[requested] ?? requested
75
- if (wire !== null) {
76
- result.reasoning = { effort: wire, summary: 'auto' }
77
- result.include = ['reasoning.encrypted_content']
78
- }
79
- } else if (includeDefaultReasoning && descriptor.provider !== 'github-copilot' && descriptor.thinkingLevelMap?.off !== null) {
80
- result.reasoning = { effort: descriptor.thinkingLevelMap?.off ?? 'none' }
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
- if (temperature !== undefined) {
84
- if (!Number.isFinite(temperature)) throw Object.assign(new Error('Responses temperature must be finite'), { code: 'LCX_RESPONSES_INVALID_INPUT' })
85
- result.temperature = Number(temperature)
86
- }
87
- if (maxTokens !== undefined) {
88
- if (!Number.isSafeInteger(maxTokens) || Number(maxTokens) <= 0) throw Object.assign(new Error('Responses maxTokens must be a positive safe integer'), { code: 'LCX_RESPONSES_INVALID_INPUT' })
89
- result.max_output_tokens = Math.max(OPENAI_RESPONSES_MIN_OUTPUT_TOKENS, Number(maxTokens))
90
- }
91
- return result
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.84 Responses semantics.
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, instructions, tools, sessionId, promptCacheKey, promptCacheRetention, cacheRetention, reasoningEffort, temperature, maxTokens, samplingParams }) {
101
- if (!Array.isArray(input)) throw Object.assign(new Error('Responses input must be an array'), { code: 'LCX_RESPONSES_INVALID_INPUT' })
102
- const descriptor = modelRecord(model)
103
- const retention = normalizeCacheRetention(cacheRetention)
104
- const compat = descriptor.compat ?? {}
105
- const cacheKey = retention === 'none'
106
- ? undefined
107
- : promptCacheKey ?? clampOpenAIPromptCacheKey(sessionId)
108
- const longRetention = promptCacheRetention ?? (retention === 'long' && compat.supportsLongCacheRetention !== false ? '24h' : undefined)
109
- // Pi's flag is route/model proof that prompt_cache_options is accepted; no mode keeps implicit caching.
110
- const currentCache = retention === 'short' && compat.supportsExplicitPromptCacheMode === true
111
- const explicitCache = retention === 'none' && compat.supportsExplicitPromptCacheMode === true
112
- const promptCacheOptions = currentCache ? { ttl: '30m' } : explicitCache ? { mode: 'explicit' } : undefined
113
- const nativeTools = responsesTools(tools)
114
- /** @type {UnknownRecord} */
115
- const body = {
116
- model: modelId(model),
117
- input: structuredClone(input),
118
- stream: true,
119
- store: false,
120
- ...(instructions === undefined ? {} : { instructions }),
121
- ...(nativeTools !== undefined && nativeTools.length > 0 ? { tools: nativeTools } : {}),
122
- ...(cacheKey ? { prompt_cache_key: cacheKey } : {}),
123
- ...(longRetention ? { prompt_cache_retention: longRetention } : {}),
124
- ...(promptCacheOptions ? { prompt_cache_options: promptCacheOptions } : {}),
125
- ...responsesGenerationEnvelope({ model: descriptor, reasoningEffort, temperature, maxTokens, includeDefaultReasoning: true }),
126
- }
127
- if (isObject(samplingParams)) Object.assign(body, structuredClone(samplingParams))
128
- return body
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
- const body = /** @type {UnknownRecord & { input: unknown[] }} */ (buildResponsesBody(options))
137
- if (body.input.some((item) => /** @type {UnknownRecord | undefined} */ (item)?.type === 'compaction_trigger')) {
138
- throw Object.assign(new Error('native compaction input already contains compaction_trigger'), { code: 'LCX_COMPACT_DUPLICATE_TRIGGER' })
139
- }
140
- body.input = [...body.input, { type: 'compaction_trigger' }]
141
- // Remote Compaction V2 has historically required these explicit controls.
142
- body.tool_choice = 'auto'
143
- body.parallel_tool_calls = true
144
- return body
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
  }