@openma/deepseek-harness-acp 0.4.9 → 0.4.10-beta.1
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 +9 -3
- package/cordis.patch.yml +9 -16
- package/dist/bridge.js +131 -56
- package/dist/index.js +25 -6
- package/dist/plugin.js +3217 -0
- package/dist/server.js +3169 -0
- package/dist/stdio.js +91 -0
- package/package.json +13 -2
package/README.md
CHANGED
|
@@ -36,13 +36,19 @@ touch your editor config — it reuses the key you saved in the dsh Web UI, or
|
|
|
36
36
|
| Best for | Getting started in one command | Living inside your dsh setup |
|
|
37
37
|
| Install | `npm i -g @openma/deepseek-harness-acp` | `dsh plugin --profile acp add -w @openma/deepseek-harness-acp` |
|
|
38
38
|
| Zed runs | `dsh-acp` | `dsh --profile acp` |
|
|
39
|
-
| Harness | Your installed dsh — or the
|
|
39
|
+
| Harness | Your installed dsh — or the npm-installed peer when none exists | The dsh that owns the profile |
|
|
40
40
|
| Composition | dsh-base + this bundle (profile machinery booted in-process) | dsh-base + this bundle + your profile's own patches |
|
|
41
41
|
|
|
42
42
|
Both shapes share `$DSH_HOME`: the same credential store, settings, presets,
|
|
43
43
|
and session logs as `dsh web` — conversations started in the Web UI can be
|
|
44
44
|
listed and loaded from the editor.
|
|
45
45
|
|
|
46
|
+
Other dsh surfaces can mount the transport-independent
|
|
47
|
+
`@openma/deepseek-harness-acp/plugin` on their Base Host tree and own the
|
|
48
|
+
transport adapter. The TUI profile uses this path: it starts a separate TUI
|
|
49
|
+
Client process and connects ACP over that process's standard stdin/stdout; it
|
|
50
|
+
does not start `dsh-acp` or use an in-process Client stream.
|
|
51
|
+
|
|
46
52
|
### A · Standalone server
|
|
47
53
|
|
|
48
54
|
```bash
|
|
@@ -61,7 +67,7 @@ dsh-acp login # interactive; or save the key in the dsh Web UI
|
|
|
61
67
|
|
|
62
68
|
Self-contained: it finds your DeepSeek Harness via `--dsh-path` / `DSH_PATH`,
|
|
63
69
|
its own tree, `./node_modules`, `dsh` on PATH, or `npm root -g` — and ships a
|
|
64
|
-
|
|
70
|
+
npm-installed harness peer as the **last** candidate, so it works out of the box
|
|
65
71
|
and always prefers the dsh you installed. When a real
|
|
66
72
|
`$DSH_HOME/profiles/acp` exists, that profile owns the composition.
|
|
67
73
|
|
|
@@ -169,7 +175,7 @@ ACP client (Zed, …)
|
|
|
169
175
|
dsh-acp
|
|
170
176
|
├─ src/profile-boot.ts boots the harness's own profile machinery
|
|
171
177
|
│ (dsh-base + this bundle + $DSH_HOME layers)
|
|
172
|
-
├─ src/harness.ts host discovery (DSH_PATH → cwd → PATH → npm -g →
|
|
178
|
+
├─ src/harness.ts host discovery (DSH_PATH → cwd → PATH → npm -g → npm peer)
|
|
173
179
|
└─ src/bridge/ the ACP bridge (a cordis plugin)
|
|
174
180
|
├─ index.ts sessions, prompts, cancel, modes, options,
|
|
175
181
|
│ commands, credentials, MCP mounts
|
package/cordis.patch.yml
CHANGED
|
@@ -97,22 +97,15 @@
|
|
|
97
97
|
disabled: true
|
|
98
98
|
|
|
99
99
|
- insert:
|
|
100
|
-
#
|
|
101
|
-
#
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
- id: agent-presets
|
|
105
|
-
name: '@deepseek-ai/dsh-agent-presets'
|
|
106
|
-
config:
|
|
107
|
-
default: standard
|
|
108
|
-
|
|
109
|
-
# Same host row the web-app bundle mounts. Without it, preset "cordis"
|
|
110
|
-
# never activates: tool-cordis waits for dynamicCordisRunner, cordisInspect.
|
|
111
|
-
- id: cordis-host-runner
|
|
112
|
-
name: '@deepseek-ai/dsh-cordis-host-runner'
|
|
113
|
-
|
|
114
|
-
- id: acp-bridge
|
|
115
|
-
name: '@openma/deepseek-harness-acp/bridge'
|
|
100
|
+
# The same complete Cordis plugin embedded by other surfaces. It owns the
|
|
101
|
+
# preset plane and transport-independent ACP server, but no transport.
|
|
102
|
+
- id: acp-plugin
|
|
103
|
+
name: '@openma/deepseek-harness-acp/plugin'
|
|
116
104
|
config:
|
|
117
105
|
model: !!js process.env.DSH_MODEL
|
|
118
106
|
permissionMode: !!js process.env.DSH_PERMISSION_MODE ?? 'workspace-write'
|
|
107
|
+
|
|
108
|
+
# The ordinary ACP profile owns stdio. Embedded surfaces replace only this
|
|
109
|
+
# adapter and reuse the exact same plugin contract above.
|
|
110
|
+
- id: acp-bridge
|
|
111
|
+
name: '@openma/deepseek-harness-acp/stdio'
|
package/dist/bridge.js
CHANGED
|
@@ -44,7 +44,21 @@ var init_self_harness = __esm({
|
|
|
44
44
|
}
|
|
45
45
|
});
|
|
46
46
|
|
|
47
|
+
// src/bundle.ts
|
|
48
|
+
import { ndJsonStream as ndJsonStream2 } from "@agentclientprotocol/sdk";
|
|
49
|
+
import { Readable as Readable2, Writable as Writable2 } from "node:stream";
|
|
50
|
+
|
|
47
51
|
// src/bridge/index.ts
|
|
52
|
+
var bridge_exports = {};
|
|
53
|
+
__export(bridge_exports, {
|
|
54
|
+
answerFromElicitation: () => answerFromElicitation,
|
|
55
|
+
apply: () => apply,
|
|
56
|
+
askUserQuestionsOverAcp: () => askUserQuestionsOverAcp,
|
|
57
|
+
inject: () => inject,
|
|
58
|
+
installAcpUserQuestionProvider: () => installAcpUserQuestionProvider,
|
|
59
|
+
name: () => name,
|
|
60
|
+
questionsToElicitation: () => questionsToElicitation
|
|
61
|
+
});
|
|
48
62
|
import { randomUUID } from "node:crypto";
|
|
49
63
|
import { isAbsolute } from "node:path";
|
|
50
64
|
import { Readable, Writable } from "node:stream";
|
|
@@ -1113,6 +1127,36 @@ ${contextBlock(resource.uri, resource.text)}
|
|
|
1113
1127
|
};
|
|
1114
1128
|
}
|
|
1115
1129
|
|
|
1130
|
+
// src/bridge/cordis-protocol.ts
|
|
1131
|
+
var CORDIS_PROTOCOL = 0;
|
|
1132
|
+
var CORDIS_CAPABILITY = Object.freeze({ protocol: CORDIS_PROTOCOL });
|
|
1133
|
+
var CORDIS_METHODS = Object.freeze({
|
|
1134
|
+
inspectSync: "_dsh/cordis/inspect/sync",
|
|
1135
|
+
inspectResolve: "_dsh/cordis/inspect/resolve",
|
|
1136
|
+
inspectQuery: "_dsh/cordis/inspect/query",
|
|
1137
|
+
inspectQueryResolved: "_dsh/cordis/inspect/query-resolved",
|
|
1138
|
+
runHost: "_dsh/cordis/run/host",
|
|
1139
|
+
getClientCode: "_dsh/cordis/run/client-code",
|
|
1140
|
+
resolveRequestRun: "_dsh/cordis/run/resolve",
|
|
1141
|
+
requestRun: "_dsh/cordis/run/request",
|
|
1142
|
+
requestRunResolved: "_dsh/cordis/run/request-resolved",
|
|
1143
|
+
userRun: "_dsh/cordis/run/user",
|
|
1144
|
+
settleUserRun: "_dsh/cordis/run/settle",
|
|
1145
|
+
pluginInvoke: "_dsh/cordis/plugin/invoke",
|
|
1146
|
+
pluginsList: "_dsh/cordis/plugins/list",
|
|
1147
|
+
pluginStart: "_dsh/cordis/plugins/start",
|
|
1148
|
+
pluginStop: "_dsh/cordis/plugins/stop",
|
|
1149
|
+
pluginRetract: "_dsh/cordis/plugins/retract"
|
|
1150
|
+
});
|
|
1151
|
+
function advertisesCordis(meta) {
|
|
1152
|
+
if (meta === null || typeof meta !== "object" || Array.isArray(meta)) return false;
|
|
1153
|
+
const dsh = meta["dsh"];
|
|
1154
|
+
if (dsh === null || typeof dsh !== "object" || Array.isArray(dsh)) return false;
|
|
1155
|
+
const cordis = dsh["cordis"];
|
|
1156
|
+
if (cordis === null || typeof cordis !== "object" || Array.isArray(cordis)) return false;
|
|
1157
|
+
return cordis["protocol"] === CORDIS_PROTOCOL;
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1116
1160
|
// src/bridge/rpc.ts
|
|
1117
1161
|
var AcpRpc = class {
|
|
1118
1162
|
handlers = /* @__PURE__ */ new Map();
|
|
@@ -1126,11 +1170,14 @@ var AcpRpc = class {
|
|
|
1126
1170
|
}
|
|
1127
1171
|
/**
|
|
1128
1172
|
* Register a bridge-owned request method intercepted before the ACP SDK.
|
|
1129
|
-
* @param method - JSON-RPC method
|
|
1173
|
+
* @param method - JSON-RPC extension method (e.g. `_dsh/cordis/inspect/sync`).
|
|
1130
1174
|
* @param handler - implementation.
|
|
1131
1175
|
* @returns disposer.
|
|
1132
1176
|
*/
|
|
1133
1177
|
registerMethod(method, handler) {
|
|
1178
|
+
if (!method.startsWith("_")) {
|
|
1179
|
+
throw new Error(`acpRpc: extension method ${JSON.stringify(method)} must start with "_"`);
|
|
1180
|
+
}
|
|
1134
1181
|
if (this.handlers.has(method)) {
|
|
1135
1182
|
throw new Error(`acpRpc: method ${JSON.stringify(method)} is already registered`);
|
|
1136
1183
|
}
|
|
@@ -1165,11 +1212,14 @@ var AcpRpc = class {
|
|
|
1165
1212
|
}
|
|
1166
1213
|
}
|
|
1167
1214
|
/**
|
|
1168
|
-
* Send a JSON-RPC notification on the ACP stream
|
|
1215
|
+
* Send a JSON-RPC extension notification on the ACP stream.
|
|
1169
1216
|
* @param method - notification method.
|
|
1170
1217
|
* @param params - payload.
|
|
1171
1218
|
*/
|
|
1172
1219
|
notify(method, params) {
|
|
1220
|
+
if (!method.startsWith("_")) {
|
|
1221
|
+
throw new Error(`acpRpc: extension notification ${JSON.stringify(method)} must start with "_"`);
|
|
1222
|
+
}
|
|
1173
1223
|
const write = this.writeJson;
|
|
1174
1224
|
if (write === void 0) return;
|
|
1175
1225
|
write(params === void 0 ? { jsonrpc: "2.0", method } : { jsonrpc: "2.0", method, params });
|
|
@@ -1214,20 +1264,19 @@ function muxAcpStream(stream, rpc) {
|
|
|
1214
1264
|
function installTuiClientPlane(ctx, rpc, opts) {
|
|
1215
1265
|
const { findAgent, advertisement } = opts;
|
|
1216
1266
|
ctx.effect(
|
|
1217
|
-
() => rpc.registerMethod(
|
|
1267
|
+
() => rpc.registerMethod(CORDIS_METHODS.inspectSync, (params) => {
|
|
1218
1268
|
const inspect = optionalInspect(ctx);
|
|
1219
1269
|
if (inspect === void 0) {
|
|
1220
1270
|
throw new Error("this agent has no Cordis inspect registry");
|
|
1221
1271
|
}
|
|
1222
1272
|
const providers = readProviders(params);
|
|
1223
1273
|
inspect.syncClientManifest(providers);
|
|
1224
|
-
advertisement.advertised = true;
|
|
1225
1274
|
return { ok: true };
|
|
1226
1275
|
}),
|
|
1227
|
-
"acp-bridge:
|
|
1276
|
+
"acp-bridge: cordis/inspect-sync"
|
|
1228
1277
|
);
|
|
1229
1278
|
ctx.effect(
|
|
1230
|
-
() => rpc.registerMethod(
|
|
1279
|
+
() => rpc.registerMethod(CORDIS_METHODS.inspectResolve, (params) => {
|
|
1231
1280
|
const inspect = optionalInspect(ctx);
|
|
1232
1281
|
if (inspect === void 0) {
|
|
1233
1282
|
throw new Error("this agent has no Cordis inspect registry");
|
|
@@ -1237,10 +1286,10 @@ function installTuiClientPlane(ctx, rpc, opts) {
|
|
|
1237
1286
|
const requestId = readString(body, "requestId");
|
|
1238
1287
|
return inspect.resolveClientQuery(agent, requestId, body["resolution"]);
|
|
1239
1288
|
}),
|
|
1240
|
-
"acp-bridge:
|
|
1289
|
+
"acp-bridge: cordis/inspect-resolve"
|
|
1241
1290
|
);
|
|
1242
1291
|
ctx.effect(
|
|
1243
|
-
() => rpc.registerMethod(
|
|
1292
|
+
() => rpc.registerMethod(CORDIS_METHODS.runHost, async (params) => {
|
|
1244
1293
|
const runner = optionalRunner(ctx);
|
|
1245
1294
|
if (runner === void 0) {
|
|
1246
1295
|
throw new Error("this agent has no dynamic Cordis runner");
|
|
@@ -1257,10 +1306,10 @@ function installTuiClientPlane(ctx, rpc, opts) {
|
|
|
1257
1306
|
body["approveFutureVersions"] === true
|
|
1258
1307
|
);
|
|
1259
1308
|
}),
|
|
1260
|
-
"acp-bridge:
|
|
1309
|
+
"acp-bridge: cordis/run-host-half"
|
|
1261
1310
|
);
|
|
1262
1311
|
ctx.effect(
|
|
1263
|
-
() => rpc.registerMethod(
|
|
1312
|
+
() => rpc.registerMethod(CORDIS_METHODS.getClientCode, (params) => {
|
|
1264
1313
|
const runner = optionalRunner(ctx);
|
|
1265
1314
|
if (runner === void 0) {
|
|
1266
1315
|
throw new Error("this agent has no dynamic Cordis runner");
|
|
@@ -1273,10 +1322,10 @@ function installTuiClientPlane(ctx, rpc, opts) {
|
|
|
1273
1322
|
readString(body, "pluginRunId")
|
|
1274
1323
|
);
|
|
1275
1324
|
}),
|
|
1276
|
-
"acp-bridge:
|
|
1325
|
+
"acp-bridge: cordis/get-client-code"
|
|
1277
1326
|
);
|
|
1278
1327
|
ctx.effect(
|
|
1279
|
-
() => rpc.registerMethod(
|
|
1328
|
+
() => rpc.registerMethod(CORDIS_METHODS.resolveRequestRun, async (params) => {
|
|
1280
1329
|
const runner = optionalRunner(ctx);
|
|
1281
1330
|
if (runner === void 0) {
|
|
1282
1331
|
throw new Error("this agent has no dynamic Cordis runner");
|
|
@@ -1287,10 +1336,10 @@ function installTuiClientPlane(ctx, rpc, opts) {
|
|
|
1287
1336
|
body["resolution"]
|
|
1288
1337
|
);
|
|
1289
1338
|
}),
|
|
1290
|
-
"acp-bridge:
|
|
1339
|
+
"acp-bridge: cordis/resolve-request-run"
|
|
1291
1340
|
);
|
|
1292
1341
|
ctx.effect(
|
|
1293
|
-
() => rpc.registerMethod(
|
|
1342
|
+
() => rpc.registerMethod(CORDIS_METHODS.pluginInvoke, async (params) => {
|
|
1294
1343
|
const runner = optionalRunner(ctx);
|
|
1295
1344
|
if (runner === void 0) {
|
|
1296
1345
|
throw new Error("this agent has no dynamic Cordis runner");
|
|
@@ -1304,28 +1353,28 @@ function installTuiClientPlane(ctx, rpc, opts) {
|
|
|
1304
1353
|
body["args"] ?? null
|
|
1305
1354
|
);
|
|
1306
1355
|
}),
|
|
1307
|
-
"acp-bridge:
|
|
1356
|
+
"acp-bridge: cordis/invoke"
|
|
1308
1357
|
);
|
|
1309
1358
|
ctx.effect(
|
|
1310
|
-
() => rpc.registerMethod(
|
|
1359
|
+
() => rpc.registerMethod(CORDIS_METHODS.pluginsList, (params) => {
|
|
1311
1360
|
const runner = requireRunnerMethod(ctx, "listPlugins");
|
|
1312
1361
|
const body = asObject(params);
|
|
1313
1362
|
const agent = requireAgent(findAgent, readString(body, "agentId"));
|
|
1314
1363
|
return runner.listPlugins(agent);
|
|
1315
1364
|
}),
|
|
1316
|
-
"acp-bridge:
|
|
1365
|
+
"acp-bridge: cordis/list-plugins"
|
|
1317
1366
|
);
|
|
1318
1367
|
ctx.effect(
|
|
1319
|
-
() => rpc.registerMethod(
|
|
1368
|
+
() => rpc.registerMethod(CORDIS_METHODS.pluginStop, async (params) => {
|
|
1320
1369
|
const runner = requireRunnerMethod(ctx, "stopFromPanel");
|
|
1321
1370
|
const body = asObject(params);
|
|
1322
1371
|
const agent = requireAgent(findAgent, readString(body, "agentId"));
|
|
1323
1372
|
return await runner.stopFromPanel(agent, readString(body, "pluginId"));
|
|
1324
1373
|
}),
|
|
1325
|
-
"acp-bridge:
|
|
1374
|
+
"acp-bridge: cordis/stop-plugin"
|
|
1326
1375
|
);
|
|
1327
1376
|
ctx.effect(
|
|
1328
|
-
() => rpc.registerMethod(
|
|
1377
|
+
() => rpc.registerMethod(CORDIS_METHODS.pluginStart, async (params) => {
|
|
1329
1378
|
const runner = requireRunnerMethod(ctx, "listPlugins");
|
|
1330
1379
|
const body = asObject(params);
|
|
1331
1380
|
const agentId = readString(body, "agentId");
|
|
@@ -1353,7 +1402,7 @@ function installTuiClientPlane(ctx, rpc, opts) {
|
|
|
1353
1402
|
const pluginRunId = readString(started, "pluginRunId");
|
|
1354
1403
|
const startedHere = started["startedHere"] !== false;
|
|
1355
1404
|
if (pkg.hasClientHalf) {
|
|
1356
|
-
rpc.notify(
|
|
1405
|
+
rpc.notify(CORDIS_METHODS.userRun, {
|
|
1357
1406
|
agentId,
|
|
1358
1407
|
pluginId,
|
|
1359
1408
|
packageId,
|
|
@@ -1365,10 +1414,10 @@ function installTuiClientPlane(ctx, rpc, opts) {
|
|
|
1365
1414
|
}
|
|
1366
1415
|
return { ok: true, status: "starting", pluginId, packageId, pluginRunId };
|
|
1367
1416
|
}),
|
|
1368
|
-
"acp-bridge:
|
|
1417
|
+
"acp-bridge: cordis/start-plugin"
|
|
1369
1418
|
);
|
|
1370
1419
|
ctx.effect(
|
|
1371
|
-
() => rpc.registerMethod(
|
|
1420
|
+
() => rpc.registerMethod(CORDIS_METHODS.settleUserRun, async (params) => {
|
|
1372
1421
|
const runner = requireRunnerMethod(ctx, "settleUserRun");
|
|
1373
1422
|
const body = asObject(params);
|
|
1374
1423
|
const agent = requireAgent(findAgent, readString(body, "agentId"));
|
|
@@ -1378,27 +1427,27 @@ function installTuiClientPlane(ctx, rpc, opts) {
|
|
|
1378
1427
|
body["resolution"]
|
|
1379
1428
|
);
|
|
1380
1429
|
}),
|
|
1381
|
-
"acp-bridge:
|
|
1430
|
+
"acp-bridge: cordis/settle-user-run"
|
|
1382
1431
|
);
|
|
1383
1432
|
ctx.on("cordis/inspect-query", (request) => {
|
|
1384
1433
|
if (!advertisement.advertised) return;
|
|
1385
|
-
rpc.notify(
|
|
1434
|
+
rpc.notify(CORDIS_METHODS.inspectQuery, request);
|
|
1386
1435
|
});
|
|
1387
1436
|
ctx.on("cordis/inspect-query-resolved", (resolved) => {
|
|
1388
1437
|
if (!advertisement.advertised) return;
|
|
1389
|
-
rpc.notify(
|
|
1438
|
+
rpc.notify(CORDIS_METHODS.inspectQueryResolved, resolved);
|
|
1390
1439
|
});
|
|
1391
1440
|
ctx.on("cordis/request-run", (request) => {
|
|
1392
1441
|
if (!advertisement.advertised) return;
|
|
1393
|
-
rpc.notify(
|
|
1442
|
+
rpc.notify(CORDIS_METHODS.requestRun, request);
|
|
1394
1443
|
});
|
|
1395
1444
|
ctx.on("cordis/request-run-resolved", (resolved) => {
|
|
1396
1445
|
if (!advertisement.advertised) return;
|
|
1397
|
-
rpc.notify(
|
|
1446
|
+
rpc.notify(CORDIS_METHODS.requestRunResolved, resolved);
|
|
1398
1447
|
});
|
|
1399
1448
|
ctx.on("cordis/dynamic-retract", (retracted) => {
|
|
1400
1449
|
if (!advertisement.advertised) return;
|
|
1401
|
-
rpc.notify(
|
|
1450
|
+
rpc.notify(CORDIS_METHODS.pluginRetract, retracted);
|
|
1402
1451
|
});
|
|
1403
1452
|
}
|
|
1404
1453
|
function optionalInspect(ctx) {
|
|
@@ -1465,6 +1514,7 @@ function readProviders(params) {
|
|
|
1465
1514
|
}
|
|
1466
1515
|
|
|
1467
1516
|
// src/bridge/user-questions.ts
|
|
1517
|
+
import { Service } from "@deepseek-ai/cordis";
|
|
1468
1518
|
import {
|
|
1469
1519
|
UserQuestionError
|
|
1470
1520
|
} from "@deepseek-ai/dsh-user-questions";
|
|
@@ -1591,25 +1641,48 @@ async function askUserQuestionsOverAcp(request, sessionId, create) {
|
|
|
1591
1641
|
}
|
|
1592
1642
|
return answer;
|
|
1593
1643
|
}
|
|
1644
|
+
var ROUTERS_KEY = /* @__PURE__ */ Symbol.for("@openma/deepseek-harness-acp/user-question-routers");
|
|
1645
|
+
var routers = globalThis[ROUTERS_KEY] ??= /* @__PURE__ */ new WeakMap();
|
|
1594
1646
|
function installAcpUserQuestionProvider(service, options) {
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1647
|
+
const tracked = service[Service.tracker];
|
|
1648
|
+
const owner = typeof tracked === "object" && tracked !== null ? tracked : service;
|
|
1649
|
+
let router = routers.get(owner);
|
|
1650
|
+
if (router === void 0) {
|
|
1651
|
+
const routes = [];
|
|
1652
|
+
const disposeProvider = service.registerProvider({
|
|
1653
|
+
async ask(request) {
|
|
1654
|
+
for (let index = routes.length - 1; index >= 0; index -= 1) {
|
|
1655
|
+
const route = routes[index];
|
|
1656
|
+
const sessionId = route?.sessionIdForRequest(request);
|
|
1657
|
+
if (route === void 0 || sessionId === void 0) continue;
|
|
1658
|
+
if (!route.formSupported()) {
|
|
1659
|
+
throw new UserQuestionError(
|
|
1660
|
+
"the ACP client does not support form elicitation",
|
|
1661
|
+
"CLIENT_UNSUPPORTED"
|
|
1662
|
+
);
|
|
1663
|
+
}
|
|
1664
|
+
return askUserQuestionsOverAcp(request, sessionId, route.create);
|
|
1665
|
+
}
|
|
1605
1666
|
throw new UserQuestionError(
|
|
1606
1667
|
"ACP user interaction requires a live root session",
|
|
1607
1668
|
"ASK_MISSING_AGENT"
|
|
1608
1669
|
);
|
|
1609
1670
|
}
|
|
1610
|
-
|
|
1611
|
-
}
|
|
1612
|
-
|
|
1671
|
+
});
|
|
1672
|
+
router = { routes, disposeProvider };
|
|
1673
|
+
routers.set(owner, router);
|
|
1674
|
+
}
|
|
1675
|
+
router.routes.push(options);
|
|
1676
|
+
let active = true;
|
|
1677
|
+
return () => {
|
|
1678
|
+
if (!active) return;
|
|
1679
|
+
active = false;
|
|
1680
|
+
const index = router.routes.indexOf(options);
|
|
1681
|
+
if (index >= 0) router.routes.splice(index, 1);
|
|
1682
|
+
if (router.routes.length !== 0) return;
|
|
1683
|
+
routers.delete(owner);
|
|
1684
|
+
router.disposeProvider();
|
|
1685
|
+
};
|
|
1613
1686
|
}
|
|
1614
1687
|
|
|
1615
1688
|
// src/bridge/presets.ts
|
|
@@ -2581,14 +2654,13 @@ async function apply(ctx, config = {}) {
|
|
|
2581
2654
|
clientTerminalOutput = capsMeta !== null && typeof capsMeta === "object" ? capsMeta["terminal_output"] === true : false;
|
|
2582
2655
|
clientSubagentTranscript = capsMeta !== null && typeof capsMeta === "object" ? capsMeta["subagent-transcript"] === true : false;
|
|
2583
2656
|
clientElicitationForm = params.clientCapabilities?.elicitation?.form !== void 0 && params.clientCapabilities.elicitation.form !== null;
|
|
2584
|
-
|
|
2585
|
-
tuiClient.advertised = true;
|
|
2586
|
-
}
|
|
2657
|
+
tuiClient.advertised = advertisesCordis(capsMeta);
|
|
2587
2658
|
const providers = await listProviderRoutes();
|
|
2588
2659
|
return {
|
|
2589
2660
|
protocolVersion: typeof requested === "number" && requested >= 1 && requested < PROTOCOL_VERSION ? requested : PROTOCOL_VERSION,
|
|
2590
2661
|
agentInfo: { name: "dsh-acp", title: "DeepSeek Harness", version: VERSION },
|
|
2591
2662
|
agentCapabilities: {
|
|
2663
|
+
_meta: { dsh: { cordis: { ...CORDIS_CAPABILITY } } },
|
|
2592
2664
|
loadSession: true,
|
|
2593
2665
|
promptCapabilities: {
|
|
2594
2666
|
image: attachmentIngestOf(ctx.get("attachments")) !== void 0,
|
|
@@ -3082,20 +3154,23 @@ async function apply(ctx, config = {}) {
|
|
|
3082
3154
|
|
|
3083
3155
|
// src/bundle.ts
|
|
3084
3156
|
init_self_harness();
|
|
3085
|
-
var name2 =
|
|
3157
|
+
var name2 = "acp-bridge";
|
|
3086
3158
|
var inject2 = inject;
|
|
3087
|
-
function
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3159
|
+
function nodeAcpStream(input, output) {
|
|
3160
|
+
return ndJsonStream2(
|
|
3161
|
+
Writable2.toWeb(output),
|
|
3162
|
+
Readable2.toWeb(input)
|
|
3163
|
+
);
|
|
3164
|
+
}
|
|
3165
|
+
function apply2(ctx, config = {}) {
|
|
3166
|
+
const stream = nodeAcpStream(process.stdin, process.stdout);
|
|
3167
|
+
const server = ctx.get("acpServer");
|
|
3168
|
+
if (server !== void 0) return server.connect(stream);
|
|
3169
|
+
return ctx.plugin(bridge_exports, { ...config, stream, harness: selfHarness() });
|
|
3096
3170
|
}
|
|
3097
3171
|
export {
|
|
3098
3172
|
apply2 as apply,
|
|
3099
3173
|
inject2 as inject,
|
|
3100
|
-
name2 as name
|
|
3174
|
+
name2 as name,
|
|
3175
|
+
nodeAcpStream
|
|
3101
3176
|
};
|
package/dist/index.js
CHANGED
|
@@ -135,9 +135,9 @@ function resolveHost(explicit) {
|
|
|
135
135
|
const globalNpm = hostFromGlobalNpm();
|
|
136
136
|
if (globalNpm !== void 0) return globalNpm;
|
|
137
137
|
probed.push("npm root -g");
|
|
138
|
-
const own = hostAt(dirname(fileURLToPath(import.meta.url)), "dsh-acp package tree (
|
|
138
|
+
const own = hostAt(dirname(fileURLToPath(import.meta.url)), "dsh-acp package tree (npm peer)");
|
|
139
139
|
if (own !== void 0) return own;
|
|
140
|
-
probed.push("dsh-acp package tree (
|
|
140
|
+
probed.push("dsh-acp package tree (npm peer)");
|
|
141
141
|
throw new HarnessNotFoundError(probed);
|
|
142
142
|
}
|
|
143
143
|
|
|
@@ -151,13 +151,19 @@ function ownRoot() {
|
|
|
151
151
|
return dirname2(createRequire(import.meta.url).resolve("../package.json"));
|
|
152
152
|
}
|
|
153
153
|
var OWN_BRIDGE_SPECIFIER = "@openma/deepseek-harness-acp/bridge";
|
|
154
|
-
|
|
155
|
-
|
|
154
|
+
var OWN_SERVER_SPECIFIER = "@openma/deepseek-harness-acp/server";
|
|
155
|
+
var OWN_PLUGIN_SPECIFIER = "@openma/deepseek-harness-acp/plugin";
|
|
156
|
+
var OWN_STDIO_SPECIFIER = "@openma/deepseek-harness-acp/stdio";
|
|
157
|
+
function rewriteOwnRows(row, entries) {
|
|
158
|
+
if (row["name"] === OWN_BRIDGE_SPECIFIER) row["name"] = entries.bridge;
|
|
159
|
+
if (row["name"] === OWN_SERVER_SPECIFIER) row["name"] = entries.server;
|
|
160
|
+
if (row["name"] === OWN_PLUGIN_SPECIFIER) row["name"] = entries.plugin;
|
|
161
|
+
if (row["name"] === OWN_STDIO_SPECIFIER) row["name"] = entries.stdio;
|
|
156
162
|
const insert = row["insert"];
|
|
157
163
|
if (Array.isArray(insert)) {
|
|
158
164
|
for (const nested of insert) {
|
|
159
165
|
if (nested !== null && typeof nested === "object") {
|
|
160
|
-
|
|
166
|
+
rewriteOwnRows(nested, entries);
|
|
161
167
|
}
|
|
162
168
|
}
|
|
163
169
|
}
|
|
@@ -231,6 +237,12 @@ async function bootAcpProfile(host, overrides) {
|
|
|
231
237
|
let bareModuleBaseUrl = pathToFileURL2(dshDir + sep2).href;
|
|
232
238
|
const distBridge = join2(ownRoot(), "dist", "bridge.js");
|
|
233
239
|
const bridgeEntry = import.meta.url.endsWith(".ts") || !existsSync2(distBridge) ? join2(ownRoot(), "src", "bundle.ts") : distBridge;
|
|
240
|
+
const distServer = join2(ownRoot(), "dist", "server.js");
|
|
241
|
+
const serverEntry = import.meta.url.endsWith(".ts") || !existsSync2(distServer) ? join2(ownRoot(), "src", "server.ts") : distServer;
|
|
242
|
+
const distPlugin = join2(ownRoot(), "dist", "plugin.js");
|
|
243
|
+
const pluginEntry = import.meta.url.endsWith(".ts") || !existsSync2(distPlugin) ? join2(ownRoot(), "src", "plugin.ts") : distPlugin;
|
|
244
|
+
const distStdio = join2(ownRoot(), "dist", "stdio.js");
|
|
245
|
+
const stdioEntry = import.meta.url.endsWith(".ts") || !existsSync2(distStdio) ? join2(ownRoot(), "src", "stdio.ts") : distStdio;
|
|
234
246
|
const realProfileDir = join2(home, "profiles", "acp");
|
|
235
247
|
if (existsSync2(join2(realProfileDir, "package.json"))) {
|
|
236
248
|
appBoot.healProfilesModuleFallback(dshPkgPath);
|
|
@@ -255,7 +267,14 @@ async function bootAcpProfile(host, overrides) {
|
|
|
255
267
|
bundlePatches.push(...loadBundleLayer(appBoot, bundle));
|
|
256
268
|
logDebug(`profile: added bundle ${bundle}`);
|
|
257
269
|
}
|
|
258
|
-
for (const row of bundlePatches)
|
|
270
|
+
for (const row of bundlePatches) {
|
|
271
|
+
rewriteOwnRows(row, {
|
|
272
|
+
bridge: bridgeEntry,
|
|
273
|
+
server: serverEntry,
|
|
274
|
+
plugin: pluginEntry,
|
|
275
|
+
stdio: stdioEntry
|
|
276
|
+
});
|
|
277
|
+
}
|
|
259
278
|
const homePatchPath = join2(home, "cordis.patch.yml");
|
|
260
279
|
const homePatches = appBoot.loadOptionalPatches(BIN, homePatchPath) ?? [];
|
|
261
280
|
const rows = /* @__PURE__ */ new Map();
|