@norman-else/dsh-claude 0.1.7 → 0.1.8
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/INSTALL.md +55 -55
- package/LICENSE +21 -21
- package/README.md +191 -191
- package/cordis.patch.yml +12 -12
- package/legacy-preset/agent.cordis.yml +11 -11
- package/legacy-preset/preset.yml +4 -4
- package/lib/bin.mjs +1 -1
- package/lib/bin.mjs.map +1 -1
- package/lib/client.d.ts +26 -0
- package/lib/client.js +329 -52
- package/lib/client.js.map +1 -1
- package/lib/{events-DP0Ov_Re.mjs → events-BVQkPmjg.mjs} +4 -2
- package/lib/events-BVQkPmjg.mjs.map +1 -0
- package/lib/index.mjs +267 -12
- package/lib/index.mjs.map +1 -1
- package/lib/{presenters-YMR2WMjn.mjs → presenters-CQ9dBVyY.mjs} +2 -2
- package/lib/presenters-CQ9dBVyY.mjs.map +1 -0
- package/lib/{preset-installer-BKw-SdOm.mjs → preset-installer-DUmmDvBm.mjs} +4 -4
- package/lib/preset-installer-DUmmDvBm.mjs.map +1 -0
- package/lib/preset-route.mjs +2 -2
- package/lib/preset-route.mjs.map +1 -1
- package/package.json +1 -1
- package/preset/claude/agent.cordis.yml +11 -11
- package/preset/claude/preset.yml +4 -4
- package/lib/events-DP0Ov_Re.mjs.map +0 -1
- package/lib/presenters-YMR2WMjn.mjs.map +0 -1
- package/lib/preset-installer-BKw-SdOm.mjs.map +0 -1
package/lib/index.mjs
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
import { a as latestClaudeTasks, c as normalizeTasksEvent, d as CLAUDE_ACTIVITY_EVENT, f as CLAUDE_CODE_PRESET_ID, g as CLAUDE_PROJECTION_PATH, h as CLAUDE_DOCTOR_PATH, i as latestClaudeSessionBinding, l as redactText, m as CLAUDE_CODE_PROVIDER_IDS, n as currentClaudeActivityCursor, o as normalizeActivity, p as CLAUDE_CODE_PROVIDER, r as latestClaudeContextUsage, s as normalizeContextUsage, t as boundText, u as safeDetail, v as
|
|
2
|
-
import { a as ClaudeCommandBridge, i as CLAUDE_COMMANDS_SERVICE, r as dynamicPresenterDefinition, t as CLAUDE_PRESENTER_NAMES } from "./presenters-
|
|
3
|
-
import { a as resolveClaudeExecutable, n as ensureManagedPreset, o as runClaudeDoctor, t as ManagedPresetConflictError } from "./preset-installer-
|
|
1
|
+
import { _ as CLAUDE_UPDATE_CHECK_PATH, a as latestClaudeTasks, b as TASK_TOOL_NAMES, c as normalizeTasksEvent, d as CLAUDE_ACTIVITY_EVENT, f as CLAUDE_CODE_PRESET_ID, g as CLAUDE_PROJECTION_PATH, h as CLAUDE_DOCTOR_PATH, i as latestClaudeSessionBinding, l as redactText, m as CLAUDE_CODE_PROVIDER_IDS, n as currentClaudeActivityCursor, o as normalizeActivity, p as CLAUDE_CODE_PROVIDER, r as latestClaudeContextUsage, s as normalizeContextUsage, t as boundText, u as safeDetail, v as CLAUDE_UPDATE_PATH } from "./events-BVQkPmjg.mjs";
|
|
2
|
+
import { a as ClaudeCommandBridge, i as CLAUDE_COMMANDS_SERVICE, r as dynamicPresenterDefinition, t as CLAUDE_PRESENTER_NAMES } from "./presenters-CQ9dBVyY.mjs";
|
|
3
|
+
import { a as resolveClaudeExecutable, n as ensureManagedPreset, o as runClaudeDoctor, t as ManagedPresetConflictError } from "./preset-installer-DUmmDvBm.mjs";
|
|
4
4
|
import z from "@deepseek-ai/schemastery";
|
|
5
5
|
import { CallId, LlmAdapter, ReasoningEffortId, createToolResultMessage, createUserMessage } from "@deepseek-ai/dsh-llm";
|
|
6
6
|
import { randomUUID } from "node:crypto";
|
|
7
|
-
import { chmod, mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
8
|
-
import { join } from "node:path";
|
|
9
|
-
import { dshHomePath } from "@deepseek-ai/dsh-home-paths";
|
|
7
|
+
import { chmod, mkdir, opendir, readFile, realpath, rename, rm, writeFile } from "node:fs/promises";
|
|
8
|
+
import { dirname, join, resolve } from "node:path";
|
|
9
|
+
import { dshHomePath, resolveDshHome } from "@deepseek-ai/dsh-home-paths";
|
|
10
10
|
import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
11
11
|
import { EventEmitter } from "node:events";
|
|
12
12
|
import { DSH_ENV_PREFIX, SENSITIVE_ENV_PATTERN } from "@deepseek-ai/dsh-subprocess";
|
|
13
|
+
import { fileURLToPath } from "node:url";
|
|
13
14
|
//#region src/sidecar.ts
|
|
14
15
|
const SIDECAR_SCHEMA_VERSION = 1;
|
|
15
16
|
const MAX_ACTIVITIES = 1e4;
|
|
@@ -2064,7 +2065,7 @@ function json(res, status, value) {
|
|
|
2064
2065
|
//#region src/doctor-routes.ts
|
|
2065
2066
|
const CLAUDE_DOCTOR_PROBE_TIMEOUT_MS = 15e3;
|
|
2066
2067
|
const claudeBridgeDiagnostics = /* @__PURE__ */ new WeakMap();
|
|
2067
|
-
function safeMessage(error) {
|
|
2068
|
+
function safeMessage$1(error) {
|
|
2068
2069
|
return redactText(error instanceof Error ? error.message : String(error), 1e3);
|
|
2069
2070
|
}
|
|
2070
2071
|
/** Live command-bridge diagnostics: which agents exist, their presets, and how
|
|
@@ -2080,14 +2081,14 @@ function commandDiagnostics(ctx) {
|
|
|
2080
2081
|
const preset = ctx.agentPresets.composedPreset(agent.ctx);
|
|
2081
2082
|
if (preset !== void 0) info.preset = preset;
|
|
2082
2083
|
} catch (error) {
|
|
2083
|
-
info.error = safeMessage(error);
|
|
2084
|
+
info.error = safeMessage$1(error);
|
|
2084
2085
|
}
|
|
2085
2086
|
try {
|
|
2086
2087
|
const list = ctx.commands.list(agent);
|
|
2087
2088
|
info.commandCount = list.length;
|
|
2088
2089
|
info.sample = list.slice(0, 10).map((command) => command.name);
|
|
2089
2090
|
} catch (error) {
|
|
2090
|
-
info.error = info.error === void 0 ? safeMessage(error) : `${info.error}; ${safeMessage(error)}`;
|
|
2091
|
+
info.error = info.error === void 0 ? safeMessage$1(error) : `${info.error}; ${safeMessage$1(error)}`;
|
|
2091
2092
|
}
|
|
2092
2093
|
const bridge = claudeBridgeDiagnostics.get(agent);
|
|
2093
2094
|
if (bridge !== void 0) info.bridge = bridge;
|
|
@@ -2095,7 +2096,7 @@ function commandDiagnostics(ctx) {
|
|
|
2095
2096
|
})
|
|
2096
2097
|
};
|
|
2097
2098
|
} catch (error) {
|
|
2098
|
-
return { error: safeMessage(error) };
|
|
2099
|
+
return { error: safeMessage$1(error) };
|
|
2099
2100
|
}
|
|
2100
2101
|
}
|
|
2101
2102
|
function registerClaudeDoctorRoutes(ctx, runtime, supervisor, config, resolutionError) {
|
|
@@ -2119,7 +2120,7 @@ function registerClaudeDoctorRoutes(ctx, runtime, supervisor, config, resolution
|
|
|
2119
2120
|
version: { status: "not-run" },
|
|
2120
2121
|
authentication: { status: "not-run" },
|
|
2121
2122
|
handshake: "not-run",
|
|
2122
|
-
message: safeMessage(resolutionError),
|
|
2123
|
+
message: safeMessage$1(resolutionError),
|
|
2123
2124
|
limits: {
|
|
2124
2125
|
idleTimeoutMs: config.idleTimeoutMs,
|
|
2125
2126
|
maxProcesses: config.maxProcesses
|
|
@@ -2149,7 +2150,7 @@ function registerClaudeDoctorRoutes(ctx, runtime, supervisor, config, resolution
|
|
|
2149
2150
|
commandBridge: commandDiagnostics(ctx)
|
|
2150
2151
|
});
|
|
2151
2152
|
} catch (error) {
|
|
2152
|
-
json(res, 500, { error: safeMessage(error) });
|
|
2153
|
+
json(res, 500, { error: safeMessage$1(error) });
|
|
2153
2154
|
}
|
|
2154
2155
|
}
|
|
2155
2156
|
}), "dsh-claude: Doctor route");
|
|
@@ -2198,6 +2199,259 @@ function registerClaudeProjectionRoute(ctx, sidecar, ownsSession) {
|
|
|
2198
2199
|
}), "dsh-claude: sidecar projection route");
|
|
2199
2200
|
}
|
|
2200
2201
|
//#endregion
|
|
2202
|
+
//#region src/update-routes.ts
|
|
2203
|
+
const PLUGIN_PACKAGE_NAME = "@norman-else/dsh-claude";
|
|
2204
|
+
const UPDATE_TIMEOUT_MS = 3e4;
|
|
2205
|
+
const CHECK_TIMEOUT_MS = 1e4;
|
|
2206
|
+
const MAX_MANIFEST_BYTES = 262144;
|
|
2207
|
+
const MAX_UPDATE_OUTPUT_BYTES = 32768;
|
|
2208
|
+
const SEMVER = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/;
|
|
2209
|
+
const PROFILE_NAME = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
|
|
2210
|
+
function safeMessage(error) {
|
|
2211
|
+
return redactText(error instanceof Error ? error.message : String(error), 500);
|
|
2212
|
+
}
|
|
2213
|
+
async function readManifest(path) {
|
|
2214
|
+
const text = await readFile(path, "utf8");
|
|
2215
|
+
if (Buffer.byteLength(text) > MAX_MANIFEST_BYTES) throw new Error("package manifest is too large");
|
|
2216
|
+
const value = JSON.parse(text);
|
|
2217
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error("package manifest is invalid");
|
|
2218
|
+
return value;
|
|
2219
|
+
}
|
|
2220
|
+
function dependencySpec(manifest) {
|
|
2221
|
+
if (typeof manifest.dependencies !== "object" || manifest.dependencies === null || Array.isArray(manifest.dependencies)) return void 0;
|
|
2222
|
+
const value = manifest.dependencies[PLUGIN_PACKAGE_NAME];
|
|
2223
|
+
return typeof value === "string" && value.length <= 2e3 ? value : void 0;
|
|
2224
|
+
}
|
|
2225
|
+
function classifyInstallSpec(spec) {
|
|
2226
|
+
if (/^(?:link|file|workspace):/i.test(spec)) return "link";
|
|
2227
|
+
if (/^(?:git(?:\+[^:]+)?:|github:|https?:|npm:)/i.test(spec) || /\.git(?:#|$)/i.test(spec)) return "unsupported";
|
|
2228
|
+
return /^(?:\^|~|>=?|<=?|=)?\s*v?\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\s*\|\|\s*(?:\^|~|>=?|<=?|=)?\s*v?\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?)*$/.test(spec.trim()) ? "registry" : "unsupported";
|
|
2229
|
+
}
|
|
2230
|
+
async function samePath(left, right) {
|
|
2231
|
+
try {
|
|
2232
|
+
const [a, b] = await Promise.all([realpath(left), realpath(right)]);
|
|
2233
|
+
return process.platform === "win32" ? a.toLowerCase() === b.toLowerCase() : a === b;
|
|
2234
|
+
} catch {
|
|
2235
|
+
return false;
|
|
2236
|
+
}
|
|
2237
|
+
}
|
|
2238
|
+
function linkedTarget(profileDir, spec) {
|
|
2239
|
+
const match = /^(?:link|file):(.*)$/i.exec(spec);
|
|
2240
|
+
return match?.[1] === void 0 ? void 0 : resolve(profileDir, match[1]);
|
|
2241
|
+
}
|
|
2242
|
+
async function discoverInstallation(dshHome, packageDir) {
|
|
2243
|
+
const profilesDir = join(dshHome, "profiles");
|
|
2244
|
+
const matches = [];
|
|
2245
|
+
let profiles;
|
|
2246
|
+
try {
|
|
2247
|
+
profiles = await opendir(profilesDir);
|
|
2248
|
+
} catch (error) {
|
|
2249
|
+
if (error.code === "ENOENT") return void 0;
|
|
2250
|
+
throw error;
|
|
2251
|
+
}
|
|
2252
|
+
for await (const entry of profiles) {
|
|
2253
|
+
if (!entry.isDirectory() || !PROFILE_NAME.test(entry.name)) continue;
|
|
2254
|
+
const profileDir = join(profilesDir, entry.name);
|
|
2255
|
+
let manifest;
|
|
2256
|
+
try {
|
|
2257
|
+
manifest = await readManifest(join(profileDir, "package.json"));
|
|
2258
|
+
} catch {
|
|
2259
|
+
continue;
|
|
2260
|
+
}
|
|
2261
|
+
const spec = dependencySpec(manifest);
|
|
2262
|
+
if (spec === void 0) continue;
|
|
2263
|
+
const source = classifyInstallSpec(spec);
|
|
2264
|
+
if (source === "link" ? linkedTarget(profileDir, spec) !== void 0 && await samePath(linkedTarget(profileDir, spec), packageDir) : await samePath(join(profileDir, "node_modules", ..."@norman-else/dsh-claude".split("/")), packageDir)) matches.push({
|
|
2265
|
+
profile: entry.name,
|
|
2266
|
+
profileDir,
|
|
2267
|
+
source,
|
|
2268
|
+
spec
|
|
2269
|
+
});
|
|
2270
|
+
}
|
|
2271
|
+
return matches.length === 1 ? matches[0] : void 0;
|
|
2272
|
+
}
|
|
2273
|
+
function parseVersion(version) {
|
|
2274
|
+
const match = SEMVER.exec(version);
|
|
2275
|
+
if (match === null) throw new Error("package version is not valid semver");
|
|
2276
|
+
return match;
|
|
2277
|
+
}
|
|
2278
|
+
function compareVersions(left, right) {
|
|
2279
|
+
const a = parseVersion(left);
|
|
2280
|
+
const b = parseVersion(right);
|
|
2281
|
+
for (const index of [
|
|
2282
|
+
1,
|
|
2283
|
+
2,
|
|
2284
|
+
3
|
|
2285
|
+
]) {
|
|
2286
|
+
const difference = Number(a[index]) - Number(b[index]);
|
|
2287
|
+
if (difference !== 0) return Math.sign(difference);
|
|
2288
|
+
}
|
|
2289
|
+
const aPre = a[4];
|
|
2290
|
+
const bPre = b[4];
|
|
2291
|
+
if (aPre === void 0) return bPre === void 0 ? 0 : 1;
|
|
2292
|
+
if (bPre === void 0) return -1;
|
|
2293
|
+
return aPre.localeCompare(bPre, "en", { numeric: true });
|
|
2294
|
+
}
|
|
2295
|
+
async function registryLatest(signal) {
|
|
2296
|
+
const response = await fetch("https://registry.npmjs.org/%40norman-else%2Fdsh-claude", {
|
|
2297
|
+
headers: { accept: "application/vnd.npm.install-v1+json" },
|
|
2298
|
+
signal
|
|
2299
|
+
});
|
|
2300
|
+
if (!response.ok) throw new Error(`npm registry returned HTTP ${response.status}`);
|
|
2301
|
+
const latest = (await response.json())["dist-tags"]?.latest;
|
|
2302
|
+
if (typeof latest !== "string") throw new Error("npm registry response has no latest version");
|
|
2303
|
+
parseVersion(latest);
|
|
2304
|
+
return latest;
|
|
2305
|
+
}
|
|
2306
|
+
async function resolvePackageContextDir(configured) {
|
|
2307
|
+
const moduleDir = dirname(fileURLToPath(import.meta.url));
|
|
2308
|
+
const candidates = configured === void 0 ? [moduleDir, dirname(moduleDir)] : [configured];
|
|
2309
|
+
for (const packageDir of candidates) try {
|
|
2310
|
+
const manifest = await readManifest(join(packageDir, "package.json"));
|
|
2311
|
+
if (manifest.name === "@norman-else/dsh-claude") return {
|
|
2312
|
+
packageDir,
|
|
2313
|
+
manifest
|
|
2314
|
+
};
|
|
2315
|
+
} catch {}
|
|
2316
|
+
throw new Error("plugin package manifest is invalid");
|
|
2317
|
+
}
|
|
2318
|
+
async function packageContext(deps) {
|
|
2319
|
+
const { packageDir, manifest } = await resolvePackageContextDir(deps.packageDir);
|
|
2320
|
+
if (typeof manifest.version !== "string") throw new Error("plugin package manifest is invalid");
|
|
2321
|
+
parseVersion(manifest.version);
|
|
2322
|
+
const installation = await discoverInstallation(deps.dshHome ?? resolveDshHome(), packageDir);
|
|
2323
|
+
return {
|
|
2324
|
+
version: manifest.version,
|
|
2325
|
+
...installation === void 0 ? {} : { installation }
|
|
2326
|
+
};
|
|
2327
|
+
}
|
|
2328
|
+
async function checkPluginUpdate(deps = {}) {
|
|
2329
|
+
try {
|
|
2330
|
+
const { version, installation } = await packageContext(deps);
|
|
2331
|
+
if (installation === void 0) return {
|
|
2332
|
+
currentVersion: version,
|
|
2333
|
+
source: "unknown",
|
|
2334
|
+
state: "unavailable",
|
|
2335
|
+
canUpdate: false,
|
|
2336
|
+
restartRequired: false,
|
|
2337
|
+
message: "Active DSH profile could not be identified uniquely"
|
|
2338
|
+
};
|
|
2339
|
+
if (installation.source === "link") return {
|
|
2340
|
+
currentVersion: version,
|
|
2341
|
+
source: "link",
|
|
2342
|
+
state: "linked",
|
|
2343
|
+
canUpdate: false,
|
|
2344
|
+
restartRequired: false,
|
|
2345
|
+
message: "Local development link; updates come from the linked checkout"
|
|
2346
|
+
};
|
|
2347
|
+
if (installation.source !== "registry") return {
|
|
2348
|
+
currentVersion: version,
|
|
2349
|
+
source: installation.source,
|
|
2350
|
+
state: "unsupported",
|
|
2351
|
+
canUpdate: false,
|
|
2352
|
+
restartRequired: false,
|
|
2353
|
+
message: "This installation source cannot be updated from the npm registry"
|
|
2354
|
+
};
|
|
2355
|
+
const latest = await (deps.fetchLatest ?? registryLatest)(AbortSignal.timeout(CHECK_TIMEOUT_MS));
|
|
2356
|
+
const comparison = compareVersions(version, latest);
|
|
2357
|
+
return {
|
|
2358
|
+
currentVersion: version,
|
|
2359
|
+
latestVersion: latest,
|
|
2360
|
+
source: "registry",
|
|
2361
|
+
state: comparison < 0 ? "available" : "current",
|
|
2362
|
+
canUpdate: comparison < 0,
|
|
2363
|
+
restartRequired: comparison < 0
|
|
2364
|
+
};
|
|
2365
|
+
} catch (error) {
|
|
2366
|
+
return {
|
|
2367
|
+
currentVersion: "unknown",
|
|
2368
|
+
source: "unknown",
|
|
2369
|
+
state: "error",
|
|
2370
|
+
canUpdate: false,
|
|
2371
|
+
restartRequired: false,
|
|
2372
|
+
message: safeMessage(error)
|
|
2373
|
+
};
|
|
2374
|
+
}
|
|
2375
|
+
}
|
|
2376
|
+
async function updatePlugin(deps = {}) {
|
|
2377
|
+
const { version, installation } = await packageContext(deps);
|
|
2378
|
+
if (installation === void 0 || installation.source !== "registry") throw new Error("Plugin update is unavailable for this installation");
|
|
2379
|
+
const latest = await (deps.fetchLatest ?? registryLatest)(AbortSignal.timeout(CHECK_TIMEOUT_MS));
|
|
2380
|
+
if (compareVersions(version, latest) >= 0) return {
|
|
2381
|
+
currentVersion: version,
|
|
2382
|
+
latestVersion: latest,
|
|
2383
|
+
source: "registry",
|
|
2384
|
+
state: "current",
|
|
2385
|
+
canUpdate: false,
|
|
2386
|
+
restartRequired: false
|
|
2387
|
+
};
|
|
2388
|
+
const resolveExecutable = deps.resolveExecutable;
|
|
2389
|
+
const spawn = deps.spawn;
|
|
2390
|
+
if (resolveExecutable === void 0 || spawn === void 0) throw new Error("DSH update runtime is unavailable");
|
|
2391
|
+
const signal = AbortSignal.timeout(UPDATE_TIMEOUT_MS);
|
|
2392
|
+
const handle = spawn({
|
|
2393
|
+
argv: [
|
|
2394
|
+
await resolveExecutable("dsh", {}, signal),
|
|
2395
|
+
"plugin",
|
|
2396
|
+
"--profile",
|
|
2397
|
+
installation.profile,
|
|
2398
|
+
"update",
|
|
2399
|
+
PLUGIN_PACKAGE_NAME
|
|
2400
|
+
],
|
|
2401
|
+
cwd: installation.profileDir,
|
|
2402
|
+
env: {},
|
|
2403
|
+
stdio: {
|
|
2404
|
+
stdin: "ignore",
|
|
2405
|
+
stdout: { maxBytes: MAX_UPDATE_OUTPUT_BYTES },
|
|
2406
|
+
stderr: { maxBytes: MAX_UPDATE_OUTPUT_BYTES }
|
|
2407
|
+
},
|
|
2408
|
+
graceMs: 2e3,
|
|
2409
|
+
signal
|
|
2410
|
+
});
|
|
2411
|
+
const outcome = await handle.done;
|
|
2412
|
+
if (outcome.exitCode !== 0) {
|
|
2413
|
+
const detail = handle.collected.stderr?.readFrom(0).text ?? "";
|
|
2414
|
+
throw new Error(`DSH plugin update failed (${outcome.exitCode ?? outcome.signal ?? "unknown exit"}): ${safeMessage(detail)}`);
|
|
2415
|
+
}
|
|
2416
|
+
return {
|
|
2417
|
+
currentVersion: version,
|
|
2418
|
+
latestVersion: latest,
|
|
2419
|
+
source: "registry",
|
|
2420
|
+
state: "current",
|
|
2421
|
+
canUpdate: false,
|
|
2422
|
+
restartRequired: true,
|
|
2423
|
+
message: "Update installed; restart DSH Desktop to load it"
|
|
2424
|
+
};
|
|
2425
|
+
}
|
|
2426
|
+
function registerClaudeUpdateRoutes(ctx, runtime, deps = {}) {
|
|
2427
|
+
const shared = {
|
|
2428
|
+
...deps,
|
|
2429
|
+
resolveExecutable: runtime.resolveExecutable.bind(runtime),
|
|
2430
|
+
spawn: runtime.spawn.bind(runtime)
|
|
2431
|
+
};
|
|
2432
|
+
for (const route of [{
|
|
2433
|
+
path: CLAUDE_UPDATE_CHECK_PATH,
|
|
2434
|
+
method: "GET",
|
|
2435
|
+
run: () => checkPluginUpdate(shared)
|
|
2436
|
+
}, {
|
|
2437
|
+
path: CLAUDE_UPDATE_PATH,
|
|
2438
|
+
method: "POST",
|
|
2439
|
+
run: () => updatePlugin(shared)
|
|
2440
|
+
}]) ctx.effect(() => ctx.webServer.register({
|
|
2441
|
+
kind: "exact",
|
|
2442
|
+
path: route.path,
|
|
2443
|
+
handler: async (req, res) => {
|
|
2444
|
+
if (req.method !== route.method) return json(res, 405, { error: "method not allowed" });
|
|
2445
|
+
if (!trustedRequest(req)) return json(res, 403, { error: "forbidden" });
|
|
2446
|
+
try {
|
|
2447
|
+
json(res, 200, await route.run());
|
|
2448
|
+
} catch (error) {
|
|
2449
|
+
json(res, 500, { error: safeMessage(error) });
|
|
2450
|
+
}
|
|
2451
|
+
}
|
|
2452
|
+
}), `dsh-claude: ${route.method} ${route.path}`);
|
|
2453
|
+
}
|
|
2454
|
+
//#endregion
|
|
2201
2455
|
//#region src/index.ts
|
|
2202
2456
|
const name = "llm-claude";
|
|
2203
2457
|
const inject = [
|
|
@@ -2409,6 +2663,7 @@ async function apply(ctx, config) {
|
|
|
2409
2663
|
ctx.effect(() => () => supervisor.dispose(), "dsh-claude: process supervisor");
|
|
2410
2664
|
ctx.inject(["webServer"], (webCtx) => {
|
|
2411
2665
|
registerClaudeDoctorRoutes(webCtx, webCtx.subprocess, supervisor, supervisorConfig, resolutionError);
|
|
2666
|
+
registerClaudeUpdateRoutes(webCtx, webCtx.subprocess);
|
|
2412
2667
|
registerClaudeProjectionRoute(webCtx, sidecar, (sessionId) => {
|
|
2413
2668
|
const agent = webCtx.agents.get(sessionId);
|
|
2414
2669
|
return agent !== void 0 && webCtx.agentPresets.composedPreset(agent.ctx) === "claude";
|