@iloom/cli 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +58 -16
- package/dist/{BranchNamingService-B5PVRR7F.js → BranchNamingService-FLPUUFOB.js} +2 -2
- package/dist/ClaudeContextManager-KE5TBZVZ.js +14 -0
- package/dist/ClaudeService-CRSETT3A.js +13 -0
- package/dist/{GitHubService-S2OGUTDR.js → GitHubService-O7U4UQ7N.js} +3 -3
- package/dist/{LoomLauncher-5LFM4LXB.js → LoomLauncher-NL65LSKP.js} +6 -6
- package/dist/{MetadataManager-DFI73J3G.js → MetadataManager-XJ2YB762.js} +2 -2
- package/dist/PRManager-2ABCWXHW.js +16 -0
- package/dist/{ProjectCapabilityDetector-S5FLNCFI.js → ProjectCapabilityDetector-UZYW32SY.js} +3 -3
- package/dist/{PromptTemplateManager-C3DK6XZL.js → PromptTemplateManager-7L3HJQQU.js} +2 -2
- package/dist/README.md +58 -16
- package/dist/{SettingsManager-35F5RUJH.js → SettingsManager-YU4VYPTW.js} +2 -2
- package/dist/agents/iloom-issue-analyze-and-plan.md +42 -17
- package/dist/agents/iloom-issue-analyzer.md +14 -14
- package/dist/agents/iloom-issue-complexity-evaluator.md +38 -15
- package/dist/agents/iloom-issue-enhancer.md +15 -15
- package/dist/agents/iloom-issue-implementer.md +44 -15
- package/dist/agents/iloom-issue-planner.md +121 -17
- package/dist/agents/iloom-issue-reviewer.md +15 -15
- package/dist/{build-FJVYP7EV.js → build-O2EJHDEW.js} +9 -9
- package/dist/{chunk-ZPSTA5PR.js → chunk-3CDWFEGL.js} +2 -2
- package/dist/{chunk-VU3QMIP2.js → chunk-453NC377.js} +91 -15
- package/dist/chunk-453NC377.js.map +1 -0
- package/dist/{chunk-UQIXZ3BA.js → chunk-5V74K5ZA.js} +2 -2
- package/dist/{chunk-7WANFUIK.js → chunk-6TL3BYH6.js} +2 -2
- package/dist/{chunk-5TXLVEXT.js → chunk-C3AKFAIR.js} +2 -2
- package/dist/{chunk-K7SEEHKO.js → chunk-CNSTXBJ3.js} +7 -419
- package/dist/chunk-CNSTXBJ3.js.map +1 -0
- package/dist/{chunk-5IWU3HXE.js → chunk-EPPPDVHD.js} +23 -11
- package/dist/chunk-EPPPDVHD.js.map +1 -0
- package/dist/{chunk-UB4TFAXJ.js → chunk-FEAJR6PN.js} +9 -55
- package/dist/chunk-FEAJR6PN.js.map +1 -0
- package/dist/{chunk-6YSFTPKW.js → chunk-FM4KBPVA.js} +18 -13
- package/dist/chunk-FM4KBPVA.js.map +1 -0
- package/dist/{chunk-AEIMYF4P.js → chunk-FP7G7DG3.js} +6 -2
- package/dist/chunk-FP7G7DG3.js.map +1 -0
- package/dist/{chunk-LT3SGBR7.js → chunk-GCPAZSGV.js} +36 -2
- package/dist/{chunk-LT3SGBR7.js.map → chunk-GCPAZSGV.js.map} +1 -1
- package/dist/chunk-GJMEKEI5.js +517 -0
- package/dist/chunk-GJMEKEI5.js.map +1 -0
- package/dist/{chunk-64O2UIWO.js → chunk-GV5X6XUE.js} +4 -4
- package/dist/{chunk-7Q66W4OH.js → chunk-HBJITKSZ.js} +37 -1
- package/dist/chunk-HBJITKSZ.js.map +1 -0
- package/dist/{chunk-7HIRPCKU.js → chunk-HVQNVRAF.js} +2 -2
- package/dist/{chunk-BXCPJJYM.js → chunk-ITN64ENQ.js} +1 -1
- package/dist/chunk-ITN64ENQ.js.map +1 -0
- package/dist/{chunk-6U6VI4SZ.js → chunk-KVS4XGBQ.js} +4 -4
- package/dist/{chunk-AXX3QIKK.js → chunk-LLWX3PCW.js} +2 -2
- package/dist/{chunk-WIJWIKAN.js → chunk-LQBLDI47.js} +105 -7
- package/dist/chunk-LQBLDI47.js.map +1 -0
- package/dist/{chunk-SN3Z6EZO.js → chunk-N7FVXZNI.js} +2 -2
- package/dist/chunk-NTIZLX42.js +822 -0
- package/dist/chunk-NTIZLX42.js.map +1 -0
- package/dist/{chunk-PMVWQBWS.js → chunk-S7YMZQUD.js} +31 -45
- package/dist/chunk-S7YMZQUD.js.map +1 -0
- package/dist/chunk-TIYJEEVO.js +79 -0
- package/dist/chunk-TIYJEEVO.js.map +1 -0
- package/dist/{chunk-EK3XCAAS.js → chunk-UDRZY65Y.js} +2 -2
- package/dist/{chunk-3PT7RKL5.js → chunk-USJSNHGG.js} +2 -2
- package/dist/{chunk-CFUWQHCJ.js → chunk-VWGKGNJP.js} +114 -35
- package/dist/chunk-VWGKGNJP.js.map +1 -0
- package/dist/{chunk-F6WVM437.js → chunk-WFQ5CLTR.js} +6 -3
- package/dist/chunk-WFQ5CLTR.js.map +1 -0
- package/dist/{chunk-TRQ76ISK.js → chunk-Z6BO53V7.js} +9 -9
- package/dist/{chunk-GEXP5IOF.js → chunk-ZA575VLF.js} +21 -8
- package/dist/chunk-ZA575VLF.js.map +1 -0
- package/dist/{claude-H33OQMXO.js → claude-6H36IBHO.js} +4 -2
- package/dist/{cleanup-OU2HFOOG.js → cleanup-ZPOMRSNN.js} +20 -16
- package/dist/cleanup-ZPOMRSNN.js.map +1 -0
- package/dist/cli.js +511 -959
- package/dist/cli.js.map +1 -1
- package/dist/commit-6S2RIA2K.js +237 -0
- package/dist/commit-6S2RIA2K.js.map +1 -0
- package/dist/{compile-ULNO5F7Q.js → compile-LRMAADUT.js} +9 -9
- package/dist/{contribute-T7ENST5N.js → contribute-GXKOIA42.js} +99 -31
- package/dist/contribute-GXKOIA42.js.map +1 -0
- package/dist/{dev-server-4RCDJ5MU.js → dev-server-GREJUEKW.js} +22 -74
- package/dist/dev-server-GREJUEKW.js.map +1 -0
- package/dist/{feedback-O4Q55SVS.js → feedback-G7G5QCY4.js} +10 -10
- package/dist/{git-FVMGBHC2.js → git-ENLT2VNI.js} +6 -4
- package/dist/hooks/iloom-hook.js +30 -2
- package/dist/{ignite-VHV65WEZ.js → ignite-YUAOJ5PP.js} +20 -20
- package/dist/ignite-YUAOJ5PP.js.map +1 -0
- package/dist/index.d.ts +71 -27
- package/dist/index.js +196 -266
- package/dist/index.js.map +1 -1
- package/dist/init-XQQMFDM6.js +21 -0
- package/dist/{lint-5JMCWE4Y.js → lint-OFVN7FT6.js} +9 -9
- package/dist/mcp/issue-management-server.js +359 -13
- package/dist/mcp/issue-management-server.js.map +1 -1
- package/dist/mcp/recap-server.js +13 -4
- package/dist/mcp/recap-server.js.map +1 -1
- package/dist/{open-WHVUYGPY.js → open-MCWQAPSZ.js} +25 -76
- package/dist/open-MCWQAPSZ.js.map +1 -0
- package/dist/{projects-SA76I4TZ.js → projects-PQOTWUII.js} +11 -4
- package/dist/projects-PQOTWUII.js.map +1 -0
- package/dist/prompts/init-prompt.txt +63 -59
- package/dist/prompts/issue-prompt.txt +132 -63
- package/dist/prompts/pr-prompt.txt +3 -3
- package/dist/prompts/regular-prompt.txt +16 -18
- package/dist/prompts/session-summary-prompt.txt +13 -13
- package/dist/{rebase-5EY3Q6XP.js → rebase-RKQED567.js} +53 -8
- package/dist/rebase-RKQED567.js.map +1 -0
- package/dist/{recap-VOOUXOGP.js → recap-ZKGHZCX6.js} +6 -6
- package/dist/{run-NCRK5NPR.js → run-CCG24PBC.js} +25 -76
- package/dist/run-CCG24PBC.js.map +1 -0
- package/dist/schema/settings.schema.json +14 -3
- package/dist/{shell-SBLXVOVJ.js → shell-2NNSIU34.js} +6 -6
- package/dist/{summary-CVFAMDOJ.js → summary-G6L3VAKK.js} +11 -10
- package/dist/{summary-CVFAMDOJ.js.map → summary-G6L3VAKK.js.map} +1 -1
- package/dist/{test-3KIVXI6J.js → test-QZDOEUIO.js} +9 -9
- package/dist/{test-git-ZB6AGGRW.js → test-git-E2BLXR6M.js} +4 -4
- package/dist/{test-prefix-FBGXKMPA.js → test-prefix-A7JGGYAA.js} +4 -4
- package/dist/{test-webserver-YVQD42W6.js → test-webserver-NRMGT2HB.js} +29 -8
- package/dist/test-webserver-NRMGT2HB.js.map +1 -0
- package/package.json +3 -1
- package/dist/ClaudeContextManager-6J2EB4QU.js +0 -14
- package/dist/ClaudeService-O2PB22GX.js +0 -13
- package/dist/PRManager-OCSB2HPT.js +0 -14
- package/dist/chunk-5IWU3HXE.js.map +0 -1
- package/dist/chunk-6YSFTPKW.js.map +0 -1
- package/dist/chunk-7Q66W4OH.js.map +0 -1
- package/dist/chunk-AEIMYF4P.js.map +0 -1
- package/dist/chunk-BXCPJJYM.js.map +0 -1
- package/dist/chunk-CFUWQHCJ.js.map +0 -1
- package/dist/chunk-F6WVM437.js.map +0 -1
- package/dist/chunk-GEXP5IOF.js.map +0 -1
- package/dist/chunk-K7SEEHKO.js.map +0 -1
- package/dist/chunk-PMVWQBWS.js.map +0 -1
- package/dist/chunk-UB4TFAXJ.js.map +0 -1
- package/dist/chunk-VU3QMIP2.js.map +0 -1
- package/dist/chunk-W6WVRHJ6.js +0 -251
- package/dist/chunk-W6WVRHJ6.js.map +0 -1
- package/dist/chunk-WIJWIKAN.js.map +0 -1
- package/dist/cleanup-OU2HFOOG.js.map +0 -1
- package/dist/contribute-T7ENST5N.js.map +0 -1
- package/dist/dev-server-4RCDJ5MU.js.map +0 -1
- package/dist/ignite-VHV65WEZ.js.map +0 -1
- package/dist/init-HB34Q5FH.js +0 -21
- package/dist/open-WHVUYGPY.js.map +0 -1
- package/dist/projects-SA76I4TZ.js.map +0 -1
- package/dist/rebase-5EY3Q6XP.js.map +0 -1
- package/dist/run-NCRK5NPR.js.map +0 -1
- package/dist/test-webserver-YVQD42W6.js.map +0 -1
- /package/dist/{BranchNamingService-B5PVRR7F.js.map → BranchNamingService-FLPUUFOB.js.map} +0 -0
- /package/dist/{ClaudeContextManager-6J2EB4QU.js.map → ClaudeContextManager-KE5TBZVZ.js.map} +0 -0
- /package/dist/{ClaudeService-O2PB22GX.js.map → ClaudeService-CRSETT3A.js.map} +0 -0
- /package/dist/{GitHubService-S2OGUTDR.js.map → GitHubService-O7U4UQ7N.js.map} +0 -0
- /package/dist/{LoomLauncher-5LFM4LXB.js.map → LoomLauncher-NL65LSKP.js.map} +0 -0
- /package/dist/{MetadataManager-DFI73J3G.js.map → MetadataManager-XJ2YB762.js.map} +0 -0
- /package/dist/{PRManager-OCSB2HPT.js.map → PRManager-2ABCWXHW.js.map} +0 -0
- /package/dist/{ProjectCapabilityDetector-S5FLNCFI.js.map → ProjectCapabilityDetector-UZYW32SY.js.map} +0 -0
- /package/dist/{PromptTemplateManager-C3DK6XZL.js.map → PromptTemplateManager-7L3HJQQU.js.map} +0 -0
- /package/dist/{SettingsManager-35F5RUJH.js.map → SettingsManager-YU4VYPTW.js.map} +0 -0
- /package/dist/{build-FJVYP7EV.js.map → build-O2EJHDEW.js.map} +0 -0
- /package/dist/{chunk-ZPSTA5PR.js.map → chunk-3CDWFEGL.js.map} +0 -0
- /package/dist/{chunk-UQIXZ3BA.js.map → chunk-5V74K5ZA.js.map} +0 -0
- /package/dist/{chunk-7WANFUIK.js.map → chunk-6TL3BYH6.js.map} +0 -0
- /package/dist/{chunk-5TXLVEXT.js.map → chunk-C3AKFAIR.js.map} +0 -0
- /package/dist/{chunk-64O2UIWO.js.map → chunk-GV5X6XUE.js.map} +0 -0
- /package/dist/{chunk-7HIRPCKU.js.map → chunk-HVQNVRAF.js.map} +0 -0
- /package/dist/{chunk-6U6VI4SZ.js.map → chunk-KVS4XGBQ.js.map} +0 -0
- /package/dist/{chunk-AXX3QIKK.js.map → chunk-LLWX3PCW.js.map} +0 -0
- /package/dist/{chunk-SN3Z6EZO.js.map → chunk-N7FVXZNI.js.map} +0 -0
- /package/dist/{chunk-EK3XCAAS.js.map → chunk-UDRZY65Y.js.map} +0 -0
- /package/dist/{chunk-3PT7RKL5.js.map → chunk-USJSNHGG.js.map} +0 -0
- /package/dist/{chunk-TRQ76ISK.js.map → chunk-Z6BO53V7.js.map} +0 -0
- /package/dist/{claude-H33OQMXO.js.map → claude-6H36IBHO.js.map} +0 -0
- /package/dist/{compile-ULNO5F7Q.js.map → compile-LRMAADUT.js.map} +0 -0
- /package/dist/{feedback-O4Q55SVS.js.map → feedback-G7G5QCY4.js.map} +0 -0
- /package/dist/{git-FVMGBHC2.js.map → git-ENLT2VNI.js.map} +0 -0
- /package/dist/{init-HB34Q5FH.js.map → init-XQQMFDM6.js.map} +0 -0
- /package/dist/{lint-5JMCWE4Y.js.map → lint-OFVN7FT6.js.map} +0 -0
- /package/dist/{recap-VOOUXOGP.js.map → recap-ZKGHZCX6.js.map} +0 -0
- /package/dist/{shell-SBLXVOVJ.js.map → shell-2NNSIU34.js.map} +0 -0
- /package/dist/{test-3KIVXI6J.js.map → test-QZDOEUIO.js.map} +0 -0
- /package/dist/{test-git-ZB6AGGRW.js.map → test-git-E2BLXR6M.js.map} +0 -0
- /package/dist/{test-prefix-FBGXKMPA.js.map → test-prefix-A7JGGYAA.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -494,11 +494,12 @@ import path2 from "path";
|
|
|
494
494
|
import os from "os";
|
|
495
495
|
import { z } from "zod";
|
|
496
496
|
import deepmerge from "deepmerge";
|
|
497
|
-
var AgentSettingsSchema, SpinAgentSettingsSchema, SummarySettingsSchema, WorkflowPermissionSchema, WorkflowPermissionSchemaNoDefaults, WorkflowsSettingsSchema, WorkflowsSettingsSchemaNoDefaults, CapabilitiesSettingsSchema, CapabilitiesSettingsSchemaNoDefaults, NeonSettingsSchema, DatabaseProvidersSettingsSchema, IloomSettingsSchema, IloomSettingsSchemaNoDefaults, SettingsManager;
|
|
497
|
+
var PROJECT_CAPABILITIES, AgentSettingsSchema, SpinAgentSettingsSchema, SummarySettingsSchema, WorkflowPermissionSchema, WorkflowPermissionSchemaNoDefaults, WorkflowsSettingsSchema, WorkflowsSettingsSchemaNoDefaults, CapabilitiesSettingsSchema, CapabilitiesSettingsSchemaNoDefaults, NeonSettingsSchema, DatabaseProvidersSettingsSchema, IloomSettingsSchema, IloomSettingsSchemaNoDefaults, SettingsManager;
|
|
498
498
|
var init_SettingsManager = __esm({
|
|
499
499
|
"src/lib/SettingsManager.ts"() {
|
|
500
500
|
"use strict";
|
|
501
501
|
init_logger();
|
|
502
|
+
PROJECT_CAPABILITIES = ["cli", "web"];
|
|
502
503
|
AgentSettingsSchema = z.object({
|
|
503
504
|
model: z.enum(["sonnet", "opus", "haiku"]).optional().describe("Claude model shorthand: sonnet, opus, or haiku")
|
|
504
505
|
// Future: could add other per-agent overrides
|
|
@@ -511,7 +512,7 @@ var init_SettingsManager = __esm({
|
|
|
511
512
|
});
|
|
512
513
|
WorkflowPermissionSchema = z.object({
|
|
513
514
|
permissionMode: z.enum(["plan", "acceptEdits", "bypassPermissions", "default"]).optional().describe("Permission mode for Claude CLI in this workflow type"),
|
|
514
|
-
noVerify: z.boolean().optional().describe("Skip pre-commit hooks (--no-verify) when committing during finish
|
|
515
|
+
noVerify: z.boolean().optional().describe("Skip pre-commit hooks (--no-verify) when committing during commit and finish workflows"),
|
|
515
516
|
startIde: z.boolean().default(true).describe("Launch IDE (code) when starting this workflow type"),
|
|
516
517
|
startDevServer: z.boolean().default(true).describe("Launch development server when starting this workflow type"),
|
|
517
518
|
startAiAgent: z.boolean().default(true).describe("Launch Claude Code agent when starting this workflow type"),
|
|
@@ -520,7 +521,7 @@ var init_SettingsManager = __esm({
|
|
|
520
521
|
});
|
|
521
522
|
WorkflowPermissionSchemaNoDefaults = z.object({
|
|
522
523
|
permissionMode: z.enum(["plan", "acceptEdits", "bypassPermissions", "default"]).optional().describe("Permission mode for Claude CLI in this workflow type"),
|
|
523
|
-
noVerify: z.boolean().optional().describe("Skip pre-commit hooks (--no-verify) when committing during finish
|
|
524
|
+
noVerify: z.boolean().optional().describe("Skip pre-commit hooks (--no-verify) when committing during commit and finish workflows"),
|
|
524
525
|
startIde: z.boolean().optional().describe("Launch IDE (code) when starting this workflow type"),
|
|
525
526
|
startDevServer: z.boolean().optional().describe("Launch development server when starting this workflow type"),
|
|
526
527
|
startAiAgent: z.boolean().optional().describe("Launch Claude Code agent when starting this workflow type"),
|
|
@@ -538,6 +539,7 @@ var init_SettingsManager = __esm({
|
|
|
538
539
|
regular: WorkflowPermissionSchemaNoDefaults.optional()
|
|
539
540
|
}).optional();
|
|
540
541
|
CapabilitiesSettingsSchema = z.object({
|
|
542
|
+
capabilities: z.array(z.enum(PROJECT_CAPABILITIES)).optional().describe("Explicitly declared project capabilities (auto-detected if not specified)"),
|
|
541
543
|
web: z.object({
|
|
542
544
|
basePort: z.number().min(1, "Base port must be >= 1").max(65535, "Base port must be <= 65535").optional().describe("Base port for web workspace port calculations (default: 3000)")
|
|
543
545
|
}).optional(),
|
|
@@ -546,6 +548,7 @@ var init_SettingsManager = __esm({
|
|
|
546
548
|
}).optional()
|
|
547
549
|
}).optional();
|
|
548
550
|
CapabilitiesSettingsSchemaNoDefaults = z.object({
|
|
551
|
+
capabilities: z.array(z.enum(PROJECT_CAPABILITIES)).optional().describe("Explicitly declared project capabilities (auto-detected if not specified)"),
|
|
549
552
|
web: z.object({
|
|
550
553
|
basePort: z.number().min(1, "Base port must be >= 1").max(65535, "Base port must be <= 65535").optional().describe("Base port for web workspace port calculations (default: 3000)")
|
|
551
554
|
}).optional(),
|
|
@@ -1171,6 +1174,30 @@ function getLogger() {
|
|
|
1171
1174
|
var MetadataManager = class {
|
|
1172
1175
|
constructor() {
|
|
1173
1176
|
this.loomsDir = path3.join(os2.homedir(), ".config", "iloom-ai", "looms");
|
|
1177
|
+
this.finishedDir = path3.join(this.loomsDir, "finished");
|
|
1178
|
+
}
|
|
1179
|
+
/**
|
|
1180
|
+
* Convert MetadataFile to LoomMetadata with default values for optional fields
|
|
1181
|
+
*/
|
|
1182
|
+
toMetadata(data) {
|
|
1183
|
+
return {
|
|
1184
|
+
description: data.description,
|
|
1185
|
+
created_at: data.created_at ?? null,
|
|
1186
|
+
branchName: data.branchName ?? null,
|
|
1187
|
+
worktreePath: data.worktreePath ?? null,
|
|
1188
|
+
issueType: data.issueType ?? null,
|
|
1189
|
+
issue_numbers: data.issue_numbers ?? [],
|
|
1190
|
+
pr_numbers: data.pr_numbers ?? [],
|
|
1191
|
+
issueTracker: data.issueTracker ?? null,
|
|
1192
|
+
colorHex: data.colorHex ?? null,
|
|
1193
|
+
sessionId: data.sessionId ?? null,
|
|
1194
|
+
projectPath: data.projectPath ?? null,
|
|
1195
|
+
issueUrls: data.issueUrls ?? {},
|
|
1196
|
+
prUrls: data.prUrls ?? {},
|
|
1197
|
+
draftPrNumber: data.draftPrNumber ?? null,
|
|
1198
|
+
capabilities: data.capabilities ?? [],
|
|
1199
|
+
parentLoom: data.parentLoom ?? null
|
|
1200
|
+
};
|
|
1174
1201
|
}
|
|
1175
1202
|
/**
|
|
1176
1203
|
* Convert worktree path to filename slug per spec section 2.2
|
|
@@ -1230,6 +1257,7 @@ var MetadataManager = class {
|
|
|
1230
1257
|
projectPath: input.projectPath,
|
|
1231
1258
|
issueUrls: input.issueUrls,
|
|
1232
1259
|
prUrls: input.prUrls,
|
|
1260
|
+
capabilities: input.capabilities,
|
|
1233
1261
|
...input.draftPrNumber && { draftPrNumber: input.draftPrNumber },
|
|
1234
1262
|
...input.parentLoom && { parentLoom: input.parentLoom }
|
|
1235
1263
|
};
|
|
@@ -1259,23 +1287,7 @@ var MetadataManager = class {
|
|
|
1259
1287
|
if (!data.description) {
|
|
1260
1288
|
return null;
|
|
1261
1289
|
}
|
|
1262
|
-
return
|
|
1263
|
-
description: data.description,
|
|
1264
|
-
created_at: data.created_at ?? null,
|
|
1265
|
-
branchName: data.branchName ?? null,
|
|
1266
|
-
worktreePath: data.worktreePath ?? null,
|
|
1267
|
-
issueType: data.issueType ?? null,
|
|
1268
|
-
issue_numbers: data.issue_numbers ?? [],
|
|
1269
|
-
pr_numbers: data.pr_numbers ?? [],
|
|
1270
|
-
issueTracker: data.issueTracker ?? null,
|
|
1271
|
-
colorHex: data.colorHex ?? null,
|
|
1272
|
-
sessionId: data.sessionId ?? null,
|
|
1273
|
-
projectPath: data.projectPath ?? null,
|
|
1274
|
-
issueUrls: data.issueUrls ?? {},
|
|
1275
|
-
prUrls: data.prUrls ?? {},
|
|
1276
|
-
draftPrNumber: data.draftPrNumber ?? null,
|
|
1277
|
-
parentLoom: data.parentLoom ?? null
|
|
1278
|
-
};
|
|
1290
|
+
return this.toMetadata(data);
|
|
1279
1291
|
} catch (error) {
|
|
1280
1292
|
getLogger().debug(
|
|
1281
1293
|
`Could not read metadata for worktree ${worktreePath}: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -1309,23 +1321,7 @@ var MetadataManager = class {
|
|
|
1309
1321
|
if (!data.description) {
|
|
1310
1322
|
continue;
|
|
1311
1323
|
}
|
|
1312
|
-
results.push(
|
|
1313
|
-
description: data.description,
|
|
1314
|
-
created_at: data.created_at ?? null,
|
|
1315
|
-
branchName: data.branchName ?? null,
|
|
1316
|
-
worktreePath: data.worktreePath ?? null,
|
|
1317
|
-
issueType: data.issueType ?? null,
|
|
1318
|
-
issue_numbers: data.issue_numbers ?? [],
|
|
1319
|
-
pr_numbers: data.pr_numbers ?? [],
|
|
1320
|
-
issueTracker: data.issueTracker ?? null,
|
|
1321
|
-
colorHex: data.colorHex ?? null,
|
|
1322
|
-
sessionId: data.sessionId ?? null,
|
|
1323
|
-
projectPath: data.projectPath ?? null,
|
|
1324
|
-
issueUrls: data.issueUrls ?? {},
|
|
1325
|
-
prUrls: data.prUrls ?? {},
|
|
1326
|
-
draftPrNumber: data.draftPrNumber ?? null,
|
|
1327
|
-
parentLoom: data.parentLoom ?? null
|
|
1328
|
-
});
|
|
1324
|
+
results.push(this.toMetadata(data));
|
|
1329
1325
|
} catch (error) {
|
|
1330
1326
|
getLogger().debug(
|
|
1331
1327
|
`Skipping metadata file ${file}: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -1362,10 +1358,104 @@ var MetadataManager = class {
|
|
|
1362
1358
|
);
|
|
1363
1359
|
}
|
|
1364
1360
|
}
|
|
1361
|
+
/**
|
|
1362
|
+
* Archive metadata for a finished worktree
|
|
1363
|
+
*
|
|
1364
|
+
* Moves the metadata file to the finished/ subdirectory and adds
|
|
1365
|
+
* status: 'finished' and finishedAt timestamp fields.
|
|
1366
|
+
*
|
|
1367
|
+
* Idempotent: silently succeeds if source file doesn't exist
|
|
1368
|
+
* Non-fatal: logs warning on errors but doesn't throw
|
|
1369
|
+
*
|
|
1370
|
+
* @param worktreePath - Absolute path to the worktree
|
|
1371
|
+
*/
|
|
1372
|
+
async archiveMetadata(worktreePath) {
|
|
1373
|
+
try {
|
|
1374
|
+
const filename = this.slugifyPath(worktreePath);
|
|
1375
|
+
const sourcePath = path3.join(this.loomsDir, filename);
|
|
1376
|
+
if (!await fs.pathExists(sourcePath)) {
|
|
1377
|
+
getLogger().debug(`No metadata file to archive for worktree: ${worktreePath}`);
|
|
1378
|
+
return;
|
|
1379
|
+
}
|
|
1380
|
+
const content = await fs.readFile(sourcePath, "utf8");
|
|
1381
|
+
const data = JSON.parse(content);
|
|
1382
|
+
const finishedData = {
|
|
1383
|
+
...data,
|
|
1384
|
+
status: "finished",
|
|
1385
|
+
finishedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1386
|
+
};
|
|
1387
|
+
await fs.ensureDir(this.finishedDir, { mode: 493 });
|
|
1388
|
+
const destPath = path3.join(this.finishedDir, filename);
|
|
1389
|
+
await fs.writeFile(destPath, JSON.stringify(finishedData, null, 2), { mode: 420 });
|
|
1390
|
+
await fs.unlink(sourcePath);
|
|
1391
|
+
getLogger().debug(`Metadata archived for worktree: ${worktreePath}`);
|
|
1392
|
+
} catch (error) {
|
|
1393
|
+
getLogger().warn(
|
|
1394
|
+
`Failed to archive metadata for worktree: ${error instanceof Error ? error.message : String(error)}`
|
|
1395
|
+
);
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1398
|
+
/**
|
|
1399
|
+
* List all finished loom metadata files
|
|
1400
|
+
*
|
|
1401
|
+
* Returns an array of LoomMetadata objects for all finished looms
|
|
1402
|
+
* in the finished/ subdirectory, sorted by finishedAt in descending order
|
|
1403
|
+
* (most recently finished first).
|
|
1404
|
+
*
|
|
1405
|
+
* @returns Array of LoomMetadata objects from finished files, sorted by finishedAt desc
|
|
1406
|
+
*/
|
|
1407
|
+
async listFinishedMetadata() {
|
|
1408
|
+
const results = [];
|
|
1409
|
+
try {
|
|
1410
|
+
if (!await fs.pathExists(this.finishedDir)) {
|
|
1411
|
+
return results;
|
|
1412
|
+
}
|
|
1413
|
+
const files = await fs.readdir(this.finishedDir);
|
|
1414
|
+
for (const file of files) {
|
|
1415
|
+
if (!file.endsWith(".json")) {
|
|
1416
|
+
continue;
|
|
1417
|
+
}
|
|
1418
|
+
try {
|
|
1419
|
+
const filePath = path3.join(this.finishedDir, file);
|
|
1420
|
+
const content = await fs.readFile(filePath, "utf8");
|
|
1421
|
+
const data = JSON.parse(content);
|
|
1422
|
+
if (!data.description) {
|
|
1423
|
+
continue;
|
|
1424
|
+
}
|
|
1425
|
+
const metadata = this.toMetadata(data);
|
|
1426
|
+
metadata.status = data.status ?? "finished";
|
|
1427
|
+
metadata.finishedAt = data.finishedAt ?? null;
|
|
1428
|
+
results.push(metadata);
|
|
1429
|
+
} catch (error) {
|
|
1430
|
+
getLogger().warn(
|
|
1431
|
+
`Skipping finished metadata file ${file}: ${error instanceof Error ? error.message : String(error)}`
|
|
1432
|
+
);
|
|
1433
|
+
}
|
|
1434
|
+
}
|
|
1435
|
+
results.sort((a, b) => {
|
|
1436
|
+
const aTime = a.finishedAt ? new Date(a.finishedAt).getTime() : 0;
|
|
1437
|
+
const bTime = b.finishedAt ? new Date(b.finishedAt).getTime() : 0;
|
|
1438
|
+
return bTime - aTime;
|
|
1439
|
+
});
|
|
1440
|
+
} catch (error) {
|
|
1441
|
+
getLogger().warn(
|
|
1442
|
+
`Could not list finished metadata files: ${error instanceof Error ? error.message : String(error)}`
|
|
1443
|
+
);
|
|
1444
|
+
}
|
|
1445
|
+
return results;
|
|
1446
|
+
}
|
|
1365
1447
|
};
|
|
1366
1448
|
|
|
1367
1449
|
// src/utils/git.ts
|
|
1368
1450
|
init_logger();
|
|
1451
|
+
var GitCommandError = class extends Error {
|
|
1452
|
+
constructor(message, exitCode, stderr) {
|
|
1453
|
+
super(message);
|
|
1454
|
+
this.exitCode = exitCode;
|
|
1455
|
+
this.stderr = stderr;
|
|
1456
|
+
this.name = "GitCommandError";
|
|
1457
|
+
}
|
|
1458
|
+
};
|
|
1369
1459
|
async function executeGitCommand(args, options) {
|
|
1370
1460
|
try {
|
|
1371
1461
|
const result = await execa2("git", args, {
|
|
@@ -1381,7 +1471,11 @@ async function executeGitCommand(args, options) {
|
|
|
1381
1471
|
} catch (error) {
|
|
1382
1472
|
const execaError = error;
|
|
1383
1473
|
const stderr = execaError.stderr ?? execaError.message ?? "Unknown Git error";
|
|
1384
|
-
throw new
|
|
1474
|
+
throw new GitCommandError(
|
|
1475
|
+
`Git command failed: ${stderr}`,
|
|
1476
|
+
execaError.exitCode,
|
|
1477
|
+
stderr
|
|
1478
|
+
);
|
|
1385
1479
|
}
|
|
1386
1480
|
}
|
|
1387
1481
|
function parseWorktreeList(output, defaultBranch) {
|
|
@@ -1621,10 +1715,10 @@ async function getRepoRoot(path7 = process.cwd()) {
|
|
|
1621
1715
|
const repoRoot = trimmedPath.replace(/\/\.git\/worktrees\/[^/]+$/, "").replace(/\/\.git$/, "");
|
|
1622
1716
|
return repoRoot;
|
|
1623
1717
|
} catch (error) {
|
|
1624
|
-
|
|
1625
|
-
if (errorMessage.includes("not a git repository")) {
|
|
1718
|
+
if (error instanceof GitCommandError && (error.exitCode === 128 || /fatal: not a git repository/i.test(error.stderr))) {
|
|
1626
1719
|
logger.info(`Note: No git repository detected: ${path7}`);
|
|
1627
1720
|
} else {
|
|
1721
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1628
1722
|
logger.warn(`Failed to determine repo root from git-common-dir: ${path7}`, errorMessage);
|
|
1629
1723
|
}
|
|
1630
1724
|
return null;
|
|
@@ -1979,7 +2073,7 @@ async function getMergeTargetBranch(worktreePath = process.cwd(), options) {
|
|
|
1979
2073
|
logger.debug(`Using configured main branch as merge target: ${mainBranch}`);
|
|
1980
2074
|
return mainBranch;
|
|
1981
2075
|
}
|
|
1982
|
-
var PLACEHOLDER_COMMIT_PREFIX = "[iloom
|
|
2076
|
+
var PLACEHOLDER_COMMIT_PREFIX = "[iloom]";
|
|
1983
2077
|
async function isPlaceholderCommit(cwd = process.cwd()) {
|
|
1984
2078
|
try {
|
|
1985
2079
|
const subject = await executeGitCommand(["log", "-1", "--format=%s", "HEAD"], { cwd });
|
|
@@ -3058,7 +3152,6 @@ async function updateLinearIssueState(identifier, stateName) {
|
|
|
3058
3152
|
}
|
|
3059
3153
|
|
|
3060
3154
|
// src/lib/LinearService.ts
|
|
3061
|
-
init_logger();
|
|
3062
3155
|
var LinearService = class {
|
|
3063
3156
|
constructor(config, options) {
|
|
3064
3157
|
// IssueTracker interface implementation
|
|
@@ -3077,22 +3170,22 @@ var LinearService = class {
|
|
|
3077
3170
|
* @returns Detection result with type and identifier
|
|
3078
3171
|
*/
|
|
3079
3172
|
async detectInputType(input, _repo) {
|
|
3080
|
-
|
|
3173
|
+
getLogger().debug(`LinearService.detectInputType called with input: "${input}"`);
|
|
3081
3174
|
const linearPattern = /^([A-Z]{2,}-\d+)$/i;
|
|
3082
3175
|
const match = input.match(linearPattern);
|
|
3083
3176
|
if (!(match == null ? void 0 : match[1])) {
|
|
3084
|
-
|
|
3177
|
+
getLogger().debug(`LinearService: Input "${input}" does not match Linear pattern`);
|
|
3085
3178
|
return { type: "unknown", identifier: null, rawInput: input };
|
|
3086
3179
|
}
|
|
3087
3180
|
const identifier = match[1].toUpperCase();
|
|
3088
|
-
|
|
3089
|
-
|
|
3181
|
+
getLogger().debug(`LinearService: Matched Linear identifier: ${identifier}`);
|
|
3182
|
+
getLogger().debug(`LinearService: Checking if ${identifier} is a valid Linear issue via SDK`);
|
|
3090
3183
|
const issue = await this.isValidIssue(identifier);
|
|
3091
3184
|
if (issue) {
|
|
3092
|
-
|
|
3185
|
+
getLogger().debug(`LinearService: Issue ${identifier} found: "${issue.title}"`);
|
|
3093
3186
|
return { type: "issue", identifier, rawInput: input };
|
|
3094
3187
|
}
|
|
3095
|
-
|
|
3188
|
+
getLogger().debug(`LinearService: Issue ${identifier} NOT found by SDK`);
|
|
3096
3189
|
return { type: "unknown", identifier: null, rawInput: input };
|
|
3097
3190
|
}
|
|
3098
3191
|
/**
|
|
@@ -3153,7 +3246,7 @@ var LinearService = class {
|
|
|
3153
3246
|
"Linear teamId not configured. Run `il init` to configure Linear settings."
|
|
3154
3247
|
);
|
|
3155
3248
|
}
|
|
3156
|
-
|
|
3249
|
+
getLogger().info(`Creating Linear issue in team ${this.config.teamId}: ${title}`);
|
|
3157
3250
|
const result = await createLinearIssue(title, body, this.config.teamId, labels);
|
|
3158
3251
|
return {
|
|
3159
3252
|
number: result.identifier,
|
|
@@ -3176,7 +3269,7 @@ var LinearService = class {
|
|
|
3176
3269
|
* @throws LinearServiceError if state update fails
|
|
3177
3270
|
*/
|
|
3178
3271
|
async moveIssueToInProgress(identifier) {
|
|
3179
|
-
|
|
3272
|
+
getLogger().info(`Moving Linear issue ${identifier} to In Progress`);
|
|
3180
3273
|
await updateLinearIssueState(String(identifier), "In Progress");
|
|
3181
3274
|
}
|
|
3182
3275
|
/**
|
|
@@ -3262,11 +3355,25 @@ var IssueTrackerFactory = class {
|
|
|
3262
3355
|
};
|
|
3263
3356
|
|
|
3264
3357
|
// src/lib/EnvironmentManager.ts
|
|
3265
|
-
import
|
|
3358
|
+
import fs4 from "fs-extra";
|
|
3266
3359
|
init_env();
|
|
3267
3360
|
|
|
3268
3361
|
// src/utils/port.ts
|
|
3269
3362
|
import { createHash } from "crypto";
|
|
3363
|
+
init_env();
|
|
3364
|
+
import fs3 from "fs-extra";
|
|
3365
|
+
init_logger();
|
|
3366
|
+
function wrapPort(rawPort, basePort) {
|
|
3367
|
+
if (rawPort <= 65535) return rawPort;
|
|
3368
|
+
const range = 65535 - basePort;
|
|
3369
|
+
return (rawPort - basePort - 1) % range + basePort + 1;
|
|
3370
|
+
}
|
|
3371
|
+
function extractNumericSuffix(issueId) {
|
|
3372
|
+
const match = issueId.match(/[-_]?(\d+)$/);
|
|
3373
|
+
const digits = match == null ? void 0 : match[1];
|
|
3374
|
+
if (digits === void 0) return null;
|
|
3375
|
+
return parseInt(digits, 10);
|
|
3376
|
+
}
|
|
3270
3377
|
function generatePortOffsetFromBranchName(branchName) {
|
|
3271
3378
|
if (!branchName || branchName.trim().length === 0) {
|
|
3272
3379
|
throw new Error("Branch name cannot be empty");
|
|
@@ -3280,12 +3387,21 @@ function generatePortOffsetFromBranchName(branchName) {
|
|
|
3280
3387
|
function calculatePortForBranch(branchName, basePort = 3e3) {
|
|
3281
3388
|
const offset = generatePortOffsetFromBranchName(branchName);
|
|
3282
3389
|
const port = basePort + offset;
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
|
|
3390
|
+
return wrapPort(port, basePort);
|
|
3391
|
+
}
|
|
3392
|
+
function calculatePortFromIdentifier(identifier, basePort = 3e3) {
|
|
3393
|
+
if (typeof identifier === "number") {
|
|
3394
|
+
return wrapPort(basePort + identifier, basePort);
|
|
3395
|
+
}
|
|
3396
|
+
const numericValue = parseInt(identifier, 10);
|
|
3397
|
+
if (!isNaN(numericValue) && String(numericValue) === identifier) {
|
|
3398
|
+
return wrapPort(basePort + numericValue, basePort);
|
|
3287
3399
|
}
|
|
3288
|
-
|
|
3400
|
+
const numericSuffix = extractNumericSuffix(identifier);
|
|
3401
|
+
if (numericSuffix !== null) {
|
|
3402
|
+
return wrapPort(basePort + numericSuffix, basePort);
|
|
3403
|
+
}
|
|
3404
|
+
return calculatePortForBranch(`issue-${identifier}`, basePort);
|
|
3289
3405
|
}
|
|
3290
3406
|
|
|
3291
3407
|
// src/lib/EnvironmentManager.ts
|
|
@@ -3303,15 +3419,15 @@ var EnvironmentManager = class {
|
|
|
3303
3419
|
if (!validation.valid) {
|
|
3304
3420
|
throw new Error(validation.error ?? "Invalid variable name");
|
|
3305
3421
|
}
|
|
3306
|
-
const fileExists = await
|
|
3422
|
+
const fileExists = await fs4.pathExists(filePath);
|
|
3307
3423
|
if (!fileExists) {
|
|
3308
3424
|
getLogger().info(`Creating ${filePath} with ${key}...`);
|
|
3309
3425
|
const content = formatEnvLine(key, value);
|
|
3310
|
-
await
|
|
3426
|
+
await fs4.writeFile(filePath, content, "utf8");
|
|
3311
3427
|
getLogger().success(`${filePath} created with ${key}`);
|
|
3312
3428
|
return;
|
|
3313
3429
|
}
|
|
3314
|
-
const existingContent = await
|
|
3430
|
+
const existingContent = await fs4.readFile(filePath, "utf8");
|
|
3315
3431
|
const envMap = parseEnvFile(existingContent);
|
|
3316
3432
|
let backupPath;
|
|
3317
3433
|
if (backup) {
|
|
@@ -3348,7 +3464,7 @@ var EnvironmentManager = class {
|
|
|
3348
3464
|
getLogger().success(`${key} updated successfully`);
|
|
3349
3465
|
}
|
|
3350
3466
|
const newContent = newLines.join("\n");
|
|
3351
|
-
await
|
|
3467
|
+
await fs4.writeFile(filePath, newContent, "utf8");
|
|
3352
3468
|
return backupPath;
|
|
3353
3469
|
}
|
|
3354
3470
|
/**
|
|
@@ -3356,7 +3472,7 @@ var EnvironmentManager = class {
|
|
|
3356
3472
|
*/
|
|
3357
3473
|
async readEnvFile(filePath) {
|
|
3358
3474
|
try {
|
|
3359
|
-
const content = await
|
|
3475
|
+
const content = await fs4.readFile(filePath, "utf8");
|
|
3360
3476
|
return parseEnvFile(content);
|
|
3361
3477
|
} catch (error) {
|
|
3362
3478
|
getLogger().debug(
|
|
@@ -3379,12 +3495,12 @@ var EnvironmentManager = class {
|
|
|
3379
3495
|
* @private
|
|
3380
3496
|
*/
|
|
3381
3497
|
async copyIfExists(source, destination) {
|
|
3382
|
-
const sourceExists = await
|
|
3498
|
+
const sourceExists = await fs4.pathExists(source);
|
|
3383
3499
|
if (!sourceExists) {
|
|
3384
3500
|
getLogger().debug(`Source file ${source} does not exist, skipping copy`);
|
|
3385
3501
|
return;
|
|
3386
3502
|
}
|
|
3387
|
-
await
|
|
3503
|
+
await fs4.copy(source, destination, { overwrite: false });
|
|
3388
3504
|
getLogger().success(`Copied ${source} to ${destination}`);
|
|
3389
3505
|
}
|
|
3390
3506
|
/**
|
|
@@ -3392,30 +3508,15 @@ var EnvironmentManager = class {
|
|
|
3392
3508
|
* Implements:
|
|
3393
3509
|
* - Issue/PR: 3000 + issue/PR number
|
|
3394
3510
|
* - Branch: 3000 + deterministic hash offset (1-999)
|
|
3511
|
+
* Delegates to calculatePortFromIdentifier for the core calculation.
|
|
3395
3512
|
*/
|
|
3396
3513
|
calculatePort(options) {
|
|
3397
3514
|
const basePort = options.basePort ?? 3e3;
|
|
3398
3515
|
if (options.issueNumber !== void 0) {
|
|
3399
|
-
|
|
3400
|
-
if (!isNaN(numericIssue) && String(numericIssue) === String(options.issueNumber)) {
|
|
3401
|
-
const port = basePort + numericIssue;
|
|
3402
|
-
if (port > 65535) {
|
|
3403
|
-
throw new Error(
|
|
3404
|
-
`Calculated port ${port} exceeds maximum (65535). Use a lower base port or issue number.`
|
|
3405
|
-
);
|
|
3406
|
-
}
|
|
3407
|
-
return port;
|
|
3408
|
-
}
|
|
3409
|
-
return calculatePortForBranch(String(options.issueNumber), basePort);
|
|
3516
|
+
return calculatePortFromIdentifier(options.issueNumber, basePort);
|
|
3410
3517
|
}
|
|
3411
3518
|
if (options.prNumber !== void 0) {
|
|
3412
|
-
|
|
3413
|
-
if (port > 65535) {
|
|
3414
|
-
throw new Error(
|
|
3415
|
-
`Calculated port ${port} exceeds maximum (65535). Use a lower base port or PR number.`
|
|
3416
|
-
);
|
|
3417
|
-
}
|
|
3418
|
-
return port;
|
|
3519
|
+
return calculatePortFromIdentifier(options.prNumber, basePort);
|
|
3419
3520
|
}
|
|
3420
3521
|
if (options.branchName !== void 0) {
|
|
3421
3522
|
return calculatePortForBranch(options.branchName, basePort);
|
|
@@ -3445,7 +3546,7 @@ var EnvironmentManager = class {
|
|
|
3445
3546
|
*/
|
|
3446
3547
|
async validateEnvFile(filePath) {
|
|
3447
3548
|
try {
|
|
3448
|
-
const content = await
|
|
3549
|
+
const content = await fs4.readFile(filePath, "utf8");
|
|
3449
3550
|
const envMap = parseEnvFile(content);
|
|
3450
3551
|
const errors = [];
|
|
3451
3552
|
for (const [key, value] of envMap.entries()) {
|
|
@@ -3473,7 +3574,7 @@ var EnvironmentManager = class {
|
|
|
3473
3574
|
async createBackup(filePath) {
|
|
3474
3575
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
3475
3576
|
const backupPath = `${filePath}${this.backupSuffix}-${timestamp}`;
|
|
3476
|
-
await
|
|
3577
|
+
await fs4.copy(filePath, backupPath);
|
|
3477
3578
|
getLogger().debug(`Created backup at ${backupPath}`);
|
|
3478
3579
|
return backupPath;
|
|
3479
3580
|
}
|
|
@@ -3481,7 +3582,7 @@ var EnvironmentManager = class {
|
|
|
3481
3582
|
|
|
3482
3583
|
// src/lib/DatabaseManager.ts
|
|
3483
3584
|
init_env();
|
|
3484
|
-
import
|
|
3585
|
+
import fs5 from "fs-extra";
|
|
3485
3586
|
var DatabaseManager = class {
|
|
3486
3587
|
constructor(provider, environment, databaseUrlEnvVarName = "DATABASE_URL") {
|
|
3487
3588
|
this.provider = provider;
|
|
@@ -3670,7 +3771,7 @@ var DatabaseManager = class {
|
|
|
3670
3771
|
const hasConfiguredVar = await hasVariableInAnyEnvFile(
|
|
3671
3772
|
workspacePath,
|
|
3672
3773
|
this.databaseUrlEnvVarName,
|
|
3673
|
-
async (p) =>
|
|
3774
|
+
async (p) => fs5.pathExists(p),
|
|
3674
3775
|
async (p, v) => this.environment.getEnvVariable(p, v)
|
|
3675
3776
|
);
|
|
3676
3777
|
if (hasConfiguredVar) {
|
|
@@ -3690,7 +3791,7 @@ var DatabaseManager = class {
|
|
|
3690
3791
|
const hasDefaultVar = await hasVariableInAnyEnvFile(
|
|
3691
3792
|
workspacePath,
|
|
3692
3793
|
"DATABASE_URL",
|
|
3693
|
-
async (p) =>
|
|
3794
|
+
async (p) => fs5.pathExists(p),
|
|
3694
3795
|
async (p, v) => this.environment.getEnvVariable(p, v)
|
|
3695
3796
|
);
|
|
3696
3797
|
if (hasDefaultVar) {
|
|
@@ -3713,7 +3814,7 @@ init_logger();
|
|
|
3713
3814
|
import { execa as execa4 } from "execa";
|
|
3714
3815
|
import { existsSync as existsSync2 } from "fs";
|
|
3715
3816
|
import { join } from "path";
|
|
3716
|
-
import { createHash as createHash3 } from "crypto";
|
|
3817
|
+
import { createHash as createHash3, randomUUID } from "crypto";
|
|
3717
3818
|
init_terminal();
|
|
3718
3819
|
async function detectClaudeCli() {
|
|
3719
3820
|
try {
|
|
@@ -4002,6 +4103,10 @@ import { readFile as readFile2 } from "fs/promises";
|
|
|
4002
4103
|
import { accessSync } from "fs";
|
|
4003
4104
|
import path6 from "path";
|
|
4004
4105
|
import { fileURLToPath } from "url";
|
|
4106
|
+
import Handlebars from "handlebars";
|
|
4107
|
+
Handlebars.registerHelper("raw", function(options) {
|
|
4108
|
+
return options.fn(this);
|
|
4109
|
+
});
|
|
4005
4110
|
var PromptTemplateManager = class {
|
|
4006
4111
|
constructor(templateDir) {
|
|
4007
4112
|
if (templateDir) {
|
|
@@ -4048,187 +4153,11 @@ var PromptTemplateManager = class {
|
|
|
4048
4153
|
}
|
|
4049
4154
|
}
|
|
4050
4155
|
/**
|
|
4051
|
-
* Substitute variables in a template string
|
|
4156
|
+
* Substitute variables in a template string using Handlebars
|
|
4052
4157
|
*/
|
|
4053
4158
|
substituteVariables(template, variables) {
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
if (variables.ISSUE_NUMBER !== void 0) {
|
|
4057
|
-
result = result.replace(/ISSUE_NUMBER/g, String(variables.ISSUE_NUMBER));
|
|
4058
|
-
}
|
|
4059
|
-
if (variables.PR_NUMBER !== void 0) {
|
|
4060
|
-
result = result.replace(/PR_NUMBER/g, String(variables.PR_NUMBER));
|
|
4061
|
-
}
|
|
4062
|
-
if (variables.ISSUE_TITLE !== void 0) {
|
|
4063
|
-
result = result.replace(/ISSUE_TITLE/g, variables.ISSUE_TITLE);
|
|
4064
|
-
}
|
|
4065
|
-
if (variables.PR_TITLE !== void 0) {
|
|
4066
|
-
result = result.replace(/PR_TITLE/g, variables.PR_TITLE);
|
|
4067
|
-
}
|
|
4068
|
-
if (variables.WORKSPACE_PATH !== void 0) {
|
|
4069
|
-
result = result.replace(/WORKSPACE_PATH/g, variables.WORKSPACE_PATH);
|
|
4070
|
-
}
|
|
4071
|
-
if (variables.PORT !== void 0) {
|
|
4072
|
-
result = result.replace(/PORT/g, String(variables.PORT));
|
|
4073
|
-
}
|
|
4074
|
-
if (variables.SETTINGS_SCHEMA !== void 0) {
|
|
4075
|
-
result = result.replace(/SETTINGS_SCHEMA/g, variables.SETTINGS_SCHEMA);
|
|
4076
|
-
}
|
|
4077
|
-
if (variables.SETTINGS_GLOBAL_JSON !== void 0) {
|
|
4078
|
-
result = result.replace(/SETTINGS_GLOBAL_JSON/g, variables.SETTINGS_GLOBAL_JSON);
|
|
4079
|
-
}
|
|
4080
|
-
if (variables.SETTINGS_JSON !== void 0) {
|
|
4081
|
-
result = result.replace(/SETTINGS_JSON/g, variables.SETTINGS_JSON);
|
|
4082
|
-
}
|
|
4083
|
-
if (variables.SETTINGS_LOCAL_JSON !== void 0) {
|
|
4084
|
-
result = result.replace(/SETTINGS_LOCAL_JSON/g, variables.SETTINGS_LOCAL_JSON);
|
|
4085
|
-
}
|
|
4086
|
-
if (variables.SHELL_TYPE !== void 0) {
|
|
4087
|
-
result = result.replace(/SHELL_TYPE/g, variables.SHELL_TYPE);
|
|
4088
|
-
}
|
|
4089
|
-
if (variables.SHELL_CONFIG_PATH !== void 0) {
|
|
4090
|
-
result = result.replace(/SHELL_CONFIG_PATH/g, variables.SHELL_CONFIG_PATH);
|
|
4091
|
-
}
|
|
4092
|
-
if (variables.SHELL_CONFIG_CONTENT !== void 0) {
|
|
4093
|
-
result = result.replace(/SHELL_CONFIG_CONTENT/g, variables.SHELL_CONFIG_CONTENT);
|
|
4094
|
-
}
|
|
4095
|
-
if (variables.REMOTES_INFO !== void 0) {
|
|
4096
|
-
result = result.replace(/REMOTES_INFO/g, variables.REMOTES_INFO);
|
|
4097
|
-
}
|
|
4098
|
-
if (variables.MULTIPLE_REMOTES !== void 0) {
|
|
4099
|
-
result = result.replace(/MULTIPLE_REMOTES/g, variables.MULTIPLE_REMOTES);
|
|
4100
|
-
}
|
|
4101
|
-
if (variables.SINGLE_REMOTE !== void 0) {
|
|
4102
|
-
result = result.replace(/SINGLE_REMOTE/g, variables.SINGLE_REMOTE);
|
|
4103
|
-
}
|
|
4104
|
-
if (variables.SINGLE_REMOTE_NAME !== void 0) {
|
|
4105
|
-
result = result.replace(/SINGLE_REMOTE_NAME/g, variables.SINGLE_REMOTE_NAME);
|
|
4106
|
-
}
|
|
4107
|
-
if (variables.SINGLE_REMOTE_URL !== void 0) {
|
|
4108
|
-
result = result.replace(/SINGLE_REMOTE_URL/g, variables.SINGLE_REMOTE_URL);
|
|
4109
|
-
}
|
|
4110
|
-
if (variables.NO_REMOTES !== void 0) {
|
|
4111
|
-
result = result.replace(/NO_REMOTES/g, variables.NO_REMOTES);
|
|
4112
|
-
}
|
|
4113
|
-
if (variables.README_CONTENT !== void 0) {
|
|
4114
|
-
result = result.replace(/README_CONTENT/g, variables.README_CONTENT);
|
|
4115
|
-
}
|
|
4116
|
-
if (variables.SETTINGS_SCHEMA_CONTENT !== void 0) {
|
|
4117
|
-
result = result.replace(/SETTINGS_SCHEMA_CONTENT/g, variables.SETTINGS_SCHEMA_CONTENT);
|
|
4118
|
-
}
|
|
4119
|
-
if (variables.VSCODE_SETTINGS_GITIGNORED !== void 0) {
|
|
4120
|
-
result = result.replace(/VSCODE_SETTINGS_GITIGNORED/g, variables.VSCODE_SETTINGS_GITIGNORED);
|
|
4121
|
-
}
|
|
4122
|
-
if (variables.SESSION_CONTEXT !== void 0) {
|
|
4123
|
-
result = result.replace(/SESSION_CONTEXT/g, variables.SESSION_CONTEXT);
|
|
4124
|
-
}
|
|
4125
|
-
if (variables.BRANCH_NAME !== void 0) {
|
|
4126
|
-
result = result.replace(/BRANCH_NAME/g, variables.BRANCH_NAME);
|
|
4127
|
-
}
|
|
4128
|
-
if (variables.LOOM_TYPE !== void 0) {
|
|
4129
|
-
result = result.replace(/LOOM_TYPE/g, variables.LOOM_TYPE);
|
|
4130
|
-
}
|
|
4131
|
-
if (variables.COMPACT_SUMMARIES !== void 0) {
|
|
4132
|
-
result = result.replace(/COMPACT_SUMMARIES/g, variables.COMPACT_SUMMARIES);
|
|
4133
|
-
}
|
|
4134
|
-
if (variables.DRAFT_PR_NUMBER !== void 0) {
|
|
4135
|
-
result = result.replace(/DRAFT_PR_NUMBER/g, String(variables.DRAFT_PR_NUMBER));
|
|
4136
|
-
}
|
|
4137
|
-
return result;
|
|
4138
|
-
}
|
|
4139
|
-
/**
|
|
4140
|
-
* Process conditional sections in template
|
|
4141
|
-
* Format: {{#IF ONE_SHOT_MODE}}content{{/IF ONE_SHOT_MODE}}
|
|
4142
|
-
*
|
|
4143
|
-
* Note: /s flag allows . to match newlines
|
|
4144
|
-
*/
|
|
4145
|
-
processConditionalSections(template, variables) {
|
|
4146
|
-
let result = template;
|
|
4147
|
-
const oneShotRegex = /\{\{#IF ONE_SHOT_MODE\}\}(.*?)\{\{\/IF ONE_SHOT_MODE\}\}/gs;
|
|
4148
|
-
if (variables.ONE_SHOT_MODE === true) {
|
|
4149
|
-
result = result.replace(oneShotRegex, "$1");
|
|
4150
|
-
} else {
|
|
4151
|
-
result = result.replace(oneShotRegex, "");
|
|
4152
|
-
}
|
|
4153
|
-
const settingsJsonRegex = /\{\{#IF SETTINGS_JSON\}\}(.*?)\{\{\/IF SETTINGS_JSON\}\}/gs;
|
|
4154
|
-
if (variables.SETTINGS_JSON !== void 0 && variables.SETTINGS_JSON !== "") {
|
|
4155
|
-
result = result.replace(settingsJsonRegex, "$1");
|
|
4156
|
-
} else {
|
|
4157
|
-
result = result.replace(settingsJsonRegex, "");
|
|
4158
|
-
}
|
|
4159
|
-
const settingsGlobalJsonRegex = /\{\{#IF SETTINGS_GLOBAL_JSON\}\}(.*?)\{\{\/IF SETTINGS_GLOBAL_JSON\}\}/gs;
|
|
4160
|
-
if (variables.SETTINGS_GLOBAL_JSON !== void 0 && variables.SETTINGS_GLOBAL_JSON !== "") {
|
|
4161
|
-
result = result.replace(settingsGlobalJsonRegex, "$1");
|
|
4162
|
-
} else {
|
|
4163
|
-
result = result.replace(settingsGlobalJsonRegex, "");
|
|
4164
|
-
}
|
|
4165
|
-
const settingsLocalJsonRegex = /\{\{#IF SETTINGS_LOCAL_JSON\}\}(.*?)\{\{\/IF SETTINGS_LOCAL_JSON\}\}/gs;
|
|
4166
|
-
if (variables.SETTINGS_LOCAL_JSON !== void 0 && variables.SETTINGS_LOCAL_JSON !== "") {
|
|
4167
|
-
result = result.replace(settingsLocalJsonRegex, "$1");
|
|
4168
|
-
} else {
|
|
4169
|
-
result = result.replace(settingsLocalJsonRegex, "");
|
|
4170
|
-
}
|
|
4171
|
-
const multipleRemotesRegex = /\{\{#IF MULTIPLE_REMOTES\}\}(.*?)\{\{\/IF MULTIPLE_REMOTES\}\}/gs;
|
|
4172
|
-
if (variables.MULTIPLE_REMOTES !== void 0 && variables.MULTIPLE_REMOTES !== "") {
|
|
4173
|
-
result = result.replace(multipleRemotesRegex, "$1");
|
|
4174
|
-
} else {
|
|
4175
|
-
result = result.replace(multipleRemotesRegex, "");
|
|
4176
|
-
}
|
|
4177
|
-
const singleRemoteRegex = /\{\{#IF SINGLE_REMOTE\}\}(.*?)\{\{\/IF SINGLE_REMOTE\}\}/gs;
|
|
4178
|
-
if (variables.SINGLE_REMOTE !== void 0 && variables.SINGLE_REMOTE !== "") {
|
|
4179
|
-
result = result.replace(singleRemoteRegex, "$1");
|
|
4180
|
-
} else {
|
|
4181
|
-
result = result.replace(singleRemoteRegex, "");
|
|
4182
|
-
}
|
|
4183
|
-
const noRemotesRegex = /\{\{#IF NO_REMOTES\}\}(.*?)\{\{\/IF NO_REMOTES\}\}/gs;
|
|
4184
|
-
if (variables.NO_REMOTES !== void 0 && variables.NO_REMOTES !== "") {
|
|
4185
|
-
result = result.replace(noRemotesRegex, "$1");
|
|
4186
|
-
} else {
|
|
4187
|
-
result = result.replace(noRemotesRegex, "");
|
|
4188
|
-
}
|
|
4189
|
-
const firstTimeUserRegex = /\{\{#IF FIRST_TIME_USER\}\}(.*?)\{\{\/IF FIRST_TIME_USER\}\}/gs;
|
|
4190
|
-
if (variables.FIRST_TIME_USER === true) {
|
|
4191
|
-
result = result.replace(firstTimeUserRegex, "$1");
|
|
4192
|
-
} else {
|
|
4193
|
-
result = result.replace(firstTimeUserRegex, "");
|
|
4194
|
-
}
|
|
4195
|
-
const interactiveModeRegex = /\{\{#IF INTERACTIVE_MODE\}\}(.*?)\{\{\/IF INTERACTIVE_MODE\}\}/gs;
|
|
4196
|
-
if (variables.INTERACTIVE_MODE === true) {
|
|
4197
|
-
result = result.replace(interactiveModeRegex, "$1");
|
|
4198
|
-
} else {
|
|
4199
|
-
result = result.replace(interactiveModeRegex, "");
|
|
4200
|
-
}
|
|
4201
|
-
const compactSummariesRegex = /\{\{#IF COMPACT_SUMMARIES\}\}(.*?)\{\{\/IF COMPACT_SUMMARIES\}\}/gs;
|
|
4202
|
-
if (variables.COMPACT_SUMMARIES !== void 0 && variables.COMPACT_SUMMARIES !== "") {
|
|
4203
|
-
result = result.replace(compactSummariesRegex, "$1");
|
|
4204
|
-
} else {
|
|
4205
|
-
result = result.replace(compactSummariesRegex, "");
|
|
4206
|
-
}
|
|
4207
|
-
const draftPrModeRegex = /\{\{#IF DRAFT_PR_MODE\}\}(.*?)\{\{\/IF DRAFT_PR_MODE\}\}/gs;
|
|
4208
|
-
if (variables.DRAFT_PR_MODE === true) {
|
|
4209
|
-
result = result.replace(draftPrModeRegex, "$1");
|
|
4210
|
-
} else {
|
|
4211
|
-
result = result.replace(draftPrModeRegex, "");
|
|
4212
|
-
}
|
|
4213
|
-
const standardIssueModeRegex = /\{\{#IF STANDARD_ISSUE_MODE\}\}(.*?)\{\{\/IF STANDARD_ISSUE_MODE\}\}/gs;
|
|
4214
|
-
if (variables.STANDARD_ISSUE_MODE === true) {
|
|
4215
|
-
result = result.replace(standardIssueModeRegex, "$1");
|
|
4216
|
-
} else {
|
|
4217
|
-
result = result.replace(standardIssueModeRegex, "");
|
|
4218
|
-
}
|
|
4219
|
-
const hasPackageJsonRegex = /\{\{#IF HAS_PACKAGE_JSON\}\}(.*?)\{\{\/IF HAS_PACKAGE_JSON\}\}/gs;
|
|
4220
|
-
if (variables.HAS_PACKAGE_JSON === true) {
|
|
4221
|
-
result = result.replace(hasPackageJsonRegex, "$1");
|
|
4222
|
-
} else {
|
|
4223
|
-
result = result.replace(hasPackageJsonRegex, "");
|
|
4224
|
-
}
|
|
4225
|
-
const noPackageJsonRegex = /\{\{#IF NO_PACKAGE_JSON\}\}(.*?)\{\{\/IF NO_PACKAGE_JSON\}\}/gs;
|
|
4226
|
-
if (variables.NO_PACKAGE_JSON === true) {
|
|
4227
|
-
result = result.replace(noPackageJsonRegex, "$1");
|
|
4228
|
-
} else {
|
|
4229
|
-
result = result.replace(noPackageJsonRegex, "");
|
|
4230
|
-
}
|
|
4231
|
-
return result;
|
|
4159
|
+
const compiled = Handlebars.compile(template, { noEscape: true });
|
|
4160
|
+
return compiled(variables);
|
|
4232
4161
|
}
|
|
4233
4162
|
/**
|
|
4234
4163
|
* Get a fully processed prompt for a workflow type
|
|
@@ -4716,6 +4645,7 @@ export {
|
|
|
4716
4645
|
ClaudeContextManager,
|
|
4717
4646
|
DatabaseManager,
|
|
4718
4647
|
EnvironmentManager,
|
|
4648
|
+
GitCommandError,
|
|
4719
4649
|
GitHubService,
|
|
4720
4650
|
GitWorktreeManager,
|
|
4721
4651
|
IssueTrackerFactory,
|