@openma/deepseek-harness-acp 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +164 -13
- package/package.json +5 -3
- package/profile-root.cordis.yml +3 -0
package/dist/index.js
CHANGED
|
@@ -47,6 +47,9 @@ var init_self_harness = __esm({
|
|
|
47
47
|
}
|
|
48
48
|
});
|
|
49
49
|
|
|
50
|
+
// src/index.ts
|
|
51
|
+
import { spawnSync } from "node:child_process";
|
|
52
|
+
|
|
50
53
|
// src/app.ts
|
|
51
54
|
var app_exports = {};
|
|
52
55
|
__export(app_exports, {
|
|
@@ -89,6 +92,10 @@ function logDebug(message) {
|
|
|
89
92
|
if (process.env["DSH_ACP_DEBUG"]) process.stderr.write(`${PREFIX} debug: ${message}
|
|
90
93
|
`);
|
|
91
94
|
}
|
|
95
|
+
function logInfo(message) {
|
|
96
|
+
process.stderr.write(`${PREFIX} ${message}
|
|
97
|
+
`);
|
|
98
|
+
}
|
|
92
99
|
|
|
93
100
|
// src/bridge/translate.ts
|
|
94
101
|
var MAX_TITLE_LENGTH = 80;
|
|
@@ -1752,9 +1759,6 @@ function resolveHost(explicit) {
|
|
|
1752
1759
|
probed.push(`--dsh-path/DSH_PATH: ${explicit}`);
|
|
1753
1760
|
throw new HarnessNotFoundError(probed);
|
|
1754
1761
|
}
|
|
1755
|
-
const own = hostAt(dirname(fileURLToPath(import.meta.url)), "dsh-acp package tree");
|
|
1756
|
-
if (own !== void 0) return own;
|
|
1757
|
-
probed.push("dsh-acp package tree");
|
|
1758
1762
|
const local = hostAt(process.cwd(), `invoking directory (${process.cwd()})`);
|
|
1759
1763
|
if (local !== void 0) return local;
|
|
1760
1764
|
probed.push(`invoking directory: ${process.cwd()}`);
|
|
@@ -1764,6 +1768,9 @@ function resolveHost(explicit) {
|
|
|
1764
1768
|
const globalNpm = hostFromGlobalNpm();
|
|
1765
1769
|
if (globalNpm !== void 0) return globalNpm;
|
|
1766
1770
|
probed.push("npm root -g");
|
|
1771
|
+
const own = hostAt(dirname(fileURLToPath(import.meta.url)), "dsh-acp package tree (vendored)");
|
|
1772
|
+
if (own !== void 0) return own;
|
|
1773
|
+
probed.push("dsh-acp package tree (vendored)");
|
|
1767
1774
|
throw new HarnessNotFoundError(probed);
|
|
1768
1775
|
}
|
|
1769
1776
|
function entryFile(packageDir, subpath) {
|
|
@@ -2000,8 +2007,8 @@ async function apply2(ctx, config) {
|
|
|
2000
2007
|
await compaction;
|
|
2001
2008
|
yield compaction.dispose;
|
|
2002
2009
|
const bridge = anyCtx.plugin(bridge_exports, {
|
|
2003
|
-
provider: settings.provider,
|
|
2004
|
-
model: settings.model,
|
|
2010
|
+
provider: settings.provider ?? "deepseek-official",
|
|
2011
|
+
model: settings.model ?? "deepseek-v4-flash",
|
|
2005
2012
|
models: settings.models,
|
|
2006
2013
|
...settings.maxTokens !== void 0 ? { maxTokens: settings.maxTokens } : {},
|
|
2007
2014
|
permissionMode: settings.permissionMode,
|
|
@@ -2012,9 +2019,130 @@ async function apply2(ctx, config) {
|
|
|
2012
2019
|
}, "dsh-acp-app.composition");
|
|
2013
2020
|
}
|
|
2014
2021
|
|
|
2022
|
+
// src/profile-boot.ts
|
|
2023
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
|
|
2024
|
+
import { createRequire as createRequire2 } from "node:module";
|
|
2025
|
+
import { dirname as dirname2, join as join2, sep as sep2 } from "node:path";
|
|
2026
|
+
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
2027
|
+
var BIN = "dsh-acp";
|
|
2028
|
+
function ownRoot() {
|
|
2029
|
+
return dirname2(createRequire2(import.meta.url).resolve("../package.json"));
|
|
2030
|
+
}
|
|
2031
|
+
var OWN_BRIDGE_SPECIFIER = "@openma/deepseek-harness-acp/bridge";
|
|
2032
|
+
function rewriteBridgeRows(row, absoluteEntry) {
|
|
2033
|
+
if (row["name"] === OWN_BRIDGE_SPECIFIER) row["name"] = absoluteEntry;
|
|
2034
|
+
const insert = row["insert"];
|
|
2035
|
+
if (Array.isArray(insert)) {
|
|
2036
|
+
for (const nested of insert) {
|
|
2037
|
+
if (nested !== null && typeof nested === "object") {
|
|
2038
|
+
rewriteBridgeRows(nested, absoluteEntry);
|
|
2039
|
+
}
|
|
2040
|
+
}
|
|
2041
|
+
}
|
|
2042
|
+
}
|
|
2043
|
+
function bundlePatchPath(packageJsonPath) {
|
|
2044
|
+
const pkg = JSON.parse(readFileSync2(packageJsonPath, "utf8"));
|
|
2045
|
+
const declared = pkg.dsh?.bundle?.patch;
|
|
2046
|
+
if (declared === void 0) {
|
|
2047
|
+
throw new Error(`${BIN}: bundle ${pkg.name ?? packageJsonPath} declares no dsh.bundle in its package.json`);
|
|
2048
|
+
}
|
|
2049
|
+
return join2(dirname2(packageJsonPath), declared);
|
|
2050
|
+
}
|
|
2051
|
+
async function bootAcpProfile(host, overrides) {
|
|
2052
|
+
const req = createRequire2(join2(host.base, "noop.js"));
|
|
2053
|
+
const dshPkgPath = req.resolve("@deepseek-ai/dsh/package.json");
|
|
2054
|
+
const dshDir = dirname2(dshPkgPath);
|
|
2055
|
+
const appBoot = await import(pathToFileURL2(req.resolve("@deepseek-ai/dsh-app-boot")).href);
|
|
2056
|
+
const homePaths = await import(pathToFileURL2(req.resolve("@deepseek-ai/dsh-home-paths")).href);
|
|
2057
|
+
const home = homePaths.resolveDshHome();
|
|
2058
|
+
let bundlePatches;
|
|
2059
|
+
let profilePatches = [];
|
|
2060
|
+
let profilePatchPath;
|
|
2061
|
+
let rootConfigPath = join2(ownRoot(), "profile-root.cordis.yml");
|
|
2062
|
+
let bareModuleBaseUrl = pathToFileURL2(dshDir + sep2).href;
|
|
2063
|
+
const distBridge = join2(ownRoot(), "dist", "bridge.js");
|
|
2064
|
+
const bridgeEntry = existsSync2(distBridge) ? distBridge : join2(ownRoot(), "src", "bundle.ts");
|
|
2065
|
+
const realProfileDir = join2(home, "profiles", "acp");
|
|
2066
|
+
if (existsSync2(join2(realProfileDir, "package.json"))) {
|
|
2067
|
+
appBoot.healProfilesModuleFallback(dshPkgPath);
|
|
2068
|
+
const profile = appBoot.loadProfile(BIN, "acp", dshPkgPath);
|
|
2069
|
+
bundlePatches = profile.layers.flatMap((layer) => layer.patches);
|
|
2070
|
+
profilePatches = profile.patches;
|
|
2071
|
+
profilePatchPath = join2(profile.dir, "cordis.patch.yml");
|
|
2072
|
+
const realRoot = join2(profile.dir, "cordis.yml");
|
|
2073
|
+
if (existsSync2(realRoot)) rootConfigPath = realRoot;
|
|
2074
|
+
bareModuleBaseUrl = void 0;
|
|
2075
|
+
logDebug(`profile: real (${profile.dir})`);
|
|
2076
|
+
} else {
|
|
2077
|
+
const basePatch = bundlePatchPath(req.resolve("@deepseek-ai/dsh-base/package.json"));
|
|
2078
|
+
const ownPatch = bundlePatchPath(join2(ownRoot(), "package.json"));
|
|
2079
|
+
bundlePatches = [
|
|
2080
|
+
...appBoot.loadOverlayPatches(BIN, basePatch),
|
|
2081
|
+
...appBoot.loadOverlayPatches(BIN, ownPatch)
|
|
2082
|
+
];
|
|
2083
|
+
logDebug(`profile: virtual (dsh-base + ${ownRoot()})`);
|
|
2084
|
+
}
|
|
2085
|
+
for (const row of bundlePatches) rewriteBridgeRows(row, bridgeEntry);
|
|
2086
|
+
const homePatchPath = join2(home, "cordis.patch.yml");
|
|
2087
|
+
const homePatches = appBoot.loadOptionalPatches(BIN, homePatchPath) ?? [];
|
|
2088
|
+
const rows = /* @__PURE__ */ new Map();
|
|
2089
|
+
for (const row of appBoot.composeEntries([bundlePatches, profilePatches, homePatches])) {
|
|
2090
|
+
if (typeof row.id === "string") rows.set(row.id, row);
|
|
2091
|
+
}
|
|
2092
|
+
const overlays = [];
|
|
2093
|
+
const shippedPresets = join2(dshDir, "config", "agent-presets") + sep2;
|
|
2094
|
+
if (rows.has("agent-presets") && existsSync2(shippedPresets)) {
|
|
2095
|
+
overlays.push({
|
|
2096
|
+
id: "agent-presets",
|
|
2097
|
+
config: {
|
|
2098
|
+
...rows.get("agent-presets")?.config ?? {},
|
|
2099
|
+
roots: [{ path: shippedPresets, trust: "system" }]
|
|
2100
|
+
}
|
|
2101
|
+
});
|
|
2102
|
+
}
|
|
2103
|
+
if (process.env["DSH_TELEMETRY_DISABLED"] !== void 0 && rows.has("session-telemetry-otel")) {
|
|
2104
|
+
overlays.push({ id: "session-telemetry-otel", disabled: true });
|
|
2105
|
+
}
|
|
2106
|
+
const bridgeRow = rows.get("acp-bridge");
|
|
2107
|
+
if (overrides !== void 0 && bridgeRow !== void 0) {
|
|
2108
|
+
const patch = {};
|
|
2109
|
+
if (overrides.provider !== void 0) patch["provider"] = overrides.provider;
|
|
2110
|
+
if (overrides.model !== void 0) patch["model"] = overrides.model;
|
|
2111
|
+
if (overrides.permissionMode !== void 0) patch["permissionMode"] = overrides.permissionMode;
|
|
2112
|
+
if (overrides.maxTokens !== void 0) patch["maxTokens"] = overrides.maxTokens;
|
|
2113
|
+
if (Object.keys(patch).length > 0) {
|
|
2114
|
+
overlays.push({ id: "acp-bridge", config: { ...bridgeRow.config ?? {}, ...patch } });
|
|
2115
|
+
}
|
|
2116
|
+
}
|
|
2117
|
+
const allPatches = [...bundlePatches, ...profilePatches, ...homePatches, ...overlays];
|
|
2118
|
+
const launchEnvironment = appBoot.loadLayeredEnv("dsh");
|
|
2119
|
+
const launchEnvKey = (await import(pathToFileURL2(req.resolve("@deepseek-ai/dsh-launch-environment")).href)).DSH_LAUNCH_ENVIRONMENT_KEY;
|
|
2120
|
+
const ctx = await appBoot.boot(
|
|
2121
|
+
BIN,
|
|
2122
|
+
rootConfigPath,
|
|
2123
|
+
structuredClone(allPatches),
|
|
2124
|
+
(hostCtx) => {
|
|
2125
|
+
hostCtx.provide(launchEnvKey, launchEnvironment);
|
|
2126
|
+
},
|
|
2127
|
+
bareModuleBaseUrl
|
|
2128
|
+
);
|
|
2129
|
+
try {
|
|
2130
|
+
appBoot.assertEntriesLoaded(ctx, BIN);
|
|
2131
|
+
await appBoot.assertEntriesActivated(ctx, BIN);
|
|
2132
|
+
} catch (error) {
|
|
2133
|
+
await ctx.fiber.dispose().catch(() => {
|
|
2134
|
+
});
|
|
2135
|
+
throw error;
|
|
2136
|
+
}
|
|
2137
|
+
if (profilePatchPath !== void 0) {
|
|
2138
|
+
logDebug(`user patch layers are read at boot; edit ${profilePatchPath} and restart to apply`);
|
|
2139
|
+
}
|
|
2140
|
+
return ctx;
|
|
2141
|
+
}
|
|
2142
|
+
|
|
2015
2143
|
// src/settings.ts
|
|
2016
2144
|
import { homedir } from "node:os";
|
|
2017
|
-
import { join as
|
|
2145
|
+
import { join as join3 } from "node:path";
|
|
2018
2146
|
var DEFAULT_PERSONA = `You are a coding assistant powered by the {{model}} model, working inside an editor via the Agent Client Protocol. Your working directory is {{cwd}}. Your bash tool runs under a file sandbox \u2014 a \`[sandbox: file access denied \u2026]\` result is policy, not a command bug.
|
|
2019
2147
|
|
|
2020
2148
|
Verify your work by running the code or tests. Keep answers brief and factual.`;
|
|
@@ -2073,7 +2201,7 @@ function resolveSettings(argv) {
|
|
|
2073
2201
|
throw new SettingsError(`unknown flag: --${name3}`);
|
|
2074
2202
|
}
|
|
2075
2203
|
}
|
|
2076
|
-
const model = stringFlag(parsed, "model") ?? envString("DSH_MODEL")
|
|
2204
|
+
const model = stringFlag(parsed, "model") ?? envString("DSH_MODEL");
|
|
2077
2205
|
const modelsRaw = stringFlag(parsed, "models") ?? envString("DSH_ACP_MODELS");
|
|
2078
2206
|
const models = (modelsRaw !== void 0 ? modelsRaw.split(",") : ["deepseek-v4-flash", "deepseek-v4-pro"]).map((entry) => entry.trim()).filter((entry) => entry.length > 0);
|
|
2079
2207
|
const permissionModeRaw = stringFlag(parsed, "permission-mode") ?? envString("DSH_PERMISSION_MODE") ?? "workspace-write";
|
|
@@ -2102,12 +2230,12 @@ function resolveSettings(argv) {
|
|
|
2102
2230
|
}
|
|
2103
2231
|
return {
|
|
2104
2232
|
dshPath: stringFlag(parsed, "dsh-path") ?? envString("DSH_PATH"),
|
|
2105
|
-
provider: stringFlag(parsed, "provider") ?? envString("DSH_PROVIDER")
|
|
2233
|
+
provider: stringFlag(parsed, "provider") ?? envString("DSH_PROVIDER"),
|
|
2106
2234
|
model,
|
|
2107
2235
|
models,
|
|
2108
2236
|
maxTokens,
|
|
2109
2237
|
permissionMode,
|
|
2110
|
-
sessionRoot: stringFlag(parsed, "session-root") ?? envString("DSH_SESSION_ROOT") ??
|
|
2238
|
+
sessionRoot: stringFlag(parsed, "session-root") ?? envString("DSH_SESSION_ROOT") ?? join3(homedir(), ".dsh-acp", "sessions"),
|
|
2111
2239
|
persona: stringFlag(parsed, "persona") ?? envString("DSH_SYSTEM_PROMPT") ?? DEFAULT_PERSONA,
|
|
2112
2240
|
thinking: !parsed.flags.has("no-thinking"),
|
|
2113
2241
|
reasoningEffort: reasoningRaw,
|
|
@@ -2158,6 +2286,18 @@ async function main() {
|
|
|
2158
2286
|
console.log(HELP_TEXT.trimEnd());
|
|
2159
2287
|
return;
|
|
2160
2288
|
}
|
|
2289
|
+
if (argv[0] === "update") {
|
|
2290
|
+
logInfo(`updating ${NAME} (npm install -g ${NAME}@latest)\u2026`);
|
|
2291
|
+
const result = spawnSync("npm", ["install", "-g", `${NAME}@latest`], { stdio: ["ignore", 2, 2] });
|
|
2292
|
+
if (result.status !== 0) {
|
|
2293
|
+
logError(`npm install failed with status ${result.status ?? "unknown"}`);
|
|
2294
|
+
process.exitCode = result.status ?? 1;
|
|
2295
|
+
return;
|
|
2296
|
+
}
|
|
2297
|
+
logInfo("updated. If you also keep a global DeepSeek Harness, refresh it with:");
|
|
2298
|
+
logInfo(" npm install -g @deepseek-ai/dsh@latest");
|
|
2299
|
+
return;
|
|
2300
|
+
}
|
|
2161
2301
|
let settings;
|
|
2162
2302
|
try {
|
|
2163
2303
|
settings = resolveSettings(argv);
|
|
@@ -2171,11 +2311,24 @@ ${HELP_TEXT}`);
|
|
|
2171
2311
|
}
|
|
2172
2312
|
throw error;
|
|
2173
2313
|
}
|
|
2174
|
-
let
|
|
2314
|
+
let ctx;
|
|
2175
2315
|
try {
|
|
2176
2316
|
const host = resolveHost(settings.dshPath);
|
|
2177
2317
|
logDebug(`harness host: ${host.base} via ${host.source} (${host.version ?? "unknown version"})`);
|
|
2178
|
-
|
|
2318
|
+
if (process.env["DSH_ACP_COMPOSE"] === "spine") {
|
|
2319
|
+
const kit = await loadKit(host);
|
|
2320
|
+
const spineCtx = new kit.cordis.Context();
|
|
2321
|
+
await spineCtx.plugin(app_exports, { settings, kit });
|
|
2322
|
+
ctx = spineCtx;
|
|
2323
|
+
} else {
|
|
2324
|
+
const booted = await bootAcpProfile(host, {
|
|
2325
|
+
...settings.provider !== void 0 ? { provider: settings.provider } : {},
|
|
2326
|
+
...settings.model !== void 0 ? { model: settings.model } : {},
|
|
2327
|
+
...settings.permissionMode !== void 0 ? { permissionMode: settings.permissionMode } : {},
|
|
2328
|
+
...settings.maxTokens !== void 0 ? { maxTokens: settings.maxTokens } : {}
|
|
2329
|
+
});
|
|
2330
|
+
ctx = booted;
|
|
2331
|
+
}
|
|
2179
2332
|
} catch (error) {
|
|
2180
2333
|
if (error instanceof HarnessNotFoundError) {
|
|
2181
2334
|
logError(error.message);
|
|
@@ -2184,8 +2337,6 @@ ${HELP_TEXT}`);
|
|
|
2184
2337
|
}
|
|
2185
2338
|
throw error;
|
|
2186
2339
|
}
|
|
2187
|
-
const ctx = new kit.cordis.Context();
|
|
2188
|
-
await ctx.plugin(app_exports, { settings, kit });
|
|
2189
2340
|
let disposing = false;
|
|
2190
2341
|
const shutdown = (code) => {
|
|
2191
2342
|
if (disposing) return;
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.4.0",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
9
|
"url": "git+https://github.com/openma-ai/deepseek-harness-acp.git"
|
|
@@ -23,7 +23,8 @@
|
|
|
23
23
|
"cordis.patch.yml",
|
|
24
24
|
"README.md",
|
|
25
25
|
"LICENSE",
|
|
26
|
-
"package.json"
|
|
26
|
+
"package.json",
|
|
27
|
+
"profile-root.cordis.yml"
|
|
27
28
|
],
|
|
28
29
|
"scripts": {
|
|
29
30
|
"prepublishOnly": "npm run build",
|
|
@@ -110,7 +111,8 @@
|
|
|
110
111
|
"@deepseek-ai/dsh-mcp-client": "^0.1.0-rc.6",
|
|
111
112
|
"@deepseek-ai/dsh-sandbox-policy": "^0.1.0-rc.6",
|
|
112
113
|
"@deepseek-ai/dsh-session": "^0.1.0-rc.6",
|
|
113
|
-
"@deepseek-ai/dsh-session-title": "^0.1.0-rc.6"
|
|
114
|
+
"@deepseek-ai/dsh-session-title": "^0.1.0-rc.6",
|
|
115
|
+
"@deepseek-ai/dsh": "^0.1.0-rc.6"
|
|
114
116
|
},
|
|
115
117
|
"exports": {
|
|
116
118
|
".": "./dist/index.js",
|