@openma/deepseek-harness-acp 0.4.24 → 0.4.26
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.
- package/dist/bridge.js +199 -59
- package/dist/index.js +11 -30
- package/dist/plugin.js +199 -59
- package/dist/server.js +199 -59
- package/dist/stdio.js +1 -0
- package/package.json +1 -1
- package/vendor/dsh-runtime.tgz +0 -0
- package/vendor/runtime.json +1 -1
package/dist/bridge.js
CHANGED
|
@@ -71,6 +71,7 @@ import {
|
|
|
71
71
|
} from "@agentclientprotocol/sdk";
|
|
72
72
|
import { credentialRef } from "@deepseek-ai/dsh-credentials";
|
|
73
73
|
import { ReasoningEffortId } from "@deepseek-ai/dsh-llm";
|
|
74
|
+
import { PERMISSION_SETTINGS_NAMESPACE } from "@deepseek-ai/dsh-permission-presets";
|
|
74
75
|
|
|
75
76
|
// src/version.ts
|
|
76
77
|
import { createRequire } from "node:module";
|
|
@@ -531,7 +532,10 @@ var SessionProjection = class {
|
|
|
531
532
|
title;
|
|
532
533
|
streamedText = /* @__PURE__ */ new Set();
|
|
533
534
|
streamedReasoning = /* @__PURE__ */ new Set();
|
|
535
|
+
/** One authoritative state per open ACP tool call. Block indexes only
|
|
536
|
+
* route streaming fragments to that state; they never own lifecycle. */
|
|
534
537
|
toolCalls = /* @__PURE__ */ new Map();
|
|
538
|
+
toolCallBlocks = /* @__PURE__ */ new Map();
|
|
535
539
|
window = emptyWindow();
|
|
536
540
|
lastContextUse;
|
|
537
541
|
/** Client renders `_meta.terminal_output` display terminals (Zed extension). */
|
|
@@ -550,6 +554,7 @@ var SessionProjection = class {
|
|
|
550
554
|
/** Reset per-prompt accumulators; call when a new `session/prompt` starts. */
|
|
551
555
|
beginPrompt() {
|
|
552
556
|
this.window = emptyWindow();
|
|
557
|
+
this.toolCallBlocks.clear();
|
|
553
558
|
}
|
|
554
559
|
/** The captured ending for a specific turn, when it already ended. */
|
|
555
560
|
turnEndFor(turn) {
|
|
@@ -589,6 +594,8 @@ var SessionProjection = class {
|
|
|
589
594
|
switch (event.type) {
|
|
590
595
|
case "assistant/chunk":
|
|
591
596
|
return this.onChunk(data);
|
|
597
|
+
case "tool-call-chunks":
|
|
598
|
+
return this.onToolCallChunks(data);
|
|
592
599
|
case "assistant/message":
|
|
593
600
|
return this.onAssistantMessage(data);
|
|
594
601
|
case "tool/call":
|
|
@@ -671,42 +678,31 @@ var SessionProjection = class {
|
|
|
671
678
|
onSubagentStart(data) {
|
|
672
679
|
const subagent = this.subagentMeta(data, "started");
|
|
673
680
|
if (subagent === void 0) return [];
|
|
674
|
-
const runId = subagent["runId"];
|
|
675
|
-
const childSessionId = subagent["childSessionId"];
|
|
676
681
|
return [{
|
|
677
|
-
sessionUpdate: "
|
|
678
|
-
|
|
679
|
-
title: `Start subagent ${childSessionId}`,
|
|
680
|
-
kind: "other",
|
|
681
|
-
status: "in_progress",
|
|
682
|
-
rawInput: {
|
|
683
|
-
childSessionId,
|
|
684
|
-
provider: subagent["provider"],
|
|
685
|
-
local: subagent["local"]
|
|
686
|
-
},
|
|
687
|
-
_meta: { dsh: { subagent } }
|
|
682
|
+
sessionUpdate: "session_info_update",
|
|
683
|
+
_meta: { dsh: { event: "subagent/lifecycle", subagent } }
|
|
688
684
|
}];
|
|
689
685
|
}
|
|
690
686
|
onSubagentEnd(data) {
|
|
691
687
|
const subagent = this.subagentMeta(data, "finished");
|
|
692
688
|
if (subagent === void 0) return [];
|
|
693
689
|
const stopReason = asString(data["stopReason"]) ?? "error";
|
|
694
|
-
const lastAssistantMessage = data["lastAssistantMessage"];
|
|
695
690
|
return [{
|
|
696
|
-
sessionUpdate: "
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
}
|
|
703
|
-
_meta: { dsh: { subagent } }
|
|
691
|
+
sessionUpdate: "session_info_update",
|
|
692
|
+
_meta: {
|
|
693
|
+
dsh: {
|
|
694
|
+
event: "subagent/lifecycle",
|
|
695
|
+
subagent: { ...subagent, stopReason }
|
|
696
|
+
}
|
|
697
|
+
}
|
|
704
698
|
}];
|
|
705
699
|
}
|
|
706
700
|
onChunk(data) {
|
|
707
701
|
const chunk = data["chunk"];
|
|
708
702
|
if (chunk === null || typeof chunk === "undefined" || typeof chunk !== "object") return [];
|
|
709
703
|
const c = chunk;
|
|
704
|
+
if (c["type"] === "block-end") return this.onToolCallBlockEnd(data, c);
|
|
705
|
+
if (c["type"] === "tool-call-delta") return this.onToolCallDelta(data, c);
|
|
710
706
|
const text = c["text"];
|
|
711
707
|
if (typeof text !== "string" || text.length === 0) return [];
|
|
712
708
|
const messageId = this.stepKey(data);
|
|
@@ -720,6 +716,97 @@ var SessionProjection = class {
|
|
|
720
716
|
}
|
|
721
717
|
return [];
|
|
722
718
|
}
|
|
719
|
+
toolBlockKey(data, index) {
|
|
720
|
+
return `${this.stepKey(data)}:${index}`;
|
|
721
|
+
}
|
|
722
|
+
onToolCallDelta(data, chunk) {
|
|
723
|
+
const callId = asString(chunk["id"]);
|
|
724
|
+
const index = chunk["index"];
|
|
725
|
+
const argumentsDelta = chunk["argumentsDelta"];
|
|
726
|
+
if (callId === void 0 || typeof index !== "number" || !Number.isInteger(index) || typeof argumentsDelta !== "string") {
|
|
727
|
+
return [];
|
|
728
|
+
}
|
|
729
|
+
const current = this.toolCalls.get(callId);
|
|
730
|
+
const name5 = asString(chunk["name"]) ?? current?.name;
|
|
731
|
+
if (name5 === void 0) return [];
|
|
732
|
+
const rawArguments = `${current?.arguments ?? ""}${argumentsDelta}`;
|
|
733
|
+
const state = {
|
|
734
|
+
callId,
|
|
735
|
+
name: name5,
|
|
736
|
+
arguments: rawArguments,
|
|
737
|
+
facts: this.toolCallFacts(name5, rawArguments),
|
|
738
|
+
status: current?.status ?? "pending"
|
|
739
|
+
};
|
|
740
|
+
this.toolCalls.set(callId, state);
|
|
741
|
+
this.toolCallBlocks.set(this.toolBlockKey(data, index), callId);
|
|
742
|
+
if (current === void 0) return [this.toolCallCreated(state)];
|
|
743
|
+
return [{
|
|
744
|
+
sessionUpdate: "tool_call_update",
|
|
745
|
+
toolCallId: callId,
|
|
746
|
+
title: state.facts.title,
|
|
747
|
+
name: name5,
|
|
748
|
+
kind: state.facts.kind,
|
|
749
|
+
status: "pending",
|
|
750
|
+
rawInput: state.facts.rawInput,
|
|
751
|
+
...state.facts.locations.length > 0 ? { locations: state.facts.locations } : {}
|
|
752
|
+
}];
|
|
753
|
+
}
|
|
754
|
+
onToolCallChunks(data) {
|
|
755
|
+
const callId = asString(data["id"]);
|
|
756
|
+
const name5 = asString(data["name"]);
|
|
757
|
+
const index = data["index"];
|
|
758
|
+
const args = data["args"];
|
|
759
|
+
if (callId === void 0 || name5 === void 0 || typeof index !== "number" || !Number.isInteger(index) || !Array.isArray(args)) {
|
|
760
|
+
return [];
|
|
761
|
+
}
|
|
762
|
+
const key = this.toolBlockKey(data, index);
|
|
763
|
+
const current = this.toolCalls.get(callId);
|
|
764
|
+
const fragments = args.filter((fragment) => typeof fragment === "string").join("");
|
|
765
|
+
const rawArguments = `${current?.arguments ?? ""}${fragments}`;
|
|
766
|
+
const state = {
|
|
767
|
+
callId,
|
|
768
|
+
name: name5,
|
|
769
|
+
arguments: rawArguments,
|
|
770
|
+
facts: this.toolCallFacts(name5, rawArguments),
|
|
771
|
+
status: current?.status ?? "pending"
|
|
772
|
+
};
|
|
773
|
+
this.toolCalls.set(callId, state);
|
|
774
|
+
this.toolCallBlocks.set(key, callId);
|
|
775
|
+
return current === void 0 ? [this.toolCallCreated(state)] : [];
|
|
776
|
+
}
|
|
777
|
+
onToolCallBlockEnd(data, chunk) {
|
|
778
|
+
const index = chunk["index"];
|
|
779
|
+
if (typeof index !== "number" || !Number.isInteger(index)) return [];
|
|
780
|
+
const key = this.toolBlockKey(data, index);
|
|
781
|
+
const callId = this.toolCallBlocks.get(key);
|
|
782
|
+
this.toolCallBlocks.delete(key);
|
|
783
|
+
const block = chunk["block"];
|
|
784
|
+
const complete = block !== null && typeof block === "object" ? block : void 0;
|
|
785
|
+
const completeCallId = complete?.["type"] === "tool-call" ? asString(complete["id"]) : void 0;
|
|
786
|
+
const resolvedCallId = callId ?? completeCallId;
|
|
787
|
+
if (resolvedCallId === void 0) return [];
|
|
788
|
+
const current = this.toolCalls.get(resolvedCallId);
|
|
789
|
+
const name5 = (complete?.["type"] === "tool-call" ? asString(complete["name"]) : void 0) ?? current?.name;
|
|
790
|
+
if (name5 === void 0) return [];
|
|
791
|
+
const rawArguments = (complete?.["type"] === "tool-call" && typeof complete["arguments"] === "string" ? complete["arguments"] : void 0) ?? current?.arguments ?? "{}";
|
|
792
|
+
const state = {
|
|
793
|
+
callId: resolvedCallId,
|
|
794
|
+
name: name5,
|
|
795
|
+
arguments: rawArguments,
|
|
796
|
+
facts: this.toolCallFacts(name5, rawArguments),
|
|
797
|
+
status: current?.status ?? "pending"
|
|
798
|
+
};
|
|
799
|
+
this.toolCalls.set(resolvedCallId, state);
|
|
800
|
+
if (current === void 0) return [this.toolCallCreated(state)];
|
|
801
|
+
return [{
|
|
802
|
+
sessionUpdate: "tool_call_update",
|
|
803
|
+
toolCallId: resolvedCallId,
|
|
804
|
+
title: state.facts.title,
|
|
805
|
+
kind: state.facts.kind,
|
|
806
|
+
rawInput: state.facts.rawInput,
|
|
807
|
+
locations: state.facts.locations
|
|
808
|
+
}];
|
|
809
|
+
}
|
|
723
810
|
onAssistantMessage(data) {
|
|
724
811
|
const updates = [];
|
|
725
812
|
const key = this.stepKey(data);
|
|
@@ -783,11 +870,7 @@ var SessionProjection = class {
|
|
|
783
870
|
}
|
|
784
871
|
return updates;
|
|
785
872
|
}
|
|
786
|
-
|
|
787
|
-
const callId = asString(data["callId"]);
|
|
788
|
-
const name5 = asString(data["name"]) ?? "tool";
|
|
789
|
-
if (callId === void 0) return [];
|
|
790
|
-
const rawArguments = typeof data["arguments"] === "string" ? data["arguments"] : "{}";
|
|
873
|
+
toolCallFacts(name5, rawArguments) {
|
|
791
874
|
let parsedArgs = {};
|
|
792
875
|
try {
|
|
793
876
|
parsedArgs = JSON.parse(rawArguments);
|
|
@@ -795,30 +878,52 @@ var SessionProjection = class {
|
|
|
795
878
|
parsedArgs = { arguments: rawArguments };
|
|
796
879
|
}
|
|
797
880
|
const presented = this.presentCall?.(name5, parsedArgs);
|
|
798
|
-
|
|
799
|
-
|
|
881
|
+
return presented !== void 0 ? factsFromPresentCall(name5, rawArguments, presented) : classifyToolCall(name5, rawArguments);
|
|
882
|
+
}
|
|
883
|
+
toolCallCreated(state) {
|
|
884
|
+
const { callId, name: name5, facts, status } = state;
|
|
800
885
|
const displayTerminal = this.terminalOutput && facts.kind === "execute";
|
|
801
|
-
return
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
...this.cwd !== void 0 ? { cwd: this.cwd } : {}
|
|
817
|
-
}
|
|
886
|
+
return {
|
|
887
|
+
sessionUpdate: "tool_call",
|
|
888
|
+
toolCallId: callId,
|
|
889
|
+
title: facts.title,
|
|
890
|
+
name: name5,
|
|
891
|
+
kind: facts.kind,
|
|
892
|
+
status,
|
|
893
|
+
rawInput: facts.rawInput,
|
|
894
|
+
...facts.locations.length > 0 ? { locations: facts.locations } : {},
|
|
895
|
+
...displayTerminal ? {
|
|
896
|
+
content: [{ type: "terminal", terminalId: callId }],
|
|
897
|
+
_meta: {
|
|
898
|
+
terminal_info: {
|
|
899
|
+
terminal_id: callId,
|
|
900
|
+
...this.cwd !== void 0 ? { cwd: this.cwd } : {}
|
|
818
901
|
}
|
|
819
|
-
}
|
|
820
|
-
}
|
|
821
|
-
|
|
902
|
+
}
|
|
903
|
+
} : {}
|
|
904
|
+
};
|
|
905
|
+
}
|
|
906
|
+
onToolCall(data) {
|
|
907
|
+
const callId = asString(data["callId"]);
|
|
908
|
+
const name5 = asString(data["name"]) ?? "tool";
|
|
909
|
+
if (callId === void 0) return [];
|
|
910
|
+
const rawArguments = typeof data["arguments"] === "string" ? data["arguments"] : "{}";
|
|
911
|
+
const facts = this.toolCallFacts(name5, rawArguments);
|
|
912
|
+
const current = this.toolCalls.get(callId);
|
|
913
|
+
const state = { callId, name: name5, arguments: rawArguments, facts, status: "in_progress" };
|
|
914
|
+
this.toolCalls.set(callId, state);
|
|
915
|
+
if (current === void 0) return [this.toolCallCreated(state)];
|
|
916
|
+
if (current.status === "in_progress" && current.arguments === rawArguments && current.name === name5) return [];
|
|
917
|
+
return [{
|
|
918
|
+
sessionUpdate: "tool_call_update",
|
|
919
|
+
toolCallId: callId,
|
|
920
|
+
title: facts.title,
|
|
921
|
+
name: name5,
|
|
922
|
+
kind: facts.kind,
|
|
923
|
+
status: "in_progress",
|
|
924
|
+
rawInput: facts.rawInput,
|
|
925
|
+
locations: facts.locations
|
|
926
|
+
}];
|
|
822
927
|
}
|
|
823
928
|
onToolResult(data) {
|
|
824
929
|
const message = data["message"];
|
|
@@ -833,7 +938,8 @@ var SessionProjection = class {
|
|
|
833
938
|
})() : void 0
|
|
834
939
|
) ?? asString(data["callId"]);
|
|
835
940
|
if (callId === void 0) return [];
|
|
836
|
-
const
|
|
941
|
+
const state = this.toolCalls.get(callId);
|
|
942
|
+
const facts = state?.facts;
|
|
837
943
|
const { failed, text, diffs } = extractToolResult(data);
|
|
838
944
|
const content = diffs.map((diff) => ({
|
|
839
945
|
type: "diff",
|
|
@@ -844,6 +950,9 @@ var SessionProjection = class {
|
|
|
844
950
|
const isCommand = facts?.kind === "execute";
|
|
845
951
|
if (this.terminalOutput && isCommand) {
|
|
846
952
|
this.toolCalls.delete(callId);
|
|
953
|
+
for (const [key, value] of this.toolCallBlocks) {
|
|
954
|
+
if (value === callId) this.toolCallBlocks.delete(key);
|
|
955
|
+
}
|
|
847
956
|
return [
|
|
848
957
|
...text.length > 0 ? [
|
|
849
958
|
{
|
|
@@ -874,6 +983,9 @@ ${text.replace(/\n+$/, "")}
|
|
|
874
983
|
content.push({ type: "content", content: block });
|
|
875
984
|
}
|
|
876
985
|
this.toolCalls.delete(callId);
|
|
986
|
+
for (const [key, value] of this.toolCallBlocks) {
|
|
987
|
+
if (value === callId) this.toolCallBlocks.delete(key);
|
|
988
|
+
}
|
|
877
989
|
return [
|
|
878
990
|
{
|
|
879
991
|
sessionUpdate: "tool_call_update",
|
|
@@ -895,6 +1007,8 @@ ${text.replace(/\n+$/, "")}
|
|
|
895
1007
|
this.window.error = { message: r.error?.message ?? "model turn failed" };
|
|
896
1008
|
}
|
|
897
1009
|
}
|
|
1010
|
+
this.toolCallBlocks.clear();
|
|
1011
|
+
this.toolCalls.clear();
|
|
898
1012
|
return [];
|
|
899
1013
|
}
|
|
900
1014
|
};
|
|
@@ -2094,11 +2208,16 @@ async function apply3(ctx, config = {}) {
|
|
|
2094
2208
|
'no credential found for this provider: call authenticate with `_meta["api-key"].apiKey` or `_meta.gateway`, use the browser method, run `dsh-acp login`, or save a key in the dsh Web UI (Settings \u2192 Models)'
|
|
2095
2209
|
);
|
|
2096
2210
|
};
|
|
2097
|
-
const agentOptionsFor = (model, provider) =>
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2211
|
+
const agentOptionsFor = (model, provider) => {
|
|
2212
|
+
const defaults = defaultSelection();
|
|
2213
|
+
const resolvedProvider = provider ?? config.provider ?? defaults.provider;
|
|
2214
|
+
const resolvedModel = model ?? config.model ?? defaults.model;
|
|
2215
|
+
return withInteractionMode({
|
|
2216
|
+
...resolvedProvider !== void 0 ? { provider: resolvedProvider } : {},
|
|
2217
|
+
...resolvedModel !== void 0 ? { model: resolvedModel } : {},
|
|
2218
|
+
...config.maxTokens !== void 0 ? { maxTokens: config.maxTokens } : {}
|
|
2219
|
+
}, clientInteractionMode);
|
|
2220
|
+
};
|
|
2102
2221
|
const ownedRecord = (agent) => {
|
|
2103
2222
|
const record = sessions.get(String(agent.session.id));
|
|
2104
2223
|
return record?.agent === agent ? record : void 0;
|
|
@@ -2291,8 +2410,8 @@ async function apply3(ctx, config = {}) {
|
|
|
2291
2410
|
return {
|
|
2292
2411
|
currentModeId: record.modeId,
|
|
2293
2412
|
availableModes: permission.names.map((name5) => {
|
|
2294
|
-
const
|
|
2295
|
-
return { id: name5,
|
|
2413
|
+
const presentation = permissionPresentation(name5);
|
|
2414
|
+
return { id: name5, ...presentation };
|
|
2296
2415
|
})
|
|
2297
2416
|
};
|
|
2298
2417
|
}
|
|
@@ -2368,6 +2487,25 @@ async function apply3(ctx, config = {}) {
|
|
|
2368
2487
|
record.approvals = policy;
|
|
2369
2488
|
};
|
|
2370
2489
|
const permissionService = () => permissionPresets;
|
|
2490
|
+
const permissionPresentation = (id) => {
|
|
2491
|
+
const spec = permissionService().resolve(id);
|
|
2492
|
+
const stock = MODE_LABELS[id];
|
|
2493
|
+
const fallbackName = stock?.name ?? id.split("-").map((part) => part.length > 0 ? `${part[0].toUpperCase()}${part.slice(1)}` : part).join(" ");
|
|
2494
|
+
return {
|
|
2495
|
+
name: typeof spec.name === "string" && spec.name.trim().length > 0 ? spec.name : fallbackName,
|
|
2496
|
+
description: typeof spec.description === "string" ? spec.description : stock?.description ?? ""
|
|
2497
|
+
};
|
|
2498
|
+
};
|
|
2499
|
+
const saveDefaultPermission = async (modeId) => {
|
|
2500
|
+
if (!permissionService().names.includes(modeId)) return;
|
|
2501
|
+
try {
|
|
2502
|
+
await ctx.get("settings")?.update(PERMISSION_SETTINGS_NAMESPACE, {
|
|
2503
|
+
defaultPreset: modeId
|
|
2504
|
+
});
|
|
2505
|
+
} catch (error) {
|
|
2506
|
+
logWarn(`permission switch applied to the session but was not saved as the default: ${String(error)}`);
|
|
2507
|
+
}
|
|
2508
|
+
};
|
|
2371
2509
|
const applyMode = (record, sessionId, modeId) => {
|
|
2372
2510
|
const permission = permissionService();
|
|
2373
2511
|
if (permission.names.includes(modeId)) {
|
|
@@ -2418,8 +2556,8 @@ async function apply3(ctx, config = {}) {
|
|
|
2418
2556
|
{
|
|
2419
2557
|
const permission = permissionService();
|
|
2420
2558
|
const levels = permission.names.length > 0 ? permission.names.map((name5) => {
|
|
2421
|
-
const
|
|
2422
|
-
return { value: name5,
|
|
2559
|
+
const presentation = permissionPresentation(name5);
|
|
2560
|
+
return { value: name5, ...presentation };
|
|
2423
2561
|
}) : SANDBOX_MODES2.map((mode) => {
|
|
2424
2562
|
const label = MODE_LABELS[mode] ?? { name: mode, description: "" };
|
|
2425
2563
|
return { value: mode, name: label.name, description: label.description };
|
|
@@ -3081,6 +3219,7 @@ async function apply3(ctx, config = {}) {
|
|
|
3081
3219
|
async setSessionMode(params) {
|
|
3082
3220
|
const record = await requireOrRestoreSession(params.sessionId);
|
|
3083
3221
|
applyMode(record, params.sessionId, params.modeId);
|
|
3222
|
+
await saveDefaultPermission(params.modeId);
|
|
3084
3223
|
notify(params.sessionId, {
|
|
3085
3224
|
sessionUpdate: "config_option_update",
|
|
3086
3225
|
configOptions: await configOptions(record)
|
|
@@ -3094,6 +3233,7 @@ async function apply3(ctx, config = {}) {
|
|
|
3094
3233
|
switch (params.configId) {
|
|
3095
3234
|
case "mode": {
|
|
3096
3235
|
applyMode(record, params.sessionId, value);
|
|
3236
|
+
await saveDefaultPermission(value);
|
|
3097
3237
|
break;
|
|
3098
3238
|
}
|
|
3099
3239
|
case "agent":
|
package/dist/index.js
CHANGED
|
@@ -295,11 +295,8 @@ async function bootAcpProfile(host, overrides) {
|
|
|
295
295
|
const appBoot = await import(pathToFileURL(req.resolve("@deepseek-ai/dsh-app-boot")).href);
|
|
296
296
|
const homePaths = await import(pathToFileURL(req.resolve("@deepseek-ai/dsh-home-paths")).href);
|
|
297
297
|
const home = homePaths.resolveDshHome();
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
let profilePatchPath;
|
|
301
|
-
let rootConfigPath = join3(ownRoot(), "profile-root.cordis.yml");
|
|
302
|
-
let bareModuleBaseUrl = pathToFileURL(dshDir + sep2).href;
|
|
298
|
+
const rootConfigPath = join3(ownRoot(), "profile-root.cordis.yml");
|
|
299
|
+
const bareModuleBaseUrl = pathToFileURL(dshDir + sep2).href;
|
|
303
300
|
const distBridge = join3(ownRoot(), "dist", "bridge.js");
|
|
304
301
|
const bridgeEntry = import.meta.url.endsWith(".ts") || !existsSync3(distBridge) ? join3(ownRoot(), "src", "bundle.ts") : distBridge;
|
|
305
302
|
const distServer = join3(ownRoot(), "dist", "server.js");
|
|
@@ -308,26 +305,13 @@ async function bootAcpProfile(host, overrides) {
|
|
|
308
305
|
const pluginEntry = import.meta.url.endsWith(".ts") || !existsSync3(distPlugin) ? join3(ownRoot(), "src", "plugin.ts") : distPlugin;
|
|
309
306
|
const distStdio = join3(ownRoot(), "dist", "stdio.js");
|
|
310
307
|
const stdioEntry = import.meta.url.endsWith(".ts") || !existsSync3(distStdio) ? join3(ownRoot(), "src", "stdio.ts") : distStdio;
|
|
311
|
-
const
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
const realRoot = join3(profile.dir, "cordis.yml");
|
|
319
|
-
if (existsSync3(realRoot)) rootConfigPath = realRoot;
|
|
320
|
-
bareModuleBaseUrl = void 0;
|
|
321
|
-
logDebug(`profile: real (${profile.dir})`);
|
|
322
|
-
} else {
|
|
323
|
-
const basePatch = bundlePatchPath(req.resolve("@deepseek-ai/dsh-base/package.json"));
|
|
324
|
-
const ownPatch = bundlePatchPath(join3(ownRoot(), "package.json"));
|
|
325
|
-
bundlePatches = [
|
|
326
|
-
...appBoot.loadOverlayPatches(BIN, basePatch),
|
|
327
|
-
...appBoot.loadOverlayPatches(BIN, ownPatch)
|
|
328
|
-
];
|
|
329
|
-
logDebug(`profile: virtual (dsh-base + ${ownRoot()})`);
|
|
330
|
-
}
|
|
308
|
+
const basePatch = bundlePatchPath(req.resolve("@deepseek-ai/dsh-base/package.json"));
|
|
309
|
+
const ownPatch = bundlePatchPath(join3(ownRoot(), "package.json"));
|
|
310
|
+
const bundlePatches = [
|
|
311
|
+
...appBoot.loadOverlayPatches(BIN, basePatch),
|
|
312
|
+
...appBoot.loadOverlayPatches(BIN, ownPatch)
|
|
313
|
+
];
|
|
314
|
+
logDebug(`profile: standalone (dsh-base + ${ownRoot()})`);
|
|
331
315
|
for (const bundle of overrides?.bundles ?? []) {
|
|
332
316
|
bundlePatches.push(...loadBundleLayer(appBoot, bundle));
|
|
333
317
|
logDebug(`profile: added bundle ${bundle}`);
|
|
@@ -343,7 +327,7 @@ async function bootAcpProfile(host, overrides) {
|
|
|
343
327
|
const homePatchPath = join3(home, "cordis.patch.yml");
|
|
344
328
|
const homePatches = appBoot.loadOptionalPatches(BIN, homePatchPath) ?? [];
|
|
345
329
|
const rows = /* @__PURE__ */ new Map();
|
|
346
|
-
for (const row of appBoot.composeEntries([bundlePatches,
|
|
330
|
+
for (const row of appBoot.composeEntries([bundlePatches, homePatches])) {
|
|
347
331
|
if (typeof row.id === "string") rows.set(row.id, row);
|
|
348
332
|
}
|
|
349
333
|
const overlays = [];
|
|
@@ -376,7 +360,7 @@ async function bootAcpProfile(host, overrides) {
|
|
|
376
360
|
overlays.push({ id: configRowId, config: { ...configRow.config ?? {}, ...patch } });
|
|
377
361
|
}
|
|
378
362
|
}
|
|
379
|
-
const allPatches = [...bundlePatches, ...
|
|
363
|
+
const allPatches = [...bundlePatches, ...homePatches, ...overlays];
|
|
380
364
|
const launchEnvironment = appBoot.loadLayeredEnv("dsh");
|
|
381
365
|
const launchEnvKey = (await import(pathToFileURL(req.resolve("@deepseek-ai/dsh-launch-environment")).href)).DSH_LAUNCH_ENVIRONMENT_KEY;
|
|
382
366
|
const ctx = await appBoot.boot(
|
|
@@ -396,9 +380,6 @@ async function bootAcpProfile(host, overrides) {
|
|
|
396
380
|
});
|
|
397
381
|
throw error;
|
|
398
382
|
}
|
|
399
|
-
if (profilePatchPath !== void 0) {
|
|
400
|
-
logDebug(`user patch layers are read at boot; edit ${profilePatchPath} and restart to apply`);
|
|
401
|
-
}
|
|
402
383
|
return ctx;
|
|
403
384
|
}
|
|
404
385
|
|
package/dist/plugin.js
CHANGED
|
@@ -73,6 +73,7 @@ import {
|
|
|
73
73
|
} from "@agentclientprotocol/sdk";
|
|
74
74
|
import { credentialRef } from "@deepseek-ai/dsh-credentials";
|
|
75
75
|
import { ReasoningEffortId } from "@deepseek-ai/dsh-llm";
|
|
76
|
+
import { PERMISSION_SETTINGS_NAMESPACE } from "@deepseek-ai/dsh-permission-presets";
|
|
76
77
|
|
|
77
78
|
// src/version.ts
|
|
78
79
|
import { createRequire } from "node:module";
|
|
@@ -533,7 +534,10 @@ var SessionProjection = class {
|
|
|
533
534
|
title;
|
|
534
535
|
streamedText = /* @__PURE__ */ new Set();
|
|
535
536
|
streamedReasoning = /* @__PURE__ */ new Set();
|
|
537
|
+
/** One authoritative state per open ACP tool call. Block indexes only
|
|
538
|
+
* route streaming fragments to that state; they never own lifecycle. */
|
|
536
539
|
toolCalls = /* @__PURE__ */ new Map();
|
|
540
|
+
toolCallBlocks = /* @__PURE__ */ new Map();
|
|
537
541
|
window = emptyWindow();
|
|
538
542
|
lastContextUse;
|
|
539
543
|
/** Client renders `_meta.terminal_output` display terminals (Zed extension). */
|
|
@@ -552,6 +556,7 @@ var SessionProjection = class {
|
|
|
552
556
|
/** Reset per-prompt accumulators; call when a new `session/prompt` starts. */
|
|
553
557
|
beginPrompt() {
|
|
554
558
|
this.window = emptyWindow();
|
|
559
|
+
this.toolCallBlocks.clear();
|
|
555
560
|
}
|
|
556
561
|
/** The captured ending for a specific turn, when it already ended. */
|
|
557
562
|
turnEndFor(turn) {
|
|
@@ -591,6 +596,8 @@ var SessionProjection = class {
|
|
|
591
596
|
switch (event.type) {
|
|
592
597
|
case "assistant/chunk":
|
|
593
598
|
return this.onChunk(data);
|
|
599
|
+
case "tool-call-chunks":
|
|
600
|
+
return this.onToolCallChunks(data);
|
|
594
601
|
case "assistant/message":
|
|
595
602
|
return this.onAssistantMessage(data);
|
|
596
603
|
case "tool/call":
|
|
@@ -673,42 +680,31 @@ var SessionProjection = class {
|
|
|
673
680
|
onSubagentStart(data) {
|
|
674
681
|
const subagent = this.subagentMeta(data, "started");
|
|
675
682
|
if (subagent === void 0) return [];
|
|
676
|
-
const runId = subagent["runId"];
|
|
677
|
-
const childSessionId = subagent["childSessionId"];
|
|
678
683
|
return [{
|
|
679
|
-
sessionUpdate: "
|
|
680
|
-
|
|
681
|
-
title: `Start subagent ${childSessionId}`,
|
|
682
|
-
kind: "other",
|
|
683
|
-
status: "in_progress",
|
|
684
|
-
rawInput: {
|
|
685
|
-
childSessionId,
|
|
686
|
-
provider: subagent["provider"],
|
|
687
|
-
local: subagent["local"]
|
|
688
|
-
},
|
|
689
|
-
_meta: { dsh: { subagent } }
|
|
684
|
+
sessionUpdate: "session_info_update",
|
|
685
|
+
_meta: { dsh: { event: "subagent/lifecycle", subagent } }
|
|
690
686
|
}];
|
|
691
687
|
}
|
|
692
688
|
onSubagentEnd(data) {
|
|
693
689
|
const subagent = this.subagentMeta(data, "finished");
|
|
694
690
|
if (subagent === void 0) return [];
|
|
695
691
|
const stopReason = asString(data["stopReason"]) ?? "error";
|
|
696
|
-
const lastAssistantMessage = data["lastAssistantMessage"];
|
|
697
692
|
return [{
|
|
698
|
-
sessionUpdate: "
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
}
|
|
705
|
-
_meta: { dsh: { subagent } }
|
|
693
|
+
sessionUpdate: "session_info_update",
|
|
694
|
+
_meta: {
|
|
695
|
+
dsh: {
|
|
696
|
+
event: "subagent/lifecycle",
|
|
697
|
+
subagent: { ...subagent, stopReason }
|
|
698
|
+
}
|
|
699
|
+
}
|
|
706
700
|
}];
|
|
707
701
|
}
|
|
708
702
|
onChunk(data) {
|
|
709
703
|
const chunk = data["chunk"];
|
|
710
704
|
if (chunk === null || typeof chunk === "undefined" || typeof chunk !== "object") return [];
|
|
711
705
|
const c = chunk;
|
|
706
|
+
if (c["type"] === "block-end") return this.onToolCallBlockEnd(data, c);
|
|
707
|
+
if (c["type"] === "tool-call-delta") return this.onToolCallDelta(data, c);
|
|
712
708
|
const text = c["text"];
|
|
713
709
|
if (typeof text !== "string" || text.length === 0) return [];
|
|
714
710
|
const messageId = this.stepKey(data);
|
|
@@ -722,6 +718,97 @@ var SessionProjection = class {
|
|
|
722
718
|
}
|
|
723
719
|
return [];
|
|
724
720
|
}
|
|
721
|
+
toolBlockKey(data, index) {
|
|
722
|
+
return `${this.stepKey(data)}:${index}`;
|
|
723
|
+
}
|
|
724
|
+
onToolCallDelta(data, chunk) {
|
|
725
|
+
const callId = asString(chunk["id"]);
|
|
726
|
+
const index = chunk["index"];
|
|
727
|
+
const argumentsDelta = chunk["argumentsDelta"];
|
|
728
|
+
if (callId === void 0 || typeof index !== "number" || !Number.isInteger(index) || typeof argumentsDelta !== "string") {
|
|
729
|
+
return [];
|
|
730
|
+
}
|
|
731
|
+
const current = this.toolCalls.get(callId);
|
|
732
|
+
const name6 = asString(chunk["name"]) ?? current?.name;
|
|
733
|
+
if (name6 === void 0) return [];
|
|
734
|
+
const rawArguments = `${current?.arguments ?? ""}${argumentsDelta}`;
|
|
735
|
+
const state = {
|
|
736
|
+
callId,
|
|
737
|
+
name: name6,
|
|
738
|
+
arguments: rawArguments,
|
|
739
|
+
facts: this.toolCallFacts(name6, rawArguments),
|
|
740
|
+
status: current?.status ?? "pending"
|
|
741
|
+
};
|
|
742
|
+
this.toolCalls.set(callId, state);
|
|
743
|
+
this.toolCallBlocks.set(this.toolBlockKey(data, index), callId);
|
|
744
|
+
if (current === void 0) return [this.toolCallCreated(state)];
|
|
745
|
+
return [{
|
|
746
|
+
sessionUpdate: "tool_call_update",
|
|
747
|
+
toolCallId: callId,
|
|
748
|
+
title: state.facts.title,
|
|
749
|
+
name: name6,
|
|
750
|
+
kind: state.facts.kind,
|
|
751
|
+
status: "pending",
|
|
752
|
+
rawInput: state.facts.rawInput,
|
|
753
|
+
...state.facts.locations.length > 0 ? { locations: state.facts.locations } : {}
|
|
754
|
+
}];
|
|
755
|
+
}
|
|
756
|
+
onToolCallChunks(data) {
|
|
757
|
+
const callId = asString(data["id"]);
|
|
758
|
+
const name6 = asString(data["name"]);
|
|
759
|
+
const index = data["index"];
|
|
760
|
+
const args = data["args"];
|
|
761
|
+
if (callId === void 0 || name6 === void 0 || typeof index !== "number" || !Number.isInteger(index) || !Array.isArray(args)) {
|
|
762
|
+
return [];
|
|
763
|
+
}
|
|
764
|
+
const key = this.toolBlockKey(data, index);
|
|
765
|
+
const current = this.toolCalls.get(callId);
|
|
766
|
+
const fragments = args.filter((fragment) => typeof fragment === "string").join("");
|
|
767
|
+
const rawArguments = `${current?.arguments ?? ""}${fragments}`;
|
|
768
|
+
const state = {
|
|
769
|
+
callId,
|
|
770
|
+
name: name6,
|
|
771
|
+
arguments: rawArguments,
|
|
772
|
+
facts: this.toolCallFacts(name6, rawArguments),
|
|
773
|
+
status: current?.status ?? "pending"
|
|
774
|
+
};
|
|
775
|
+
this.toolCalls.set(callId, state);
|
|
776
|
+
this.toolCallBlocks.set(key, callId);
|
|
777
|
+
return current === void 0 ? [this.toolCallCreated(state)] : [];
|
|
778
|
+
}
|
|
779
|
+
onToolCallBlockEnd(data, chunk) {
|
|
780
|
+
const index = chunk["index"];
|
|
781
|
+
if (typeof index !== "number" || !Number.isInteger(index)) return [];
|
|
782
|
+
const key = this.toolBlockKey(data, index);
|
|
783
|
+
const callId = this.toolCallBlocks.get(key);
|
|
784
|
+
this.toolCallBlocks.delete(key);
|
|
785
|
+
const block = chunk["block"];
|
|
786
|
+
const complete = block !== null && typeof block === "object" ? block : void 0;
|
|
787
|
+
const completeCallId = complete?.["type"] === "tool-call" ? asString(complete["id"]) : void 0;
|
|
788
|
+
const resolvedCallId = callId ?? completeCallId;
|
|
789
|
+
if (resolvedCallId === void 0) return [];
|
|
790
|
+
const current = this.toolCalls.get(resolvedCallId);
|
|
791
|
+
const name6 = (complete?.["type"] === "tool-call" ? asString(complete["name"]) : void 0) ?? current?.name;
|
|
792
|
+
if (name6 === void 0) return [];
|
|
793
|
+
const rawArguments = (complete?.["type"] === "tool-call" && typeof complete["arguments"] === "string" ? complete["arguments"] : void 0) ?? current?.arguments ?? "{}";
|
|
794
|
+
const state = {
|
|
795
|
+
callId: resolvedCallId,
|
|
796
|
+
name: name6,
|
|
797
|
+
arguments: rawArguments,
|
|
798
|
+
facts: this.toolCallFacts(name6, rawArguments),
|
|
799
|
+
status: current?.status ?? "pending"
|
|
800
|
+
};
|
|
801
|
+
this.toolCalls.set(resolvedCallId, state);
|
|
802
|
+
if (current === void 0) return [this.toolCallCreated(state)];
|
|
803
|
+
return [{
|
|
804
|
+
sessionUpdate: "tool_call_update",
|
|
805
|
+
toolCallId: resolvedCallId,
|
|
806
|
+
title: state.facts.title,
|
|
807
|
+
kind: state.facts.kind,
|
|
808
|
+
rawInput: state.facts.rawInput,
|
|
809
|
+
locations: state.facts.locations
|
|
810
|
+
}];
|
|
811
|
+
}
|
|
725
812
|
onAssistantMessage(data) {
|
|
726
813
|
const updates = [];
|
|
727
814
|
const key = this.stepKey(data);
|
|
@@ -785,11 +872,7 @@ var SessionProjection = class {
|
|
|
785
872
|
}
|
|
786
873
|
return updates;
|
|
787
874
|
}
|
|
788
|
-
|
|
789
|
-
const callId = asString(data["callId"]);
|
|
790
|
-
const name6 = asString(data["name"]) ?? "tool";
|
|
791
|
-
if (callId === void 0) return [];
|
|
792
|
-
const rawArguments = typeof data["arguments"] === "string" ? data["arguments"] : "{}";
|
|
875
|
+
toolCallFacts(name6, rawArguments) {
|
|
793
876
|
let parsedArgs = {};
|
|
794
877
|
try {
|
|
795
878
|
parsedArgs = JSON.parse(rawArguments);
|
|
@@ -797,30 +880,52 @@ var SessionProjection = class {
|
|
|
797
880
|
parsedArgs = { arguments: rawArguments };
|
|
798
881
|
}
|
|
799
882
|
const presented = this.presentCall?.(name6, parsedArgs);
|
|
800
|
-
|
|
801
|
-
|
|
883
|
+
return presented !== void 0 ? factsFromPresentCall(name6, rawArguments, presented) : classifyToolCall(name6, rawArguments);
|
|
884
|
+
}
|
|
885
|
+
toolCallCreated(state) {
|
|
886
|
+
const { callId, name: name6, facts, status } = state;
|
|
802
887
|
const displayTerminal = this.terminalOutput && facts.kind === "execute";
|
|
803
|
-
return
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
...this.cwd !== void 0 ? { cwd: this.cwd } : {}
|
|
819
|
-
}
|
|
888
|
+
return {
|
|
889
|
+
sessionUpdate: "tool_call",
|
|
890
|
+
toolCallId: callId,
|
|
891
|
+
title: facts.title,
|
|
892
|
+
name: name6,
|
|
893
|
+
kind: facts.kind,
|
|
894
|
+
status,
|
|
895
|
+
rawInput: facts.rawInput,
|
|
896
|
+
...facts.locations.length > 0 ? { locations: facts.locations } : {},
|
|
897
|
+
...displayTerminal ? {
|
|
898
|
+
content: [{ type: "terminal", terminalId: callId }],
|
|
899
|
+
_meta: {
|
|
900
|
+
terminal_info: {
|
|
901
|
+
terminal_id: callId,
|
|
902
|
+
...this.cwd !== void 0 ? { cwd: this.cwd } : {}
|
|
820
903
|
}
|
|
821
|
-
}
|
|
822
|
-
}
|
|
823
|
-
|
|
904
|
+
}
|
|
905
|
+
} : {}
|
|
906
|
+
};
|
|
907
|
+
}
|
|
908
|
+
onToolCall(data) {
|
|
909
|
+
const callId = asString(data["callId"]);
|
|
910
|
+
const name6 = asString(data["name"]) ?? "tool";
|
|
911
|
+
if (callId === void 0) return [];
|
|
912
|
+
const rawArguments = typeof data["arguments"] === "string" ? data["arguments"] : "{}";
|
|
913
|
+
const facts = this.toolCallFacts(name6, rawArguments);
|
|
914
|
+
const current = this.toolCalls.get(callId);
|
|
915
|
+
const state = { callId, name: name6, arguments: rawArguments, facts, status: "in_progress" };
|
|
916
|
+
this.toolCalls.set(callId, state);
|
|
917
|
+
if (current === void 0) return [this.toolCallCreated(state)];
|
|
918
|
+
if (current.status === "in_progress" && current.arguments === rawArguments && current.name === name6) return [];
|
|
919
|
+
return [{
|
|
920
|
+
sessionUpdate: "tool_call_update",
|
|
921
|
+
toolCallId: callId,
|
|
922
|
+
title: facts.title,
|
|
923
|
+
name: name6,
|
|
924
|
+
kind: facts.kind,
|
|
925
|
+
status: "in_progress",
|
|
926
|
+
rawInput: facts.rawInput,
|
|
927
|
+
locations: facts.locations
|
|
928
|
+
}];
|
|
824
929
|
}
|
|
825
930
|
onToolResult(data) {
|
|
826
931
|
const message = data["message"];
|
|
@@ -835,7 +940,8 @@ var SessionProjection = class {
|
|
|
835
940
|
})() : void 0
|
|
836
941
|
) ?? asString(data["callId"]);
|
|
837
942
|
if (callId === void 0) return [];
|
|
838
|
-
const
|
|
943
|
+
const state = this.toolCalls.get(callId);
|
|
944
|
+
const facts = state?.facts;
|
|
839
945
|
const { failed, text, diffs } = extractToolResult(data);
|
|
840
946
|
const content = diffs.map((diff) => ({
|
|
841
947
|
type: "diff",
|
|
@@ -846,6 +952,9 @@ var SessionProjection = class {
|
|
|
846
952
|
const isCommand = facts?.kind === "execute";
|
|
847
953
|
if (this.terminalOutput && isCommand) {
|
|
848
954
|
this.toolCalls.delete(callId);
|
|
955
|
+
for (const [key, value] of this.toolCallBlocks) {
|
|
956
|
+
if (value === callId) this.toolCallBlocks.delete(key);
|
|
957
|
+
}
|
|
849
958
|
return [
|
|
850
959
|
...text.length > 0 ? [
|
|
851
960
|
{
|
|
@@ -876,6 +985,9 @@ ${text.replace(/\n+$/, "")}
|
|
|
876
985
|
content.push({ type: "content", content: block });
|
|
877
986
|
}
|
|
878
987
|
this.toolCalls.delete(callId);
|
|
988
|
+
for (const [key, value] of this.toolCallBlocks) {
|
|
989
|
+
if (value === callId) this.toolCallBlocks.delete(key);
|
|
990
|
+
}
|
|
879
991
|
return [
|
|
880
992
|
{
|
|
881
993
|
sessionUpdate: "tool_call_update",
|
|
@@ -897,6 +1009,8 @@ ${text.replace(/\n+$/, "")}
|
|
|
897
1009
|
this.window.error = { message: r.error?.message ?? "model turn failed" };
|
|
898
1010
|
}
|
|
899
1011
|
}
|
|
1012
|
+
this.toolCallBlocks.clear();
|
|
1013
|
+
this.toolCalls.clear();
|
|
900
1014
|
return [];
|
|
901
1015
|
}
|
|
902
1016
|
};
|
|
@@ -2096,11 +2210,16 @@ async function apply3(ctx, config = {}) {
|
|
|
2096
2210
|
'no credential found for this provider: call authenticate with `_meta["api-key"].apiKey` or `_meta.gateway`, use the browser method, run `dsh-acp login`, or save a key in the dsh Web UI (Settings \u2192 Models)'
|
|
2097
2211
|
);
|
|
2098
2212
|
};
|
|
2099
|
-
const agentOptionsFor = (model, provider) =>
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2213
|
+
const agentOptionsFor = (model, provider) => {
|
|
2214
|
+
const defaults = defaultSelection();
|
|
2215
|
+
const resolvedProvider = provider ?? config.provider ?? defaults.provider;
|
|
2216
|
+
const resolvedModel = model ?? config.model ?? defaults.model;
|
|
2217
|
+
return withInteractionMode({
|
|
2218
|
+
...resolvedProvider !== void 0 ? { provider: resolvedProvider } : {},
|
|
2219
|
+
...resolvedModel !== void 0 ? { model: resolvedModel } : {},
|
|
2220
|
+
...config.maxTokens !== void 0 ? { maxTokens: config.maxTokens } : {}
|
|
2221
|
+
}, clientInteractionMode);
|
|
2222
|
+
};
|
|
2104
2223
|
const ownedRecord = (agent) => {
|
|
2105
2224
|
const record = sessions.get(String(agent.session.id));
|
|
2106
2225
|
return record?.agent === agent ? record : void 0;
|
|
@@ -2293,8 +2412,8 @@ async function apply3(ctx, config = {}) {
|
|
|
2293
2412
|
return {
|
|
2294
2413
|
currentModeId: record.modeId,
|
|
2295
2414
|
availableModes: permission.names.map((name6) => {
|
|
2296
|
-
const
|
|
2297
|
-
return { id: name6,
|
|
2415
|
+
const presentation = permissionPresentation(name6);
|
|
2416
|
+
return { id: name6, ...presentation };
|
|
2298
2417
|
})
|
|
2299
2418
|
};
|
|
2300
2419
|
}
|
|
@@ -2370,6 +2489,25 @@ async function apply3(ctx, config = {}) {
|
|
|
2370
2489
|
record.approvals = policy;
|
|
2371
2490
|
};
|
|
2372
2491
|
const permissionService = () => permissionPresets;
|
|
2492
|
+
const permissionPresentation = (id) => {
|
|
2493
|
+
const spec = permissionService().resolve(id);
|
|
2494
|
+
const stock = MODE_LABELS[id];
|
|
2495
|
+
const fallbackName = stock?.name ?? id.split("-").map((part) => part.length > 0 ? `${part[0].toUpperCase()}${part.slice(1)}` : part).join(" ");
|
|
2496
|
+
return {
|
|
2497
|
+
name: typeof spec.name === "string" && spec.name.trim().length > 0 ? spec.name : fallbackName,
|
|
2498
|
+
description: typeof spec.description === "string" ? spec.description : stock?.description ?? ""
|
|
2499
|
+
};
|
|
2500
|
+
};
|
|
2501
|
+
const saveDefaultPermission = async (modeId) => {
|
|
2502
|
+
if (!permissionService().names.includes(modeId)) return;
|
|
2503
|
+
try {
|
|
2504
|
+
await ctx.get("settings")?.update(PERMISSION_SETTINGS_NAMESPACE, {
|
|
2505
|
+
defaultPreset: modeId
|
|
2506
|
+
});
|
|
2507
|
+
} catch (error) {
|
|
2508
|
+
logWarn(`permission switch applied to the session but was not saved as the default: ${String(error)}`);
|
|
2509
|
+
}
|
|
2510
|
+
};
|
|
2373
2511
|
const applyMode = (record, sessionId, modeId) => {
|
|
2374
2512
|
const permission = permissionService();
|
|
2375
2513
|
if (permission.names.includes(modeId)) {
|
|
@@ -2420,8 +2558,8 @@ async function apply3(ctx, config = {}) {
|
|
|
2420
2558
|
{
|
|
2421
2559
|
const permission = permissionService();
|
|
2422
2560
|
const levels = permission.names.length > 0 ? permission.names.map((name6) => {
|
|
2423
|
-
const
|
|
2424
|
-
return { value: name6,
|
|
2561
|
+
const presentation = permissionPresentation(name6);
|
|
2562
|
+
return { value: name6, ...presentation };
|
|
2425
2563
|
}) : SANDBOX_MODES2.map((mode) => {
|
|
2426
2564
|
const label = MODE_LABELS[mode] ?? { name: mode, description: "" };
|
|
2427
2565
|
return { value: mode, name: label.name, description: label.description };
|
|
@@ -3083,6 +3221,7 @@ async function apply3(ctx, config = {}) {
|
|
|
3083
3221
|
async setSessionMode(params) {
|
|
3084
3222
|
const record = await requireOrRestoreSession(params.sessionId);
|
|
3085
3223
|
applyMode(record, params.sessionId, params.modeId);
|
|
3224
|
+
await saveDefaultPermission(params.modeId);
|
|
3086
3225
|
notify(params.sessionId, {
|
|
3087
3226
|
sessionUpdate: "config_option_update",
|
|
3088
3227
|
configOptions: await configOptions(record)
|
|
@@ -3096,6 +3235,7 @@ async function apply3(ctx, config = {}) {
|
|
|
3096
3235
|
switch (params.configId) {
|
|
3097
3236
|
case "mode": {
|
|
3098
3237
|
applyMode(record, params.sessionId, value);
|
|
3238
|
+
await saveDefaultPermission(value);
|
|
3099
3239
|
break;
|
|
3100
3240
|
}
|
|
3101
3241
|
case "agent":
|
package/dist/server.js
CHANGED
|
@@ -67,6 +67,7 @@ import {
|
|
|
67
67
|
} from "@agentclientprotocol/sdk";
|
|
68
68
|
import { credentialRef } from "@deepseek-ai/dsh-credentials";
|
|
69
69
|
import { ReasoningEffortId } from "@deepseek-ai/dsh-llm";
|
|
70
|
+
import { PERMISSION_SETTINGS_NAMESPACE } from "@deepseek-ai/dsh-permission-presets";
|
|
70
71
|
|
|
71
72
|
// src/version.ts
|
|
72
73
|
import { createRequire } from "node:module";
|
|
@@ -527,7 +528,10 @@ var SessionProjection = class {
|
|
|
527
528
|
title;
|
|
528
529
|
streamedText = /* @__PURE__ */ new Set();
|
|
529
530
|
streamedReasoning = /* @__PURE__ */ new Set();
|
|
531
|
+
/** One authoritative state per open ACP tool call. Block indexes only
|
|
532
|
+
* route streaming fragments to that state; they never own lifecycle. */
|
|
530
533
|
toolCalls = /* @__PURE__ */ new Map();
|
|
534
|
+
toolCallBlocks = /* @__PURE__ */ new Map();
|
|
531
535
|
window = emptyWindow();
|
|
532
536
|
lastContextUse;
|
|
533
537
|
/** Client renders `_meta.terminal_output` display terminals (Zed extension). */
|
|
@@ -546,6 +550,7 @@ var SessionProjection = class {
|
|
|
546
550
|
/** Reset per-prompt accumulators; call when a new `session/prompt` starts. */
|
|
547
551
|
beginPrompt() {
|
|
548
552
|
this.window = emptyWindow();
|
|
553
|
+
this.toolCallBlocks.clear();
|
|
549
554
|
}
|
|
550
555
|
/** The captured ending for a specific turn, when it already ended. */
|
|
551
556
|
turnEndFor(turn) {
|
|
@@ -585,6 +590,8 @@ var SessionProjection = class {
|
|
|
585
590
|
switch (event.type) {
|
|
586
591
|
case "assistant/chunk":
|
|
587
592
|
return this.onChunk(data);
|
|
593
|
+
case "tool-call-chunks":
|
|
594
|
+
return this.onToolCallChunks(data);
|
|
588
595
|
case "assistant/message":
|
|
589
596
|
return this.onAssistantMessage(data);
|
|
590
597
|
case "tool/call":
|
|
@@ -667,42 +674,31 @@ var SessionProjection = class {
|
|
|
667
674
|
onSubagentStart(data) {
|
|
668
675
|
const subagent = this.subagentMeta(data, "started");
|
|
669
676
|
if (subagent === void 0) return [];
|
|
670
|
-
const runId = subagent["runId"];
|
|
671
|
-
const childSessionId = subagent["childSessionId"];
|
|
672
677
|
return [{
|
|
673
|
-
sessionUpdate: "
|
|
674
|
-
|
|
675
|
-
title: `Start subagent ${childSessionId}`,
|
|
676
|
-
kind: "other",
|
|
677
|
-
status: "in_progress",
|
|
678
|
-
rawInput: {
|
|
679
|
-
childSessionId,
|
|
680
|
-
provider: subagent["provider"],
|
|
681
|
-
local: subagent["local"]
|
|
682
|
-
},
|
|
683
|
-
_meta: { dsh: { subagent } }
|
|
678
|
+
sessionUpdate: "session_info_update",
|
|
679
|
+
_meta: { dsh: { event: "subagent/lifecycle", subagent } }
|
|
684
680
|
}];
|
|
685
681
|
}
|
|
686
682
|
onSubagentEnd(data) {
|
|
687
683
|
const subagent = this.subagentMeta(data, "finished");
|
|
688
684
|
if (subagent === void 0) return [];
|
|
689
685
|
const stopReason = asString(data["stopReason"]) ?? "error";
|
|
690
|
-
const lastAssistantMessage = data["lastAssistantMessage"];
|
|
691
686
|
return [{
|
|
692
|
-
sessionUpdate: "
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
}
|
|
699
|
-
_meta: { dsh: { subagent } }
|
|
687
|
+
sessionUpdate: "session_info_update",
|
|
688
|
+
_meta: {
|
|
689
|
+
dsh: {
|
|
690
|
+
event: "subagent/lifecycle",
|
|
691
|
+
subagent: { ...subagent, stopReason }
|
|
692
|
+
}
|
|
693
|
+
}
|
|
700
694
|
}];
|
|
701
695
|
}
|
|
702
696
|
onChunk(data) {
|
|
703
697
|
const chunk = data["chunk"];
|
|
704
698
|
if (chunk === null || typeof chunk === "undefined" || typeof chunk !== "object") return [];
|
|
705
699
|
const c = chunk;
|
|
700
|
+
if (c["type"] === "block-end") return this.onToolCallBlockEnd(data, c);
|
|
701
|
+
if (c["type"] === "tool-call-delta") return this.onToolCallDelta(data, c);
|
|
706
702
|
const text = c["text"];
|
|
707
703
|
if (typeof text !== "string" || text.length === 0) return [];
|
|
708
704
|
const messageId = this.stepKey(data);
|
|
@@ -716,6 +712,97 @@ var SessionProjection = class {
|
|
|
716
712
|
}
|
|
717
713
|
return [];
|
|
718
714
|
}
|
|
715
|
+
toolBlockKey(data, index) {
|
|
716
|
+
return `${this.stepKey(data)}:${index}`;
|
|
717
|
+
}
|
|
718
|
+
onToolCallDelta(data, chunk) {
|
|
719
|
+
const callId = asString(chunk["id"]);
|
|
720
|
+
const index = chunk["index"];
|
|
721
|
+
const argumentsDelta = chunk["argumentsDelta"];
|
|
722
|
+
if (callId === void 0 || typeof index !== "number" || !Number.isInteger(index) || typeof argumentsDelta !== "string") {
|
|
723
|
+
return [];
|
|
724
|
+
}
|
|
725
|
+
const current = this.toolCalls.get(callId);
|
|
726
|
+
const name5 = asString(chunk["name"]) ?? current?.name;
|
|
727
|
+
if (name5 === void 0) return [];
|
|
728
|
+
const rawArguments = `${current?.arguments ?? ""}${argumentsDelta}`;
|
|
729
|
+
const state = {
|
|
730
|
+
callId,
|
|
731
|
+
name: name5,
|
|
732
|
+
arguments: rawArguments,
|
|
733
|
+
facts: this.toolCallFacts(name5, rawArguments),
|
|
734
|
+
status: current?.status ?? "pending"
|
|
735
|
+
};
|
|
736
|
+
this.toolCalls.set(callId, state);
|
|
737
|
+
this.toolCallBlocks.set(this.toolBlockKey(data, index), callId);
|
|
738
|
+
if (current === void 0) return [this.toolCallCreated(state)];
|
|
739
|
+
return [{
|
|
740
|
+
sessionUpdate: "tool_call_update",
|
|
741
|
+
toolCallId: callId,
|
|
742
|
+
title: state.facts.title,
|
|
743
|
+
name: name5,
|
|
744
|
+
kind: state.facts.kind,
|
|
745
|
+
status: "pending",
|
|
746
|
+
rawInput: state.facts.rawInput,
|
|
747
|
+
...state.facts.locations.length > 0 ? { locations: state.facts.locations } : {}
|
|
748
|
+
}];
|
|
749
|
+
}
|
|
750
|
+
onToolCallChunks(data) {
|
|
751
|
+
const callId = asString(data["id"]);
|
|
752
|
+
const name5 = asString(data["name"]);
|
|
753
|
+
const index = data["index"];
|
|
754
|
+
const args = data["args"];
|
|
755
|
+
if (callId === void 0 || name5 === void 0 || typeof index !== "number" || !Number.isInteger(index) || !Array.isArray(args)) {
|
|
756
|
+
return [];
|
|
757
|
+
}
|
|
758
|
+
const key = this.toolBlockKey(data, index);
|
|
759
|
+
const current = this.toolCalls.get(callId);
|
|
760
|
+
const fragments = args.filter((fragment) => typeof fragment === "string").join("");
|
|
761
|
+
const rawArguments = `${current?.arguments ?? ""}${fragments}`;
|
|
762
|
+
const state = {
|
|
763
|
+
callId,
|
|
764
|
+
name: name5,
|
|
765
|
+
arguments: rawArguments,
|
|
766
|
+
facts: this.toolCallFacts(name5, rawArguments),
|
|
767
|
+
status: current?.status ?? "pending"
|
|
768
|
+
};
|
|
769
|
+
this.toolCalls.set(callId, state);
|
|
770
|
+
this.toolCallBlocks.set(key, callId);
|
|
771
|
+
return current === void 0 ? [this.toolCallCreated(state)] : [];
|
|
772
|
+
}
|
|
773
|
+
onToolCallBlockEnd(data, chunk) {
|
|
774
|
+
const index = chunk["index"];
|
|
775
|
+
if (typeof index !== "number" || !Number.isInteger(index)) return [];
|
|
776
|
+
const key = this.toolBlockKey(data, index);
|
|
777
|
+
const callId = this.toolCallBlocks.get(key);
|
|
778
|
+
this.toolCallBlocks.delete(key);
|
|
779
|
+
const block = chunk["block"];
|
|
780
|
+
const complete = block !== null && typeof block === "object" ? block : void 0;
|
|
781
|
+
const completeCallId = complete?.["type"] === "tool-call" ? asString(complete["id"]) : void 0;
|
|
782
|
+
const resolvedCallId = callId ?? completeCallId;
|
|
783
|
+
if (resolvedCallId === void 0) return [];
|
|
784
|
+
const current = this.toolCalls.get(resolvedCallId);
|
|
785
|
+
const name5 = (complete?.["type"] === "tool-call" ? asString(complete["name"]) : void 0) ?? current?.name;
|
|
786
|
+
if (name5 === void 0) return [];
|
|
787
|
+
const rawArguments = (complete?.["type"] === "tool-call" && typeof complete["arguments"] === "string" ? complete["arguments"] : void 0) ?? current?.arguments ?? "{}";
|
|
788
|
+
const state = {
|
|
789
|
+
callId: resolvedCallId,
|
|
790
|
+
name: name5,
|
|
791
|
+
arguments: rawArguments,
|
|
792
|
+
facts: this.toolCallFacts(name5, rawArguments),
|
|
793
|
+
status: current?.status ?? "pending"
|
|
794
|
+
};
|
|
795
|
+
this.toolCalls.set(resolvedCallId, state);
|
|
796
|
+
if (current === void 0) return [this.toolCallCreated(state)];
|
|
797
|
+
return [{
|
|
798
|
+
sessionUpdate: "tool_call_update",
|
|
799
|
+
toolCallId: resolvedCallId,
|
|
800
|
+
title: state.facts.title,
|
|
801
|
+
kind: state.facts.kind,
|
|
802
|
+
rawInput: state.facts.rawInput,
|
|
803
|
+
locations: state.facts.locations
|
|
804
|
+
}];
|
|
805
|
+
}
|
|
719
806
|
onAssistantMessage(data) {
|
|
720
807
|
const updates = [];
|
|
721
808
|
const key = this.stepKey(data);
|
|
@@ -779,11 +866,7 @@ var SessionProjection = class {
|
|
|
779
866
|
}
|
|
780
867
|
return updates;
|
|
781
868
|
}
|
|
782
|
-
|
|
783
|
-
const callId = asString(data["callId"]);
|
|
784
|
-
const name5 = asString(data["name"]) ?? "tool";
|
|
785
|
-
if (callId === void 0) return [];
|
|
786
|
-
const rawArguments = typeof data["arguments"] === "string" ? data["arguments"] : "{}";
|
|
869
|
+
toolCallFacts(name5, rawArguments) {
|
|
787
870
|
let parsedArgs = {};
|
|
788
871
|
try {
|
|
789
872
|
parsedArgs = JSON.parse(rawArguments);
|
|
@@ -791,30 +874,52 @@ var SessionProjection = class {
|
|
|
791
874
|
parsedArgs = { arguments: rawArguments };
|
|
792
875
|
}
|
|
793
876
|
const presented = this.presentCall?.(name5, parsedArgs);
|
|
794
|
-
|
|
795
|
-
|
|
877
|
+
return presented !== void 0 ? factsFromPresentCall(name5, rawArguments, presented) : classifyToolCall(name5, rawArguments);
|
|
878
|
+
}
|
|
879
|
+
toolCallCreated(state) {
|
|
880
|
+
const { callId, name: name5, facts, status } = state;
|
|
796
881
|
const displayTerminal = this.terminalOutput && facts.kind === "execute";
|
|
797
|
-
return
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
...this.cwd !== void 0 ? { cwd: this.cwd } : {}
|
|
813
|
-
}
|
|
882
|
+
return {
|
|
883
|
+
sessionUpdate: "tool_call",
|
|
884
|
+
toolCallId: callId,
|
|
885
|
+
title: facts.title,
|
|
886
|
+
name: name5,
|
|
887
|
+
kind: facts.kind,
|
|
888
|
+
status,
|
|
889
|
+
rawInput: facts.rawInput,
|
|
890
|
+
...facts.locations.length > 0 ? { locations: facts.locations } : {},
|
|
891
|
+
...displayTerminal ? {
|
|
892
|
+
content: [{ type: "terminal", terminalId: callId }],
|
|
893
|
+
_meta: {
|
|
894
|
+
terminal_info: {
|
|
895
|
+
terminal_id: callId,
|
|
896
|
+
...this.cwd !== void 0 ? { cwd: this.cwd } : {}
|
|
814
897
|
}
|
|
815
|
-
}
|
|
816
|
-
}
|
|
817
|
-
|
|
898
|
+
}
|
|
899
|
+
} : {}
|
|
900
|
+
};
|
|
901
|
+
}
|
|
902
|
+
onToolCall(data) {
|
|
903
|
+
const callId = asString(data["callId"]);
|
|
904
|
+
const name5 = asString(data["name"]) ?? "tool";
|
|
905
|
+
if (callId === void 0) return [];
|
|
906
|
+
const rawArguments = typeof data["arguments"] === "string" ? data["arguments"] : "{}";
|
|
907
|
+
const facts = this.toolCallFacts(name5, rawArguments);
|
|
908
|
+
const current = this.toolCalls.get(callId);
|
|
909
|
+
const state = { callId, name: name5, arguments: rawArguments, facts, status: "in_progress" };
|
|
910
|
+
this.toolCalls.set(callId, state);
|
|
911
|
+
if (current === void 0) return [this.toolCallCreated(state)];
|
|
912
|
+
if (current.status === "in_progress" && current.arguments === rawArguments && current.name === name5) return [];
|
|
913
|
+
return [{
|
|
914
|
+
sessionUpdate: "tool_call_update",
|
|
915
|
+
toolCallId: callId,
|
|
916
|
+
title: facts.title,
|
|
917
|
+
name: name5,
|
|
918
|
+
kind: facts.kind,
|
|
919
|
+
status: "in_progress",
|
|
920
|
+
rawInput: facts.rawInput,
|
|
921
|
+
locations: facts.locations
|
|
922
|
+
}];
|
|
818
923
|
}
|
|
819
924
|
onToolResult(data) {
|
|
820
925
|
const message = data["message"];
|
|
@@ -829,7 +934,8 @@ var SessionProjection = class {
|
|
|
829
934
|
})() : void 0
|
|
830
935
|
) ?? asString(data["callId"]);
|
|
831
936
|
if (callId === void 0) return [];
|
|
832
|
-
const
|
|
937
|
+
const state = this.toolCalls.get(callId);
|
|
938
|
+
const facts = state?.facts;
|
|
833
939
|
const { failed, text, diffs } = extractToolResult(data);
|
|
834
940
|
const content = diffs.map((diff) => ({
|
|
835
941
|
type: "diff",
|
|
@@ -840,6 +946,9 @@ var SessionProjection = class {
|
|
|
840
946
|
const isCommand = facts?.kind === "execute";
|
|
841
947
|
if (this.terminalOutput && isCommand) {
|
|
842
948
|
this.toolCalls.delete(callId);
|
|
949
|
+
for (const [key, value] of this.toolCallBlocks) {
|
|
950
|
+
if (value === callId) this.toolCallBlocks.delete(key);
|
|
951
|
+
}
|
|
843
952
|
return [
|
|
844
953
|
...text.length > 0 ? [
|
|
845
954
|
{
|
|
@@ -870,6 +979,9 @@ ${text.replace(/\n+$/, "")}
|
|
|
870
979
|
content.push({ type: "content", content: block });
|
|
871
980
|
}
|
|
872
981
|
this.toolCalls.delete(callId);
|
|
982
|
+
for (const [key, value] of this.toolCallBlocks) {
|
|
983
|
+
if (value === callId) this.toolCallBlocks.delete(key);
|
|
984
|
+
}
|
|
873
985
|
return [
|
|
874
986
|
{
|
|
875
987
|
sessionUpdate: "tool_call_update",
|
|
@@ -891,6 +1003,8 @@ ${text.replace(/\n+$/, "")}
|
|
|
891
1003
|
this.window.error = { message: r.error?.message ?? "model turn failed" };
|
|
892
1004
|
}
|
|
893
1005
|
}
|
|
1006
|
+
this.toolCallBlocks.clear();
|
|
1007
|
+
this.toolCalls.clear();
|
|
894
1008
|
return [];
|
|
895
1009
|
}
|
|
896
1010
|
};
|
|
@@ -2090,11 +2204,16 @@ async function apply3(ctx, config = {}) {
|
|
|
2090
2204
|
'no credential found for this provider: call authenticate with `_meta["api-key"].apiKey` or `_meta.gateway`, use the browser method, run `dsh-acp login`, or save a key in the dsh Web UI (Settings \u2192 Models)'
|
|
2091
2205
|
);
|
|
2092
2206
|
};
|
|
2093
|
-
const agentOptionsFor = (model, provider) =>
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2207
|
+
const agentOptionsFor = (model, provider) => {
|
|
2208
|
+
const defaults = defaultSelection();
|
|
2209
|
+
const resolvedProvider = provider ?? config.provider ?? defaults.provider;
|
|
2210
|
+
const resolvedModel = model ?? config.model ?? defaults.model;
|
|
2211
|
+
return withInteractionMode({
|
|
2212
|
+
...resolvedProvider !== void 0 ? { provider: resolvedProvider } : {},
|
|
2213
|
+
...resolvedModel !== void 0 ? { model: resolvedModel } : {},
|
|
2214
|
+
...config.maxTokens !== void 0 ? { maxTokens: config.maxTokens } : {}
|
|
2215
|
+
}, clientInteractionMode);
|
|
2216
|
+
};
|
|
2098
2217
|
const ownedRecord = (agent) => {
|
|
2099
2218
|
const record = sessions.get(String(agent.session.id));
|
|
2100
2219
|
return record?.agent === agent ? record : void 0;
|
|
@@ -2287,8 +2406,8 @@ async function apply3(ctx, config = {}) {
|
|
|
2287
2406
|
return {
|
|
2288
2407
|
currentModeId: record.modeId,
|
|
2289
2408
|
availableModes: permission.names.map((name5) => {
|
|
2290
|
-
const
|
|
2291
|
-
return { id: name5,
|
|
2409
|
+
const presentation = permissionPresentation(name5);
|
|
2410
|
+
return { id: name5, ...presentation };
|
|
2292
2411
|
})
|
|
2293
2412
|
};
|
|
2294
2413
|
}
|
|
@@ -2364,6 +2483,25 @@ async function apply3(ctx, config = {}) {
|
|
|
2364
2483
|
record.approvals = policy;
|
|
2365
2484
|
};
|
|
2366
2485
|
const permissionService = () => permissionPresets;
|
|
2486
|
+
const permissionPresentation = (id) => {
|
|
2487
|
+
const spec = permissionService().resolve(id);
|
|
2488
|
+
const stock = MODE_LABELS[id];
|
|
2489
|
+
const fallbackName = stock?.name ?? id.split("-").map((part) => part.length > 0 ? `${part[0].toUpperCase()}${part.slice(1)}` : part).join(" ");
|
|
2490
|
+
return {
|
|
2491
|
+
name: typeof spec.name === "string" && spec.name.trim().length > 0 ? spec.name : fallbackName,
|
|
2492
|
+
description: typeof spec.description === "string" ? spec.description : stock?.description ?? ""
|
|
2493
|
+
};
|
|
2494
|
+
};
|
|
2495
|
+
const saveDefaultPermission = async (modeId) => {
|
|
2496
|
+
if (!permissionService().names.includes(modeId)) return;
|
|
2497
|
+
try {
|
|
2498
|
+
await ctx.get("settings")?.update(PERMISSION_SETTINGS_NAMESPACE, {
|
|
2499
|
+
defaultPreset: modeId
|
|
2500
|
+
});
|
|
2501
|
+
} catch (error) {
|
|
2502
|
+
logWarn(`permission switch applied to the session but was not saved as the default: ${String(error)}`);
|
|
2503
|
+
}
|
|
2504
|
+
};
|
|
2367
2505
|
const applyMode = (record, sessionId, modeId) => {
|
|
2368
2506
|
const permission = permissionService();
|
|
2369
2507
|
if (permission.names.includes(modeId)) {
|
|
@@ -2414,8 +2552,8 @@ async function apply3(ctx, config = {}) {
|
|
|
2414
2552
|
{
|
|
2415
2553
|
const permission = permissionService();
|
|
2416
2554
|
const levels = permission.names.length > 0 ? permission.names.map((name5) => {
|
|
2417
|
-
const
|
|
2418
|
-
return { value: name5,
|
|
2555
|
+
const presentation = permissionPresentation(name5);
|
|
2556
|
+
return { value: name5, ...presentation };
|
|
2419
2557
|
}) : SANDBOX_MODES2.map((mode) => {
|
|
2420
2558
|
const label = MODE_LABELS[mode] ?? { name: mode, description: "" };
|
|
2421
2559
|
return { value: mode, name: label.name, description: label.description };
|
|
@@ -3077,6 +3215,7 @@ async function apply3(ctx, config = {}) {
|
|
|
3077
3215
|
async setSessionMode(params) {
|
|
3078
3216
|
const record = await requireOrRestoreSession(params.sessionId);
|
|
3079
3217
|
applyMode(record, params.sessionId, params.modeId);
|
|
3218
|
+
await saveDefaultPermission(params.modeId);
|
|
3080
3219
|
notify(params.sessionId, {
|
|
3081
3220
|
sessionUpdate: "config_option_update",
|
|
3082
3221
|
configOptions: await configOptions(record)
|
|
@@ -3090,6 +3229,7 @@ async function apply3(ctx, config = {}) {
|
|
|
3090
3229
|
switch (params.configId) {
|
|
3091
3230
|
case "mode": {
|
|
3092
3231
|
applyMode(record, params.sessionId, value);
|
|
3232
|
+
await saveDefaultPermission(value);
|
|
3093
3233
|
break;
|
|
3094
3234
|
}
|
|
3095
3235
|
case "agent":
|
package/dist/stdio.js
CHANGED
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
} from "@agentclientprotocol/sdk";
|
|
35
35
|
import { credentialRef } from "@deepseek-ai/dsh-credentials";
|
|
36
36
|
import { ReasoningEffortId } from "@deepseek-ai/dsh-llm";
|
|
37
|
+
import { PERMISSION_SETTINGS_NAMESPACE } from "@deepseek-ai/dsh-permission-presets";
|
|
37
38
|
|
|
38
39
|
// src/version.ts
|
|
39
40
|
import { createRequire } from "node:module";
|
package/package.json
CHANGED
package/vendor/dsh-runtime.tgz
CHANGED
|
Binary file
|
package/vendor/runtime.json
CHANGED