lody 0.93.2 → 0.94.0

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,429 @@
1
+ import { pathToFileURL } from "node:url";
2
+ const DEEPSEEK_HARNESS_PERMISSION_PRESETS = [
3
+ {
4
+ id: "read-only",
5
+ name: "Read-only",
6
+ description: "Read inside the workspace; protected writes require one-time approval.",
7
+ sandbox: "read-only",
8
+ approval: "ask"
9
+ },
10
+ {
11
+ id: "workspace-write",
12
+ name: "Workspace write",
13
+ description: "Read and write inside the workspace; wider access requires one-time approval.",
14
+ sandbox: "workspace-write",
15
+ approval: "ask"
16
+ },
17
+ {
18
+ id: "danger-full-access",
19
+ name: "Full access",
20
+ description: "Allow unrestricted file and command access without approval prompts.",
21
+ sandbox: "danger-full-access",
22
+ approval: "never"
23
+ }
24
+ ];
25
+ const DEEPSEEK_HARNESS_DEFAULT_PERMISSION_PRESET = "workspace-write";
26
+ const DEEPSEEK_HARNESS_PERMISSION_MODES = DEEPSEEK_HARNESS_PERMISSION_PRESETS.map(({ id, name, description }) => ({ id, name, description }));
27
+ const DEEPSEEK_HARNESS_API_KEY_ENV = "DEEPSEEK_API_KEY";
28
+ const DEEPSEEK_HARNESS_BASE_URL_ENV = "DEEPSEEK_BASE_URL";
29
+ const DEEPSEEK_HARNESS_AGENT_PRESETS = [
30
+ {
31
+ value: "standard",
32
+ name: "Standard mode",
33
+ description: "Full coding agent with file editing, shell, search, skills, planning, goals, subagents, and workflows."
34
+ },
35
+ {
36
+ value: "ptc",
37
+ name: "PTC mode",
38
+ description: "Full coding agent without the workflow tools; other tools are exposed through the PTC SDK so one TypeScript program composes multi-step work."
39
+ },
40
+ {
41
+ value: "minimal",
42
+ name: "Minimal mode",
43
+ description: "Single-tool coding agent with a persistent shell."
44
+ },
45
+ {
46
+ value: "cordis",
47
+ name: "Creator mode",
48
+ description: "Standard capabilities plus runtime inspection, plugin experiments, and preset-authoring guidance."
49
+ }
50
+ ];
51
+ const ACP_EXTENSION_DSH_VERSION = "0.2.0";
52
+ const DEEPSEEK_HARNESS_VERSION = "0.1.5-rc.2";
53
+ const ACP_EXTENSION_DSH_PROFILE_REVISION = "v12";
54
+ const ACP_EXTENSION_DSH_SESSION_ROOT_ENV = "ACP_EXTENSION_DSH_SESSION_ROOT";
55
+ const ACP_EXTENSION_DSH_QUERY_PATH_ENV = "ACP_EXTENSION_DSH_QUERY_PATH";
56
+ const DEEPSEEK_HARNESS_DEFAULT_SESSION_COMPRESSION = "zstd";
57
+ const DEEPSEEK_HARNESS_PROFILE_NAME = "lody-acp";
58
+ const DEEPSEEK_HARNESS_PROFILE_BUNDLES = ["@deepseek-ai/dsh-base"];
59
+ const DEEPSEEK_HARNESS_PROVIDER = "deepseek-official";
60
+ const DEEPSEEK_HARNESS_DEFAULT_MODEL = "deepseek-flash";
61
+ const ACP_EXTENSION_DSH_CAPABILITY_SOURCE_VERSION = `acp-extension-dsh@${ACP_EXTENSION_DSH_VERSION}:dsh@${DEEPSEEK_HARNESS_VERSION}:profile-${ACP_EXTENSION_DSH_PROFILE_REVISION}`;
62
+ const DEEPSEEK_HARNESS_NPX_PACKAGES = [
63
+ "@deepseek-ai/dsh",
64
+ "@deepseek-ai/cordis",
65
+ "@deepseek-ai/cordis-plugin-group",
66
+ "@deepseek-ai/cordis-plugin-hmr",
67
+ "@deepseek-ai/cordis-plugin-include",
68
+ "@deepseek-ai/cordis-plugin-loader",
69
+ "@deepseek-ai/cordis-plugin-timer",
70
+ "@deepseek-ai/dsh-acp",
71
+ "@deepseek-ai/dsh-acp-app",
72
+ "@deepseek-ai/dsh-agent",
73
+ "@deepseek-ai/dsh-agent-default-model",
74
+ "@deepseek-ai/dsh-agent-instructions",
75
+ "@deepseek-ai/dsh-agent-loop",
76
+ "@deepseek-ai/dsh-agent-presets",
77
+ "@deepseek-ai/dsh-agent-tool-presentation",
78
+ "@deepseek-ai/dsh-anonymous-user-id",
79
+ "@deepseek-ai/dsh-api-gateway",
80
+ "@deepseek-ai/dsh-api-remotes",
81
+ "@deepseek-ai/dsh-api-session-controller",
82
+ "@deepseek-ai/dsh-api-settings-controller",
83
+ "@deepseek-ai/dsh-api-workspace-controller",
84
+ "@deepseek-ai/dsh-api-workspace-files",
85
+ "@deepseek-ai/dsh-app-boot",
86
+ "@deepseek-ai/dsh-atomic-write",
87
+ "@deepseek-ai/dsh-attachment",
88
+ "@deepseek-ai/dsh-attachment-local",
89
+ "@deepseek-ai/dsh-authorization",
90
+ "@deepseek-ai/dsh-base",
91
+ "@deepseek-ai/dsh-bash-local",
92
+ "@deepseek-ai/dsh-bash-sandbox",
93
+ "@deepseek-ai/dsh-brand",
94
+ "@deepseek-ai/dsh-chunked-list",
95
+ "@deepseek-ai/dsh-client-connection",
96
+ "@deepseek-ai/dsh-client-file-upload",
97
+ "@deepseek-ai/dsh-client-hmr",
98
+ "@deepseek-ai/dsh-client-locale",
99
+ "@deepseek-ai/dsh-client-modules",
100
+ "@deepseek-ai/dsh-client-resources",
101
+ "@deepseek-ai/dsh-client-ui-agent-preset",
102
+ "@deepseek-ai/dsh-client-ui-approval",
103
+ "@deepseek-ai/dsh-client-ui-attachment",
104
+ "@deepseek-ai/dsh-client-ui-brand-official",
105
+ "@deepseek-ai/dsh-client-ui-chat",
106
+ "@deepseek-ai/dsh-client-ui-commands",
107
+ "@deepseek-ai/dsh-client-ui-conversation",
108
+ "@deepseek-ai/dsh-client-ui-cordis",
109
+ "@deepseek-ai/dsh-client-ui-deliverables",
110
+ "@deepseek-ai/dsh-client-ui-directory-picker-browse",
111
+ "@deepseek-ai/dsh-client-ui-directory-picker-native",
112
+ "@deepseek-ai/dsh-client-ui-goal",
113
+ "@deepseek-ai/dsh-client-ui-input-trigger",
114
+ "@deepseek-ai/dsh-client-ui-jobs",
115
+ "@deepseek-ai/dsh-client-ui-layout",
116
+ "@deepseek-ai/dsh-client-ui-message-feedback",
117
+ "@deepseek-ai/dsh-client-ui-model-selection",
118
+ "@deepseek-ai/dsh-client-ui-open-in-app",
119
+ "@deepseek-ai/dsh-client-ui-permission-presets",
120
+ "@deepseek-ai/dsh-client-ui-plan",
121
+ "@deepseek-ai/dsh-client-ui-reference",
122
+ "@deepseek-ai/dsh-client-ui-renderer",
123
+ "@deepseek-ai/dsh-client-ui-schedule",
124
+ "@deepseek-ai/dsh-client-ui-session",
125
+ "@deepseek-ai/dsh-client-ui-settings",
126
+ "@deepseek-ai/dsh-client-ui-settings-general",
127
+ "@deepseek-ai/dsh-client-ui-settings-models",
128
+ "@deepseek-ai/dsh-client-ui-settings-plugin-inventory",
129
+ "@deepseek-ai/dsh-client-ui-settings-plugins",
130
+ "@deepseek-ai/dsh-client-ui-sidebar",
131
+ "@deepseek-ai/dsh-client-ui-sidebar-documentpreview",
132
+ "@deepseek-ai/dsh-client-ui-sidebar-files",
133
+ "@deepseek-ai/dsh-client-ui-sidebar-right",
134
+ "@deepseek-ai/dsh-client-ui-skill",
135
+ "@deepseek-ai/dsh-client-ui-subagent",
136
+ "@deepseek-ai/dsh-client-ui-theme",
137
+ "@deepseek-ai/dsh-client-ui-tool",
138
+ "@deepseek-ai/dsh-client-ui-trajectory",
139
+ "@deepseek-ai/dsh-client-ui-user-questions",
140
+ "@deepseek-ai/dsh-client-ui-workflow-run",
141
+ "@deepseek-ai/dsh-client-ui-workspace",
142
+ "@deepseek-ai/dsh-cmdline",
143
+ "@deepseek-ai/dsh-code-runtime",
144
+ "@deepseek-ai/dsh-code-runtime-worker-thread",
145
+ "@deepseek-ai/dsh-command-compact",
146
+ "@deepseek-ai/dsh-command-feedback",
147
+ "@deepseek-ai/dsh-command-goal",
148
+ "@deepseek-ai/dsh-commands",
149
+ "@deepseek-ai/dsh-compaction",
150
+ "@deepseek-ai/dsh-compaction-basic",
151
+ "@deepseek-ai/dsh-compaction-tool-result-pruner",
152
+ "@deepseek-ai/dsh-cordis-client-runner",
153
+ "@deepseek-ai/dsh-cordis-host-runner",
154
+ "@deepseek-ai/dsh-credentials",
155
+ "@deepseek-ai/dsh-credentials-local",
156
+ "@deepseek-ai/dsh-deepseek-llm-api-extensions",
157
+ "@deepseek-ai/dsh-deque",
158
+ "@deepseek-ai/dsh-file-reference",
159
+ "@deepseek-ai/dsh-file-reference-local",
160
+ "@deepseek-ai/dsh-fs",
161
+ "@deepseek-ai/dsh-fs-local",
162
+ "@deepseek-ai/dsh-fs-observation-policy",
163
+ "@deepseek-ai/dsh-fs-sandbox",
164
+ "@deepseek-ai/dsh-goal",
165
+ "@deepseek-ai/dsh-goal-round-driver",
166
+ "@deepseek-ai/dsh-headless",
167
+ "@deepseek-ai/dsh-home-paths",
168
+ "@deepseek-ai/dsh-hook-protocol",
169
+ "@deepseek-ai/dsh-hooks-claude-code",
170
+ "@deepseek-ai/dsh-hooks-codex",
171
+ "@deepseek-ai/dsh-host-directory-picker",
172
+ "@deepseek-ai/dsh-host-directory-picker-auto",
173
+ "@deepseek-ai/dsh-host-directory-picker-browse",
174
+ "@deepseek-ai/dsh-host-directory-picker-native",
175
+ "@deepseek-ai/dsh-host-frontend-static",
176
+ "@deepseek-ai/dsh-host-open-in-app",
177
+ "@deepseek-ai/dsh-host-plugin-inventory",
178
+ "@deepseek-ai/dsh-host-webserver",
179
+ "@deepseek-ai/dsh-http-proxy",
180
+ "@deepseek-ai/dsh-invariants",
181
+ "@deepseek-ai/dsh-jobs",
182
+ "@deepseek-ai/dsh-jobs-local",
183
+ "@deepseek-ai/dsh-launch-environment",
184
+ "@deepseek-ai/dsh-llm",
185
+ "@deepseek-ai/dsh-llm-deepseek",
186
+ "@deepseek-ai/dsh-llm-pi-ai",
187
+ "@deepseek-ai/dsh-llm-retry",
188
+ "@deepseek-ai/dsh-mcp-client",
189
+ "@deepseek-ai/dsh-message-feedback",
190
+ "@deepseek-ai/dsh-native-command",
191
+ "@deepseek-ai/dsh-output-retention",
192
+ "@deepseek-ai/dsh-package-manifest",
193
+ "@deepseek-ai/dsh-permission-presets",
194
+ "@deepseek-ai/dsh-persona",
195
+ "@deepseek-ai/dsh-plan-mode",
196
+ "@deepseek-ai/dsh-plugin-package-inventory-deepseek",
197
+ "@deepseek-ai/dsh-pwsh-local",
198
+ "@deepseek-ai/dsh-pwsh-sandbox",
199
+ "@deepseek-ai/dsh-repeat-tool-reminder",
200
+ "@deepseek-ai/dsh-sandbox",
201
+ "@deepseek-ai/dsh-sandbox-local",
202
+ "@deepseek-ai/dsh-sandbox-policy",
203
+ "@deepseek-ai/dsh-sandbox-windows-acl",
204
+ "@deepseek-ai/dsh-schedule",
205
+ "@deepseek-ai/dsh-scope",
206
+ "@deepseek-ai/dsh-sdk-app",
207
+ "@deepseek-ai/dsh-sdk-jsonrpc-server",
208
+ "@deepseek-ai/dsh-sdk-minimal",
209
+ "@deepseek-ai/dsh-sdk-protocol",
210
+ "@deepseek-ai/dsh-session",
211
+ "@deepseek-ai/dsh-session-checkpoint-policy",
212
+ "@deepseek-ai/dsh-session-format",
213
+ "@deepseek-ai/dsh-session-format-catalog",
214
+ "@deepseek-ai/dsh-session-format-v0-to-v1",
215
+ "@deepseek-ai/dsh-session-format-v1-to-v2",
216
+ "@deepseek-ai/dsh-session-format-v2-to-v3",
217
+ "@deepseek-ai/dsh-session-log-deepseek",
218
+ "@deepseek-ai/dsh-session-log-export",
219
+ "@deepseek-ai/dsh-session-persistence",
220
+ "@deepseek-ai/dsh-session-persistence-jsonl",
221
+ "@deepseek-ai/dsh-session-projection",
222
+ "@deepseek-ai/dsh-session-projection-cache",
223
+ "@deepseek-ai/dsh-session-query",
224
+ "@deepseek-ai/dsh-session-query-sqlite",
225
+ "@deepseek-ai/dsh-session-reference",
226
+ "@deepseek-ai/dsh-session-stats",
227
+ "@deepseek-ai/dsh-session-telemetry",
228
+ "@deepseek-ai/dsh-session-telemetry-otel",
229
+ "@deepseek-ai/dsh-session-title",
230
+ "@deepseek-ai/dsh-session-title-first-prompt-llm",
231
+ "@deepseek-ai/dsh-session-title-llm",
232
+ "@deepseek-ai/dsh-session-turn-outline",
233
+ "@deepseek-ai/dsh-settings",
234
+ "@deepseek-ai/dsh-settings-file",
235
+ "@deepseek-ai/dsh-shell",
236
+ "@deepseek-ai/dsh-shell-env",
237
+ "@deepseek-ai/dsh-skill",
238
+ "@deepseek-ai/dsh-skill-badge",
239
+ "@deepseek-ai/dsh-skill-filesystem",
240
+ "@deepseek-ai/dsh-spill",
241
+ "@deepseek-ai/dsh-spill-local",
242
+ "@deepseek-ai/dsh-spill-policy",
243
+ "@deepseek-ai/dsh-storage",
244
+ "@deepseek-ai/dsh-storage-domain",
245
+ "@deepseek-ai/dsh-storage-json",
246
+ "@deepseek-ai/dsh-subagent",
247
+ "@deepseek-ai/dsh-subagent-fork-in-process",
248
+ "@deepseek-ai/dsh-subagent-in-process-driver",
249
+ "@deepseek-ai/dsh-subagent-spawn-in-process",
250
+ "@deepseek-ai/dsh-subprocess",
251
+ "@deepseek-ai/dsh-subprocess-local",
252
+ "@deepseek-ai/dsh-system-prompt",
253
+ "@deepseek-ai/dsh-terminal",
254
+ "@deepseek-ai/dsh-terminal-bash",
255
+ "@deepseek-ai/dsh-time-context",
256
+ "@deepseek-ai/dsh-timeout",
257
+ "@deepseek-ai/dsh-tmux-context",
258
+ "@deepseek-ai/dsh-token-meter",
259
+ "@deepseek-ai/dsh-tool-ask-user",
260
+ "@deepseek-ai/dsh-tool-bash",
261
+ "@deepseek-ai/dsh-tool-bash-persistent",
262
+ "@deepseek-ai/dsh-tool-call-timeout-policy",
263
+ "@deepseek-ai/dsh-tool-cordis",
264
+ "@deepseek-ai/dsh-tool-fs",
265
+ "@deepseek-ai/dsh-tool-fs-search",
266
+ "@deepseek-ai/dsh-tool-goal",
267
+ "@deepseek-ai/dsh-tool-jobs",
268
+ "@deepseek-ai/dsh-tool-present",
269
+ "@deepseek-ai/dsh-tool-pwsh",
270
+ "@deepseek-ai/dsh-tool-pwsh-persistent",
271
+ "@deepseek-ai/dsh-tool-ralph",
272
+ "@deepseek-ai/dsh-tool-skill",
273
+ "@deepseek-ai/dsh-tool-str-replace-editor",
274
+ "@deepseek-ai/dsh-tool-subagent",
275
+ "@deepseek-ai/dsh-tool-subagent-control",
276
+ "@deepseek-ai/dsh-tool-todo",
277
+ "@deepseek-ai/dsh-tool-web",
278
+ "@deepseek-ai/dsh-tool-workflow",
279
+ "@deepseek-ai/dsh-tools",
280
+ "@deepseek-ai/dsh-typert-loader",
281
+ "@deepseek-ai/dsh-typert-protocol",
282
+ "@deepseek-ai/dsh-typert-registry",
283
+ "@deepseek-ai/dsh-user-approval",
284
+ "@deepseek-ai/dsh-user-questions",
285
+ "@deepseek-ai/dsh-util-crypto",
286
+ "@deepseek-ai/dsh-util-time",
287
+ "@deepseek-ai/dsh-util-values",
288
+ "@deepseek-ai/dsh-util-workspace-path",
289
+ "@deepseek-ai/dsh-web",
290
+ "@deepseek-ai/dsh-web-app",
291
+ "@deepseek-ai/dsh-web-fetch-http",
292
+ "@deepseek-ai/dsh-web-frontend",
293
+ "@deepseek-ai/dsh-web-search-deepseek",
294
+ "@deepseek-ai/dsh-webhook",
295
+ "@deepseek-ai/dsh-webhook-github",
296
+ "@deepseek-ai/dsh-win32-process",
297
+ "@deepseek-ai/dsh-workflow",
298
+ "@deepseek-ai/dsh-workflow-worker-thread",
299
+ "@deepseek-ai/dsh-workspace"
300
+ ];
301
+ const DEEPSEEK_HARNESS_CORDIS_PACKAGE_VERSIONS = {
302
+ "@deepseek-ai/cordis": "4.0.2",
303
+ "@deepseek-ai/cordis-plugin-group": "1.0.2",
304
+ "@deepseek-ai/cordis-plugin-hmr": "1.0.17",
305
+ "@deepseek-ai/cordis-plugin-include": "1.0.7",
306
+ "@deepseek-ai/cordis-plugin-loader": "1.0.3",
307
+ "@deepseek-ai/cordis-plugin-timer": "1.1.4"
308
+ };
309
+ function createDeepSeekHarnessNpxSpecifiers(versions = DEEPSEEK_HARNESS_CORDIS_PACKAGE_VERSIONS) {
310
+ return DEEPSEEK_HARNESS_NPX_PACKAGES.map((packageName) => `${packageName}@${versions[packageName] ?? DEEPSEEK_HARNESS_VERSION}`);
311
+ }
312
+ function toAdapterModuleSpecifier(adapterPath, windows = process.platform === "win32") {
313
+ if (adapterPath.startsWith("file:"))
314
+ return adapterPath;
315
+ return pathToFileURL(adapterPath, { windows }).href;
316
+ }
317
+ const PROFILE_PNPM_WORKSPACE = "packages:\n - .\n\nnodeLinker: hoisted\nautoInstallPeers: false\n";
318
+ function createDeepSeekHarnessProfileFiles(config) {
319
+ const provider = config.provider?.trim() || DEEPSEEK_HARNESS_PROVIDER;
320
+ const model = config.model?.trim() || DEEPSEEK_HARNESS_DEFAULT_MODEL;
321
+ const compression = config.sessionCompression ?? DEEPSEEK_HARNESS_DEFAULT_SESSION_COMPRESSION;
322
+ const adapterPath = JSON.stringify(toAdapterModuleSpecifier(config.adapterPath));
323
+ const presetRoot = JSON.stringify(config.presetRoot);
324
+ const permissionPresets = DEEPSEEK_HARNESS_PERMISSION_PRESETS.map((preset) => ` ${preset.id}:
325
+ sandbox: ${preset.sandbox}
326
+ approval: ${preset.approval}
327
+ name: ${preset.name}
328
+ description: ${preset.description}`).join("\n");
329
+ const packageJson = JSON.stringify({
330
+ name: `dsh-profile-${DEEPSEEK_HARNESS_PROFILE_NAME}`,
331
+ private: true,
332
+ dependencies: {},
333
+ dsh: {
334
+ profile: {
335
+ bundles: [...DEEPSEEK_HARNESS_PROFILE_BUNDLES],
336
+ patchReload: "startup"
337
+ }
338
+ }
339
+ }, null, 2) + "\n";
340
+ const cordisYml = "[]\n";
341
+ const cordisPatchYml = `# Generated by acp-extension-dsh ${ACP_EXTENSION_DSH_VERSION} for DeepSeek Harness ${DEEPSEEK_HARNESS_VERSION}.
342
+ # API credentials stay in the host environment; never inline them here.
343
+
344
+ # The ACP host owns no telemetry or product inventory rows.
345
+ - id: session-telemetry-otel
346
+ disabled: true
347
+
348
+ - id: plugin-package-inventory-deepseek
349
+ disabled: true
350
+
351
+ - id: session-log-deepseek
352
+ disabled: true
353
+
354
+ # Titles come from the client; do not spend a model call on the first prompt.
355
+ - id: session-title-llm
356
+ disabled: true
357
+
358
+ # Keep sessions and the exact-read query index on Lody's own roots.
359
+ - id: session-persistence-jsonl
360
+ config:
361
+ root: !!js process.env.${ACP_EXTENSION_DSH_SESSION_ROOT_ENV}
362
+ compression: ${compression}
363
+
364
+ - id: session-query-sqlite
365
+ config:
366
+ path: !!js process.env.${ACP_EXTENSION_DSH_QUERY_PATH_ENV}
367
+ openAt: never
368
+
369
+ # The agent factory default for any preset-created child.
370
+ - id: agent-default-model
371
+ config:
372
+ provider: ${JSON.stringify(provider)}
373
+ model: ${JSON.stringify(model)}
374
+
375
+ # Preserve the product's three permission modes with client-facing labels.
376
+ - id: permission
377
+ config:
378
+ defaultPreset: ${DEEPSEEK_HARNESS_DEFAULT_PERMISSION_PRESET}
379
+ presets:
380
+ ${permissionPresets}
381
+
382
+ - insert:
383
+ - id: agent-presets
384
+ name: '@deepseek-ai/dsh-agent-presets'
385
+ config:
386
+ default: standard
387
+ includeShippedRoot: false
388
+ includeUserRoot: true
389
+ roots:
390
+ - path: ${presetRoot}
391
+ trust: system
392
+
393
+ # The shipped presets' delegation group resolves this host-scope opt-in.
394
+ - id: subagent-model-selection-settings
395
+ name: '@deepseek-ai/dsh-tool-subagent/model-selection-settings'
396
+
397
+ - id: acp-agent
398
+ name: ${adapterPath}
399
+ inject: [settings]
400
+ config:
401
+ provider: ${JSON.stringify(provider)}
402
+ model: ${JSON.stringify(model)}${config.reasoningEffort ? `
403
+ reasoningEffort: ${JSON.stringify(config.reasoningEffort)}` : ""}
404
+ `;
405
+ return { packageJson, cordisYml, cordisPatchYml, pnpmWorkspaceYaml: PROFILE_PNPM_WORKSPACE };
406
+ }
407
+ const DEEPSEEK_HARNESS_PROFILE_FILENAMES = {
408
+ packageJson: "package.json",
409
+ cordisYml: "cordis.yml",
410
+ cordisPatchYml: "cordis.patch.yml",
411
+ pnpmWorkspaceYaml: "pnpm-workspace.yaml"
412
+ };
413
+ export {
414
+ ACP_EXTENSION_DSH_CAPABILITY_SOURCE_VERSION as A,
415
+ DEEPSEEK_HARNESS_PERMISSION_MODES as D,
416
+ DEEPSEEK_HARNESS_AGENT_PRESETS as a,
417
+ DEEPSEEK_HARNESS_PROFILE_NAME as b,
418
+ createDeepSeekHarnessProfileFiles as c,
419
+ DEEPSEEK_HARNESS_PROFILE_FILENAMES as d,
420
+ ACP_EXTENSION_DSH_QUERY_PATH_ENV as e,
421
+ ACP_EXTENSION_DSH_SESSION_ROOT_ENV as f,
422
+ createDeepSeekHarnessNpxSpecifiers as g,
423
+ DEEPSEEK_HARNESS_DEFAULT_SESSION_COMPRESSION as h,
424
+ DEEPSEEK_HARNESS_BASE_URL_ENV as i,
425
+ DEEPSEEK_HARNESS_API_KEY_ENV as j,
426
+ ACP_EXTENSION_DSH_VERSION as k,
427
+ DEEPSEEK_HARNESS_DEFAULT_MODEL as l,
428
+ DEEPSEEK_HARNESS_PROVIDER as m
429
+ };
@@ -27,13 +27,14 @@ import "https";
27
27
  import "node:util";
28
28
  import "node:zlib";
29
29
  import "child_process";
30
+ import "./plan-mode-BLOER-fv.js";
31
+ import "./profile-6mKAZyTP.js";
32
+ import "node:url";
30
33
  import { __tla as __tla_1 } from "./loro_wasm_bg-Br-Fa9wV.js";
31
34
  import "perf_hooks";
32
35
  import "net";
33
36
  import "tls";
34
37
  import "url";
35
- import "./plan-mode-BLOER-fv.js";
36
- import "./profile-Dv5auBPt.js";
37
38
  import "assert";
38
39
  import "fs/promises";
39
40
  import "better-sqlite3";
@@ -48,7 +49,6 @@ import "node:tls";
48
49
  import "node:perf_hooks";
49
50
  import "node:util/types";
50
51
  import "node:worker_threads";
51
- import "node:url";
52
52
  import "node:console";
53
53
  import "node:dns";
54
54
  import "./directory-handle-35P9qcGk.js";
@@ -81,7 +81,7 @@ let __tla = Promise.all([
81
81
  }
82
82
  })()
83
83
  ]).then(async () => {
84
- const reviewViewerVersion = "0.93.2";
84
+ const reviewViewerVersion = "0.94.0";
85
85
  const reviewViewerSha256 = "dc9c7fc1dde49bb39c5fe86392d69219b469c0cab4fd492d8b562045e7f676e4";
86
86
  const reviewViewerFileName = "standalone.html";
87
87
  const DEFAULT_CDN_BASES = [
@@ -0,0 +1,69 @@
1
+ const counters = [
2
+ "inputTokens",
3
+ "outputTokens",
4
+ "cacheReadInputTokens",
5
+ "cacheCreationInputTokens",
6
+ "reasoningOutputTokens",
7
+ "webSearchRequests"
8
+ ];
9
+ const emptyUsage = () => ({ inputTokens: 0, outputTokens: 0, cacheReadInputTokens: 0 });
10
+ function sumModelUsage(rows) {
11
+ const result = emptyUsage();
12
+ const values = Object.values(rows);
13
+ for (const row of values) {
14
+ for (const key of counters)
15
+ result[key] = (result[key] ?? 0) + (row[key] ?? 0);
16
+ }
17
+ if (values.length > 0 && values.every((row) => row.costUSD !== void 0)) {
18
+ result.costUSD = values.reduce((sum, row) => sum + (row.costUSD ?? 0), 0);
19
+ }
20
+ return result;
21
+ }
22
+ class SessionUsageAccumulator {
23
+ operations = /* @__PURE__ */ new Map();
24
+ totals = {};
25
+ update(sessionId, operationId, rows) {
26
+ const previous = this.operations.get(operationId) ?? {};
27
+ const merged = Object.assign(/* @__PURE__ */ Object.create(null), structuredClone(previous));
28
+ for (const [model, row] of Object.entries(rows)) {
29
+ const next2 = merged[model] ?? emptyUsage();
30
+ for (const key of counters)
31
+ next2[key] = Math.max(next2[key] ?? 0, row[key] ?? 0);
32
+ if (row.costUSD !== void 0)
33
+ next2.costUSD = Math.max(next2.costUSD ?? 0, row.costUSD);
34
+ merged[model] = next2;
35
+ }
36
+ if (JSON.stringify(previous) === JSON.stringify(merged))
37
+ return void 0;
38
+ this.operations.set(operationId, merged);
39
+ const grouped = /* @__PURE__ */ Object.create(null);
40
+ for (const [id, models] of this.operations) {
41
+ for (const [model, row] of Object.entries(models))
42
+ (grouped[model] ??= /* @__PURE__ */ Object.create(null))[id] = row;
43
+ }
44
+ const next = /* @__PURE__ */ Object.create(null);
45
+ const delta = /* @__PURE__ */ Object.create(null);
46
+ for (const [model, contributions] of Object.entries(grouped)) {
47
+ const total = sumModelUsage(contributions);
48
+ next[model] = total;
49
+ const old = this.totals[model];
50
+ const difference = emptyUsage();
51
+ for (const key of counters)
52
+ difference[key] = (total[key] ?? 0) - (old?.[key] ?? 0);
53
+ if (total.costUSD !== void 0 && (!old || old.costUSD !== void 0)) {
54
+ difference.costUSD = total.costUSD - (old?.costUSD ?? 0);
55
+ }
56
+ delta[model] = difference;
57
+ }
58
+ this.totals = next;
59
+ return structuredClone({
60
+ sessionId,
61
+ usage: sumModelUsage(merged),
62
+ modelUsage: next,
63
+ delta: { usage: sumModelUsage(delta), modelUsage: delta }
64
+ });
65
+ }
66
+ }
67
+ export {
68
+ SessionUsageAccumulator as S
69
+ };
@@ -68082,6 +68082,64 @@ ${content.text}
68082
68082
  }
68083
68083
  logger.error(`Unexpected case: ${valueAsString}`);
68084
68084
  }
68085
+ function toAccountingModelUsage(usage) {
68086
+ return {
68087
+ inputTokens: usage.inputTokens,
68088
+ outputTokens: Math.max(0, usage.outputTokens - (usage.thinkingTokens ?? 0)),
68089
+ cacheReadInputTokens: usage.cacheReadInputTokens,
68090
+ cacheCreationInputTokens: usage.cacheCreationInputTokens,
68091
+ ...usage.thinkingTokens === void 0 ? {} : {
68092
+ reasoningOutputTokens: usage.thinkingTokens
68093
+ },
68094
+ webSearchRequests: usage.webSearchRequests,
68095
+ ...usage.costBasis === "unknown" ? {} : {
68096
+ costUSD: usage.costUSD
68097
+ },
68098
+ contextWindow: usage.contextWindow
68099
+ };
68100
+ }
68101
+ function accountingDelta(current, previous = {}) {
68102
+ const keys = [
68103
+ "inputTokens",
68104
+ "outputTokens",
68105
+ "cacheReadInputTokens",
68106
+ "cacheCreationInputTokens",
68107
+ "reasoningOutputTokens",
68108
+ "webSearchRequests"
68109
+ ];
68110
+ const usage = {
68111
+ inputTokens: 0,
68112
+ outputTokens: 0,
68113
+ cacheReadInputTokens: 0
68114
+ };
68115
+ const modelUsage = {};
68116
+ let knownCost = Object.keys(current).length > 0;
68117
+ let cost = 0;
68118
+ for (const [model, row] of Object.entries(current)) {
68119
+ const old = previous[model];
68120
+ const delta = {
68121
+ inputTokens: 0,
68122
+ outputTokens: 0,
68123
+ cacheReadInputTokens: 0
68124
+ };
68125
+ for (const key of keys) {
68126
+ const difference = (row[key] ?? 0) - (old?.[key] ?? 0);
68127
+ if (difference < 0) return void 0;
68128
+ delta[key] = difference;
68129
+ usage[key] = (usage[key] ?? 0) + difference;
68130
+ }
68131
+ if (row.costUSD !== void 0 && (!old || old.costUSD !== void 0) && row.costUSD >= (old?.costUSD ?? 0)) {
68132
+ delta.costUSD = row.costUSD - (old?.costUSD ?? 0);
68133
+ cost += delta.costUSD;
68134
+ } else knownCost = false;
68135
+ modelUsage[model] = delta;
68136
+ }
68137
+ if (knownCost) usage.costUSD = cost;
68138
+ return {
68139
+ usage,
68140
+ modelUsage
68141
+ };
68142
+ }
68085
68143
  const ScopedWeeklyLimitSchema = object({
68086
68144
  kind: literal("weekly_scoped"),
68087
68145
  percent: number(),
@@ -70333,25 +70391,15 @@ ${explanation}` : fallbackSummary;
70333
70391
  }
70334
70392
  });
70335
70393
  }
70336
- if (session.cancelled) {
70337
- if (!isAutonomousResult) {
70338
- await clearFailuresFromEarlierTurns();
70339
- stopReason = "cancelled";
70340
- }
70341
- break;
70342
- }
70343
70394
  const extNotification = this.client.extNotification?.bind(this.client);
70344
70395
  if (extNotification) {
70345
70396
  const modelUsage = {};
70346
70397
  for (const [model, usage] of Object.entries(message.modelUsage)) {
70347
- modelUsage[model] = {
70348
- inputTokens: usage.inputTokens,
70349
- outputTokens: usage.outputTokens,
70350
- cacheReadInputTokens: usage.cacheReadInputTokens,
70351
- cacheCreationInputTokens: usage.cacheCreationInputTokens,
70352
- webSearchRequests: usage.webSearchRequests,
70353
- costUSD: usage.costUSD
70354
- };
70398
+ modelUsage[model] = toAccountingModelUsage(usage);
70399
+ if (usage.costBasis === "unknown") {
70400
+ (session.unknownUsageCostModels ??= /* @__PURE__ */ new Set()).add(model);
70401
+ }
70402
+ if (session.unknownUsageCostModels?.has(model)) delete modelUsage[model].costUSD;
70355
70403
  }
70356
70404
  const usages = {
70357
70405
  sessionId: params.sessionId,
@@ -70361,14 +70409,23 @@ ${explanation}` : fallbackSummary;
70361
70409
  cacheCreationInputTokens: message.usage.cache_creation_input_tokens,
70362
70410
  cacheReadInputTokens: message.usage.cache_read_input_tokens
70363
70411
  },
70364
- modelUsage
70412
+ modelUsage,
70413
+ delta: accountingDelta(modelUsage, session.usageBaseline)
70365
70414
  };
70366
70415
  await extNotification(LODY_EXTENSION_METHODS.sessionUsageUpdate, usages);
70416
+ session.usageBaseline = modelUsage;
70367
70417
  const limits = await getUsage();
70368
70418
  if (limits) {
70369
70419
  await extNotification(LODY_EXTENSION_METHODS.rateLimitsUpdate, limits);
70370
70420
  }
70371
70421
  }
70422
+ if (session.cancelled) {
70423
+ if (!isAutonomousResult) {
70424
+ await clearFailuresFromEarlierTurns();
70425
+ stopReason = "cancelled";
70426
+ }
70427
+ break;
70428
+ }
70372
70429
  if (isAutonomousResult) {
70373
70430
  settleDeferredIfDrained();
70374
70431
  if (!session.activeTurn && !firstUnsettledQueuedTurn()) {
package/dist/codex-acp.js CHANGED
@@ -3,5 +3,5 @@
3
3
  console.error("CODEX_PATH is required for the bundled Codex ACP adapter.");
4
4
  process.exit(1);
5
5
  }
6
- await import("./chunks/index-Bxge7nr7.js");
6
+ await import("./chunks/index-rdPvrzqi.js");
7
7
  })();