lody 0.84.0 → 0.85.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.
@@ -19,12 +19,20 @@ const DEEPSEEK_HARNESS_MODELS = [
19
19
  {
20
20
  modelId: "deepseek-v4-flash",
21
21
  name: "DeepSeek-V4-Flash",
22
- description: "Faster DeepSeek Harness coding model."
22
+ description: "Faster DeepSeek Harness coding model.",
23
+ inputModalities: ["text"]
23
24
  },
24
25
  {
25
26
  modelId: "deepseek-v4-pro",
26
27
  name: "DeepSeek-V4-Pro",
27
- description: "More capable DeepSeek Harness coding model."
28
+ description: "More capable DeepSeek Harness coding model.",
29
+ inputModalities: ["text"]
30
+ },
31
+ {
32
+ modelId: "deepseek-v4-flash-vision-exp",
33
+ name: "DeepSeek-V4-Flash-Vision-Exp",
34
+ description: "Experimental multimodal DeepSeek model with image understanding.",
35
+ inputModalities: ["text", "image"]
28
36
  }
29
37
  ];
30
38
  const DEEPSEEK_HARNESS_REASONING_OPTIONS = [
@@ -55,8 +63,8 @@ const DEEPSEEK_HARNESS_AGENT_PRESETS = [
55
63
  }
56
64
  ];
57
65
  const ACP_EXTENSION_DSH_VERSION = "0.1.0";
58
- const DEEPSEEK_HARNESS_VERSION = "0.1.0-rc.7";
59
- const ACP_EXTENSION_DSH_PROFILE_REVISION = "v3";
66
+ const DEEPSEEK_HARNESS_VERSION = "0.1.1-rc.1";
67
+ const ACP_EXTENSION_DSH_PROFILE_REVISION = "v5";
60
68
  const ACP_EXTENSION_DSH_SESSION_ROOT_ENV = "ACP_EXTENSION_DSH_SESSION_ROOT";
61
69
  const ACP_EXTENSION_DSH_QUERY_PATH_ENV = "ACP_EXTENSION_DSH_QUERY_PATH";
62
70
  const DEEPSEEK_HARNESS_DEFAULT_SESSION_COMPRESSION = "zstd";
@@ -67,6 +75,7 @@ const DEEPSEEK_HARNESS_NPX_PACKAGES = [
67
75
  "@deepseek-ai/dsh-session-persistence-jsonl",
68
76
  "@deepseek-ai/dsh-session-checkpoint-policy",
69
77
  "@deepseek-ai/dsh-session-query-sqlite",
78
+ "@deepseek-ai/dsh-attachment-local",
70
79
  "@deepseek-ai/dsh-llm-deepseek",
71
80
  "@deepseek-ai/dsh-sandbox-local",
72
81
  "@deepseek-ai/dsh-sandbox-policy",
@@ -122,6 +131,7 @@ const DEEPSEEK_HARNESS_NPX_PACKAGES = [
122
131
  "@deepseek-ai/dsh-terminal",
123
132
  "@deepseek-ai/dsh-terminal-bash",
124
133
  "@deepseek-ai/dsh-tool-bash-persistent",
134
+ "@deepseek-ai/dsh-tool-pwsh-persistent",
125
135
  "@deepseek-ai/dsh-fs-local",
126
136
  "@deepseek-ai/dsh-tool-str-replace-editor",
127
137
  // Pin the complete transitive DSH dependency and peer closure too. Harness
@@ -196,15 +206,16 @@ function createDeepSeekHarnessCordisConfig(adapterPath, presetRoot, sessionCompr
196
206
  name: '@deepseek-ai/dsh-session-query-sqlite'
197
207
  config:
198
208
  path: !!js process.env.${ACP_EXTENSION_DSH_QUERY_PATH_ENV}
209
+ openAt: never
210
+
211
+ - id: attachment-local
212
+ name: '@deepseek-ai/dsh-attachment-local'
199
213
 
200
214
  - id: llm-deepseek
201
215
  name: '@deepseek-ai/dsh-llm-deepseek'
202
216
  config:
203
217
  thinking: enabled
204
218
  reasoningEffort: max
205
- models:
206
- - id: deepseek-v4-flash
207
- - id: deepseek-v4-pro
208
219
 
209
220
  - id: sandbox
210
221
  name: '@deepseek-ai/dsh-sandbox-local'
@@ -32,7 +32,7 @@ import "perf_hooks";
32
32
  import "net";
33
33
  import "tls";
34
34
  import "url";
35
- import "./profile-RfMzWliN.js";
35
+ import "./profile-Cxxl5hCq.js";
36
36
  import "assert";
37
37
  import "fs/promises";
38
38
  import "better-sqlite3";
@@ -79,7 +79,7 @@ let __tla = Promise.all([
79
79
  }
80
80
  })()
81
81
  ]).then(async () => {
82
- const reviewViewerVersion = "0.84.0";
82
+ const reviewViewerVersion = "0.85.0";
83
83
  const reviewViewerSha256 = "2ae06d0f134be0ae82e0a9962179037cbee997a59c4240753e44e77b11d92dd6";
84
84
  const reviewViewerFileName = "standalone.html";
85
85
  const DEFAULT_CDN_BASES = [
@@ -2,13 +2,15 @@ import { randomUUID, createHash } from "node:crypto";
2
2
  import { isAbsolute } from "node:path";
3
3
  import { Readable, Writable } from "node:stream";
4
4
  import { n as ndJsonStream, A as AgentSideConnection, R as RequestError, P as PROTOCOL_VERSION } from "./chunks/acp-CrvzLY5A.js";
5
- import { b as DEEPSEEK_HARNESS_MODELS, D as DEEPSEEK_HARNESS_PERMISSION_MODES, c as DEEPSEEK_HARNESS_REASONING_OPTIONS, e as ACP_EXTENSION_DSH_VERSION, a as DEEPSEEK_HARNESS_AGENT_PRESETS } from "./chunks/profile-RfMzWliN.js";
5
+ import { D as DEEPSEEK_HARNESS_PERMISSION_MODES, c as DEEPSEEK_HARNESS_REASONING_OPTIONS, e as ACP_EXTENSION_DSH_VERSION, a as DEEPSEEK_HARNESS_AGENT_PRESETS } from "./chunks/profile-Cxxl5hCq.js";
6
6
  import "./chunks/schemas-Du3qLZPS.js";
7
7
  const name = "acp-extension-dsh";
8
8
  const inject = [
9
9
  "agents",
10
10
  "agentPresets",
11
+ "attachments",
11
12
  "loader",
13
+ "llm",
12
14
  "permissionPresets",
13
15
  "sessionPersistence",
14
16
  "sessionQuery"
@@ -22,7 +24,24 @@ const MCP_TOOL_CALL_TIMEOUT_MS = 6e4;
22
24
  const MCP_SERVER_NAME_MAX_LENGTH = 32;
23
25
  const MCP_SERVER_NAME_HASH_LENGTH = 8;
24
26
  const INVALID_MCP_SERVER_NAME_CHARS = /[^A-Za-z0-9_-]/gu;
25
- const MODEL_IDS = new Set(DEEPSEEK_HARNESS_MODELS.map((model) => model.modelId));
27
+ const IMAGE_MEDIA_TYPES = [
28
+ "image/png",
29
+ "image/jpeg",
30
+ "image/webp",
31
+ "image/gif"
32
+ ];
33
+ const CANONICAL_BASE64 = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/u;
34
+ const IMAGE_ADMISSION_ERROR_CODES = /* @__PURE__ */ new Set([
35
+ "TOO_MANY_IMAGES",
36
+ "IMAGES_TOO_LARGE",
37
+ "UNSUPPORTED_IMAGE_TYPE",
38
+ "INVALID_IMAGE_BASE64",
39
+ "INVALID_IMAGE",
40
+ "IMAGE_TYPE_MISMATCH",
41
+ "IMAGE_TOO_LARGE",
42
+ "IMAGE_TOO_MANY_PIXELS",
43
+ "IMAGE_DIMENSION_TOO_LARGE"
44
+ ]);
26
45
  const PERMISSION_MODE_IDS = new Set(DEEPSEEK_HARNESS_PERMISSION_MODES.map((mode) => mode.id));
27
46
  const REASONING_EFFORT_IDS = new Set(DEEPSEEK_HARNESS_REASONING_OPTIONS.map((effort) => effort.value));
28
47
  function invalidParams(detail) {
@@ -38,9 +57,6 @@ function resolveAdapterConfig(config) {
38
57
  const provider = nonEmptyString(config?.provider, "deepseek-official");
39
58
  const model = nonEmptyString(config?.model, "deepseek-v4-pro");
40
59
  const reasoningEffort = config?.reasoningEffort ?? "max";
41
- if (!MODEL_IDS.has(model)) {
42
- throw new Error(`acp-extension-dsh: unsupported model ${JSON.stringify(model)}`);
43
- }
44
60
  if (!REASONING_EFFORT_IDS.has(reasoningEffort)) {
45
61
  throw new Error(`acp-extension-dsh: unsupported reasoning effort ${JSON.stringify(reasoningEffort)}`);
46
62
  }
@@ -51,6 +67,27 @@ function resolveAdapterConfig(config) {
51
67
  ...config?.stream ? { stream: config.stream } : {}
52
68
  };
53
69
  }
70
+ async function loadHarnessModels(ctx, provider) {
71
+ const llm = ctx.get("llm");
72
+ if (!llm)
73
+ throw new Error("acp-extension-dsh: no Harness LLM catalog is mounted");
74
+ const listed = await llm.listModels(provider);
75
+ const models = [];
76
+ const ids = /* @__PURE__ */ new Set();
77
+ for (const model of listed) {
78
+ if (model.provider !== provider || !model.id.trim())
79
+ continue;
80
+ if (ids.has(model.id)) {
81
+ throw new Error(`acp-extension-dsh: duplicate model ${JSON.stringify(model.id)} for provider ${JSON.stringify(provider)}`);
82
+ }
83
+ ids.add(model.id);
84
+ models.push({
85
+ ...model,
86
+ ...model.inputModalities ? { inputModalities: [...model.inputModalities] } : {}
87
+ });
88
+ }
89
+ return models;
90
+ }
54
91
  async function loadMcpClientPlugin(agentContext) {
55
92
  const module = agentContext.loader.unwrapExports(await agentContext.loader.import(MCP_CLIENT_PACKAGE));
56
93
  if (typeof module !== "object" || module === null || !("apply" in module) || typeof module.apply !== "function") {
@@ -202,9 +239,9 @@ function configOptions(record) {
202
239
  category: "model",
203
240
  type: "select",
204
241
  currentValue: record.selection.current.model,
205
- options: DEEPSEEK_HARNESS_MODELS.map((model) => ({
206
- value: model.modelId,
207
- name: model.name,
242
+ options: record.models.map((model) => ({
243
+ value: model.id,
244
+ name: model.name ?? model.id,
208
245
  description: model.description ?? null
209
246
  }))
210
247
  },
@@ -233,28 +270,97 @@ function modeState(record) {
233
270
  }))
234
271
  };
235
272
  }
236
- function acpPromptToText(prompt) {
237
- return prompt.flatMap((block) => {
238
- if (block.type === "text")
239
- return [block.text];
240
- if (block.type === "resource_link") {
241
- return [
242
- `
273
+ function modelSupportsImages(models, modelId) {
274
+ return models.some((model) => model.id === modelId && model.inputModalities?.includes("image"));
275
+ }
276
+ function imageMediaType(value) {
277
+ return IMAGE_MEDIA_TYPES.includes(value) ? value : void 0;
278
+ }
279
+ function decodePromptImage(block) {
280
+ const mediaType = imageMediaType(block.mimeType);
281
+ if (!mediaType) {
282
+ throw invalidParams("image mimeType must be image/png, image/jpeg, image/webp, or image/gif");
283
+ }
284
+ if (!block.data || !CANONICAL_BASE64.test(block.data)) {
285
+ throw invalidParams("image data must be canonical base64");
286
+ }
287
+ const decoded = Buffer.from(block.data, "base64");
288
+ if (decoded.toString("base64") !== block.data) {
289
+ throw invalidParams("image data must be canonical base64");
290
+ }
291
+ return { data: new Uint8Array(decoded), mediaType };
292
+ }
293
+ function isImageAdmissionError(error) {
294
+ return error instanceof Error && "code" in error && typeof error.code === "string" && IMAGE_ADMISSION_ERROR_CODES.has(error.code);
295
+ }
296
+ async function admitAcpPrompt(prompt, models, modelId, attachments) {
297
+ const images = [];
298
+ for (const block of prompt) {
299
+ switch (block.type) {
300
+ case "text":
301
+ case "resource_link":
302
+ break;
303
+ case "image":
304
+ if (!modelSupportsImages(models, modelId)) {
305
+ throw invalidParams(`model ${JSON.stringify(modelId)} does not support image input`);
306
+ }
307
+ images.push(decodePromptImage(block));
308
+ break;
309
+ case "audio":
310
+ throw invalidParams("audio prompt content is not supported");
311
+ case "resource":
312
+ throw invalidParams("embedded resource prompt content is not supported");
313
+ default:
314
+ throw invalidParams("unsupported ACP prompt content");
315
+ }
316
+ }
317
+ let refs = [];
318
+ if (images.length > 0) {
319
+ if (!attachments)
320
+ throw internalError("no Harness attachment store is mounted");
321
+ try {
322
+ refs = await attachments.saveImages(images);
323
+ } catch (error) {
324
+ if (isImageAdmissionError(error))
325
+ throw invalidParams(error.message);
326
+ throw internalError("unable to persist the prompt image batch");
327
+ }
328
+ }
329
+ const content = [];
330
+ let pendingText = "";
331
+ let imageIndex = 0;
332
+ const flushText = () => {
333
+ if (!pendingText)
334
+ return;
335
+ content.push({ type: "text", text: pendingText });
336
+ pendingText = "";
337
+ };
338
+ for (const block of prompt) {
339
+ if (block.type === "text") {
340
+ pendingText += block.text;
341
+ } else if (block.type === "resource_link") {
342
+ pendingText += `
243
343
  [resource_link name=${JSON.stringify(block.name)} uri=${JSON.stringify(block.uri)}]
244
- `
245
- ];
344
+ `;
345
+ } else if (block.type === "image") {
346
+ flushText();
347
+ const attachment = refs[imageIndex++];
348
+ if (!attachment)
349
+ throw internalError("the attachment store returned an incomplete image batch");
350
+ content.push({ type: "image", attachment });
246
351
  }
247
- return [];
248
- }).join("");
249
- }
250
- function promptHasUnsupportedContent(prompt) {
251
- return prompt.some((block) => block.type !== "text" && block.type !== "resource_link");
352
+ }
353
+ flushText();
354
+ if (!content.some((block) => block.type === "image" || block.type === "text" && block.text.trim().length > 0)) {
355
+ throw invalidParams("empty prompt");
356
+ }
357
+ return content;
252
358
  }
253
- function createUserMessage(text) {
359
+ function createUserMessage(id, content) {
254
360
  return Object.freeze({
255
- id: randomUUID(),
361
+ id,
256
362
  role: "user",
257
- content: [Object.freeze({ type: "text", text })],
363
+ content: Object.freeze(content.map((block) => Object.freeze(block))),
258
364
  source: Object.freeze({ kind: "user" })
259
365
  });
260
366
  }
@@ -482,7 +588,7 @@ function apply(ctx, rawConfig) {
482
588
  throw invalidParams(`failed to select agent preset ${JSON.stringify(value)}: ${errorChain(error)}`);
483
589
  });
484
590
  } else if (params.configId === MODEL_CONFIG_ID) {
485
- assertAllowed(value, MODEL_IDS, "model");
591
+ assertAllowed(value, new Set(record.models.map((model) => model.id)), "model");
486
592
  record.selection.current = { ...record.selection.current, model: value };
487
593
  } else if (params.configId === REASONING_EFFORT_CONFIG_ID) {
488
594
  assertAllowed(value, REASONING_EFFORT_IDS, "reasoning effort");
@@ -498,17 +604,22 @@ function apply(ctx, rawConfig) {
498
604
  const makeAgent = (connection) => {
499
605
  conn = connection;
500
606
  return {
501
- initialize(_params) {
502
- return Promise.resolve({
607
+ async initialize(_params) {
608
+ const models = await loadHarnessModels(ctx, config.provider);
609
+ return {
503
610
  protocolVersion: PROTOCOL_VERSION,
504
611
  agentInfo: { name: "acp-extension-dsh", version: ACP_EXTENSION_DSH_VERSION },
505
612
  agentCapabilities: {
506
- promptCapabilities: { image: false, audio: false, embeddedContext: false },
613
+ promptCapabilities: {
614
+ image: models.some((model) => modelSupportsImages(models, model.id)),
615
+ audio: false,
616
+ embeddedContext: false
617
+ },
507
618
  mcpCapabilities: { http: true },
508
619
  sessionCapabilities: { close: {} }
509
620
  },
510
621
  authMethods: []
511
- });
622
+ };
512
623
  },
513
624
  authenticate(_params) {
514
625
  return Promise.resolve();
@@ -516,6 +627,12 @@ function apply(ctx, rawConfig) {
516
627
  async newSession(params) {
517
628
  assertOpen();
518
629
  validateSessionParams(params);
630
+ let models;
631
+ try {
632
+ models = await loadHarnessModels(ctx, config.provider);
633
+ } catch (error) {
634
+ throw internalError(`failed to list models: ${errorChain(error)}`);
635
+ }
519
636
  const sessionId = randomUUID();
520
637
  const selection = {
521
638
  current: {
@@ -575,13 +692,22 @@ function apply(ctx, rawConfig) {
575
692
  permissionMode,
576
693
  agentPreset: mountedPreset,
577
694
  agentPresetOptions,
695
+ models,
578
696
  started: false
579
697
  };
580
698
  sessions.set(sessionId, record);
581
699
  return {
582
700
  sessionId,
583
701
  modes: modeState(record),
584
- configOptions: configOptions(record)
702
+ configOptions: configOptions(record),
703
+ models: {
704
+ currentModelId: record.selection.current.model,
705
+ availableModels: record.models.map((model) => ({
706
+ modelId: model.id,
707
+ name: model.name ?? model.id,
708
+ description: model.description ?? null
709
+ }))
710
+ }
585
711
  };
586
712
  },
587
713
  setSessionMode(params) {
@@ -596,20 +722,29 @@ function apply(ctx, rawConfig) {
596
722
  const record = requireSession(params.sessionId);
597
723
  if (record.inflight)
598
724
  throw invalidParams("a prompt is already in flight for this session");
599
- if (promptHasUnsupportedContent(params.prompt)) {
600
- throw invalidParams("only text and resource_link prompt content is supported");
601
- }
602
- const text = acpPromptToText(params.prompt);
603
- if (!text.trim())
604
- throw invalidParams("empty prompt");
605
725
  if (ctx.agents.get(record.agent.id) !== record.agent) {
606
726
  throw internalError("prompt was not queued: the agent was disposed outside the bridge");
607
727
  }
608
- const message = createUserMessage(text);
609
- record.started = true;
610
- const stopReason = await new Promise((resolve, reject) => {
611
- const inflight = { resolve, reject, messageId: message.id };
612
- record.inflight = inflight;
728
+ const attachments = ctx.get("attachments");
729
+ const messageId = randomUUID();
730
+ let resolvePrompt;
731
+ let rejectPrompt;
732
+ const completion = new Promise((resolve, reject) => {
733
+ resolvePrompt = resolve;
734
+ rejectPrompt = reject;
735
+ });
736
+ const inflight = {
737
+ resolve: resolvePrompt,
738
+ reject: rejectPrompt,
739
+ messageId
740
+ };
741
+ record.inflight = inflight;
742
+ try {
743
+ const content = await admitAcpPrompt(params.prompt, record.models, record.selection.current.model, attachments);
744
+ if (record.inflight !== inflight)
745
+ return { stopReason: await completion };
746
+ const message = createUserMessage(messageId, content);
747
+ record.started = true;
613
748
  try {
614
749
  record.agent.followup(message);
615
750
  } catch (error) {
@@ -624,8 +759,12 @@ function apply(ctx, rawConfig) {
624
759
  const end = inflight.endReason;
625
760
  inflight.resolve(end ? end.kind === "max-tokens" ? "end_turn" : turnEndToStopReason(end) : "cancelled");
626
761
  });
627
- });
628
- return { stopReason };
762
+ } catch (error) {
763
+ if (record.inflight === inflight)
764
+ record.inflight = void 0;
765
+ throw error;
766
+ }
767
+ return { stopReason: await completion };
629
768
  },
630
769
  cancel(params) {
631
770
  const record = sessions.get(params.sessionId);
@@ -198,9 +198,10 @@
198
198
  toolName: subagent_fork
199
199
  backgroundMode: continuable
200
200
 
201
- # Production dsh does not install these optional providers. An opting-in
202
- # Profile mounts each provider once on the host plane; copy this preset,
203
- # then remove `disabled` from the matching tool row.
201
+ # Production dsh does not install these optional providers. Install the
202
+ # matching Bundle in this Profile and restart the Host, then copy this
203
+ # preset and remove `disabled` from the matching tool row. Host availability
204
+ # alone grants no tool.
204
205
  - id: tool-subagent-codex
205
206
  name: '@deepseek-ai/dsh-tool-subagent'
206
207
  disabled: true
@@ -185,9 +185,10 @@
185
185
  toolName: subagent_fork
186
186
  backgroundMode: continuable
187
187
 
188
- # Production dsh does not install these optional providers. An opting-in
189
- # Profile mounts each provider once on the host plane; copy this preset,
190
- # then remove `disabled` from the matching tool row.
188
+ # Production dsh does not install these optional providers. Install the
189
+ # matching Bundle in this Profile and restart the Host, then copy this
190
+ # preset and remove `disabled` from the matching tool row. Host availability
191
+ # alone grants no tool.
191
192
  - id: tool-subagent-codex
192
193
  name: '@deepseek-ai/dsh-tool-subagent'
193
194
  disabled: true
@@ -123,7 +123,16 @@ After a clean mount-validation, ask the user to start a session on the new prese
123
123
 
124
124
  ## Native product subagents
125
125
 
126
- Codex and Claude Code providers belong on the host plane but are not installed by production `dsh`. The active Profile must install and mount the selected provider before a preset can expose its ordinary delegation-tool row; never move a product provider into the preset and never add a product-specific settings field.
126
+ Codex and Claude Code providers are independent optional Profile Bundles. Install only the products a Profile needs, then restart the Profile so its Host registers those providers:
127
+
128
+ ```sh
129
+ dsh plugin --profile <name> add @deepseek-ai/dsh-subagent-codex
130
+ dsh plugin --profile <name> add @deepseek-ai/dsh-subagent-claude-code
131
+ dsh plugin --profile <name> remove @deepseek-ai/dsh-subagent-codex
132
+ dsh plugin --profile <name> remove @deepseek-ai/dsh-subagent-claude-code
133
+ ```
134
+
135
+ Each Bundle owns its Host availability; the preset separately grants one Agent its ordinary delegation tool. Never move a product provider into the preset and never add a product-specific settings field. Removing one package withdraws only that provider on the next Profile start.
127
136
 
128
137
  Copy these disabled templates from a shipped full preset and remove `disabled` only for the products the user requested:
129
138
 
@@ -147,7 +156,9 @@ Copy these disabled templates from a shipped full preset and remove `disabled` o
147
156
  maxDepth: provider-managed
148
157
  ```
149
158
 
150
- The two rows are independent. Leaving both disabled preserves the copied preset, enabling one exposes only that product tool, and enabling both exposes both. Production `dsh` does not install or mount either optional provider: before enabling a row, the Profile must install the matching `@deepseek-ai/dsh-subagent-codex` or `@deepseek-ai/dsh-subagent-claude-code` package and mount it once on the host plane. A preset cannot provide that host dependency. `backgroundMode: one-shot` keeps omitted or `false` calls in the foreground and lets explicit `run_in_background: true` return a generic Job id. Full presets already carry `tool-jobs`, while the base host carries the job registry; retain both so `job_output`, `job_list`, `job_kill`, cancellation, and completion notices stay available. The host must also provide `codex` or `claude` on `PATH`; the preset does not install, authenticate, select a model for, or probe either product.
159
+ For additional named Codex or Claude Code instances, mount a separate host-plane provider row for each instance with a unique `providerName`, then add a separate preset tool row whose `provider` exactly matches that name and whose `toolName` is also unique. Keep the shipped rows for the default `codex` and `claude-code` names; do not reuse one tool row for several providers or derive either name from permission or environment settings.
160
+
161
+ The two rows are independent. Leaving both disabled preserves the copied preset, enabling one exposes only that product tool, and enabling both exposes both. Production `dsh` does not install either optional provider: before enabling a row, install the matching `@deepseek-ai/dsh-subagent-codex` or `@deepseek-ai/dsh-subagent-claude-code` Bundle in the Profile and restart it. Each Bundle registers its dormant default provider and exclusively uses its pinned package-local platform CLI; additional named instances use extra host-plane rows from the same installed package. A preset cannot provide that host dependency. `backgroundMode: one-shot` keeps omitted or `false` calls in the foreground and lets explicit `run_in_background: true` return a generic Job id. Full presets already carry `tool-jobs`, while the base host carries the job registry; retain both so `job_output`, `job_list`, `job_kill`, cancellation, and completion notices stay available. Installing a Bundle or composing a preset row does not start a product, authenticate an account, select a model, probe credentials, or manage native product settings.
151
162
 
152
163
  ## What not to move into a preset
153
164
 
@@ -3,7 +3,8 @@
3
3
  # The persona is the complete system prompt, so global identity, Web orientation,
4
4
  # tool guidance, and later assembly listeners cannot add prompt text. Runtime
5
5
  # context snapshots are suppressed for this preset, and the model composes only
6
- # persistent `bash` and `str_replace_editor`. Context compaction is absent.
6
+ # the persistent shell (`bash` on POSIX, `pwsh` on win32) and
7
+ # `str_replace_editor`. Context compaction is absent.
7
8
 
8
9
  - id: persona
9
10
  name: '@deepseek-ai/dsh-persona'
@@ -15,6 +16,8 @@
15
16
  # The PTY registry is an agent-owned service, so it lives in an entry-local
16
17
  # realm. The backend still consumes the host sandbox policy and subprocess
17
18
  # implementation, while the tool registers into this agent's scoped catalog.
19
+ # Exactly one shell stack mounts per host: the bash stack gates off win32 and
20
+ # its pwsh twin gates off POSIX, mirroring the one-shot shell rows.
18
21
  - id: persistent-shell
19
22
  name: cordis:group
20
23
  group: true
@@ -26,11 +29,13 @@
26
29
 
27
30
  - id: terminal-bash
28
31
  name: '@deepseek-ai/dsh-terminal-bash'
32
+ disabled: !!js process.platform === 'win32'
29
33
  config:
30
34
  timeoutMs: 300000
31
35
 
32
36
  - id: persistent-bash
33
37
  name: '@deepseek-ai/dsh-tool-bash-persistent'
38
+ disabled: !!js process.platform === 'win32'
34
39
  config:
35
40
  timeoutMs: 300000
36
41
  description: |-
@@ -43,6 +48,27 @@
43
48
  * Please avoid commands that may produce a very large amount of output.
44
49
  * Please run long lived commands in the background, e.g. 'sleep 10 &' or start a server in the background.
45
50
 
51
+ - id: terminal-pwsh
52
+ name: '@deepseek-ai/dsh-terminal-bash'
53
+ disabled: !!js process.platform !== 'win32'
54
+ config:
55
+ shellDialect: pwsh
56
+ timeoutMs: 300000
57
+
58
+ - id: persistent-pwsh
59
+ name: '@deepseek-ai/dsh-tool-pwsh-persistent'
60
+ disabled: !!js process.platform !== 'win32'
61
+ config:
62
+ timeoutMs: 300000
63
+ description: |-
64
+ Run commands in a PowerShell shell
65
+ * When invoking this tool, the contents of the "command" parameter does NOT need to be XML-escaped.
66
+ * You don't have access to the internet via this tool.
67
+ * State is persistent across command calls and discussions with the user.
68
+ * Use native Windows paths (C:\...) and $env:NAME variables; this is PowerShell, not bash.
69
+ * Please avoid commands that may produce a very large amount of output.
70
+ * Please run long lived commands in the background, e.g. 'Start-Job' or start a server with Start-Process.
71
+
46
72
  # The bare local filesystem shadows the host's sandboxed provider only for this
47
73
  # preset. The editor shares that realm and requires absolute paths.
48
74
  - id: filesystem
@@ -197,9 +197,10 @@
197
197
  toolName: subagent_fork
198
198
  backgroundMode: continuable
199
199
 
200
- # Production dsh does not install these optional providers. An opting-in
201
- # Profile mounts each provider once on the host plane; copy this preset,
202
- # then remove `disabled` from the matching tool row.
200
+ # Production dsh does not install these optional providers. Install the
201
+ # matching Bundle in this Profile and restart the Host, then copy this
202
+ # preset and remove `disabled` from the matching tool row. Host availability
203
+ # alone grants no tool.
203
204
  - id: tool-subagent-codex
204
205
  name: '@deepseek-ai/dsh-tool-subagent'
205
206
  disabled: true
package/dist/grok-acp.js CHANGED
@@ -200,6 +200,45 @@ function permissionNotification(clientIdentifier, mode) {
200
200
  if (!mapped) return void 0;
201
201
  return extensionNotification("permissionNotification", { clientIdentifier, ...mapped });
202
202
  }
203
+ function stripLodySessionConfig(meta) {
204
+ if (!meta || typeof meta !== "object") return meta;
205
+ const lody = meta.lody;
206
+ if (!lody || typeof lody !== "object" || !Object.hasOwn(lody, "sessionConfig")) return meta;
207
+ const { sessionConfig: _sessionConfig, ...remainingLody } = lody;
208
+ const { lody: _lody, ...remainingMeta } = meta;
209
+ return Object.keys(remainingLody).length > 0 ? { ...remainingMeta, lody: remainingLody } : remainingMeta;
210
+ }
211
+ function readLodySessionConfigOption(meta, configId) {
212
+ if (!meta || typeof meta !== "object") return void 0;
213
+ const sessionConfig = meta.lody?.sessionConfig;
214
+ if (!sessionConfig || typeof sessionConfig !== "object" || sessionConfig.version !== 1 || !sessionConfig.configOptionValues || typeof sessionConfig.configOptionValues !== "object") {
215
+ return void 0;
216
+ }
217
+ const value = sessionConfig.configOptionValues[configId];
218
+ return typeof value === "string" || typeof value === "boolean" ? value : void 0;
219
+ }
220
+ function translateSessionStart(message) {
221
+ const params = message.params ?? {};
222
+ const permissionMode = readLodySessionConfigOption(params._meta, "permission_mode");
223
+ const mapped = typeof permissionMode === "string" ? PERMISSION_MODES[permissionMode] : void 0;
224
+ if (!mapped) return { message, permissionMode: void 0, notification: void 0 };
225
+ const clientIdentifier = params._meta?.clientIdentifier;
226
+ const translated = {
227
+ ...message,
228
+ params: {
229
+ ...params,
230
+ _meta: {
231
+ ...stripLodySessionConfig(params._meta),
232
+ yoloMode: mapped.yolo_mode
233
+ }
234
+ }
235
+ };
236
+ return {
237
+ message: translated,
238
+ permissionMode,
239
+ notification: mapped.auto_mode && typeof clientIdentifier === "string" ? permissionNotification(clientIdentifier, permissionMode) : void 0
240
+ };
241
+ }
203
242
  class GrokAcpCompatibilityProxy {
204
243
  constructor() {
205
244
  this.sessions = /* @__PURE__ */ new Map();
@@ -236,8 +275,12 @@ class GrokAcpCompatibilityProxy {
236
275
  handleClient(message) {
237
276
  if (!message || typeof message !== "object") return { toRuntime: [message], toClient: [] };
238
277
  const params = message.params ?? {};
239
- if (message.method === "session/new" || message.method === "session/load" || message.method === "session/resume") {
278
+ if (message.method === "session/new" || message.method === "session/load" || message.method === "session/resume" || message.method === "session/fork") {
240
279
  const clientIdentifier = params._meta?.clientIdentifier;
280
+ const translated2 = translateSessionStart(message);
281
+ if (translated2.permissionMode && typeof clientIdentifier === "string") {
282
+ this.permissionModes.set(clientIdentifier, translated2.permissionMode);
283
+ }
241
284
  if (message.id !== void 0) {
242
285
  this.pending.set(message.id, {
243
286
  kind: "session",
@@ -246,7 +289,10 @@ class GrokAcpCompatibilityProxy {
246
289
  clientIdentifier
247
290
  });
248
291
  }
249
- return { toRuntime: [message], toClient: [] };
292
+ return {
293
+ toRuntime: translated2.notification ? [translated2.notification, translated2.message] : [translated2.message],
294
+ toClient: []
295
+ };
250
296
  }
251
297
  if (message.method === "session/prompt") {
252
298
  if (message.id !== void 0) {
package/dist/index.js CHANGED
@@ -42,7 +42,7 @@ import { performance as performance$1 } from "perf_hooks";
42
42
  import require$$0$9 from "net";
43
43
  import require$$4$2 from "tls";
44
44
  import require$$7$2, { fileURLToPath as fileURLToPath$1, pathToFileURL as pathToFileURL$1 } from "url";
45
- import { D as DEEPSEEK_HARNESS_PERMISSION_MODES, a as DEEPSEEK_HARNESS_AGENT_PRESETS, b as DEEPSEEK_HARNESS_MODELS, c as DEEPSEEK_HARNESS_REASONING_OPTIONS, A as ACP_EXTENSION_DSH_CAPABILITY_SOURCE_VERSION, d as createDeepSeekHarnessCordisConfig, e as ACP_EXTENSION_DSH_VERSION, f as ACP_EXTENSION_DSH_PROFILE_REVISION, g as ACP_EXTENSION_DSH_QUERY_PATH_ENV, h as ACP_EXTENSION_DSH_SESSION_ROOT_ENV, i as DEEPSEEK_HARNESS_NPX_PACKAGES, j as DEEPSEEK_HARNESS_VERSION, k as DEEPSEEK_HARNESS_DEFAULT_SESSION_COMPRESSION } from "./chunks/profile-RfMzWliN.js";
45
+ import { D as DEEPSEEK_HARNESS_PERMISSION_MODES, a as DEEPSEEK_HARNESS_AGENT_PRESETS, b as DEEPSEEK_HARNESS_MODELS, c as DEEPSEEK_HARNESS_REASONING_OPTIONS, A as ACP_EXTENSION_DSH_CAPABILITY_SOURCE_VERSION, d as createDeepSeekHarnessCordisConfig, e as ACP_EXTENSION_DSH_VERSION, f as ACP_EXTENSION_DSH_PROFILE_REVISION, g as ACP_EXTENSION_DSH_QUERY_PATH_ENV, h as ACP_EXTENSION_DSH_SESSION_ROOT_ENV, i as DEEPSEEK_HARNESS_NPX_PACKAGES, j as DEEPSEEK_HARNESS_VERSION, k as DEEPSEEK_HARNESS_DEFAULT_SESSION_COMPRESSION } from "./chunks/profile-Cxxl5hCq.js";
46
46
  import assert from "assert";
47
47
  import * as fs$2 from "fs/promises";
48
48
  import fs__default$2 from "fs/promises";
@@ -4324,7 +4324,7 @@ Upgrade Node, then re-run: npx lody@latest`;
4324
4324
  }
4325
4325
  const name$2 = "lody";
4326
4326
  const name$1 = "@lody/cli-cloud";
4327
- const version$9 = "0.84.0";
4327
+ const version$9 = "0.85.0";
4328
4328
  const type$2 = "module";
4329
4329
  const scripts = {
4330
4330
  "dev": "node dev.mjs",
@@ -113527,6 +113527,9 @@ ${incoming}`).output;
113527
113527
  this.logger = options.logger;
113528
113528
  this.terminalManager = options.terminalManager;
113529
113529
  this.terminalEnabled = options.terminalEnabled ?? true;
113530
+ this.configOptionValues = {
113531
+ ...options.configOptionValues ?? {}
113532
+ };
113530
113533
  }
113531
113534
  connection = null;
113532
113535
  lastSessionUpdateAtMs = Date.now();
@@ -113550,6 +113553,7 @@ ${incoming}`).output;
113550
113553
  sessionWorkdir = null;
113551
113554
  agentMcpCapabilities;
113552
113555
  configOptions = [];
113556
+ configOptionValues;
113553
113557
  legacySessionModelState = null;
113554
113558
  currentModel;
113555
113559
  codexImageGenerationToolCallIds = /* @__PURE__ */ new Set();
@@ -114254,13 +114258,35 @@ ${incoming}`).output;
114254
114258
  getGrokClientIdentifier() {
114255
114259
  return this.options.agentConfig?.cliType === "builtin" && this.options.agentConfig.agentType === "grok" ? `lody:${this.options.sessionId}` : void 0;
114256
114260
  }
114257
- getGrokSessionMeta() {
114261
+ getSessionStartMeta(forkSessionTurnId) {
114258
114262
  const clientIdentifier = this.getGrokClientIdentifier();
114259
- return clientIdentifier ? {
114263
+ const lody = {
114264
+ ...forkSessionTurnId !== void 0 ? {
114265
+ forkAtTurn: {
114266
+ version: 1,
114267
+ turnId: forkSessionTurnId
114268
+ }
114269
+ } : {},
114270
+ ...Object.keys(this.configOptionValues).length > 0 ? {
114271
+ sessionConfig: {
114272
+ version: 1,
114273
+ configOptionValues: {
114274
+ ...this.configOptionValues
114275
+ }
114276
+ }
114277
+ } : {}
114278
+ };
114279
+ if (clientIdentifier === void 0 && Object.keys(lody).length === 0) return {};
114280
+ return {
114260
114281
  _meta: {
114261
- clientIdentifier
114282
+ ...clientIdentifier !== void 0 ? {
114283
+ clientIdentifier
114284
+ } : {},
114285
+ ...Object.keys(lody).length > 0 ? {
114286
+ lody
114287
+ } : {}
114262
114288
  }
114263
- } : {};
114289
+ };
114264
114290
  }
114265
114291
  isCurrentAcpSession(acpSessionId) {
114266
114292
  return this.acpSessionId !== null && acpSessionId === this.acpSessionId;
@@ -114280,7 +114306,7 @@ ${incoming}`).output;
114280
114306
  const connection2 = new ClientSideConnection(() => this, stream2);
114281
114307
  this.connection = connection2;
114282
114308
  const grokClientIdentifier = this.getGrokClientIdentifier();
114283
- const grokSessionMeta = this.getGrokSessionMeta();
114309
+ const sessionStartMeta = this.getSessionStartMeta();
114284
114310
  this.logger.debug(`[${this.options.sessionId}] Starting ACP client (workdir=${workdir} resumeSessionId=${resumeSessionId ?? "none"} forkSessionId=${forkSessionId ?? "none"})`);
114285
114311
  if (resumeSessionId && forkSessionId) {
114286
114312
  throw new Error("[ACP_SESSION_START_INVALID] resumeSessionId and forkSessionId are exclusive");
@@ -114476,16 +114502,7 @@ ${incoming}`).output;
114476
114502
  sessionId: forkSessionId,
114477
114503
  cwd: workdir,
114478
114504
  mcpServers,
114479
- ...forkSessionTurnId ? {
114480
- _meta: {
114481
- lody: {
114482
- forkAtTurn: {
114483
- version: 1,
114484
- turnId: forkSessionTurnId
114485
- }
114486
- }
114487
- }
114488
- } : {}
114505
+ ...this.getSessionStartMeta(forkSessionTurnId)
114489
114506
  }), startupAbort), this.logger, "connection.unstable_forkSession", this.options.sessionId, ACP_FORK_SESSION_TIMEOUT_MS);
114490
114507
  this.logger.debug(`[${this.options.sessionId}] ACP fork succeeded in ${Math.round(performance$1.now() - forkStart)}ms (sourceAcpSessionId=${forkSessionId}, acpSessionId=${sessionResponse.sessionId})`);
114491
114508
  } catch (error2) {
@@ -114520,7 +114537,7 @@ ${incoming}`).output;
114520
114537
  sessionId: resumeSessionId,
114521
114538
  cwd: workdir,
114522
114539
  mcpServers,
114523
- ...grokSessionMeta
114540
+ ...sessionStartMeta
114524
114541
  }), startupAbort), this.logger, "connection.loadSession", this.options.sessionId, ACP_LOAD_SESSION_TIMEOUT_MS);
114525
114542
  const loadDurationMs = performance$1.now() - loadStart;
114526
114543
  sessionResponse = {
@@ -114562,7 +114579,7 @@ ${incoming}`).output;
114562
114579
  sessionId: resumeSessionId,
114563
114580
  cwd: workdir,
114564
114581
  mcpServers,
114565
- ...grokSessionMeta
114582
+ ...sessionStartMeta
114566
114583
  }), startupAbort), this.logger, "connection.resumeSession", this.options.sessionId, ACP_RESUME_SESSION_TIMEOUT_MS);
114567
114584
  const resumeDurationMs = performance$1.now() - resumeStart;
114568
114585
  sessionResponse = {
@@ -114602,7 +114619,7 @@ ${incoming}`).output;
114602
114619
  sessionResponse = await withTimeout$2(withAbort(connection2.newSession({
114603
114620
  cwd: workdir,
114604
114621
  mcpServers,
114605
- ...grokSessionMeta
114622
+ ...sessionStartMeta
114606
114623
  }), startupAbort), this.logger, "connection.newSession", this.options.sessionId, ACP_NEW_SESSION_TIMEOUT_MS);
114607
114624
  } catch (error2) {
114608
114625
  if (isAcpAuthenticationRequired(error2)) {
@@ -114669,7 +114686,7 @@ ${incoming}`).output;
114669
114686
  return await withTimeout$2(connection2.newSession({
114670
114687
  cwd: workdir,
114671
114688
  mcpServers,
114672
- ...this.getGrokSessionMeta()
114689
+ ...this.getSessionStartMeta()
114673
114690
  }), this.logger, "connection.newSession.editAndResend", this.options.sessionId, timeoutMs);
114674
114691
  } catch (error2) {
114675
114692
  throw new Error(`[ACP_SESSION_PREPARE_FAILED] ${formatErrorMessage(error2)}`, {
@@ -114685,14 +114702,7 @@ ${incoming}`).output;
114685
114702
  sessionId: sourceSessionId,
114686
114703
  cwd: workdir,
114687
114704
  mcpServers,
114688
- _meta: {
114689
- lody: {
114690
- forkAtTurn: {
114691
- version: 1,
114692
- turnId: forkSessionTurnId
114693
- }
114694
- }
114695
- }
114705
+ ...this.getSessionStartMeta(forkSessionTurnId)
114696
114706
  }), this.logger, "connection.unstable_forkSession.editAndResend", this.options.sessionId, timeoutMs);
114697
114707
  } catch (error2) {
114698
114708
  throw new Error(`[ACP_FORK_FAILED] ${formatErrorMessage(error2)}`, {
@@ -114954,6 +114964,7 @@ ${incoming}`).output;
114954
114964
  this.currentModel = this.resolveModelInfo(this.currentModel.modelId);
114955
114965
  }
114956
114966
  }
114967
+ if (result) this.configOptionValues[configId] = value;
114957
114968
  this.logger.debug(`[${this.options.sessionId}] ACP session config option set: ${configId}=${value}`);
114958
114969
  return result?.configOptions;
114959
114970
  }
@@ -125493,6 +125504,7 @@ ${error2.message}` : execaMessage;
125493
125504
  return {
125494
125505
  command: "npx",
125495
125506
  args: [
125507
+ "--force",
125496
125508
  "--prefer-offline",
125497
125509
  "-y",
125498
125510
  ...DEEPSEEK_HARNESS_NPX_PACKAGES.flatMap((packageName) => [
@@ -126909,6 +126921,7 @@ ${fallbackStderrTail}` : errorMessage2;
126909
126921
  machineId: options.machineId,
126910
126922
  terminalManager: options.terminalManager,
126911
126923
  agentConfig: options.agentConfig,
126924
+ configOptionValues: options.configOptionValues,
126912
126925
  launcher: options.launcher,
126913
126926
  terminalEnabled: options.terminalEnabled,
126914
126927
  onStartupStage: options.onStartupStage,
@@ -133980,6 +133993,7 @@ The postId is ${normalizedFeedbackPostId}. Use the feedback-progress-reporter sk
133980
133993
  workspaceId: message.workspaceId,
133981
133994
  agentCliType: acpSessionConfig.cliType,
133982
133995
  agentType: acpSessionConfig.agentType,
133996
+ configOptionValues: acpSessionConfig.configOptionValues,
133983
133997
  mcpServerIds: acpSessionConfig.mcpServerIds ?? [],
133984
133998
  customAcp: resumeCustomAcp,
133985
133999
  runtimeOverrides: resumeRuntimeOverrides,
@@ -134477,6 +134491,7 @@ The postId is ${normalizedFeedbackPostId}. Use the feedback-progress-reporter sk
134477
134491
  workspaceId,
134478
134492
  agentCliType: acpSessionConfig.cliType,
134479
134493
  agentType: acpSessionConfig.agentType,
134494
+ configOptionValues: acpSessionConfig.configOptionValues,
134480
134495
  mcpServerIds: acpSessionConfig.mcpServerIds ?? [],
134481
134496
  agentConfigId: existingMeta?.agentConfigId,
134482
134497
  customAcp: acpSessionConfig.customAcp,
@@ -180557,6 +180572,7 @@ export PATH=${toSingleQuotedShellString(ghShimBinDir)}:"$PATH"
180557
180572
  cliType: callbacks.cliType,
180558
180573
  agentType: callbacks.agentType
180559
180574
  },
180575
+ configOptionValues: this.config.configOptionValues,
180560
180576
  launcher,
180561
180577
  workspaceId: this.config.workspaceId,
180562
180578
  machineId: this.config.machineId,
@@ -181286,14 +181302,19 @@ export PATH=${toSingleQuotedShellString(ghShimBinDir)}:"$PATH"
181286
181302
  }
181287
181303
  };
181288
181304
  }
181289
- function buildSessionPreparationCompatibility(launchSource, mcpServerIds) {
181305
+ function buildSessionPreparationCompatibility(launchSource, mcpServerIds, configOptionValues) {
181290
181306
  return {
181291
181307
  launch: buildSessionLaunchConfig({
181292
181308
  customAcp: launchSource?.customAcp,
181293
181309
  runtimeOverrides: launchSource?.runtimeOverrides,
181294
181310
  env: launchSource?.env
181295
181311
  }),
181296
- mcpServerIds: normalizeMcpServerIdsForDedup(mcpServerIds)
181312
+ runConfig: normalizeSessionPreparationRunConfigForDedup({
181313
+ mcpServerIds: mcpServerIds ? [
181314
+ ...mcpServerIds
181315
+ ] : void 0,
181316
+ configOptionValues
181317
+ })
181297
181318
  };
181298
181319
  }
181299
181320
  function agentConfigMatchesPreparation(agentConfig, spec, machineId) {
@@ -181408,7 +181429,7 @@ export PATH=${toSingleQuotedShellString(ghShimBinDir)}:"$PATH"
181408
181429
  return null;
181409
181430
  }
181410
181431
  const current2 = resource.readCurrentLaunchConfig(sessionMeta);
181411
- if (!current2 || !isDeepStrictEqual(resource.compatibility, buildSessionPreparationCompatibility(current2.config, resource.config.mcpServerIds))) {
181432
+ if (!current2 || !isDeepStrictEqual(resource.compatibility, buildSessionPreparationCompatibility(current2.config, resource.config.mcpServerIds, resource.config.configOptionValues))) {
181412
181433
  return null;
181413
181434
  }
181414
181435
  return {
@@ -181449,7 +181470,7 @@ export PATH=${toSingleQuotedShellString(ghShimBinDir)}:"$PATH"
181449
181470
  await this.preparationService.discard(sessionId);
181450
181471
  return await this.createSessionInnerWithAgent(config2, agentStart);
181451
181472
  }
181452
- const compatibility = buildSessionPreparationCompatibility(config2, config2.mcpServerIds);
181473
+ const compatibility = buildSessionPreparationCompatibility(config2, config2.mcpServerIds, config2.configOptionValues);
181453
181474
  const claim = this.preparationService.claim({
181454
181475
  sessionId,
181455
181476
  requesterUserId: config2.requesterUserId,
@@ -181468,7 +181489,7 @@ export PATH=${toSingleQuotedShellString(ghShimBinDir)}:"$PATH"
181468
181489
  cliType: config2.agentCliType,
181469
181490
  agentType: config2.agentType
181470
181491
  });
181471
- return current2 !== null && isDeepStrictEqual(resource.compatibility, buildSessionPreparationCompatibility(current2.config, config2.mcpServerIds));
181492
+ return current2 !== null && isDeepStrictEqual(resource.compatibility, buildSessionPreparationCompatibility(current2.config, config2.mcpServerIds, config2.configOptionValues));
181472
181493
  }
181473
181494
  });
181474
181495
  if (claim.status === "miss") {
@@ -181624,6 +181645,7 @@ export PATH=${toSingleQuotedShellString(ghShimBinDir)}:"$PATH"
181624
181645
  agentConfigId: spec.agentConfigId,
181625
181646
  agentCliType: spec.cliType,
181626
181647
  agentType: spec.agentType,
181648
+ configOptionValues: spec.runConfig?.configOptionValues,
181627
181649
  mcpServerIds: spec.runConfig?.mcpServerIds ?? [],
181628
181650
  customAcp: agentConfig.customAcp,
181629
181651
  runtimeOverrides: agentConfig.runtimeOverrides,
@@ -181638,7 +181660,7 @@ export PATH=${toSingleQuotedShellString(ghShimBinDir)}:"$PATH"
181638
181660
  userName: user.name,
181639
181661
  userEmail: user.email
181640
181662
  };
181641
- const compatibility = buildSessionPreparationCompatibility(config2, config2.mcpServerIds);
181663
+ const compatibility = buildSessionPreparationCompatibility(config2, config2.mcpServerIds, config2.configOptionValues);
181642
181664
  const ghTokenInjected = await this.prepareGitHubRepoSessionConfig(config2);
181643
181665
  signal.throwIfAborted();
181644
181666
  const launch = await resolveACPProcessLaunchAsync({
@@ -219003,7 +219025,7 @@ ${page}${helpTipBottom}${choiceDescription}${ansiEscapes.cursorHide}`;
219003
219025
  data = createReviewBundleSnapshot(bundle);
219004
219026
  }
219005
219027
  const { injectReviewSnapshot } = await import("./chunks/index-VoI6Ds2-.js");
219006
- const { resolveReviewViewerTemplate } = await import("./chunks/review-viewer-BZC6lRid.js").then(async (m) => {
219028
+ const { resolveReviewViewerTemplate } = await import("./chunks/review-viewer-oYzxdgq4.js").then(async (m) => {
219007
219029
  await m.__tla;
219008
219030
  return m;
219009
219031
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lody",
3
- "version": "0.84.0",
3
+ "version": "0.85.0",
4
4
  "description": "Lody Agent CLI tool for managing remote command execution",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",