@ycodium-ai/agent-dsh 0.2.2976 → 0.2.2980

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +7 -0
  2. package/dist/index.js +551 -402
  3. package/package.json +3 -3
package/README.md CHANGED
@@ -29,6 +29,13 @@ Facts:
29
29
  `$DSH_HOME/.credentials.yaml` `refs.DEEPSEEK_API_KEY`, then `$DSH_HOME/.env`. A `DEEPSEEK_BASE_URL` that is
30
30
  not `api.deepseek.com` reports `customEndpoint` and sends nothing. No `readTokenUsage`: DSH's ACP reply
31
31
  carries no usage and its session log (`session.v4.jsonl.zstd`) has no per-event timestamps.
32
+ - User stop: `ExecutorInstance.openCommandProcesses` lists the shell tool calls still running in the
33
+ turn (`title` `bash` / `pwsh`, not `run_in_background`) with an exact argv check for each, so the
34
+ host can confirm the command's process ended and end what DSH left behind. The process shapes are
35
+ the ones measured with dsh 0.1.5-rc.2 and 0.2.0-rc.2 on Windows 10 and Ubuntu 22.04
36
+ (`src/openCommands.ts`); a release that wraps commands differently is simply not recognised and the
37
+ UI says the command may still be running. macOS and a Linux machine where DSH uses a systemd user
38
+ scope have not been measured.
32
39
  - Manifest permission is `{ kind: "executor" }`.
33
40
  - Session model switching is `unsupported` on the card: the plugin does not switch
34
41
  models inside a running session.
package/dist/index.js CHANGED
@@ -66,7 +66,7 @@ var require_identity = __commonJS({
66
66
  }
67
67
  return false;
68
68
  }
69
- function isNode(node2) {
69
+ function isNode2(node2) {
70
70
  if (node2 && typeof node2 === "object")
71
71
  switch (node2[NODE_TYPE]) {
72
72
  case ALIAS:
@@ -90,7 +90,7 @@ var require_identity = __commonJS({
90
90
  exports.isCollection = isCollection;
91
91
  exports.isDocument = isDocument;
92
92
  exports.isMap = isMap;
93
- exports.isNode = isNode;
93
+ exports.isNode = isNode2;
94
94
  exports.isPair = isPair;
95
95
  exports.isScalar = isScalar;
96
96
  exports.isSeq = isSeq;
@@ -31868,383 +31868,6 @@ function deriveToolActivityPresentation(input2) {
31868
31868
  };
31869
31869
  }
31870
31870
 
31871
- // ../../packages/ycodium-acp-executor/src/events.ts
31872
- function canonicalRequestTypeFromAcpKind(kind) {
31873
- switch (kind) {
31874
- case "execute":
31875
- return "exec_command_approval";
31876
- case "read":
31877
- return "file_read_approval";
31878
- case "edit":
31879
- case "delete":
31880
- case "move":
31881
- return "file_change_approval";
31882
- case "fetch":
31883
- return "web_fetch_approval";
31884
- case "search":
31885
- return "web_search_approval";
31886
- default:
31887
- return "dynamic_tool_call";
31888
- }
31889
- }
31890
- function fileChangesFromAcpPermission(permissionRequest) {
31891
- const content = permissionRequest.toolCall?.data["content"];
31892
- const changes = Array.isArray(content) ? content.flatMap((entry) => {
31893
- if (entry === null || typeof entry !== "object") {
31894
- return [];
31895
- }
31896
- const block = entry;
31897
- if (block["type"] !== "diff" || typeof block["path"] !== "string" || typeof block["newText"] !== "string") {
31898
- return [];
31899
- }
31900
- const oldText = typeof block["oldText"] === "string" ? block["oldText"] : void 0;
31901
- return [
31902
- {
31903
- path: block["path"],
31904
- changeKind: oldText === void 0 ? "add" : "modify",
31905
- content: {
31906
- kind: "replace",
31907
- ...oldText !== void 0 ? { oldText } : {},
31908
- newText: block["newText"]
31909
- }
31910
- }
31911
- ];
31912
- }) : [];
31913
- if (changes.length > 0) {
31914
- return changes;
31915
- }
31916
- if (canonicalRequestTypeFromAcpKind(permissionRequest.kind) !== "file_change_approval") {
31917
- return void 0;
31918
- }
31919
- const locations = permissionRequest.toolCall?.data["locations"];
31920
- const paths = Array.isArray(locations) ? locations.flatMap((entry) => {
31921
- const path = entry?.["path"];
31922
- return typeof path === "string" && path.trim().length > 0 ? [path] : [];
31923
- }) : [];
31924
- return paths.length > 0 ? paths.map((path) => ({ path, omitted: "unavailable" })) : void 0;
31925
- }
31926
- function runtimeItemStatusFromAcpToolStatus(status) {
31927
- switch (status) {
31928
- case "pending":
31929
- case "inProgress":
31930
- return "inProgress";
31931
- case "completed":
31932
- return "completed";
31933
- case "failed":
31934
- return "failed";
31935
- default:
31936
- return void 0;
31937
- }
31938
- }
31939
- function makeAcpRequestOpenedEvent(input2) {
31940
- const requestType = canonicalRequestTypeFromAcpKind(input2.permissionRequest.kind);
31941
- const toolName = requestType === "dynamic_tool_call" ? input2.permissionRequest.toolCall?.title : void 0;
31942
- return {
31943
- type: "request.opened",
31944
- ...input2.stamp,
31945
- provider: input2.provider,
31946
- threadId: input2.threadId,
31947
- ...input2.turnId !== void 0 ? { turnId: input2.turnId } : {},
31948
- requestId: input2.requestId,
31949
- payload: {
31950
- requestType,
31951
- detail: input2.detail,
31952
- ...toolName ? { toolName } : {},
31953
- args: input2.args,
31954
- ...input2.options ? { options: input2.options } : {},
31955
- ...input2.fileChanges ? { fileChanges: input2.fileChanges } : {},
31956
- declineReasonRelay: "queued"
31957
- },
31958
- raw: {
31959
- source: input2.source,
31960
- method: input2.method,
31961
- payload: input2.rawPayload
31962
- }
31963
- };
31964
- }
31965
- function makeAcpRequestResolvedEvent(input2) {
31966
- return {
31967
- type: "request.resolved",
31968
- ...input2.stamp,
31969
- provider: input2.provider,
31970
- threadId: input2.threadId,
31971
- ...input2.turnId !== void 0 ? { turnId: input2.turnId } : {},
31972
- requestId: input2.requestId,
31973
- payload: {
31974
- requestType: canonicalRequestTypeFromAcpKind(input2.permissionRequest.kind),
31975
- decision: input2.decision,
31976
- ...input2.reason ? { reason: input2.reason } : {}
31977
- }
31978
- };
31979
- }
31980
- function makeAcpPlanUpdatedEvent(input2) {
31981
- return {
31982
- type: "turn.plan.updated",
31983
- ...input2.stamp,
31984
- provider: input2.provider,
31985
- threadId: input2.threadId,
31986
- ...input2.turnId !== void 0 ? { turnId: input2.turnId } : {},
31987
- payload: input2.payload,
31988
- raw: {
31989
- source: input2.source,
31990
- method: input2.method,
31991
- payload: input2.rawPayload
31992
- }
31993
- };
31994
- }
31995
- function makeAcpToolCallEvent(input2) {
31996
- const runtimeStatus = runtimeItemStatusFromAcpToolStatus(input2.toolCall.status);
31997
- const { data } = input2.toolCall;
31998
- return {
31999
- type: input2.toolCall.status === "completed" || input2.toolCall.status === "failed" ? "item.completed" : "item.updated",
32000
- ...input2.stamp,
32001
- provider: input2.provider,
32002
- threadId: input2.threadId,
32003
- ...input2.turnId !== void 0 ? { turnId: input2.turnId } : {},
32004
- itemId: input2.toolCall.toolCallId,
32005
- payload: {
32006
- itemType: canonicalItemTypeFromAcpToolKind(input2.toolCall.kind),
32007
- ...runtimeStatus ? { status: runtimeStatus } : {},
32008
- ...input2.toolCall.title ? { title: input2.toolCall.title } : {},
32009
- ...input2.toolCall.detail ? { detail: input2.toolCall.detail } : {},
32010
- ...Object.keys(data).length > 0 ? { data } : {}
32011
- },
32012
- raw: {
32013
- source: "acp.jsonrpc",
32014
- method: "session/update",
32015
- payload: input2.rawPayload
32016
- }
32017
- };
32018
- }
32019
- function makeAcpAssistantItemEvent(input2) {
32020
- return {
32021
- type: input2.lifecycle,
32022
- ...input2.stamp,
32023
- provider: input2.provider,
32024
- threadId: input2.threadId,
32025
- ...input2.turnId !== void 0 ? { turnId: input2.turnId } : {},
32026
- itemId: input2.itemId,
32027
- payload: {
32028
- itemType: "assistant_message",
32029
- status: input2.lifecycle === "item.completed" ? "completed" : "inProgress"
32030
- }
32031
- };
32032
- }
32033
- function makeAcpContentDeltaEvent(input2) {
32034
- return {
32035
- type: "content.delta",
32036
- ...input2.stamp,
32037
- provider: input2.provider,
32038
- threadId: input2.threadId,
32039
- ...input2.turnId !== void 0 ? { turnId: input2.turnId } : {},
32040
- ...input2.itemId ? { itemId: input2.itemId } : {},
32041
- payload: {
32042
- streamKind: input2.streamKind ?? "assistant_text",
32043
- delta: input2.text
32044
- },
32045
- raw: {
32046
- source: "acp.jsonrpc",
32047
- method: "session/update",
32048
- payload: input2.rawPayload
32049
- }
32050
- };
32051
- }
32052
-
32053
- // ../../packages/ycodium-acp-executor/src/config-options.ts
32054
- function isRecord4(value) {
32055
- return typeof value === "object" && value !== null && !Array.isArray(value);
32056
- }
32057
- function asString(value) {
32058
- return typeof value === "string" ? value : void 0;
32059
- }
32060
- function normalizedField(option, key) {
32061
- return asString(option[key])?.trim().toLowerCase() ?? "";
32062
- }
32063
- function looksLikeEffortOption(option) {
32064
- const id = normalizedField(option, "id");
32065
- const name = normalizedField(option, "name");
32066
- return id === "effort" || id === "reasoning" || name === "effort" || name === "reasoning" || name.includes("effort") || name.includes("reasoning") || normalizedField(option, "category") === "thought_level";
32067
- }
32068
- function flattenChoices(rawOptions, currentValue) {
32069
- if (!Array.isArray(rawOptions)) return [];
32070
- const out = [];
32071
- const seen = /* @__PURE__ */ new Set();
32072
- const push = (entry) => {
32073
- if (!isRecord4(entry)) return;
32074
- const value = asString(entry["value"]);
32075
- if (value === void 0 || seen.has(value)) return;
32076
- seen.add(value);
32077
- const description = asString(entry["description"])?.trim();
32078
- const name = asString(entry["name"])?.trim();
32079
- out.push({
32080
- value,
32081
- ...name ? { name } : {},
32082
- label: name || value,
32083
- ...description ? { description } : {},
32084
- ...currentValue !== void 0 && currentValue === value ? { isDefault: true } : {}
32085
- });
32086
- };
32087
- for (const entry of rawOptions) {
32088
- if (isRecord4(entry) && Array.isArray(entry["options"])) {
32089
- for (const nested of entry["options"]) push(nested);
32090
- continue;
32091
- }
32092
- push(entry);
32093
- }
32094
- return out;
32095
- }
32096
- function findAcpEffortConfig(configOptions) {
32097
- if (!Array.isArray(configOptions)) return void 0;
32098
- const candidates = configOptions.filter(isRecord4).filter((option) => normalizedField(option, "type") === "select").filter(looksLikeEffortOption);
32099
- if (candidates.length === 0) return void 0;
32100
- const picked = candidates.find((option) => normalizedField(option, "category") === "model_option") ?? candidates.find((option) => normalizedField(option, "id") === "effort") ?? candidates.find((option) => normalizedField(option, "category") === "thought_level") ?? candidates[0];
32101
- if (picked === void 0) return void 0;
32102
- const configId = asString(picked["id"])?.trim();
32103
- if (!configId) return void 0;
32104
- const choices = flattenChoices(picked["options"], asString(picked["currentValue"])?.trim());
32105
- if (choices.length === 0) return void 0;
32106
- return {
32107
- configId,
32108
- label: asString(picked["name"])?.trim() ?? "",
32109
- choices
32110
- };
32111
- }
32112
- function acpModelChoicesFromConfigOptions(configOptions) {
32113
- if (!Array.isArray(configOptions)) return void 0;
32114
- const records = configOptions.filter(isRecord4);
32115
- const modelOption = records.find((option) => normalizedField(option, "category") === "model") ?? records.find(
32116
- (option) => normalizedField(option, "id") === "model" && normalizedField(option, "type") === "select"
32117
- );
32118
- if (modelOption === void 0) return void 0;
32119
- if (!asString(modelOption["id"])?.trim()) return void 0;
32120
- return flattenChoices(modelOption["options"], asString(modelOption["currentValue"])?.trim());
32121
- }
32122
-
32123
- // ../../packages/ycodium-acp-executor/src/runtime-mode.ts
32124
- function isRecord5(value) {
32125
- return typeof value === "object" && value !== null && !Array.isArray(value);
32126
- }
32127
- function asString2(value) {
32128
- return typeof value === "string" ? value : void 0;
32129
- }
32130
- function acpModeConfigId(setup) {
32131
- if (!isRecord5(setup)) return void 0;
32132
- const configOptions = setup["configOptions"];
32133
- if (!Array.isArray(configOptions)) return void 0;
32134
- for (const option of configOptions) {
32135
- if (!isRecord5(option)) continue;
32136
- if (asString2(option["category"])?.trim().toLowerCase() !== "mode") continue;
32137
- const id = asString2(option["id"])?.trim();
32138
- if (id) return id;
32139
- }
32140
- return void 0;
32141
- }
32142
-
32143
- // ../../packages/ycodium-acp-executor/src/handshake.ts
32144
- function acpInitializePayload(clientInfo, overrides) {
32145
- return {
32146
- protocolVersion: PROTOCOL_VERSION,
32147
- clientCapabilities: {
32148
- fs: {
32149
- readTextFile: false,
32150
- writeTextFile: false,
32151
- ...overrides?.fs
32152
- },
32153
- terminal: overrides?.terminal ?? false
32154
- },
32155
- clientInfo
32156
- };
32157
- }
32158
-
32159
- // ../../packages/ycodium-acp-executor/src/config-option-wiring.ts
32160
- var VENDOR_CATEGORY_PREFIX = "_";
32161
- var ACP_CONFIG_CATEGORY_HANDLING = {
32162
- mode: {
32163
- consumed: true,
32164
- via: "runtime-mode.ts\uFF1AacpAvailableModes / acpCurrentModeId / acpModeConfigId"
32165
- },
32166
- model: {
32167
- consumed: true,
32168
- via: "runtime-model.ts:extractModelConfigId \u2192 executor.ts:applyRequestedModel"
32169
- },
32170
- thought_level: {
32171
- consumed: true,
32172
- via: "config-options.ts:findAcpEffortConfig \u2192 executor.ts:applyRequestedEffort"
32173
- },
32174
- model_option: {
32175
- consumed: true,
32176
- // 精确说法:它不是**识别器**,是**优先级**。`looksLikeEffortOption` 先筛出候选,
32177
- // 标了 `model_option` 的在候选里排第一(厂商自己标的最准),排在 id 叫 `effort`
32178
- // 的和标 `thought_level` 的前面。光有这个 category 而 id/name 不像力度档的,
32179
- // 压根进不了候选。
32180
- via: "config-options.ts:findAcpEffortConfig\uFF08\u5019\u9009\u91CC\u7684\u6700\u9AD8\u4F18\u5148\u7EA7\uFF0C\u538B\u8FC7 thought_level\uFF09"
32181
- },
32182
- model_config: {
32183
- consumed: false,
32184
- note: "\u53EA\u6709\u5BBF\u4E3B\u7684 CursorProvider \u6D88\u8D39\u8FC7\uFF08context / fast / thinking \u4E09\u4E2A\u5F00\u5173\uFF09\u3002Cursor 2026-09-20 \u5E9F\u5F03\u5220\u9664\uFF0C\u8FD9\u4E00\u7C7B\u73B0\u5728\u6CA1\u6709\u6D88\u8D39\u70B9\uFF1B\u6CA1\u89C1\u8FC7\u522B\u5BB6\u7684\u771F\u5B9E\u8F7D\u8377\uFF0C\u5148\u8BB0\u8D26\u4E0D\u731C\u5F62\u72B6\u3002"
32185
- }
32186
- };
32187
- var KNOWN_CATEGORIES = new Set(Object.keys(ACP_CONFIG_CATEGORY_HANDLING));
32188
- function unhandledConfigCategories(configOptions) {
32189
- if (!configOptions) return [];
32190
- const seen = /* @__PURE__ */ new Set();
32191
- const out = [];
32192
- for (const option of configOptions) {
32193
- const category = option.category?.trim();
32194
- if (!category) continue;
32195
- if (KNOWN_CATEGORIES.has(category)) continue;
32196
- if (seen.has(category)) continue;
32197
- seen.add(category);
32198
- out.push({
32199
- category,
32200
- optionId: option.id.trim(),
32201
- vendorExtension: category.startsWith(VENDOR_CATEGORY_PREFIX)
32202
- });
32203
- }
32204
- return out;
32205
- }
32206
-
32207
- // ../../packages/ycodium-acp-executor/src/mutex.ts
32208
- var Mutex = class {
32209
- locked = false;
32210
- waiters = [];
32211
- get isLocked() {
32212
- return this.locked;
32213
- }
32214
- acquire() {
32215
- if (!this.locked) {
32216
- this.locked = true;
32217
- return Promise.resolve();
32218
- }
32219
- return new Promise((resolve2) => {
32220
- this.waiters.push(resolve2);
32221
- });
32222
- }
32223
- tryAcquire() {
32224
- if (this.locked) {
32225
- return false;
32226
- }
32227
- this.locked = true;
32228
- return true;
32229
- }
32230
- release() {
32231
- const next = this.waiters.shift();
32232
- if (next) {
32233
- next();
32234
- return;
32235
- }
32236
- this.locked = false;
32237
- }
32238
- async runExclusive(fn) {
32239
- await this.acquire();
32240
- try {
32241
- return await fn();
32242
- } finally {
32243
- this.release();
32244
- }
32245
- }
32246
- };
32247
-
32248
31871
  // ../../packages/ycodium-acp-executor/src/runtime-model.ts
32249
31872
  function extractModelConfigId(sessionResponse) {
32250
31873
  const configOptions = sessionResponse.configOptions;
@@ -32781,6 +32404,424 @@ function filterMcpServersByAgentCapabilities(mcpServers, agentCapabilities) {
32781
32404
  });
32782
32405
  }
32783
32406
 
32407
+ // ../../packages/ycodium-acp-executor/src/events.ts
32408
+ function canonicalRequestTypeFromAcpKind(kind) {
32409
+ switch (kind) {
32410
+ case "execute":
32411
+ return "exec_command_approval";
32412
+ case "read":
32413
+ return "file_read_approval";
32414
+ case "edit":
32415
+ case "delete":
32416
+ case "move":
32417
+ return "file_change_approval";
32418
+ case "fetch":
32419
+ return "web_fetch_approval";
32420
+ case "search":
32421
+ return "web_search_approval";
32422
+ default:
32423
+ return "dynamic_tool_call";
32424
+ }
32425
+ }
32426
+ function fileChangesFromAcpPermission(permissionRequest) {
32427
+ const content = permissionRequest.toolCall?.data["content"];
32428
+ const changes = Array.isArray(content) ? content.flatMap((entry) => {
32429
+ if (entry === null || typeof entry !== "object") {
32430
+ return [];
32431
+ }
32432
+ const block = entry;
32433
+ if (block["type"] !== "diff" || typeof block["path"] !== "string" || typeof block["newText"] !== "string") {
32434
+ return [];
32435
+ }
32436
+ const oldText = typeof block["oldText"] === "string" ? block["oldText"] : void 0;
32437
+ return [
32438
+ {
32439
+ path: block["path"],
32440
+ changeKind: oldText === void 0 ? "add" : "modify",
32441
+ content: {
32442
+ kind: "replace",
32443
+ ...oldText !== void 0 ? { oldText } : {},
32444
+ newText: block["newText"]
32445
+ }
32446
+ }
32447
+ ];
32448
+ }) : [];
32449
+ if (changes.length > 0) {
32450
+ return changes;
32451
+ }
32452
+ if (canonicalRequestTypeFromAcpKind(permissionRequest.kind) !== "file_change_approval") {
32453
+ return void 0;
32454
+ }
32455
+ const locations = permissionRequest.toolCall?.data["locations"];
32456
+ const paths = Array.isArray(locations) ? locations.flatMap((entry) => {
32457
+ const path = entry?.["path"];
32458
+ return typeof path === "string" && path.trim().length > 0 ? [path] : [];
32459
+ }) : [];
32460
+ return paths.length > 0 ? paths.map((path) => ({ path, omitted: "unavailable" })) : void 0;
32461
+ }
32462
+ function runtimeItemStatusFromAcpToolStatus(status) {
32463
+ switch (status) {
32464
+ case "pending":
32465
+ case "inProgress":
32466
+ return "inProgress";
32467
+ case "completed":
32468
+ return "completed";
32469
+ case "failed":
32470
+ return "failed";
32471
+ default:
32472
+ return void 0;
32473
+ }
32474
+ }
32475
+ function makeAcpRequestOpenedEvent(input2) {
32476
+ const requestType = canonicalRequestTypeFromAcpKind(input2.permissionRequest.kind);
32477
+ const toolName = requestType === "dynamic_tool_call" ? input2.permissionRequest.toolCall?.title : void 0;
32478
+ return {
32479
+ type: "request.opened",
32480
+ ...input2.stamp,
32481
+ provider: input2.provider,
32482
+ threadId: input2.threadId,
32483
+ ...input2.turnId !== void 0 ? { turnId: input2.turnId } : {},
32484
+ requestId: input2.requestId,
32485
+ payload: {
32486
+ requestType,
32487
+ detail: input2.detail,
32488
+ ...toolName ? { toolName } : {},
32489
+ args: input2.args,
32490
+ ...input2.options ? { options: input2.options } : {},
32491
+ ...input2.fileChanges ? { fileChanges: input2.fileChanges } : {},
32492
+ declineReasonRelay: "queued"
32493
+ },
32494
+ raw: {
32495
+ source: input2.source,
32496
+ method: input2.method,
32497
+ payload: input2.rawPayload
32498
+ }
32499
+ };
32500
+ }
32501
+ function makeAcpRequestResolvedEvent(input2) {
32502
+ return {
32503
+ type: "request.resolved",
32504
+ ...input2.stamp,
32505
+ provider: input2.provider,
32506
+ threadId: input2.threadId,
32507
+ ...input2.turnId !== void 0 ? { turnId: input2.turnId } : {},
32508
+ requestId: input2.requestId,
32509
+ payload: {
32510
+ requestType: canonicalRequestTypeFromAcpKind(input2.permissionRequest.kind),
32511
+ decision: input2.decision,
32512
+ ...input2.reason ? { reason: input2.reason } : {}
32513
+ }
32514
+ };
32515
+ }
32516
+ function makeAcpPlanUpdatedEvent(input2) {
32517
+ return {
32518
+ type: "turn.plan.updated",
32519
+ ...input2.stamp,
32520
+ provider: input2.provider,
32521
+ threadId: input2.threadId,
32522
+ ...input2.turnId !== void 0 ? { turnId: input2.turnId } : {},
32523
+ payload: input2.payload,
32524
+ raw: {
32525
+ source: input2.source,
32526
+ method: input2.method,
32527
+ payload: input2.rawPayload
32528
+ }
32529
+ };
32530
+ }
32531
+ function makeAcpToolCallEvent(input2) {
32532
+ const runtimeStatus = runtimeItemStatusFromAcpToolStatus(input2.toolCall.status);
32533
+ const { data } = input2.toolCall;
32534
+ return {
32535
+ type: input2.toolCall.status === "completed" || input2.toolCall.status === "failed" ? "item.completed" : "item.updated",
32536
+ ...input2.stamp,
32537
+ provider: input2.provider,
32538
+ threadId: input2.threadId,
32539
+ ...input2.turnId !== void 0 ? { turnId: input2.turnId } : {},
32540
+ itemId: input2.toolCall.toolCallId,
32541
+ payload: {
32542
+ itemType: canonicalItemTypeFromAcpToolKind(input2.toolCall.kind),
32543
+ ...runtimeStatus ? { status: runtimeStatus } : {},
32544
+ ...input2.toolCall.title ? { title: input2.toolCall.title } : {},
32545
+ ...input2.toolCall.detail ? { detail: input2.toolCall.detail } : {},
32546
+ ...Object.keys(data).length > 0 ? { data } : {}
32547
+ },
32548
+ raw: {
32549
+ source: "acp.jsonrpc",
32550
+ method: "session/update",
32551
+ payload: input2.rawPayload
32552
+ }
32553
+ };
32554
+ }
32555
+ function makeAcpAssistantItemEvent(input2) {
32556
+ return {
32557
+ type: input2.lifecycle,
32558
+ ...input2.stamp,
32559
+ provider: input2.provider,
32560
+ threadId: input2.threadId,
32561
+ ...input2.turnId !== void 0 ? { turnId: input2.turnId } : {},
32562
+ itemId: input2.itemId,
32563
+ payload: {
32564
+ itemType: "assistant_message",
32565
+ status: input2.lifecycle === "item.completed" ? "completed" : "inProgress"
32566
+ }
32567
+ };
32568
+ }
32569
+ function makeAcpContentDeltaEvent(input2) {
32570
+ return {
32571
+ type: "content.delta",
32572
+ ...input2.stamp,
32573
+ provider: input2.provider,
32574
+ threadId: input2.threadId,
32575
+ ...input2.turnId !== void 0 ? { turnId: input2.turnId } : {},
32576
+ ...input2.itemId ? { itemId: input2.itemId } : {},
32577
+ payload: {
32578
+ streamKind: input2.streamKind ?? "assistant_text",
32579
+ delta: input2.text
32580
+ },
32581
+ raw: {
32582
+ source: "acp.jsonrpc",
32583
+ method: "session/update",
32584
+ payload: input2.rawPayload
32585
+ }
32586
+ };
32587
+ }
32588
+ function retainToolCallUpdate(toolCalls, next, seen) {
32589
+ const tracked = toolCalls.get(next.toolCallId);
32590
+ const previous = tracked?.state;
32591
+ const nextToolCall = mergeToolCallState(previous, next);
32592
+ const decision = decideToolCallUpdateEmission({
32593
+ previous,
32594
+ next: nextToolCall,
32595
+ lastEmittedDetailLength: tracked?.lastEmittedDetailLength,
32596
+ skippedSinceEmit: tracked?.skippedSinceEmit ?? 0
32597
+ });
32598
+ if (nextToolCall.status === "completed" || nextToolCall.status === "failed") {
32599
+ toolCalls.delete(nextToolCall.toolCallId);
32600
+ } else {
32601
+ toolCalls.set(nextToolCall.toolCallId, {
32602
+ state: nextToolCall,
32603
+ lastEmittedDetailLength: decision.emit ? nextToolCall.detail?.length : tracked?.lastEmittedDetailLength,
32604
+ skippedSinceEmit: decision.skippedSinceEmit,
32605
+ turnId: tracked === void 0 ? seen.turnId : tracked.turnId,
32606
+ startedAtMs: tracked?.startedAtMs ?? (nextToolCall.status === "inProgress" ? seen.nowMs() : void 0),
32607
+ rawTitle: typeof seen.rawTitle === "string" ? seen.rawTitle : tracked?.rawTitle
32608
+ });
32609
+ }
32610
+ return { nextToolCall, decision };
32611
+ }
32612
+
32613
+ // ../../packages/ycodium-acp-executor/src/openCommands.ts
32614
+ function readOpenToolCalls(toolCalls, turnId) {
32615
+ const running = [];
32616
+ for (const tracked of toolCalls.values()) {
32617
+ if (tracked.turnId !== turnId || tracked.startedAtMs === void 0) continue;
32618
+ running.push({
32619
+ toolCallId: tracked.state.toolCallId,
32620
+ turnId: tracked.turnId,
32621
+ startedAtMs: tracked.startedAtMs,
32622
+ kind: tracked.state.kind,
32623
+ title: tracked.rawTitle,
32624
+ rawInput: tracked.state.data["rawInput"]
32625
+ });
32626
+ }
32627
+ return running;
32628
+ }
32629
+
32630
+ // ../../packages/ycodium-acp-executor/src/config-options.ts
32631
+ function isRecord4(value) {
32632
+ return typeof value === "object" && value !== null && !Array.isArray(value);
32633
+ }
32634
+ function asString(value) {
32635
+ return typeof value === "string" ? value : void 0;
32636
+ }
32637
+ function normalizedField(option, key) {
32638
+ return asString(option[key])?.trim().toLowerCase() ?? "";
32639
+ }
32640
+ function looksLikeEffortOption(option) {
32641
+ const id = normalizedField(option, "id");
32642
+ const name = normalizedField(option, "name");
32643
+ return id === "effort" || id === "reasoning" || name === "effort" || name === "reasoning" || name.includes("effort") || name.includes("reasoning") || normalizedField(option, "category") === "thought_level";
32644
+ }
32645
+ function flattenChoices(rawOptions, currentValue) {
32646
+ if (!Array.isArray(rawOptions)) return [];
32647
+ const out = [];
32648
+ const seen = /* @__PURE__ */ new Set();
32649
+ const push = (entry) => {
32650
+ if (!isRecord4(entry)) return;
32651
+ const value = asString(entry["value"]);
32652
+ if (value === void 0 || seen.has(value)) return;
32653
+ seen.add(value);
32654
+ const description = asString(entry["description"])?.trim();
32655
+ const name = asString(entry["name"])?.trim();
32656
+ out.push({
32657
+ value,
32658
+ ...name ? { name } : {},
32659
+ label: name || value,
32660
+ ...description ? { description } : {},
32661
+ ...currentValue !== void 0 && currentValue === value ? { isDefault: true } : {}
32662
+ });
32663
+ };
32664
+ for (const entry of rawOptions) {
32665
+ if (isRecord4(entry) && Array.isArray(entry["options"])) {
32666
+ for (const nested of entry["options"]) push(nested);
32667
+ continue;
32668
+ }
32669
+ push(entry);
32670
+ }
32671
+ return out;
32672
+ }
32673
+ function findAcpEffortConfig(configOptions) {
32674
+ if (!Array.isArray(configOptions)) return void 0;
32675
+ const candidates = configOptions.filter(isRecord4).filter((option) => normalizedField(option, "type") === "select").filter(looksLikeEffortOption);
32676
+ if (candidates.length === 0) return void 0;
32677
+ const picked = candidates.find((option) => normalizedField(option, "category") === "model_option") ?? candidates.find((option) => normalizedField(option, "id") === "effort") ?? candidates.find((option) => normalizedField(option, "category") === "thought_level") ?? candidates[0];
32678
+ if (picked === void 0) return void 0;
32679
+ const configId = asString(picked["id"])?.trim();
32680
+ if (!configId) return void 0;
32681
+ const choices = flattenChoices(picked["options"], asString(picked["currentValue"])?.trim());
32682
+ if (choices.length === 0) return void 0;
32683
+ return {
32684
+ configId,
32685
+ label: asString(picked["name"])?.trim() ?? "",
32686
+ choices
32687
+ };
32688
+ }
32689
+ function acpModelChoicesFromConfigOptions(configOptions) {
32690
+ if (!Array.isArray(configOptions)) return void 0;
32691
+ const records = configOptions.filter(isRecord4);
32692
+ const modelOption = records.find((option) => normalizedField(option, "category") === "model") ?? records.find(
32693
+ (option) => normalizedField(option, "id") === "model" && normalizedField(option, "type") === "select"
32694
+ );
32695
+ if (modelOption === void 0) return void 0;
32696
+ if (!asString(modelOption["id"])?.trim()) return void 0;
32697
+ return flattenChoices(modelOption["options"], asString(modelOption["currentValue"])?.trim());
32698
+ }
32699
+
32700
+ // ../../packages/ycodium-acp-executor/src/runtime-mode.ts
32701
+ function isRecord5(value) {
32702
+ return typeof value === "object" && value !== null && !Array.isArray(value);
32703
+ }
32704
+ function asString2(value) {
32705
+ return typeof value === "string" ? value : void 0;
32706
+ }
32707
+ function acpModeConfigId(setup) {
32708
+ if (!isRecord5(setup)) return void 0;
32709
+ const configOptions = setup["configOptions"];
32710
+ if (!Array.isArray(configOptions)) return void 0;
32711
+ for (const option of configOptions) {
32712
+ if (!isRecord5(option)) continue;
32713
+ if (asString2(option["category"])?.trim().toLowerCase() !== "mode") continue;
32714
+ const id = asString2(option["id"])?.trim();
32715
+ if (id) return id;
32716
+ }
32717
+ return void 0;
32718
+ }
32719
+
32720
+ // ../../packages/ycodium-acp-executor/src/handshake.ts
32721
+ function acpInitializePayload(clientInfo, overrides) {
32722
+ return {
32723
+ protocolVersion: PROTOCOL_VERSION,
32724
+ clientCapabilities: {
32725
+ fs: {
32726
+ readTextFile: false,
32727
+ writeTextFile: false,
32728
+ ...overrides?.fs
32729
+ },
32730
+ terminal: overrides?.terminal ?? false
32731
+ },
32732
+ clientInfo
32733
+ };
32734
+ }
32735
+
32736
+ // ../../packages/ycodium-acp-executor/src/config-option-wiring.ts
32737
+ var VENDOR_CATEGORY_PREFIX = "_";
32738
+ var ACP_CONFIG_CATEGORY_HANDLING = {
32739
+ mode: {
32740
+ consumed: true,
32741
+ via: "runtime-mode.ts\uFF1AacpAvailableModes / acpCurrentModeId / acpModeConfigId"
32742
+ },
32743
+ model: {
32744
+ consumed: true,
32745
+ via: "runtime-model.ts:extractModelConfigId \u2192 executor.ts:applyRequestedModel"
32746
+ },
32747
+ thought_level: {
32748
+ consumed: true,
32749
+ via: "config-options.ts:findAcpEffortConfig \u2192 executor.ts:applyRequestedEffort"
32750
+ },
32751
+ model_option: {
32752
+ consumed: true,
32753
+ // 精确说法:它不是**识别器**,是**优先级**。`looksLikeEffortOption` 先筛出候选,
32754
+ // 标了 `model_option` 的在候选里排第一(厂商自己标的最准),排在 id 叫 `effort`
32755
+ // 的和标 `thought_level` 的前面。光有这个 category 而 id/name 不像力度档的,
32756
+ // 压根进不了候选。
32757
+ via: "config-options.ts:findAcpEffortConfig\uFF08\u5019\u9009\u91CC\u7684\u6700\u9AD8\u4F18\u5148\u7EA7\uFF0C\u538B\u8FC7 thought_level\uFF09"
32758
+ },
32759
+ model_config: {
32760
+ consumed: false,
32761
+ note: "\u53EA\u6709\u5BBF\u4E3B\u7684 CursorProvider \u6D88\u8D39\u8FC7\uFF08context / fast / thinking \u4E09\u4E2A\u5F00\u5173\uFF09\u3002Cursor 2026-09-20 \u5E9F\u5F03\u5220\u9664\uFF0C\u8FD9\u4E00\u7C7B\u73B0\u5728\u6CA1\u6709\u6D88\u8D39\u70B9\uFF1B\u6CA1\u89C1\u8FC7\u522B\u5BB6\u7684\u771F\u5B9E\u8F7D\u8377\uFF0C\u5148\u8BB0\u8D26\u4E0D\u731C\u5F62\u72B6\u3002"
32762
+ }
32763
+ };
32764
+ var KNOWN_CATEGORIES = new Set(Object.keys(ACP_CONFIG_CATEGORY_HANDLING));
32765
+ function unhandledConfigCategories(configOptions) {
32766
+ if (!configOptions) return [];
32767
+ const seen = /* @__PURE__ */ new Set();
32768
+ const out = [];
32769
+ for (const option of configOptions) {
32770
+ const category = option.category?.trim();
32771
+ if (!category) continue;
32772
+ if (KNOWN_CATEGORIES.has(category)) continue;
32773
+ if (seen.has(category)) continue;
32774
+ seen.add(category);
32775
+ out.push({
32776
+ category,
32777
+ optionId: option.id.trim(),
32778
+ vendorExtension: category.startsWith(VENDOR_CATEGORY_PREFIX)
32779
+ });
32780
+ }
32781
+ return out;
32782
+ }
32783
+
32784
+ // ../../packages/ycodium-acp-executor/src/mutex.ts
32785
+ var Mutex = class {
32786
+ locked = false;
32787
+ waiters = [];
32788
+ get isLocked() {
32789
+ return this.locked;
32790
+ }
32791
+ acquire() {
32792
+ if (!this.locked) {
32793
+ this.locked = true;
32794
+ return Promise.resolve();
32795
+ }
32796
+ return new Promise((resolve2) => {
32797
+ this.waiters.push(resolve2);
32798
+ });
32799
+ }
32800
+ tryAcquire() {
32801
+ if (this.locked) {
32802
+ return false;
32803
+ }
32804
+ this.locked = true;
32805
+ return true;
32806
+ }
32807
+ release() {
32808
+ const next = this.waiters.shift();
32809
+ if (next) {
32810
+ next();
32811
+ return;
32812
+ }
32813
+ this.locked = false;
32814
+ }
32815
+ async runExclusive(fn) {
32816
+ await this.acquire();
32817
+ try {
32818
+ return await fn();
32819
+ } finally {
32820
+ this.release();
32821
+ }
32822
+ }
32823
+ };
32824
+
32784
32825
  // ../../packages/ycodium-acp-executor/src/model-selection.ts
32785
32826
  function normalizeModelId(value) {
32786
32827
  return value?.trim() || void 0;
@@ -33038,24 +33079,11 @@ function createAcpExecutor(options) {
33038
33079
  }
33039
33080
  for (const event of parsed.events) {
33040
33081
  if (event._tag === "ToolCallUpdated") {
33041
- const tracked = toolCalls.get(event.toolCall.toolCallId);
33042
- const previous = tracked?.state;
33043
- const nextToolCall = mergeToolCallState(previous, event.toolCall);
33044
- const decision = decideToolCallUpdateEmission({
33045
- previous,
33046
- next: nextToolCall,
33047
- lastEmittedDetailLength: tracked?.lastEmittedDetailLength,
33048
- skippedSinceEmit: tracked?.skippedSinceEmit ?? 0
33082
+ const { nextToolCall, decision } = retainToolCallUpdate(toolCalls, event.toolCall, {
33083
+ turnId: activeTurnId,
33084
+ rawTitle: params.update.title,
33085
+ nowMs
33049
33086
  });
33050
- if (nextToolCall.status === "completed" || nextToolCall.status === "failed") {
33051
- toolCalls.delete(nextToolCall.toolCallId);
33052
- } else {
33053
- toolCalls.set(nextToolCall.toolCallId, {
33054
- state: nextToolCall,
33055
- lastEmittedDetailLength: decision.emit ? nextToolCall.detail?.length : tracked?.lastEmittedDetailLength,
33056
- skippedSinceEmit: decision.skippedSinceEmit
33057
- });
33058
- }
33059
33087
  const hookResult = hooks.onToolCallUpdated?.({
33060
33088
  toolCallId: nextToolCall.toolCallId,
33061
33089
  status: nextToolCall.status,
@@ -34083,6 +34111,7 @@ function createAcpExecutor(options) {
34083
34111
  respondToUserInput,
34084
34112
  setNativeMode,
34085
34113
  compact,
34114
+ openToolCalls: () => readOpenToolCalls(toolCalls, activeTurnId),
34086
34115
  dispose
34087
34116
  };
34088
34117
  }
@@ -34412,17 +34441,21 @@ async function ensureDshSkillOverlay(skillsDir, tempRoot = NodeOS2.tmpdir()) {
34412
34441
  });
34413
34442
  return file2;
34414
34443
  }
34415
- function spawnDsh(host, launch, prefix, suffix = []) {
34416
- return host.process.spawn({
34444
+ async function spawnDsh(host, launch, prefix, suffix = []) {
34445
+ const spawned = {
34417
34446
  program: launch.program,
34418
34447
  args: [...prefix, ...launch.args, ...suffix],
34419
- cwd: launch.cwd,
34448
+ cwd: launch.cwd
34449
+ };
34450
+ const handle = await host.process.spawn({
34451
+ ...spawned,
34420
34452
  owner: { bindingId: host.bindingId },
34421
34453
  ...Object.keys(launch.env).length > 0 ? { env: launch.env } : {}
34422
34454
  });
34455
+ return { handle, spawned };
34423
34456
  }
34424
34457
  async function overlayTakesEffect(input2) {
34425
- const handle = await spawnDsh(
34458
+ const { handle } = await spawnDsh(
34426
34459
  input2.host,
34427
34460
  input2.launch,
34428
34461
  ["--patch", input2.overlay],
@@ -34770,6 +34803,112 @@ async function probeDshVersion(input2) {
34770
34803
  });
34771
34804
  }
34772
34805
 
34806
+ // src/openCommands.ts
34807
+ import {
34808
+ isPowerShellExecutableName,
34809
+ posixShellCommandMatches,
34810
+ sameArgv
34811
+ } from "@ycodium-ai/plugin-api/executor";
34812
+ var WINDOWS_POWERSHELL_PREFIX = "[Console]::OutputEncoding = [System.Text.UTF8Encoding]::new($false); $OutputEncoding = [System.Text.UTF8Encoding]::new($false); ";
34813
+ var WINDOWS_POWERSHELL_FLAGS = ["-NoLogo", "-NoProfile", "-NonInteractive", "-Command"];
34814
+ var NODE_EXECUTABLES = /* @__PURE__ */ new Set(["node", "node.exe"]);
34815
+ var SHELL_TOOL_TITLES = /* @__PURE__ */ new Set(["bash", "pwsh"]);
34816
+ var isDshShellToolTitle = (title) => SHELL_TOOL_TITLES.has(title);
34817
+ var slashed = (path) => path.replaceAll("\\", "/").replace(/\/{2,}/g, "/");
34818
+ var basename = (path) => {
34819
+ const normalized = slashed(path);
34820
+ return normalized.slice(normalized.lastIndexOf("/") + 1);
34821
+ };
34822
+ var isNode = (program) => NODE_EXECUTABLES.has(basename(program).toLowerCase());
34823
+ var endsWithPath = (path, suffix) => slashed(path).toLowerCase().endsWith(suffix);
34824
+ var SUBPROCESS_RUNNER = "/@deepseek-ai/dsh-subprocess-local/lib/runner.js";
34825
+ var SANDBOX_RUNNER = "/@deepseek-ai/dsh-sandbox-windows-acl/lib/runner.js";
34826
+ var DSH_ENTRY = "/@deepseek-ai/dsh/lib/bin.js";
34827
+ var sameWindowsDirectory = (left, right) => {
34828
+ const trimmed = (path) => slashed(path).replace(/\/+$/, "").toLowerCase();
34829
+ return trimmed(left) === trimmed(right);
34830
+ };
34831
+ var TEMP_DIRECTORY = /^dsh-[A-Za-z0-9]{6}$/;
34832
+ var WINDOWS_ABSOLUTE_PATH = /^[A-Za-z]:[\\/]/;
34833
+ var SID = /^S-1-\d+(-\d+)+$/;
34834
+ function windowsShellMatches(argv, command) {
34835
+ const [shell, ...rest] = argv;
34836
+ if (shell === void 0 || !isPowerShellExecutableName(basename(shell))) return false;
34837
+ return sameArgv(rest, [...WINDOWS_POWERSHELL_FLAGS, WINDOWS_POWERSHELL_PREFIX + command]);
34838
+ }
34839
+ function unwrapWindowsSandbox(argv, cwd) {
34840
+ const [node2, runner, workspaceFlag, workspace, tempFlag, temp, modeFlag, mode, ...rest] = argv;
34841
+ if (node2 === void 0 || runner === void 0) return void 0;
34842
+ if (!isNode(node2) || !endsWithPath(runner, SANDBOX_RUNNER)) return void 0;
34843
+ if (workspaceFlag !== "--workspace" || !sameWindowsDirectory(workspace ?? "", cwd)) {
34844
+ return void 0;
34845
+ }
34846
+ if (tempFlag !== "--temp" || temp === void 0 || modeFlag !== "--mode") return void 0;
34847
+ if (mode === "read-only") {
34848
+ const [separator2, ...shell2] = rest;
34849
+ return WINDOWS_ABSOLUTE_PATH.test(temp) && separator2 === "--" ? shell2 : void 0;
34850
+ }
34851
+ if (mode !== "workspace-write" || !TEMP_DIRECTORY.test(basename(temp))) return void 0;
34852
+ const [writeFlag, writeSid, tempWriteFlag, tempWriteSid, separator, ...shell] = rest;
34853
+ if (writeFlag !== "--write-sid" || !SID.test(writeSid ?? "")) return void 0;
34854
+ if (tempWriteFlag !== "--temp-write-sid" || !SID.test(tempWriteSid ?? "")) return void 0;
34855
+ return separator === "--" ? shell : void 0;
34856
+ }
34857
+ function windowsCommandMatches(argv, command, cwd) {
34858
+ const [node2, runner, separator, ...inner] = argv;
34859
+ if (node2 === void 0 || runner === void 0 || separator !== "--") return false;
34860
+ if (!isNode(node2) || !endsWithPath(runner, SUBPROCESS_RUNNER)) return false;
34861
+ return windowsShellMatches(unwrapWindowsSandbox(inner, cwd) ?? inner, command);
34862
+ }
34863
+ function dshCommandMatcher(input2) {
34864
+ return (argv, platform) => {
34865
+ if (platform === "win32") {
34866
+ return input2.title === "pwsh" && windowsCommandMatches(argv, input2.command, input2.cwd);
34867
+ }
34868
+ if (input2.title !== "bash") return false;
34869
+ const first = argv[0] ?? "";
34870
+ const shell = argv.length === 3 && basename(first) === "bash" ? first : "bash";
34871
+ return posixShellCommandMatches({ shell, script: input2.command }, argv);
34872
+ };
34873
+ }
34874
+ function dshSessionProcessMatcher(program, args) {
34875
+ return (argv, platform) => {
34876
+ const [node2, entry, ...rest] = argv;
34877
+ if (node2 === void 0 || entry === void 0 || !isNode(node2)) return false;
34878
+ if (!sameArgv(rest, args)) return false;
34879
+ if (platform === "win32") return endsWithPath(entry, DSH_ENTRY);
34880
+ return basename(entry) === basename(program);
34881
+ };
34882
+ }
34883
+ var commandOf = (call) => {
34884
+ if (call.title === void 0 || !isDshShellToolTitle(call.title)) return void 0;
34885
+ const rawInput = call.rawInput;
34886
+ if (typeof rawInput !== "object" || rawInput === null) return void 0;
34887
+ const input2 = rawInput;
34888
+ if (input2["run_in_background"] === true) return void 0;
34889
+ const command = input2["command"];
34890
+ return typeof command === "string" && command.trim() !== "" ? command : void 0;
34891
+ };
34892
+ function dshOpenCommands(session) {
34893
+ const commands = session.openToolCalls.flatMap((call) => {
34894
+ const command = commandOf(call);
34895
+ if (command === void 0 || call.title === void 0) return [];
34896
+ return [
34897
+ {
34898
+ toolCallId: call.toolCallId,
34899
+ startedAtMs: call.startedAtMs,
34900
+ matches: dshCommandMatcher({ title: call.title, command, cwd: session.cwd })
34901
+ }
34902
+ ];
34903
+ });
34904
+ if (commands.length === 0) return void 0;
34905
+ return {
34906
+ rootPid: session.rootPid,
34907
+ sessionProcess: dshSessionProcessMatcher(session.program, session.args),
34908
+ commands
34909
+ };
34910
+ }
34911
+
34773
34912
  // src/dshInstance.ts
34774
34913
  var RESUME_SCHEMA_VERSION = 1;
34775
34914
  var yieldTick = () => new Promise((resolve2) => {
@@ -34898,7 +35037,7 @@ var createDshInstance = (config2, host) => {
34898
35037
  launch,
34899
35038
  verified: skillOverlayChecks
34900
35039
  });
34901
- const handle = await spawnDsh(host, launch, skillArgs);
35040
+ const { handle, spawned } = await spawnDsh(host, launch, skillArgs);
34902
35041
  const { readable, writable, stderrTail } = nodeStreamsFromHandle2(handle);
34903
35042
  const resume = input2.discardResumeCursor === true ? void 0 : parseAcpResumeCursor(input2.resumeCursor, RESUME_SCHEMA_VERSION);
34904
35043
  const requestedModelId = modelIdFromSelection(input2.modelSelection);
@@ -34965,7 +35104,8 @@ var createDshInstance = (config2, host) => {
34965
35104
  turns: [],
34966
35105
  executor,
34967
35106
  handle,
34968
- forwarding
35107
+ forwarding,
35108
+ spawned
34969
35109
  });
34970
35110
  host.log.info("session started", {
34971
35111
  threadId: input2.threadId,
@@ -35011,6 +35151,15 @@ var createDshInstance = (config2, host) => {
35011
35151
  await booked.executor.cancel(turnId);
35012
35152
  await yieldTick();
35013
35153
  },
35154
+ openCommandProcesses: async (threadId) => {
35155
+ const booked = threads.get(threadId);
35156
+ if (booked === void 0) return void 0;
35157
+ return dshOpenCommands({
35158
+ rootPid: booked.handle.pid,
35159
+ ...booked.spawned,
35160
+ openToolCalls: booked.executor.openToolCalls()
35161
+ });
35162
+ },
35014
35163
  respondToRequest: async (threadId, requestId, decision, reason) => {
35015
35164
  const booked = requireThread(threadId);
35016
35165
  await booked.executor.respondToRequest(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ycodium-ai/agent-dsh",
3
- "version": "0.2.2976",
3
+ "version": "0.2.2980",
4
4
  "description": "DeepSeek Harness executor: dsh CLI over Agent Client Protocol stdio.",
5
5
  "keywords": [
6
6
  "ycodium",
@@ -22,8 +22,8 @@
22
22
  "esbuild": "0.28.1",
23
23
  "vite-plus": "0.2.2",
24
24
  "yaml": "^2.9.0",
25
- "@ycodium-ai/plugin-api": "0.2.2976",
26
- "ycodium-acp-executor": "0.2.0",
25
+ "@ycodium-ai/plugin-api": "0.2.2980",
26
+ "ycodium-acp-executor": "0.2.2980",
27
27
  "ycodium-executor-testing": "0.0.0"
28
28
  },
29
29
  "ycodium": {