@schoolai/shipyard 3.2.3-rc.20260422.2 → 3.2.3-rc.20260422.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +2 -2
- package/dist/{serve-3FTGY4YL.js → serve-ZAI7K2HR.js} +291 -65
- package/dist/{serve-3FTGY4YL.js.map → serve-ZAI7K2HR.js.map} +1 -1
- package/dist/{start-4KHICMP2.js → start-NH5IIB6O.js} +2 -2
- package/package.json +1 -1
- /package/dist/{start-4KHICMP2.js.map → start-NH5IIB6O.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -106,7 +106,7 @@ async function handleSubcommand() {
|
|
|
106
106
|
return true;
|
|
107
107
|
}
|
|
108
108
|
if (subcommand === "start") {
|
|
109
|
-
const { startCommand } = await import("./start-
|
|
109
|
+
const { startCommand } = await import("./start-NH5IIB6O.js");
|
|
110
110
|
await startCommand();
|
|
111
111
|
return true;
|
|
112
112
|
}
|
|
@@ -123,7 +123,7 @@ async function main() {
|
|
|
123
123
|
const args = parseCliArgs();
|
|
124
124
|
if (args.serve) {
|
|
125
125
|
await loadAuthFromConfig(env);
|
|
126
|
-
const { serve } = await import("./serve-
|
|
126
|
+
const { serve } = await import("./serve-ZAI7K2HR.js");
|
|
127
127
|
return serve({ isDev: env.SHIPYARD_DEV });
|
|
128
128
|
}
|
|
129
129
|
logger.error("Use `shipyard start` to run the daemon. Use --help for usage.");
|
|
@@ -87774,6 +87774,7 @@ function skipForMainChannel(content) {
|
|
|
87774
87774
|
|
|
87775
87775
|
// src/services/plan/plan-handler.ts
|
|
87776
87776
|
import { existsSync as existsSync7, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
|
|
87777
|
+
import { readFile as readFile30 } from "fs/promises";
|
|
87777
87778
|
import { homedir as homedir4 } from "os";
|
|
87778
87779
|
import { join as join39 } from "path";
|
|
87779
87780
|
|
|
@@ -87851,6 +87852,80 @@ var PlanFileBridge = class _PlanFileBridge {
|
|
|
87851
87852
|
});
|
|
87852
87853
|
}, PERIODIC_REREAD_MS);
|
|
87853
87854
|
}
|
|
87855
|
+
/**
|
|
87856
|
+
* Re-initialize the bridge for a plan file known from a prior daemon session.
|
|
87857
|
+
*
|
|
87858
|
+
* Differs from `attach()` in that the caller explicitly decides whether to
|
|
87859
|
+
* preserve CRDT content. This lets PlanHandler do a three-way compare
|
|
87860
|
+
* (file vs CRDT vs last stored PlanVersion) and tell the bridge which side
|
|
87861
|
+
* is authoritative:
|
|
87862
|
+
*
|
|
87863
|
+
* - `preserveCrdt: false` — file is truth (fresh daemon start, or Claude
|
|
87864
|
+
* rewrote the plan while the daemon was down). Overwrite CRDT with file
|
|
87865
|
+
* content, same as `attach()`.
|
|
87866
|
+
* - `preserveCrdt: true` — CRDT has edits not yet written to disk (browser
|
|
87867
|
+
* edited before the daemon's debounced write-back fired). Keep CRDT
|
|
87868
|
+
* content; the subscription below will flush it on the next loro change.
|
|
87869
|
+
*
|
|
87870
|
+
* Returns `{ fileContent }` so callers can emit catch-up versions, or
|
|
87871
|
+
* `null` if the file is unreadable.
|
|
87872
|
+
*/
|
|
87873
|
+
async reattach(filePath, options) {
|
|
87874
|
+
if (this.#disposed) return null;
|
|
87875
|
+
this.#dirWatcher?.close();
|
|
87876
|
+
this.#dirWatcher = null;
|
|
87877
|
+
this.#crdtUnsub?.();
|
|
87878
|
+
this.#crdtUnsub = null;
|
|
87879
|
+
if (this.#periodicRereadTimer) {
|
|
87880
|
+
clearInterval(this.#periodicRereadTimer);
|
|
87881
|
+
this.#periodicRereadTimer = null;
|
|
87882
|
+
}
|
|
87883
|
+
let fileContent;
|
|
87884
|
+
try {
|
|
87885
|
+
fileContent = await this.#readFileWithRetry(filePath);
|
|
87886
|
+
} catch (err) {
|
|
87887
|
+
this.#config.log({
|
|
87888
|
+
event: "plan_bridge_reattach_read_failed",
|
|
87889
|
+
taskId: this.#config.taskId,
|
|
87890
|
+
filePath,
|
|
87891
|
+
error: err instanceof Error ? err.message : String(err)
|
|
87892
|
+
});
|
|
87893
|
+
return null;
|
|
87894
|
+
}
|
|
87895
|
+
this.#filePath = filePath;
|
|
87896
|
+
this.#config.planRepo.setMetadata(this.#config.taskId, filePath);
|
|
87897
|
+
this.#lastWrittenHash = contentHash(fileContent);
|
|
87898
|
+
if (!options.preserveCrdt) {
|
|
87899
|
+
this.#config.planRepo.updateContent(this.#config.taskId, fileContent);
|
|
87900
|
+
}
|
|
87901
|
+
this.#hasAttachedContent = true;
|
|
87902
|
+
this.#config.log({
|
|
87903
|
+
event: "plan_bridge_reattached",
|
|
87904
|
+
taskId: this.#config.taskId,
|
|
87905
|
+
filePath,
|
|
87906
|
+
crdtPreserved: options.preserveCrdt,
|
|
87907
|
+
fileLength: fileContent.length
|
|
87908
|
+
});
|
|
87909
|
+
this.#startDirectoryWatcher(filePath);
|
|
87910
|
+
this.#startCrdtSubscription();
|
|
87911
|
+
this.#periodicRereadTimer = setInterval(() => {
|
|
87912
|
+
this.#handleFileChanged().catch(() => {
|
|
87913
|
+
});
|
|
87914
|
+
}, PERIODIC_REREAD_MS);
|
|
87915
|
+
if (options.preserveCrdt) {
|
|
87916
|
+
try {
|
|
87917
|
+
await this.flushWriteBack();
|
|
87918
|
+
} catch (err) {
|
|
87919
|
+
this.#config.log({
|
|
87920
|
+
event: "plan_bridge_reattach_flush_failed",
|
|
87921
|
+
taskId: this.#config.taskId,
|
|
87922
|
+
filePath,
|
|
87923
|
+
error: err instanceof Error ? err.message : String(err)
|
|
87924
|
+
});
|
|
87925
|
+
}
|
|
87926
|
+
}
|
|
87927
|
+
return { fileContent };
|
|
87928
|
+
}
|
|
87854
87929
|
/**
|
|
87855
87930
|
* Watch the plans DIRECTORY (not the file) for changes.
|
|
87856
87931
|
* This survives inode changes from atomic writes (tmp + rename).
|
|
@@ -88273,8 +88348,177 @@ var PlanHandler = class {
|
|
|
88273
88348
|
this.#lastPersistedPlanDetection = deps.initialPlanDetection;
|
|
88274
88349
|
this.#planPublished = true;
|
|
88275
88350
|
this.#processedPlanToolUseIds.add(deps.initialPlanDetection.toolUseId);
|
|
88351
|
+
const seedFilePath = deps.initialPlanDetection.filePath;
|
|
88352
|
+
const seedToolUseId = deps.initialPlanDetection.toolUseId;
|
|
88353
|
+
deps.enqueueAsync(() => this.#rehydratePlanFileBridge(seedFilePath, seedToolUseId));
|
|
88354
|
+
}
|
|
88355
|
+
}
|
|
88356
|
+
async #rehydratePlanFileBridge(filePath, toolUseId) {
|
|
88357
|
+
if (this.#deps.isDisposed()) return;
|
|
88358
|
+
if (!existsSync7(filePath)) {
|
|
88359
|
+
this.#deps.log({
|
|
88360
|
+
event: "plan_bridge_rehydrate_file_missing",
|
|
88361
|
+
taskId: this.#deps.taskId,
|
|
88362
|
+
filePath
|
|
88363
|
+
});
|
|
88364
|
+
return;
|
|
88365
|
+
}
|
|
88366
|
+
const fileContent = await this.#readFileForRehydrate(filePath);
|
|
88367
|
+
if (fileContent === null || this.#deps.isDisposed()) return;
|
|
88368
|
+
const versions = await this.#deps.annotationStore.getPlanVersions(this.#deps.taskId);
|
|
88369
|
+
if (this.#deps.isDisposed()) return;
|
|
88370
|
+
const lastVersionMarkdown = versions.at(-1)?.markdown ?? "";
|
|
88371
|
+
const preserveCrdt = this.#shouldPreserveCrdt(fileContent, lastVersionMarkdown);
|
|
88372
|
+
const result = await this.#ensureBridgeAttached(filePath, toolUseId, {
|
|
88373
|
+
mode: "rehydrate",
|
|
88374
|
+
preserveCrdt
|
|
88375
|
+
});
|
|
88376
|
+
if (!result || this.#deps.isDisposed()) return;
|
|
88377
|
+
await this.#maybeEmitRehydrateCatchup(lastVersionMarkdown, preserveCrdt, toolUseId);
|
|
88378
|
+
}
|
|
88379
|
+
/**
|
|
88380
|
+
* Three-way compare of {file on disk, CRDT content, last stored PlanVersion}:
|
|
88381
|
+
*
|
|
88382
|
+
* Case 1 (all equal) → preserveCrdt=false (no-op attach)
|
|
88383
|
+
* Case 2 (file drifted) → preserveCrdt=false (file wins)
|
|
88384
|
+
* Case 3 (browser-edited CRDT) → preserveCrdt=true (keep in-flight edits)
|
|
88385
|
+
* Case 4 (both drifted) → preserveCrdt=false (file wins)
|
|
88386
|
+
*
|
|
88387
|
+
* Case 3 also requires a non-empty lastVersionMarkdown — otherwise a
|
|
88388
|
+
* brand-new task with no prior stored versions would preserve whatever
|
|
88389
|
+
* happens to be in CRDT (e.g. a stale browser session's edits on a fresh
|
|
88390
|
+
* epoch) over an authoritative empty file.
|
|
88391
|
+
*/
|
|
88392
|
+
#shouldPreserveCrdt(fileContent, lastVersionMarkdown) {
|
|
88393
|
+
if (lastVersionMarkdown === "") return false;
|
|
88394
|
+
const crdtContent = this.#deps.planRepo.getContent(this.#deps.taskId);
|
|
88395
|
+
const fileMatchesLast = fileContent === lastVersionMarkdown;
|
|
88396
|
+
const crdtHasUnsavedEdits = crdtContent.length > 0 && crdtContent !== lastVersionMarkdown;
|
|
88397
|
+
return fileMatchesLast && crdtHasUnsavedEdits;
|
|
88398
|
+
}
|
|
88399
|
+
/**
|
|
88400
|
+
* Post-attach catch-up: read whatever CRDT now holds (file content or
|
|
88401
|
+
* preserved CRDT content) and emit a single version if it drifted from
|
|
88402
|
+
* `lastVersionMarkdown`. Covers file-drifted and browser-edited cases.
|
|
88403
|
+
*
|
|
88404
|
+
* Source labeling follows authoritative side: preserved CRDT = 'human',
|
|
88405
|
+
* file-overwritten CRDT = 'agent'. Mislabeling would corrupt
|
|
88406
|
+
* `findLastAgentVersion`'s baseline for plan-review diffs.
|
|
88407
|
+
*/
|
|
88408
|
+
async #maybeEmitRehydrateCatchup(lastVersionMarkdown, preserveCrdt, toolUseId) {
|
|
88409
|
+
const postAttachMarkdown = this.#deps.planRepo.getContent(this.#deps.taskId);
|
|
88410
|
+
if (postAttachMarkdown.length === 0 || postAttachMarkdown === lastVersionMarkdown) return;
|
|
88411
|
+
const source = preserveCrdt ? "human" : "agent";
|
|
88412
|
+
await this.#emitCatchupVersion(postAttachMarkdown, toolUseId, source);
|
|
88413
|
+
}
|
|
88414
|
+
async #readFileForRehydrate(filePath) {
|
|
88415
|
+
try {
|
|
88416
|
+
return await readFile30(filePath, "utf-8");
|
|
88417
|
+
} catch (err) {
|
|
88418
|
+
this.#deps.log({
|
|
88419
|
+
event: "plan_bridge_rehydrate_read_failed",
|
|
88420
|
+
taskId: this.#deps.taskId,
|
|
88421
|
+
filePath,
|
|
88422
|
+
error: err instanceof Error ? err.message : String(err)
|
|
88423
|
+
});
|
|
88424
|
+
return null;
|
|
88425
|
+
}
|
|
88426
|
+
}
|
|
88427
|
+
async #emitCatchupVersion(markdown, toolUseId, source) {
|
|
88428
|
+
const version = {
|
|
88429
|
+
markdown,
|
|
88430
|
+
timestamp: Date.now(),
|
|
88431
|
+
source,
|
|
88432
|
+
toolUseId
|
|
88433
|
+
};
|
|
88434
|
+
try {
|
|
88435
|
+
await this.#deps.annotationStore.addPlanVersion(this.#deps.taskId, version);
|
|
88436
|
+
const msg = {
|
|
88437
|
+
type: "annotation_version_added",
|
|
88438
|
+
taskId: this.#deps.taskId,
|
|
88439
|
+
version
|
|
88440
|
+
};
|
|
88441
|
+
const send = this.#deps.getSendControlMessage();
|
|
88442
|
+
if (send) {
|
|
88443
|
+
send(msg);
|
|
88444
|
+
} else {
|
|
88445
|
+
this.#deps.enqueueControlMessage(msg);
|
|
88446
|
+
}
|
|
88447
|
+
} catch (err) {
|
|
88448
|
+
this.#deps.log({
|
|
88449
|
+
event: "plan_version_add_failed",
|
|
88450
|
+
taskId: this.#deps.taskId,
|
|
88451
|
+
error: err instanceof Error ? err.message : String(err)
|
|
88452
|
+
});
|
|
88276
88453
|
}
|
|
88277
88454
|
}
|
|
88455
|
+
/**
|
|
88456
|
+
* Ensure a PlanFileBridge is attached for this task at the given file path.
|
|
88457
|
+
* Creates the bridge lazily and routes attach vs reattach based on options:
|
|
88458
|
+
*
|
|
88459
|
+
* - `mode: 'fresh'` — new ExitPlanMode cycle, no prior context. Uses
|
|
88460
|
+
* `attach()` which overwrites CRDT with file content.
|
|
88461
|
+
* - `mode: 'rehydrate'` — daemon restart. Uses `reattach()` with an
|
|
88462
|
+
* explicit `preserveCrdt` flag so the caller's three-way compare picks
|
|
88463
|
+
* the authoritative side.
|
|
88464
|
+
*
|
|
88465
|
+
* Noop if the bridge is already attached to the same filePath. Re-attaches
|
|
88466
|
+
* if the bridge points at a different filePath (Scenario A: a 2nd
|
|
88467
|
+
* ExitPlanMode cycle writes to a new UUID).
|
|
88468
|
+
*/
|
|
88469
|
+
async #ensureBridgeAttached(filePath, toolUseId, options) {
|
|
88470
|
+
if (this.#deps.isDisposed()) return null;
|
|
88471
|
+
const isFirstAttach = !this.#planFileBridge;
|
|
88472
|
+
if (!this.#planFileBridge) {
|
|
88473
|
+
this.#planFileBridge = this.#createPlanFileBridge(toolUseId);
|
|
88474
|
+
} else if (this.#planFileBridge.filePath === filePath) {
|
|
88475
|
+
return { isFirstAttach: false };
|
|
88476
|
+
}
|
|
88477
|
+
if (options.mode === "rehydrate") {
|
|
88478
|
+
const result = await this.#planFileBridge.reattach(filePath, {
|
|
88479
|
+
preserveCrdt: options.preserveCrdt
|
|
88480
|
+
});
|
|
88481
|
+
if (!result) return null;
|
|
88482
|
+
} else {
|
|
88483
|
+
await this.#planFileBridge.attach(filePath);
|
|
88484
|
+
}
|
|
88485
|
+
if (this.#deps.isDisposed()) return null;
|
|
88486
|
+
return { isFirstAttach };
|
|
88487
|
+
}
|
|
88488
|
+
#createPlanFileBridge(fallbackToolUseId) {
|
|
88489
|
+
return new PlanFileBridge({
|
|
88490
|
+
taskId: this.#deps.taskId,
|
|
88491
|
+
planRepo: this.#deps.planRepo,
|
|
88492
|
+
log: this.#deps.log,
|
|
88493
|
+
onBeforeContentUpdate: (currentMarkdown) => {
|
|
88494
|
+
const version = {
|
|
88495
|
+
markdown: currentMarkdown,
|
|
88496
|
+
timestamp: Date.now(),
|
|
88497
|
+
source: "agent",
|
|
88498
|
+
toolUseId: this.#lastPlanDetection?.toolUseId ?? fallbackToolUseId
|
|
88499
|
+
};
|
|
88500
|
+
this.#deps.annotationStore.addPlanVersion(this.#deps.taskId, version).then(() => {
|
|
88501
|
+
const msg = {
|
|
88502
|
+
type: "annotation_version_added",
|
|
88503
|
+
taskId: this.#deps.taskId,
|
|
88504
|
+
version
|
|
88505
|
+
};
|
|
88506
|
+
const send = this.#deps.getSendControlMessage();
|
|
88507
|
+
if (send) {
|
|
88508
|
+
send(msg);
|
|
88509
|
+
} else {
|
|
88510
|
+
this.#deps.enqueueControlMessage(msg);
|
|
88511
|
+
}
|
|
88512
|
+
}).catch((err) => {
|
|
88513
|
+
this.#deps.log({
|
|
88514
|
+
event: "plan_version_add_failed",
|
|
88515
|
+
taskId: this.#deps.taskId,
|
|
88516
|
+
error: err instanceof Error ? err.message : String(err)
|
|
88517
|
+
});
|
|
88518
|
+
});
|
|
88519
|
+
}
|
|
88520
|
+
});
|
|
88521
|
+
}
|
|
88278
88522
|
/**
|
|
88279
88523
|
* Persist a detection (or null clear) with shadow-pending semantics:
|
|
88280
88524
|
* optimistically update #lastPlanDetection so concurrent reads see the new
|
|
@@ -88410,9 +88654,10 @@ var PlanHandler = class {
|
|
|
88410
88654
|
});
|
|
88411
88655
|
}
|
|
88412
88656
|
detectPlanEvents(content) {
|
|
88413
|
-
if (this.#approvalReceived
|
|
88657
|
+
if (this.#approvalReceived) return;
|
|
88414
88658
|
for (const block2 of content) {
|
|
88415
88659
|
if (block2.type !== "tool_use" || block2.toolName !== "ExitPlanMode") continue;
|
|
88660
|
+
if (this.#processedPlanToolUseIds.has(block2.toolUseId)) continue;
|
|
88416
88661
|
this.#deps.log({
|
|
88417
88662
|
event: "exit_plan_mode_detected",
|
|
88418
88663
|
taskId: this.#deps.taskId,
|
|
@@ -88577,51 +88822,32 @@ var PlanHandler = class {
|
|
|
88577
88822
|
this.#pendingPlanAllowedPrompts.delete(toolUseId);
|
|
88578
88823
|
this.#deps.enqueueAsync(async () => {
|
|
88579
88824
|
if (this.#deps.isDisposed()) return;
|
|
88580
|
-
const
|
|
88581
|
-
|
|
88582
|
-
|
|
88583
|
-
|
|
88584
|
-
planRepo: this.#deps.planRepo,
|
|
88585
|
-
log: this.#deps.log,
|
|
88586
|
-
onBeforeContentUpdate: (currentMarkdown) => {
|
|
88587
|
-
const version = {
|
|
88588
|
-
markdown: currentMarkdown,
|
|
88589
|
-
timestamp: Date.now(),
|
|
88590
|
-
source: "agent",
|
|
88591
|
-
toolUseId: this.#lastPlanDetection?.toolUseId ?? toolUseId
|
|
88592
|
-
};
|
|
88593
|
-
this.#deps.annotationStore.addPlanVersion(this.#deps.taskId, version).then(() => {
|
|
88594
|
-
this.#deps.getSendControlMessage()?.({
|
|
88595
|
-
type: "annotation_version_added",
|
|
88596
|
-
taskId: this.#deps.taskId,
|
|
88597
|
-
version
|
|
88598
|
-
});
|
|
88599
|
-
}).catch((err) => {
|
|
88600
|
-
this.#deps.log({
|
|
88601
|
-
event: "plan_version_add_failed",
|
|
88602
|
-
taskId: this.#deps.taskId,
|
|
88603
|
-
error: err instanceof Error ? err.message : String(err)
|
|
88604
|
-
});
|
|
88605
|
-
});
|
|
88606
|
-
}
|
|
88607
|
-
});
|
|
88608
|
-
}
|
|
88609
|
-
await this.#planFileBridge.attach(filePath);
|
|
88825
|
+
const attachResult = await this.#ensureBridgeAttached(filePath, toolUseId, {
|
|
88826
|
+
mode: "fresh"
|
|
88827
|
+
});
|
|
88828
|
+
if (!attachResult) return;
|
|
88610
88829
|
const markdown = this.#deps.planRepo.getContent(this.#deps.taskId);
|
|
88611
|
-
if (
|
|
88612
|
-
const
|
|
88613
|
-
|
|
88614
|
-
|
|
88615
|
-
|
|
88616
|
-
|
|
88617
|
-
|
|
88618
|
-
|
|
88619
|
-
|
|
88620
|
-
|
|
88621
|
-
|
|
88622
|
-
|
|
88623
|
-
|
|
88830
|
+
if (markdown.length > 0) {
|
|
88831
|
+
const existingVersions = await this.#deps.annotationStore.getPlanVersions(
|
|
88832
|
+
this.#deps.taskId
|
|
88833
|
+
);
|
|
88834
|
+
const lastVersion = existingVersions.at(-1);
|
|
88835
|
+
if (lastVersion?.markdown !== markdown) {
|
|
88836
|
+
const initialVersion = {
|
|
88837
|
+
markdown,
|
|
88838
|
+
timestamp: Date.now(),
|
|
88839
|
+
source: "agent",
|
|
88840
|
+
toolUseId
|
|
88841
|
+
};
|
|
88842
|
+
await this.#deps.annotationStore.addPlanVersion(this.#deps.taskId, initialVersion);
|
|
88843
|
+
this.#deps.getSendControlMessage()?.({
|
|
88844
|
+
type: "annotation_version_added",
|
|
88845
|
+
taskId: this.#deps.taskId,
|
|
88846
|
+
version: initialVersion
|
|
88847
|
+
});
|
|
88848
|
+
}
|
|
88624
88849
|
}
|
|
88850
|
+
const isFirstAttach = attachResult.isFirstAttach;
|
|
88625
88851
|
const pendingDetection = {
|
|
88626
88852
|
toolUseId,
|
|
88627
88853
|
filePath,
|
|
@@ -90109,7 +90335,7 @@ var RewindCheckpointHandler = class {
|
|
|
90109
90335
|
};
|
|
90110
90336
|
|
|
90111
90337
|
// src/services/task/side-thread-registry.ts
|
|
90112
|
-
import { mkdir as mkdir17, readFile as
|
|
90338
|
+
import { mkdir as mkdir17, readFile as readFile31, rename as rename17, writeFile as writeFile23 } from "fs/promises";
|
|
90113
90339
|
import { dirname as dirname15, join as join40 } from "path";
|
|
90114
90340
|
var ThreadFileSchema = external_exports.object({
|
|
90115
90341
|
threads: external_exports.record(external_exports.string(), ThreadMetadataSchema)
|
|
@@ -90443,7 +90669,7 @@ var SideThreadRegistry = class {
|
|
|
90443
90669
|
const filePath = this.#filePath();
|
|
90444
90670
|
let raw;
|
|
90445
90671
|
try {
|
|
90446
|
-
raw = await
|
|
90672
|
+
raw = await readFile31(filePath, "utf-8");
|
|
90447
90673
|
} catch (err) {
|
|
90448
90674
|
if (isEnoent(err)) return;
|
|
90449
90675
|
throw err;
|
|
@@ -90882,7 +91108,7 @@ async function resolveResources(ctx, content, history2, excludeUris) {
|
|
|
90882
91108
|
|
|
90883
91109
|
// src/services/task/cc-task-file-store.ts
|
|
90884
91110
|
import { watch as watch4 } from "fs";
|
|
90885
|
-
import { readdir as readdir9, readFile as
|
|
91111
|
+
import { readdir as readdir9, readFile as readFile32 } from "fs/promises";
|
|
90886
91112
|
import { homedir as homedir6 } from "os";
|
|
90887
91113
|
import { basename as basename4, dirname as dirname16, join as join41 } from "path";
|
|
90888
91114
|
var VALID_STATUSES2 = /* @__PURE__ */ new Set(["pending", "in_progress", "completed"]);
|
|
@@ -90918,7 +91144,7 @@ function createCCTaskFileWatcher(listId, log) {
|
|
|
90918
91144
|
async function readTask(taskId) {
|
|
90919
91145
|
const filePath = join41(dir, `${taskId}.json`);
|
|
90920
91146
|
try {
|
|
90921
|
-
const raw = await
|
|
91147
|
+
const raw = await readFile32(filePath, "utf-8");
|
|
90922
91148
|
const parsed = JSON.parse(raw);
|
|
90923
91149
|
if (isCCTaskFile(parsed)) return parsed;
|
|
90924
91150
|
log?.({
|
|
@@ -97178,7 +97404,7 @@ function isPlainObject2(v2) {
|
|
|
97178
97404
|
}
|
|
97179
97405
|
|
|
97180
97406
|
// src/services/themes/theme-store.ts
|
|
97181
|
-
import { mkdir as mkdir19, readdir as readdir11, readFile as
|
|
97407
|
+
import { mkdir as mkdir19, readdir as readdir11, readFile as readFile33, rename as rename19, stat as stat8, unlink as unlink9, writeFile as writeFile26 } from "fs/promises";
|
|
97182
97408
|
import { join as join47 } from "path";
|
|
97183
97409
|
function planSeed(input) {
|
|
97184
97410
|
if (input.configExists) {
|
|
@@ -97258,7 +97484,7 @@ function buildThemeStore(dataDir) {
|
|
|
97258
97484
|
}
|
|
97259
97485
|
async function readConfigFile() {
|
|
97260
97486
|
try {
|
|
97261
|
-
const raw = await
|
|
97487
|
+
const raw = await readFile33(configPath, "utf-8");
|
|
97262
97488
|
const parsed = ThemeConfigSchema.safeParse(JSON.parse(raw));
|
|
97263
97489
|
if (!parsed.success) return null;
|
|
97264
97490
|
return parsed.data;
|
|
@@ -97277,7 +97503,7 @@ function buildThemeStore(dataDir) {
|
|
|
97277
97503
|
await atomicWrite3(themePath(id), serialized);
|
|
97278
97504
|
}
|
|
97279
97505
|
async function readThemeFile(id) {
|
|
97280
|
-
const raw = await
|
|
97506
|
+
const raw = await readFile33(themePath(id), "utf-8");
|
|
97281
97507
|
const parsed = VSCodeThemeSchema.safeParse(JSON.parse(raw));
|
|
97282
97508
|
if (!parsed.success) {
|
|
97283
97509
|
throw new Error(
|
|
@@ -97429,7 +97655,7 @@ function buildThemeStore(dataDir) {
|
|
|
97429
97655
|
}
|
|
97430
97656
|
|
|
97431
97657
|
// src/services/themes/vscode-scanner.ts
|
|
97432
|
-
import { readdir as readdir12, readFile as
|
|
97658
|
+
import { readdir as readdir12, readFile as readFile34, stat as stat9 } from "fs/promises";
|
|
97433
97659
|
import { homedir as homedir8 } from "os";
|
|
97434
97660
|
import { dirname as dirname17, join as join48, normalize as normalize5, resolve } from "path";
|
|
97435
97661
|
var VSCodeThemeEntrySchema2 = external_exports.object({
|
|
@@ -97488,7 +97714,7 @@ var PackageJsonContribSchema = external_exports.object({
|
|
|
97488
97714
|
async function tryReadPackageJson(extDir) {
|
|
97489
97715
|
let pkgRaw;
|
|
97490
97716
|
try {
|
|
97491
|
-
pkgRaw = await
|
|
97717
|
+
pkgRaw = await readFile34(join48(extDir, "package.json"), "utf-8");
|
|
97492
97718
|
} catch {
|
|
97493
97719
|
return null;
|
|
97494
97720
|
}
|
|
@@ -97558,7 +97784,7 @@ async function readVSCodeThemeWithIncludes(absolutePath) {
|
|
|
97558
97784
|
if (!validateScanPath(filePath)) {
|
|
97559
97785
|
throw new Error(`Include path outside allowed directories: ${filePath}`);
|
|
97560
97786
|
}
|
|
97561
|
-
const raw = await
|
|
97787
|
+
const raw = await readFile34(filePath, "utf-8");
|
|
97562
97788
|
const errors2 = [];
|
|
97563
97789
|
const parsed = parse3(raw, errors2, {
|
|
97564
97790
|
allowTrailingComma: true,
|
|
@@ -102221,7 +102447,7 @@ function createCollabRoomManager(deps) {
|
|
|
102221
102447
|
|
|
102222
102448
|
// src/services/file-io-handler.ts
|
|
102223
102449
|
import { execFile as execFile10, spawn as spawn6 } from "child_process";
|
|
102224
|
-
import { readdir as readdir14, readFile as
|
|
102450
|
+
import { readdir as readdir14, readFile as readFile35, realpath as realpath2, stat as stat10, unlink as unlink10, writeFile as writeFile28 } from "fs/promises";
|
|
102225
102451
|
import { normalize as normalize7, relative as relative3, resolve as resolve2 } from "path";
|
|
102226
102452
|
import { promisify as promisify7 } from "util";
|
|
102227
102453
|
|
|
@@ -102689,7 +102915,7 @@ function handleFileIOChannel(initialCwd, send, log, deps) {
|
|
|
102689
102915
|
respondError(requestId, "File too large (>10MB)");
|
|
102690
102916
|
return;
|
|
102691
102917
|
}
|
|
102692
|
-
const content = await
|
|
102918
|
+
const content = await readFile35(absPath, "utf-8");
|
|
102693
102919
|
respond({ type: "file_content", requestId, content });
|
|
102694
102920
|
} catch (err) {
|
|
102695
102921
|
respondError(requestId, formatError(err));
|
|
@@ -102883,7 +103109,7 @@ function handleFileIOChannel(initialCwd, send, log, deps) {
|
|
|
102883
103109
|
const originalContent = await readGitObject(`${mergeBase}:${filePath}`) ?? "";
|
|
102884
103110
|
let modifiedContent;
|
|
102885
103111
|
try {
|
|
102886
|
-
modifiedContent = await
|
|
103112
|
+
modifiedContent = await readFile35(resolve2(cwd, filePath), "utf-8");
|
|
102887
103113
|
} catch {
|
|
102888
103114
|
modifiedContent = "";
|
|
102889
103115
|
}
|
|
@@ -102940,7 +103166,7 @@ function handleFileIOChannel(initialCwd, send, log, deps) {
|
|
|
102940
103166
|
const indexContent = await readGitObject(`:${safeRelPath}`);
|
|
102941
103167
|
originalContent = indexContent ?? await readGitObject(`HEAD:${safeRelPath}`) ?? "";
|
|
102942
103168
|
try {
|
|
102943
|
-
modifiedContent = await
|
|
103169
|
+
modifiedContent = await readFile35(absPath, "utf-8");
|
|
102944
103170
|
} catch {
|
|
102945
103171
|
modifiedContent = "";
|
|
102946
103172
|
}
|
|
@@ -104312,7 +104538,7 @@ import { dirname as dirname21, join as join54 } from "path";
|
|
|
104312
104538
|
// src/services/bootstrap/self-update.ts
|
|
104313
104539
|
import { execFile as execFile11, spawn as spawn8 } from "child_process";
|
|
104314
104540
|
import { createHash as createHash6 } from "crypto";
|
|
104315
|
-
import { chmod as chmod3, mkdir as mkdir22, readFile as
|
|
104541
|
+
import { chmod as chmod3, mkdir as mkdir22, readFile as readFile36, rename as rename20, unlink as unlink11, writeFile as writeFile29 } from "fs/promises";
|
|
104316
104542
|
import { join as join53 } from "path";
|
|
104317
104543
|
|
|
104318
104544
|
// src/services/bootstrap/self-update-installer-scripts.ts
|
|
@@ -104734,7 +104960,7 @@ async function downloadTarball(url, destPath, fetchFn) {
|
|
|
104734
104960
|
}
|
|
104735
104961
|
async function verifyChecksum(path2, expectedHash) {
|
|
104736
104962
|
const algo = expectedHash.length === 40 ? "sha1" : "sha256";
|
|
104737
|
-
const raw = await
|
|
104963
|
+
const raw = await readFile36(path2);
|
|
104738
104964
|
const actual = createHash6(algo).update(raw).digest("hex");
|
|
104739
104965
|
if (actual !== expectedHash) {
|
|
104740
104966
|
try {
|
|
@@ -105485,7 +105711,7 @@ function buildLocalDirectChannelCallbacks(deps) {
|
|
|
105485
105711
|
|
|
105486
105712
|
// src/services/storage/daemon-settings-store.ts
|
|
105487
105713
|
import { createHash as createHash7 } from "crypto";
|
|
105488
|
-
import { mkdir as mkdir23, readFile as
|
|
105714
|
+
import { mkdir as mkdir23, readFile as readFile37, rename as rename21, writeFile as writeFile30 } from "fs/promises";
|
|
105489
105715
|
import { join as join55 } from "path";
|
|
105490
105716
|
var ProjectSettingsSchema = external_exports.object({
|
|
105491
105717
|
disabledMcpServers: external_exports.array(external_exports.string()).optional()
|
|
@@ -105504,7 +105730,7 @@ function buildDaemonSettingsStore(dataDir) {
|
|
|
105504
105730
|
return {
|
|
105505
105731
|
async load(projectPath) {
|
|
105506
105732
|
try {
|
|
105507
|
-
const raw = await
|
|
105733
|
+
const raw = await readFile37(settingsPath(projectPath), "utf-8");
|
|
105508
105734
|
return ProjectSettingsSchema.parse(JSON.parse(raw));
|
|
105509
105735
|
} catch (err) {
|
|
105510
105736
|
if (isEnoent(err)) return {};
|
|
@@ -105522,7 +105748,7 @@ function buildDaemonSettingsStore(dataDir) {
|
|
|
105522
105748
|
}
|
|
105523
105749
|
|
|
105524
105750
|
// src/services/storage/plugin-config-store.ts
|
|
105525
|
-
import { mkdir as mkdir24, readFile as
|
|
105751
|
+
import { mkdir as mkdir24, readFile as readFile38, rename as rename22, writeFile as writeFile31 } from "fs/promises";
|
|
105526
105752
|
import { join as join56 } from "path";
|
|
105527
105753
|
function buildPluginConfigStore(pluginsDir) {
|
|
105528
105754
|
const cache2 = /* @__PURE__ */ new Map();
|
|
@@ -105534,7 +105760,7 @@ function buildPluginConfigStore(pluginsDir) {
|
|
|
105534
105760
|
const cached2 = cache2.get(pluginId);
|
|
105535
105761
|
if (cached2) return cached2;
|
|
105536
105762
|
try {
|
|
105537
|
-
const raw = await
|
|
105763
|
+
const raw = await readFile38(configPath(pluginId), "utf-8");
|
|
105538
105764
|
const parsed = JSON.parse(raw);
|
|
105539
105765
|
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
105540
105766
|
const record = Object.fromEntries(Object.entries(parsed));
|
|
@@ -105949,4 +106175,4 @@ export {
|
|
|
105949
106175
|
_testing,
|
|
105950
106176
|
serve
|
|
105951
106177
|
};
|
|
105952
|
-
//# sourceMappingURL=serve-
|
|
106178
|
+
//# sourceMappingURL=serve-ZAI7K2HR.js.map
|