@iloom/cli 0.9.1 → 0.10.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 +179 -41
- package/dist/{BranchNamingService-K6XNWQ6C.js → BranchNamingService-ECJHBB67.js} +2 -2
- package/dist/ClaudeContextManager-QXX6ZFST.js +14 -0
- package/dist/ClaudeService-NJNK2SUH.js +13 -0
- package/dist/{GitHubService-O7T6CFAJ.js → GitHubService-MEHKHUQP.js} +4 -4
- package/dist/IssueTrackerFactory-NG53YX5S.js +14 -0
- package/dist/{LoomLauncher-3I47SUPV.js → LoomLauncher-L64HHS3T.js} +9 -9
- package/dist/{MetadataManager-W3C54UYT.js → MetadataManager-5QZSTKNN.js} +2 -2
- package/dist/{ProjectCapabilityDetector-N5L7T4IY.js → ProjectCapabilityDetector-5KSYUTBJ.js} +3 -3
- package/dist/{PromptTemplateManager-36YLQRHP.js → PromptTemplateManager-DULSVRRE.js} +2 -2
- package/dist/README.md +179 -41
- package/dist/{SettingsManager-QR7V2IW2.js → SettingsManager-BQDQA3FK.js} +4 -2
- package/dist/agents/iloom-artifact-reviewer.md +11 -0
- package/dist/agents/iloom-code-reviewer.md +14 -0
- package/dist/agents/iloom-issue-analyze-and-plan.md +55 -12
- package/dist/agents/iloom-issue-analyzer.md +49 -6
- package/dist/agents/iloom-issue-complexity-evaluator.md +47 -6
- package/dist/agents/iloom-issue-enhancer.md +86 -7
- package/dist/agents/iloom-issue-implementer.md +48 -7
- package/dist/agents/iloom-issue-planner.md +115 -62
- package/dist/{build-IC4CJRMP.js → build-5GO3XW26.js} +9 -9
- package/dist/{chunk-USSL2X4A.js → chunk-3D7WQM7I.js} +2 -2
- package/dist/chunk-4232AHNQ.js +35 -0
- package/dist/chunk-4232AHNQ.js.map +1 -0
- package/dist/{chunk-QN47QVBX.js → chunk-4WJNIR5O.js} +1 -1
- package/dist/chunk-4WJNIR5O.js.map +1 -0
- package/dist/{chunk-2JPXGGP4.js → chunk-5MWV33NN.js} +4 -4
- package/dist/{chunk-POU2UMWN.js → chunk-6EU6TCF6.js} +10 -10
- package/dist/chunk-6EU6TCF6.js.map +1 -0
- package/dist/{chunk-Y5O2ALDZ.js → chunk-FB47TIJG.js} +29 -11
- package/dist/chunk-FB47TIJG.js.map +1 -0
- package/dist/chunk-HEXKPKCK.js +1396 -0
- package/dist/chunk-HEXKPKCK.js.map +1 -0
- package/dist/{chunk-KAYXR544.js → chunk-J5S7DFYC.js} +2 -2
- package/dist/{chunk-OK7LUTRW.js → chunk-JO2LZ6EQ.js} +476 -5
- package/dist/chunk-JO2LZ6EQ.js.map +1 -0
- package/dist/{chunk-KBEIQP4G.js → chunk-KB64WNBZ.js} +43 -3
- package/dist/chunk-KB64WNBZ.js.map +1 -0
- package/dist/{chunk-Y5HSSIK2.js → chunk-KXDRI47U.js} +71 -13
- package/dist/chunk-KXDRI47U.js.map +1 -0
- package/dist/{chunk-HZXBHMVM.js → chunk-LXLMMXXY.js} +54 -14
- package/dist/chunk-LXLMMXXY.js.map +1 -0
- package/dist/{chunk-H6ST2TGP.js → chunk-MNHZB4Z2.js} +4 -4
- package/dist/{chunk-TL72BGP6.js → chunk-MORRVYPT.js} +2 -2
- package/dist/{chunk-TGRK3CHF.js → chunk-NRSWLOAZ.js} +8 -8
- package/dist/chunk-NRSWLOAZ.js.map +1 -0
- package/dist/{chunk-FO5GGFOV.js → chunk-ONQYPICO.js} +13 -5
- package/dist/chunk-ONQYPICO.js.map +1 -0
- package/dist/{chunk-7ZEHSSUP.js → chunk-P4O6EH46.js} +4 -4
- package/dist/chunk-QZWEJVWV.js +207 -0
- package/dist/chunk-QZWEJVWV.js.map +1 -0
- package/dist/chunk-RSYT7MVI.js +202 -0
- package/dist/chunk-RSYT7MVI.js.map +1 -0
- package/dist/{chunk-OAVJR4PM.js → chunk-RYWFS37M.js} +6 -6
- package/dist/chunk-RYWFS37M.js.map +1 -0
- package/dist/{chunk-B7U6OKUR.js → chunk-SF2P22EE.js} +11 -3
- package/dist/chunk-SF2P22EE.js.map +1 -0
- package/dist/{chunk-MZPRBNYC.js → chunk-SN3SQCFK.js} +10 -8
- package/dist/{chunk-MZPRBNYC.js.map → chunk-SN3SQCFK.js.map} +1 -1
- package/dist/{chunk-4ZIHFUPN.js → chunk-UD3WJDIV.js} +145 -107
- package/dist/chunk-UD3WJDIV.js.map +1 -0
- package/dist/{chunk-3P6J4IZZ.js → chunk-UKBAJ2QQ.js} +61 -7
- package/dist/chunk-UKBAJ2QQ.js.map +1 -0
- package/dist/{chunk-RD7OPXZK.js → chunk-UVD4CZKS.js} +3 -3
- package/dist/chunk-UWGVCXRF.js +207 -0
- package/dist/chunk-UWGVCXRF.js.map +1 -0
- package/dist/{chunk-JT5LZRMI.js → chunk-VECNX6VX.js} +2 -2
- package/dist/{chunk-TRUMP4DA.js → chunk-VG45TUYK.js} +75 -6
- package/dist/chunk-VG45TUYK.js.map +1 -0
- package/dist/{chunk-4GAJJUYS.js → chunk-VGGST52X.js} +2 -2
- package/dist/{chunk-4LKGCFGG.js → chunk-WWKOVDWC.js} +2 -2
- package/dist/{chunk-2HZX6AMR.js → chunk-WY4QBK43.js} +7 -7
- package/dist/chunk-WY4QBK43.js.map +1 -0
- package/dist/chunk-Y4YZTHZE.js +73 -0
- package/dist/chunk-Y4YZTHZE.js.map +1 -0
- package/dist/{chunk-VOGGLPG5.js → chunk-YQ57ORTV.js} +14 -1
- package/dist/chunk-YQ57ORTV.js.map +1 -0
- package/dist/{chunk-XFEK2X2D.js → chunk-YYAKPQBT.js} +73 -20
- package/dist/chunk-YYAKPQBT.js.map +1 -0
- package/dist/{chunk-NTTSUAVM.js → chunk-ZEWU5PZK.js} +2 -2
- package/dist/{chunk-5LVVQGB3.js → chunk-ZHPNZC75.js} +17 -17
- package/dist/chunk-ZHPNZC75.js.map +1 -0
- package/dist/{chunk-I3HMNWQQ.js → chunk-ZW2LKWWE.js} +9 -9
- package/dist/chunk-ZW2LKWWE.js.map +1 -0
- package/dist/{claude-TP2QO3BU.js → claude-P3NQR6IJ.js} +2 -2
- package/dist/{cleanup-D3CSRBBZ.js → cleanup-6UCPVMFG.js} +81 -32
- package/dist/cleanup-6UCPVMFG.js.map +1 -0
- package/dist/cli.js +640 -350
- package/dist/cli.js.map +1 -1
- package/dist/{commit-IWGT42XN.js → commit-L3EPY5QG.js} +23 -21
- package/dist/commit-L3EPY5QG.js.map +1 -0
- package/dist/{compile-EOWJORKO.js → compile-ZS4HYRX5.js} +9 -9
- package/dist/{contribute-WSJTV2RX.js → contribute-ORDDQGSL.js} +14 -6
- package/dist/contribute-ORDDQGSL.js.map +1 -0
- package/dist/{dev-server-Q6M62ATG.js → dev-server-FYZ2AQIH.js} +29 -15
- package/dist/dev-server-FYZ2AQIH.js.map +1 -0
- package/dist/{feedback-QPNDZQRV.js → feedback-TMBXSCM5.js} +15 -15
- package/dist/{git-W3XUIFTR.js → git-ET64COO3.js} +4 -4
- package/dist/hooks/iloom-hook.js +15 -0
- package/dist/ignite-CGOV3TD4.js +1393 -0
- package/dist/ignite-CGOV3TD4.js.map +1 -0
- package/dist/index.d.ts +397 -53
- package/dist/index.js +1178 -40
- package/dist/index.js.map +1 -1
- package/dist/{init-ALYWKNWG.js → init-GFQ5W7GK.js} +57 -21
- package/dist/init-GFQ5W7GK.js.map +1 -0
- package/dist/issues-T4ZZSPEG.js +179 -0
- package/dist/issues-T4ZZSPEG.js.map +1 -0
- package/dist/{lint-IHUH45OC.js → lint-6TQXDZ3T.js} +9 -9
- package/dist/mcp/issue-management-server.js +2472 -257
- package/dist/mcp/issue-management-server.js.map +1 -1
- package/dist/mcp/recap-server.js +144 -21
- package/dist/mcp/recap-server.js.map +1 -1
- package/dist/{neon-helpers-VVFFTLXE.js → neon-helpers-CQN2PB4S.js} +3 -3
- package/dist/neon-helpers-CQN2PB4S.js.map +1 -0
- package/dist/{open-KWOV2OFO.js → open-5QZGXQRF.js} +15 -15
- package/dist/open-5QZGXQRF.js.map +1 -0
- package/dist/{plan-BRJBFJHF.js → plan-U7ZQWLFY.js} +41 -25
- package/dist/plan-U7ZQWLFY.js.map +1 -0
- package/dist/{projects-LH362JZQ.js → projects-2UOXFLNZ.js} +4 -4
- package/dist/prompts/CLAUDE.md +62 -0
- package/dist/prompts/init-prompt.txt +386 -47
- package/dist/prompts/issue-prompt.txt +427 -54
- package/dist/prompts/plan-prompt.txt +97 -16
- package/dist/prompts/pr-prompt.txt +44 -1
- package/dist/prompts/regular-prompt.txt +42 -1
- package/dist/prompts/session-summary-prompt.txt +14 -0
- package/dist/prompts/swarm-orchestrator-prompt.txt +437 -0
- package/dist/{rebase-AJOJOZUG.js → rebase-DWIB77KV.js} +10 -10
- package/dist/{recap-GKJXMDXW.js → recap-MX63HAKV.js} +47 -19
- package/dist/recap-MX63HAKV.js.map +1 -0
- package/dist/{run-QEUVZF7J.js → run-O3TFNQFC.js} +15 -15
- package/dist/run-O3TFNQFC.js.map +1 -0
- package/dist/schema/package-iloom.schema.json +58 -0
- package/dist/schema/settings.schema.json +130 -15
- package/dist/{shell-DAAVG4YN.js → shell-G6VC2CYR.js} +14 -7
- package/dist/shell-G6VC2CYR.js.map +1 -0
- package/dist/{summary-ZKOA35PT.js → summary-FWHAX55O.js} +27 -25
- package/dist/summary-FWHAX55O.js.map +1 -0
- package/dist/{test-5GPWWO3P.js → test-F7JNJZYP.js} +9 -9
- package/dist/{test-git-EJUKDB7F.js → test-git-BTAOIUE2.js} +4 -4
- package/dist/test-jira-CHYNV33F.js +96 -0
- package/dist/test-jira-CHYNV33F.js.map +1 -0
- package/dist/{test-prefix-23TOBUXY.js → test-prefix-Q6TFSU6F.js} +4 -4
- package/dist/{test-webserver-CKROHFBQ.js → test-webserver-EONCG7E7.js} +6 -6
- package/dist/{vscode-6TOLFCI2.js → vscode-VA5X4P25.js} +7 -7
- package/package.json +5 -1
- package/dist/ClaudeContextManager-X2Y72GRL.js +0 -14
- package/dist/ClaudeService-7P32TTES.js +0 -13
- package/dist/chunk-2HZX6AMR.js.map +0 -1
- package/dist/chunk-3P6J4IZZ.js.map +0 -1
- package/dist/chunk-4ZIHFUPN.js.map +0 -1
- package/dist/chunk-5LVVQGB3.js.map +0 -1
- package/dist/chunk-B7U6OKUR.js.map +0 -1
- package/dist/chunk-ENGCJIYQ.js +0 -520
- package/dist/chunk-ENGCJIYQ.js.map +0 -1
- package/dist/chunk-FO5GGFOV.js.map +0 -1
- package/dist/chunk-HZXBHMVM.js.map +0 -1
- package/dist/chunk-I3HMNWQQ.js.map +0 -1
- package/dist/chunk-J7FJ6PUT.js +0 -121
- package/dist/chunk-J7FJ6PUT.js.map +0 -1
- package/dist/chunk-KBEIQP4G.js.map +0 -1
- package/dist/chunk-OAVJR4PM.js.map +0 -1
- package/dist/chunk-OK7LUTRW.js.map +0 -1
- package/dist/chunk-POU2UMWN.js.map +0 -1
- package/dist/chunk-QN47QVBX.js.map +0 -1
- package/dist/chunk-TGRK3CHF.js.map +0 -1
- package/dist/chunk-TRUMP4DA.js.map +0 -1
- package/dist/chunk-VOGGLPG5.js.map +0 -1
- package/dist/chunk-XFEK2X2D.js.map +0 -1
- package/dist/chunk-Y5HSSIK2.js.map +0 -1
- package/dist/chunk-Y5O2ALDZ.js.map +0 -1
- package/dist/cleanup-D3CSRBBZ.js.map +0 -1
- package/dist/commit-IWGT42XN.js.map +0 -1
- package/dist/contribute-WSJTV2RX.js.map +0 -1
- package/dist/dev-server-Q6M62ATG.js.map +0 -1
- package/dist/ignite-OPO6EDYT.js +0 -784
- package/dist/ignite-OPO6EDYT.js.map +0 -1
- package/dist/init-ALYWKNWG.js.map +0 -1
- package/dist/issues-L7TBUPXT.js +0 -116
- package/dist/issues-L7TBUPXT.js.map +0 -1
- package/dist/open-KWOV2OFO.js.map +0 -1
- package/dist/plan-BRJBFJHF.js.map +0 -1
- package/dist/recap-GKJXMDXW.js.map +0 -1
- package/dist/run-QEUVZF7J.js.map +0 -1
- package/dist/shell-DAAVG4YN.js.map +0 -1
- package/dist/summary-ZKOA35PT.js.map +0 -1
- /package/dist/{BranchNamingService-K6XNWQ6C.js.map → BranchNamingService-ECJHBB67.js.map} +0 -0
- /package/dist/{ClaudeContextManager-X2Y72GRL.js.map → ClaudeContextManager-QXX6ZFST.js.map} +0 -0
- /package/dist/{ClaudeService-7P32TTES.js.map → ClaudeService-NJNK2SUH.js.map} +0 -0
- /package/dist/{GitHubService-O7T6CFAJ.js.map → GitHubService-MEHKHUQP.js.map} +0 -0
- /package/dist/{MetadataManager-W3C54UYT.js.map → IssueTrackerFactory-NG53YX5S.js.map} +0 -0
- /package/dist/{LoomLauncher-3I47SUPV.js.map → LoomLauncher-L64HHS3T.js.map} +0 -0
- /package/dist/{ProjectCapabilityDetector-N5L7T4IY.js.map → MetadataManager-5QZSTKNN.js.map} +0 -0
- /package/dist/{PromptTemplateManager-36YLQRHP.js.map → ProjectCapabilityDetector-5KSYUTBJ.js.map} +0 -0
- /package/dist/{SettingsManager-QR7V2IW2.js.map → PromptTemplateManager-DULSVRRE.js.map} +0 -0
- /package/dist/{claude-TP2QO3BU.js.map → SettingsManager-BQDQA3FK.js.map} +0 -0
- /package/dist/{build-IC4CJRMP.js.map → build-5GO3XW26.js.map} +0 -0
- /package/dist/{chunk-USSL2X4A.js.map → chunk-3D7WQM7I.js.map} +0 -0
- /package/dist/{chunk-2JPXGGP4.js.map → chunk-5MWV33NN.js.map} +0 -0
- /package/dist/{chunk-KAYXR544.js.map → chunk-J5S7DFYC.js.map} +0 -0
- /package/dist/{chunk-H6ST2TGP.js.map → chunk-MNHZB4Z2.js.map} +0 -0
- /package/dist/{chunk-TL72BGP6.js.map → chunk-MORRVYPT.js.map} +0 -0
- /package/dist/{chunk-7ZEHSSUP.js.map → chunk-P4O6EH46.js.map} +0 -0
- /package/dist/{chunk-RD7OPXZK.js.map → chunk-UVD4CZKS.js.map} +0 -0
- /package/dist/{chunk-JT5LZRMI.js.map → chunk-VECNX6VX.js.map} +0 -0
- /package/dist/{chunk-4GAJJUYS.js.map → chunk-VGGST52X.js.map} +0 -0
- /package/dist/{chunk-4LKGCFGG.js.map → chunk-WWKOVDWC.js.map} +0 -0
- /package/dist/{chunk-NTTSUAVM.js.map → chunk-ZEWU5PZK.js.map} +0 -0
- /package/dist/{git-W3XUIFTR.js.map → claude-P3NQR6IJ.js.map} +0 -0
- /package/dist/{compile-EOWJORKO.js.map → compile-ZS4HYRX5.js.map} +0 -0
- /package/dist/{feedback-QPNDZQRV.js.map → feedback-TMBXSCM5.js.map} +0 -0
- /package/dist/{neon-helpers-VVFFTLXE.js.map → git-ET64COO3.js.map} +0 -0
- /package/dist/{lint-IHUH45OC.js.map → lint-6TQXDZ3T.js.map} +0 -0
- /package/dist/{projects-LH362JZQ.js.map → projects-2UOXFLNZ.js.map} +0 -0
- /package/dist/{rebase-AJOJOZUG.js.map → rebase-DWIB77KV.js.map} +0 -0
- /package/dist/{test-5GPWWO3P.js.map → test-F7JNJZYP.js.map} +0 -0
- /package/dist/{test-git-EJUKDB7F.js.map → test-git-BTAOIUE2.js.map} +0 -0
- /package/dist/{test-prefix-23TOBUXY.js.map → test-prefix-Q6TFSU6F.js.map} +0 -0
- /package/dist/{test-webserver-CKROHFBQ.js.map → test-webserver-EONCG7E7.js.map} +0 -0
- /package/dist/{vscode-6TOLFCI2.js.map → vscode-VA5X4P25.js.map} +0 -0
package/dist/ignite-OPO6EDYT.js
DELETED
|
@@ -1,784 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
IssueTrackerFactory
|
|
4
|
-
} from "./chunk-3P6J4IZZ.js";
|
|
5
|
-
import {
|
|
6
|
-
getWorkspacePort
|
|
7
|
-
} from "./chunk-USSL2X4A.js";
|
|
8
|
-
import {
|
|
9
|
-
FirstRunManager
|
|
10
|
-
} from "./chunk-Q7POFB5Q.js";
|
|
11
|
-
import {
|
|
12
|
-
generateIssueManagementMcpConfig,
|
|
13
|
-
generateRecapMcpConfig
|
|
14
|
-
} from "./chunk-J7FJ6PUT.js";
|
|
15
|
-
import {
|
|
16
|
-
AgentManager
|
|
17
|
-
} from "./chunk-B7U6OKUR.js";
|
|
18
|
-
import "./chunk-ENGCJIYQ.js";
|
|
19
|
-
import {
|
|
20
|
-
GitWorktreeManager
|
|
21
|
-
} from "./chunk-4GAJJUYS.js";
|
|
22
|
-
import {
|
|
23
|
-
PromptTemplateManager,
|
|
24
|
-
buildReviewTemplateVariables
|
|
25
|
-
} from "./chunk-QN47QVBX.js";
|
|
26
|
-
import {
|
|
27
|
-
extractSettingsOverrides
|
|
28
|
-
} from "./chunk-GYCR2LOU.js";
|
|
29
|
-
import {
|
|
30
|
-
extractIssueNumber,
|
|
31
|
-
getWorktreeRoot,
|
|
32
|
-
isValidGitRepo
|
|
33
|
-
} from "./chunk-H6ST2TGP.js";
|
|
34
|
-
import {
|
|
35
|
-
SettingsManager
|
|
36
|
-
} from "./chunk-XFEK2X2D.js";
|
|
37
|
-
import {
|
|
38
|
-
MetadataManager
|
|
39
|
-
} from "./chunk-KBEIQP4G.js";
|
|
40
|
-
import "./chunk-Y5HSSIK2.js";
|
|
41
|
-
import "./chunk-TRUMP4DA.js";
|
|
42
|
-
import "./chunk-7JDMYTFZ.js";
|
|
43
|
-
import {
|
|
44
|
-
launchClaude
|
|
45
|
-
} from "./chunk-FO5GGFOV.js";
|
|
46
|
-
import {
|
|
47
|
-
withLogger
|
|
48
|
-
} from "./chunk-6MLEBAYZ.js";
|
|
49
|
-
import {
|
|
50
|
-
createStderrLogger,
|
|
51
|
-
logger
|
|
52
|
-
} from "./chunk-VT4PDUYT.js";
|
|
53
|
-
|
|
54
|
-
// src/commands/ignite.ts
|
|
55
|
-
import path2 from "path";
|
|
56
|
-
import { readFile } from "fs/promises";
|
|
57
|
-
|
|
58
|
-
// src/lib/ClaudeHookManager.ts
|
|
59
|
-
import os from "os";
|
|
60
|
-
import path from "path";
|
|
61
|
-
import fs from "fs-extra";
|
|
62
|
-
import { parse, modify, applyEdits } from "jsonc-parser";
|
|
63
|
-
import { fileURLToPath } from "url";
|
|
64
|
-
import { accessSync } from "fs";
|
|
65
|
-
var ClaudeHookManager = class {
|
|
66
|
-
constructor() {
|
|
67
|
-
this.claudeDir = path.join(os.homedir(), ".claude");
|
|
68
|
-
this.hooksDir = path.join(this.claudeDir, "hooks");
|
|
69
|
-
this.settingsPath = path.join(this.claudeDir, "settings.json");
|
|
70
|
-
const currentFileUrl = import.meta.url;
|
|
71
|
-
const currentFilePath = fileURLToPath(currentFileUrl);
|
|
72
|
-
const distDir = path.dirname(currentFilePath);
|
|
73
|
-
let templateDir = path.join(distDir, "hooks");
|
|
74
|
-
let currentDir = distDir;
|
|
75
|
-
while (currentDir !== path.dirname(currentDir)) {
|
|
76
|
-
const candidatePath = path.join(currentDir, "hooks");
|
|
77
|
-
try {
|
|
78
|
-
accessSync(candidatePath);
|
|
79
|
-
templateDir = candidatePath;
|
|
80
|
-
break;
|
|
81
|
-
} catch {
|
|
82
|
-
currentDir = path.dirname(currentDir);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
this.templateDir = templateDir;
|
|
86
|
-
logger.debug("ClaudeHookManager initialized", {
|
|
87
|
-
claudeDir: this.claudeDir,
|
|
88
|
-
hooksDir: this.hooksDir,
|
|
89
|
-
settingsPath: this.settingsPath,
|
|
90
|
-
templateDir: this.templateDir
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* Install Claude hooks for VSCode integration
|
|
95
|
-
*
|
|
96
|
-
* This is idempotent - safe to call on every spin.
|
|
97
|
-
* Installs hook script to ~/.claude/hooks/ and merges
|
|
98
|
-
* hook configuration into ~/.claude/settings.json
|
|
99
|
-
*/
|
|
100
|
-
async installHooks() {
|
|
101
|
-
try {
|
|
102
|
-
await fs.ensureDir(this.hooksDir);
|
|
103
|
-
await this.installHookScript();
|
|
104
|
-
await this.mergeHookConfig();
|
|
105
|
-
logger.debug("Claude hooks installed successfully");
|
|
106
|
-
} catch (error) {
|
|
107
|
-
logger.warn(
|
|
108
|
-
`Failed to install Claude hooks: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
109
|
-
);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
/**
|
|
113
|
-
* Check if hooks are already installed
|
|
114
|
-
*/
|
|
115
|
-
async isHooksInstalled() {
|
|
116
|
-
try {
|
|
117
|
-
const hookScriptPath = path.join(this.hooksDir, "iloom-hook.js");
|
|
118
|
-
if (!await fs.pathExists(hookScriptPath)) {
|
|
119
|
-
return false;
|
|
120
|
-
}
|
|
121
|
-
if (!await fs.pathExists(this.settingsPath)) {
|
|
122
|
-
return false;
|
|
123
|
-
}
|
|
124
|
-
const content = await fs.readFile(this.settingsPath, "utf8");
|
|
125
|
-
const errors = [];
|
|
126
|
-
const settings = parse(content, errors, { allowTrailingComma: true });
|
|
127
|
-
if (errors.length > 0 || !(settings == null ? void 0 : settings.hooks)) {
|
|
128
|
-
return false;
|
|
129
|
-
}
|
|
130
|
-
return Array.isArray(settings.hooks.SessionStart);
|
|
131
|
-
} catch {
|
|
132
|
-
return false;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
/**
|
|
136
|
-
* Install the hook script from bundled templates
|
|
137
|
-
* Skips write if destination already has identical content
|
|
138
|
-
*/
|
|
139
|
-
async installHookScript() {
|
|
140
|
-
const sourcePath = path.join(this.templateDir, "iloom-hook.js");
|
|
141
|
-
const destPath = path.join(this.hooksDir, "iloom-hook.js");
|
|
142
|
-
if (!await fs.pathExists(sourcePath)) {
|
|
143
|
-
throw new Error(`Hook template not found at ${sourcePath}`);
|
|
144
|
-
}
|
|
145
|
-
if (await fs.pathExists(destPath)) {
|
|
146
|
-
const [sourceContent, destContent] = await Promise.all([
|
|
147
|
-
fs.readFile(sourcePath, "utf8"),
|
|
148
|
-
fs.readFile(destPath, "utf8")
|
|
149
|
-
]);
|
|
150
|
-
if (sourceContent === destContent) {
|
|
151
|
-
logger.debug("Hook script already up to date, skipping");
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
await fs.copyFile(sourcePath, destPath);
|
|
156
|
-
logger.debug("Hook script installed", { sourcePath, destPath });
|
|
157
|
-
}
|
|
158
|
-
/**
|
|
159
|
-
* Merge hook configuration into settings.json
|
|
160
|
-
* Preserves existing user hooks and comments
|
|
161
|
-
*/
|
|
162
|
-
async mergeHookConfig() {
|
|
163
|
-
var _a, _b;
|
|
164
|
-
await fs.ensureDir(this.claudeDir);
|
|
165
|
-
let existingContent = "{}";
|
|
166
|
-
let existingSettings = {};
|
|
167
|
-
if (await fs.pathExists(this.settingsPath)) {
|
|
168
|
-
existingContent = await fs.readFile(this.settingsPath, "utf8");
|
|
169
|
-
const errors = [];
|
|
170
|
-
existingSettings = parse(existingContent, errors, { allowTrailingComma: true });
|
|
171
|
-
if (errors.length > 0) {
|
|
172
|
-
logger.warn("Existing settings.json has parse errors, will attempt to merge anyway");
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
const ourHooks = this.getHookConfig();
|
|
176
|
-
const mergedHooks = { ...existingSettings.hooks ?? {} };
|
|
177
|
-
let hooksAdded = false;
|
|
178
|
-
for (const [eventName, eventConfigs] of Object.entries(ourHooks)) {
|
|
179
|
-
const existing = mergedHooks[eventName] ?? [];
|
|
180
|
-
const ourConfig = eventConfigs[0];
|
|
181
|
-
const ourCommand = (_b = (_a = ourConfig == null ? void 0 : ourConfig.hooks) == null ? void 0 : _a[0]) == null ? void 0 : _b.command;
|
|
182
|
-
const existingConfigIndex = existing.findIndex(
|
|
183
|
-
(config) => {
|
|
184
|
-
var _a2;
|
|
185
|
-
return (_a2 = config.hooks) == null ? void 0 : _a2.some((h) => h.command === ourCommand);
|
|
186
|
-
}
|
|
187
|
-
);
|
|
188
|
-
if (existingConfigIndex === -1) {
|
|
189
|
-
mergedHooks[eventName] = [...existing, ...eventConfigs];
|
|
190
|
-
hooksAdded = true;
|
|
191
|
-
} else {
|
|
192
|
-
const existingConfig = existing[existingConfigIndex];
|
|
193
|
-
const ourMatcher = ourConfig == null ? void 0 : ourConfig.matcher;
|
|
194
|
-
if (existingConfig && ourMatcher !== void 0 && existingConfig.matcher !== ourMatcher) {
|
|
195
|
-
existing[existingConfigIndex] = {
|
|
196
|
-
...existingConfig,
|
|
197
|
-
matcher: ourMatcher
|
|
198
|
-
};
|
|
199
|
-
hooksAdded = true;
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
if (!hooksAdded) {
|
|
204
|
-
logger.debug("All hooks already registered, skipping settings.json update");
|
|
205
|
-
return;
|
|
206
|
-
}
|
|
207
|
-
let content;
|
|
208
|
-
if (existingContent.includes("//") || existingContent.includes("/*")) {
|
|
209
|
-
let modifiedContent = existingContent;
|
|
210
|
-
const edits = modify(modifiedContent, ["hooks"], mergedHooks, {});
|
|
211
|
-
content = applyEdits(modifiedContent, edits);
|
|
212
|
-
} else {
|
|
213
|
-
const updatedSettings = {
|
|
214
|
-
...existingSettings,
|
|
215
|
-
hooks: mergedHooks
|
|
216
|
-
};
|
|
217
|
-
content = JSON.stringify(updatedSettings, null, 2) + "\n";
|
|
218
|
-
}
|
|
219
|
-
const tempPath = `${this.settingsPath}.tmp`;
|
|
220
|
-
await fs.writeFile(tempPath, content, "utf8");
|
|
221
|
-
await fs.rename(tempPath, this.settingsPath);
|
|
222
|
-
logger.debug("Hook configuration merged into settings.json");
|
|
223
|
-
}
|
|
224
|
-
/**
|
|
225
|
-
* Get the hook configuration to register
|
|
226
|
-
*
|
|
227
|
-
* Each event maps to a hook that runs iloom-hook.js
|
|
228
|
-
*/
|
|
229
|
-
getHookConfig() {
|
|
230
|
-
const hookCommand = `node ${path.join(this.hooksDir, "iloom-hook.js")}`;
|
|
231
|
-
return {
|
|
232
|
-
Notification: [
|
|
233
|
-
{ hooks: [{ type: "command", command: hookCommand }] }
|
|
234
|
-
],
|
|
235
|
-
Stop: [
|
|
236
|
-
{ hooks: [{ type: "command", command: hookCommand }] }
|
|
237
|
-
],
|
|
238
|
-
SubagentStop: [
|
|
239
|
-
{ hooks: [{ type: "command", command: hookCommand }] }
|
|
240
|
-
],
|
|
241
|
-
PermissionRequest: [
|
|
242
|
-
{ matcher: "*", hooks: [{ type: "command", command: hookCommand, timeout: 86400 }] }
|
|
243
|
-
],
|
|
244
|
-
PreToolUse: [
|
|
245
|
-
{ matcher: "*", hooks: [{ type: "command", command: hookCommand }] }
|
|
246
|
-
],
|
|
247
|
-
PostToolUse: [
|
|
248
|
-
{ matcher: "*", hooks: [{ type: "command", command: hookCommand }] }
|
|
249
|
-
],
|
|
250
|
-
SessionStart: [
|
|
251
|
-
{ matcher: "*", hooks: [{ type: "command", command: hookCommand }] }
|
|
252
|
-
],
|
|
253
|
-
SessionEnd: [
|
|
254
|
-
{ hooks: [{ type: "command", command: hookCommand }] }
|
|
255
|
-
],
|
|
256
|
-
UserPromptSubmit: [
|
|
257
|
-
{ hooks: [{ type: "command", command: hookCommand }] }
|
|
258
|
-
]
|
|
259
|
-
};
|
|
260
|
-
}
|
|
261
|
-
};
|
|
262
|
-
|
|
263
|
-
// src/commands/ignite.ts
|
|
264
|
-
var WorktreeValidationError = class extends Error {
|
|
265
|
-
constructor(message, suggestion) {
|
|
266
|
-
super(message);
|
|
267
|
-
this.suggestion = suggestion;
|
|
268
|
-
this.name = "WorktreeValidationError";
|
|
269
|
-
}
|
|
270
|
-
};
|
|
271
|
-
var IgniteCommand = class {
|
|
272
|
-
constructor(templateManager, gitWorktreeManager, agentManager, settingsManager, firstRunManager, hookManager) {
|
|
273
|
-
this.templateManager = templateManager ?? new PromptTemplateManager();
|
|
274
|
-
this.gitWorktreeManager = gitWorktreeManager ?? new GitWorktreeManager();
|
|
275
|
-
this.agentManager = agentManager ?? new AgentManager();
|
|
276
|
-
this.settingsManager = settingsManager ?? new SettingsManager();
|
|
277
|
-
this.firstRunManager = firstRunManager ?? new FirstRunManager("spin");
|
|
278
|
-
this.hookManager = hookManager ?? new ClaudeHookManager();
|
|
279
|
-
}
|
|
280
|
-
/**
|
|
281
|
-
* Validate that we're not running from the main worktree
|
|
282
|
-
* @throws WorktreeValidationError if running from main worktree
|
|
283
|
-
*/
|
|
284
|
-
async validateNotMainWorktree() {
|
|
285
|
-
const currentDir = process.cwd();
|
|
286
|
-
const isGitRepo = await isValidGitRepo(currentDir);
|
|
287
|
-
if (!isGitRepo) {
|
|
288
|
-
return;
|
|
289
|
-
}
|
|
290
|
-
const worktreeRoot = await getWorktreeRoot(currentDir);
|
|
291
|
-
if (!worktreeRoot) {
|
|
292
|
-
return;
|
|
293
|
-
}
|
|
294
|
-
const worktrees = await this.gitWorktreeManager.listWorktrees();
|
|
295
|
-
const currentWorktree = worktrees.find((wt) => wt.path === worktreeRoot);
|
|
296
|
-
if (!currentWorktree) {
|
|
297
|
-
return;
|
|
298
|
-
}
|
|
299
|
-
const isMain = await this.gitWorktreeManager.isMainWorktree(currentWorktree, this.settingsManager);
|
|
300
|
-
if (isMain) {
|
|
301
|
-
throw new WorktreeValidationError(
|
|
302
|
-
"You cannot run the command from the main worktree.",
|
|
303
|
-
"Navigate to a feature worktree created by 'il start <issue>' and run 'il spin' from there."
|
|
304
|
-
);
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
/**
|
|
308
|
-
* Main entry point for spin command
|
|
309
|
-
* @param oneShot - One-shot automation mode
|
|
310
|
-
* @param printOptions - Print mode options for headless/CI execution
|
|
311
|
-
*/
|
|
312
|
-
async execute(oneShot, printOptions) {
|
|
313
|
-
var _a, _b;
|
|
314
|
-
this.printOptions = printOptions;
|
|
315
|
-
const isJsonMode = (((_a = this.printOptions) == null ? void 0 : _a.json) ?? false) || (((_b = this.printOptions) == null ? void 0 : _b.jsonStream) ?? false);
|
|
316
|
-
if (isJsonMode) {
|
|
317
|
-
const jsonLogger = createStderrLogger();
|
|
318
|
-
return withLogger(jsonLogger, () => this.executeInternal(oneShot));
|
|
319
|
-
}
|
|
320
|
-
return this.executeInternal(oneShot);
|
|
321
|
-
}
|
|
322
|
-
/**
|
|
323
|
-
* Internal execution method (separated for withLogger wrapping)
|
|
324
|
-
*/
|
|
325
|
-
async executeInternal(oneShot) {
|
|
326
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
|
|
327
|
-
process.env.ILOOM = "1";
|
|
328
|
-
try {
|
|
329
|
-
await this.validateNotMainWorktree();
|
|
330
|
-
} catch (error) {
|
|
331
|
-
if (error instanceof WorktreeValidationError) {
|
|
332
|
-
logger.error(error.message);
|
|
333
|
-
logger.info(error.suggestion);
|
|
334
|
-
throw error;
|
|
335
|
-
}
|
|
336
|
-
throw error;
|
|
337
|
-
}
|
|
338
|
-
try {
|
|
339
|
-
logger.info("\u{1F680} Your loom is spinning up, please wait...");
|
|
340
|
-
const isFirstRun = await this.firstRunManager.isFirstRun();
|
|
341
|
-
if (isFirstRun) {
|
|
342
|
-
logger.success("Welcome to iloom! Preparing first-time experience...");
|
|
343
|
-
}
|
|
344
|
-
await this.hookManager.installHooks();
|
|
345
|
-
const context = await this.detectWorkspaceContext();
|
|
346
|
-
logger.debug("Auto-detected workspace context", { context });
|
|
347
|
-
this.logDetectedContext(context);
|
|
348
|
-
logger.info("\u{1F4DD} Loading prompt template and preparing Claude...");
|
|
349
|
-
const metadataManager = new MetadataManager();
|
|
350
|
-
const metadata = await metadataManager.readMetadata(context.workspacePath);
|
|
351
|
-
const draftPrNumber = (metadata == null ? void 0 : metadata.draftPrNumber) ?? void 0;
|
|
352
|
-
const draftPrUrl = draftPrNumber && ((_a = metadata == null ? void 0 : metadata.prUrls) == null ? void 0 : _a[String(draftPrNumber)]) ? metadata.prUrls[String(draftPrNumber)] : void 0;
|
|
353
|
-
const storedOneShot = (metadata == null ? void 0 : metadata.oneShot) ?? "default";
|
|
354
|
-
const isHeadlessForOneShot = ((_b = this.printOptions) == null ? void 0 : _b.print) ?? false;
|
|
355
|
-
const effectiveOneShot = isHeadlessForOneShot ? "noReview" : oneShot ?? storedOneShot;
|
|
356
|
-
if (!this.settings) {
|
|
357
|
-
const cliOverrides = extractSettingsOverrides();
|
|
358
|
-
this.settings = await this.settingsManager.loadSettings(void 0, cliOverrides);
|
|
359
|
-
}
|
|
360
|
-
if (((_c = metadata == null ? void 0 : metadata.capabilities) == null ? void 0 : _c.includes("web")) && context.branchName) {
|
|
361
|
-
const basePort = ((_f = (_e = (_d = this.settings) == null ? void 0 : _d.capabilities) == null ? void 0 : _e.web) == null ? void 0 : _f.basePort) ?? 3e3;
|
|
362
|
-
context.port = await getWorkspacePort({
|
|
363
|
-
basePort,
|
|
364
|
-
worktreePath: context.workspacePath,
|
|
365
|
-
worktreeBranch: context.branchName
|
|
366
|
-
});
|
|
367
|
-
logger.info(`\u{1F310} Development server port: ${context.port}`);
|
|
368
|
-
}
|
|
369
|
-
const variables = this.buildTemplateVariables(context, effectiveOneShot, draftPrNumber, draftPrUrl);
|
|
370
|
-
if (isFirstRun) {
|
|
371
|
-
variables.FIRST_TIME_USER = true;
|
|
372
|
-
variables.README_CONTENT = await this.loadReadmeContent();
|
|
373
|
-
variables.SETTINGS_SCHEMA_CONTENT = await this.loadSettingsSchemaContent();
|
|
374
|
-
}
|
|
375
|
-
const systemInstructions = await this.templateManager.getPrompt(context.type, variables);
|
|
376
|
-
const userPrompt = this.buildUserPrompt(effectiveOneShot);
|
|
377
|
-
const model = this.settingsManager.getSpinModel(this.settings);
|
|
378
|
-
let permissionMode = this.getPermissionModeForWorkflow(context.type);
|
|
379
|
-
if (effectiveOneShot === "bypassPermissions") {
|
|
380
|
-
permissionMode = "bypassPermissions";
|
|
381
|
-
}
|
|
382
|
-
if (permissionMode === "bypassPermissions") {
|
|
383
|
-
logger.warn(
|
|
384
|
-
"\u26A0\uFE0F WARNING: Using bypassPermissions mode - Claude will execute all tool calls without confirmation. This can be dangerous. Use with caution."
|
|
385
|
-
);
|
|
386
|
-
}
|
|
387
|
-
const sessionId = metadata == null ? void 0 : metadata.sessionId;
|
|
388
|
-
if (!sessionId) {
|
|
389
|
-
throw new Error("No session ID found in loom metadata. This loom may need to be recreated with `il start`.");
|
|
390
|
-
}
|
|
391
|
-
logger.debug("Using session ID from metadata", { sessionId });
|
|
392
|
-
const isHeadless = ((_g = this.printOptions) == null ? void 0 : _g.print) ?? false;
|
|
393
|
-
const claudeOptions = {
|
|
394
|
-
headless: isHeadless,
|
|
395
|
-
addDir: context.workspacePath,
|
|
396
|
-
sessionId
|
|
397
|
-
// Enable Claude Code session resume
|
|
398
|
-
};
|
|
399
|
-
if (model !== void 0) {
|
|
400
|
-
claudeOptions.model = model;
|
|
401
|
-
}
|
|
402
|
-
if (isHeadless) {
|
|
403
|
-
permissionMode = "bypassPermissions";
|
|
404
|
-
}
|
|
405
|
-
if (permissionMode !== void 0 && permissionMode !== "default") {
|
|
406
|
-
claudeOptions.permissionMode = permissionMode;
|
|
407
|
-
}
|
|
408
|
-
if (((_h = this.printOptions) == null ? void 0 : _h.outputFormat) !== void 0) {
|
|
409
|
-
claudeOptions.outputFormat = this.printOptions.outputFormat;
|
|
410
|
-
}
|
|
411
|
-
if (((_i = this.printOptions) == null ? void 0 : _i.verbose) !== void 0) {
|
|
412
|
-
claudeOptions.verbose = this.printOptions.verbose;
|
|
413
|
-
}
|
|
414
|
-
if ((_j = this.printOptions) == null ? void 0 : _j.json) {
|
|
415
|
-
claudeOptions.jsonMode = "json";
|
|
416
|
-
claudeOptions.outputFormat = "stream-json";
|
|
417
|
-
} else if ((_k = this.printOptions) == null ? void 0 : _k.jsonStream) {
|
|
418
|
-
claudeOptions.jsonMode = "stream";
|
|
419
|
-
claudeOptions.outputFormat = "stream-json";
|
|
420
|
-
}
|
|
421
|
-
if (context.branchName !== void 0) {
|
|
422
|
-
claudeOptions.branchName = context.branchName;
|
|
423
|
-
}
|
|
424
|
-
let mcpConfig;
|
|
425
|
-
let allowedTools;
|
|
426
|
-
let disallowedTools;
|
|
427
|
-
if (context.type === "issue" || context.type === "pr") {
|
|
428
|
-
try {
|
|
429
|
-
const provider = this.settings ? IssueTrackerFactory.getProviderName(this.settings) : "github";
|
|
430
|
-
mcpConfig = await generateIssueManagementMcpConfig(context.type, void 0, provider, this.settings, draftPrNumber);
|
|
431
|
-
logger.debug("Generated MCP configuration for issue management", { provider, draftPrNumber });
|
|
432
|
-
const baseTools = [
|
|
433
|
-
"mcp__issue_management__get_issue",
|
|
434
|
-
"mcp__issue_management__get_comment",
|
|
435
|
-
"mcp__issue_management__create_comment",
|
|
436
|
-
"mcp__issue_management__update_comment",
|
|
437
|
-
"mcp__issue_management__create_issue",
|
|
438
|
-
"mcp__recap__add_entry",
|
|
439
|
-
"mcp__recap__get_recap",
|
|
440
|
-
"mcp__recap__add_artifact",
|
|
441
|
-
"mcp__recap__set_complexity"
|
|
442
|
-
];
|
|
443
|
-
allowedTools = context.type === "pr" ? [...baseTools, "mcp__issue_management__get_pr", "mcp__recap__set_goal"] : baseTools;
|
|
444
|
-
disallowedTools = ["Bash(gh api:*), Bash(gh issue view:*), Bash(gh pr view:*), Bash(gh issue comment:*)"];
|
|
445
|
-
logger.debug("Configured tool filtering for issue/PR workflow", { allowedTools, disallowedTools });
|
|
446
|
-
} catch (error) {
|
|
447
|
-
logger.warn(`Failed to generate MCP config: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
448
|
-
}
|
|
449
|
-
} else {
|
|
450
|
-
allowedTools = [
|
|
451
|
-
"mcp__recap__set_goal",
|
|
452
|
-
"mcp__recap__add_entry",
|
|
453
|
-
"mcp__recap__get_recap",
|
|
454
|
-
"mcp__recap__set_complexity"
|
|
455
|
-
];
|
|
456
|
-
logger.debug("Configured tool filtering for regular workflow", { allowedTools });
|
|
457
|
-
}
|
|
458
|
-
try {
|
|
459
|
-
if (!metadata) {
|
|
460
|
-
throw new Error("No loom metadata found for this workspace");
|
|
461
|
-
}
|
|
462
|
-
const recapMcpConfig = generateRecapMcpConfig(context.workspacePath, metadata);
|
|
463
|
-
if (mcpConfig) {
|
|
464
|
-
mcpConfig.push(...recapMcpConfig);
|
|
465
|
-
} else {
|
|
466
|
-
mcpConfig = recapMcpConfig;
|
|
467
|
-
}
|
|
468
|
-
logger.debug("Generated MCP configuration for recap server");
|
|
469
|
-
} catch (error) {
|
|
470
|
-
logger.warn(`Failed to generate recap MCP config: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
471
|
-
}
|
|
472
|
-
let agents;
|
|
473
|
-
try {
|
|
474
|
-
if (((_l = this.settings) == null ? void 0 : _l.agents) && Object.keys(this.settings.agents).length > 0) {
|
|
475
|
-
logger.debug("Loaded project settings", {
|
|
476
|
-
agentOverrides: Object.keys(this.settings.agents)
|
|
477
|
-
});
|
|
478
|
-
}
|
|
479
|
-
const loadedAgents = await this.agentManager.loadAgents(
|
|
480
|
-
this.settings,
|
|
481
|
-
variables,
|
|
482
|
-
["*.md", "!iloom-framework-detector.md"]
|
|
483
|
-
);
|
|
484
|
-
agents = this.agentManager.formatForCli(loadedAgents);
|
|
485
|
-
logger.debug("Loaded agent configurations", {
|
|
486
|
-
agentCount: Object.keys(agents).length,
|
|
487
|
-
agentNames: Object.keys(agents)
|
|
488
|
-
});
|
|
489
|
-
} catch (error) {
|
|
490
|
-
logger.warn(`Failed to load agents: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
491
|
-
}
|
|
492
|
-
logger.debug("Launching Claude in current terminal", {
|
|
493
|
-
type: context.type,
|
|
494
|
-
model,
|
|
495
|
-
permissionMode,
|
|
496
|
-
workspacePath: context.workspacePath,
|
|
497
|
-
hasMcpConfig: !!mcpConfig
|
|
498
|
-
});
|
|
499
|
-
logger.info(isHeadless ? "\u2728 Launching Claude in headless mode..." : "\u2728 Launching Claude in current terminal...");
|
|
500
|
-
const claudeResult = await launchClaude(userPrompt, {
|
|
501
|
-
...claudeOptions,
|
|
502
|
-
appendSystemPrompt: systemInstructions,
|
|
503
|
-
...mcpConfig && { mcpConfig },
|
|
504
|
-
...allowedTools && { allowedTools },
|
|
505
|
-
...disallowedTools && { disallowedTools },
|
|
506
|
-
...agents && { agents }
|
|
507
|
-
});
|
|
508
|
-
if ((_m = this.printOptions) == null ? void 0 : _m.json) {
|
|
509
|
-
console.log(JSON.stringify({
|
|
510
|
-
success: true,
|
|
511
|
-
output: claudeResult ?? ""
|
|
512
|
-
}));
|
|
513
|
-
}
|
|
514
|
-
if (isFirstRun) {
|
|
515
|
-
await this.firstRunManager.markAsRun();
|
|
516
|
-
}
|
|
517
|
-
} catch (error) {
|
|
518
|
-
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
519
|
-
if ((_n = this.printOptions) == null ? void 0 : _n.json) {
|
|
520
|
-
console.log(JSON.stringify({
|
|
521
|
-
success: false,
|
|
522
|
-
error: errorMessage
|
|
523
|
-
}));
|
|
524
|
-
} else {
|
|
525
|
-
logger.error(`Failed to launch Claude: ${errorMessage}`);
|
|
526
|
-
}
|
|
527
|
-
throw error;
|
|
528
|
-
}
|
|
529
|
-
}
|
|
530
|
-
/**
|
|
531
|
-
* Log user-friendly information about detected context
|
|
532
|
-
*/
|
|
533
|
-
logDetectedContext(context) {
|
|
534
|
-
if (context.type === "issue") {
|
|
535
|
-
logger.info(`\u{1F3AF} Detected issue workflow: Issue #${context.issueNumber}`);
|
|
536
|
-
} else if (context.type === "pr") {
|
|
537
|
-
logger.info(`\u{1F504} Detected PR workflow: PR #${context.prNumber}`);
|
|
538
|
-
} else {
|
|
539
|
-
logger.info("\u{1F31F} Detected regular workflow");
|
|
540
|
-
}
|
|
541
|
-
if (context.branchName) {
|
|
542
|
-
logger.info(`\u{1F33F} Working on branch: ${context.branchName}`);
|
|
543
|
-
}
|
|
544
|
-
if (context.port) {
|
|
545
|
-
logger.info(`\u{1F310} Development server port: ${context.port}`);
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
/**
|
|
549
|
-
* Build template variables from context
|
|
550
|
-
*/
|
|
551
|
-
buildTemplateVariables(context, oneShot, draftPrNumber, draftPrUrl) {
|
|
552
|
-
var _a, _b, _c, _d, _e;
|
|
553
|
-
const variables = {
|
|
554
|
-
WORKSPACE_PATH: context.workspacePath
|
|
555
|
-
};
|
|
556
|
-
if (context.issueNumber !== void 0) {
|
|
557
|
-
variables.ISSUE_NUMBER = context.issueNumber;
|
|
558
|
-
}
|
|
559
|
-
if (context.prNumber !== void 0) {
|
|
560
|
-
variables.PR_NUMBER = context.prNumber;
|
|
561
|
-
}
|
|
562
|
-
if (context.title !== void 0) {
|
|
563
|
-
if (context.type === "issue") {
|
|
564
|
-
variables.ISSUE_TITLE = context.title;
|
|
565
|
-
} else if (context.type === "pr") {
|
|
566
|
-
variables.PR_TITLE = context.title;
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
if (context.port !== void 0) {
|
|
570
|
-
variables.PORT = context.port;
|
|
571
|
-
}
|
|
572
|
-
if (oneShot === "noReview" || oneShot === "bypassPermissions") {
|
|
573
|
-
variables.ONE_SHOT_MODE = true;
|
|
574
|
-
} else {
|
|
575
|
-
variables.INTERACTIVE_MODE = true;
|
|
576
|
-
}
|
|
577
|
-
Object.assign(variables, buildReviewTemplateVariables((_a = this.settings) == null ? void 0 : _a.agents));
|
|
578
|
-
if (draftPrNumber !== void 0) {
|
|
579
|
-
variables.DRAFT_PR_MODE = true;
|
|
580
|
-
variables.DRAFT_PR_NUMBER = draftPrNumber;
|
|
581
|
-
if (draftPrUrl) {
|
|
582
|
-
variables.DRAFT_PR_URL = draftPrUrl;
|
|
583
|
-
}
|
|
584
|
-
const autoCommitPushEnabled = ((_c = (_b = this.settings) == null ? void 0 : _b.mergeBehavior) == null ? void 0 : _c.autoCommitPush) !== false;
|
|
585
|
-
variables.AUTO_COMMIT_PUSH = autoCommitPushEnabled;
|
|
586
|
-
const remote = ((_e = (_d = this.settings) == null ? void 0 : _d.mergeBehavior) == null ? void 0 : _e.remote) ?? "origin";
|
|
587
|
-
if (!/^[a-zA-Z0-9_-]+$/.test(remote)) {
|
|
588
|
-
throw new Error(`Invalid git remote name: "${remote}". Remote names can only contain alphanumeric characters, underscores, and hyphens.`);
|
|
589
|
-
}
|
|
590
|
-
variables.GIT_REMOTE = remote;
|
|
591
|
-
} else if (context.type === "regular") {
|
|
592
|
-
variables.STANDARD_BRANCH_MODE = true;
|
|
593
|
-
} else {
|
|
594
|
-
variables.STANDARD_ISSUE_MODE = true;
|
|
595
|
-
}
|
|
596
|
-
return variables;
|
|
597
|
-
}
|
|
598
|
-
/**
|
|
599
|
-
* Get the appropriate permission mode for a workflow type
|
|
600
|
-
* Same logic as ClaudeService.getPermissionModeForWorkflow()
|
|
601
|
-
*/
|
|
602
|
-
getPermissionModeForWorkflow(type) {
|
|
603
|
-
var _a;
|
|
604
|
-
if ((_a = this.settings) == null ? void 0 : _a.workflows) {
|
|
605
|
-
const workflowConfig = type === "issue" ? this.settings.workflows.issue : type === "pr" ? this.settings.workflows.pr : this.settings.workflows.regular;
|
|
606
|
-
if (workflowConfig == null ? void 0 : workflowConfig.permissionMode) {
|
|
607
|
-
return workflowConfig.permissionMode;
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
|
-
if (type === "issue") {
|
|
611
|
-
return "acceptEdits";
|
|
612
|
-
}
|
|
613
|
-
return "default";
|
|
614
|
-
}
|
|
615
|
-
/**
|
|
616
|
-
* Auto-detect workspace context from current directory and git branch
|
|
617
|
-
*
|
|
618
|
-
* Detection priority:
|
|
619
|
-
* 1. Directory name patterns (_pr_N, issue-N)
|
|
620
|
-
* 2. Git branch name patterns
|
|
621
|
-
* 3. Fallback to 'regular' workflow
|
|
622
|
-
*
|
|
623
|
-
* This leverages the same logic as FinishCommand.autoDetectFromCurrentDirectory()
|
|
624
|
-
*/
|
|
625
|
-
async detectWorkspaceContext() {
|
|
626
|
-
const workspacePath = process.cwd();
|
|
627
|
-
const currentDir = path2.basename(workspacePath);
|
|
628
|
-
const prPattern = /_pr_(\d+)$/;
|
|
629
|
-
const prMatch = currentDir.match(prPattern);
|
|
630
|
-
if (prMatch == null ? void 0 : prMatch[1]) {
|
|
631
|
-
const prNumber = parseInt(prMatch[1], 10);
|
|
632
|
-
logger.debug(`Auto-detected PR #${prNumber} from directory: ${currentDir}`);
|
|
633
|
-
return this.buildContextForPR(prNumber, workspacePath);
|
|
634
|
-
}
|
|
635
|
-
const issueNumber = extractIssueNumber(currentDir);
|
|
636
|
-
if (issueNumber !== null) {
|
|
637
|
-
logger.debug(`Auto-detected issue #${issueNumber} from directory: ${currentDir}`);
|
|
638
|
-
return this.buildContextForIssue(issueNumber, workspacePath);
|
|
639
|
-
}
|
|
640
|
-
try {
|
|
641
|
-
const repoInfo = await this.gitWorktreeManager.getRepoInfo();
|
|
642
|
-
const currentBranch = repoInfo.currentBranch;
|
|
643
|
-
if (currentBranch) {
|
|
644
|
-
const branchIssueNumber = extractIssueNumber(currentBranch);
|
|
645
|
-
if (branchIssueNumber !== null) {
|
|
646
|
-
logger.debug(`Auto-detected issue #${branchIssueNumber} from branch: ${currentBranch}`);
|
|
647
|
-
return this.buildContextForIssue(branchIssueNumber, workspacePath, currentBranch);
|
|
648
|
-
}
|
|
649
|
-
}
|
|
650
|
-
} catch (error) {
|
|
651
|
-
logger.debug("Could not detect from git branch", { error });
|
|
652
|
-
}
|
|
653
|
-
logger.debug("No specific context detected, using regular workflow");
|
|
654
|
-
return this.buildContextForRegular(workspacePath);
|
|
655
|
-
}
|
|
656
|
-
/**
|
|
657
|
-
* Build context for issue workflow
|
|
658
|
-
*/
|
|
659
|
-
async buildContextForIssue(issueNumber, workspacePath, branchName) {
|
|
660
|
-
if (!branchName) {
|
|
661
|
-
try {
|
|
662
|
-
const repoInfo = await this.gitWorktreeManager.getRepoInfo();
|
|
663
|
-
branchName = repoInfo.currentBranch ?? void 0;
|
|
664
|
-
} catch {
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
const context = {
|
|
668
|
-
type: "issue",
|
|
669
|
-
issueNumber,
|
|
670
|
-
workspacePath,
|
|
671
|
-
headless: false
|
|
672
|
-
// Interactive mode
|
|
673
|
-
};
|
|
674
|
-
if (branchName !== void 0) {
|
|
675
|
-
context.branchName = branchName;
|
|
676
|
-
}
|
|
677
|
-
return context;
|
|
678
|
-
}
|
|
679
|
-
/**
|
|
680
|
-
* Build context for PR workflow
|
|
681
|
-
*/
|
|
682
|
-
async buildContextForPR(prNumber, workspacePath) {
|
|
683
|
-
let branchName;
|
|
684
|
-
try {
|
|
685
|
-
const repoInfo = await this.gitWorktreeManager.getRepoInfo();
|
|
686
|
-
branchName = repoInfo.currentBranch ?? void 0;
|
|
687
|
-
} catch {
|
|
688
|
-
}
|
|
689
|
-
const context = {
|
|
690
|
-
type: "pr",
|
|
691
|
-
prNumber,
|
|
692
|
-
workspacePath,
|
|
693
|
-
headless: false
|
|
694
|
-
// Interactive mode
|
|
695
|
-
};
|
|
696
|
-
if (branchName !== void 0) {
|
|
697
|
-
context.branchName = branchName;
|
|
698
|
-
}
|
|
699
|
-
return context;
|
|
700
|
-
}
|
|
701
|
-
/**
|
|
702
|
-
* Build context for regular workflow
|
|
703
|
-
*/
|
|
704
|
-
async buildContextForRegular(workspacePath) {
|
|
705
|
-
let branchName;
|
|
706
|
-
try {
|
|
707
|
-
const repoInfo = await this.gitWorktreeManager.getRepoInfo();
|
|
708
|
-
branchName = repoInfo.currentBranch ?? void 0;
|
|
709
|
-
} catch {
|
|
710
|
-
}
|
|
711
|
-
const context = {
|
|
712
|
-
type: "regular",
|
|
713
|
-
workspacePath,
|
|
714
|
-
headless: false
|
|
715
|
-
// Interactive mode
|
|
716
|
-
};
|
|
717
|
-
if (branchName !== void 0) {
|
|
718
|
-
context.branchName = branchName;
|
|
719
|
-
}
|
|
720
|
-
return context;
|
|
721
|
-
}
|
|
722
|
-
/**
|
|
723
|
-
* Build user prompt based on one-shot mode
|
|
724
|
-
*/
|
|
725
|
-
buildUserPrompt(oneShot = "default") {
|
|
726
|
-
if (oneShot === "noReview" || oneShot === "bypassPermissions") {
|
|
727
|
-
return "Guide the user through the iloom workflow! The user has requested you move through the workflow without awaiting confirmation. This supersedes any other guidance.";
|
|
728
|
-
}
|
|
729
|
-
return "Guide the user through the iloom workflow!";
|
|
730
|
-
}
|
|
731
|
-
/**
|
|
732
|
-
* Load README.md content for first-time users
|
|
733
|
-
* Walks up from dist directory to find README.md in project root
|
|
734
|
-
*/
|
|
735
|
-
async loadReadmeContent() {
|
|
736
|
-
try {
|
|
737
|
-
let currentDir = path2.dirname(new URL(import.meta.url).pathname);
|
|
738
|
-
while (currentDir !== path2.dirname(currentDir)) {
|
|
739
|
-
const readmePath = path2.join(currentDir, "README.md");
|
|
740
|
-
try {
|
|
741
|
-
const content = await readFile(readmePath, "utf-8");
|
|
742
|
-
logger.debug("Loaded README.md for first-time user", { readmePath });
|
|
743
|
-
return content;
|
|
744
|
-
} catch {
|
|
745
|
-
currentDir = path2.dirname(currentDir);
|
|
746
|
-
}
|
|
747
|
-
}
|
|
748
|
-
logger.debug("README.md not found, returning empty string");
|
|
749
|
-
return "";
|
|
750
|
-
} catch (error) {
|
|
751
|
-
logger.debug(`Failed to load README.md: ${error}`);
|
|
752
|
-
return "";
|
|
753
|
-
}
|
|
754
|
-
}
|
|
755
|
-
/**
|
|
756
|
-
* Load settings schema content for first-time users
|
|
757
|
-
* Walks up from dist directory to find .iloom/README.md
|
|
758
|
-
*/
|
|
759
|
-
async loadSettingsSchemaContent() {
|
|
760
|
-
try {
|
|
761
|
-
let currentDir = path2.dirname(new URL(import.meta.url).pathname);
|
|
762
|
-
while (currentDir !== path2.dirname(currentDir)) {
|
|
763
|
-
const schemaPath = path2.join(currentDir, ".iloom", "README.md");
|
|
764
|
-
try {
|
|
765
|
-
const content = await readFile(schemaPath, "utf-8");
|
|
766
|
-
logger.debug("Loaded .iloom/README.md for first-time user", { schemaPath });
|
|
767
|
-
return content;
|
|
768
|
-
} catch {
|
|
769
|
-
currentDir = path2.dirname(currentDir);
|
|
770
|
-
}
|
|
771
|
-
}
|
|
772
|
-
logger.debug(".iloom/README.md not found, returning empty string");
|
|
773
|
-
return "";
|
|
774
|
-
} catch (error) {
|
|
775
|
-
logger.debug(`Failed to load .iloom/README.md: ${error}`);
|
|
776
|
-
return "";
|
|
777
|
-
}
|
|
778
|
-
}
|
|
779
|
-
};
|
|
780
|
-
export {
|
|
781
|
-
IgniteCommand,
|
|
782
|
-
WorktreeValidationError
|
|
783
|
-
};
|
|
784
|
-
//# sourceMappingURL=ignite-OPO6EDYT.js.map
|