@schoolai/shipyard 3.10.0 → 3.11.0-rc.20260610.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/capability-detector-worker.js +3 -3
- package/dist/{chunk-EI4HMJ54.js → chunk-C6QOTETH.js} +28 -5
- package/dist/chunk-C6QOTETH.js.map +1 -0
- package/dist/{chunk-AEUTFH76.js → chunk-L7ELOV3S.js} +2 -2
- package/dist/{chunk-KRX7OJER.js → chunk-R3XQ6W7L.js} +2 -2
- package/dist/{chunk-4PBXNWJV.js → chunk-RMLQ5DRP.js} +5 -3
- package/dist/chunk-RMLQ5DRP.js.map +1 -0
- package/dist/{chunk-VKCGK333.js → chunk-YXPPZQBJ.js} +4 -2
- package/dist/chunk-YXPPZQBJ.js.map +1 -0
- package/dist/{chunk-4THTCNVI.js → chunk-ZRJTZLRF.js} +3 -3
- package/dist/cursor-runner.js +2 -2
- package/dist/electron-utility.js +2 -2
- package/dist/index.js +3 -3
- package/dist/{login-NZKH63H7.js → login-U256OVOJ.js} +3 -3
- package/dist/{serve-HVLR5UQ7.js → serve-MSZSF5JT.js} +564 -248
- package/dist/{serve-HVLR5UQ7.js.map → serve-MSZSF5JT.js.map} +1 -1
- package/dist/{start-YA4H2XFQ.js → start-CVNCLJMM.js} +6 -6
- package/package.json +2 -2
- package/dist/chunk-4PBXNWJV.js.map +0 -1
- package/dist/chunk-EI4HMJ54.js.map +0 -1
- package/dist/chunk-VKCGK333.js.map +0 -1
- /package/dist/{chunk-AEUTFH76.js.map → chunk-L7ELOV3S.js.map} +0 -0
- /package/dist/{chunk-KRX7OJER.js.map → chunk-R3XQ6W7L.js.map} +0 -0
- /package/dist/{chunk-4THTCNVI.js.map → chunk-ZRJTZLRF.js.map} +0 -0
- /package/dist/{login-NZKH63H7.js.map → login-U256OVOJ.js.map} +0 -0
- /package/dist/{start-YA4H2XFQ.js.map → start-CVNCLJMM.js.map} +0 -0
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
guardedSubscribe,
|
|
13
13
|
makeInitialAttemptState,
|
|
14
14
|
shutdownFileWatcherGuard
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-L7ELOV3S.js";
|
|
16
16
|
import {
|
|
17
17
|
TRAILER_SCHEMA_VERSION,
|
|
18
18
|
appendTrailerToMessage,
|
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
} from "./chunk-3WEEGJJN.js";
|
|
29
29
|
import {
|
|
30
30
|
getDaemonVersion
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-ZRJTZLRF.js";
|
|
32
32
|
import {
|
|
33
33
|
getRecentWasmPanicMessages
|
|
34
34
|
} from "./chunk-7H34LI75.js";
|
|
@@ -146,7 +146,7 @@ import {
|
|
|
146
146
|
translateWarningNotification,
|
|
147
147
|
unresolveReviewThread,
|
|
148
148
|
writeCursorApiKeyToVault
|
|
149
|
-
} from "./chunk-
|
|
149
|
+
} from "./chunk-C6QOTETH.js";
|
|
150
150
|
import {
|
|
151
151
|
buildNodeSpawnEnv,
|
|
152
152
|
nodeSpawnEnvOverlay,
|
|
@@ -399,7 +399,7 @@ import {
|
|
|
399
399
|
unsafeAssertSourceId,
|
|
400
400
|
vizFileExtension,
|
|
401
401
|
withPreferredRuntimeAuthMethod
|
|
402
|
-
} from "./chunk-
|
|
402
|
+
} from "./chunk-YXPPZQBJ.js";
|
|
403
403
|
import {
|
|
404
404
|
AuthGitHubCallbackRequestSchema,
|
|
405
405
|
AuthGitHubCallbackResponseSchema,
|
|
@@ -444,7 +444,7 @@ import {
|
|
|
444
444
|
VaultKeyPutRequestSchema,
|
|
445
445
|
VaultKeyPutResponseSchema,
|
|
446
446
|
classifyClaudeCodeCompatibility
|
|
447
|
-
} from "./chunk-
|
|
447
|
+
} from "./chunk-RMLQ5DRP.js";
|
|
448
448
|
import {
|
|
449
449
|
external_exports as external_exports2
|
|
450
450
|
} from "./chunk-EHQITHQX.js";
|
|
@@ -472,7 +472,7 @@ import "./chunk-2H7UOFLK.js";
|
|
|
472
472
|
// src/services/serve.ts
|
|
473
473
|
import { mkdir as mkdir44, realpath as realpath3 } from "fs/promises";
|
|
474
474
|
import { homedir as homedir14 } from "os";
|
|
475
|
-
import { join as
|
|
475
|
+
import { join as join87 } from "path";
|
|
476
476
|
import { query as query2 } from "@anthropic-ai/claude-agent-sdk";
|
|
477
477
|
|
|
478
478
|
// ../../node_modules/.pnpm/@logtape+logtape@1.3.7/node_modules/@logtape/logtape/dist/level.js
|
|
@@ -12998,6 +12998,7 @@ async function writePeerIdAtomic(target, peerId) {
|
|
|
12998
12998
|
import { readFile as readFile6, writeFile as writeFile7 } from "fs/promises";
|
|
12999
12999
|
import { join as join12 } from "path";
|
|
13000
13000
|
var PID_FILE = "children.pid";
|
|
13001
|
+
var GRACE_TERM_TO_KILL_MS = 2e3;
|
|
13001
13002
|
function buildPidTracker(shipyardHome) {
|
|
13002
13003
|
const filePath = join12(shipyardHome, PID_FILE);
|
|
13003
13004
|
let queue = Promise.resolve();
|
|
@@ -13043,14 +13044,10 @@ function buildPidTracker(shipyardHome) {
|
|
|
13043
13044
|
return enqueue(async () => {
|
|
13044
13045
|
const pids = await readPids();
|
|
13045
13046
|
if (pids.length === 0) return 0;
|
|
13046
|
-
|
|
13047
|
-
|
|
13048
|
-
|
|
13049
|
-
|
|
13050
|
-
killed++;
|
|
13051
|
-
log({ event: "orphan_killed", pid });
|
|
13052
|
-
} catch {
|
|
13053
|
-
}
|
|
13047
|
+
const killed = sendSigtermToEach(pids, log);
|
|
13048
|
+
if (killed > 0) {
|
|
13049
|
+
await new Promise((resolve10) => setTimeout(resolve10, GRACE_TERM_TO_KILL_MS));
|
|
13050
|
+
escalateSigkillToSurvivors(pids, log);
|
|
13054
13051
|
}
|
|
13055
13052
|
await writePids([]);
|
|
13056
13053
|
log({ event: "orphan_sweep_complete", found: pids.length, killed });
|
|
@@ -13059,6 +13056,28 @@ function buildPidTracker(shipyardHome) {
|
|
|
13059
13056
|
}
|
|
13060
13057
|
};
|
|
13061
13058
|
}
|
|
13059
|
+
function sendSigtermToEach(pids, log) {
|
|
13060
|
+
let killed = 0;
|
|
13061
|
+
for (const pid of pids) {
|
|
13062
|
+
try {
|
|
13063
|
+
process.kill(pid, "SIGTERM");
|
|
13064
|
+
killed++;
|
|
13065
|
+
log({ event: "orphan_killed", pid, signal: "SIGTERM" });
|
|
13066
|
+
} catch {
|
|
13067
|
+
}
|
|
13068
|
+
}
|
|
13069
|
+
return killed;
|
|
13070
|
+
}
|
|
13071
|
+
function escalateSigkillToSurvivors(pids, log) {
|
|
13072
|
+
for (const pid of pids) {
|
|
13073
|
+
try {
|
|
13074
|
+
process.kill(pid, 0);
|
|
13075
|
+
process.kill(pid, "SIGKILL");
|
|
13076
|
+
log({ event: "orphan_killed", pid, signal: "SIGKILL" });
|
|
13077
|
+
} catch {
|
|
13078
|
+
}
|
|
13079
|
+
}
|
|
13080
|
+
}
|
|
13062
13081
|
|
|
13063
13082
|
// src/services/bootstrap/repo-reload.ts
|
|
13064
13083
|
function buildGetDocDiagnostics(repoRef) {
|
|
@@ -13115,7 +13134,7 @@ function nanoid(size2 = 21) {
|
|
|
13115
13134
|
}
|
|
13116
13135
|
|
|
13117
13136
|
// src/services/bootstrap/signaling.ts
|
|
13118
|
-
var DAEMON_NPM_VERSION = true ? "3.
|
|
13137
|
+
var DAEMON_NPM_VERSION = true ? "3.11.0" : "unknown";
|
|
13119
13138
|
function createDaemonSignaling(config) {
|
|
13120
13139
|
const agentId = config.agentId ?? nanoid();
|
|
13121
13140
|
function send(msg) {
|
|
@@ -14288,7 +14307,7 @@ function runTaskSearch(args) {
|
|
|
14288
14307
|
}
|
|
14289
14308
|
|
|
14290
14309
|
// src/services/channels/control-channel-wiring.ts
|
|
14291
|
-
import { join as
|
|
14310
|
+
import { join as join35 } from "path";
|
|
14292
14311
|
|
|
14293
14312
|
// src/shared/type-utils.ts
|
|
14294
14313
|
function narrow(value) {
|
|
@@ -25647,7 +25666,7 @@ function spawnCodexLogout(callbacks) {
|
|
|
25647
25666
|
|
|
25648
25667
|
// src/services/serve-factory-helpers.ts
|
|
25649
25668
|
import { existsSync as existsSync3, readFileSync as readFileSync4 } from "fs";
|
|
25650
|
-
import { join as
|
|
25669
|
+
import { join as join29 } from "path";
|
|
25651
25670
|
|
|
25652
25671
|
// src/shared/capabilities/runtime/rate-limit-account-key.ts
|
|
25653
25672
|
function providerForProfile(profile) {
|
|
@@ -26940,6 +26959,7 @@ async function healGlobalDefault(settingsStore, workspaceRoot, detectedCount, lo
|
|
|
26940
26959
|
|
|
26941
26960
|
// src/services/session/anthropic-adapter.ts
|
|
26942
26961
|
import { spawn as spawn9 } from "child_process";
|
|
26962
|
+
import { join as join27 } from "path";
|
|
26943
26963
|
|
|
26944
26964
|
// src/shared/strip-ansi.ts
|
|
26945
26965
|
function stripAnsi(text) {
|
|
@@ -26981,6 +27001,7 @@ var PREFIX_FALLBACK_CONTEXT_WINDOWS = [
|
|
|
26981
27001
|
{ prefix: "claude-opus-4-8", contextWindow: 1e6 },
|
|
26982
27002
|
{ prefix: "claude-opus-4-7", contextWindow: 1e6 },
|
|
26983
27003
|
{ prefix: "claude-opus-4-6", contextWindow: 1e6 },
|
|
27004
|
+
{ prefix: "claude-fable-5", contextWindow: 1e6 },
|
|
26984
27005
|
{ prefix: "claude-opus-4", contextWindow: 2e5 },
|
|
26985
27006
|
{ prefix: "claude-sonnet-4", contextWindow: 2e5 },
|
|
26986
27007
|
{ prefix: "claude-haiku-4", contextWindow: 2e5 },
|
|
@@ -27055,7 +27076,12 @@ function prefsToFraction(prefs, maxTokens) {
|
|
|
27055
27076
|
if (maxTokens <= 0) return void 0;
|
|
27056
27077
|
return prefs.thresholdTokens / maxTokens;
|
|
27057
27078
|
}
|
|
27058
|
-
var ONE_M_SPAWN_PREFIXES = [
|
|
27079
|
+
var ONE_M_SPAWN_PREFIXES = [
|
|
27080
|
+
"claude-opus-4-8",
|
|
27081
|
+
"claude-opus-4-7",
|
|
27082
|
+
"claude-opus-4-6",
|
|
27083
|
+
"claude-fable-5"
|
|
27084
|
+
];
|
|
27059
27085
|
function resolveSpawnModel(model) {
|
|
27060
27086
|
if (!model) return model;
|
|
27061
27087
|
if (model.includes("[1m]")) return model;
|
|
@@ -27278,6 +27304,12 @@ function hasActiveCollaborators(participants) {
|
|
|
27278
27304
|
function shouldClearPersistence(status) {
|
|
27279
27305
|
return status === "completed" || status === "canceled";
|
|
27280
27306
|
}
|
|
27307
|
+
function isRefusalStopReason(stopReason) {
|
|
27308
|
+
return stopReason === "refusal";
|
|
27309
|
+
}
|
|
27310
|
+
function refusalBannerMessage() {
|
|
27311
|
+
return "The model declined this request (safety classifier).";
|
|
27312
|
+
}
|
|
27281
27313
|
function classifyRoiTransition(nextStatus, roiEverRan) {
|
|
27282
27314
|
if (nextStatus === "completed" || nextStatus === "canceled") return "emit-ended";
|
|
27283
27315
|
if (nextStatus === "input_required" && roiEverRan) return "emit-ended";
|
|
@@ -27572,6 +27604,11 @@ function hasErrorCode(err3, code) {
|
|
|
27572
27604
|
const record = err3;
|
|
27573
27605
|
return record.code === code;
|
|
27574
27606
|
}
|
|
27607
|
+
function errnoCode(err3) {
|
|
27608
|
+
if (typeof err3 !== "object" || err3 === null || !("code" in err3)) return void 0;
|
|
27609
|
+
const record = err3;
|
|
27610
|
+
return typeof record.code === "string" ? record.code : void 0;
|
|
27611
|
+
}
|
|
27575
27612
|
function isCliFlagEffort(effort) {
|
|
27576
27613
|
switch (effort) {
|
|
27577
27614
|
case "low":
|
|
@@ -27651,6 +27688,13 @@ var AnthropicAgentSubprocess = class _AnthropicAgentSubprocess {
|
|
|
27651
27688
|
#onEvent;
|
|
27652
27689
|
#spawnMcpServers;
|
|
27653
27690
|
#harnessTaskIdSetter = null;
|
|
27691
|
+
/**
|
|
27692
|
+
* The epoch bound to this subprocess's in-process harness server at spawn
|
|
27693
|
+
* time (installed by serve-factory immediately after `setHarnessEpoch`).
|
|
27694
|
+
* Surfaced via the `harnessEpoch` getter so the pre-warm adoption handshake
|
|
27695
|
+
* writes the SAME epoch to the registry that the harness fence checks.
|
|
27696
|
+
*/
|
|
27697
|
+
#harnessEpoch = null;
|
|
27654
27698
|
/**
|
|
27655
27699
|
* Mutable slot for the CwdChanged handler. The SDK hook is registered
|
|
27656
27700
|
* unconditionally at spawn time and reads through this slot on each
|
|
@@ -27709,6 +27753,18 @@ var AnthropicAgentSubprocess = class _AnthropicAgentSubprocess {
|
|
|
27709
27753
|
installHarnessTaskIdSetter(setter) {
|
|
27710
27754
|
this.#harnessTaskIdSetter = setter;
|
|
27711
27755
|
}
|
|
27756
|
+
/**
|
|
27757
|
+
* Record the epoch serve-factory minted and bound to this subprocess's
|
|
27758
|
+
* in-process harness server (called right after `setHarnessEpoch`). The
|
|
27759
|
+
* pre-warm manager reads it back via `harnessEpoch` so adoption registers
|
|
27760
|
+
* the same epoch the fence will check — never a second, divergent UUID.
|
|
27761
|
+
*/
|
|
27762
|
+
installHarnessEpoch(epoch) {
|
|
27763
|
+
this.#harnessEpoch = epoch;
|
|
27764
|
+
}
|
|
27765
|
+
get harnessEpoch() {
|
|
27766
|
+
return this.#harnessEpoch;
|
|
27767
|
+
}
|
|
27712
27768
|
setHarnessTaskId(taskId) {
|
|
27713
27769
|
if (!this.#harnessTaskIdSetter) {
|
|
27714
27770
|
throw new Error("setHarnessTaskId called before installHarnessTaskIdSetter");
|
|
@@ -27867,7 +27923,24 @@ var AnthropicAgentSubprocess = class _AnthropicAgentSubprocess {
|
|
|
27867
27923
|
...process.env,
|
|
27868
27924
|
...options.env,
|
|
27869
27925
|
DISABLE_AUTO_COMPACT: "1",
|
|
27870
|
-
CLAUDE_CODE_ENTRYPOINT: "shipyard"
|
|
27926
|
+
CLAUDE_CODE_ENTRYPOINT: "shipyard",
|
|
27927
|
+
/**
|
|
27928
|
+
* Isolate every `codex` binary the agent invokes (via Bash/shell
|
|
27929
|
+
* tool) from the user's real `~/.codex/auth.json`. The primary
|
|
27930
|
+
* codex engine (daemon-internal, spawned by `codex-facade.ts`'s
|
|
27931
|
+
* `getOrCreateCodexEngine`) reads `~/.codex` directly through its
|
|
27932
|
+
* own `resolveSpawnConfig` path and is NOT affected by this env.
|
|
27933
|
+
*
|
|
27934
|
+
* Value is keyed off `SHIPYARD_HOME` so in E2E tests it resolves
|
|
27935
|
+
* to the per-test isolated home (`${shipyardHome}/codex-isolated`),
|
|
27936
|
+
* and in the primary daemon it resolves to
|
|
27937
|
+
* `~/.shipyard/codex-isolated` — distinct from `~/.codex`.
|
|
27938
|
+
*
|
|
27939
|
+
* Must come AFTER the spread of `options.env` and `process.env`
|
|
27940
|
+
* so it always wins, preventing an ambient `CODEX_HOME` from the
|
|
27941
|
+
* developer's shell from leaking through to the agent subprocess.
|
|
27942
|
+
*/
|
|
27943
|
+
CODEX_HOME: join27(getShipyardHome(), "codex-isolated")
|
|
27871
27944
|
},
|
|
27872
27945
|
disallowedTools: options.disallowedTools,
|
|
27873
27946
|
skills: options.skills,
|
|
@@ -27944,9 +28017,17 @@ var AnthropicAgentSubprocess = class _AnthropicAgentSubprocess {
|
|
|
27944
28017
|
forceKill() {
|
|
27945
28018
|
this.#forceKilled = true;
|
|
27946
28019
|
if (this.#pidRef.current != null) {
|
|
28020
|
+
const pid = this.#pidRef.current;
|
|
27947
28021
|
try {
|
|
27948
|
-
process.kill(
|
|
27949
|
-
} catch {
|
|
28022
|
+
process.kill(-pid, "SIGKILL");
|
|
28023
|
+
} catch (err3) {
|
|
28024
|
+
const code = errnoCode(err3);
|
|
28025
|
+
if (code === "EPERM" || code === "EINVAL") {
|
|
28026
|
+
try {
|
|
28027
|
+
process.kill(pid, "SIGKILL");
|
|
28028
|
+
} catch {
|
|
28029
|
+
}
|
|
28030
|
+
}
|
|
27950
28031
|
}
|
|
27951
28032
|
this.#pidRef.current = null;
|
|
27952
28033
|
}
|
|
@@ -28261,7 +28342,15 @@ function createChildSpawner(stderrCallback, pidRef, onChildSpawned, onChildExite
|
|
|
28261
28342
|
stdio: ["pipe", "pipe", stderrCallback ? "pipe" : "ignore"],
|
|
28262
28343
|
signal: spawnOpts.signal,
|
|
28263
28344
|
env: { ...spawnOpts.env, CLAUDECODE: void 0, NODE_OPTIONS: nodeOptions },
|
|
28264
|
-
windowsHide: true
|
|
28345
|
+
windowsHide: true,
|
|
28346
|
+
/**
|
|
28347
|
+
* detached: true makes the child the leader of its own process group.
|
|
28348
|
+
* Combined with the process-group kill in forceKill() (`kill(-pid)`)
|
|
28349
|
+
* this ensures the agent's subprocesses (bash, gh, git, npx) are
|
|
28350
|
+
* reaped when we abort — they would otherwise be orphaned to launchd.
|
|
28351
|
+
* POSIX only (macOS + Linux); Windows is not shipped.
|
|
28352
|
+
*/
|
|
28353
|
+
detached: true
|
|
28265
28354
|
});
|
|
28266
28355
|
if (!child.stdin || !child.stdout) {
|
|
28267
28356
|
throw new Error("Failed to create stdio pipes for Claude subprocess");
|
|
@@ -28337,7 +28426,7 @@ import { homedir as homedir4 } from "os";
|
|
|
28337
28426
|
|
|
28338
28427
|
// src/shared/capabilities/capabilities-cache.ts
|
|
28339
28428
|
import { mkdir as mkdir13, readFile as readFile18, rename as rename11, unlink as unlink8, writeFile as writeFile14 } from "fs/promises";
|
|
28340
|
-
import { dirname as dirname15, join as
|
|
28429
|
+
import { dirname as dirname15, join as join28 } from "path";
|
|
28341
28430
|
var CAPABILITIES_CACHE_VERSION = 1;
|
|
28342
28431
|
var GitRepoInfoCacheSchema = external_exports.object({
|
|
28343
28432
|
path: external_exports.string(),
|
|
@@ -28371,7 +28460,7 @@ var CacheFileSchema = external_exports.object({
|
|
|
28371
28460
|
mcpServers: external_exports.array(MCPServerInfoCacheSchema)
|
|
28372
28461
|
});
|
|
28373
28462
|
function cacheFilePath() {
|
|
28374
|
-
return
|
|
28463
|
+
return join28(getShipyardHome(), "data", "capabilities-cache.json");
|
|
28375
28464
|
}
|
|
28376
28465
|
var EMPTY_ENVIRONMENTS = [];
|
|
28377
28466
|
var EMPTY_MCP_SERVERS = [];
|
|
@@ -28637,7 +28726,7 @@ function appendDynamicPrompt(base2, appendix) {
|
|
|
28637
28726
|
${appendix}` : base2;
|
|
28638
28727
|
}
|
|
28639
28728
|
function rehydrateVizRegistry(registry, vizWatcher, resolvedTaskId, vizDir, log) {
|
|
28640
|
-
const registryPath =
|
|
28729
|
+
const registryPath = join29(vizDir, resolvedTaskId, "registry.json");
|
|
28641
28730
|
if (!existsSync3(registryPath)) return Promise.resolve();
|
|
28642
28731
|
try {
|
|
28643
28732
|
const raw = readFileSync4(registryPath, "utf-8");
|
|
@@ -28874,7 +28963,7 @@ async function initializeVaultSync(vaultKey, deps, credentialsVaultStore, oauthS
|
|
|
28874
28963
|
});
|
|
28875
28964
|
}
|
|
28876
28965
|
function buildDefaultRepo(dataDir, identity) {
|
|
28877
|
-
const storage = new FileStorageAdapter(
|
|
28966
|
+
const storage = new FileStorageAdapter(join29(dataDir, "loro"));
|
|
28878
28967
|
return {
|
|
28879
28968
|
repo: new Repo({
|
|
28880
28969
|
identity,
|
|
@@ -29116,6 +29205,9 @@ function buildRejectionStubSubprocess(input) {
|
|
|
29116
29205
|
stopBackgroundTask: noop3,
|
|
29117
29206
|
setHarnessTaskId() {
|
|
29118
29207
|
},
|
|
29208
|
+
get harnessEpoch() {
|
|
29209
|
+
return null;
|
|
29210
|
+
},
|
|
29119
29211
|
setOnCwdChanged() {
|
|
29120
29212
|
},
|
|
29121
29213
|
async rollback(_numTurns) {
|
|
@@ -29660,12 +29752,12 @@ function createBestEffortSender(deps) {
|
|
|
29660
29752
|
|
|
29661
29753
|
// src/services/comments/github-ingest-pipeline.ts
|
|
29662
29754
|
import { readFile as readFile20 } from "fs/promises";
|
|
29663
|
-
import { join as
|
|
29755
|
+
import { join as join31 } from "path";
|
|
29664
29756
|
|
|
29665
29757
|
// src/services/harness/comment-server.ts
|
|
29666
29758
|
import { randomUUID as randomUUID9 } from "crypto";
|
|
29667
29759
|
import { access as access4, readFile as readFile19 } from "fs/promises";
|
|
29668
|
-
import { join as
|
|
29760
|
+
import { join as join30, relative as relative5 } from "path";
|
|
29669
29761
|
|
|
29670
29762
|
// src/shared/xml-utils.ts
|
|
29671
29763
|
function escapeXmlAttr(text) {
|
|
@@ -30554,7 +30646,7 @@ async function resolveDiffScopeForFile(cwd, normalizedPath) {
|
|
|
30554
30646
|
}
|
|
30555
30647
|
async function handleDiffComment(ctx, filePath, lineNumber, comment) {
|
|
30556
30648
|
const normalizedPath = normalizeToWorkspaceRelative(filePath, ctx.environmentKey);
|
|
30557
|
-
const absolutePath =
|
|
30649
|
+
const absolutePath = join30(ctx.environmentKey, normalizedPath);
|
|
30558
30650
|
const fileExists2 = await access4(absolutePath).then(
|
|
30559
30651
|
() => true,
|
|
30560
30652
|
() => false
|
|
@@ -30841,7 +30933,7 @@ function prCommentToAnnotation(prComment, ctx) {
|
|
|
30841
30933
|
// src/services/comments/github-ingest-pipeline.ts
|
|
30842
30934
|
async function readLocalFileContent(cwd, path5) {
|
|
30843
30935
|
try {
|
|
30844
|
-
return await readFile20(
|
|
30936
|
+
return await readFile20(join31(cwd, path5), "utf-8");
|
|
30845
30937
|
} catch {
|
|
30846
30938
|
return getFileAtRef(cwd, path5, "HEAD");
|
|
30847
30939
|
}
|
|
@@ -31649,12 +31741,12 @@ function createPRPoller(callbacks, log, resolveTopLevel = getGitTopLevel) {
|
|
|
31649
31741
|
|
|
31650
31742
|
// src/services/roi/commit-sweep.ts
|
|
31651
31743
|
import { stat as stat11 } from "fs/promises";
|
|
31652
|
-
import { join as
|
|
31744
|
+
import { join as join33 } from "path";
|
|
31653
31745
|
|
|
31654
31746
|
// src/services/git-checkpoint.ts
|
|
31655
31747
|
import { execFile as execFileCb2 } from "child_process";
|
|
31656
31748
|
import { readFile as readFile21, stat as stat10, unlink as unlink9, writeFile as writeFile15 } from "fs/promises";
|
|
31657
|
-
import { join as
|
|
31749
|
+
import { join as join32 } from "path";
|
|
31658
31750
|
import { promisify as promisify7 } from "util";
|
|
31659
31751
|
var execFile9 = promisify7(execFileCb2);
|
|
31660
31752
|
var NOT_A_GIT_REPO = "Not a git repository";
|
|
@@ -31666,10 +31758,10 @@ async function resolveGitPaths(repoDir, taskId) {
|
|
|
31666
31758
|
try {
|
|
31667
31759
|
const { stdout } = await execFile9("git", ["rev-parse", "--git-dir"], { cwd: repoDir });
|
|
31668
31760
|
const gitDir = stdout.trim();
|
|
31669
|
-
const absoluteGitDir = gitDir.startsWith("/") ? gitDir :
|
|
31761
|
+
const absoluteGitDir = gitDir.startsWith("/") ? gitDir : join32(repoDir, gitDir);
|
|
31670
31762
|
return {
|
|
31671
31763
|
gitDir: absoluteGitDir,
|
|
31672
|
-
shadowIndex:
|
|
31764
|
+
shadowIndex: join32(absoluteGitDir, `shipyard-index-${taskId}`)
|
|
31673
31765
|
};
|
|
31674
31766
|
} catch {
|
|
31675
31767
|
return null;
|
|
@@ -31764,7 +31856,7 @@ async function rewindToCheckpointImpl(repoDir, taskId, turnNo) {
|
|
|
31764
31856
|
const untrackedFiles = untrackedRaw.trim().split("\n").filter((f2) => f2.length > 0);
|
|
31765
31857
|
for (const file of untrackedFiles) {
|
|
31766
31858
|
try {
|
|
31767
|
-
const fullPath =
|
|
31859
|
+
const fullPath = join32(repoDir, file);
|
|
31768
31860
|
const s2 = await stat10(fullPath);
|
|
31769
31861
|
if (s2.isFile()) {
|
|
31770
31862
|
await unlink9(fullPath);
|
|
@@ -32031,7 +32123,7 @@ async function revertSingleFile(repoDir, file, restoreCommit, mode) {
|
|
|
32031
32123
|
const isDeletedByAgent = file.status === "deleted";
|
|
32032
32124
|
const shouldDelete = mode === "revert" && isAddedByAgent || mode === "unrevert" && isDeletedByAgent;
|
|
32033
32125
|
if (shouldDelete) {
|
|
32034
|
-
await unlink9(
|
|
32126
|
+
await unlink9(join32(repoDir, file.path)).catch((err3) => {
|
|
32035
32127
|
if (!isEnoent(err3)) throw err3;
|
|
32036
32128
|
});
|
|
32037
32129
|
await execFile9("git", ["reset", "HEAD", "--", file.path], { cwd: repoDir }).catch(() => {
|
|
@@ -32043,7 +32135,7 @@ async function revertSingleFile(repoDir, file, restoreCommit, mode) {
|
|
|
32043
32135
|
maxBuffer: 10 * 1024 * 1024,
|
|
32044
32136
|
encoding: "buffer"
|
|
32045
32137
|
});
|
|
32046
|
-
await writeFile15(
|
|
32138
|
+
await writeFile15(join32(repoDir, file.path), stdout);
|
|
32047
32139
|
await execFile9("git", ["reset", "HEAD", "--", file.path], { cwd: repoDir }).catch(() => {
|
|
32048
32140
|
});
|
|
32049
32141
|
return true;
|
|
@@ -32136,7 +32228,7 @@ async function diffCheckpointToWorkingTreeImpl(repoDir, taskId, fromTurnNo, scop
|
|
|
32136
32228
|
if (!line || statusMap.has(line)) continue;
|
|
32137
32229
|
let ins = 0;
|
|
32138
32230
|
try {
|
|
32139
|
-
ins = countLines(await readFile21(
|
|
32231
|
+
ins = countLines(await readFile21(join32(repoDir, line), "utf-8"));
|
|
32140
32232
|
} catch {
|
|
32141
32233
|
}
|
|
32142
32234
|
entries.push({ path: line, status: "added", insertions: ins, deletions: 0 });
|
|
@@ -32156,7 +32248,7 @@ async function getFileVsWorkingTreeImpl(repoDir, taskId, fromTurnNo, filePath) {
|
|
|
32156
32248
|
if (from2 === "error") return null;
|
|
32157
32249
|
let modifiedContent;
|
|
32158
32250
|
try {
|
|
32159
|
-
modifiedContent = await readFile21(
|
|
32251
|
+
modifiedContent = await readFile21(join32(repoDir, filePath), "utf-8");
|
|
32160
32252
|
} catch {
|
|
32161
32253
|
modifiedContent = "";
|
|
32162
32254
|
}
|
|
@@ -32437,7 +32529,7 @@ async function isGitBinaryMissing() {
|
|
|
32437
32529
|
}
|
|
32438
32530
|
async function isGitWorkingTree(cwd) {
|
|
32439
32531
|
try {
|
|
32440
|
-
await stat11(
|
|
32532
|
+
await stat11(join33(cwd, ".git"));
|
|
32441
32533
|
return true;
|
|
32442
32534
|
} catch {
|
|
32443
32535
|
return false;
|
|
@@ -33401,7 +33493,7 @@ async function sweepOrphanedNotifications(taskStateStore, log) {
|
|
|
33401
33493
|
|
|
33402
33494
|
// src/services/loro-recovery.ts
|
|
33403
33495
|
import { access as access5, mkdir as mkdir14, rename as rename12, rm as rm6 } from "fs/promises";
|
|
33404
|
-
import { join as
|
|
33496
|
+
import { join as join34 } from "path";
|
|
33405
33497
|
var DEFAULT_RECOVERY_TTL_MS = 6e4;
|
|
33406
33498
|
function createLoroRecoveryService(deps) {
|
|
33407
33499
|
const disabled = validateEnv().SHIPYARD_DISABLE_LORO_RECOVERY;
|
|
@@ -33452,9 +33544,9 @@ function createLoroRecoveryService(deps) {
|
|
|
33452
33544
|
}
|
|
33453
33545
|
async function quarantineAndSweep(docId, isoTs) {
|
|
33454
33546
|
const encDocId = encodeURIComponent(docId);
|
|
33455
|
-
const sourcePath =
|
|
33456
|
-
const quarantineRoot =
|
|
33457
|
-
const quarantinePath =
|
|
33547
|
+
const sourcePath = join34(deps.dataDir, "loro", encDocId);
|
|
33548
|
+
const quarantineRoot = join34(deps.dataDir, "loro-quarantine", isoTs);
|
|
33549
|
+
const quarantinePath = join34(quarantineRoot, encDocId);
|
|
33458
33550
|
const sourceExists = await pathExists3(sourcePath);
|
|
33459
33551
|
if (!sourceExists) return "";
|
|
33460
33552
|
await mkdir14(quarantineRoot, { recursive: true, mode: 448 });
|
|
@@ -33463,7 +33555,7 @@ function createLoroRecoveryService(deps) {
|
|
|
33463
33555
|
}
|
|
33464
33556
|
async function postDeleteSweep(docId) {
|
|
33465
33557
|
const encDocId = encodeURIComponent(docId);
|
|
33466
|
-
const sourcePath =
|
|
33558
|
+
const sourcePath = join34(deps.dataDir, "loro", encDocId);
|
|
33467
33559
|
if (await pathExists3(sourcePath)) {
|
|
33468
33560
|
try {
|
|
33469
33561
|
await rm6(sourcePath, { recursive: true, force: true });
|
|
@@ -35290,7 +35382,7 @@ function wireControlChannel(rawChannel, daemon, logAdapter, deps) {
|
|
|
35290
35382
|
const aloStreamId = controlChannelStreamId(deps.peerSourceId);
|
|
35291
35383
|
const aloOutboxChannelName = controlChannelOutboxChannel("daemon", deps.peerSourceId);
|
|
35292
35384
|
const channelEpoch = registerControlChannelEpoch(controlPeerId);
|
|
35293
|
-
const dataDir =
|
|
35385
|
+
const dataDir = join35(deps?.shipyardHome ?? getShipyardHome(), "data");
|
|
35294
35386
|
const aloOutbox = new JsonDocOutbox({
|
|
35295
35387
|
dataDir,
|
|
35296
35388
|
channel: aloOutboxChannelName,
|
|
@@ -35714,7 +35806,7 @@ function createPeerRoleRegistry() {
|
|
|
35714
35806
|
|
|
35715
35807
|
// src/services/epoch-pruning.ts
|
|
35716
35808
|
import { readdir as readdir14, rm as rm7 } from "fs/promises";
|
|
35717
|
-
import { join as
|
|
35809
|
+
import { join as join36 } from "path";
|
|
35718
35810
|
var LEGACY_PREFIXES = [
|
|
35719
35811
|
"task-meta",
|
|
35720
35812
|
"task-conv",
|
|
@@ -35754,7 +35846,7 @@ async function pruneOldEpochData(dataDir, currentEpoch, log) {
|
|
|
35754
35846
|
}
|
|
35755
35847
|
if (!shouldPrune(decoded, currentEpoch)) continue;
|
|
35756
35848
|
removals.push(
|
|
35757
|
-
rm7(
|
|
35849
|
+
rm7(join36(dataDir, entry.name), { recursive: true }).then(() => {
|
|
35758
35850
|
pruned++;
|
|
35759
35851
|
}).catch((err3) => {
|
|
35760
35852
|
log({
|
|
@@ -37979,7 +38071,7 @@ function onConnection(ws, deps, peers) {
|
|
|
37979
38071
|
|
|
37980
38072
|
// src/services/local-direct/local-direct-token.ts
|
|
37981
38073
|
import { chmod as chmod2, mkdir as mkdir15, rename as rename13, rm as rm8, writeFile as writeFile16 } from "fs/promises";
|
|
37982
|
-
import { dirname as dirname17, join as
|
|
38074
|
+
import { dirname as dirname17, join as join37 } from "path";
|
|
37983
38075
|
var ADVERTISEMENT_FILE = "local-direct.json";
|
|
37984
38076
|
var ADVERTISEMENT_MODE = 384;
|
|
37985
38077
|
var ADVERTISEMENT_DIR_MODE = 448;
|
|
@@ -37988,7 +38080,7 @@ function generateLocalDirectToken() {
|
|
|
37988
38080
|
return nanoid(TOKEN_LENGTH);
|
|
37989
38081
|
}
|
|
37990
38082
|
function advertisementPath(shipyardHome) {
|
|
37991
|
-
return
|
|
38083
|
+
return join37(shipyardHome, "data", ADVERTISEMENT_FILE);
|
|
37992
38084
|
}
|
|
37993
38085
|
async function writeAdvertisement(shipyardHome, ad) {
|
|
37994
38086
|
const target = advertisementPath(shipyardHome);
|
|
@@ -38255,7 +38347,7 @@ async function setupPluginEventWiring(deps) {
|
|
|
38255
38347
|
import { exec as execCb2 } from "child_process";
|
|
38256
38348
|
import { existsSync as existsSync5 } from "fs";
|
|
38257
38349
|
import { readdir as readdir15, readFile as readFile22, stat as stat12 } from "fs/promises";
|
|
38258
|
-
import { basename as basename7, dirname as dirname18, join as
|
|
38350
|
+
import { basename as basename7, dirname as dirname18, join as join38 } from "path";
|
|
38259
38351
|
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
38260
38352
|
import { promisify as promisify8 } from "util";
|
|
38261
38353
|
|
|
@@ -38390,7 +38482,7 @@ var PluginFileWatcher = class {
|
|
|
38390
38482
|
}
|
|
38391
38483
|
const loaded = [];
|
|
38392
38484
|
for (const entry of entries) {
|
|
38393
|
-
const pluginDir =
|
|
38485
|
+
const pluginDir = join38(dir, entry);
|
|
38394
38486
|
let stats;
|
|
38395
38487
|
try {
|
|
38396
38488
|
stats = await stat12(pluginDir);
|
|
@@ -38405,7 +38497,7 @@ var PluginFileWatcher = class {
|
|
|
38405
38497
|
this.#reconcile(loaded);
|
|
38406
38498
|
}
|
|
38407
38499
|
async #loadPlugin(id, pluginDir) {
|
|
38408
|
-
const manifestPath =
|
|
38500
|
+
const manifestPath = join38(pluginDir, "plugin.json");
|
|
38409
38501
|
let manifestRaw;
|
|
38410
38502
|
try {
|
|
38411
38503
|
manifestRaw = await readFile22(manifestPath, "utf-8");
|
|
@@ -38442,7 +38534,7 @@ var PluginFileWatcher = class {
|
|
|
38442
38534
|
return null;
|
|
38443
38535
|
}
|
|
38444
38536
|
let template = "";
|
|
38445
|
-
const templatePath =
|
|
38537
|
+
const templatePath = join38(pluginDir, "template.html");
|
|
38446
38538
|
try {
|
|
38447
38539
|
template = await readFile22(templatePath, "utf-8");
|
|
38448
38540
|
} catch {
|
|
@@ -38457,7 +38549,7 @@ var PluginFileWatcher = class {
|
|
|
38457
38549
|
};
|
|
38458
38550
|
}
|
|
38459
38551
|
async #loadAndRegisterHandler(id, pluginDir, title, manifest) {
|
|
38460
|
-
const handlerPath =
|
|
38552
|
+
const handlerPath = join38(pluginDir, "handler.mjs");
|
|
38461
38553
|
const loaded = await this.#resolveHandler(id, handlerPath);
|
|
38462
38554
|
const { handlerFn, provideResourcesFn } = loaded;
|
|
38463
38555
|
if (manifest.provideResources && provideResourcesFn && this.#config.resourceResolver) {
|
|
@@ -38615,7 +38707,7 @@ async function findNativeDependencyMarker(pluginDir) {
|
|
|
38615
38707
|
}
|
|
38616
38708
|
async function scanNativeDependencyDir(dir, stack) {
|
|
38617
38709
|
for (const entry of await readNativeScanEntries(dir)) {
|
|
38618
|
-
const fullPath =
|
|
38710
|
+
const fullPath = join38(dir, entry.name);
|
|
38619
38711
|
if (isNativeDependencyMarker(entry, dir)) return fullPath;
|
|
38620
38712
|
if (shouldDescendForNativeScan(entry)) stack.push(fullPath);
|
|
38621
38713
|
}
|
|
@@ -38640,7 +38732,7 @@ function isNodeBuildReleaseDir(dir) {
|
|
|
38640
38732
|
|
|
38641
38733
|
// src/services/port-detection.ts
|
|
38642
38734
|
import { existsSync as existsSync6, readFileSync as readFileSync5 } from "fs";
|
|
38643
|
-
import { dirname as dirname19, join as
|
|
38735
|
+
import { dirname as dirname19, join as join39 } from "path";
|
|
38644
38736
|
var LSOF_TIMEOUT_MS = 8e3;
|
|
38645
38737
|
var LSOF_TTL_MS = 5e3;
|
|
38646
38738
|
var DEFAULT_POLL_INTERVAL_MS = 5e3;
|
|
@@ -38823,7 +38915,7 @@ function hasStringName(val) {
|
|
|
38823
38915
|
function resolveProjectRoot(cwd) {
|
|
38824
38916
|
let dir = cwd;
|
|
38825
38917
|
while (true) {
|
|
38826
|
-
const candidate =
|
|
38918
|
+
const candidate = join39(dir, "package.json");
|
|
38827
38919
|
if (existsSync6(candidate)) {
|
|
38828
38920
|
let packageName;
|
|
38829
38921
|
try {
|
|
@@ -38947,7 +39039,7 @@ import {
|
|
|
38947
39039
|
unlinkSync as unlinkSync2,
|
|
38948
39040
|
writeFileSync as writeFileSync2
|
|
38949
39041
|
} from "fs";
|
|
38950
|
-
import { join as
|
|
39042
|
+
import { join as join40 } from "path";
|
|
38951
39043
|
function isEnoent6(err3) {
|
|
38952
39044
|
return err3 instanceof Error && Reflect.get(err3, "code") === "ENOENT";
|
|
38953
39045
|
}
|
|
@@ -38957,7 +39049,7 @@ function atomicWriteSync(filePath, content) {
|
|
|
38957
39049
|
renameSync(tmpPath, filePath);
|
|
38958
39050
|
}
|
|
38959
39051
|
function recordFilePath2(rootDir, taskId, elementId) {
|
|
38960
|
-
return
|
|
39052
|
+
return join40(rootDir, taskId, `${elementId}.json`);
|
|
38961
39053
|
}
|
|
38962
39054
|
function parseRecord2(filePath, logger2) {
|
|
38963
39055
|
let raw;
|
|
@@ -38997,7 +39089,7 @@ function createPreviewStateStore(opts) {
|
|
|
38997
39089
|
return taskMap;
|
|
38998
39090
|
}
|
|
38999
39091
|
function scanTaskDir(taskId) {
|
|
39000
|
-
const taskPath =
|
|
39092
|
+
const taskPath = join40(rootDir, taskId);
|
|
39001
39093
|
let files;
|
|
39002
39094
|
try {
|
|
39003
39095
|
files = readdirSync4(taskPath);
|
|
@@ -39006,7 +39098,7 @@ function createPreviewStateStore(opts) {
|
|
|
39006
39098
|
}
|
|
39007
39099
|
for (const file of files) {
|
|
39008
39100
|
if (!file.endsWith(".json")) continue;
|
|
39009
|
-
const record = parseRecord2(
|
|
39101
|
+
const record = parseRecord2(join40(taskPath, file), logger2);
|
|
39010
39102
|
if (record) getTaskMap(taskId).set(record.elementId, record);
|
|
39011
39103
|
}
|
|
39012
39104
|
}
|
|
@@ -39032,7 +39124,7 @@ function createPreviewStateStore(opts) {
|
|
|
39032
39124
|
function writeToDisk(taskId, state) {
|
|
39033
39125
|
const filePath = recordFilePath2(rootDir, taskId, state.elementId);
|
|
39034
39126
|
try {
|
|
39035
|
-
mkdirSync3(
|
|
39127
|
+
mkdirSync3(join40(rootDir, taskId), { recursive: true });
|
|
39036
39128
|
atomicWriteSync(filePath, JSON.stringify(state));
|
|
39037
39129
|
} catch (err3) {
|
|
39038
39130
|
logger2.warn(
|
|
@@ -41373,7 +41465,7 @@ function wireThreadErrorFallback(daemon, dc, taskId, threadId, channelId, log) {
|
|
|
41373
41465
|
}
|
|
41374
41466
|
|
|
41375
41467
|
// src/services/terminal-handler.ts
|
|
41376
|
-
import { join as
|
|
41468
|
+
import { join as join41 } from "path";
|
|
41377
41469
|
|
|
41378
41470
|
// src/shared/pty-manager.ts
|
|
41379
41471
|
import { accessSync, chmodSync, constants as constants2, createWriteStream } from "fs";
|
|
@@ -41654,7 +41746,7 @@ function createPtyManager() {
|
|
|
41654
41746
|
// src/services/terminal-handler.ts
|
|
41655
41747
|
var MAX_PTYS_DEFAULT = 20;
|
|
41656
41748
|
function terminalLogPathFor(dir, terminalId) {
|
|
41657
|
-
return
|
|
41749
|
+
return join41(dir, `${terminalId}.log`);
|
|
41658
41750
|
}
|
|
41659
41751
|
function handleTerminalChannel(taskId, terminalId, cwd, send, log, deps) {
|
|
41660
41752
|
const maxPtys = deps.maxPtys ?? MAX_PTYS_DEFAULT;
|
|
@@ -42264,7 +42356,7 @@ function buildCollabRoomManager(deps) {
|
|
|
42264
42356
|
// src/services/serve-factory.ts
|
|
42265
42357
|
import { randomUUID as randomUUID25 } from "crypto";
|
|
42266
42358
|
import { mkdir as mkdir36 } from "fs/promises";
|
|
42267
|
-
import { join as
|
|
42359
|
+
import { join as join79 } from "path";
|
|
42268
42360
|
|
|
42269
42361
|
// src/shared/capabilities/cursor-boot-auth.ts
|
|
42270
42362
|
async function mergeCursorAuthFromVault(caps, detect, log) {
|
|
@@ -42305,12 +42397,12 @@ async function mergeCursorAuthFromVault(caps, detect, log) {
|
|
|
42305
42397
|
|
|
42306
42398
|
// src/shared/capabilities/cursor-hook-shim-path.ts
|
|
42307
42399
|
import { statSync as statSync3 } from "fs";
|
|
42308
|
-
import { join as
|
|
42400
|
+
import { join as join42 } from "path";
|
|
42309
42401
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
42310
42402
|
function getCursorHookShimPath() {
|
|
42311
42403
|
const resourcesPath = Reflect.get(process, "resourcesPath");
|
|
42312
42404
|
if (typeof resourcesPath === "string" && resourcesPath.length > 0) {
|
|
42313
|
-
return
|
|
42405
|
+
return join42(resourcesPath, "daemon", "cursor-hook-shim.js");
|
|
42314
42406
|
}
|
|
42315
42407
|
return fileURLToPath2(new URL("./cursor-hook-shim.js", import.meta.url));
|
|
42316
42408
|
}
|
|
@@ -42545,7 +42637,7 @@ function resolveRuntimeAuthIdentity(runtimeAuth, runtimeId) {
|
|
|
42545
42637
|
// src/shared/capabilities/spinner-verbs-reader.ts
|
|
42546
42638
|
import { readFile as readFile23 } from "fs/promises";
|
|
42547
42639
|
import { homedir as homedir5 } from "os";
|
|
42548
|
-
import { join as
|
|
42640
|
+
import { join as join43 } from "path";
|
|
42549
42641
|
var ClaudeSpinnerVerbsSchema = external_exports.object({
|
|
42550
42642
|
mode: external_exports.enum(["append", "replace"]),
|
|
42551
42643
|
verbs: external_exports.array(external_exports.string())
|
|
@@ -42570,8 +42662,8 @@ function toPersistedVerbs(resolved, defaults2) {
|
|
|
42570
42662
|
return resolved.every((v2, i) => v2 === defaults2[i]) ? [] : [...resolved];
|
|
42571
42663
|
}
|
|
42572
42664
|
async function readSpinnerVerbs() {
|
|
42573
|
-
const claudeDir =
|
|
42574
|
-
const paths = [
|
|
42665
|
+
const claudeDir = join43(homedir5(), ".claude");
|
|
42666
|
+
const paths = [join43(claudeDir, "settings.json"), join43(claudeDir, "settings.local.json")];
|
|
42575
42667
|
const parsed = await Promise.all(
|
|
42576
42668
|
paths.map(async (p2) => {
|
|
42577
42669
|
try {
|
|
@@ -42613,7 +42705,7 @@ async function reimportSpinnerVerbs(store, log) {
|
|
|
42613
42705
|
|
|
42614
42706
|
// src/shared/mcp/oauth-state-store.ts
|
|
42615
42707
|
import { readFile as readFile24 } from "fs/promises";
|
|
42616
|
-
import { join as
|
|
42708
|
+
import { join as join44 } from "path";
|
|
42617
42709
|
import {
|
|
42618
42710
|
OAuthClientInformationFullSchema as OAuthClientInformationFullSchema2,
|
|
42619
42711
|
OAuthClientInformationSchema as OAuthClientInformationSchema2,
|
|
@@ -42659,7 +42751,7 @@ var MCPOAuthStateStore = class {
|
|
|
42659
42751
|
this.#shipyardHome = shipyardHome;
|
|
42660
42752
|
}
|
|
42661
42753
|
#filePath() {
|
|
42662
|
-
return
|
|
42754
|
+
return join44(this.#shipyardHome, STATE_FILE);
|
|
42663
42755
|
}
|
|
42664
42756
|
#lockPath() {
|
|
42665
42757
|
return `${this.#filePath()}.lock`;
|
|
@@ -42758,11 +42850,11 @@ function getShipyardSubagentCatalog() {
|
|
|
42758
42850
|
|
|
42759
42851
|
// src/services/bootstrap/rehydrate.ts
|
|
42760
42852
|
import { readFile as readFile26, rename as rename16, writeFile as writeFile18 } from "fs/promises";
|
|
42761
|
-
import { join as
|
|
42853
|
+
import { join as join46 } from "path";
|
|
42762
42854
|
|
|
42763
42855
|
// src/services/collab/collab-queue-persistence.ts
|
|
42764
42856
|
import { appendFile as appendFile2, mkdir as mkdir16, readdir as readdir16, readFile as readFile25, rename as rename15, rm as rm9, writeFile as writeFile17 } from "fs/promises";
|
|
42765
|
-
import { join as
|
|
42857
|
+
import { join as join45 } from "path";
|
|
42766
42858
|
var PersistedQueueEntrySchema = external_exports.object({
|
|
42767
42859
|
content: external_exports.array(ContentBlockSchema),
|
|
42768
42860
|
settings: DaemonSettingsSchema.optional(),
|
|
@@ -42786,9 +42878,9 @@ function parsePersistedLine(line) {
|
|
|
42786
42878
|
};
|
|
42787
42879
|
}
|
|
42788
42880
|
function buildCollabQueuePersistence(dataDir) {
|
|
42789
|
-
const queuesDir =
|
|
42881
|
+
const queuesDir = join45(dataDir, "collab-queues");
|
|
42790
42882
|
function queuePath(queueKey) {
|
|
42791
|
-
return
|
|
42883
|
+
return join45(queuesDir, `${queueKey}.jsonl`);
|
|
42792
42884
|
}
|
|
42793
42885
|
async function ensureDir() {
|
|
42794
42886
|
await mkdir16(queuesDir, { recursive: true });
|
|
@@ -42881,7 +42973,7 @@ function buildCollabQueuePersistence(dataDir) {
|
|
|
42881
42973
|
}
|
|
42882
42974
|
for (const name of names) {
|
|
42883
42975
|
if (!name.includes(".tmp-")) continue;
|
|
42884
|
-
await rm9(
|
|
42976
|
+
await rm9(join45(queuesDir, name), { force: true }).catch(() => {
|
|
42885
42977
|
});
|
|
42886
42978
|
}
|
|
42887
42979
|
}
|
|
@@ -43200,7 +43292,7 @@ async function stripPinnedFieldFromTasksFile(tasksPath, envelope, records) {
|
|
|
43200
43292
|
}
|
|
43201
43293
|
}
|
|
43202
43294
|
async function migratePinnedToFavoriteTasks(dataDir, userSettingsStore, log) {
|
|
43203
|
-
const tasksPath =
|
|
43295
|
+
const tasksPath = join46(dataDir, "tasks.json");
|
|
43204
43296
|
const parsed = await readRawTasksEnvelope(tasksPath);
|
|
43205
43297
|
if (!parsed) return;
|
|
43206
43298
|
const { records, envelope, fromMigrated } = parsed;
|
|
@@ -43316,7 +43408,7 @@ async function sweepStaleTasks(taskStateStore, taskManager, log) {
|
|
|
43316
43408
|
|
|
43317
43409
|
// src/services/bootstrap/update-status.ts
|
|
43318
43410
|
import { readFile as readFile27, unlink as unlink11 } from "fs/promises";
|
|
43319
|
-
import { join as
|
|
43411
|
+
import { join as join47 } from "path";
|
|
43320
43412
|
var UPDATE_STATUS_FILENAME = "update-status.json";
|
|
43321
43413
|
var RAW_LOG_MAX_CHARS = 500;
|
|
43322
43414
|
var UpdateStatusSchema = external_exports.object({
|
|
@@ -43329,7 +43421,7 @@ var UpdateStatusSchema = external_exports.object({
|
|
|
43329
43421
|
rolledBack: external_exports.boolean()
|
|
43330
43422
|
});
|
|
43331
43423
|
async function readAndClearUpdateStatus(shipyardHome, log) {
|
|
43332
|
-
const path5 =
|
|
43424
|
+
const path5 = join47(shipyardHome, UPDATE_STATUS_FILENAME);
|
|
43333
43425
|
let raw;
|
|
43334
43426
|
try {
|
|
43335
43427
|
raw = await readFile27(path5, "utf-8");
|
|
@@ -43416,11 +43508,11 @@ function wireUpdateStatusForwarding(report, sink2, onMessage, log) {
|
|
|
43416
43508
|
|
|
43417
43509
|
// src/services/bootstrap/updates-cleanup.ts
|
|
43418
43510
|
import { readdir as readdir17, rm as rm10, stat as stat14, unlink as unlink13 } from "fs/promises";
|
|
43419
|
-
import { join as
|
|
43511
|
+
import { join as join49 } from "path";
|
|
43420
43512
|
|
|
43421
43513
|
// src/services/bootstrap/self-update-lock.ts
|
|
43422
43514
|
import { mkdir as mkdir17, readFile as readFile28, stat as stat13, unlink as unlink12, writeFile as writeFile19 } from "fs/promises";
|
|
43423
|
-
import { dirname as dirname21, join as
|
|
43515
|
+
import { dirname as dirname21, join as join48 } from "path";
|
|
43424
43516
|
var LOCK_FILENAME = ".lock";
|
|
43425
43517
|
var STALE_LOCK_MS = 10 * 60 * 1e3;
|
|
43426
43518
|
var LockFileSchema = external_exports.object({
|
|
@@ -43428,7 +43520,7 @@ var LockFileSchema = external_exports.object({
|
|
|
43428
43520
|
startedAt: external_exports.number()
|
|
43429
43521
|
});
|
|
43430
43522
|
function lockPath(shipyardHome) {
|
|
43431
|
-
return
|
|
43523
|
+
return join48(shipyardHome, "updates", LOCK_FILENAME);
|
|
43432
43524
|
}
|
|
43433
43525
|
function isStaleLock(lock, now, isProcessAlive2) {
|
|
43434
43526
|
const age = now - lock.startedAt;
|
|
@@ -43551,7 +43643,7 @@ async function cleanupUpdatesDir(shipyardHome, deps = {}) {
|
|
|
43551
43643
|
const now = deps.now ?? Date.now;
|
|
43552
43644
|
const isProcessAlive2 = deps.isProcessAlive ?? defaultIsProcessAlive;
|
|
43553
43645
|
const log = deps.log;
|
|
43554
|
-
const updatesDir =
|
|
43646
|
+
const updatesDir = join49(shipyardHome, "updates");
|
|
43555
43647
|
const empty2 = {
|
|
43556
43648
|
tarballsKept: [],
|
|
43557
43649
|
tarballsDeleted: [],
|
|
@@ -43675,7 +43767,7 @@ async function sortByMtimeDesc(baseDir, names, log) {
|
|
|
43675
43767
|
const rows = [];
|
|
43676
43768
|
for (const name of names) {
|
|
43677
43769
|
try {
|
|
43678
|
-
const s2 = await stat14(
|
|
43770
|
+
const s2 = await stat14(join49(baseDir, name));
|
|
43679
43771
|
rows.push({ name, mtimeMs: s2.mtimeMs });
|
|
43680
43772
|
} catch (err3) {
|
|
43681
43773
|
log?.info({ err: err3, entry: name }, "updates cleanup: stat failed, skipping entry");
|
|
@@ -43688,7 +43780,7 @@ async function filterOlderThan(baseDir, names, nowMs, thresholdMs, log) {
|
|
|
43688
43780
|
const out = [];
|
|
43689
43781
|
for (const name of names) {
|
|
43690
43782
|
try {
|
|
43691
|
-
const s2 = await stat14(
|
|
43783
|
+
const s2 = await stat14(join49(baseDir, name));
|
|
43692
43784
|
if (nowMs - s2.mtimeMs > thresholdMs) {
|
|
43693
43785
|
out.push(name);
|
|
43694
43786
|
}
|
|
@@ -43702,7 +43794,7 @@ async function deleteFiles(baseDir, names, log) {
|
|
|
43702
43794
|
const deleted = [];
|
|
43703
43795
|
for (const name of names) {
|
|
43704
43796
|
try {
|
|
43705
|
-
await unlink13(
|
|
43797
|
+
await unlink13(join49(baseDir, name));
|
|
43706
43798
|
deleted.push(name);
|
|
43707
43799
|
} catch (err3) {
|
|
43708
43800
|
if (isEnoent(err3)) {
|
|
@@ -43718,7 +43810,7 @@ async function deleteDirs(baseDir, names, log) {
|
|
|
43718
43810
|
const deleted = [];
|
|
43719
43811
|
for (const name of names) {
|
|
43720
43812
|
try {
|
|
43721
|
-
await rm10(
|
|
43813
|
+
await rm10(join49(baseDir, name), { recursive: true, force: true });
|
|
43722
43814
|
deleted.push(name);
|
|
43723
43815
|
} catch (err3) {
|
|
43724
43816
|
log?.info({ err: err3, entry: name }, "updates cleanup: rm -rf failed");
|
|
@@ -43727,7 +43819,7 @@ async function deleteDirs(baseDir, names, log) {
|
|
|
43727
43819
|
return deleted;
|
|
43728
43820
|
}
|
|
43729
43821
|
async function maybeClearLock(shipyardHome, nowMs, isProcessAlive2, log) {
|
|
43730
|
-
const lockFilePath =
|
|
43822
|
+
const lockFilePath = join49(shipyardHome, "updates", LOCK_FILENAME);
|
|
43731
43823
|
const outcome = await readLockFileWithOutcome(shipyardHome);
|
|
43732
43824
|
switch (outcome.kind) {
|
|
43733
43825
|
case "absent":
|
|
@@ -45028,7 +45120,7 @@ function wireDevServersAndTerminalsResolvers(deps) {
|
|
|
45028
45120
|
|
|
45029
45121
|
// src/services/file-resource-resolver.ts
|
|
45030
45122
|
import { readFile as readFile29, stat as stat15 } from "fs/promises";
|
|
45031
|
-
import { basename as basename8, join as
|
|
45123
|
+
import { basename as basename8, join as join50, normalize as normalize4, sep as sep3 } from "path";
|
|
45032
45124
|
var MAX_FILE_SIZE = 10 * 1024 * 1024;
|
|
45033
45125
|
var MIME_BY_EXT2 = {
|
|
45034
45126
|
".ts": "text/typescript",
|
|
@@ -45097,7 +45189,7 @@ function createFileResourceResolver(deps) {
|
|
|
45097
45189
|
const { taskId, relativePath } = parseFileUri2(uri);
|
|
45098
45190
|
const cwd = deps.getTaskCwd(taskId) ?? deps.workspaceRoot;
|
|
45099
45191
|
const normalizedCwd = normalize4(cwd);
|
|
45100
|
-
const absolutePath = normalize4(
|
|
45192
|
+
const absolutePath = normalize4(join50(cwd, relativePath));
|
|
45101
45193
|
const cwdPrefix = normalizedCwd.endsWith(sep3) ? normalizedCwd : `${normalizedCwd}${sep3}`;
|
|
45102
45194
|
if (!absolutePath.startsWith(cwdPrefix) && absolutePath !== normalizedCwd) {
|
|
45103
45195
|
throw new Error(`Path traversal rejected: ${relativePath}`);
|
|
@@ -45142,10 +45234,30 @@ function createFileResourceResolver(deps) {
|
|
|
45142
45234
|
// src/services/harness/harness-server.ts
|
|
45143
45235
|
import { createSdkMcpServer } from "@anthropic-ai/claude-agent-sdk";
|
|
45144
45236
|
|
|
45237
|
+
// src/services/session/subprocess-epoch-registry.ts
|
|
45238
|
+
var subprocessEpochs = /* @__PURE__ */ new Map();
|
|
45239
|
+
function registerSubprocessEpoch(taskId, registry = subprocessEpochs) {
|
|
45240
|
+
const epoch = crypto.randomUUID();
|
|
45241
|
+
registry.set(taskId, epoch);
|
|
45242
|
+
return epoch;
|
|
45243
|
+
}
|
|
45244
|
+
function setSubprocessEpoch(taskId, epoch, registry = subprocessEpochs) {
|
|
45245
|
+
registry.set(taskId, epoch);
|
|
45246
|
+
}
|
|
45247
|
+
function currentSubprocessEpoch(taskId, registry = subprocessEpochs) {
|
|
45248
|
+
return registry.get(taskId);
|
|
45249
|
+
}
|
|
45250
|
+
function isLiveSubprocessEpoch(taskId, epoch, registry = subprocessEpochs) {
|
|
45251
|
+
return registry.get(taskId) === epoch;
|
|
45252
|
+
}
|
|
45253
|
+
function unregisterSubprocessEpoch(taskId, registry = subprocessEpochs) {
|
|
45254
|
+
registry.delete(taskId);
|
|
45255
|
+
}
|
|
45256
|
+
|
|
45145
45257
|
// src/services/harness/deliverable-server.ts
|
|
45146
45258
|
import { randomUUID as randomUUID12 } from "crypto";
|
|
45147
45259
|
import { copyFile, rm as fsRm, stat as fsStat3, mkdir as mkdir18 } from "fs/promises";
|
|
45148
|
-
import { basename as basename9, extname as extname2, join as
|
|
45260
|
+
import { basename as basename9, extname as extname2, join as join51, resolve as resolve8, sep as sep4 } from "path";
|
|
45149
45261
|
var TOOL_DESCRIPTION2 = [
|
|
45150
45262
|
"Register a proof-of-work deliverable for this task. Call this after producing an artifact (screenshot, video, log, markdown document, AX tree, DOM snapshot) so reviewers can see verifiable evidence of what the agent produced.",
|
|
45151
45263
|
"",
|
|
@@ -45205,7 +45317,7 @@ var RegisterDeliverableInput = {
|
|
|
45205
45317
|
};
|
|
45206
45318
|
var COPY_MAX_BYTES = 50 * 1024 * 1024;
|
|
45207
45319
|
function isInternedFile(dataDir, filePath) {
|
|
45208
|
-
const internBase = resolve8(
|
|
45320
|
+
const internBase = resolve8(join51(dataDir, "deliverable-files")) + sep4;
|
|
45209
45321
|
return resolve8(filePath).startsWith(internBase);
|
|
45210
45322
|
}
|
|
45211
45323
|
async function internDeliverableFile(deliverableId, taskId, filePath, storedSizeBytes, dataDir, prevInternedPath) {
|
|
@@ -45229,8 +45341,8 @@ async function internDeliverableFile(deliverableId, taskId, filePath, storedSize
|
|
|
45229
45341
|
};
|
|
45230
45342
|
}
|
|
45231
45343
|
const ext = extname2(filePath);
|
|
45232
|
-
const destDir =
|
|
45233
|
-
const destPath =
|
|
45344
|
+
const destDir = join51(dataDir, "deliverable-files", taskId);
|
|
45345
|
+
const destPath = join51(destDir, `${deliverableId}${ext}`);
|
|
45234
45346
|
try {
|
|
45235
45347
|
await mkdir18(destDir, { recursive: true });
|
|
45236
45348
|
await copyFile(filePath, destPath);
|
|
@@ -45656,7 +45768,7 @@ function createDeliverableTools(ctx) {
|
|
|
45656
45768
|
|
|
45657
45769
|
// src/services/harness/plugin-server.ts
|
|
45658
45770
|
import { mkdir as mkdir19, writeFile as writeFile20 } from "fs/promises";
|
|
45659
|
-
import { join as
|
|
45771
|
+
import { join as join52 } from "path";
|
|
45660
45772
|
|
|
45661
45773
|
// src/services/harness/sandbox-docs.ts
|
|
45662
45774
|
var SANDBOX_HTML_RULES = `## HTML Rules
|
|
@@ -46274,14 +46386,14 @@ ${addendum}`;
|
|
|
46274
46386
|
events: input.events,
|
|
46275
46387
|
provideResources: input.provideResources
|
|
46276
46388
|
});
|
|
46277
|
-
const pluginDir =
|
|
46389
|
+
const pluginDir = join52(ctx.pluginsDir, input.pluginId);
|
|
46278
46390
|
await mkdir19(pluginDir, { recursive: true });
|
|
46279
|
-
await writeFile20(
|
|
46391
|
+
await writeFile20(join52(pluginDir, "template.html"), input.template, "utf-8");
|
|
46280
46392
|
if (input.handler) {
|
|
46281
|
-
await writeFile20(
|
|
46393
|
+
await writeFile20(join52(pluginDir, "handler.mjs"), input.handler, "utf-8");
|
|
46282
46394
|
}
|
|
46283
46395
|
await writeFile20(
|
|
46284
|
-
|
|
46396
|
+
join52(pluginDir, "plugin.json"),
|
|
46285
46397
|
JSON.stringify(manifest, null, 2),
|
|
46286
46398
|
"utf-8"
|
|
46287
46399
|
);
|
|
@@ -56329,6 +56441,7 @@ var LSP_TOOL_NAMES = [
|
|
|
56329
56441
|
];
|
|
56330
56442
|
function buildHarnessTools(ctx) {
|
|
56331
56443
|
const taskIdRef = { current: ctx.taskId };
|
|
56444
|
+
const epochRef = { current: null };
|
|
56332
56445
|
const deliverableCtx = {
|
|
56333
56446
|
deliverableStore: ctx.deliverableStore,
|
|
56334
56447
|
taskId: taskIdRef,
|
|
@@ -56407,21 +56520,59 @@ function buildHarnessTools(ctx) {
|
|
|
56407
56520
|
const tool = builtByName.get(spec.name);
|
|
56408
56521
|
if (tool) tools.push(tool);
|
|
56409
56522
|
}
|
|
56523
|
+
function wrapWithEpochGate(tool) {
|
|
56524
|
+
const originalHandler = tool.handler;
|
|
56525
|
+
return {
|
|
56526
|
+
...tool,
|
|
56527
|
+
// biome-ignore lint/suspicious/noExplicitAny: args is typed per-tool by the generic; widening to any here matches the per-request HTTP path which also widened at the binding seam.
|
|
56528
|
+
handler: async (args, extra) => {
|
|
56529
|
+
const epoch = epochRef.current;
|
|
56530
|
+
if (epoch === null) {
|
|
56531
|
+
return originalHandler(args, extra);
|
|
56532
|
+
}
|
|
56533
|
+
if (!isLiveSubprocessEpoch(taskIdRef.current, epoch)) {
|
|
56534
|
+
ctx.log({
|
|
56535
|
+
event: "subprocess_epoch_mismatch",
|
|
56536
|
+
taskId: taskIdRef.current,
|
|
56537
|
+
bound: epoch,
|
|
56538
|
+
current: currentSubprocessEpoch(taskIdRef.current),
|
|
56539
|
+
runtime: "in-process",
|
|
56540
|
+
kind: "task",
|
|
56541
|
+
tool: tool.name
|
|
56542
|
+
});
|
|
56543
|
+
return {
|
|
56544
|
+
content: [
|
|
56545
|
+
{
|
|
56546
|
+
type: "text",
|
|
56547
|
+
text: "subprocess epoch mismatch: this runtime has been superseded"
|
|
56548
|
+
}
|
|
56549
|
+
],
|
|
56550
|
+
isError: true
|
|
56551
|
+
};
|
|
56552
|
+
}
|
|
56553
|
+
return originalHandler(args, extra);
|
|
56554
|
+
}
|
|
56555
|
+
};
|
|
56556
|
+
}
|
|
56557
|
+
const wrappedTools = tools.map(wrapWithEpochGate);
|
|
56410
56558
|
return {
|
|
56411
|
-
tools,
|
|
56559
|
+
tools: wrappedTools,
|
|
56412
56560
|
setTaskId: (taskId) => {
|
|
56413
56561
|
taskIdRef.current = taskId;
|
|
56562
|
+
},
|
|
56563
|
+
setEpoch: (epoch) => {
|
|
56564
|
+
epochRef.current = epoch;
|
|
56414
56565
|
}
|
|
56415
56566
|
};
|
|
56416
56567
|
}
|
|
56417
56568
|
function createHarnessMcpServer(ctx) {
|
|
56418
|
-
const { tools, setTaskId } = buildHarnessTools(ctx);
|
|
56569
|
+
const { tools, setTaskId, setEpoch } = buildHarnessTools(ctx);
|
|
56419
56570
|
const server = createSdkMcpServer({
|
|
56420
56571
|
name: HARNESS_SERVER_NAME,
|
|
56421
56572
|
version: "1.0.0",
|
|
56422
56573
|
tools
|
|
56423
56574
|
});
|
|
56424
|
-
return { server, setTaskId };
|
|
56575
|
+
return { server, setTaskId, setEpoch };
|
|
56425
56576
|
}
|
|
56426
56577
|
|
|
56427
56578
|
// src/services/harness/lsp-agent-client.ts
|
|
@@ -56433,7 +56584,7 @@ import { pathToFileURL as pathToFileURL3 } from "url";
|
|
|
56433
56584
|
// src/services/lsp/language-server-registry.ts
|
|
56434
56585
|
import { existsSync as existsSync7, readFileSync as readFileSync7 } from "fs";
|
|
56435
56586
|
import { createRequire as createRequire3 } from "module";
|
|
56436
|
-
import { dirname as dirname22, isAbsolute as isAbsolute4, join as
|
|
56587
|
+
import { dirname as dirname22, isAbsolute as isAbsolute4, join as join53 } from "path";
|
|
56437
56588
|
function decideTypescriptServer(d) {
|
|
56438
56589
|
if (d.hasAngular || d.hasNest || d.hasTsserverPlugins) return "vtsls";
|
|
56439
56590
|
return "tsgo";
|
|
@@ -56523,11 +56674,11 @@ function isRecord7(value) {
|
|
|
56523
56674
|
return typeof value === "object" && value !== null;
|
|
56524
56675
|
}
|
|
56525
56676
|
function gatherTsDetection(cwd, deps) {
|
|
56526
|
-
const pkg = deps.readJsonFile(
|
|
56677
|
+
const pkg = deps.readJsonFile(join53(cwd, "package.json"));
|
|
56527
56678
|
const depNames = isRecord7(pkg) ? [...keysOf(pkg.dependencies), ...keysOf(pkg.devDependencies)] : [];
|
|
56528
|
-
const hasAngular = depNames.includes("@angular/core") || deps.fileExists(
|
|
56529
|
-
const hasNest = depNames.includes("@nestjs/core") || deps.fileExists(
|
|
56530
|
-
const tsconfig = deps.readJsonFile(
|
|
56679
|
+
const hasAngular = depNames.includes("@angular/core") || deps.fileExists(join53(cwd, "angular.json"));
|
|
56680
|
+
const hasNest = depNames.includes("@nestjs/core") || deps.fileExists(join53(cwd, "nest-cli.json"));
|
|
56681
|
+
const tsconfig = deps.readJsonFile(join53(cwd, "tsconfig.json"));
|
|
56531
56682
|
const compilerOptions = isRecord7(tsconfig) ? tsconfig.compilerOptions : void 0;
|
|
56532
56683
|
const plugins2 = isRecord7(compilerOptions) ? compilerOptions.plugins : void 0;
|
|
56533
56684
|
const hasTsserverPlugins = Array.isArray(plugins2) && plugins2.length > 0;
|
|
@@ -56542,11 +56693,11 @@ function detectPythonVenv(cwd, deps) {
|
|
|
56542
56693
|
if (envVenv && isAbsolute4(envVenv) && deps.fileExists(envVenv)) {
|
|
56543
56694
|
candidates.push(envVenv);
|
|
56544
56695
|
}
|
|
56545
|
-
candidates.push(
|
|
56696
|
+
candidates.push(join53(cwd, ".venv"), join53(cwd, "venv"));
|
|
56546
56697
|
const isWin = deps.platform === "win32";
|
|
56547
56698
|
for (const root of candidates) {
|
|
56548
|
-
const python = isWin ?
|
|
56549
|
-
const python3 = isWin ? python :
|
|
56699
|
+
const python = isWin ? join53(root, "Scripts", "python.exe") : join53(root, "bin", "python");
|
|
56700
|
+
const python3 = isWin ? python : join53(root, "bin", "python3");
|
|
56550
56701
|
if (deps.fileExists(python) || deps.fileExists(python3)) return root;
|
|
56551
56702
|
}
|
|
56552
56703
|
return null;
|
|
@@ -56579,8 +56730,8 @@ function resolveTsgoBinaryPath(req) {
|
|
|
56579
56730
|
`Unable to resolve ${platformPkg}: ${err3 instanceof Error ? err3.message : String(err3)}`
|
|
56580
56731
|
);
|
|
56581
56732
|
}
|
|
56582
|
-
const exeDir =
|
|
56583
|
-
const exe = process.platform === "win32" ?
|
|
56733
|
+
const exeDir = join53(dirname22(pkgJsonPath), "lib");
|
|
56734
|
+
const exe = process.platform === "win32" ? join53(exeDir, "tsgo.exe") : join53(exeDir, "tsgo");
|
|
56584
56735
|
if (!existsSync7(exe)) {
|
|
56585
56736
|
throw new Error(`tsgo native binary not found: ${exe}`);
|
|
56586
56737
|
}
|
|
@@ -56593,7 +56744,7 @@ function resolveBinViaPackageJson(pkg, binName, req) {
|
|
|
56593
56744
|
const named = isRecord7(binField) ? binField[binName] : void 0;
|
|
56594
56745
|
const bin = typeof binField === "string" ? binField : typeof named === "string" ? named : void 0;
|
|
56595
56746
|
if (!bin) throw new Error(`package '${pkg}' has no bin entry '${binName}'`);
|
|
56596
|
-
return
|
|
56747
|
+
return join53(dirname22(pkgJsonPath), bin);
|
|
56597
56748
|
}
|
|
56598
56749
|
function errorMessage3(err3) {
|
|
56599
56750
|
return err3 instanceof Error ? err3.message : String(err3);
|
|
@@ -59456,7 +59607,7 @@ import { execFile as execFileCb3 } from "child_process";
|
|
|
59456
59607
|
import { createHash as createHash3 } from "crypto";
|
|
59457
59608
|
import { readFile as readFile31 } from "fs/promises";
|
|
59458
59609
|
import { homedir as homedir6 } from "os";
|
|
59459
|
-
import { join as
|
|
59610
|
+
import { join as join54 } from "path";
|
|
59460
59611
|
import { promisify as promisify9 } from "util";
|
|
59461
59612
|
var execFile10 = promisify9(execFileCb3);
|
|
59462
59613
|
var CodexCredentialsEntrySchema = external_exports.object({
|
|
@@ -59517,10 +59668,10 @@ async function readKeychainStore() {
|
|
|
59517
59668
|
return null;
|
|
59518
59669
|
}
|
|
59519
59670
|
}
|
|
59520
|
-
async function readCodexMcpCredentials(serverName, serverUrl, codexHome =
|
|
59671
|
+
async function readCodexMcpCredentials(serverName, serverUrl, codexHome = join54(homedir6(), ".codex")) {
|
|
59521
59672
|
if (!serverUrl) return null;
|
|
59522
59673
|
try {
|
|
59523
|
-
const raw = await readFile31(
|
|
59674
|
+
const raw = await readFile31(join54(codexHome, FALLBACK_FILENAME), "utf-8");
|
|
59524
59675
|
const fileResult = CodexCredentialsFileSchema.safeParse(JSON.parse(raw));
|
|
59525
59676
|
if (fileResult.success) {
|
|
59526
59677
|
const entry = findEntry2(fileResult.data, serverName, serverUrl);
|
|
@@ -61717,7 +61868,7 @@ var HealthMetrics = class {
|
|
|
61717
61868
|
// src/services/metrics/stall-profiler.ts
|
|
61718
61869
|
import { mkdir as mkdir20, readdir as readdir18, unlink as unlink14, writeFile as writeFile21 } from "fs/promises";
|
|
61719
61870
|
import { Session as Session2 } from "inspector/promises";
|
|
61720
|
-
import { join as
|
|
61871
|
+
import { join as join55 } from "path";
|
|
61721
61872
|
import { monitorEventLoopDelay as monitorEventLoopDelay3 } from "perf_hooks";
|
|
61722
61873
|
function hasProfile2(value) {
|
|
61723
61874
|
return typeof value === "object" && value !== null && "profile" in value;
|
|
@@ -61827,7 +61978,7 @@ var StallProfiler = class {
|
|
|
61827
61978
|
const isoTs = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
61828
61979
|
const stallRounded = Math.round(stallMs);
|
|
61829
61980
|
const filename = `stall-${isoTs}-${stallRounded}ms.cpuprofile`;
|
|
61830
|
-
const profilePath =
|
|
61981
|
+
const profilePath = join55(this.#outDir, filename);
|
|
61831
61982
|
await mkdir20(this.#outDir, { recursive: true });
|
|
61832
61983
|
await writeFile21(profilePath, JSON.stringify(stopResult.profile));
|
|
61833
61984
|
this.#log({
|
|
@@ -61861,7 +62012,7 @@ var StallProfiler = class {
|
|
|
61861
62012
|
const entries = await readdir18(this.#outDir);
|
|
61862
62013
|
const toDelete = planProfileEviction(entries, this.#maxProfiles, STALL_PROFILE_PREFIX);
|
|
61863
62014
|
if (toDelete.length === 0) return;
|
|
61864
|
-
const results = await Promise.allSettled(toDelete.map((f2) => unlink14(
|
|
62015
|
+
const results = await Promise.allSettled(toDelete.map((f2) => unlink14(join55(this.#outDir, f2))));
|
|
61865
62016
|
const failures = results.filter((r) => r.status === "rejected").length;
|
|
61866
62017
|
if (failures > 0) {
|
|
61867
62018
|
this.#log({
|
|
@@ -62920,7 +63071,7 @@ function joinPoint(doc2, pos, dir = -1) {
|
|
|
62920
63071
|
pos = dir < 0 ? $pos.before(d) : $pos.after(d);
|
|
62921
63072
|
}
|
|
62922
63073
|
}
|
|
62923
|
-
function
|
|
63074
|
+
function join56(tr2, pos, depth) {
|
|
62924
63075
|
let convertNewlines = null;
|
|
62925
63076
|
let { linebreakReplacement } = tr2.doc.type.schema;
|
|
62926
63077
|
let $before = tr2.doc.resolve(pos - depth), beforeType = $before.node().type;
|
|
@@ -63606,7 +63757,7 @@ var Transform = class {
|
|
|
63606
63757
|
last and first siblings are also joined, and so on.
|
|
63607
63758
|
*/
|
|
63608
63759
|
join(pos, depth = 1) {
|
|
63609
|
-
|
|
63760
|
+
join56(this, pos, depth);
|
|
63610
63761
|
return this;
|
|
63611
63762
|
}
|
|
63612
63763
|
/**
|
|
@@ -84019,6 +84170,14 @@ var PreWarmManager = class {
|
|
|
84019
84170
|
#subprocess = null;
|
|
84020
84171
|
#cwd = null;
|
|
84021
84172
|
#generation = 0;
|
|
84173
|
+
/**
|
|
84174
|
+
* The harness-bound epoch captured from `subprocess.harnessEpoch` after the
|
|
84175
|
+
* spawn dispatcher minted+bound it (NOT minted here). Surfaced on
|
|
84176
|
+
* `PreWarmClaim` so the adopting Thread registers the SAME epoch the harness
|
|
84177
|
+
* fence checks (AGENTS.md Invariant #2b). Reset to `null` on
|
|
84178
|
+
* `#teardown()` / `dispose()`.
|
|
84179
|
+
*/
|
|
84180
|
+
#epoch = null;
|
|
84022
84181
|
#disposed = false;
|
|
84023
84182
|
/** Per-spawn event slot — each spawn gets its own, never shared. */
|
|
84024
84183
|
#eventSlot = null;
|
|
@@ -84238,6 +84397,13 @@ var PreWarmManager = class {
|
|
|
84238
84397
|
this.#subprocess = null;
|
|
84239
84398
|
this.#eventSlot = null;
|
|
84240
84399
|
this.#canUseToolSlot = null;
|
|
84400
|
+
if (this.#epoch === null) {
|
|
84401
|
+
throw new Error(
|
|
84402
|
+
`PreWarmManager.claim() invariant violated: warm subprocess has no harness epoch (status=${this.#status}, cwd=${cwd})`
|
|
84403
|
+
);
|
|
84404
|
+
}
|
|
84405
|
+
const epoch = this.#epoch;
|
|
84406
|
+
this.#epoch = null;
|
|
84241
84407
|
this.#deps.log({ event: "prewarm_claimed", cwd });
|
|
84242
84408
|
return {
|
|
84243
84409
|
subprocess,
|
|
@@ -84246,7 +84412,8 @@ var PreWarmManager = class {
|
|
|
84246
84412
|
},
|
|
84247
84413
|
redirectCanUseTool: (handler) => {
|
|
84248
84414
|
canUseToolSlot.current = handler;
|
|
84249
|
-
}
|
|
84415
|
+
},
|
|
84416
|
+
epoch
|
|
84250
84417
|
};
|
|
84251
84418
|
}
|
|
84252
84419
|
kill() {
|
|
@@ -84276,6 +84443,7 @@ var PreWarmManager = class {
|
|
|
84276
84443
|
return;
|
|
84277
84444
|
}
|
|
84278
84445
|
const generation = ++this.#generation;
|
|
84446
|
+
this.#epoch = null;
|
|
84279
84447
|
this.#cwd = cwd;
|
|
84280
84448
|
this.#status = "spawning";
|
|
84281
84449
|
const slot = createEventSlot();
|
|
@@ -84313,6 +84481,7 @@ var PreWarmManager = class {
|
|
|
84313
84481
|
settings,
|
|
84314
84482
|
cwd
|
|
84315
84483
|
);
|
|
84484
|
+
this.#epoch = this.#subprocess.harnessEpoch;
|
|
84316
84485
|
emitStep("spawn_call", performance.now() - tSpawnCall);
|
|
84317
84486
|
this.#startWarmTimer(generation);
|
|
84318
84487
|
}
|
|
@@ -84342,6 +84511,7 @@ var PreWarmManager = class {
|
|
|
84342
84511
|
}
|
|
84343
84512
|
this.#status = "idle";
|
|
84344
84513
|
this.#cwd = null;
|
|
84514
|
+
this.#epoch = null;
|
|
84345
84515
|
}
|
|
84346
84516
|
/** ---------------------------------------------------------------- */
|
|
84347
84517
|
/** Private: own event handler (during pre-warm phase) */
|
|
@@ -91093,6 +91263,16 @@ var CodexAgentSubprocess = class _CodexAgentSubprocess {
|
|
|
91093
91263
|
...opts.spawnArgs.stripEnv !== void 0 ? { stripEnv: opts.spawnArgs.stripEnv } : {}
|
|
91094
91264
|
};
|
|
91095
91265
|
const initializeResponse = await client.connect(connectArgs);
|
|
91266
|
+
const tracker = opts.pidTracker;
|
|
91267
|
+
if (tracker !== void 0) {
|
|
91268
|
+
const pid = client.transport.pid;
|
|
91269
|
+
if (pid !== void 0) {
|
|
91270
|
+
void tracker.add(pid);
|
|
91271
|
+
client.transport.once("close", () => {
|
|
91272
|
+
void tracker.remove(pid);
|
|
91273
|
+
});
|
|
91274
|
+
}
|
|
91275
|
+
}
|
|
91096
91276
|
const compat = classifyCodexAppServerCompatibility(initializeResponse.userAgent);
|
|
91097
91277
|
opts.log({
|
|
91098
91278
|
event: "codex_app_server_version",
|
|
@@ -91769,6 +91949,10 @@ var CodexAgentSubprocess = class _CodexAgentSubprocess {
|
|
|
91769
91949
|
reason: "Codex prewarm not supported; taskId is set at thread/start only."
|
|
91770
91950
|
});
|
|
91771
91951
|
}
|
|
91952
|
+
/** Codex fences its harness MCP via the HTTP `x-shipyard-generation` header / per-runner bearer, not an in-process epoch. */
|
|
91953
|
+
get harnessEpoch() {
|
|
91954
|
+
return null;
|
|
91955
|
+
}
|
|
91772
91956
|
setOnCwdChanged(handler) {
|
|
91773
91957
|
this.#cwdHandler = handler;
|
|
91774
91958
|
}
|
|
@@ -92286,6 +92470,10 @@ function createCodexSubprocessFacade(options, log) {
|
|
|
92286
92470
|
}
|
|
92287
92471
|
pending.push({ kind: "setHarnessTaskId", taskId });
|
|
92288
92472
|
},
|
|
92473
|
+
/** Codex fences via HTTP header / per-runner bearer — always null (delegated for forward-compat). */
|
|
92474
|
+
get harnessEpoch() {
|
|
92475
|
+
return inner ? inner.harnessEpoch : null;
|
|
92476
|
+
},
|
|
92289
92477
|
setOnCwdChanged(handler) {
|
|
92290
92478
|
cwdHandler = handler;
|
|
92291
92479
|
if (inner) {
|
|
@@ -92364,6 +92552,10 @@ function createCodexFacadeApiBuilder(d) {
|
|
|
92364
92552
|
reconnectMcpServer: (serverName) => codexFacadeReconnectMcpServer(state, serverName),
|
|
92365
92553
|
stopBackgroundTask: (taskId) => codexFacadeStopBackgroundTask(state, taskId),
|
|
92366
92554
|
setHarnessTaskId: (taskId) => codexFacadeSetHarnessTaskId(state, taskId),
|
|
92555
|
+
/** Codex fences its harness via HTTP header / per-runner bearer — delegate (always null today). */
|
|
92556
|
+
get harnessEpoch() {
|
|
92557
|
+
return state.inner?.harnessEpoch ?? null;
|
|
92558
|
+
},
|
|
92367
92559
|
setOnCwdChanged: (handler) => codexFacadeSetOnCwdChanged(state, handler),
|
|
92368
92560
|
getContextUsage: () => state.inner?.getContextUsage() ?? Promise.resolve(null),
|
|
92369
92561
|
restartWithExtendedSandbox: (grant) => codexFacadeRestartWithExtendedSandbox(state, grant),
|
|
@@ -92496,6 +92688,7 @@ import { randomUUID as randomUUID15 } from "crypto";
|
|
|
92496
92688
|
import { createServer as createServer4 } from "http";
|
|
92497
92689
|
import { McpServer as McpServer2 } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
92498
92690
|
import { StreamableHTTPServerTransport as StreamableHTTPServerTransport2 } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
92691
|
+
var SHIPYARD_GENERATION_HEADER = "x-shipyard-generation";
|
|
92499
92692
|
async function createHarnessHttpServer(opts = {}) {
|
|
92500
92693
|
const log = opts.log ?? (() => {
|
|
92501
92694
|
});
|
|
@@ -92576,6 +92769,29 @@ async function createHarnessHttpServer(opts = {}) {
|
|
|
92576
92769
|
await rejectAuth(req, res, 401, JSON_RPC_ERROR_UNAUTHORIZED, "unauthorized");
|
|
92577
92770
|
return null;
|
|
92578
92771
|
}
|
|
92772
|
+
const headerEpochRunner = req.headers[SHIPYARD_GENERATION_HEADER];
|
|
92773
|
+
if (typeof headerEpochRunner === "string" && headerEpochRunner.length > 0) {
|
|
92774
|
+
if (!isLiveSubprocessEpoch(runnerEntry.currentTaskId, headerEpochRunner)) {
|
|
92775
|
+
log({
|
|
92776
|
+
event: "subprocess_epoch_mismatch",
|
|
92777
|
+
taskId: runnerEntry.currentTaskId,
|
|
92778
|
+
/*
|
|
92779
|
+
* `bound` = the epoch the subprocess was given at spawn time
|
|
92780
|
+
* (here it arrived via the `x-shipyard-generation` header).
|
|
92781
|
+
* `current` = the live value the registry holds (the most recent
|
|
92782
|
+
* spawn's epoch). Same fields on the in-process path
|
|
92783
|
+
* (harness-server.ts) so log triage can query both
|
|
92784
|
+
* transports with one schema.
|
|
92785
|
+
*/
|
|
92786
|
+
bound: headerEpochRunner,
|
|
92787
|
+
current: currentSubprocessEpoch(runnerEntry.currentTaskId),
|
|
92788
|
+
runtime: "http",
|
|
92789
|
+
kind: "runner"
|
|
92790
|
+
});
|
|
92791
|
+
await respondError(req, res, 410, JSON_RPC_ERROR_GONE, "task_epoch_stale");
|
|
92792
|
+
return null;
|
|
92793
|
+
}
|
|
92794
|
+
}
|
|
92579
92795
|
return { entry: runnerEntry, scope: { kind: "runner", runnerId } };
|
|
92580
92796
|
}
|
|
92581
92797
|
async function resolveTaskEntry(token, req, res) {
|
|
@@ -92598,6 +92814,22 @@ async function createHarnessHttpServer(opts = {}) {
|
|
|
92598
92814
|
await rejectAuth(req, res, 401, JSON_RPC_ERROR_UNAUTHORIZED, "unauthorized");
|
|
92599
92815
|
return null;
|
|
92600
92816
|
}
|
|
92817
|
+
const headerEpoch = req.headers[SHIPYARD_GENERATION_HEADER];
|
|
92818
|
+
if (typeof headerEpoch === "string" && headerEpoch.length > 0) {
|
|
92819
|
+
if (!isLiveSubprocessEpoch(tokenTaskId, headerEpoch)) {
|
|
92820
|
+
log({
|
|
92821
|
+
event: "subprocess_epoch_mismatch",
|
|
92822
|
+
taskId: tokenTaskId,
|
|
92823
|
+
/** See `kind: 'runner'` block above for the bound vs current field semantics. */
|
|
92824
|
+
bound: headerEpoch,
|
|
92825
|
+
current: currentSubprocessEpoch(tokenTaskId),
|
|
92826
|
+
runtime: "http",
|
|
92827
|
+
kind: "task"
|
|
92828
|
+
});
|
|
92829
|
+
await respondError(req, res, 410, JSON_RPC_ERROR_GONE, "task_epoch_stale");
|
|
92830
|
+
return null;
|
|
92831
|
+
}
|
|
92832
|
+
}
|
|
92601
92833
|
return { entry, scope: { kind: "task", taskId: tokenTaskId } };
|
|
92602
92834
|
}
|
|
92603
92835
|
function logRequestEntry(req) {
|
|
@@ -92758,6 +92990,7 @@ var JSON_RPC_ERROR_INTERNAL = -32603;
|
|
|
92758
92990
|
var JSON_RPC_ERROR_UNAUTHORIZED = -32001;
|
|
92759
92991
|
var JSON_RPC_ERROR_FORBIDDEN = -32002;
|
|
92760
92992
|
var JSON_RPC_ERROR_NOT_FOUND = -32004;
|
|
92993
|
+
var JSON_RPC_ERROR_GONE = -32005;
|
|
92761
92994
|
async function respondError(req, res, status, code, message) {
|
|
92762
92995
|
sendJsonRpcHttpError(res, status, code, message, await readRequestId(req));
|
|
92763
92996
|
}
|
|
@@ -92855,6 +93088,16 @@ function compactionPrefsChanged(a, b2) {
|
|
|
92855
93088
|
}
|
|
92856
93089
|
|
|
92857
93090
|
// src/services/serve-factory/codex-facade.ts
|
|
93091
|
+
async function bailoutIfOuterClosed(state, input) {
|
|
93092
|
+
if (!state.outerClosed) return false;
|
|
93093
|
+
await input.harnessHttp.unregisterTask(input.args.taskId).catch(() => {
|
|
93094
|
+
});
|
|
93095
|
+
return true;
|
|
93096
|
+
}
|
|
93097
|
+
function pickPidTrackerForFacade(useSharedEngine, daemonPidTracker) {
|
|
93098
|
+
if (useSharedEngine) return void 0;
|
|
93099
|
+
return daemonPidTracker;
|
|
93100
|
+
}
|
|
92858
93101
|
function createCodexFacadeSubsystem(d) {
|
|
92859
93102
|
const { deps, taskManager, taskStateStore, store, userSettingsStore, proxyRef } = d;
|
|
92860
93103
|
const harnessHttpServer = d.harnessHttpServer;
|
|
@@ -92880,6 +93123,7 @@ function createCodexFacadeSubsystem(d) {
|
|
|
92880
93123
|
reasonKind: args.reason.kind,
|
|
92881
93124
|
resumeSessionId: args.reason.kind === "resume" ? args.reason.sessionId : null
|
|
92882
93125
|
});
|
|
93126
|
+
registerSubprocessEpoch(args.taskId);
|
|
92883
93127
|
return buildCodexOuterFacade({ args, harnessHttp: localHarnessHttp });
|
|
92884
93128
|
}
|
|
92885
93129
|
function buildCodexOuterFacade(input) {
|
|
@@ -93007,11 +93251,7 @@ function createCodexFacadeSubsystem(d) {
|
|
|
93007
93251
|
agentSystem: AGENT_SYSTEM_CODEX
|
|
93008
93252
|
})
|
|
93009
93253
|
);
|
|
93010
|
-
if (state
|
|
93011
|
-
await input.harnessHttp.unregisterTask(input.args.taskId).catch(() => {
|
|
93012
|
-
});
|
|
93013
|
-
return;
|
|
93014
|
-
}
|
|
93254
|
+
if (await bailoutIfOuterClosed(state, input)) return;
|
|
93015
93255
|
await verifyCodexHarnessRegistration({
|
|
93016
93256
|
taskId: input.args.taskId,
|
|
93017
93257
|
harnessUrl: `http://127.0.0.1:${input.harnessHttp.port}/mcp`,
|
|
@@ -93019,11 +93259,7 @@ function createCodexFacadeSubsystem(d) {
|
|
|
93019
93259
|
unregisterTask: (taskId) => input.harnessHttp.unregisterTask(taskId),
|
|
93020
93260
|
log: deps.log
|
|
93021
93261
|
});
|
|
93022
|
-
if (state
|
|
93023
|
-
await input.harnessHttp.unregisterTask(input.args.taskId).catch(() => {
|
|
93024
|
-
});
|
|
93025
|
-
return;
|
|
93026
|
-
}
|
|
93262
|
+
if (await bailoutIfOuterClosed(state, input)) return;
|
|
93027
93263
|
const stashRequestedPaths = (taskId, itemId, raw) => {
|
|
93028
93264
|
const grant = codexProfile.sandboxExtensionFlow?.parseRequestedPaths(raw) ?? null;
|
|
93029
93265
|
if (grant !== null) {
|
|
@@ -93250,6 +93486,7 @@ function createCodexFacadeSubsystem(d) {
|
|
|
93250
93486
|
});
|
|
93251
93487
|
const codexPendingNeutral = taskManager.getOrchestrator(input.args.taskId)?.consumePendingNeutralHandoff("codex") ?? void 0;
|
|
93252
93488
|
const useSharedEngine = validateEnv().SHIPYARD_CODEX_SHARED_ENGINE;
|
|
93489
|
+
const pidTrackerForFacade = pickPidTrackerForFacade(useSharedEngine, deps.pidTracker);
|
|
93253
93490
|
const facade = createCodexSubprocessFacade(
|
|
93254
93491
|
{
|
|
93255
93492
|
spawnArgs,
|
|
@@ -93354,7 +93591,8 @@ function createCodexFacadeSubsystem(d) {
|
|
|
93354
93591
|
workspaceMcpServers: input.args.workspaceMcpServers,
|
|
93355
93592
|
workspaceMcpProxyBridges
|
|
93356
93593
|
}),
|
|
93357
|
-
...deps.onCodexCapabilitiesDiscovered !== void 0 ? { onCodexCapabilitiesDiscovered: deps.onCodexCapabilitiesDiscovered } : {}
|
|
93594
|
+
...deps.onCodexCapabilitiesDiscovered !== void 0 ? { onCodexCapabilitiesDiscovered: deps.onCodexCapabilitiesDiscovered } : {},
|
|
93595
|
+
pidTracker: pidTrackerForFacade
|
|
93358
93596
|
},
|
|
93359
93597
|
deps.log
|
|
93360
93598
|
);
|
|
@@ -93432,12 +93670,12 @@ function handleTaskStoreBroadcast(deps, event) {
|
|
|
93432
93670
|
}
|
|
93433
93671
|
|
|
93434
93672
|
// src/services/serve-factory/viz-preview.ts
|
|
93435
|
-
import { join as
|
|
93673
|
+
import { join as join59 } from "path";
|
|
93436
93674
|
|
|
93437
93675
|
// src/services/harness/visualization-file-watcher.ts
|
|
93438
93676
|
import { randomUUID as randomUUID16 } from "crypto";
|
|
93439
93677
|
import { mkdir as mkdir21, readFile as readFile32, rename as rename17, writeFile as writeFile22 } from "fs/promises";
|
|
93440
|
-
import { basename as basename10, dirname as dirname23, join as
|
|
93678
|
+
import { basename as basename10, dirname as dirname23, join as join57 } from "path";
|
|
93441
93679
|
var PREVIEW_DEFAULT_W = 1200;
|
|
93442
93680
|
var PREVIEW_DEFAULT_H = 800;
|
|
93443
93681
|
function previewDataToLoroValue(data) {
|
|
@@ -93648,7 +93886,7 @@ var VisualizationFileWatcher = class {
|
|
|
93648
93886
|
}
|
|
93649
93887
|
case "persist_registry":
|
|
93650
93888
|
await atomicWrite2(
|
|
93651
|
-
|
|
93889
|
+
join57(this.#deps.vizDir, effect.taskId, "registry.json"),
|
|
93652
93890
|
JSON.stringify(effect.data, null, 2)
|
|
93653
93891
|
);
|
|
93654
93892
|
break;
|
|
@@ -93916,7 +94154,7 @@ var VisualizationFileWatcher = class {
|
|
|
93916
94154
|
|
|
93917
94155
|
// src/services/harness/visualization-registry.ts
|
|
93918
94156
|
import { createHash as createHash5 } from "crypto";
|
|
93919
|
-
import { join as
|
|
94157
|
+
import { join as join58 } from "path";
|
|
93920
94158
|
function hashContent(content) {
|
|
93921
94159
|
return createHash5("sha256").update(content).digest("hex");
|
|
93922
94160
|
}
|
|
@@ -93930,7 +94168,7 @@ var VisualizationRegistry = class {
|
|
|
93930
94168
|
return null;
|
|
93931
94169
|
}
|
|
93932
94170
|
const ext = vizFileExtension(vizType);
|
|
93933
|
-
const filePath =
|
|
94171
|
+
const filePath = join58(vizDir, taskId, `${slug}${ext}`);
|
|
93934
94172
|
const contentHash3 = hashContent(content);
|
|
93935
94173
|
const viz = {
|
|
93936
94174
|
slug,
|
|
@@ -94081,7 +94319,7 @@ var VisualizationRegistry = class {
|
|
|
94081
94319
|
// src/services/serve-factory/viz-preview.ts
|
|
94082
94320
|
function createVizPreviewRegistry(deps) {
|
|
94083
94321
|
const { canvasRepo } = deps;
|
|
94084
|
-
const vizDir =
|
|
94322
|
+
const vizDir = join59(deps.dataDir, "visualizations");
|
|
94085
94323
|
const vizWatchers = /* @__PURE__ */ new Map();
|
|
94086
94324
|
function getOrCreateVizWatcher(taskId) {
|
|
94087
94325
|
const existing = vizWatchers.get(taskId);
|
|
@@ -95837,6 +96075,11 @@ var CursorAgentSubprocess = class {
|
|
|
95837
96075
|
* unhealthy way (kill, do not pool). Null when no pooled close is in flight.
|
|
95838
96076
|
*/
|
|
95839
96077
|
#pooledIdleState = null;
|
|
96078
|
+
/**
|
|
96079
|
+
* Optional PID tracker — registers the forked runner PID on spawn and
|
|
96080
|
+
* removes it on exit so sweepOrphans can reap it if the daemon crashes.
|
|
96081
|
+
*/
|
|
96082
|
+
#pidTracker;
|
|
95840
96083
|
constructor(opts) {
|
|
95841
96084
|
this.#harnessTaskId = opts.taskId;
|
|
95842
96085
|
this.#cwd = opts.cwd;
|
|
@@ -95855,6 +96098,7 @@ var CursorAgentSubprocess = class {
|
|
|
95855
96098
|
this.#harnessRunnerId = opts.adoptChild?.runnerId ?? opts.harnessRunnerId ?? "";
|
|
95856
96099
|
this.#onReleaseToPool = opts.onReleaseToPool ?? null;
|
|
95857
96100
|
this.#onRunnerExited = opts.onRunnerExited;
|
|
96101
|
+
this.#pidTracker = opts.pidTracker ?? null;
|
|
95858
96102
|
this.#translatorCtx = createCursorTranslatorCtx(0);
|
|
95859
96103
|
this.#translatorCtx.collaborationMode = this.#collaborationMode;
|
|
95860
96104
|
this.#maybeLogFastModeApplied();
|
|
@@ -96285,6 +96529,10 @@ var CursorAgentSubprocess = class {
|
|
|
96285
96529
|
token: this.#harnessToken
|
|
96286
96530
|
});
|
|
96287
96531
|
}
|
|
96532
|
+
/** Cursor fences its harness MCP via the HTTP `x-shipyard-generation` header / per-runner bearer, not an in-process epoch. */
|
|
96533
|
+
get harnessEpoch() {
|
|
96534
|
+
return null;
|
|
96535
|
+
}
|
|
96288
96536
|
setOnCwdChanged(_handler) {
|
|
96289
96537
|
}
|
|
96290
96538
|
async rollback(_numTurns) {
|
|
@@ -96341,6 +96589,13 @@ var CursorAgentSubprocess = class {
|
|
|
96341
96589
|
env: buildNodeSpawnEnv(process.env)
|
|
96342
96590
|
});
|
|
96343
96591
|
this.#child = child;
|
|
96592
|
+
const tracker = this.#pidTracker;
|
|
96593
|
+
if (child.pid !== void 0 && tracker !== null) {
|
|
96594
|
+
void tracker.add(child.pid);
|
|
96595
|
+
child.once("exit", () => {
|
|
96596
|
+
if (child.pid !== void 0) void tracker.remove(child.pid);
|
|
96597
|
+
});
|
|
96598
|
+
}
|
|
96344
96599
|
attachCursorRunnerStdoutCapture(child, this.#harnessRunnerId);
|
|
96345
96600
|
attachCursorRunnerStderrCapture(child, this.#harnessRunnerId);
|
|
96346
96601
|
this.#attachChildListeners(child);
|
|
@@ -97545,7 +97800,7 @@ function createShipyardResolver() {
|
|
|
97545
97800
|
|
|
97546
97801
|
// src/services/stack-detection.ts
|
|
97547
97802
|
import { access as access6 } from "fs/promises";
|
|
97548
|
-
import { join as
|
|
97803
|
+
import { join as join61 } from "path";
|
|
97549
97804
|
var STACK_TIMEOUT_MS = TIMEOUT_MS;
|
|
97550
97805
|
async function defaultIsCommandAvailable(command2) {
|
|
97551
97806
|
try {
|
|
@@ -97587,7 +97842,7 @@ async function detectStack(cwd, currentBranch, deps = {}) {
|
|
|
97587
97842
|
async function detectGraphite(cwd, currentBranch, isCommandAvailable, fileExists2, exec, getDefaultBranch2) {
|
|
97588
97843
|
const gtAvailable = await isCommandAvailable("gt");
|
|
97589
97844
|
if (!gtAvailable) return null;
|
|
97590
|
-
const markerPresent = await fileExists2(
|
|
97845
|
+
const markerPresent = await fileExists2(join61(cwd, ".git", ".graphite_repo_config"));
|
|
97591
97846
|
if (!markerPresent) return null;
|
|
97592
97847
|
const ancestor = await exec("gt", ["parent"], cwd).then((s2) => normalizeBranchName(s2)).catch(() => null);
|
|
97593
97848
|
const childrenRaw = await exec("gt", ["children"], cwd).then((s2) => s2).catch(() => "");
|
|
@@ -97600,7 +97855,7 @@ async function detectGraphite(cwd, currentBranch, isCommandAvailable, fileExists
|
|
|
97600
97855
|
return { ancestor: resolvedAncestor, descendants };
|
|
97601
97856
|
}
|
|
97602
97857
|
async function detectJujutsu(cwd, fileExists2, exec) {
|
|
97603
|
-
const jjPresent = await fileExists2(
|
|
97858
|
+
const jjPresent = await fileExists2(join61(cwd, ".jj"));
|
|
97604
97859
|
if (!jjPresent) return null;
|
|
97605
97860
|
const ancestorRaw = await exec(
|
|
97606
97861
|
"jj",
|
|
@@ -97649,7 +97904,7 @@ function parseJjLines(raw) {
|
|
|
97649
97904
|
|
|
97650
97905
|
// src/services/storage/annotation-store.ts
|
|
97651
97906
|
import { mkdir as mkdir22, readFile as readFile34 } from "fs/promises";
|
|
97652
|
-
import { dirname as dirname25, join as
|
|
97907
|
+
import { dirname as dirname25, join as join62 } from "path";
|
|
97653
97908
|
var LegacyBaseFields = external_exports.object({
|
|
97654
97909
|
commentId: external_exports.string(),
|
|
97655
97910
|
body: external_exports.string(),
|
|
@@ -97676,7 +97931,7 @@ var LegacyPlanStoreSchema = external_exports.object({
|
|
|
97676
97931
|
versions: external_exports.array(PlanVersionZodSchema)
|
|
97677
97932
|
});
|
|
97678
97933
|
function buildAnnotationStore(dataDir) {
|
|
97679
|
-
const baseDir =
|
|
97934
|
+
const baseDir = join62(dataDir, "annotations");
|
|
97680
97935
|
const cache2 = /* @__PURE__ */ new Map();
|
|
97681
97936
|
const listeners = /* @__PURE__ */ new Set();
|
|
97682
97937
|
const writeQueues = /* @__PURE__ */ new Map();
|
|
@@ -97689,7 +97944,7 @@ function buildAnnotationStore(dataDir) {
|
|
|
97689
97944
|
}
|
|
97690
97945
|
}
|
|
97691
97946
|
function filePath(taskId) {
|
|
97692
|
-
return
|
|
97947
|
+
return join62(baseDir, `${taskId}.json`);
|
|
97693
97948
|
}
|
|
97694
97949
|
function emptyData() {
|
|
97695
97950
|
return {
|
|
@@ -97754,9 +98009,9 @@ function buildAnnotationStore(dataDir) {
|
|
|
97754
98009
|
}
|
|
97755
98010
|
async function migrateLegacyFiles(taskId) {
|
|
97756
98011
|
const [diffRaw, previewRaw, planRaw] = await Promise.all([
|
|
97757
|
-
readLegacyFile(
|
|
97758
|
-
readLegacyFile(
|
|
97759
|
-
readLegacyFile(
|
|
98012
|
+
readLegacyFile(join62(dataDir, "diff-review", `${taskId}.json`)),
|
|
98013
|
+
readLegacyFile(join62(dataDir, "preview-annotations", `${taskId}.json`)),
|
|
98014
|
+
readLegacyFile(join62(dataDir, "plan-comments", `${taskId}.json`))
|
|
97760
98015
|
]);
|
|
97761
98016
|
if (diffRaw === null && previewRaw === null && planRaw === null) {
|
|
97762
98017
|
return null;
|
|
@@ -97959,7 +98214,7 @@ function buildAnnotationStore(dataDir) {
|
|
|
97959
98214
|
|
|
97960
98215
|
// src/services/storage/asset-store.ts
|
|
97961
98216
|
import { mkdir as mkdir23, readFile as readFile35, rename as rename18, writeFile as writeFile23 } from "fs/promises";
|
|
97962
|
-
import { join as
|
|
98217
|
+
import { join as join63 } from "path";
|
|
97963
98218
|
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
97964
98219
|
function isValidAssetId(id) {
|
|
97965
98220
|
return UUID_RE.test(id);
|
|
@@ -97985,10 +98240,10 @@ function buildAssetStore(assetsDir) {
|
|
|
97985
98240
|
}
|
|
97986
98241
|
}
|
|
97987
98242
|
function binaryPath(assetId) {
|
|
97988
|
-
return
|
|
98243
|
+
return join63(assetsDir, `${assetId}.bin`);
|
|
97989
98244
|
}
|
|
97990
98245
|
function metaPath(assetId) {
|
|
97991
|
-
return
|
|
98246
|
+
return join63(assetsDir, `${assetId}.meta.json`);
|
|
97992
98247
|
}
|
|
97993
98248
|
function parseMeta(raw) {
|
|
97994
98249
|
return AssetMetadataSchema.parse(JSON.parse(raw));
|
|
@@ -98012,8 +98267,8 @@ function buildAssetStore(assetsDir) {
|
|
|
98012
98267
|
size: data.byteLength,
|
|
98013
98268
|
createdAt: Date.now()
|
|
98014
98269
|
};
|
|
98015
|
-
const tmpBin =
|
|
98016
|
-
const tmpMeta =
|
|
98270
|
+
const tmpBin = join63(assetsDir, `${assetId}.bin.tmp`);
|
|
98271
|
+
const tmpMeta = join63(assetsDir, `${assetId}.meta.tmp`);
|
|
98017
98272
|
await writeFile23(tmpBin, data);
|
|
98018
98273
|
await writeFile23(tmpMeta, JSON.stringify(metadata), "utf-8");
|
|
98019
98274
|
await rename18(tmpBin, binaryPath(assetId));
|
|
@@ -98238,7 +98493,7 @@ function buildCredentialsVaultStore(filePath, corruptionLogger) {
|
|
|
98238
98493
|
|
|
98239
98494
|
// src/services/storage/deliverable-store.ts
|
|
98240
98495
|
import { mkdir as mkdir25, readFile as readFile37 } from "fs/promises";
|
|
98241
|
-
import { dirname as dirname27, join as
|
|
98496
|
+
import { dirname as dirname27, join as join64 } from "path";
|
|
98242
98497
|
var DELIVERABLE_STORE_VERSION = 1;
|
|
98243
98498
|
var DeliverableStoreSchema = external_exports.object({
|
|
98244
98499
|
schemaVersion: external_exports.number(),
|
|
@@ -98252,7 +98507,7 @@ function migrateDeliverableStore(raw) {
|
|
|
98252
98507
|
return { schemaVersion: DELIVERABLE_STORE_VERSION, records: [] };
|
|
98253
98508
|
}
|
|
98254
98509
|
function buildDeliverableStore(dataDir) {
|
|
98255
|
-
const baseDir =
|
|
98510
|
+
const baseDir = join64(dataDir, "deliverables");
|
|
98256
98511
|
const cache2 = /* @__PURE__ */ new Map();
|
|
98257
98512
|
const listeners = /* @__PURE__ */ new Set();
|
|
98258
98513
|
const writeQueues = /* @__PURE__ */ new Map();
|
|
@@ -98265,7 +98520,7 @@ function buildDeliverableStore(dataDir) {
|
|
|
98265
98520
|
}
|
|
98266
98521
|
}
|
|
98267
98522
|
function filePath(taskId) {
|
|
98268
|
-
return
|
|
98523
|
+
return join64(baseDir, `${taskId}.json`);
|
|
98269
98524
|
}
|
|
98270
98525
|
function emptyData() {
|
|
98271
98526
|
return { schemaVersion: DELIVERABLE_STORE_VERSION, records: [] };
|
|
@@ -98405,7 +98660,7 @@ function buildDeliverableStore(dataDir) {
|
|
|
98405
98660
|
|
|
98406
98661
|
// src/services/storage/jsonl-conversation-store.ts
|
|
98407
98662
|
import { appendFile as appendFile3, mkdir as mkdir26, open, readFile as readFile38, stat as stat16 } from "fs/promises";
|
|
98408
|
-
import { join as
|
|
98663
|
+
import { join as join65 } from "path";
|
|
98409
98664
|
var StoredMessageSchema = MessageSchema.omit({ seqNo: true, channelId: true });
|
|
98410
98665
|
function logPerf(entry) {
|
|
98411
98666
|
try {
|
|
@@ -98415,12 +98670,12 @@ function logPerf(entry) {
|
|
|
98415
98670
|
}
|
|
98416
98671
|
}
|
|
98417
98672
|
function buildJsonlConversationStore(dataDir, opts = {}) {
|
|
98418
|
-
const channelsDir =
|
|
98673
|
+
const channelsDir = join65(dataDir, "channels");
|
|
98419
98674
|
const seqCounters = /* @__PURE__ */ new Map();
|
|
98420
98675
|
const channelQueues = /* @__PURE__ */ new Map();
|
|
98421
98676
|
const readCache = /* @__PURE__ */ new Map();
|
|
98422
98677
|
function channelPath(channelId) {
|
|
98423
|
-
return
|
|
98678
|
+
return join65(channelsDir, `${channelId}.jsonl`);
|
|
98424
98679
|
}
|
|
98425
98680
|
async function ensureDir() {
|
|
98426
98681
|
await mkdir26(channelsDir, { recursive: true });
|
|
@@ -99192,7 +99447,7 @@ function buildProjectsStore(filePath) {
|
|
|
99192
99447
|
|
|
99193
99448
|
// src/services/storage/rate-limit-store.ts
|
|
99194
99449
|
import { mkdir as mkdir28, readFile as readFile40 } from "fs/promises";
|
|
99195
|
-
import { dirname as dirname29, join as
|
|
99450
|
+
import { dirname as dirname29, join as join66 } from "path";
|
|
99196
99451
|
var RATE_LIMIT_STORE_VERSION = 4;
|
|
99197
99452
|
var RateLimitRecordSchema = external_exports.object({
|
|
99198
99453
|
info: RateLimitInfoSchema,
|
|
@@ -99231,7 +99486,7 @@ function isWindowKey(x2) {
|
|
|
99231
99486
|
return x2 !== void 0 && WINDOW_KEYS.has(x2);
|
|
99232
99487
|
}
|
|
99233
99488
|
async function buildRateLimitStore(dataDir, opts) {
|
|
99234
|
-
const filePath =
|
|
99489
|
+
const filePath = join66(dataDir, "rate-limits.json");
|
|
99235
99490
|
const lockPath2 = `${filePath}.lock`;
|
|
99236
99491
|
const initial = await loadStoreFile(filePath, opts.logger);
|
|
99237
99492
|
const records = { ...initial.records };
|
|
@@ -99484,7 +99739,7 @@ async function atomicWrite4(filePath, data) {
|
|
|
99484
99739
|
}
|
|
99485
99740
|
|
|
99486
99741
|
// src/services/storage/schedule-store.ts
|
|
99487
|
-
import { join as
|
|
99742
|
+
import { join as join67 } from "path";
|
|
99488
99743
|
|
|
99489
99744
|
// src/services/storage/json-document-store.ts
|
|
99490
99745
|
import { mkdir as mkdir29, readFile as readFile41 } from "fs/promises";
|
|
@@ -99675,7 +99930,7 @@ function buildScheduleStore(dataDir) {
|
|
|
99675
99930
|
const store = buildJsonDocumentStore({
|
|
99676
99931
|
storeName: "schedules",
|
|
99677
99932
|
docType: "schedule",
|
|
99678
|
-
filePath:
|
|
99933
|
+
filePath: join67(dataDir, "schedules.json"),
|
|
99679
99934
|
recordSchema: ScheduleRecordSchema,
|
|
99680
99935
|
currentVersion: SCHEDULE_STORE_VERSION,
|
|
99681
99936
|
migrate(raw) {
|
|
@@ -99714,7 +99969,7 @@ function buildScheduleStore(dataDir) {
|
|
|
99714
99969
|
|
|
99715
99970
|
// src/services/storage/session-persistence.ts
|
|
99716
99971
|
import { mkdir as mkdir30, readdir as readdir19, readFile as readFile42, rm as rm12 } from "fs/promises";
|
|
99717
|
-
import { join as
|
|
99972
|
+
import { join as join68 } from "path";
|
|
99718
99973
|
var PersistedSessionSchema = external_exports.object({
|
|
99719
99974
|
sessionId: external_exports.string(),
|
|
99720
99975
|
channelId: external_exports.string(),
|
|
@@ -99771,9 +100026,9 @@ async function loadOneSessionFile(originalPath, corruptionLogger) {
|
|
|
99771
100026
|
}
|
|
99772
100027
|
}
|
|
99773
100028
|
function buildSessionPersistence(dataDir, corruptionLogger) {
|
|
99774
|
-
const channelsDir =
|
|
100029
|
+
const channelsDir = join68(dataDir, "channels");
|
|
99775
100030
|
function sessionPath(channelId) {
|
|
99776
|
-
return
|
|
100031
|
+
return join68(channelsDir, `${channelId}.session.json`);
|
|
99777
100032
|
}
|
|
99778
100033
|
async function ensureDir() {
|
|
99779
100034
|
await mkdir30(channelsDir, { recursive: true });
|
|
@@ -99831,7 +100086,7 @@ function buildSessionPersistence(dataDir, corruptionLogger) {
|
|
|
99831
100086
|
if (i >= sessionEntries.length) return;
|
|
99832
100087
|
const entry = sessionEntries[i];
|
|
99833
100088
|
if (!entry) return;
|
|
99834
|
-
results[i] = await loadOneSessionFile(
|
|
100089
|
+
results[i] = await loadOneSessionFile(join68(channelsDir, entry), corruptionLogger);
|
|
99835
100090
|
}
|
|
99836
100091
|
}
|
|
99837
100092
|
const workers = Array.from(
|
|
@@ -99845,12 +100100,12 @@ function buildSessionPersistence(dataDir, corruptionLogger) {
|
|
|
99845
100100
|
}
|
|
99846
100101
|
|
|
99847
100102
|
// src/services/storage/template-store.ts
|
|
99848
|
-
import { join as
|
|
100103
|
+
import { join as join69 } from "path";
|
|
99849
100104
|
function buildTemplateStore(dataDir) {
|
|
99850
100105
|
const store = buildJsonDocumentStore({
|
|
99851
100106
|
storeName: "templates",
|
|
99852
100107
|
docType: "template",
|
|
99853
|
-
filePath:
|
|
100108
|
+
filePath: join69(dataDir, "templates.json"),
|
|
99854
100109
|
recordSchema: TaskTemplateRecordSchema,
|
|
99855
100110
|
currentVersion: TEMPLATE_STORE_VERSION,
|
|
99856
100111
|
migrate(raw) {
|
|
@@ -102735,7 +102990,7 @@ function handleRunning(snapshot, event) {
|
|
|
102735
102990
|
effects: b2.effects
|
|
102736
102991
|
};
|
|
102737
102992
|
}
|
|
102738
|
-
if (event.type === "
|
|
102993
|
+
if (event.type === "subprocess_died") {
|
|
102739
102994
|
b2.log("running", "resumable_idle", event.type);
|
|
102740
102995
|
b2.effects.push({ type: "clear_pending_inputs" });
|
|
102741
102996
|
b2.effects.push({ type: "clear_queue" });
|
|
@@ -102749,10 +103004,26 @@ function handleRunning(snapshot, event) {
|
|
|
102749
103004
|
effects: b2.effects
|
|
102750
103005
|
};
|
|
102751
103006
|
}
|
|
103007
|
+
if (event.type === "sdk_error") {
|
|
103008
|
+
b2.log("running", "resumable_idle", event.type);
|
|
103009
|
+
b2.effects.push({ type: "clear_pending_inputs" });
|
|
103010
|
+
b2.effects.push({ type: "clear_queue" });
|
|
103011
|
+
b2.taskStatus("input_required");
|
|
103012
|
+
emitSessionDeath(b2, event, "running");
|
|
103013
|
+
b2.effects.push({ type: "force_kill" });
|
|
103014
|
+
return {
|
|
103015
|
+
state: "resumable_idle",
|
|
103016
|
+
sessionId,
|
|
103017
|
+
rewindAtMessageId: null,
|
|
103018
|
+
awaitingSetup: false,
|
|
103019
|
+
effects: b2.effects
|
|
103020
|
+
};
|
|
103021
|
+
}
|
|
102752
103022
|
if (event.type === "abort_retry") {
|
|
102753
103023
|
b2.log("running", "resumable_idle", event.type);
|
|
102754
103024
|
b2.effects.push({ type: "clear_pending_inputs" });
|
|
102755
103025
|
b2.effects.push({ type: "clear_queue" });
|
|
103026
|
+
b2.effects.push({ type: "force_kill" });
|
|
102756
103027
|
return {
|
|
102757
103028
|
state: "resumable_idle",
|
|
102758
103029
|
sessionId,
|
|
@@ -104354,6 +104625,7 @@ var Thread = class {
|
|
|
104354
104625
|
config.adoptedSubprocess.redirectEvents(
|
|
104355
104626
|
(event) => this.#enqueueSubprocessEvent(event, generation)
|
|
104356
104627
|
);
|
|
104628
|
+
setSubprocessEpoch(this.#config.threadId, config.adoptedSubprocess.epoch);
|
|
104357
104629
|
if (config.onCwdChanged) {
|
|
104358
104630
|
this.#subprocess.setOnCwdChanged(config.onCwdChanged);
|
|
104359
104631
|
}
|
|
@@ -105019,11 +105291,13 @@ var Thread = class {
|
|
|
105019
105291
|
this.#subprocess?.close();
|
|
105020
105292
|
this.#subprocess = null;
|
|
105021
105293
|
this.#appliedToSubprocess = {};
|
|
105294
|
+
unregisterSubprocessEpoch(this.#config.threadId);
|
|
105022
105295
|
}
|
|
105023
105296
|
#handleForceKill() {
|
|
105024
105297
|
this.#subprocess?.forceKill();
|
|
105025
105298
|
this.#subprocess = null;
|
|
105026
105299
|
this.#appliedToSubprocess = {};
|
|
105300
|
+
unregisterSubprocessEpoch(this.#config.threadId);
|
|
105027
105301
|
}
|
|
105028
105302
|
/**
|
|
105029
105303
|
* Persist a FINAL SDK error to the chat JSONL as an inline assistant
|
|
@@ -105366,7 +105640,7 @@ import { randomUUID as randomUUID21 } from "crypto";
|
|
|
105366
105640
|
import { existsSync as existsSync10, readdirSync as readdirSync5, statSync as statSync4 } from "fs";
|
|
105367
105641
|
import { mkdir as mkdir32, readFile as readFile45, writeFile as writeFile25 } from "fs/promises";
|
|
105368
105642
|
import { homedir as homedir9 } from "os";
|
|
105369
|
-
import { dirname as dirname33, join as
|
|
105643
|
+
import { dirname as dirname33, join as join71 } from "path";
|
|
105370
105644
|
|
|
105371
105645
|
// src/services/plan/plan-detection-policy.ts
|
|
105372
105646
|
function decidePlanDetection(trigger, snapshot) {
|
|
@@ -105993,8 +106267,8 @@ function greedyLCS(a, b2) {
|
|
|
105993
106267
|
// src/services/plan/plan-file-watcher.ts
|
|
105994
106268
|
import { existsSync as existsSync9 } from "fs";
|
|
105995
106269
|
import { homedir as homedir8 } from "os";
|
|
105996
|
-
import { join as
|
|
105997
|
-
var DEFAULT_PLANS_DIR =
|
|
106270
|
+
import { join as join70 } from "path";
|
|
106271
|
+
var DEFAULT_PLANS_DIR = join70(homedir8(), ".claude", "plans");
|
|
105998
106272
|
var PLAN_WATCH_TIMEOUT_MS = 1e4;
|
|
105999
106273
|
var PLAN_WATCH_DEBOUNCE_MS = 250;
|
|
106000
106274
|
function createPlanFileWatcher(deps) {
|
|
@@ -106443,7 +106717,7 @@ var PlanHandler = class {
|
|
|
106443
106717
|
* Called when a Write tool result mentions a file in ~/.claude/plans/.
|
|
106444
106718
|
*/
|
|
106445
106719
|
trackCreatedFile(filePath) {
|
|
106446
|
-
const plansDir =
|
|
106720
|
+
const plansDir = join71(homedir9(), ".claude", "plans");
|
|
106447
106721
|
if (filePath.startsWith(plansDir) && filePath.endsWith(".md")) {
|
|
106448
106722
|
this.#createdPlanFiles.add(filePath);
|
|
106449
106723
|
this.#deps.log({
|
|
@@ -106475,7 +106749,7 @@ var PlanHandler = class {
|
|
|
106475
106749
|
}
|
|
106476
106750
|
async #runHandleCodexPlanReady(content) {
|
|
106477
106751
|
if (this.#deps.isDisposed()) return;
|
|
106478
|
-
const filePath =
|
|
106752
|
+
const filePath = join71(getShipyardHome(), "plans", `${this.#deps.taskId}.md`);
|
|
106479
106753
|
try {
|
|
106480
106754
|
await mkdir32(dirname33(filePath), { recursive: true });
|
|
106481
106755
|
await writeFile25(filePath, content, "utf-8");
|
|
@@ -106855,12 +107129,12 @@ var PlanHandler = class {
|
|
|
106855
107129
|
}).filter((f2) => f2 !== null).sort((a, b2) => b2.mtime - a.mtime)[0];
|
|
106856
107130
|
return newest?.path ?? null;
|
|
106857
107131
|
}
|
|
106858
|
-
const plansDir =
|
|
107132
|
+
const plansDir = join71(homedir9(), ".claude", "plans");
|
|
106859
107133
|
if (!existsSync10(plansDir)) return null;
|
|
106860
107134
|
try {
|
|
106861
107135
|
const files = readdirSync5(plansDir).filter((f2) => f2.endsWith(".md")).map((f2) => ({
|
|
106862
|
-
path:
|
|
106863
|
-
mtime: statSync4(
|
|
107136
|
+
path: join71(plansDir, f2),
|
|
107137
|
+
mtime: statSync4(join71(plansDir, f2)).mtimeMs
|
|
106864
107138
|
})).sort((a, b2) => b2.mtime - a.mtime);
|
|
106865
107139
|
const recent = files[0];
|
|
106866
107140
|
if (recent && Date.now() - recent.mtime < 3e4) return recent.path;
|
|
@@ -109201,7 +109475,7 @@ var RewindCheckpointHandler = class {
|
|
|
109201
109475
|
|
|
109202
109476
|
// src/services/task/side-thread-registry.ts
|
|
109203
109477
|
import { mkdir as mkdir33, readFile as readFile46, rename as rename20, writeFile as writeFile26 } from "fs/promises";
|
|
109204
|
-
import { dirname as dirname34, join as
|
|
109478
|
+
import { dirname as dirname34, join as join72 } from "path";
|
|
109205
109479
|
var ThreadFileSchema = external_exports.object({
|
|
109206
109480
|
threads: external_exports.record(external_exports.string(), ThreadMetadataSchema)
|
|
109207
109481
|
});
|
|
@@ -109577,7 +109851,7 @@ var SideThreadRegistry = class {
|
|
|
109577
109851
|
}
|
|
109578
109852
|
/** Persistence */
|
|
109579
109853
|
#filePath() {
|
|
109580
|
-
return
|
|
109854
|
+
return join72(this.#deps.dataDir, "threads", `${this.#deps.taskId}.json`);
|
|
109581
109855
|
}
|
|
109582
109856
|
async #ensureLoaded() {
|
|
109583
109857
|
if (this.#loadedFromDisk.has(this.#deps.taskId)) return;
|
|
@@ -110579,6 +110853,14 @@ function handleTurnComplete(ctx, event) {
|
|
|
110579
110853
|
ctx.telemetryCaptureTurnComplete(event.result);
|
|
110580
110854
|
ctx.telemetryResetTurn();
|
|
110581
110855
|
ctx.enqueueCheckpoint();
|
|
110856
|
+
if (isRefusalStopReason(event.result.stopReason)) {
|
|
110857
|
+
ctx.broadcast({
|
|
110858
|
+
type: "task_error",
|
|
110859
|
+
taskId: ctx.taskId,
|
|
110860
|
+
error: refusalBannerMessage(),
|
|
110861
|
+
errorKind: "sdk_error"
|
|
110862
|
+
});
|
|
110863
|
+
}
|
|
110582
110864
|
}
|
|
110583
110865
|
function handleSdkError(ctx, event) {
|
|
110584
110866
|
ctx.collabQueueTurnComplete();
|
|
@@ -112404,7 +112686,7 @@ async function resolveTaskListPrepend(ctx) {
|
|
|
112404
112686
|
// src/services/task/cc-task-file-store.ts
|
|
112405
112687
|
import { readdir as readdir20, readFile as readFile47 } from "fs/promises";
|
|
112406
112688
|
import { homedir as homedir10 } from "os";
|
|
112407
|
-
import { basename as basename12, dirname as dirname35, join as
|
|
112689
|
+
import { basename as basename12, dirname as dirname35, join as join73 } from "path";
|
|
112408
112690
|
var VALID_STATUSES = /* @__PURE__ */ new Set(["pending", "in_progress", "completed"]);
|
|
112409
112691
|
var IDLE_DETACH_MS = 5 * 60 * 1e3;
|
|
112410
112692
|
var IDLE_SWEEP_INTERVAL_MS = 6e4;
|
|
@@ -112420,7 +112702,7 @@ function isCCTaskFile(value) {
|
|
|
112420
112702
|
}
|
|
112421
112703
|
function createCCTaskFileWatcher(listId, log) {
|
|
112422
112704
|
const sanitizedId = sanitize(listId);
|
|
112423
|
-
const dir =
|
|
112705
|
+
const dir = join73(homedir10(), ".claude", "tasks", sanitizedId);
|
|
112424
112706
|
const targetDirName = basename12(dir);
|
|
112425
112707
|
const parentDir = dirname35(dir);
|
|
112426
112708
|
const watchState = {
|
|
@@ -112456,7 +112738,7 @@ function createCCTaskFileWatcher(listId, log) {
|
|
|
112456
112738
|
return tasks;
|
|
112457
112739
|
}
|
|
112458
112740
|
async function readTask(taskId) {
|
|
112459
|
-
const filePath =
|
|
112741
|
+
const filePath = join73(dir, `${taskId}.json`);
|
|
112460
112742
|
try {
|
|
112461
112743
|
const raw = await readFile47(filePath, "utf-8");
|
|
112462
112744
|
const parsed = JSON.parse(raw);
|
|
@@ -112523,7 +112805,7 @@ function createCCTaskFileWatcher(listId, log) {
|
|
|
112523
112805
|
watchState.parentSub = null;
|
|
112524
112806
|
return;
|
|
112525
112807
|
}
|
|
112526
|
-
if (ev.path.endsWith(targetDirName) || ev.path ===
|
|
112808
|
+
if (ev.path.endsWith(targetDirName) || ev.path === join73(parentDir, targetDirName)) {
|
|
112527
112809
|
void ensureDirWatcher();
|
|
112528
112810
|
break;
|
|
112529
112811
|
}
|
|
@@ -112639,7 +112921,7 @@ function createCCTaskFileWatcher(listId, log) {
|
|
|
112639
112921
|
// src/services/task/cc-task-file-writer.ts
|
|
112640
112922
|
import { createHash as createHash10 } from "crypto";
|
|
112641
112923
|
import { mkdir as mkdir34, readdir as readdir21, rename as rename21, unlink as unlink15, writeFile as writeFile27 } from "fs/promises";
|
|
112642
|
-
import { join as
|
|
112924
|
+
import { join as join74 } from "path";
|
|
112643
112925
|
function contentHash2(data) {
|
|
112644
112926
|
return createHash10("sha256").update(data).digest("hex").slice(0, 16);
|
|
112645
112927
|
}
|
|
@@ -112655,7 +112937,7 @@ async function writeTasks(dir, tasks, hashes) {
|
|
|
112655
112937
|
const json = JSON.stringify(structuredTaskToCCFile(task), null, 2);
|
|
112656
112938
|
const hash = contentHash2(json);
|
|
112657
112939
|
if (hashes.get(id) === hash) continue;
|
|
112658
|
-
await atomicWriteFile2(
|
|
112940
|
+
await atomicWriteFile2(join74(dir, `${id}.json`), json);
|
|
112659
112941
|
hashes.set(id, hash);
|
|
112660
112942
|
}
|
|
112661
112943
|
return targetIds;
|
|
@@ -112671,7 +112953,7 @@ async function removeStaleFiles(dir, targetIds, hashes) {
|
|
|
112671
112953
|
if (!entry.endsWith(".json")) continue;
|
|
112672
112954
|
const id = entry.slice(0, -".json".length);
|
|
112673
112955
|
if (!targetIds.has(id) && hashes.has(id)) {
|
|
112674
|
-
await unlink15(
|
|
112956
|
+
await unlink15(join74(dir, entry)).catch(() => {
|
|
112675
112957
|
});
|
|
112676
112958
|
hashes.delete(id);
|
|
112677
112959
|
}
|
|
@@ -113273,10 +113555,10 @@ var StructuredTaskTracker = class {
|
|
|
113273
113555
|
import { unwatchFile, watchFile } from "fs";
|
|
113274
113556
|
import { open as open2 } from "fs/promises";
|
|
113275
113557
|
import { homedir as homedir11 } from "os";
|
|
113276
|
-
import { join as
|
|
113558
|
+
import { join as join75 } from "path";
|
|
113277
113559
|
function computeTranscriptPath(cwd, sessionId, taskId) {
|
|
113278
113560
|
const cwdSlug = cwd.replace(/[^a-zA-Z0-9]/g, "-").slice(0, 200);
|
|
113279
|
-
return
|
|
113561
|
+
return join75(
|
|
113280
113562
|
homedir11(),
|
|
113281
113563
|
".claude",
|
|
113282
113564
|
"projects",
|
|
@@ -113991,7 +114273,7 @@ import { createHash as createHash11 } from "crypto";
|
|
|
113991
114273
|
import { unlink as unlink16, writeFile as writeFile28 } from "fs/promises";
|
|
113992
114274
|
import { createRequire as createRequire4 } from "module";
|
|
113993
114275
|
import { tmpdir } from "os";
|
|
113994
|
-
import { join as
|
|
114276
|
+
import { join as join76 } from "path";
|
|
113995
114277
|
import { promisify as promisify10 } from "util";
|
|
113996
114278
|
var execFileAsync4 = promisify10(execFile11);
|
|
113997
114279
|
function resolveDaemonNodeModules(log) {
|
|
@@ -114004,7 +114286,7 @@ function resolveDaemonNodeModules(log) {
|
|
|
114004
114286
|
} catch {
|
|
114005
114287
|
}
|
|
114006
114288
|
try {
|
|
114007
|
-
const cwdRequire = createRequire4(
|
|
114289
|
+
const cwdRequire = createRequire4(join76(process.cwd(), "package.json"));
|
|
114008
114290
|
const sdkPath = cwdRequire.resolve("@modelcontextprotocol/sdk/server/mcp.js");
|
|
114009
114291
|
const idx = sdkPath.lastIndexOf("node_modules");
|
|
114010
114292
|
if (idx >= 0) return sdkPath.slice(0, idx + "node_modules".length);
|
|
@@ -114014,7 +114296,7 @@ function resolveDaemonNodeModules(log) {
|
|
|
114014
114296
|
error: err3 instanceof Error ? err3.message : String(err3)
|
|
114015
114297
|
});
|
|
114016
114298
|
}
|
|
114017
|
-
return
|
|
114299
|
+
return join76(process.cwd(), "node_modules");
|
|
114018
114300
|
}
|
|
114019
114301
|
function planTokenCount(systemPrompt, metadata, cwd, model, mcpServers) {
|
|
114020
114302
|
return {
|
|
@@ -114211,7 +114493,7 @@ async function serializeMcpConfig(servers, allToolNames, daemonNodeModules, rese
|
|
|
114211
114493
|
if (isReservedMcpServerName(serverName, reservedServerNames)) continue;
|
|
114212
114494
|
const script = buildStubServerScript(serverName, tools);
|
|
114213
114495
|
if (!script) continue;
|
|
114214
|
-
const stubPath =
|
|
114496
|
+
const stubPath = join76(tmpdir(), `shipyard-mcp-stub-${serverName}-${Date.now()}.cjs`);
|
|
114215
114497
|
await writeFile28(stubPath, script, "utf-8");
|
|
114216
114498
|
stubPaths.push(stubPath);
|
|
114217
114499
|
mcpServers[serverName] = {
|
|
@@ -114237,7 +114519,7 @@ async function prepareTokenCountArgs(plan, log, reservedServerNames = SDK_RESERV
|
|
|
114237
114519
|
reservedServerNames
|
|
114238
114520
|
);
|
|
114239
114521
|
if (!serialized.config) return { args, mcpConfigPath: null, stubPaths: serialized.stubPaths };
|
|
114240
|
-
const mcpConfigPath =
|
|
114522
|
+
const mcpConfigPath = join76(tmpdir(), `shipyard-mcp-${Date.now()}.json`);
|
|
114241
114523
|
await writeFile28(mcpConfigPath, JSON.stringify(serialized.config), "utf-8");
|
|
114242
114524
|
args.push("--mcp-config", mcpConfigPath);
|
|
114243
114525
|
return { args, mcpConfigPath, stubPaths: serialized.stubPaths };
|
|
@@ -115338,6 +115620,7 @@ var Task = class {
|
|
|
115338
115620
|
* compaction occurred on those.
|
|
115339
115621
|
*/
|
|
115340
115622
|
applyCrossRuntimeSwitch(newRuntimeId, pendingHandoff, mode) {
|
|
115623
|
+
this.#deps.onCrossRuntimeSwitch?.(this.#deps.taskId, this.#runtimeId, newRuntimeId);
|
|
115341
115624
|
applyCrossRuntimeSwitch(this.#crossRuntimeCtx(), newRuntimeId, pendingHandoff, mode);
|
|
115342
115625
|
}
|
|
115343
115626
|
/**
|
|
@@ -119390,6 +119673,9 @@ var TaskManager = class {
|
|
|
119390
119673
|
resolveMcpServers: this.#deps.resolveMcpServers,
|
|
119391
119674
|
notifyTaskMetadataChange: this.#deps.notifyTaskMetadataChange,
|
|
119392
119675
|
notifyPlanResourceChange: this.#deps.notifyPlanResourceChange,
|
|
119676
|
+
...this.#deps.onCrossRuntimeSwitch && {
|
|
119677
|
+
onCrossRuntimeSwitch: this.#deps.onCrossRuntimeSwitch
|
|
119678
|
+
},
|
|
119393
119679
|
onSubprocessReady: (tid) => {
|
|
119394
119680
|
const task = this.#tasks.get(tid);
|
|
119395
119681
|
if (!task) return;
|
|
@@ -119502,11 +119788,11 @@ function pathExistsForLog2(path5) {
|
|
|
119502
119788
|
}
|
|
119503
119789
|
|
|
119504
119790
|
// src/services/task/manager/task-state-store.ts
|
|
119505
|
-
import { join as
|
|
119791
|
+
import { join as join78 } from "path";
|
|
119506
119792
|
|
|
119507
119793
|
// src/services/storage/directory-record-store.ts
|
|
119508
119794
|
import { mkdir as mkdir35, readdir as readdir22, readFile as readFile48, rename as rename22, stat as stat17, unlink as unlink17 } from "fs/promises";
|
|
119509
|
-
import { join as
|
|
119795
|
+
import { join as join77 } from "path";
|
|
119510
119796
|
var SCHEMA_VERSION_FILENAME = "__schema-version";
|
|
119511
119797
|
var RECORD_SUFFIX = ".json";
|
|
119512
119798
|
var SAFE_ID_RE = /^[A-Za-z0-9_-][A-Za-z0-9_.-]*$/;
|
|
@@ -119526,7 +119812,7 @@ function buildDirectoryRecordStore(opts) {
|
|
|
119526
119812
|
let writeQueue = Promise.resolve();
|
|
119527
119813
|
function recordPath(id) {
|
|
119528
119814
|
assertSafeRecordId(id);
|
|
119529
|
-
return
|
|
119815
|
+
return join77(dataDir, `${id}${RECORD_SUFFIX}`);
|
|
119530
119816
|
}
|
|
119531
119817
|
function notify(event) {
|
|
119532
119818
|
for (const listener of listeners) {
|
|
@@ -119541,7 +119827,7 @@ function buildDirectoryRecordStore(opts) {
|
|
|
119541
119827
|
}
|
|
119542
119828
|
async function readSchemaVersion() {
|
|
119543
119829
|
try {
|
|
119544
|
-
const raw = await readFile48(
|
|
119830
|
+
const raw = await readFile48(join77(dataDir, SCHEMA_VERSION_FILENAME), "utf-8");
|
|
119545
119831
|
const parsed = Number.parseInt(raw.trim(), 10);
|
|
119546
119832
|
return Number.isFinite(parsed) ? parsed : null;
|
|
119547
119833
|
} catch (err3) {
|
|
@@ -119550,7 +119836,7 @@ function buildDirectoryRecordStore(opts) {
|
|
|
119550
119836
|
}
|
|
119551
119837
|
}
|
|
119552
119838
|
async function writeSchemaVersion(version) {
|
|
119553
|
-
const path5 =
|
|
119839
|
+
const path5 = join77(dataDir, SCHEMA_VERSION_FILENAME);
|
|
119554
119840
|
await atomicWriteFile(path5, String(version));
|
|
119555
119841
|
}
|
|
119556
119842
|
async function legacyFileExists() {
|
|
@@ -119655,7 +119941,7 @@ function buildDirectoryRecordStore(opts) {
|
|
|
119655
119941
|
for (const entry of entries) {
|
|
119656
119942
|
if (!entry.endsWith(RECORD_SUFFIX)) continue;
|
|
119657
119943
|
const id = entry.slice(0, -RECORD_SUFFIX.length);
|
|
119658
|
-
const record = await loadOneRecord(
|
|
119944
|
+
const record = await loadOneRecord(join77(dataDir, entry), entry);
|
|
119659
119945
|
if (record !== null) records.set(id, record);
|
|
119660
119946
|
}
|
|
119661
119947
|
return records;
|
|
@@ -119956,8 +120242,8 @@ function computePaginatedPage(all, capturedVersion, opts) {
|
|
|
119956
120242
|
}
|
|
119957
120243
|
function buildTaskStateStore(dataDir) {
|
|
119958
120244
|
const store = buildDirectoryRecordStore({
|
|
119959
|
-
dataDir:
|
|
119960
|
-
legacyFilePath:
|
|
120245
|
+
dataDir: join78(dataDir, "tasks"),
|
|
120246
|
+
legacyFilePath: join78(dataDir, "tasks.json"),
|
|
119961
120247
|
recordSchema: TaskRecordSchema,
|
|
119962
120248
|
currentVersion: TASK_STORE_VERSION,
|
|
119963
120249
|
migrate(raw) {
|
|
@@ -121041,7 +121327,7 @@ async function createDaemon(deps) {
|
|
|
121041
121327
|
const annotationStore = buildAnnotationStore(deps.dataDir);
|
|
121042
121328
|
const deliverableStore = buildDeliverableStore(deps.dataDir);
|
|
121043
121329
|
const resourceRegistry = createResourceRegistry();
|
|
121044
|
-
const assetStore = buildAssetStore(
|
|
121330
|
+
const assetStore = buildAssetStore(join79(deps.dataDir, "assets"));
|
|
121045
121331
|
const shipyardResolver = createShipyardResolver();
|
|
121046
121332
|
shipyardResolver.addSubResolver("asset", createAssetResolver(assetStore));
|
|
121047
121333
|
const pluginResourceResolver = new PluginResourceResolver(deps.log);
|
|
@@ -121050,10 +121336,10 @@ async function createDaemon(deps) {
|
|
|
121050
121336
|
const capabilitiesRef = { current: null };
|
|
121051
121337
|
const rateLimitStoreRef = { current: null };
|
|
121052
121338
|
const gitCheckpoint = createGitCheckpointService();
|
|
121053
|
-
const userSettingsStore = buildUserSettingsStore(
|
|
121054
|
-
const projectsStore = buildProjectsStore(
|
|
121339
|
+
const userSettingsStore = buildUserSettingsStore(join79(deps.dataDir, "user-settings.json"));
|
|
121340
|
+
const projectsStore = buildProjectsStore(join79(deps.dataDir, "projects.json"));
|
|
121055
121341
|
const credentialsVaultStore = buildCredentialsVaultStore(
|
|
121056
|
-
|
|
121342
|
+
join79(deps.dataDir, "credentials-vault.json")
|
|
121057
121343
|
);
|
|
121058
121344
|
const cursorVaultKeyRef = { current: null };
|
|
121059
121345
|
let resolveCursorVaultKey;
|
|
@@ -121254,6 +121540,7 @@ async function createDaemon(deps) {
|
|
|
121254
121540
|
});
|
|
121255
121541
|
return null;
|
|
121256
121542
|
}
|
|
121543
|
+
registerSubprocessEpoch(args.taskId);
|
|
121257
121544
|
deps.log({
|
|
121258
121545
|
event: "cursor_spawn_dispatch",
|
|
121259
121546
|
taskId: args.taskId,
|
|
@@ -121443,7 +121730,8 @@ async function createDaemon(deps) {
|
|
|
121443
121730
|
content,
|
|
121444
121731
|
capabilitiesRef.current?.skills ?? [],
|
|
121445
121732
|
deps.log
|
|
121446
|
-
)
|
|
121733
|
+
),
|
|
121734
|
+
...deps.pidTracker !== void 0 && { pidTracker: deps.pidTracker }
|
|
121447
121735
|
});
|
|
121448
121736
|
void initAsync.then(async (resolved) => {
|
|
121449
121737
|
try {
|
|
@@ -121497,7 +121785,7 @@ async function createDaemon(deps) {
|
|
|
121497
121785
|
taskId: args.taskId,
|
|
121498
121786
|
agentSystem: args.agentSystem,
|
|
121499
121787
|
environmentKey: args.cwd,
|
|
121500
|
-
pluginsDir:
|
|
121788
|
+
pluginsDir: join79(deps.shipyardHome, "plugins"),
|
|
121501
121789
|
vizWatcher: getOrCreateVizWatcher(args.taskId).watcher,
|
|
121502
121790
|
mode: "task",
|
|
121503
121791
|
previewProxy: deps.previewProxy,
|
|
@@ -121577,7 +121865,11 @@ async function createDaemon(deps) {
|
|
|
121577
121865
|
}
|
|
121578
121866
|
}
|
|
121579
121867
|
function spawnClaudeTaskSubprocess(args) {
|
|
121580
|
-
const {
|
|
121868
|
+
const {
|
|
121869
|
+
server: harnessServer,
|
|
121870
|
+
setTaskId: setHarnessTaskId,
|
|
121871
|
+
setEpoch: setHarnessEpoch
|
|
121872
|
+
} = createHarnessMcpServer({
|
|
121581
121873
|
annotationStore,
|
|
121582
121874
|
deliverableStore,
|
|
121583
121875
|
dataDir: deps.dataDir,
|
|
@@ -121586,7 +121878,7 @@ async function createDaemon(deps) {
|
|
|
121586
121878
|
/** Claude in-process harness — Codex uses the HTTP path with 'codex' above. */
|
|
121587
121879
|
agentSystem: AGENT_SYSTEM_CLAUDE_CODE,
|
|
121588
121880
|
environmentKey: args.cwd,
|
|
121589
|
-
pluginsDir:
|
|
121881
|
+
pluginsDir: join79(deps.shipyardHome, "plugins"),
|
|
121590
121882
|
vizWatcher: args.vizWatcher,
|
|
121591
121883
|
mode: args.mode ?? "task",
|
|
121592
121884
|
previewProxy: deps.previewProxy,
|
|
@@ -121663,6 +121955,8 @@ async function createDaemon(deps) {
|
|
|
121663
121955
|
if (pendingNeutral !== null) {
|
|
121664
121956
|
applyClaudePendingNeutralHandoff(pendingNeutral, options, args.taskId);
|
|
121665
121957
|
}
|
|
121958
|
+
const epoch = registerSubprocessEpoch(args.taskId);
|
|
121959
|
+
setHarnessEpoch(epoch);
|
|
121666
121960
|
const subprocess = AnthropicAgentSubprocess.spawn(
|
|
121667
121961
|
deps.queryFn,
|
|
121668
121962
|
args.initialContent,
|
|
@@ -121671,6 +121965,7 @@ async function createDaemon(deps) {
|
|
|
121671
121965
|
deps.log
|
|
121672
121966
|
);
|
|
121673
121967
|
subprocess.installHarnessTaskIdSetter(setHarnessTaskId);
|
|
121968
|
+
subprocess.installHarnessEpoch(epoch);
|
|
121674
121969
|
return subprocess;
|
|
121675
121970
|
}
|
|
121676
121971
|
const lastUsageLimitBroadcastByTask = /* @__PURE__ */ new Map();
|
|
@@ -122115,7 +122410,28 @@ async function createDaemon(deps) {
|
|
|
122115
122410
|
templateStore: templateStoreEarly,
|
|
122116
122411
|
getDefaultComposerSettings,
|
|
122117
122412
|
getCompactionPrefs: (runtime) => cachedCompactionByRuntime.get(runtime) ?? null,
|
|
122118
|
-
resolveProfileForModel: (modelId) => profileRegistry.findByModelId(modelId)?.id ?? null
|
|
122413
|
+
resolveProfileForModel: (modelId) => profileRegistry.findByModelId(modelId)?.id ?? null,
|
|
122414
|
+
/**
|
|
122415
|
+
* ST9: Tear down HTTP MCP bearers from the source runtime when a
|
|
122416
|
+
* cross-runtime switch fires. Called before `stopPrimary()` so the
|
|
122417
|
+
* source identity is still unambiguous. Codex uses per-task bearer
|
|
122418
|
+
* (`unregisterTask`); Cursor uses per-runner bearer (`unregisterRunner`
|
|
122419
|
+
* is handled by its own `onRunnerExited` path — Cursor teardown is
|
|
122420
|
+
* runner-scoped, not task-scoped, so `unregisterTask` is a no-op for
|
|
122421
|
+
* Cursor but safe to call). Only fires when `harnessHttpServer` is
|
|
122422
|
+
* active (Codex / Cursor require it).
|
|
122423
|
+
*/
|
|
122424
|
+
onCrossRuntimeSwitch: (taskId, sourceRuntimeId, _destRuntimeId) => {
|
|
122425
|
+
if (sourceRuntimeId !== "codex") return;
|
|
122426
|
+
if (!harnessHttpServer) return;
|
|
122427
|
+
void harnessHttpServer.unregisterTask(taskId).catch(() => {
|
|
122428
|
+
});
|
|
122429
|
+
deps.log({
|
|
122430
|
+
event: "cross_runtime_http_bearer_unregistered",
|
|
122431
|
+
taskId,
|
|
122432
|
+
sourceRuntimeId
|
|
122433
|
+
});
|
|
122434
|
+
}
|
|
122119
122435
|
});
|
|
122120
122436
|
const vizPreview = createVizPreviewRegistry({
|
|
122121
122437
|
dataDir: deps.dataDir,
|
|
@@ -122577,7 +122893,7 @@ async function createDaemon(deps) {
|
|
|
122577
122893
|
const stallProfilerConfig = getStallProfilerConfig();
|
|
122578
122894
|
const stallProfiler = new StallProfiler({
|
|
122579
122895
|
log: deps.log,
|
|
122580
|
-
outDir:
|
|
122896
|
+
outDir: join79(deps.dataDir, "stall-profiles"),
|
|
122581
122897
|
thresholdMs: stallProfilerConfig.thresholdMs,
|
|
122582
122898
|
captureMs: stallProfilerConfig.captureMs,
|
|
122583
122899
|
rateLimitMs: stallProfilerConfig.rateLimitMs
|
|
@@ -123180,7 +123496,7 @@ import { existsSync as existsSync12 } from "fs";
|
|
|
123180
123496
|
import { execFile as execFile12, spawn as spawn13 } from "child_process";
|
|
123181
123497
|
import { createHash as createHash12 } from "crypto";
|
|
123182
123498
|
import { chmod as chmod3, mkdir as mkdir37, readFile as readFile49, rename as rename23, unlink as unlink18, writeFile as writeFile29 } from "fs/promises";
|
|
123183
|
-
import { join as
|
|
123499
|
+
import { join as join80 } from "path";
|
|
123184
123500
|
|
|
123185
123501
|
// src/services/bootstrap/self-update-installer-scripts.ts
|
|
123186
123502
|
function buildPosixInstallerScript(params) {
|
|
@@ -123582,7 +123898,7 @@ async function downloadTarball(url, destPath, fetchFn) {
|
|
|
123582
123898
|
throw new Error(`download failed: HTTP ${response.status} ${response.statusText}`);
|
|
123583
123899
|
}
|
|
123584
123900
|
const bytes = new Uint8Array(await response.arrayBuffer());
|
|
123585
|
-
await mkdir37(
|
|
123901
|
+
await mkdir37(join80(destPath, ".."), { recursive: true });
|
|
123586
123902
|
try {
|
|
123587
123903
|
await writeFile29(tmpPath, bytes);
|
|
123588
123904
|
await rename23(tmpPath, destPath);
|
|
@@ -123612,7 +123928,7 @@ async function verifyChecksum(path5, expectedHash) {
|
|
|
123612
123928
|
}
|
|
123613
123929
|
}
|
|
123614
123930
|
async function stageInstallerScript(scriptPath, params) {
|
|
123615
|
-
await mkdir37(
|
|
123931
|
+
await mkdir37(join80(scriptPath, ".."), { recursive: true });
|
|
123616
123932
|
const body = process.platform === "win32" ? buildWindowsInstallerScript(params) : buildPosixInstallerScript(params);
|
|
123617
123933
|
await writeFile29(scriptPath, body);
|
|
123618
123934
|
await chmod3(scriptPath, 493);
|
|
@@ -123662,16 +123978,16 @@ function buildInstallerParams(state, deps) {
|
|
|
123662
123978
|
targetVersion: state.resolved.version,
|
|
123663
123979
|
previousVersion: deps.currentVersion,
|
|
123664
123980
|
parentPid: deps.pid,
|
|
123665
|
-
statusFilePath:
|
|
123666
|
-
pidFilePath:
|
|
123667
|
-
logPath:
|
|
123668
|
-
snapshotPath:
|
|
123981
|
+
statusFilePath: join80(deps.shipyardHome, "update-status.json"),
|
|
123982
|
+
pidFilePath: join80(deps.shipyardHome, "daemon.pid"),
|
|
123983
|
+
logPath: join80(deps.shipyardHome, "updates", `install-${deps.pid}.log`),
|
|
123984
|
+
snapshotPath: join80(deps.shipyardHome, "updates", `rollback-${deps.currentVersion}`),
|
|
123669
123985
|
npmBin: "npm"
|
|
123670
123986
|
};
|
|
123671
123987
|
}
|
|
123672
123988
|
function tarballPathFor(shipyardHome, version, shasum) {
|
|
123673
123989
|
const shaPrefix = shasum.slice(0, 12);
|
|
123674
|
-
return
|
|
123990
|
+
return join80(shipyardHome, "updates", `${version}-${shaPrefix}.tgz`);
|
|
123675
123991
|
}
|
|
123676
123992
|
async function runResolveStep(step, state, deps) {
|
|
123677
123993
|
const resolver = deps.resolveVersion ?? defaultResolveVersion;
|
|
@@ -124746,7 +125062,7 @@ function buildLocalDirectChannelCallbacks(deps) {
|
|
|
124746
125062
|
|
|
124747
125063
|
// src/services/skills-cache/codex-skills-cache.ts
|
|
124748
125064
|
import { mkdir as mkdir38, readFile as readFile50, rename as rename24, writeFile as writeFile30 } from "fs/promises";
|
|
124749
|
-
import { dirname as dirname37, join as
|
|
125065
|
+
import { dirname as dirname37, join as join81 } from "path";
|
|
124750
125066
|
var CACHE_FILENAME = "codex-skills-cache.json";
|
|
124751
125067
|
var SkillInfoCacheEntrySchema = external_exports.object({
|
|
124752
125068
|
name: external_exports.string(),
|
|
@@ -124763,7 +125079,7 @@ var CodexSkillsCacheFileSchema = external_exports.object({
|
|
|
124763
125079
|
skills: external_exports.array(SkillInfoCacheEntrySchema)
|
|
124764
125080
|
});
|
|
124765
125081
|
function defaultCodexSkillsCachePath(shipyardHome) {
|
|
124766
|
-
return
|
|
125082
|
+
return join81(shipyardHome, "state", CACHE_FILENAME);
|
|
124767
125083
|
}
|
|
124768
125084
|
async function loadCodexSkillsCache(path5) {
|
|
124769
125085
|
let raw;
|
|
@@ -124827,11 +125143,11 @@ async function saveCodexSkillsCache(path5, cache2) {
|
|
|
124827
125143
|
// src/services/skills-mirror/manager.ts
|
|
124828
125144
|
import { lstat, mkdir as mkdir40, readlink, stat as stat18, symlink, unlink as unlink20 } from "fs/promises";
|
|
124829
125145
|
import { homedir as homedir13 } from "os";
|
|
124830
|
-
import { dirname as dirname39, join as
|
|
125146
|
+
import { dirname as dirname39, join as join83 } from "path";
|
|
124831
125147
|
|
|
124832
125148
|
// src/services/skills-mirror/manifest.ts
|
|
124833
125149
|
import { mkdir as mkdir39, readFile as readFile51, rename as rename25, unlink as unlink19, writeFile as writeFile31 } from "fs/promises";
|
|
124834
|
-
import { dirname as dirname38, join as
|
|
125150
|
+
import { dirname as dirname38, join as join82 } from "path";
|
|
124835
125151
|
var MANIFEST_VERSION = 1;
|
|
124836
125152
|
var ManifestEntrySchema = external_exports.object({
|
|
124837
125153
|
/** Display name of the skill (e.g. `qa`, or `plugin:name` when namespaced). */
|
|
@@ -124851,7 +125167,7 @@ function emptyManifest() {
|
|
|
124851
125167
|
return { version: MANIFEST_VERSION, entries: [] };
|
|
124852
125168
|
}
|
|
124853
125169
|
function defaultManifestPath(shipyardHome) {
|
|
124854
|
-
return
|
|
125170
|
+
return join82(shipyardHome, "state", "skill-mirror-manifest.json");
|
|
124855
125171
|
}
|
|
124856
125172
|
async function loadManifest(path5) {
|
|
124857
125173
|
try {
|
|
@@ -124882,15 +125198,15 @@ async function deleteManifest(path5) {
|
|
|
124882
125198
|
function defaultPaths() {
|
|
124883
125199
|
const home = homedir13();
|
|
124884
125200
|
return {
|
|
124885
|
-
claudeSkillsDir:
|
|
124886
|
-
codexSkillsDir:
|
|
125201
|
+
claudeSkillsDir: join83(home, ".claude", "skills"),
|
|
125202
|
+
codexSkillsDir: join83(home, ".agents", "skills"),
|
|
124887
125203
|
manifestPath: defaultManifestPath(getShipyardHome())
|
|
124888
125204
|
};
|
|
124889
125205
|
}
|
|
124890
125206
|
function plannedSymlinkPath(skill, paths) {
|
|
124891
125207
|
const linkName = skill.namespace ? `${skill.namespace}:${skill.name}` : skill.name;
|
|
124892
|
-
if (skill.sourceAgent === "claude-code") return
|
|
124893
|
-
if (skill.sourceAgent === "codex") return
|
|
125208
|
+
if (skill.sourceAgent === "claude-code") return join83(paths.codexSkillsDir, linkName);
|
|
125209
|
+
if (skill.sourceAgent === "codex") return join83(paths.claudeSkillsDir, linkName);
|
|
124894
125210
|
return null;
|
|
124895
125211
|
}
|
|
124896
125212
|
function isPermissionError(err3) {
|
|
@@ -125103,7 +125419,7 @@ async function ensureMirror(skills, config, paths = defaultPaths()) {
|
|
|
125103
125419
|
|
|
125104
125420
|
// src/services/skills-mirror/prefs.ts
|
|
125105
125421
|
import { mkdir as mkdir41, readFile as readFile52, rename as rename26, writeFile as writeFile32 } from "fs/promises";
|
|
125106
|
-
import { dirname as dirname40, join as
|
|
125422
|
+
import { dirname as dirname40, join as join84 } from "path";
|
|
125107
125423
|
var SkillsMirrorPrefsSchema = external_exports.object({
|
|
125108
125424
|
enabled: external_exports.boolean().default(true)
|
|
125109
125425
|
});
|
|
@@ -125112,7 +125428,7 @@ function defaultSkillsMirrorPrefs() {
|
|
|
125112
125428
|
return { enabled: true };
|
|
125113
125429
|
}
|
|
125114
125430
|
function prefsPath(dataDir) {
|
|
125115
|
-
return
|
|
125431
|
+
return join84(dataDir, FILENAME);
|
|
125116
125432
|
}
|
|
125117
125433
|
async function loadSkillsMirrorPrefs(dataDir) {
|
|
125118
125434
|
try {
|
|
@@ -125161,7 +125477,7 @@ async function reconcileSkillsMirror(args) {
|
|
|
125161
125477
|
// src/services/storage/daemon-settings-store.ts
|
|
125162
125478
|
import { createHash as createHash13 } from "crypto";
|
|
125163
125479
|
import { mkdir as mkdir42, readFile as readFile53 } from "fs/promises";
|
|
125164
|
-
import { join as
|
|
125480
|
+
import { join as join85 } from "path";
|
|
125165
125481
|
var ProjectSettingsSchema = external_exports.object({
|
|
125166
125482
|
disabledMcpServers: external_exports.array(external_exports.string()).optional(),
|
|
125167
125483
|
previewMigrationV36Done: external_exports.boolean().default(false)
|
|
@@ -125170,9 +125486,9 @@ function hashProjectPath(projectPath) {
|
|
|
125170
125486
|
return createHash13("sha256").update(projectPath).digest("hex").slice(0, 16);
|
|
125171
125487
|
}
|
|
125172
125488
|
function buildDaemonSettingsStore(dataDir) {
|
|
125173
|
-
const settingsDir =
|
|
125489
|
+
const settingsDir = join85(dataDir, "settings");
|
|
125174
125490
|
function settingsPath(projectPath) {
|
|
125175
|
-
return
|
|
125491
|
+
return join85(settingsDir, `${hashProjectPath(projectPath)}.json`);
|
|
125176
125492
|
}
|
|
125177
125493
|
async function ensureDir() {
|
|
125178
125494
|
await mkdir42(settingsDir, { recursive: true });
|
|
@@ -125197,12 +125513,12 @@ function buildDaemonSettingsStore(dataDir) {
|
|
|
125197
125513
|
|
|
125198
125514
|
// src/services/storage/plugin-config-store.ts
|
|
125199
125515
|
import { mkdir as mkdir43, readFile as readFile54 } from "fs/promises";
|
|
125200
|
-
import { join as
|
|
125516
|
+
import { join as join86 } from "path";
|
|
125201
125517
|
function buildPluginConfigStore(pluginsDir) {
|
|
125202
125518
|
const cache2 = /* @__PURE__ */ new Map();
|
|
125203
125519
|
const writeQueues = /* @__PURE__ */ new Map();
|
|
125204
125520
|
function configPath(pluginId) {
|
|
125205
|
-
return
|
|
125521
|
+
return join86(pluginsDir, pluginId, "config.json");
|
|
125206
125522
|
}
|
|
125207
125523
|
async function readConfigFromDisk(pluginId) {
|
|
125208
125524
|
const fp = configPath(pluginId);
|
|
@@ -125256,7 +125572,7 @@ function buildPluginConfigStore(pluginsDir) {
|
|
|
125256
125572
|
const fresh = await readConfigFromDisk(pluginId);
|
|
125257
125573
|
fresh[key] = value;
|
|
125258
125574
|
cache2.set(pluginId, fresh);
|
|
125259
|
-
await mkdir43(
|
|
125575
|
+
await mkdir43(join86(pluginsDir, pluginId), { recursive: true });
|
|
125260
125576
|
await atomicWriteFile(configPath(pluginId), JSON.stringify(fresh, null, 2));
|
|
125261
125577
|
})
|
|
125262
125578
|
);
|
|
@@ -125502,7 +125818,7 @@ async function serve(options = {}) {
|
|
|
125502
125818
|
}
|
|
125503
125819
|
async function runServeBody(options, captureRefs) {
|
|
125504
125820
|
const shipyardHome = options.shipyardHome ?? getShipyardHome();
|
|
125505
|
-
const dataDir =
|
|
125821
|
+
const dataDir = join87(shipyardHome, options.isDev ? "data-dev" : "data");
|
|
125506
125822
|
const log = createChildLogger({ mode: "serve" });
|
|
125507
125823
|
log.info(
|
|
125508
125824
|
{ event: "daemon_start", version: getDaemonVersion(), pid: process.pid },
|
|
@@ -125510,7 +125826,7 @@ async function runServeBody(options, captureRefs) {
|
|
|
125510
125826
|
);
|
|
125511
125827
|
const { workspaceRoot, unscopedWorkspace, unscopedReason } = await resolveWorkspaceScope();
|
|
125512
125828
|
registerBuiltinPlugins();
|
|
125513
|
-
const pluginConfigStore = buildPluginConfigStore(
|
|
125829
|
+
const pluginConfigStore = buildPluginConfigStore(join87(dataDir, "plugins"));
|
|
125514
125830
|
await mkdir44(dataDir, { recursive: true });
|
|
125515
125831
|
log.info(
|
|
125516
125832
|
{
|
|
@@ -125603,9 +125919,9 @@ async function runServeBody(options, captureRefs) {
|
|
|
125603
125919
|
await bootstrapPhase("pid_sweep_orphans", () => pidTracker.sweepOrphans(logAdapter));
|
|
125604
125920
|
await bootstrapPhase(
|
|
125605
125921
|
"legacy_epoch_prune",
|
|
125606
|
-
() => pruneOldEpochData(
|
|
125922
|
+
() => pruneOldEpochData(join87(dataDir, "loro"), LEGACY_EPOCH, logAdapter)
|
|
125607
125923
|
);
|
|
125608
|
-
const storage = new FileStorageAdapter(
|
|
125924
|
+
const storage = new FileStorageAdapter(join87(dataDir, "loro"));
|
|
125609
125925
|
const personalWebrtcAdapter = new WebRtcDataChannelAdapter();
|
|
125610
125926
|
const peerRoleRegistry = createPeerRoleRegistry();
|
|
125611
125927
|
const presencePoolRef = { pool: {} };
|
|
@@ -125713,14 +126029,14 @@ async function runServeBody(options, captureRefs) {
|
|
|
125713
126029
|
current: []
|
|
125714
126030
|
};
|
|
125715
126031
|
const terminalPtys = /* @__PURE__ */ new Map();
|
|
125716
|
-
const terminalLogsDir =
|
|
126032
|
+
const terminalLogsDir = join87(shipyardHome, "data", "terminals");
|
|
125717
126033
|
await mkdir44(terminalLogsDir, { recursive: true, mode: 448 });
|
|
125718
126034
|
const publishedArtifactStore = createPublishedArtifactStore({
|
|
125719
|
-
rootDir:
|
|
126035
|
+
rootDir: join87(dataDir, "published"),
|
|
125720
126036
|
log: logAdapter
|
|
125721
126037
|
});
|
|
125722
126038
|
const previewStateStore = createPreviewStateStore({
|
|
125723
|
-
rootDir:
|
|
126039
|
+
rootDir: join87(dataDir, "preview-state"),
|
|
125724
126040
|
logger: log
|
|
125725
126041
|
});
|
|
125726
126042
|
let codexSkillsApplyScopedPatchRef = null;
|
|
@@ -125799,7 +126115,7 @@ async function runServeBody(options, captureRefs) {
|
|
|
125799
126115
|
daemon.healthMetrics.start();
|
|
125800
126116
|
publishedArtifactStore.setSendControlMessage((msg) => daemon.taskManager.broadcastControl(msg));
|
|
125801
126117
|
previewStateStore.setSendControlMessage((msg) => daemon.taskManager.broadcastControl(msg));
|
|
125802
|
-
const pluginsDir =
|
|
126118
|
+
const pluginsDir = join87(shipyardHome, "plugins");
|
|
125803
126119
|
await mkdir44(pluginsDir, { recursive: true });
|
|
125804
126120
|
let loadedPlugins = [];
|
|
125805
126121
|
const loadedPluginsRef = {
|
|
@@ -126324,4 +126640,4 @@ export {
|
|
|
126324
126640
|
decideWorkspaceScope,
|
|
126325
126641
|
serve
|
|
126326
126642
|
};
|
|
126327
|
-
//# sourceMappingURL=serve-
|
|
126643
|
+
//# sourceMappingURL=serve-MSZSF5JT.js.map
|