lody 0.101.1 → 0.103.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.
@@ -1,5 +1,5 @@
1
1
  import { pathToFileURL } from "node:url";
2
- import { c as array, u as unknown, N as NEVER, e as union, n as number, s as string, o as object, r as record, Q as int, l as literal, b as boolean, E as intersection, H as url } from "./schemas-9JpFbIUJ.js";
2
+ import { c as array, u as unknown, N as NEVER, e as union, n as number, s as string, o as object, r as record, Q as int, l as literal, b as boolean, E as intersection, H as url } from "./schemas-WuyisFi9.js";
3
3
  const DEEPSEEK_HARNESS_PERMISSION_PRESETS = [
4
4
  {
5
5
  id: "read-only",
@@ -51,7 +51,9 @@ const DEEPSEEK_HARNESS_AGENT_PRESETS = [
51
51
  ];
52
52
  const ACP_EXTENSION_DSH_VERSION = "0.2.0";
53
53
  const DEEPSEEK_HARNESS_VERSION = "0.1.5-rc.2";
54
- const ACP_EXTENSION_DSH_PROFILE_REVISION = "v13";
54
+ const DEEPSEEK_HARNESS_PI_AI_VERSION = "0.85.1";
55
+ const DEEPSEEK_HARNESS_SCHEMASTERY_VERSION = "3.18.2";
56
+ const ACP_EXTENSION_DSH_PROFILE_REVISION = "v14";
55
57
  const ACP_EXTENSION_DSH_SESSION_ROOT_ENV = "ACP_EXTENSION_DSH_SESSION_ROOT";
56
58
  const ACP_EXTENSION_DSH_QUERY_PATH_ENV = "ACP_EXTENSION_DSH_QUERY_PATH";
57
59
  const DEEPSEEK_HARNESS_DEFAULT_SESSION_COMPRESSION = "zstd";
@@ -308,7 +310,11 @@ const DEEPSEEK_HARNESS_CORDIS_PACKAGE_VERSIONS = {
308
310
  "@deepseek-ai/cordis-plugin-timer": "1.1.4"
309
311
  };
310
312
  function createDeepSeekHarnessNpxSpecifiers(versions = DEEPSEEK_HARNESS_CORDIS_PACKAGE_VERSIONS) {
311
- return DEEPSEEK_HARNESS_NPX_PACKAGES.map((packageName) => `${packageName}@${versions[packageName] ?? DEEPSEEK_HARNESS_VERSION}`);
313
+ return [
314
+ ...DEEPSEEK_HARNESS_NPX_PACKAGES.map((packageName) => `${packageName}@${versions[packageName] ?? DEEPSEEK_HARNESS_VERSION}`),
315
+ `@earendil-works/pi-ai@${DEEPSEEK_HARNESS_PI_AI_VERSION}`,
316
+ `@deepseek-ai/schemastery@${DEEPSEEK_HARNESS_SCHEMASTERY_VERSION}`
317
+ ];
312
318
  }
313
319
  function toAdapterModuleSpecifier(adapterPath, windows = process.platform === "win32") {
314
320
  if (adapterPath.startsWith("file:"))
@@ -369,6 +375,14 @@ function createDeepSeekHarnessProfileFiles(config) {
369
375
  provider: ${JSON.stringify(provider)}
370
376
  model: ${JSON.stringify(model)}
371
377
 
378
+ # Dormant until llm-pi-ai.providers in settings.yaml declares a route. The
379
+ # upstream adapter owns profile validation, route lifecycle, and credentials.
380
+ - id: llm-pi-ai
381
+ name: '@deepseek-ai/dsh-llm-pi-ai'
382
+ inject: [settings]
383
+ config:
384
+ providers: {}
385
+
372
386
  # Preserve the product's three permission modes with client-facing labels.
373
387
  - id: permission
374
388
  config:
@@ -4929,4 +4943,4 @@ export {
4929
4943
  DEEPSEEK_HARNESS_DEFAULT_MODEL as q,
4930
4944
  DEEPSEEK_HARNESS_PROVIDER as r
4931
4945
  };
4932
- //# sourceMappingURL=acp-w0Ug9k0u.js.map
4946
+ //# sourceMappingURL=acp-BzvviK-N.js.map
@@ -2,7 +2,7 @@ import { spawn } from "node:child_process";
2
2
  import { mkdtemp, writeFile, rm } from "node:fs/promises";
3
3
  import { tmpdir } from "node:os";
4
4
  import { join } from "node:path";
5
- import { o as object, a as _enum, s as string } from "./schemas-9JpFbIUJ.js";
5
+ import { o as object, a as _enum, s as string } from "./schemas-WuyisFi9.js";
6
6
  class CloudflaredError extends Error {
7
7
  constructor(stage, message, cause) {
8
8
  super(message, { cause });
@@ -237,4 +237,4 @@ export {
237
237
  CloudflaredError as C,
238
238
  startCloudflaredNative as s
239
239
  };
240
- //# sourceMappingURL=cloudflared-native-BPe7OSUZ.js.map
240
+ //# sourceMappingURL=cloudflared-native-DbUToPHH.js.map
@@ -0,0 +1,97 @@
1
+ import { a as getSessionCommandEnvironment, b as getSessionRoomId, i as isLoroRepoDocDeleted, r as runWithMcpSessionContext, S as SessionToolResultSchema, c as buildSessionToolServer } from "../index.js";
2
+ import "path";
3
+ import "node:fs";
4
+ import "node:readline";
5
+ import "node:async_hooks";
6
+ import "fs";
7
+ import "crypto";
8
+ import "node:os";
9
+ import "node:path";
10
+ import "./schemas-WuyisFi9.js";
11
+ import "node:events";
12
+ import "node:child_process";
13
+ import "node:process";
14
+ import "node:tty";
15
+ import "os";
16
+ import "node:crypto";
17
+ import "util";
18
+ import "stream";
19
+ import "buffer";
20
+ import "events";
21
+ import "zlib";
22
+ import "tty";
23
+ import "string_decoder";
24
+ import "http";
25
+ import "https";
26
+ import "node:util";
27
+ import "node:fs/promises";
28
+ import "node:zlib";
29
+ import "child_process";
30
+ import "./plan-mode-D0D5cnMs.js";
31
+ import "./acp-BzvviK-N.js";
32
+ import "node:url";
33
+ import "./subagent-events-BJ9JwZva.js";
34
+ import "./loro_wasm_bg-DIxpLA2J.js";
35
+ import "perf_hooks";
36
+ import "net";
37
+ import "tls";
38
+ import "url";
39
+ import "assert";
40
+ import "fs/promises";
41
+ import "better-sqlite3";
42
+ import "node:diagnostics_channel";
43
+ import "node:assert";
44
+ import "node:net";
45
+ import "node:http";
46
+ import "node:stream";
47
+ import "node:buffer";
48
+ import "node:querystring";
49
+ import "node:tls";
50
+ import "node:perf_hooks";
51
+ import "node:util/types";
52
+ import "node:worker_threads";
53
+ import "node:console";
54
+ import "node:dns";
55
+ import "./directory-handle-CtdCjbNh.js";
56
+ import "./diff-line-counts-DDGc5P-T.js";
57
+ import "node:stream/promises";
58
+ import "node:string_decoder";
59
+ import "./package-BoOO46ct.js";
60
+ import "./session-DyqwlJbY.js";
61
+ import "async_hooks";
62
+ import "module";
63
+ import "./diff-worker-task-MZsLArT5.js";
64
+ import "./workspace-watch-protocol-POg9Lpeq.js";
65
+ import "node:dns/promises";
66
+ import "./cloudflared-native-DbUToPHH.js";
67
+ import "node:timers/promises";
68
+ import "node:module";
69
+ import "node:v8";
70
+ import "http2";
71
+ let handlers;
72
+ const getHandlers = () => {
73
+ if (!handlers) {
74
+ handlers = /* @__PURE__ */ new Map();
75
+ void buildSessionToolServer(handlers);
76
+ }
77
+ return handlers;
78
+ };
79
+ async function executeDaemonSessionTool(context, name, args) {
80
+ const environment = getSessionCommandEnvironment();
81
+ if (!environment || context.machineId !== environment.auth.machineId || context.workspaceId !== environment.workspace.id)
82
+ throw new Error("Session tool scope mismatch");
83
+ const invocation = environment.host.readInvocation(context.sessionId);
84
+ if (!invocation.active || invocation.requesterUserId !== environment.auth.userId)
85
+ throw new Error("Session tool requires an active local user Turn");
86
+ const row = await environment.manager.repo.getDocMeta(getSessionRoomId(context.sessionId));
87
+ if (!row?.meta || isLoroRepoDocDeleted(row) || row.meta.machineId !== environment.auth.machineId)
88
+ throw new Error("Requester Session does not belong to this machine");
89
+ const handler = getHandlers().get(name);
90
+ if (!handler) throw new Error(`Unsupported daemon Session tool: ${name}`);
91
+ const result = await runWithMcpSessionContext(context, () => handler(args));
92
+ return SessionToolResultSchema.parse({ type: "session/tool-result", ...result });
93
+ }
94
+ export {
95
+ executeDaemonSessionTool
96
+ };
97
+ //# sourceMappingURL=daemon-session-tools-DESvdAeY.js.map
@@ -1,4 +1,4 @@
1
- import { o as object, s as string, l as literal, b as boolean, a as _enum, e as union, n as number, d as discriminatedUnion, c as array, r as record, P as tuple, u as unknown } from "./schemas-9JpFbIUJ.js";
1
+ import { o as object, s as string, l as literal, b as boolean, a as _enum, e as union, n as number, d as discriminatedUnion, c as array, r as record, P as tuple, u as unknown } from "./schemas-WuyisFi9.js";
2
2
  import { execFile } from "node:child_process";
3
3
  import { readFile } from "node:fs/promises";
4
4
  import path__default from "node:path";
@@ -1178,4 +1178,4 @@ export {
1178
1178
  writeCodeCollabFileIndexToFlock as y,
1179
1179
  buildCodeCollabFileIndexState as z
1180
1180
  };
1181
- //# sourceMappingURL=directory-handle-CjQk33eZ.js.map
1181
+ //# sourceMappingURL=directory-handle-CtdCjbNh.js.map
@@ -27455,7 +27455,7 @@ var package_default = {
27455
27455
  },
27456
27456
  dependencies: {
27457
27457
  "@agentclientprotocol/sdk": "^1.4.0",
27458
- "@openai/codex": "^0.156.0",
27458
+ "@openai/codex": "^0.159.2",
27459
27459
  "acp-extension-core": "0.1.9",
27460
27460
  diff: "^9.0.0",
27461
27461
  open: "^11.0.1",
@@ -35224,4 +35224,4 @@ function startAcpServer() {
35224
35224
  }
35225
35225
  createCodexAcpApp({ name: package_default.name, createAgent }).connect(acpJsonStream);
35226
35226
  }
35227
- //# sourceMappingURL=index-C0n6fro1.js.map
35227
+ //# sourceMappingURL=index-DEdPzgH7.js.map
@@ -10,7 +10,7 @@ import "node:async_hooks";
10
10
  import "fs";
11
11
  import "crypto";
12
12
  import "node:os";
13
- import "./schemas-9JpFbIUJ.js";
13
+ import "./schemas-WuyisFi9.js";
14
14
  import "node:events";
15
15
  import "node:child_process";
16
16
  import "node:tty";
@@ -28,7 +28,7 @@ import "node:util";
28
28
  import "node:zlib";
29
29
  import "child_process";
30
30
  import "./plan-mode-D0D5cnMs.js";
31
- import "./acp-w0Ug9k0u.js";
31
+ import "./acp-BzvviK-N.js";
32
32
  import "node:url";
33
33
  import "./subagent-events-BJ9JwZva.js";
34
34
  import "./loro_wasm_bg-DIxpLA2J.js";
@@ -52,22 +52,23 @@ import "node:util/types";
52
52
  import "node:worker_threads";
53
53
  import "node:console";
54
54
  import "node:dns";
55
- import "./directory-handle-CjQk33eZ.js";
55
+ import "./directory-handle-CtdCjbNh.js";
56
56
  import "./diff-line-counts-DDGc5P-T.js";
57
57
  import "node:stream/promises";
58
58
  import "node:string_decoder";
59
59
  import "./package-BoOO46ct.js";
60
+ import "./session-DyqwlJbY.js";
60
61
  import "async_hooks";
61
62
  import "module";
62
63
  import "./diff-worker-task-MZsLArT5.js";
63
64
  import "./workspace-watch-protocol-POg9Lpeq.js";
64
65
  import "node:dns/promises";
65
- import "./cloudflared-native-BPe7OSUZ.js";
66
+ import "./cloudflared-native-DbUToPHH.js";
66
67
  import "node:timers/promises";
67
68
  import "node:module";
68
69
  import "node:v8";
69
70
  import "http2";
70
- const reviewViewerVersion = "0.101.1";
71
+ const reviewViewerVersion = "0.103.0";
71
72
  const reviewViewerSha256 = "d1ba5702aa0bd441b40492bd916d6412f8b970e92683f7073878a36efbdb0649";
72
73
  const reviewViewerFileName = "standalone.html";
73
74
  const DEFAULT_CDN_BASES = ["https://cdn.jsdelivr.net/npm", "https://unpkg.com"];
@@ -142,4 +143,4 @@ async function resolveReviewViewerTemplate() {
142
143
  export {
143
144
  resolveReviewViewerTemplate
144
145
  };
145
- //# sourceMappingURL=review-viewer-CEUQAboP.js.map
146
+ //# sourceMappingURL=review-viewer-BZiXmQnJ.js.map
@@ -4908,8 +4908,8 @@ function preprocess(fn, schema) {
4908
4908
  export {
4909
4909
  uuid as A,
4910
4910
  _null as B,
4911
- lazy as C,
4912
- looseObject as D,
4911
+ looseObject as C,
4912
+ lazy as D,
4913
4913
  intersection as E,
4914
4914
  optional as F,
4915
4915
  datetime as G,
@@ -4918,9 +4918,9 @@ export {
4918
4918
  toJSONSchema as J,
4919
4919
  date as K,
4920
4920
  email as L,
4921
- never as M,
4921
+ xor as M,
4922
4922
  NEVER as N,
4923
- xor as O,
4923
+ never as O,
4924
4924
  tuple as P,
4925
4925
  int as Q,
4926
4926
  ZodNumber as Z,
@@ -4952,4 +4952,4 @@ export {
4952
4952
  ZodDiscriminatedUnion as y,
4953
4953
  _instanceof as z
4954
4954
  };
4955
- //# sourceMappingURL=schemas-9JpFbIUJ.js.map
4955
+ //# sourceMappingURL=schemas-WuyisFi9.js.map
@@ -0,0 +1,10 @@
1
+ const LODY_TOOL_NAMES = {
2
+ imageGeneration: "ImageGeneration",
3
+ cronCreate: "CronCreate",
4
+ cronDelete: "CronDelete",
5
+ cronList: "CronList"
6
+ };
7
+ export {
8
+ LODY_TOOL_NAMES as L
9
+ };
10
+ //# sourceMappingURL=session-DyqwlJbY.js.map
@@ -23,7 +23,7 @@ import { isIPv4, isIPv6 } from "net";
23
23
  import { createRequire as createRequire$1 } from "module";
24
24
  import { fileURLToPath } from "url";
25
25
  import { StringDecoder } from "string_decoder";
26
- import { c as array, u as unknown, N as NEVER, e as union, n as number, s as string, o as object, r as record, Q as int, l as literal, b as boolean, E as intersection, H as url } from "./chunks/schemas-9JpFbIUJ.js";
26
+ import { c as array, u as unknown, N as NEVER, e as union, n as number, s as string, o as object, r as record, Q as int, l as literal, b as boolean, E as intersection, H as url } from "./chunks/schemas-WuyisFi9.js";
27
27
  import { L as LODY_EXTENSION_METHODS, s as sumModelUsage, e as supportsLodySubagentEvents, d as LODY_SUBAGENT_EVENT_METHOD } from "./chunks/subagent-events-BJ9JwZva.js";
28
28
  import { L as LodySubagentEmitter } from "./chunks/subagent-emitter-BsTuVPDw.js";
29
29
  import { execFile as execFile$1 } from "node:child_process";
@@ -1,5 +1,5 @@
1
- import { s as startCloudflaredNative, C as CloudflaredError } from "./chunks/cloudflared-native-BPe7OSUZ.js";
2
- import { P as tuple, s as string, o as object, l as literal } from "./chunks/schemas-9JpFbIUJ.js";
1
+ import { s as startCloudflaredNative, C as CloudflaredError } from "./chunks/cloudflared-native-DbUToPHH.js";
2
+ import { P as tuple, s as string, o as object, l as literal } from "./chunks/schemas-WuyisFi9.js";
3
3
  import "node:child_process";
4
4
  import "node:fs/promises";
5
5
  import "node:os";
package/dist/codex-acp.js CHANGED
@@ -2,5 +2,5 @@ if (!process.env.CODEX_PATH?.trim()) {
2
2
  console.error("CODEX_PATH is required for the bundled Codex ACP adapter.");
3
3
  process.exit(1);
4
4
  }
5
- await import("./chunks/index-C0n6fro1.js");
5
+ await import("./chunks/index-DEdPzgH7.js");
6
6
  //# sourceMappingURL=codex-acp.js.map
@@ -1,9 +1,9 @@
1
1
  import { resolve, isAbsolute } from "node:path";
2
- import { o as object, s as string, b as boolean, c as array, l as literal, u as unknown, n as number, a as _enum, r as record } from "./chunks/schemas-9JpFbIUJ.js";
2
+ import { o as object, s as string, b as boolean, c as array, l as literal, u as unknown, n as number, a as _enum, r as record } from "./chunks/schemas-WuyisFi9.js";
3
3
  import { S as SessionUsageAccumulator, L as LODY_EXTENSION_METHODS, e as supportsLodySubagentEvents, d as LODY_SUBAGENT_EVENT_METHOD } from "./chunks/subagent-events-BJ9JwZva.js";
4
4
  import { randomUUID, createHash } from "node:crypto";
5
5
  import { Readable, Writable } from "node:stream";
6
- import { j as DEEPSEEK_HARNESS_BASE_URL_ENV, l as DEEPSEEK_HARNESS_API_KEY_ENV, n as ndJsonStream, o as AgentSideConnection, a as DEEPSEEK_HARNESS_AGENT_PRESETS, R as RequestError, p as ACP_EXTENSION_DSH_VERSION, P as PROTOCOL_VERSION, q as DEEPSEEK_HARNESS_DEFAULT_MODEL, r as DEEPSEEK_HARNESS_PROVIDER } from "./chunks/acp-w0Ug9k0u.js";
6
+ import { j as DEEPSEEK_HARNESS_BASE_URL_ENV, l as DEEPSEEK_HARNESS_API_KEY_ENV, n as ndJsonStream, o as AgentSideConnection, a as DEEPSEEK_HARNESS_AGENT_PRESETS, R as RequestError, p as ACP_EXTENSION_DSH_VERSION, P as PROTOCOL_VERSION, q as DEEPSEEK_HARNESS_DEFAULT_MODEL, r as DEEPSEEK_HARNESS_PROVIDER } from "./chunks/acp-BzvviK-N.js";
7
7
  import { c as createPlanModeConfigOption, L as LODY_PLAN_MODE_CONFIG_ID } from "./chunks/plan-mode-D0D5cnMs.js";
8
8
  import { L as LodySubagentEmitter } from "./chunks/subagent-emitter-BsTuVPDw.js";
9
9
  import "node:url";
@@ -432,6 +432,7 @@ const MODEL_DISCOVERY_TIMEOUT_MS = 15e3;
432
432
  const MODEL_DISCOVERY_MAX_BYTES = 1024 * 1024;
433
433
  const MODEL_DISCOVERY_MAX_MODELS = 1e3;
434
434
  const MODEL_ID_MAX_LENGTH = 512;
435
+ const ACP_MODEL_ID_PREFIX = "dsh-route:";
435
436
  const INVALID_MCP_SERVER_NAME_CHARS = /[^A-Za-z0-9_-]/gu;
436
437
  const IMAGE_MEDIA_TYPES = [
437
438
  "image/png",
@@ -470,33 +471,60 @@ function resolveAdapterConfig(config) {
470
471
  ...config?.stream ? { stream: config.stream } : {}
471
472
  };
472
473
  }
473
- async function loadHarnessModels(llm, provider, configuredModel, endpoint) {
474
- const listed = endpoint ? (await discoverDeepSeekModelIds(endpoint.baseUrl, endpoint.apiKey)).map((id) => ({
475
- provider,
476
- id
477
- })) : await llm.listModels(provider);
478
- const modelIds = [];
479
- const ids = /* @__PURE__ */ new Set();
480
- for (const model of listed) {
481
- if (model.provider !== provider || !model.id.trim())
482
- continue;
483
- if (ids.has(model.id)) {
484
- throw new Error(`acp-extension-dsh: duplicate model ${JSON.stringify(model.id)} for provider ${JSON.stringify(provider)}`);
474
+ async function loadHarnessModels(llm, defaultProvider, configuredModel, endpoint) {
475
+ const providers = llm.listProviders?.() ?? [{ id: defaultProvider, name: defaultProvider }];
476
+ if (!providers.some(({ id }) => id === defaultProvider)) {
477
+ throw new Error(`configured provider ${JSON.stringify(defaultProvider)} is unavailable`);
478
+ }
479
+ const identities = [];
480
+ for (const { id: provider } of providers) {
481
+ const listed = endpoint && provider === defaultProvider ? (await discoverDeepSeekModelIds(endpoint.baseUrl, endpoint.apiKey)).map((id) => ({
482
+ provider,
483
+ id
484
+ })) : await llm.listModels(provider);
485
+ const ids = /* @__PURE__ */ new Set();
486
+ for (const model of listed) {
487
+ if (model.provider !== provider || !model.id.trim())
488
+ continue;
489
+ if (ids.has(model.id)) {
490
+ throw new Error(`acp-extension-dsh: duplicate model ${JSON.stringify(model.id)} for provider ${JSON.stringify(provider)}`);
491
+ }
492
+ ids.add(model.id);
493
+ identities.push({ provider, model: model.id });
494
+ }
495
+ if (endpoint && provider === defaultProvider && ids.size === 0) {
496
+ throw new Error("the endpoint returned no usable models");
497
+ }
498
+ if (provider === defaultProvider && !endpoint && !ids.has(configuredModel)) {
499
+ identities.unshift({ provider, model: configuredModel });
485
500
  }
486
- ids.add(model.id);
487
- modelIds.push(model.id);
488
501
  }
489
- if (endpoint && modelIds.length === 0) {
502
+ const initialSelection = endpoint ? identities.find(({ provider }) => provider === defaultProvider) : { provider: defaultProvider, model: configuredModel };
503
+ if (!initialSelection)
490
504
  throw new Error("the endpoint returned no usable models");
491
- }
492
- if (!endpoint && !ids.has(configuredModel))
493
- modelIds.unshift(configuredModel);
494
- const initialModel = endpoint ? modelIds[0] : configuredModel;
495
505
  return {
496
- models: await Promise.all(modelIds.map((modelId) => resolveHarnessModel(llm, provider, modelId))),
497
- initialModel
506
+ models: await Promise.all(identities.map(({ provider, model }) => resolveHarnessModel(llm, provider, model))),
507
+ initialSelection
498
508
  };
499
509
  }
510
+ function encodeAcpModelId(provider, model) {
511
+ return `${ACP_MODEL_ID_PREFIX}${Buffer.from(JSON.stringify([provider, model])).toString("base64url")}`;
512
+ }
513
+ function decodeAcpModelId(value, legacyProvider) {
514
+ if (!value.startsWith(ACP_MODEL_ID_PREFIX))
515
+ return { provider: legacyProvider, model: value };
516
+ try {
517
+ const decoded = JSON.parse(Buffer.from(value.slice(ACP_MODEL_ID_PREFIX.length), "base64url").toString("utf8"));
518
+ if (Array.isArray(decoded) && decoded.length === 2 && decoded.every((part) => typeof part === "string" && part.trim())) {
519
+ return { provider: decoded[0], model: decoded[1] };
520
+ }
521
+ } catch {
522
+ }
523
+ throw invalidParams("model route id is invalid");
524
+ }
525
+ function selectedModel(record2) {
526
+ return record2.models.find((candidate) => candidate.provider === record2.selection.current.provider && candidate.id === record2.selection.current.model);
527
+ }
500
528
  function modelDiscoveryUrl(baseUrl) {
501
529
  const url = new URL(baseUrl);
502
530
  url.pathname = `${url.pathname.replace(/\/+$/u, "")}/models`;
@@ -727,13 +755,13 @@ function configOptions(record2) {
727
755
  {
728
756
  id: MODEL_CONFIG_ID,
729
757
  name: "Model",
730
- description: "DeepSeek model used for the session",
758
+ description: "Provider route and model used for the session",
731
759
  category: "model",
732
760
  type: "select",
733
- currentValue: record2.selection.current.model,
761
+ currentValue: encodeAcpModelId(record2.selection.current.provider, record2.selection.current.model),
734
762
  options: record2.models.map((model2) => ({
735
- value: model2.id,
736
- name: model2.name,
763
+ value: encodeAcpModelId(model2.provider, model2.id),
764
+ name: `${model2.name} (${model2.provider})`,
737
765
  description: model2.description ?? null
738
766
  }))
739
767
  }
@@ -743,7 +771,7 @@ function configOptions(record2) {
743
771
  const state = plan.get(record2.agent);
744
772
  options.push(createPlanModeConfigOption(state.pending ?? state.active));
745
773
  }
746
- const model = record2.models.find((candidate) => candidate.id === record2.selection.current.model);
774
+ const model = selectedModel(record2);
747
775
  if (model?.reasoning && record2.selection.current.reasoningEffort) {
748
776
  options.push({
749
777
  id: REASONING_EFFORT_CONFIG_ID,
@@ -763,16 +791,16 @@ function configOptions(record2) {
763
791
  }
764
792
  function legacyModels(record2) {
765
793
  return {
766
- currentModelId: record2.selection.current.model,
794
+ currentModelId: encodeAcpModelId(record2.selection.current.provider, record2.selection.current.model),
767
795
  availableModels: record2.models.flatMap((model) => [
768
796
  {
769
- modelId: model.id,
770
- name: model.name,
797
+ modelId: encodeAcpModelId(model.provider, model.id),
798
+ name: `${model.name} (${model.provider})`,
771
799
  description: model.description ?? null
772
800
  },
773
801
  ...model.reasoning?.efforts.map((effort) => ({
774
- modelId: `${model.id}[${effort.id}]`,
775
- name: `${model.name} (${effort.name})`,
802
+ modelId: `${encodeAcpModelId(model.provider, model.id)}[${effort.id}]`,
803
+ name: `${model.name} (${model.provider}, ${effort.name})`,
776
804
  description: model.description ?? null
777
805
  })) ?? []
778
806
  ])
@@ -1440,26 +1468,27 @@ function apply(ctx, rawConfig) {
1440
1468
  throw invalidParams(`failed to select agent preset ${JSON.stringify(value)}: ${errorChain(error)}`);
1441
1469
  });
1442
1470
  } else if (params.configId === MODEL_CONFIG_ID) {
1443
- return resolveHarnessModel(llm, record2.selection.current.provider, value).then((model) => {
1444
- const index = record2.models.findIndex((candidate) => candidate.id === value);
1471
+ const selected = decodeAcpModelId(value, record2.selection.current.provider);
1472
+ return resolveHarnessModel(llm, selected.provider, selected.model).then((model) => {
1473
+ const index = record2.models.findIndex((candidate) => candidate.provider === selected.provider && candidate.id === selected.model);
1445
1474
  if (index === -1)
1446
1475
  record2.models.push(model);
1447
1476
  else
1448
1477
  record2.models[index] = model;
1449
1478
  const reasoningEffort = resolveReasoningEffort(model, record2.selection.current.reasoningEffort && model.reasoning?.efforts.some((effort) => effort.id === record2.selection.current.reasoningEffort) ? record2.selection.current.reasoningEffort : void 0);
1450
1479
  record2.selection.current = {
1451
- provider: record2.selection.current.provider,
1452
- model: value,
1480
+ provider: selected.provider,
1481
+ model: selected.model,
1453
1482
  ...reasoningEffort ? { reasoningEffort } : {}
1454
1483
  };
1455
1484
  return { configOptions: configOptions(record2) };
1456
1485
  }).catch((error) => {
1457
1486
  if (error instanceof RequestError)
1458
1487
  throw error;
1459
- throw invalidParams(`failed to resolve model ${JSON.stringify(value)}: ${errorChain(error)}`);
1488
+ throw invalidParams(`failed to resolve model route ${JSON.stringify(selected.provider)} / ${JSON.stringify(selected.model)}: ${errorChain(error)}`);
1460
1489
  });
1461
1490
  } else if (params.configId === REASONING_EFFORT_CONFIG_ID) {
1462
- const model = record2.models.find((candidate) => candidate.id === record2.selection.current.model);
1491
+ const model = selectedModel(record2);
1463
1492
  if (!model)
1464
1493
  throw internalError("selected model metadata is unavailable");
1465
1494
  const reasoningEffort = resolveReasoningEffort(model, value);
@@ -1519,17 +1548,17 @@ function apply(ctx, rawConfig) {
1519
1548
  } catch (error) {
1520
1549
  throw internalError(`failed to discover models: ${errorChain(error)}`);
1521
1550
  }
1522
- const { models, initialModel: initialModelId } = catalog;
1551
+ const { models, initialSelection } = catalog;
1523
1552
  const sessionId = randomUUID();
1524
1553
  const questions = new UserQuestionBridge(sessionId, (request) => conn.unstable_createElicitation(request), () => questionCapabilities);
1525
- const initialModel = models.find((model) => model.id === initialModelId);
1554
+ const initialModel = models.find((model) => model.provider === initialSelection.provider && model.id === initialSelection.model);
1526
1555
  if (!initialModel)
1527
1556
  throw internalError("initial model metadata is unavailable");
1528
1557
  const reasoningEffort = resolveReasoningEffort(initialModel, config.reasoningEffort);
1529
1558
  const selection = {
1530
1559
  current: {
1531
- provider: config.provider,
1532
- model: initialModelId,
1560
+ provider: initialSelection.provider,
1561
+ model: initialSelection.model,
1533
1562
  ...reasoningEffort ? { reasoningEffort } : {}
1534
1563
  }
1535
1564
  };
@@ -1545,7 +1574,10 @@ function apply(ctx, rawConfig) {
1545
1574
  handle = await ctx.agents.create({
1546
1575
  sessionId,
1547
1576
  meta: { cwd: params.cwd, agentPreset: requestedPreset },
1548
- agentOptions: { provider: config.provider, model: initialModelId },
1577
+ agentOptions: {
1578
+ provider: initialSelection.provider,
1579
+ model: initialSelection.model
1580
+ },
1549
1581
  setup: async (agentContext) => {
1550
1582
  if (subagentEvents && !carrierKeyOf) {
1551
1583
  const scope = await agentContext.loader.import("@deepseek-ai/dsh-scope");
@@ -1,7 +1,7 @@
1
1
  import { opendir } from "node:fs/promises";
2
2
  import path__default from "node:path";
3
- import { z as buildCodeCollabFileIndexState, F as scanGitDirectoryEntries, H as joinWorkspacePath, I as isInsideGitWorktree, D as computeAllChanges, J as pathSegmentComparisonKey, G as closeDirectoryQuietly } from "./chunks/directory-handle-CjQk33eZ.js";
4
- import "./chunks/schemas-9JpFbIUJ.js";
3
+ import { z as buildCodeCollabFileIndexState, F as scanGitDirectoryEntries, H as joinWorkspacePath, I as isInsideGitWorktree, D as computeAllChanges, J as pathSegmentComparisonKey, G as closeDirectoryQuietly } from "./chunks/directory-handle-CtdCjbNh.js";
4
+ import "./chunks/schemas-WuyisFi9.js";
5
5
  import "node:child_process";
6
6
  import "node:util";
7
7
  import "./chunks/diff-line-counts-DDGc5P-T.js";
package/dist/grok-acp.js CHANGED
@@ -2,6 +2,7 @@ import { createInterface } from "node:readline";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import { c as isLodySubagentOutput, d as LODY_SUBAGENT_EVENT_METHOD, L as LODY_EXTENSION_METHODS, e as supportsLodySubagentEvents, S as SessionUsageAccumulator } from "./chunks/subagent-events-BJ9JwZva.js";
4
4
  import { L as LODY_PLAN_MODE_CONFIG_ID, c as createPlanModeConfigOption } from "./chunks/plan-mode-D0D5cnMs.js";
5
+ import { L as LODY_TOOL_NAMES } from "./chunks/session-DyqwlJbY.js";
5
6
  import { spawn } from "node:child_process";
6
7
  const privateWireContract = { "permissionNotification": "x.ai/yolo_mode_changed", "sessionConfigMeta": "x.ai/sessionConfig", "sessionNotification": "x.ai/session_notification", "sessionUpdateNotification": "x.ai/session/update", "modelsUpdateNotification": "x.ai/models/update", "userMessageEchoCapability": "x.ai/userMessageEcho", "turnCompletedUpdate": "turn_completed", "sessionForkRequest": "x.ai/session/fork", "sessionInfoRequest": "x.ai/session/info", "billingRequest": "x.ai/billing", "weeklyUsagePeriodType": "USAGE_PERIOD_TYPE_WEEKLY", "reasoningEffortMeta": "reasoningEffort", "autoPermissionMode": false, "planApprovalRequest": "x.ai/exit_plan_mode" };
7
8
  const runtimeManifest = {
@@ -510,6 +511,7 @@ const INTERNAL_REQUESTS = {
510
511
  const USD_TICKS_PER_USD = 1e10;
511
512
  const MAX_TRACKED_PROMPTS = 256;
512
513
  const GROK_LODY_CAPABILITIES = {
514
+ tasks: { version: 1, scheduled: true },
513
515
  subagentEvents: { version: 1 },
514
516
  sessionTitle: { version: 1 },
515
517
  forkAtTurn: { version: 1 },
@@ -521,6 +523,61 @@ const GROK_MODEL_SNAPSHOT_SETTLE_TIMEOUT_MS = 2e3;
521
523
  function logicalExtensionMethod(method) {
522
524
  return typeof method === "string" && method.startsWith("_") ? method.slice(1) : method;
523
525
  }
526
+ const SCHEDULING_TOOLS = /* @__PURE__ */ new Map([
527
+ ["scheduler_create", LODY_TOOL_NAMES.cronCreate],
528
+ ["scheduler_delete", LODY_TOOL_NAMES.cronDelete],
529
+ ["scheduler_list", LODY_TOOL_NAMES.cronList]
530
+ ]);
531
+ function scheduledTaskUpdate(message) {
532
+ const { update: update2 } = message.params;
533
+ const method = logicalExtensionMethod(message.method);
534
+ if (message.method === "session/update" && ["tool_call", "tool_call_update"].includes(update2?.sessionUpdate)) {
535
+ const native = update2._meta?.["x.ai/tool"];
536
+ const toolName = native?.version === 1 && native.namespace === "grok_build" ? SCHEDULING_TOOLS.get(native.name) : void 0;
537
+ if (!toolName) return message;
538
+ return {
539
+ ...message,
540
+ params: {
541
+ ...message.params,
542
+ update: {
543
+ ...update2,
544
+ _meta: { ...update2._meta, lody: { ...update2._meta?.lody, toolName } }
545
+ }
546
+ }
547
+ };
548
+ }
549
+ const event = update2?.sessionUpdate;
550
+ if (!["scheduled_task_created", "scheduled_task_fired", "scheduled_task_deleted"].includes(event) || ![`x.ai/${event}`, contract.sessionNotification].includes(method) || typeof update2.task_id !== "string" || !update2.task_id.trim()) return message;
551
+ const deleted = event === "scheduled_task_deleted";
552
+ if (!deleted && (typeof update2.prompt !== "string" || typeof update2.human_schedule !== "string"))
553
+ return message;
554
+ if (deleted && update2.reason === "shutdown") return null;
555
+ const taskId = `grok-scheduled:${update2.task_id}`;
556
+ const status = deleted ? "completed" : event === "scheduled_task_created" ? "pending" : "in_progress";
557
+ const task = {
558
+ version: 1,
559
+ taskId,
560
+ kind: "scheduled",
561
+ status,
562
+ ...!deleted ? { description: `${update2.prompt} (${update2.human_schedule})` } : {},
563
+ ...deleted ? { summary: `Schedule removed (${typeof update2.reason === "string" ? update2.reason : "unknown"})` } : {}
564
+ };
565
+ return {
566
+ ...message,
567
+ method: "session/update",
568
+ params: {
569
+ ...message.params,
570
+ update: {
571
+ sessionUpdate: "tool_call_update",
572
+ toolCallId: taskId,
573
+ title: task.description ?? "Scheduled task removed",
574
+ kind: "other",
575
+ status,
576
+ _meta: { ...update2._meta, lody: { ...update2._meta?.lody, task } }
577
+ }
578
+ }
579
+ };
580
+ }
524
581
  function wireExtensionMethod(method) {
525
582
  return `_${method}`;
526
583
  }
@@ -1303,6 +1360,14 @@ class GrokAcpCompatibilityProxy {
1303
1360
  handleRuntimeMethod(message) {
1304
1361
  message = this.forks.update(message);
1305
1362
  if (!message) return { toRuntime: [], toClient: [] };
1363
+ const scheduleSessionId = message.params?.sessionId;
1364
+ const ownsScheduleSession = this.sessions.has(scheduleSessionId) || typeof scheduleSessionId === "string" && [...this.pending.values()].some(
1365
+ (pending) => pending.kind === "session" && pending.sessionId === scheduleSessionId && ["session/load", "session/resume"].includes(pending.method)
1366
+ );
1367
+ if (ownsScheduleSession) {
1368
+ message = scheduledTaskUpdate(message);
1369
+ if (!message) return { toRuntime: [], toClient: [] };
1370
+ }
1306
1371
  if (supportsLodySubagentEvents(this.clientCapabilities)) {
1307
1372
  const normalized = this.subagents.handle(message, this.sessions);
1308
1373
  if (normalized?.length === 1 && normalized[0].method === "session/request_permission") message = normalized[0];