@agentteams/cli 0.1.78 → 0.1.81
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/.eslintcache +1 -1
- package/dist/commands/attachment.d.ts.map +1 -1
- package/dist/commands/attachment.js +24 -10
- package/dist/commands/attachment.js.map +1 -1
- package/dist/commands/doctor.d.ts +14 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +65 -6
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/init.d.ts +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +232 -21
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/worktree.d.ts +10 -0
- package/dist/commands/worktree.d.ts.map +1 -1
- package/dist/commands/worktree.js +11 -4
- package/dist/commands/worktree.js.map +1 -1
- package/dist/index.js +7 -5
- package/dist/index.js.map +1 -1
- package/dist/mcp/context.d.ts +7 -0
- package/dist/mcp/context.d.ts.map +1 -1
- package/dist/mcp/context.js +21 -1
- package/dist/mcp/context.js.map +1 -1
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +2 -1
- package/dist/mcp/tools.js.map +1 -1
- package/dist/mcp-registration/index.d.ts.map +1 -1
- package/dist/mcp-registration/index.js +10 -6
- package/dist/mcp-registration/index.js.map +1 -1
- package/dist/mcp-registration/install.d.ts +1 -0
- package/dist/mcp-registration/install.d.ts.map +1 -1
- package/dist/mcp-registration/install.js +5 -4
- package/dist/mcp-registration/install.js.map +1 -1
- package/dist/mcp-registration/vendorCommand.d.ts +16 -0
- package/dist/mcp-registration/vendorCommand.d.ts.map +1 -1
- package/dist/mcp-registration/vendorCommand.js +5 -2
- package/dist/mcp-registration/vendorCommand.js.map +1 -1
- package/dist/utils/config.d.ts +2 -0
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +6 -2
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/conventionLink.d.ts +5 -3
- package/dist/utils/conventionLink.d.ts.map +1 -1
- package/dist/utils/conventionLink.js +28 -5
- package/dist/utils/conventionLink.js.map +1 -1
- package/dist/utils/doctorOutput.d.ts.map +1 -1
- package/dist/utils/doctorOutput.js +17 -0
- package/dist/utils/doctorOutput.js.map +1 -1
- package/dist/utils/initOutput.d.ts.map +1 -1
- package/dist/utils/initOutput.js +4 -0
- package/dist/utils/initOutput.js.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attachment.d.ts","sourceRoot":"","sources":["../../src/commands/attachment.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"attachment.d.ts","sourceRoot":"","sources":["../../src/commands/attachment.ts"],"names":[],"mappings":"AAmEA,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,OAAO,CAAC,CA8DlB"}
|
|
@@ -39,21 +39,35 @@ const resolveContentType = (fileName) => {
|
|
|
39
39
|
const resolveTarget = (options) => {
|
|
40
40
|
const codeReviewId = optionalString(options.codeReviewId);
|
|
41
41
|
const completionReportId = optionalString(options.completionReportId);
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
const documentId = optionalString(options.documentId);
|
|
43
|
+
const targets = [
|
|
44
|
+
codeReviewId ? { targetType: 'codeReview', targetId: codeReviewId } : null,
|
|
45
|
+
completionReportId ? { targetType: 'completionReport', targetId: completionReportId } : null,
|
|
46
|
+
documentId ? { targetType: 'document', targetId: documentId } : null,
|
|
47
|
+
].filter((target) => target !== null);
|
|
48
|
+
if (targets.length > 1) {
|
|
49
|
+
throw new Error('Use only one of --code-review-id, --completion-report-id, or --document-id.');
|
|
44
50
|
}
|
|
45
|
-
|
|
46
|
-
|
|
51
|
+
const target = targets[0];
|
|
52
|
+
if (target) {
|
|
53
|
+
return target;
|
|
47
54
|
}
|
|
48
|
-
|
|
49
|
-
return { targetType: 'completionReport', targetId: completionReportId };
|
|
50
|
-
}
|
|
51
|
-
throw new Error('Exactly one of --code-review-id or --completion-report-id is required.');
|
|
55
|
+
throw new Error('Exactly one of --code-review-id, --completion-report-id, or --document-id is required.');
|
|
52
56
|
};
|
|
53
57
|
export async function executeAttachmentCommand(apiUrl, headers, action, options) {
|
|
54
58
|
if (action === 'list') {
|
|
55
|
-
const triggerId =
|
|
56
|
-
const
|
|
59
|
+
const triggerId = optionalString(options.triggerId);
|
|
60
|
+
const documentId = optionalString(options.documentId);
|
|
61
|
+
if (triggerId && documentId) {
|
|
62
|
+
throw new Error('Use only one of --trigger-id or --document-id.');
|
|
63
|
+
}
|
|
64
|
+
if (!triggerId && !documentId) {
|
|
65
|
+
throw new Error('Exactly one of --trigger-id or --document-id is required.');
|
|
66
|
+
}
|
|
67
|
+
const path = documentId
|
|
68
|
+
? `/api/documents/${documentId}/attachments`
|
|
69
|
+
: `/api/daemon-triggers/${triggerId}/attachments`;
|
|
70
|
+
const response = await axios.get(`${apiUrl}${path}`, { headers });
|
|
57
71
|
return response.data;
|
|
58
72
|
}
|
|
59
73
|
if (action === 'create') {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attachment.js","sourceRoot":"","sources":["../../src/commands/attachment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,KAAK,MAAM,wBAAwB,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,MAAM,aAAa,GAAG,CAAC,KAAc,EAAE,IAAY,EAAE,EAAE;IACrD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3D,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,cAAc,CAAC,CAAC;IACzC,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC;AACtB,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,CAAC,KAAc,EAAsB,EAAE;IAC5D,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzD,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC;IACtB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC;AAEF,MAAM,yBAAyB,GAA2B;IACxD,GAAG,EAAE,YAAY;IACjB,IAAI,EAAE,YAAY;IAClB,GAAG,EAAE,WAAW;IAChB,GAAG,EAAE,WAAW;IAChB,IAAI,EAAE,YAAY;IAClB,GAAG,EAAE,YAAY;IACjB,GAAG,EAAE,YAAY;IACjB,EAAE,EAAE,eAAe;IACnB,QAAQ,EAAE,eAAe;IACzB,GAAG,EAAE,iBAAiB;IACtB,IAAI,EAAE,WAAW;IACjB,GAAG,EAAE,WAAW;CACjB,CAAC;AAEF,MAAM,kBAAkB,GAAG,CAAC,QAAgB,EAAU,EAAE;IACtD,MAAM,GAAG,GAAG,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3F,MAAM,WAAW,GAAG,yBAAyB,CAAC,GAAG,CAAC,CAAC;IACnD,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CACb,iCAAiC,GAAG,eAAe,MAAM,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACvG,CAAC;IACJ,CAAC;IACD,OAAO,WAAW,CAAC;AACrB,CAAC,CAAC;AAEF,MAAM,aAAa,GAAG,CACpB,OAAgC,
|
|
1
|
+
{"version":3,"file":"attachment.js","sourceRoot":"","sources":["../../src/commands/attachment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,KAAK,MAAM,wBAAwB,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,MAAM,aAAa,GAAG,CAAC,KAAc,EAAE,IAAY,EAAE,EAAE;IACrD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3D,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,cAAc,CAAC,CAAC;IACzC,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC;AACtB,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,CAAC,KAAc,EAAsB,EAAE;IAC5D,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzD,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC;IACtB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC;AAEF,MAAM,yBAAyB,GAA2B;IACxD,GAAG,EAAE,YAAY;IACjB,IAAI,EAAE,YAAY;IAClB,GAAG,EAAE,WAAW;IAChB,GAAG,EAAE,WAAW;IAChB,IAAI,EAAE,YAAY;IAClB,GAAG,EAAE,YAAY;IACjB,GAAG,EAAE,YAAY;IACjB,EAAE,EAAE,eAAe;IACnB,QAAQ,EAAE,eAAe;IACzB,GAAG,EAAE,iBAAiB;IACtB,IAAI,EAAE,WAAW;IACjB,GAAG,EAAE,WAAW;CACjB,CAAC;AAEF,MAAM,kBAAkB,GAAG,CAAC,QAAgB,EAAU,EAAE;IACtD,MAAM,GAAG,GAAG,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3F,MAAM,WAAW,GAAG,yBAAyB,CAAC,GAAG,CAAC,CAAC;IACnD,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CACb,iCAAiC,GAAG,eAAe,MAAM,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACvG,CAAC;IACJ,CAAC;IACD,OAAO,WAAW,CAAC;AACrB,CAAC,CAAC;AAEF,MAAM,aAAa,GAAG,CACpB,OAAgC,EACkD,EAAE;IACpF,MAAM,YAAY,GAAG,cAAc,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAC1D,MAAM,kBAAkB,GAAG,cAAc,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACtE,MAAM,UAAU,GAAG,cAAc,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACtD,MAAM,OAAO,GAAG;QACd,YAAY,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,YAAqB,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,IAAI;QACnF,kBAAkB,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,kBAA2B,EAAE,QAAQ,EAAE,kBAAkB,EAAE,CAAC,CAAC,CAAC,IAAI;QACrG,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,UAAmB,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,IAAI;KAC9E,CAAC,MAAM,CAAC,CAAC,MAAM,EAAwC,EAAE,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC;IAE5E,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,6EAA6E,CAAC,CAAC;IACjG,CAAC;IACD,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAC1B,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,wFAAwF,CAAC,CAAC;AAC5G,CAAC,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,MAAc,EACd,OAA+B,EAC/B,MAAc,EACd,OAAgC;IAEhC,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,MAAM,SAAS,GAAG,cAAc,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACpD,MAAM,UAAU,GAAG,cAAc,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACtD,IAAI,SAAS,IAAI,UAAU,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;QACpE,CAAC;QACD,IAAI,CAAC,SAAS,IAAI,CAAC,UAAU,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;QAC/E,CAAC;QACD,MAAM,IAAI,GAAG,UAAU;YACrB,CAAC,CAAC,kBAAkB,UAAU,cAAc;YAC5C,CAAC,CAAC,wBAAwB,SAAS,cAAc,CAAC;QACpD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,MAAM,GAAG,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;QAClE,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAED,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;QACxB,MAAM,cAAc,GAAG,aAAa,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC7D,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;QAExD,MAAM,QAAQ,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;QACzC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,mBAAmB,cAAc,EAAE,CAAC,CAAC;QACvD,CAAC;QACD,MAAM,MAAM,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;QACtC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAC/C,CAAC;QAED,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACpC,MAAM,WAAW,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;QACjD,iBAAiB,CAAC,cAAc,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QAEjD,gCAAgC;QAChC,MAAM,aAAa,GAAG,MAAM,KAAK,CAAC,IAAI,CACpC,GAAG,MAAM,mCAAmC,EAC5C,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,EAC9C,EAAE,OAAO,EAAE,CACZ,CAAC;QACF,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,GAAG,aAAa,CAAC,IAAI,CAAC,IAA0C,CAAC;QAEzF,yCAAyC;QACzC,MAAM,KAAK,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,EAAE,cAAc,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC;QAEjF,sBAAsB;QACtB,MAAM,cAAc,GAAG,MAAM,KAAK,CAAC,IAAI,CACrC,GAAG,MAAM,kBAAkB,EAC3B,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,YAAY,EAAE,QAAQ,EAAE,EACrD,EAAE,OAAO,EAAE,CACZ,CAAC;QACF,OAAO,cAAc,CAAC,IAAI,CAAC;IAC7B,CAAC;IAED,IAAI,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC/C,MAAM,IAAI,KAAK,CACb,eAAe,MAAM,iCAAiC;YACpD,sFAAsF,CACzF,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,8BAA8B,MAAM,EAAE,CAAC,CAAC;AAC1D,CAAC"}
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { type ConventionIssue, type ConventionLinkState } from '../utils/conventionLink.js';
|
|
2
2
|
export type DoctorStatus = 'READY' | 'DEGRADED' | 'NOT_APPLICABLE';
|
|
3
|
+
/**
|
|
4
|
+
* Which project layout the diagnosis ran against. Output and readiness rules
|
|
5
|
+
* differ per layout, so this — not a derived field such as `rootHook` — is what
|
|
6
|
+
* consumers branch on.
|
|
7
|
+
*/
|
|
8
|
+
export type DoctorLayout = 'git-root' | 'non-git-root' | 'unknown';
|
|
3
9
|
export interface DoctorIssue {
|
|
4
10
|
code: string;
|
|
5
11
|
path: string | null;
|
|
@@ -22,12 +28,20 @@ export interface DoctorRepositoryResult {
|
|
|
22
28
|
}
|
|
23
29
|
export interface DoctorResult {
|
|
24
30
|
status: DoctorStatus;
|
|
31
|
+
layout: DoctorLayout;
|
|
25
32
|
applicable: boolean;
|
|
26
33
|
changedCount: number;
|
|
27
34
|
rootDir: string | null;
|
|
28
35
|
rootEntryPoints: string[];
|
|
29
36
|
missingRecommendedEntryPoints: string[];
|
|
30
37
|
repositories: DoctorRepositoryResult[];
|
|
38
|
+
/**
|
|
39
|
+
* State of the worktree bootstrap hook on the convention root itself. Only a
|
|
40
|
+
* git root project has one — a non-git root has no git-common dir and its
|
|
41
|
+
* hooks live per member repo (`DoctorRepositoryResult.hook`), so it reports
|
|
42
|
+
* `skipped`.
|
|
43
|
+
*/
|
|
44
|
+
rootHook: 'ready' | 'blocked' | 'skipped';
|
|
31
45
|
issues: DoctorIssue[];
|
|
32
46
|
}
|
|
33
47
|
type DoctorOptions = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAIA,OAAO,EAQL,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACzB,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAIA,OAAO,EAQL,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACzB,MAAM,4BAA4B,CAAC;AAgBpC,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,UAAU,GAAG,gBAAgB,CAAC;AAEnE;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,cAAc,GAAG,SAAS,CAAC;AAEnE,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,GAAG,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,wBAAwB;IACvC,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,SAAS,GAAG,UAAU,CAAC;CAC/B;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,GAAG,UAAU,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,OAAO,GAAG,SAAS,CAAC;IAC7B,IAAI,EAAE,mBAAmB,CAAC;IAC1B,IAAI,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;IACtC,mBAAmB,EAAE,wBAAwB,EAAE,CAAC;IAChD,MAAM,EAAE,eAAe,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,YAAY,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,6BAA6B,EAAE,MAAM,EAAE,CAAC;IACxC,YAAY,EAAE,sBAAsB,EAAE,CAAC;IACvC;;;;;OAKG;IACH,QAAQ,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;IAC1C,MAAM,EAAE,WAAW,EAAE,CAAC;CACvB;AAED,KAAK,aAAa,GAAG;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAiNF,wBAAsB,oBAAoB,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CAEzF"}
|
package/dist/commands/doctor.js
CHANGED
|
@@ -11,6 +11,9 @@ const CONVENTION_FILE = 'convention.md';
|
|
|
11
11
|
// which of these exist at the convention root; it never creates root files.
|
|
12
12
|
const ENTRY_POINT_ALLOWLIST = ['CLAUDE.md', 'AGENTS.md', 'GEMINI.md', '.cursor/rules/agentteams.mdc'];
|
|
13
13
|
const RECOMMENDED_ENTRY_POINTS = ['CLAUDE.md', 'AGENTS.md'];
|
|
14
|
+
// Hook installation blocked by the user's own hook setup, not by a defect the
|
|
15
|
+
// doctor can or should repair.
|
|
16
|
+
const USER_HOOK_CONFIG_CODES = new Set(['hook-hookspath', 'hook-custom']);
|
|
14
17
|
function pathEntryExists(path) {
|
|
15
18
|
try {
|
|
16
19
|
lstatSync(path);
|
|
@@ -23,15 +26,71 @@ function pathEntryExists(path) {
|
|
|
23
26
|
function notApplicableResult(rootDir, issue) {
|
|
24
27
|
return {
|
|
25
28
|
status: 'NOT_APPLICABLE',
|
|
29
|
+
layout: 'unknown',
|
|
26
30
|
applicable: false,
|
|
27
31
|
changedCount: 0,
|
|
28
32
|
rootDir,
|
|
29
33
|
rootEntryPoints: [],
|
|
30
34
|
missingRecommendedEntryPoints: [],
|
|
31
35
|
repositories: [],
|
|
36
|
+
rootHook: 'skipped',
|
|
32
37
|
issues: [issue],
|
|
33
38
|
};
|
|
34
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* A git root project has no member repos to manage, but it does own the
|
|
42
|
+
* worktree bootstrap hook that makes `git worktree add` materialize
|
|
43
|
+
* conventions. That hook was previously reachable only from the interactive
|
|
44
|
+
* OAuth `init`, so any project configured before it existed had no way to get
|
|
45
|
+
* one. Installing it here is the doctor's whole job for this layout — member
|
|
46
|
+
* repo management (exclude, link, entry points) stays out of it.
|
|
47
|
+
*
|
|
48
|
+
* A project whose hook infrastructure the CLI must not touch is not a broken
|
|
49
|
+
* project: it keeps exit 0 (the code a git root project has always returned)
|
|
50
|
+
* and is told to use the manual per-worktree `agentteams init` fallback.
|
|
51
|
+
*/
|
|
52
|
+
function runGitRootDoctor(rootDir) {
|
|
53
|
+
const preflightIssues = validateRootPreflight(rootDir);
|
|
54
|
+
if (preflightIssues.length > 0) {
|
|
55
|
+
return {
|
|
56
|
+
status: 'DEGRADED',
|
|
57
|
+
layout: 'git-root',
|
|
58
|
+
applicable: true,
|
|
59
|
+
changedCount: 0,
|
|
60
|
+
rootDir,
|
|
61
|
+
rootEntryPoints: [],
|
|
62
|
+
missingRecommendedEntryPoints: [],
|
|
63
|
+
repositories: [],
|
|
64
|
+
rootHook: 'skipped',
|
|
65
|
+
issues: preflightIssues,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
const hookResult = ensurePostCheckoutHook(rootDir);
|
|
69
|
+
const blockedByUserHookConfig = hookResult.status === 'blocked' && USER_HOOK_CONFIG_CODES.has(hookResult.issue?.code ?? '');
|
|
70
|
+
const issues = hookResult.issue
|
|
71
|
+
? [
|
|
72
|
+
blockedByUserHookConfig
|
|
73
|
+
? {
|
|
74
|
+
...hookResult.issue,
|
|
75
|
+
message: `${hookResult.issue.message} Run 'agentteams init' from the root of each new worktree instead.`,
|
|
76
|
+
severity: 'info',
|
|
77
|
+
}
|
|
78
|
+
: { ...hookResult.issue, severity: 'error' },
|
|
79
|
+
]
|
|
80
|
+
: [];
|
|
81
|
+
return {
|
|
82
|
+
status: hookResult.status === 'ready' || blockedByUserHookConfig ? 'READY' : 'DEGRADED',
|
|
83
|
+
layout: 'git-root',
|
|
84
|
+
applicable: true,
|
|
85
|
+
changedCount: hookResult.changed ? 1 : 0,
|
|
86
|
+
rootDir,
|
|
87
|
+
rootEntryPoints: [],
|
|
88
|
+
missingRecommendedEntryPoints: [],
|
|
89
|
+
repositories: [],
|
|
90
|
+
rootHook: hookResult.status,
|
|
91
|
+
issues,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
35
94
|
/**
|
|
36
95
|
* Validate the root before any member mutation. The check never echoes the
|
|
37
96
|
* config body or API key — only paths appear in issues.
|
|
@@ -176,24 +235,21 @@ function runDoctor(options) {
|
|
|
176
235
|
});
|
|
177
236
|
}
|
|
178
237
|
if (!isNonGitRootProject(rootDir)) {
|
|
179
|
-
return
|
|
180
|
-
code: 'git-root-project',
|
|
181
|
-
path: rootDir,
|
|
182
|
-
message: `${rootDir} is a git repository root project; the doctor only manages non-git root projects.`,
|
|
183
|
-
severity: 'info',
|
|
184
|
-
});
|
|
238
|
+
return runGitRootDoctor(rootDir);
|
|
185
239
|
}
|
|
186
240
|
const issues = [];
|
|
187
241
|
const preflightIssues = validateRootPreflight(rootDir);
|
|
188
242
|
if (preflightIssues.length > 0) {
|
|
189
243
|
return {
|
|
190
244
|
status: 'DEGRADED',
|
|
245
|
+
layout: 'non-git-root',
|
|
191
246
|
applicable: true,
|
|
192
247
|
changedCount: 0,
|
|
193
248
|
rootDir,
|
|
194
249
|
rootEntryPoints: [],
|
|
195
250
|
missingRecommendedEntryPoints: [],
|
|
196
251
|
repositories: [],
|
|
252
|
+
rootHook: 'skipped',
|
|
197
253
|
issues: preflightIssues,
|
|
198
254
|
};
|
|
199
255
|
}
|
|
@@ -234,12 +290,15 @@ function runDoctor(options) {
|
|
|
234
290
|
const degraded = issues.some((issue) => issue.severity === 'error') || repositories.some((repo) => repo.status === 'DEGRADED');
|
|
235
291
|
return {
|
|
236
292
|
status: degraded ? 'DEGRADED' : 'READY',
|
|
293
|
+
layout: 'non-git-root',
|
|
237
294
|
applicable: true,
|
|
238
295
|
changedCount: repositories.reduce((sum, repo) => sum + repo.changedCount, 0),
|
|
239
296
|
rootDir,
|
|
240
297
|
rootEntryPoints: [...rootEntryPoints],
|
|
241
298
|
missingRecommendedEntryPoints: [...missingRecommendedEntryPoints],
|
|
242
299
|
repositories,
|
|
300
|
+
// Hooks for this layout are installed per member repo, not on the root.
|
|
301
|
+
rootHook: 'skipped',
|
|
243
302
|
issues,
|
|
244
303
|
};
|
|
245
304
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAChE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACjF,OAAO,EACL,2BAA2B,EAC3B,oBAAoB,EACpB,kBAAkB,EAClB,sBAAsB,EACtB,qBAAqB,EACrB,qBAAqB,EACrB,wBAAwB,GAGzB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAEhE,MAAM,UAAU,GAAG,aAAa,CAAC;AACjC,MAAM,WAAW,GAAG,aAAa,CAAC;AAClC,MAAM,eAAe,GAAG,eAAe,CAAC;AAExC,8EAA8E;AAC9E,4EAA4E;AAC5E,MAAM,qBAAqB,GAAG,CAAC,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,8BAA8B,CAAU,CAAC;AAC/G,MAAM,wBAAwB,GAAG,CAAC,WAAW,EAAE,WAAW,CAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/init.d.ts
CHANGED
|
@@ -30,7 +30,7 @@ export type WorktreeInitResult = {
|
|
|
30
30
|
worktreePath: string;
|
|
31
31
|
sourcePath: string;
|
|
32
32
|
targetPath: string;
|
|
33
|
-
materialization: 'symlink' | 'copy' | 'existing' | 'blocked';
|
|
33
|
+
materialization: 'symlink' | 'copy' | 'relinked' | 'existing' | 'blocked';
|
|
34
34
|
entryPoints: WorktreeEntryPointEntry[];
|
|
35
35
|
issues: ConventionIssue[];
|
|
36
36
|
warning?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AA6BA,OAAO,EAQL,KAAK,yBAAyB,EAC9B,KAAK,eAAe,EACpB,KAAK,4BAA4B,EAClC,MAAM,4BAA4B,CAAC;AAyBpC,KAAK,WAAW,GAAG;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,SAAS,GAAG,SAAS,CAAC;CAC7B,CAAC;AAEF,KAAK,eAAe,GAAG;IACrB,OAAO,EAAE,IAAI,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,gBAAgB,CAAC,EAAE,4BAA4B,CAAC;CACjD,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG,yBAAyB,CAAC;AAEhE,MAAM,MAAM,uBAAuB,GAAG;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,uBAAuB,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,EAAE,IAAI,CAAC;IACd,IAAI,EAAE,UAAU,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,SAAS,GAAG,MAAM,GAAG,UAAU,GAAG,UAAU,GAAG,SAAS,CAAC;IAC1E,WAAW,EAAE,uBAAuB,EAAE,CAAC;IACvC,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,KAAK,UAAU,GAAG,eAAe,GAAG,kBAAkB,CAAC;AAoCvD,wBAAgB,YAAY,IAAI,OAAO,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,CAcxE;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAYlH;AAgbD,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI,CA6F9E;AAED,wBAAsB,kBAAkB,CAAC,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAEnF"}
|
package/dist/commands/init.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { appendFileSync, cpSync, existsSync, lstatSync, mkdirSync, readFileSync, realpathSync, symlinkSync, unlinkSync, writeFileSync, } from 'node:fs';
|
|
1
|
+
import { appendFileSync, cpSync, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, symlinkSync, unlinkSync, writeFileSync, } from 'node:fs';
|
|
2
2
|
import { basename, dirname, join, resolve } from 'node:path';
|
|
3
3
|
import { constants, createCipheriv, publicEncrypt, randomBytes } from 'node:crypto';
|
|
4
4
|
import { multiselect, isCancel, cancel } from '@clack/prompts';
|
|
@@ -11,7 +11,7 @@ import { withCommandContext } from '../utils/commandContext.js';
|
|
|
11
11
|
import { conventionDownload } from './convention.js';
|
|
12
12
|
import { resolveGitTopLevel, resolveMainCheckoutRoot } from '../utils/git.js';
|
|
13
13
|
import { buildAuthHeaders } from '../utils/apiContext.js';
|
|
14
|
-
import { DEFAULT_CONVENTION_REFERENCE, ensureConventionEntryPoints, ensureLocalExclude, ensurePostCheckoutHook, isReadableRegularFile, toAnchoredExcludePattern, } from '../utils/conventionLink.js';
|
|
14
|
+
import { DEFAULT_CONVENTION_REFERENCE, ensureConventionEntryPoints, ensureLocalExclude, ensurePostCheckoutHook, isReadableRegularFile, resolveGitCommonDir, toAnchoredExcludePattern, } from '../utils/conventionLink.js';
|
|
15
15
|
const AUTH_BASE_URL = process.env.AGENTTEAMS_WEB_URL || 'https://agentteams.run';
|
|
16
16
|
const AGENT_ENTRY_POINT_FILES = [
|
|
17
17
|
{ value: 'CLAUDE.md', label: 'CLAUDE.md', hint: 'Claude Code' },
|
|
@@ -22,6 +22,7 @@ const AGENT_ENTRY_POINT_FILES = [
|
|
|
22
22
|
const CONFIG_DIR = '.agentteams';
|
|
23
23
|
const CONFIG_FILE = 'config.json';
|
|
24
24
|
const CONVENTION_FILE = 'convention.md';
|
|
25
|
+
const RELINK_BACKUP_NAME = 'agentteams-relink';
|
|
25
26
|
const AUTH_PATH_PUBLIC_KEY_PEM = `-----BEGIN PUBLIC KEY-----
|
|
26
27
|
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs9s9+n0C8Z099LrOTlKB
|
|
27
28
|
83c2WluO/TxZFxJQ07XgfKJ2RG/8K2kvCwVKeSgzzBP/hmY2qWAgAOrXIoSHNYGt
|
|
@@ -232,6 +233,221 @@ function isConfiguredMainCheckout(sourcePath) {
|
|
|
232
233
|
return false;
|
|
233
234
|
}
|
|
234
235
|
}
|
|
236
|
+
/**
|
|
237
|
+
* Materialize the worktree's `.agentteams` entry as a real link.
|
|
238
|
+
*
|
|
239
|
+
* Windows directory symlinks require SeCreateSymbolicLinkPrivilege (Developer
|
|
240
|
+
* Mode or elevation), so an unprivileged win32 run fails with EPERM and used to
|
|
241
|
+
* fall through to a copy — silently breaking the guarantee that a worktree
|
|
242
|
+
* tracks the main checkout's conventions. Junctions need no privilege, which is
|
|
243
|
+
* why `utils/conventionLink.ts` and the daemon's worktree helper already use
|
|
244
|
+
* them; this is the same documented platform exception.
|
|
245
|
+
*
|
|
246
|
+
* The copy fallback stays for environments neither link type supports (UNC
|
|
247
|
+
* paths, filesystems without reparse points). It dereferences because in a
|
|
248
|
+
* non-git-root layout the source is itself a link, and copying a link
|
|
249
|
+
* recursively re-creates it — which fails for exactly the same reason.
|
|
250
|
+
*/
|
|
251
|
+
function linkConventionDir(sourcePath, targetPath) {
|
|
252
|
+
try {
|
|
253
|
+
if (process.platform === 'win32') {
|
|
254
|
+
// Junctions only accept absolute targets, so resolve the chain first.
|
|
255
|
+
symlinkSync(realpathSync(sourcePath), targetPath, 'junction');
|
|
256
|
+
}
|
|
257
|
+
else {
|
|
258
|
+
symlinkSync(sourcePath, targetPath, 'dir');
|
|
259
|
+
}
|
|
260
|
+
return { materialization: 'symlink' };
|
|
261
|
+
}
|
|
262
|
+
catch (error) {
|
|
263
|
+
cpSync(sourcePath, targetPath, { recursive: true, dereference: true });
|
|
264
|
+
return {
|
|
265
|
+
materialization: 'copy',
|
|
266
|
+
warning: `Could not create the .agentteams symlink (${error instanceof Error ? error.message : String(error)}). Copied the directory instead.`,
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Decide whether a plain directory sitting at the worktree's `.agentteams` may
|
|
272
|
+
* be the copy an earlier failed link attempt left behind, rather than something
|
|
273
|
+
* the user created. Identity is judged by the config file, the one artifact a
|
|
274
|
+
* copy reproduces byte for byte — anything else is treated as the user's and is
|
|
275
|
+
* never touched. This only authorizes moving the directory aside; whether the
|
|
276
|
+
* moved copy may be deleted is decided separately by `findCopyOnlyFiles`.
|
|
277
|
+
*/
|
|
278
|
+
function isCopyOfMainCheckout(sourcePath, targetPath) {
|
|
279
|
+
try {
|
|
280
|
+
return (readFileSync(join(targetPath, CONFIG_FILE), 'utf-8') === readFileSync(join(sourcePath, CONFIG_FILE), 'utf-8'));
|
|
281
|
+
}
|
|
282
|
+
catch {
|
|
283
|
+
return false;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
function toErrorMessage(error) {
|
|
287
|
+
return error instanceof Error ? error.message : String(error);
|
|
288
|
+
}
|
|
289
|
+
function hasIdenticalFile(sourceFile, backupFile) {
|
|
290
|
+
try {
|
|
291
|
+
const sourceStats = statSync(sourceFile);
|
|
292
|
+
if (!sourceStats.isFile() || sourceStats.size !== statSync(backupFile).size)
|
|
293
|
+
return false;
|
|
294
|
+
return readFileSync(sourceFile).equals(readFileSync(backupFile));
|
|
295
|
+
}
|
|
296
|
+
catch {
|
|
297
|
+
return false;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* List every file in the moved-aside copy that the main checkout does not
|
|
302
|
+
* already hold byte for byte. A worktree that ran as a copy accumulates its own
|
|
303
|
+
* artifacts inside `.agentteams` — runner history, evidence, downloaded plans,
|
|
304
|
+
* review findings — and none of them can be regenerated, so the copy is only
|
|
305
|
+
* safe to delete when it is a strict subset of the source. Anything that is not
|
|
306
|
+
* a plain matching file (a symlink, a special file, an unreadable directory)
|
|
307
|
+
* counts as copy-only: it cannot be proven redundant.
|
|
308
|
+
*/
|
|
309
|
+
function findCopyOnlyFiles(backupPath, sourcePath) {
|
|
310
|
+
const copyOnlyFiles = [];
|
|
311
|
+
const walk = (relativeDir) => {
|
|
312
|
+
let entries;
|
|
313
|
+
try {
|
|
314
|
+
entries = readdirSync(join(backupPath, relativeDir), { withFileTypes: true });
|
|
315
|
+
}
|
|
316
|
+
catch {
|
|
317
|
+
copyOnlyFiles.push(relativeDir || '.');
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
for (const entry of entries) {
|
|
321
|
+
const relativePath = relativeDir ? join(relativeDir, entry.name) : entry.name;
|
|
322
|
+
if (entry.isDirectory()) {
|
|
323
|
+
walk(relativePath);
|
|
324
|
+
}
|
|
325
|
+
else if (!entry.isFile() || !hasIdenticalFile(join(sourcePath, relativePath), join(backupPath, relativePath))) {
|
|
326
|
+
copyOnlyFiles.push(relativePath);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
};
|
|
330
|
+
walk('');
|
|
331
|
+
return copyOnlyFiles;
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Park the copy outside every tracked surface while the link is created. A
|
|
335
|
+
* backup next to `.agentteams` would show up in `git status` — the anchored
|
|
336
|
+
* `/.agentteams` exclude is an exact match and does not cover a sibling name —
|
|
337
|
+
* and the copied `config.json` carries the project apiKey. `git-common-dir` is
|
|
338
|
+
* part of no working tree, so nothing can surface from there. A worktree on a
|
|
339
|
+
* different volume cannot be renamed into it, and only then does the
|
|
340
|
+
* in-worktree fallback apply — after registering its own exclude pattern.
|
|
341
|
+
*/
|
|
342
|
+
function moveConventionCopyAside(worktreePath, targetPath) {
|
|
343
|
+
const failures = [];
|
|
344
|
+
const commonDir = resolveGitCommonDir(worktreePath);
|
|
345
|
+
if (commonDir) {
|
|
346
|
+
const backupPath = join(commonDir, `${RELINK_BACKUP_NAME}-${process.pid}`);
|
|
347
|
+
try {
|
|
348
|
+
renameSync(targetPath, backupPath);
|
|
349
|
+
return { backupPath };
|
|
350
|
+
}
|
|
351
|
+
catch (error) {
|
|
352
|
+
failures.push(toErrorMessage(error));
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
const excludeResult = ensureLocalExclude(worktreePath, [toAnchoredExcludePattern(`.${RELINK_BACKUP_NAME}`)]);
|
|
356
|
+
if (excludeResult.status !== 'ready') {
|
|
357
|
+
failures.push(`the in-worktree backup cannot be kept out of git status (${excludeResult.issue?.message ?? 'local exclude is blocked'})`);
|
|
358
|
+
return { error: failures.join('; ') };
|
|
359
|
+
}
|
|
360
|
+
try {
|
|
361
|
+
const backupPath = join(worktreePath, `.${RELINK_BACKUP_NAME}`);
|
|
362
|
+
renameSync(targetPath, backupPath);
|
|
363
|
+
return { backupPath };
|
|
364
|
+
}
|
|
365
|
+
catch (error) {
|
|
366
|
+
failures.push(toErrorMessage(error));
|
|
367
|
+
return { error: failures.join('; ') };
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
/** Undo the move-aside. The target may hold a fresh link or a partial copy, and
|
|
371
|
+
* `renameSync` onto a non-empty directory fails with ENOTEMPTY, so clear it
|
|
372
|
+
* first and never let the restore itself escape as an exception. */
|
|
373
|
+
function restoreConventionCopy(backupPath, targetPath) {
|
|
374
|
+
try {
|
|
375
|
+
rmSync(targetPath, { recursive: true, force: true });
|
|
376
|
+
renameSync(backupPath, targetPath);
|
|
377
|
+
return true;
|
|
378
|
+
}
|
|
379
|
+
catch {
|
|
380
|
+
return false;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* Replace a copied `.agentteams` directory with a real link so a worktree that
|
|
385
|
+
* predates the link fix starts tracking the main checkout again. Without this
|
|
386
|
+
* the `existing` branch treats the copy as settled and the worktree keeps
|
|
387
|
+
* serving stale conventions forever.
|
|
388
|
+
*
|
|
389
|
+
* The copy is moved aside first and is deleted only once the link is in place
|
|
390
|
+
* *and* the copy proves to be a strict subset of the main checkout; otherwise
|
|
391
|
+
* the backup is kept and its path reported. Any failure restores the original
|
|
392
|
+
* directory, and a failed restore reports where the original is.
|
|
393
|
+
*/
|
|
394
|
+
function promoteCopiedConventionDir(worktreePath, sourcePath, targetPath) {
|
|
395
|
+
if (!isCopyOfMainCheckout(sourcePath, targetPath)) {
|
|
396
|
+
return {
|
|
397
|
+
materialization: 'existing',
|
|
398
|
+
issue: {
|
|
399
|
+
code: 'link-occupied',
|
|
400
|
+
path: targetPath,
|
|
401
|
+
message: `The directory at ${targetPath} does not match the main checkout's ${CONFIG_DIR}; leaving it untouched. Remove it manually to restore the convention link.`,
|
|
402
|
+
},
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
const moved = moveConventionCopyAside(worktreePath, targetPath);
|
|
406
|
+
if ('error' in moved) {
|
|
407
|
+
return {
|
|
408
|
+
materialization: 'existing',
|
|
409
|
+
issue: {
|
|
410
|
+
code: 'link-create-failed',
|
|
411
|
+
path: targetPath,
|
|
412
|
+
message: `Could not move the copied ${CONFIG_DIR} aside at ${targetPath}: ${moved.error}`,
|
|
413
|
+
},
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
const { backupPath } = moved;
|
|
417
|
+
try {
|
|
418
|
+
const { materialization } = linkConventionDir(sourcePath, targetPath);
|
|
419
|
+
// A copy fallback here would only rebuild the state being replaced.
|
|
420
|
+
if (materialization !== 'symlink') {
|
|
421
|
+
throw new Error('the link could not be created and a copy would not restore the convention chain');
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
catch (error) {
|
|
425
|
+
const restored = restoreConventionCopy(backupPath, targetPath);
|
|
426
|
+
return {
|
|
427
|
+
materialization: 'existing',
|
|
428
|
+
issue: {
|
|
429
|
+
code: 'link-create-failed',
|
|
430
|
+
path: targetPath,
|
|
431
|
+
message: restored
|
|
432
|
+
? `Could not relink ${targetPath} to the main checkout: ${toErrorMessage(error)}`
|
|
433
|
+
: `Could not relink ${targetPath} to the main checkout: ${toErrorMessage(error)}. The original ${CONFIG_DIR} was left at ${backupPath}; move it back manually.`,
|
|
434
|
+
},
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
const copyOnlyFiles = findCopyOnlyFiles(backupPath, sourcePath);
|
|
438
|
+
if (copyOnlyFiles.length > 0) {
|
|
439
|
+
return {
|
|
440
|
+
materialization: 'relinked',
|
|
441
|
+
issue: {
|
|
442
|
+
code: 'link-backup-retained',
|
|
443
|
+
path: backupPath,
|
|
444
|
+
message: `Kept ${copyOnlyFiles.length} file(s) that exist only in the replaced ${CONFIG_DIR} copy (${copyOnlyFiles.slice(0, 3).join(', ')}${copyOnlyFiles.length > 3 ? ', …' : ''}) at ${backupPath}; move what you still need out of it and delete it.`,
|
|
445
|
+
},
|
|
446
|
+
};
|
|
447
|
+
}
|
|
448
|
+
rmSync(backupPath, { recursive: true, force: true });
|
|
449
|
+
return { materialization: 'relinked' };
|
|
450
|
+
}
|
|
235
451
|
function isBrokenSymbolicLink(path) {
|
|
236
452
|
try {
|
|
237
453
|
return lstatSync(path).isSymbolicLink() && !existsSync(path);
|
|
@@ -289,30 +505,25 @@ export function bootstrapLinkedWorktree(cwd) {
|
|
|
289
505
|
}
|
|
290
506
|
else if (isBrokenSymbolicLink(targetPath)) {
|
|
291
507
|
unlinkSync(targetPath);
|
|
292
|
-
|
|
293
|
-
symlinkSync(sourcePath, targetPath, 'dir');
|
|
294
|
-
materialization = 'symlink';
|
|
295
|
-
}
|
|
296
|
-
catch (error) {
|
|
297
|
-
warning = `Could not create the .agentteams symlink (${error instanceof Error ? error.message : String(error)}). Copied the directory instead.`;
|
|
298
|
-
cpSync(sourcePath, targetPath, { recursive: true });
|
|
299
|
-
materialization = 'copy';
|
|
300
|
-
}
|
|
508
|
+
({ materialization, warning } = linkConventionDir(sourcePath, targetPath));
|
|
301
509
|
}
|
|
302
510
|
else if (existsSync(targetPath)) {
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
symlinkSync(sourcePath, targetPath, 'dir');
|
|
308
|
-
materialization = 'symlink';
|
|
511
|
+
// An entry that is already a link is settled; a plain directory is either a
|
|
512
|
+
// copy left by a failed link attempt or something the user put there.
|
|
513
|
+
if (lstatSync(targetPath).isSymbolicLink()) {
|
|
514
|
+
materialization = 'existing';
|
|
309
515
|
}
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
516
|
+
else {
|
|
517
|
+
const promotion = promoteCopiedConventionDir(worktreePath, sourcePath, targetPath);
|
|
518
|
+
materialization = promotion.materialization;
|
|
519
|
+
if (promotion.issue) {
|
|
520
|
+
issues.push(promotion.issue);
|
|
521
|
+
}
|
|
314
522
|
}
|
|
315
523
|
}
|
|
524
|
+
else {
|
|
525
|
+
({ materialization, warning } = linkConventionDir(sourcePath, targetPath));
|
|
526
|
+
}
|
|
316
527
|
const entryPointResult = ensureConventionEntryPoints(worktreePath, selectedEntryPoints, {
|
|
317
528
|
allowCreate: excludeReady,
|
|
318
529
|
validateExistingReference: false,
|