@ycodium-ai/agent-dsh 0.2.2143 → 0.2.2488
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/README.md +4 -4
- package/dist/index.js +69 -67
- package/locales/en.json +14 -0
- package/locales/zh-CN.json +14 -0
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# @ycodium-ai/agent-dsh
|
|
2
2
|
|
|
3
3
|
DeepSeek Harness executor plugin. Spawns `dsh --profile acp` over stdio and runs
|
|
4
|
-
`ycodium-acp-executor`
|
|
4
|
+
the shared `ycodium-acp-executor` state machine. DSH has no vendor extensions —
|
|
5
5
|
permissions, plan updates, tool calls, and content deltas all arrive as standard
|
|
6
6
|
`session/update` notifications — so the plugin is three facts on top of the shared
|
|
7
7
|
machine:
|
|
8
8
|
|
|
9
|
-
- Launch is `dsh --profile acp` (the disk
|
|
9
|
+
- Launch is `dsh --profile acp` (the on-disk settings shape has no `launchArgs`;
|
|
10
10
|
the default lives on the card).
|
|
11
11
|
- Sessions resume through `session/resume`, not `session/load` — the agent
|
|
12
12
|
reactivates a persisted session without replaying its transcript and answers
|
|
@@ -23,8 +23,8 @@ Facts:
|
|
|
23
23
|
- Credentials come from the environment (`DEEPSEEK_API_KEY`); there is no login
|
|
24
24
|
command and no device-code flow, so `ExecutorInstance.signIn` is not implemented.
|
|
25
25
|
- Manifest permission is `{ kind: "executor" }`.
|
|
26
|
-
- Session model switching is `unsupported` on the card
|
|
27
|
-
|
|
26
|
+
- Session model switching is `unsupported` on the card: the plugin does not switch
|
|
27
|
+
models inside a running session.
|
|
28
28
|
|
|
29
29
|
Develop with `vp run --filter @ycodium-ai/agent-dsh typecheck`, `build`, and `test`.
|
|
30
30
|
|
package/dist/index.js
CHANGED
|
@@ -15,7 +15,7 @@ var DSH_CARD = {
|
|
|
15
15
|
displayName: "DeepSeek Harness",
|
|
16
16
|
iconUrl: "./assets/icon.svg",
|
|
17
17
|
commandName: "dsh",
|
|
18
|
-
// 启动命令是 `dsh --profile acp
|
|
18
|
+
// 启动命令是 `dsh --profile acp`(磁盘上的设置形状没有 launchArgs 字段,
|
|
19
19
|
// 宿主旧实现把它写死在 DshAcpSupport,这里落在名片上)。
|
|
20
20
|
launchArgs: "--profile acp",
|
|
21
21
|
homeEnvVar: "DSH_HOME",
|
|
@@ -41,10 +41,6 @@ var DSH_CARD = {
|
|
|
41
41
|
defaultTextGenerationModel: "",
|
|
42
42
|
customModelIdExample: "",
|
|
43
43
|
modelSlugAliases: null,
|
|
44
|
-
// models.dev 的 `deepseek.env` 恰好也是 `["DEEPSEEK_API_KEY"]`,指向同一个 api.deepseek.com。
|
|
45
|
-
modelsDevProviderIds: ["deepseek"],
|
|
46
|
-
modelsDevSlugPrefixed: false,
|
|
47
|
-
modelSlugPrefix: "",
|
|
48
44
|
// 与宿主 dsh driver 今天的注入面一致。
|
|
49
45
|
mcpTransports: ["stdio", "http", "sse"],
|
|
50
46
|
pluginManaged: true,
|
|
@@ -52,7 +48,7 @@ var DSH_CARD = {
|
|
|
52
48
|
everydayHarness: false,
|
|
53
49
|
capabilities: {
|
|
54
50
|
// DSH 换模型只有 `session/set_config_option` 一条路;库会按握手形状自动协商,
|
|
55
|
-
//
|
|
51
|
+
// 但插件不承诺在跑着的会话里换型号,名片必须说实话。
|
|
56
52
|
sessionModelSwitch: "unsupported",
|
|
57
53
|
// **这一位今天是空头支票,别当它验过**(2026-09-19 拿真 `dsh --profile acp`
|
|
58
54
|
// 起一轮 ACP 会话实测)。两件事都不成立:
|
|
@@ -70,13 +66,29 @@ var DSH_CARD = {
|
|
|
70
66
|
// 凭据由 CLI 自己保管在它 home 里,宿主不读 token。
|
|
71
67
|
credentialSources: [],
|
|
72
68
|
diagnostics: [],
|
|
69
|
+
// 设置表单照这份画:带 x-ycodium-form 的属性才进表单(enabled、customModels 等另有入口,不在此列),
|
|
70
|
+
// 顺序看 x-ycodium-form-order;文案键在本插件 locales/<locale>.json 里解析,宿主不兜底。
|
|
73
71
|
configSchema: {
|
|
74
72
|
type: "object",
|
|
73
|
+
"x-ycodium-form-order": ["binaryPath", "homePath"],
|
|
75
74
|
properties: {
|
|
76
|
-
binaryPath: {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
75
|
+
binaryPath: {
|
|
76
|
+
type: "string",
|
|
77
|
+
"x-ycodium-form": {
|
|
78
|
+
titleKey: "form.binaryPath.title",
|
|
79
|
+
descriptionKey: "form.binaryPath.description",
|
|
80
|
+
placeholderKey: "form.binaryPath.placeholder",
|
|
81
|
+
control: "executable-path"
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
homePath: {
|
|
85
|
+
type: "string",
|
|
86
|
+
"x-ycodium-form": {
|
|
87
|
+
titleKey: "form.homePath.title",
|
|
88
|
+
descriptionKey: "form.homePath.description",
|
|
89
|
+
placeholderKey: "form.homePath.placeholder"
|
|
90
|
+
}
|
|
91
|
+
},
|
|
80
92
|
enabled: { type: "boolean" },
|
|
81
93
|
customModels: { type: "array" },
|
|
82
94
|
driver: { type: "string" },
|
|
@@ -88,8 +100,8 @@ var DSH_CARD = {
|
|
|
88
100
|
modelConnectivity: {
|
|
89
101
|
dialects: ["openai-chat-completions"],
|
|
90
102
|
acceptsExternalEndpoints: true,
|
|
91
|
-
// CLI
|
|
92
|
-
//
|
|
103
|
+
// CLI 在 `DEEPSEEK_BASE_URL` 后追加 `/chat/completions`,所以实例上填的 base 是
|
|
104
|
+
// 服务地址去掉这一截。
|
|
93
105
|
nativePathSuffix: "/chat/completions",
|
|
94
106
|
// 两个都从进程环境读,进程环境只读且优先(它自己的说法:启动时覆盖是操作者意图)。
|
|
95
107
|
// 端点这条有实证:dsh 的端到端测试就是设 DEEPSEEK_BASE_URL 指向假服务器
|
|
@@ -23493,10 +23505,44 @@ var legacyClientNotificationMethods = /* @__PURE__ */ new Set([
|
|
|
23493
23505
|
CLIENT_METHODS.elicitation_complete
|
|
23494
23506
|
]);
|
|
23495
23507
|
|
|
23496
|
-
// ../../packages/ycodium-acp-
|
|
23508
|
+
// ../../packages/ycodium-acp-executor/src/connection.ts
|
|
23497
23509
|
import * as NodeStream from "node:stream";
|
|
23498
23510
|
|
|
23499
|
-
// ../../packages/ycodium-acp-
|
|
23511
|
+
// ../../packages/ycodium-acp-executor/src/errors.ts
|
|
23512
|
+
var AcpExecutorError = class extends Error {
|
|
23513
|
+
code;
|
|
23514
|
+
constructor(code, message) {
|
|
23515
|
+
super(message);
|
|
23516
|
+
this.name = "AcpExecutorError";
|
|
23517
|
+
this.code = code;
|
|
23518
|
+
}
|
|
23519
|
+
};
|
|
23520
|
+
var AcpExecutorDisposedError = class extends AcpExecutorError {
|
|
23521
|
+
constructor(message = "ACP executor has been disposed") {
|
|
23522
|
+
super("disposed", message);
|
|
23523
|
+
this.name = "AcpExecutorDisposedError";
|
|
23524
|
+
}
|
|
23525
|
+
};
|
|
23526
|
+
var AcpExecutorNotStartedError = class extends AcpExecutorError {
|
|
23527
|
+
constructor(message = "ACP session has not been started") {
|
|
23528
|
+
super("not-started", message);
|
|
23529
|
+
this.name = "AcpExecutorNotStartedError";
|
|
23530
|
+
}
|
|
23531
|
+
};
|
|
23532
|
+
var AcpExecutorCancelTimeoutError = class extends AcpExecutorError {
|
|
23533
|
+
constructor(message = "Timed out waiting for session/prompt to finish after cancellation") {
|
|
23534
|
+
super("cancel-timeout", message);
|
|
23535
|
+
this.name = "AcpExecutorCancelTimeoutError";
|
|
23536
|
+
}
|
|
23537
|
+
};
|
|
23538
|
+
var AcpExecutorRequestError = class extends AcpExecutorError {
|
|
23539
|
+
method;
|
|
23540
|
+
constructor(method, message) {
|
|
23541
|
+
super("request-failed", message);
|
|
23542
|
+
this.name = "AcpExecutorRequestError";
|
|
23543
|
+
this.method = method;
|
|
23544
|
+
}
|
|
23545
|
+
};
|
|
23500
23546
|
var AcpConnectionClosedError = class extends Error {
|
|
23501
23547
|
constructor(message = "ACP connection closed") {
|
|
23502
23548
|
super(message);
|
|
@@ -23504,7 +23550,7 @@ var AcpConnectionClosedError = class extends Error {
|
|
|
23504
23550
|
}
|
|
23505
23551
|
};
|
|
23506
23552
|
|
|
23507
|
-
// ../../packages/ycodium-acp-
|
|
23553
|
+
// ../../packages/ycodium-acp-executor/src/jsonrpc.ts
|
|
23508
23554
|
function isRecord2(value) {
|
|
23509
23555
|
return typeof value === "object" && value !== null;
|
|
23510
23556
|
}
|
|
@@ -23542,7 +23588,7 @@ function readJsonRpcError(value) {
|
|
|
23542
23588
|
};
|
|
23543
23589
|
}
|
|
23544
23590
|
|
|
23545
|
-
// ../../packages/ycodium-acp-
|
|
23591
|
+
// ../../packages/ycodium-acp-executor/src/line-buffer.ts
|
|
23546
23592
|
var newline2 = 10;
|
|
23547
23593
|
var LineBuffer2 = class {
|
|
23548
23594
|
#pending = [];
|
|
@@ -23586,7 +23632,7 @@ var LineBuffer2 = class {
|
|
|
23586
23632
|
}
|
|
23587
23633
|
};
|
|
23588
23634
|
|
|
23589
|
-
// ../../packages/ycodium-acp-
|
|
23635
|
+
// ../../packages/ycodium-acp-executor/src/session-update.ts
|
|
23590
23636
|
var KNOWN_SESSION_UPDATES = /* @__PURE__ */ new Set([
|
|
23591
23637
|
"user_message_chunk",
|
|
23592
23638
|
"agent_message_chunk",
|
|
@@ -23631,7 +23677,7 @@ function decodeSessionUpdate(payload) {
|
|
|
23631
23677
|
return { status: "raw", params: payload };
|
|
23632
23678
|
}
|
|
23633
23679
|
|
|
23634
|
-
// ../../packages/ycodium-acp-
|
|
23680
|
+
// ../../packages/ycodium-acp-executor/src/connection.ts
|
|
23635
23681
|
var textDecoder = new TextDecoder();
|
|
23636
23682
|
var textEncoder = new TextEncoder();
|
|
23637
23683
|
function asBytes(chunk) {
|
|
@@ -24156,42 +24202,6 @@ var UnboundedEventStream = class {
|
|
|
24156
24202
|
}
|
|
24157
24203
|
};
|
|
24158
24204
|
|
|
24159
|
-
// ../../packages/ycodium-acp-executor/src/errors.ts
|
|
24160
|
-
var AcpExecutorError = class extends Error {
|
|
24161
|
-
code;
|
|
24162
|
-
constructor(code, message) {
|
|
24163
|
-
super(message);
|
|
24164
|
-
this.name = "AcpExecutorError";
|
|
24165
|
-
this.code = code;
|
|
24166
|
-
}
|
|
24167
|
-
};
|
|
24168
|
-
var AcpExecutorDisposedError = class extends AcpExecutorError {
|
|
24169
|
-
constructor(message = "ACP executor has been disposed") {
|
|
24170
|
-
super("disposed", message);
|
|
24171
|
-
this.name = "AcpExecutorDisposedError";
|
|
24172
|
-
}
|
|
24173
|
-
};
|
|
24174
|
-
var AcpExecutorNotStartedError = class extends AcpExecutorError {
|
|
24175
|
-
constructor(message = "ACP session has not been started") {
|
|
24176
|
-
super("not-started", message);
|
|
24177
|
-
this.name = "AcpExecutorNotStartedError";
|
|
24178
|
-
}
|
|
24179
|
-
};
|
|
24180
|
-
var AcpExecutorCancelTimeoutError = class extends AcpExecutorError {
|
|
24181
|
-
constructor(message = "Timed out waiting for session/prompt to finish after cancellation") {
|
|
24182
|
-
super("cancel-timeout", message);
|
|
24183
|
-
this.name = "AcpExecutorCancelTimeoutError";
|
|
24184
|
-
}
|
|
24185
|
-
};
|
|
24186
|
-
var AcpExecutorRequestError = class extends AcpExecutorError {
|
|
24187
|
-
method;
|
|
24188
|
-
constructor(method, message) {
|
|
24189
|
-
super("request-failed", message);
|
|
24190
|
-
this.name = "AcpExecutorRequestError";
|
|
24191
|
-
this.method = method;
|
|
24192
|
-
}
|
|
24193
|
-
};
|
|
24194
|
-
|
|
24195
24205
|
// ../../packages/ycodium-acp-executor/src/events.ts
|
|
24196
24206
|
function canonicalRequestTypeFromAcpKind(kind) {
|
|
24197
24207
|
switch (kind) {
|
|
@@ -26567,7 +26577,7 @@ import { nodeStreamsFromHandle } from "@ycodium-ai/plugin-api/process-stdin";
|
|
|
26567
26577
|
// src/spawnEnv.ts
|
|
26568
26578
|
import * as NodeOS from "node:os";
|
|
26569
26579
|
import * as NodePath from "node:path";
|
|
26570
|
-
import { mergeLaunchEnv
|
|
26580
|
+
import { mergeLaunchEnv } from "@ycodium-ai/plugin-api/executor";
|
|
26571
26581
|
|
|
26572
26582
|
// src/permission.ts
|
|
26573
26583
|
var DSH_NATIVE_MODES = [
|
|
@@ -26624,17 +26634,15 @@ function dshContinuationKey(homePath) {
|
|
|
26624
26634
|
const resolved = resolveHomePath(homePath);
|
|
26625
26635
|
return `dsh:home:${resolved.length > 0 ? resolved : NodePath.join(NodeOS.homedir(), ".dsh")}`;
|
|
26626
26636
|
}
|
|
26627
|
-
function buildSpawnEnv(recipe, resolvedHomePath,
|
|
26637
|
+
function buildSpawnEnv(recipe, resolvedHomePath, nativeModeId) {
|
|
26628
26638
|
const homeEnvVar = recipe.homeEnvVar.trim() || DSH_CARD.homeEnvVar;
|
|
26629
26639
|
const homeInjection = resolvedHomePath.length > 0 && homeEnvVar.length > 0 ? { [homeEnvVar]: resolvedHomePath } : {};
|
|
26630
26640
|
return mergeLaunchEnv({
|
|
26631
|
-
brainSlots: brainSlotEnvKeys(DSH_CARD),
|
|
26632
26641
|
accountHome: homeInjection,
|
|
26633
26642
|
instanceTable: recipe.environment,
|
|
26634
26643
|
// 用户挑的档压过实例表:实例表里那一栏是这台机器的默认,输入区那一下是这一轮的
|
|
26635
26644
|
// 意思。铺在 `handOverrides` 这一层正是为了这个先后(见 `mergeLaunchEnv` 的层序)。
|
|
26636
|
-
handOverrides: dshPermissionEnv(nativeModeId)
|
|
26637
|
-
launch: launchEnv
|
|
26645
|
+
handOverrides: dshPermissionEnv(nativeModeId)
|
|
26638
26646
|
});
|
|
26639
26647
|
}
|
|
26640
26648
|
|
|
@@ -26866,13 +26874,7 @@ var createDshInstance = (config2, host) => {
|
|
|
26866
26874
|
await stopBooked(existing);
|
|
26867
26875
|
threads.delete(input2.threadId);
|
|
26868
26876
|
}
|
|
26869
|
-
const
|
|
26870
|
-
const env = buildSpawnEnv(
|
|
26871
|
-
recipe,
|
|
26872
|
-
resolvedHomePath,
|
|
26873
|
-
input2.launch.processEnv,
|
|
26874
|
-
input2.nativeModeId
|
|
26875
|
-
);
|
|
26877
|
+
const env = buildSpawnEnv(recipe, resolveHomePath(recipe.homePath), input2.nativeModeId);
|
|
26876
26878
|
const handle = await host.process.spawn({
|
|
26877
26879
|
program: recipe.binaryPath,
|
|
26878
26880
|
args: tokenizeLaunchArgs(recipe.launchArgs),
|
|
@@ -26882,7 +26884,7 @@ var createDshInstance = (config2, host) => {
|
|
|
26882
26884
|
});
|
|
26883
26885
|
const { readable, writable } = nodeStreamsFromHandle2(handle);
|
|
26884
26886
|
const resume = input2.discardResumeCursor === true ? void 0 : parseAcpResumeCursor(input2.resumeCursor, RESUME_SCHEMA_VERSION);
|
|
26885
|
-
const requestedModelId =
|
|
26887
|
+
const requestedModelId = modelIdFromSelection(input2.modelSelection);
|
|
26886
26888
|
const executor = createAcpExecutor({
|
|
26887
26889
|
readable,
|
|
26888
26890
|
writable,
|
package/locales/en.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"form": {
|
|
3
|
+
"binaryPath": {
|
|
4
|
+
"title": "Program path",
|
|
5
|
+
"description": "Path to the DeepSeek Harness program this provider runs.",
|
|
6
|
+
"placeholder": "dsh"
|
|
7
|
+
},
|
|
8
|
+
"homePath": {
|
|
9
|
+
"title": "Account directory",
|
|
10
|
+
"description": "Sessions live here, so providers sharing this directory can pick up each other's threads and providers with different directories cannot. Leave empty to use the CLI's default (~/.dsh).",
|
|
11
|
+
"placeholder": "e.g. ~/.dsh-work"
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"form": {
|
|
3
|
+
"binaryPath": {
|
|
4
|
+
"title": "程序路径",
|
|
5
|
+
"description": "此 provider 运行的 DeepSeek Harness 程序的路径。",
|
|
6
|
+
"placeholder": "dsh"
|
|
7
|
+
},
|
|
8
|
+
"homePath": {
|
|
9
|
+
"title": "账户目录",
|
|
10
|
+
"description": "会话保存在这里,因此共用同一目录的 provider 可以接手彼此的会话,目录不同的则不能。留空则使用该命令行工具的默认目录(~/.dsh)。",
|
|
11
|
+
"placeholder": "例如 ~/.dsh-work"
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ycodium-ai/agent-dsh",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2488",
|
|
4
4
|
"description": "DeepSeek Harness executor: dsh CLI over Agent Client Protocol stdio.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ycodium",
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"files": [
|
|
11
11
|
"dist",
|
|
12
12
|
"assets",
|
|
13
|
+
"locales",
|
|
13
14
|
"README.md"
|
|
14
15
|
],
|
|
15
16
|
"type": "module",
|
|
@@ -20,9 +21,9 @@
|
|
|
20
21
|
"@types/node": "24.12.4",
|
|
21
22
|
"esbuild": "0.28.1",
|
|
22
23
|
"vite-plus": "0.2.2",
|
|
23
|
-
"@ycodium-ai/plugin-api": "0.2.
|
|
24
|
-
"ycodium-acp-executor": "0.
|
|
25
|
-
"ycodium-
|
|
24
|
+
"@ycodium-ai/plugin-api": "0.2.2488",
|
|
25
|
+
"ycodium-acp-executor": "0.2.2488",
|
|
26
|
+
"ycodium-executor-testing": "0.0.0"
|
|
26
27
|
},
|
|
27
28
|
"ycodium": {
|
|
28
29
|
"plugin": "./dist/index.js",
|