@agimon-ai/po-git 0.0.0-alpha.3 → 0.0.0-alpha.30
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/LICENSE +149 -21
- package/README.md +16 -4
- package/dist/extensions/native.mjs +1642 -456
- package/dist/extensions/native.mjs.map +1 -1
- package/dist/extensions/server.cjs +241 -73
- package/dist/extensions/server.cjs.map +1 -1
- package/dist/extensions/server.d.mts +2 -2
- package/dist/extensions/server.d.mts.map +1 -1
- package/dist/extensions/server.mjs +240 -72
- package/dist/extensions/server.mjs.map +1 -1
- package/dist/extensions/web.mjs +1373 -1292
- package/dist/extensions/web.mjs.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{worktreeOperations-2PaaLPTF.mjs → worktreeOperations-BqLLypS5.mjs} +86 -41
- package/dist/worktreeOperations-BqLLypS5.mjs.map +1 -0
- package/dist/{worktreeOperations-C6_xikos.cjs → worktreeOperations-CU0iV2h-.cjs} +124 -49
- package/dist/worktreeOperations-CU0iV2h-.cjs.map +1 -0
- package/llms.txt +1 -1
- package/package.json +21 -20
- package/src/prompts/{po-use-git → codemode-how-to-git}/SKILL.md +34 -31
- package/dist/worktreeOperations-2PaaLPTF.mjs.map +0 -1
- package/dist/worktreeOperations-C6_xikos.cjs.map +0 -1
|
@@ -24,10 +24,11 @@ let node_child_process = require("node:child_process");
|
|
|
24
24
|
let node_fs = require("node:fs");
|
|
25
25
|
node_fs = __toESM(node_fs, 1);
|
|
26
26
|
let node_crypto = require("node:crypto");
|
|
27
|
-
let node_os = require("node:os");
|
|
28
|
-
node_os = __toESM(node_os, 1);
|
|
29
27
|
let node_path = require("node:path");
|
|
30
28
|
node_path = __toESM(node_path, 1);
|
|
29
|
+
let js_yaml = require("js-yaml");
|
|
30
|
+
let node_os = require("node:os");
|
|
31
|
+
node_os = __toESM(node_os, 1);
|
|
31
32
|
let node_util = require("node:util");
|
|
32
33
|
let _agimon_ai_po_core_piSettings = require("@agimon-ai/po-core/piSettings");
|
|
33
34
|
let node_timers_promises = require("node:timers/promises");
|
|
@@ -285,8 +286,25 @@ function createWorktreeGit() {
|
|
|
285
286
|
};
|
|
286
287
|
}
|
|
287
288
|
//#endregion
|
|
289
|
+
//#region src/constants/git.ts
|
|
290
|
+
/** Workspace-mounted routes behind the new-session dialog. */
|
|
291
|
+
const GIT_BRANCHES_PATH = "/branches";
|
|
292
|
+
const GIT_SESSIONS_PATH = "/sessions";
|
|
293
|
+
/** Workspace-mounted: that workspace's remote auth for manual pull, push and rebase. */
|
|
294
|
+
const GIT_AUTH_PATH = "/auth";
|
|
295
|
+
/** Session-mounted: the session's change against its base, and one file's hunks. */
|
|
296
|
+
const GIT_REVIEW_PATH = "/review";
|
|
297
|
+
const GIT_REVIEW_FILE_PATH = "/review/file";
|
|
298
|
+
/** Repository file, relative to the checkout root, whose `setup` commands run in every new worktree. */
|
|
299
|
+
const WORKTREE_CONFIG_FILE = ".po/worktree.yaml";
|
|
300
|
+
/**
|
|
301
|
+
* po-runner's session command, so setup runs as a runner of the worktree session and its log
|
|
302
|
+
* shows in Runners. Mirrors po-runner's `runnerLaunchLine`; the command follows the separator.
|
|
303
|
+
*/
|
|
304
|
+
const WORKTREE_SETUP_LAUNCH = "/runners start name=worktree-setup --";
|
|
305
|
+
//#endregion
|
|
288
306
|
//#region src/services/errors/index.ts
|
|
289
|
-
var
|
|
307
|
+
var PoGitExpectedError = class extends Error {
|
|
290
308
|
code;
|
|
291
309
|
retryable;
|
|
292
310
|
recovery;
|
|
@@ -295,7 +313,7 @@ var DoomGitExpectedError = class extends Error {
|
|
|
295
313
|
this.code = code;
|
|
296
314
|
this.retryable = retryable;
|
|
297
315
|
this.recovery = recovery;
|
|
298
|
-
this.name = "
|
|
316
|
+
this.name = "PoGitExpectedError";
|
|
299
317
|
}
|
|
300
318
|
};
|
|
301
319
|
/** Raised when a worktree action needs the canonical hub but it is not injected. */
|
|
@@ -306,7 +324,7 @@ var HubUnavailableError = class extends Error {
|
|
|
306
324
|
}
|
|
307
325
|
};
|
|
308
326
|
function invalidRequest(message, recovery) {
|
|
309
|
-
return new
|
|
327
|
+
return new PoGitExpectedError("invalid_request", message, false, recovery);
|
|
310
328
|
}
|
|
311
329
|
//#endregion
|
|
312
330
|
//#region src/services/atomicJson/index.ts
|
|
@@ -417,12 +435,12 @@ function shortId(seed) {
|
|
|
417
435
|
* worktree, so a session there would build the wrong source while appearing to
|
|
418
436
|
* work.
|
|
419
437
|
*/
|
|
420
|
-
function
|
|
438
|
+
function poGitRoot(homeDir = node_os.default.homedir()) {
|
|
421
439
|
return node_path.default.join((0, _agimon_ai_po_core_piSettings.poHomeDirectory)(homeDir), "git");
|
|
422
440
|
}
|
|
423
441
|
/** The directory every worktree for every repository is created under. */
|
|
424
442
|
function worktreesRoot(homeDir = node_os.default.homedir()) {
|
|
425
|
-
return node_path.default.join(
|
|
443
|
+
return node_path.default.join(poGitRoot(homeDir), "worktrees");
|
|
426
444
|
}
|
|
427
445
|
/**
|
|
428
446
|
* Remote auth for every workspace, one entry per workspace root.
|
|
@@ -431,12 +449,12 @@ function worktreesRoot(homeDir = node_os.default.homedir()) {
|
|
|
431
449
|
* only by the owner. It holds secrets, which no other file here does.
|
|
432
450
|
*/
|
|
433
451
|
function credentialsFile(homeDir = node_os.default.homedir()) {
|
|
434
|
-
return node_path.default.join(
|
|
452
|
+
return node_path.default.join(poGitRoot(homeDir), "credentials.json");
|
|
435
453
|
}
|
|
436
454
|
/** One registry file per repository, keyed by the shared git directory. */
|
|
437
455
|
function registryFile(repositoryRoot, homeDir = node_os.default.homedir()) {
|
|
438
456
|
const id = repositoryId(repositoryRoot);
|
|
439
|
-
const root = node_path.default.join(
|
|
457
|
+
const root = node_path.default.join(poGitRoot(homeDir), "registry");
|
|
440
458
|
const canonical = node_path.default.join(root, id, "worktrees.json");
|
|
441
459
|
if (node_fs.default.existsSync(canonical)) return canonical;
|
|
442
460
|
let names;
|
|
@@ -681,7 +699,7 @@ function createWorktreeRegistry(file) {
|
|
|
681
699
|
break;
|
|
682
700
|
} catch (error) {
|
|
683
701
|
if (error.code !== "EEXIST") throw error;
|
|
684
|
-
if (Date.now() >= deadline) throw new
|
|
702
|
+
if (Date.now() >= deadline) throw new PoGitExpectedError("registry_busy", "Another worktree operation holds the repository registry.", true, "Retry after it finishes. After a host crash, inspect and remove the abandoned worktrees.json.lock directory.");
|
|
685
703
|
await (0, node_timers_promises.setTimeout)(LOCK_RETRY_MS, void 0, { signal });
|
|
686
704
|
}
|
|
687
705
|
}
|
|
@@ -703,6 +721,23 @@ function createWorktreeRegistry(file) {
|
|
|
703
721
|
const GIT_WORKTREE_DELEGATION_KIND = "git.worktree.delegation";
|
|
704
722
|
const GIT_WORKTREE_MESSAGE_KIND = "git.worktree.message";
|
|
705
723
|
const GIT_WORKTREE_REPORT_KIND = "git.worktree.report";
|
|
724
|
+
/**
|
|
725
|
+
* The repository's worktree setup as one shell command, or undefined when it asks for none.
|
|
726
|
+
* Read from the checkout the spawn starts in, so an uncommitted edit applies at once.
|
|
727
|
+
*/
|
|
728
|
+
function readWorktreeSetup(root) {
|
|
729
|
+
const file = node_path.default.join(root, WORKTREE_CONFIG_FILE);
|
|
730
|
+
if (!node_fs.default.existsSync(file)) return void 0;
|
|
731
|
+
let setup;
|
|
732
|
+
try {
|
|
733
|
+
setup = (0, js_yaml.load)(node_fs.default.readFileSync(file, "utf8"))?.setup;
|
|
734
|
+
} catch (error) {
|
|
735
|
+
throw new PoGitExpectedError("invalid_request", `${WORKTREE_CONFIG_FILE} is not valid YAML (${error.message}).`, false, "Fix the file and try again.");
|
|
736
|
+
}
|
|
737
|
+
const commands = [setup ?? []].flat();
|
|
738
|
+
if (!commands.every((command) => typeof command === "string")) throw new PoGitExpectedError("invalid_request", `${WORKTREE_CONFIG_FILE} setup must be a command or a list of commands.`, false, "Fix the file and try again.");
|
|
739
|
+
return commands.filter((command) => command.trim() !== "").join(" && ") || void 0;
|
|
740
|
+
}
|
|
706
741
|
function createWorktreeOperations(deps) {
|
|
707
742
|
const { git } = deps;
|
|
708
743
|
const sessionService = deps.sessionService;
|
|
@@ -734,7 +769,7 @@ function createWorktreeOperations(deps) {
|
|
|
734
769
|
*/
|
|
735
770
|
const resolve = async (context) => {
|
|
736
771
|
const root = await git.repositoryRoot(context.cwd);
|
|
737
|
-
if (root === void 0) throw new
|
|
772
|
+
if (root === void 0) throw new PoGitExpectedError("not_a_repository", `${context.cwd} is not inside a git repository.`, false, "Run this from a repository checkout.");
|
|
738
773
|
const store = createWorktreeRegistry(registryFile(root, deps.homeDir));
|
|
739
774
|
return {
|
|
740
775
|
root,
|
|
@@ -744,7 +779,7 @@ function createWorktreeOperations(deps) {
|
|
|
744
779
|
};
|
|
745
780
|
const require$1 = (records, id) => {
|
|
746
781
|
const record = records.find((entry) => entry.id === id);
|
|
747
|
-
if (record === void 0) throw new
|
|
782
|
+
if (record === void 0) throw new PoGitExpectedError("worktree_not_found", `No worktree with id ${id}.`, false, "Call list to see the current ids.");
|
|
748
783
|
return record;
|
|
749
784
|
};
|
|
750
785
|
/**
|
|
@@ -760,10 +795,10 @@ function createWorktreeOperations(deps) {
|
|
|
760
795
|
const requireOwner = (context, record, action) => {
|
|
761
796
|
if (record.parentSessionId === context.sessionId) return;
|
|
762
797
|
if (record.parentSessionId === void 0 || !requireSessionService().isLive(record.parentSessionId)) return;
|
|
763
|
-
throw new
|
|
798
|
+
throw new PoGitExpectedError("worktree_not_owned", `Worktree ${record.id} belongs to another session.`, false, `Ask the session that created it to ${action} it, or close that session first.`);
|
|
764
799
|
};
|
|
765
800
|
const peerFor = (context, record) => {
|
|
766
|
-
if (record.parentSessionId === void 0) throw new
|
|
801
|
+
if (record.parentSessionId === void 0) throw new PoGitExpectedError("worktree_peer_unavailable", `Worktree ${record.id} was opened on its own and has no parent session to message.`, false, "Message a worktree this session created.");
|
|
767
802
|
if (context.sessionId === record.parentSessionId) return {
|
|
768
803
|
sessionId: record.sessionId,
|
|
769
804
|
party: "parent"
|
|
@@ -772,10 +807,10 @@ function createWorktreeOperations(deps) {
|
|
|
772
807
|
sessionId: record.parentSessionId,
|
|
773
808
|
party: "child"
|
|
774
809
|
};
|
|
775
|
-
throw new
|
|
810
|
+
throw new PoGitExpectedError("worktree_not_owned", `Worktree ${record.id} belongs to another session.`, false, "Use a worktree owned by this session.");
|
|
776
811
|
};
|
|
777
812
|
const requirePeerLive = (peerSessionId) => {
|
|
778
|
-
if (!requireSessionService().isLive(peerSessionId)) throw new
|
|
813
|
+
if (!requireSessionService().isLive(peerSessionId)) throw new PoGitExpectedError("worktree_peer_unavailable", "The other worktree session is no longer live.", false, "Start a new worktree session before sending a message.");
|
|
779
814
|
};
|
|
780
815
|
const operations = {
|
|
781
816
|
async spawn(context, request, options) {
|
|
@@ -783,7 +818,7 @@ function createWorktreeOperations(deps) {
|
|
|
783
818
|
const parented = parentSessionId === void 0 ? {} : { parentSessionId };
|
|
784
819
|
const { root, store, records } = await resolve(context);
|
|
785
820
|
const reservations = request.reservationId === void 0 ? void 0 : requireSessionService().reservations;
|
|
786
|
-
if (request.reservationId !== void 0 && (!reservations || request.task !== void 0)) throw new
|
|
821
|
+
if (request.reservationId !== void 0 && (!reservations || request.task !== void 0)) throw new PoGitExpectedError("invalid_request", "Reserved worktree sessions require host setup and cannot start a task.", false, "Create the session from its pending setup card.");
|
|
787
822
|
const reserved = request.reservationId === void 0 ? void 0 : reservations.read(request.reservationId, parentSessionId);
|
|
788
823
|
const existing = reserved === void 0 ? void 0 : records.find((record) => record.sessionId === reserved.sessionId);
|
|
789
824
|
if (existing) {
|
|
@@ -794,7 +829,7 @@ function createWorktreeOperations(deps) {
|
|
|
794
829
|
branch: request.branch,
|
|
795
830
|
shortId: shortId(reserved.sessionId)
|
|
796
831
|
});
|
|
797
|
-
if (existing.parentSessionId !== parentSessionId || existing.repositoryRoot !== root || existing.branch !== request.branch || existing.path !== expectedPath || existing.path !== reserved?.cwd || request.baseRef !== void 0 && existing.baseRef !== request.baseRef || !node_fs.default.existsSync(existing.path) || !(await git.listWorktreePaths(root)).includes(existing.path) || await git.repositoryRoot(existing.path) !== existing.path || await git.currentBranch(existing.path) !== request.branch) throw new
|
|
832
|
+
if (existing.parentSessionId !== parentSessionId || existing.repositoryRoot !== root || existing.branch !== request.branch || existing.path !== expectedPath || existing.path !== reserved?.cwd || request.baseRef !== void 0 && existing.baseRef !== request.baseRef || !node_fs.default.existsSync(existing.path) || !(await git.listWorktreePaths(root)).includes(existing.path) || await git.repositoryRoot(existing.path) !== existing.path || await git.currentBranch(existing.path) !== request.branch) throw new PoGitExpectedError("invalid_request", "The reserved checkout no longer matches this setup.", false, "Inspect the existing branch and checkout; they will not be replaced.");
|
|
798
833
|
if (!requireSessionService().isLive(existing.sessionId)) {
|
|
799
834
|
if ((await requireSessionService().create({
|
|
800
835
|
cwd: existing.path,
|
|
@@ -812,8 +847,9 @@ function createWorktreeOperations(deps) {
|
|
|
812
847
|
branch: request.branch,
|
|
813
848
|
existing: records
|
|
814
849
|
});
|
|
815
|
-
if (refusal !== void 0) throw new
|
|
850
|
+
if (refusal !== void 0) throw new PoGitExpectedError("worktree_exists", refusal, false, "Pick another branch name, or close it.");
|
|
816
851
|
const taskDelivery = request.task === void 0 ? void 0 : requireSessionDelivery();
|
|
852
|
+
const setup = readWorktreeSetup(root);
|
|
817
853
|
const existingBranch = request.checkout === "existing";
|
|
818
854
|
const id = shortId(reserved?.sessionId ?? (0, node_crypto.randomUUID)());
|
|
819
855
|
let path = worktreeDirectory({
|
|
@@ -825,16 +861,16 @@ function createWorktreeOperations(deps) {
|
|
|
825
861
|
});
|
|
826
862
|
if (request.reservationId !== void 0) path = (await reservations.prepare(request.reservationId, parentSessionId, path)).cwd;
|
|
827
863
|
const recovering = reserved?.cwd !== void 0 && node_fs.default.existsSync(path);
|
|
828
|
-
if (recovering && (!(await git.listWorktreePaths(root)).includes(path) || await git.currentBranch(path) !== request.branch)) throw new
|
|
864
|
+
if (recovering && (!(await git.listWorktreePaths(root)).includes(path) || await git.currentBranch(path) !== request.branch)) throw new PoGitExpectedError("invalid_request", "The reserved checkout no longer matches this setup.", false, "Inspect the existing directory; it will not be replaced.");
|
|
829
865
|
if (!recovering) {
|
|
830
866
|
if (existingBranch) {
|
|
831
867
|
const branches = await git.listBranches(root);
|
|
832
868
|
const local = branches.local.find((branch) => branch.name === request.branch);
|
|
833
|
-
if (!(request.remote === void 0 ? local !== void 0 && local.checkedOutAt === void 0 : local === void 0 && branches.remote.some((branch) => branch.remote === request.remote && branch.name === request.branch))) throw new
|
|
834
|
-
} else if ((await git.listBranches(root)).local.some((branch) => branch.name === request.branch)) throw new
|
|
869
|
+
if (!(request.remote === void 0 ? local !== void 0 && local.checkedOutAt === void 0 : local === void 0 && branches.remote.some((branch) => branch.remote === request.remote && branch.name === request.branch))) throw new PoGitExpectedError("invalid_request", local?.checkedOutAt === void 0 ? `The branch ${request.branch} is not available to check out.` : `The branch ${request.branch} is already checked out at ${local.checkedOutAt}.`, false, "Pick another branch, or create a new one.");
|
|
870
|
+
} else if ((await git.listBranches(root)).local.some((branch) => branch.name === request.branch)) throw new PoGitExpectedError("invalid_request", `The branch ${request.branch} already exists.`, false, "Pick another name, or open it as an existing branch.");
|
|
835
871
|
}
|
|
836
872
|
const baseRef = existingBranch ? request.remote === void 0 ? request.branch : `${request.remote}/${request.branch}` : request.baseRef ?? await git.remoteBaseRef(root);
|
|
837
|
-
if (baseRef === void 0) throw new
|
|
873
|
+
if (baseRef === void 0) throw new PoGitExpectedError("git_failed", "No remote base branch is available for this repository.", false, "Fetch a remote branch or pass an explicit baseRef.");
|
|
838
874
|
const cancelled = () => options?.signal?.aborted === true;
|
|
839
875
|
const rollback = async () => {
|
|
840
876
|
if (reserved) return ` The reserved checkout at ${path} was retained for recovery.`;
|
|
@@ -864,7 +900,7 @@ function createWorktreeOperations(deps) {
|
|
|
864
900
|
baseRef
|
|
865
901
|
});
|
|
866
902
|
}
|
|
867
|
-
if (cancelled()) throw new
|
|
903
|
+
if (cancelled()) throw new PoGitExpectedError("spawn_cancelled", `Cancelled before the session started.${await rollback()}`, false, reserved ? "Retry setup with the same branch to recover the reserved checkout." : "The worktree was removed; run it again when you are ready.");
|
|
868
904
|
options?.onProgress?.("starting session…");
|
|
869
905
|
let sessionId;
|
|
870
906
|
try {
|
|
@@ -879,8 +915,8 @@ function createWorktreeOperations(deps) {
|
|
|
879
915
|
if (reserved && sessionId !== reserved.sessionId) throw new Error("The host did not use the reserved session identity.");
|
|
880
916
|
} catch (error) {
|
|
881
917
|
const kept = await rollback();
|
|
882
|
-
if (cancelled()) throw new
|
|
883
|
-
if (error instanceof HubUnavailableError) throw new
|
|
918
|
+
if (cancelled()) throw new PoGitExpectedError("spawn_cancelled", `Cancelled while the session was starting.${kept}`, false, reserved ? "Retry setup with the same branch to recover the reserved checkout." : "The worktree was removed; run it again when you are ready.");
|
|
919
|
+
if (error instanceof HubUnavailableError) throw new PoGitExpectedError("hub_unavailable", `${error.message}${kept}`, true, "Start the cockpit and try again.");
|
|
884
920
|
throw error;
|
|
885
921
|
}
|
|
886
922
|
const record = {
|
|
@@ -900,13 +936,22 @@ function createWorktreeOperations(deps) {
|
|
|
900
936
|
} catch (error) {
|
|
901
937
|
await requireSessionService().close(sessionId).catch(() => void 0);
|
|
902
938
|
const kept = await rollback();
|
|
903
|
-
throw new
|
|
939
|
+
throw new PoGitExpectedError("registry_write_failed", `The worktree was created but the registry could not be written (${error.message}).${kept}`, true, "Check the registry file for permissions or free space, then try again.");
|
|
940
|
+
}
|
|
941
|
+
let setupStarted = false;
|
|
942
|
+
if (setup !== void 0) try {
|
|
943
|
+
const service = requireSessionService();
|
|
944
|
+
if (service.prompt === void 0) throw new Error("this host cannot run session commands");
|
|
945
|
+
await service.prompt(sessionId, `${WORKTREE_SETUP_LAUNCH} ${setup}`);
|
|
946
|
+
setupStarted = true;
|
|
947
|
+
} catch (error) {
|
|
948
|
+
options?.onProgress?.(`worktree setup did not start (${String(error)})`);
|
|
904
949
|
}
|
|
905
950
|
if (request.task !== void 0 && taskDelivery !== void 0) try {
|
|
906
951
|
const receipt = await taskDelivery.deliver({
|
|
907
952
|
recipientKey: sessionId,
|
|
908
953
|
kind: GIT_WORKTREE_DELEGATION_KIND,
|
|
909
|
-
prompt: request.task,
|
|
954
|
+
prompt: setupStarted ? `${request.task}\n\nThe worktree setup (${setup}) is running as the runner "worktree-setup". Check it with po-runner before relying on installed dependencies or builds.` : request.task,
|
|
910
955
|
metadata: {
|
|
911
956
|
worktreeId: record.id,
|
|
912
957
|
fromRole: "parent",
|
|
@@ -915,10 +960,10 @@ function createWorktreeOperations(deps) {
|
|
|
915
960
|
}
|
|
916
961
|
});
|
|
917
962
|
const admission = await taskDelivery.waitForAdmission(receipt.deliveryId);
|
|
918
|
-
if (admission !== "admitted") throw new
|
|
963
|
+
if (admission !== "admitted") throw new PoGitExpectedError("task_delivery_failed", `Worktree ${record.id} was created and task delivery ${receipt.deliveryId} was persisted, but admission ${admission === "recovery_required" ? "requires recovery" : "was not confirmed before the timeout"}.`, true, admission === "recovery_required" ? `Call messages from worktree ${record.id} to recover the task in the recipient session. Do not resend it automatically.` : `Check delivery ${receipt.deliveryId} in the sender outbox or call messages from worktree ${record.id} in the recipient session before deciding whether to resend.`);
|
|
919
964
|
} catch (error) {
|
|
920
|
-
if (error instanceof
|
|
921
|
-
throw new
|
|
965
|
+
if (error instanceof PoGitExpectedError) throw error;
|
|
966
|
+
throw new PoGitExpectedError("task_delivery_failed", `Worktree ${record.id} was created, but task delivery failed (${String(error)}).`, true, `Inspect worktree ${record.id} and the sender outbox before using send to deliver the task. Do not recreate the worktree.`);
|
|
922
967
|
}
|
|
923
968
|
if (request.reservationId !== void 0) await reservations.complete(request.reservationId, parentSessionId);
|
|
924
969
|
return record;
|
|
@@ -932,7 +977,7 @@ function createWorktreeOperations(deps) {
|
|
|
932
977
|
dirtyFiles: node_fs.default.existsSync(record.path) ? await git.dirtyFiles(record.path) : [],
|
|
933
978
|
force
|
|
934
979
|
});
|
|
935
|
-
if (refusal !== void 0) throw new
|
|
980
|
+
if (refusal !== void 0) throw new PoGitExpectedError("worktree_dirty", refusal, false, "Commit the work, or pass force: true.");
|
|
936
981
|
await requireSessionService().close(record.sessionId);
|
|
937
982
|
await git.removeWorktree({
|
|
938
983
|
repositoryRoot: root,
|
|
@@ -961,7 +1006,7 @@ function createWorktreeOperations(deps) {
|
|
|
961
1006
|
const record = require$1(records, id);
|
|
962
1007
|
requireOwner(context, record, "merge");
|
|
963
1008
|
const parentDirty = await git.dirtyFiles(root);
|
|
964
|
-
if (parentDirty.length > 0) throw new
|
|
1009
|
+
if (parentDirty.length > 0) throw new PoGitExpectedError("worktree_dirty", `The parent checkout has ${String(parentDirty.length)} uncommitted file(s): ${parentDirty.slice(0, 10).join(", ")}.`, false, "Commit or stash the parent checkout first.");
|
|
965
1010
|
await git.mergeBranch({
|
|
966
1011
|
repositoryRoot: root,
|
|
967
1012
|
branch: record.branch,
|
|
@@ -971,7 +1016,7 @@ function createWorktreeOperations(deps) {
|
|
|
971
1016
|
},
|
|
972
1017
|
/** Sends only between the parent session and its own worktree session. */
|
|
973
1018
|
async send(context, id, message) {
|
|
974
|
-
if (Buffer.byteLength(message, "utf8") > 65536) throw new
|
|
1019
|
+
if (Buffer.byteLength(message, "utf8") > 65536) throw new PoGitExpectedError("message_too_large", `A message may not exceed ${String(MAX_WORKTREE_MESSAGE_BYTES)} bytes.`, false, "Send a shorter message.");
|
|
975
1020
|
const { records } = await resolve(context);
|
|
976
1021
|
const record = require$1(records, id);
|
|
977
1022
|
const peer = peerFor(context, record);
|
|
@@ -992,7 +1037,7 @@ function createWorktreeOperations(deps) {
|
|
|
992
1037
|
}
|
|
993
1038
|
});
|
|
994
1039
|
const admission = await delivery.waitForAdmission(receipt.deliveryId);
|
|
995
|
-
if (admission !== "admitted") throw new
|
|
1040
|
+
if (admission !== "admitted") throw new PoGitExpectedError("message_delivery_failed", `Worktree ${record.id} persisted message delivery ${receipt.deliveryId}, but admission ${admission === "recovery_required" ? "requires recovery" : "was not confirmed before the timeout"}.`, true, admission === "recovery_required" ? `Call messages from the recipient session to recover delivery ${receipt.deliveryId}. Do not resend it automatically.` : `Check delivery ${receipt.deliveryId} in the sender outbox or call messages from the recipient session before deciding whether to resend.`);
|
|
996
1041
|
return;
|
|
997
1042
|
}
|
|
998
1043
|
requireMessageInbox().send(peer.sessionId, {
|
|
@@ -1059,22 +1104,22 @@ function createWorktreeOperations(deps) {
|
|
|
1059
1104
|
const { store } = await resolve(context);
|
|
1060
1105
|
return await store.transaction(operation, signal);
|
|
1061
1106
|
} catch (error) {
|
|
1062
|
-
if (signal?.aborted && !(error instanceof
|
|
1107
|
+
if (signal?.aborted && !(error instanceof PoGitExpectedError)) throw new PoGitExpectedError("spawn_cancelled", "The worktree operation was cancelled.", false, "Inspect its recorded state before retrying.");
|
|
1063
1108
|
if ([
|
|
1064
1109
|
"ENOTDIR",
|
|
1065
1110
|
"EACCES",
|
|
1066
1111
|
"EROFS",
|
|
1067
1112
|
"ENOSPC"
|
|
1068
|
-
].includes(String(error.code))) throw new
|
|
1113
|
+
].includes(String(error.code))) throw new PoGitExpectedError("registry_write_failed", "The worktree registry is not writable.", true, "Check permissions and free space before retrying.");
|
|
1069
1114
|
throw error;
|
|
1070
1115
|
}
|
|
1071
1116
|
};
|
|
1072
1117
|
return {
|
|
1073
1118
|
...operations,
|
|
1074
1119
|
spawn: (context, request, options) => {
|
|
1075
|
-
if (sessionService === void 0) return Promise.reject(new
|
|
1076
|
-
if (!validRefName(request.branch) || request.baseRef !== void 0 && !validRefName(request.baseRef)) return Promise.reject(new
|
|
1077
|
-
if (request.reservationId !== void 0 && context.sessionId === void 0) return Promise.reject(new
|
|
1120
|
+
if (sessionService === void 0) return Promise.reject(new PoGitExpectedError("hub_unavailable", "The cockpit session service is unavailable.", true, "Use the cockpit worktree tool after its Git server plugin is available."));
|
|
1121
|
+
if (!validRefName(request.branch) || request.baseRef !== void 0 && !validRefName(request.baseRef)) return Promise.reject(new PoGitExpectedError("invalid_request", "That is not a valid branch name.", false, "Pick another name."));
|
|
1122
|
+
if (request.reservationId !== void 0 && context.sessionId === void 0) return Promise.reject(new PoGitExpectedError("invalid_request", "A reserved worktree session requires its owning parent.", false, "Create the session from its pending setup card."));
|
|
1078
1123
|
return locked(context, () => operations.spawn(context, request, options), options?.signal);
|
|
1079
1124
|
},
|
|
1080
1125
|
close: (context, id, force) => locked(context, () => operations.close(context, id, force)),
|
|
@@ -1084,10 +1129,34 @@ function createWorktreeOperations(deps) {
|
|
|
1084
1129
|
};
|
|
1085
1130
|
}
|
|
1086
1131
|
//#endregion
|
|
1087
|
-
Object.defineProperty(exports, "
|
|
1132
|
+
Object.defineProperty(exports, "GIT_AUTH_PATH", {
|
|
1088
1133
|
enumerable: true,
|
|
1089
1134
|
get: function() {
|
|
1090
|
-
return
|
|
1135
|
+
return GIT_AUTH_PATH;
|
|
1136
|
+
}
|
|
1137
|
+
});
|
|
1138
|
+
Object.defineProperty(exports, "GIT_BRANCHES_PATH", {
|
|
1139
|
+
enumerable: true,
|
|
1140
|
+
get: function() {
|
|
1141
|
+
return GIT_BRANCHES_PATH;
|
|
1142
|
+
}
|
|
1143
|
+
});
|
|
1144
|
+
Object.defineProperty(exports, "GIT_REVIEW_FILE_PATH", {
|
|
1145
|
+
enumerable: true,
|
|
1146
|
+
get: function() {
|
|
1147
|
+
return GIT_REVIEW_FILE_PATH;
|
|
1148
|
+
}
|
|
1149
|
+
});
|
|
1150
|
+
Object.defineProperty(exports, "GIT_REVIEW_PATH", {
|
|
1151
|
+
enumerable: true,
|
|
1152
|
+
get: function() {
|
|
1153
|
+
return GIT_REVIEW_PATH;
|
|
1154
|
+
}
|
|
1155
|
+
});
|
|
1156
|
+
Object.defineProperty(exports, "GIT_SESSIONS_PATH", {
|
|
1157
|
+
enumerable: true,
|
|
1158
|
+
get: function() {
|
|
1159
|
+
return GIT_SESSIONS_PATH;
|
|
1091
1160
|
}
|
|
1092
1161
|
});
|
|
1093
1162
|
Object.defineProperty(exports, "GIT_SESSION_CHANGED_EVENT", {
|
|
@@ -1114,6 +1183,12 @@ Object.defineProperty(exports, "NETWORK_TIMEOUT_MS", {
|
|
|
1114
1183
|
return NETWORK_TIMEOUT_MS;
|
|
1115
1184
|
}
|
|
1116
1185
|
});
|
|
1186
|
+
Object.defineProperty(exports, "PoGitExpectedError", {
|
|
1187
|
+
enumerable: true,
|
|
1188
|
+
get: function() {
|
|
1189
|
+
return PoGitExpectedError;
|
|
1190
|
+
}
|
|
1191
|
+
});
|
|
1117
1192
|
Object.defineProperty(exports, "READ_TIMEOUT_MS", {
|
|
1118
1193
|
enumerable: true,
|
|
1119
1194
|
get: function() {
|
|
@@ -1162,12 +1237,6 @@ Object.defineProperty(exports, "credentialsFile", {
|
|
|
1162
1237
|
return credentialsFile;
|
|
1163
1238
|
}
|
|
1164
1239
|
});
|
|
1165
|
-
Object.defineProperty(exports, "doomGitRoot", {
|
|
1166
|
-
enumerable: true,
|
|
1167
|
-
get: function() {
|
|
1168
|
-
return doomGitRoot;
|
|
1169
|
-
}
|
|
1170
|
-
});
|
|
1171
1240
|
Object.defineProperty(exports, "invalidRequest", {
|
|
1172
1241
|
enumerable: true,
|
|
1173
1242
|
get: function() {
|
|
@@ -1186,6 +1255,12 @@ Object.defineProperty(exports, "isWorktreeLifecycleEvent", {
|
|
|
1186
1255
|
return isWorktreeLifecycleEvent;
|
|
1187
1256
|
}
|
|
1188
1257
|
});
|
|
1258
|
+
Object.defineProperty(exports, "poGitRoot", {
|
|
1259
|
+
enumerable: true,
|
|
1260
|
+
get: function() {
|
|
1261
|
+
return poGitRoot;
|
|
1262
|
+
}
|
|
1263
|
+
});
|
|
1189
1264
|
Object.defineProperty(exports, "readJson", {
|
|
1190
1265
|
enumerable: true,
|
|
1191
1266
|
get: function() {
|
|
@@ -1217,4 +1292,4 @@ Object.defineProperty(exports, "writeJsonAtomic", {
|
|
|
1217
1292
|
}
|
|
1218
1293
|
});
|
|
1219
1294
|
|
|
1220
|
-
//# sourceMappingURL=worktreeOperations-
|
|
1295
|
+
//# sourceMappingURL=worktreeOperations-CU0iV2h-.cjs.map
|