@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 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 join2 } from "node:path";
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") ?? "deepseek-v4-flash";
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") ?? "deepseek-official",
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") ?? join2(homedir(), ".dsh-acp", "sessions"),
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 kit;
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
- kit = await loadKit(host);
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.3.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",
@@ -0,0 +1,3 @@
1
+ # dsh-acp self-hosted profile root — an empty entry list; the tree is
2
+ # composed as bundle patches (dsh-base, this package) plus the home layer.
3
+ []