@iloom/cli 0.1.17 → 0.1.18
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/README.md +14 -0
- package/dist/ClaudeContextManager-LD3VB6EM.js +13 -0
- package/dist/ClaudeService-CFFI7DD5.js +12 -0
- package/dist/{GitHubService-F7Z3XJOS.js → GitHubService-SH4H6VS5.js} +3 -3
- package/dist/{LoomLauncher-MODG2SEM.js → LoomLauncher-FB2MV2ZI.js} +7 -7
- package/dist/{PromptTemplateManager-7FINLRDE.js → PromptTemplateManager-WM5GIPEF.js} +2 -2
- package/dist/{SettingsManager-VAZF26S2.js → SettingsManager-SKLUVE3K.js} +6 -2
- package/dist/{add-issue-22JBNOML.js → add-issue-L5HX6LEV.js} +23 -8
- package/dist/add-issue-L5HX6LEV.js.map +1 -0
- package/dist/{chunk-SSR5AVRJ.js → chunk-6OTVPRXH.js} +21 -8
- package/dist/chunk-6OTVPRXH.js.map +1 -0
- package/dist/{chunk-KQDEK2ZW.js → chunk-DGEKUT7Q.js} +9 -5
- package/dist/chunk-DGEKUT7Q.js.map +1 -0
- package/dist/chunk-FXV24OYZ.js +83 -0
- package/dist/chunk-FXV24OYZ.js.map +1 -0
- package/dist/{chunk-HPJJSYNS.js → chunk-H5LDRGVK.js} +6 -8
- package/dist/{chunk-HPJJSYNS.js.map → chunk-H5LDRGVK.js.map} +1 -1
- package/dist/{chunk-WKEWRSDB.js → chunk-HURVAQRK.js} +3 -3
- package/dist/{chunk-T7QPXANZ.js → chunk-IIPTBZQW.js} +17 -17
- package/dist/chunk-IIPTBZQW.js.map +1 -0
- package/dist/{chunk-QEPVTTHD.js → chunk-IO4WFTL2.js} +17 -11
- package/dist/chunk-IO4WFTL2.js.map +1 -0
- package/dist/{chunk-JQ7VOSTC.js → chunk-KOCQAD2E.js} +3 -3
- package/dist/{chunk-F3XBU2R7.js → chunk-L4QGC27H.js} +68 -2
- package/dist/chunk-L4QGC27H.js.map +1 -0
- package/dist/{chunk-YYSKGAZT.js → chunk-LAPY6NAE.js} +17 -8
- package/dist/chunk-LAPY6NAE.js.map +1 -0
- package/dist/{chunk-O2QWO64Z.js → chunk-PV3GAXQO.js} +56 -3
- package/dist/chunk-PV3GAXQO.js.map +1 -0
- package/dist/{chunk-CP2NU2JC.js → chunk-Q2KYPAH2.js} +7 -7
- package/dist/{chunk-CP2NU2JC.js.map → chunk-Q2KYPAH2.js.map} +1 -1
- package/dist/{chunk-Y7SAGNUT.js → chunk-SLIMABFA.js} +2 -2
- package/dist/{chunk-W3DQTW63.js → chunk-USVVV3FP.js} +4 -4
- package/dist/chunk-VVH3ANF2.js +307 -0
- package/dist/chunk-VVH3ANF2.js.map +1 -0
- package/dist/{chunk-JBH2ZYYZ.js → chunk-VYQLLHZ7.js} +22 -3
- package/dist/chunk-VYQLLHZ7.js.map +1 -0
- package/dist/{chunk-SJUQ2NDR.js → chunk-ZMNQBJUI.js} +24 -19
- package/dist/chunk-ZMNQBJUI.js.map +1 -0
- package/dist/{cleanup-3LUWPSM7.js → cleanup-ZHROIBSQ.js} +12 -16
- package/dist/cleanup-ZHROIBSQ.js.map +1 -0
- package/dist/cli.js +96 -48
- package/dist/cli.js.map +1 -1
- package/dist/{enhance-XJIQHVPD.js → enhance-VVMAKMVZ.js} +18 -8
- package/dist/enhance-VVMAKMVZ.js.map +1 -0
- package/dist/{feedback-23CLXKFT.js → feedback-AKHD7QIM.js} +8 -8
- package/dist/{finish-3CQZIULO.js → finish-WGPISUEH.js} +36 -313
- package/dist/finish-WGPISUEH.js.map +1 -0
- package/dist/{git-LVRZ57GJ.js → git-OUYMVYJX.js} +2 -2
- package/dist/{ignite-WXEF2ID5.js → ignite-JEN3K3OT.js} +7 -7
- package/dist/index.d.ts +791 -712
- package/dist/index.js +126 -32
- package/dist/index.js.map +1 -1
- package/dist/init-EVUT4ZQJ.js +339 -0
- package/dist/init-EVUT4ZQJ.js.map +1 -0
- package/dist/mcp/github-comment-server.js +12 -9
- package/dist/mcp/github-comment-server.js.map +1 -1
- package/dist/neon-helpers-ZVIRPKCI.js +10 -0
- package/dist/{open-X6BTENPV.js → open-ETZUFSE4.js} +15 -17
- package/dist/{open-X6BTENPV.js.map → open-ETZUFSE4.js.map} +1 -1
- package/dist/prompts/init-prompt.txt +746 -0
- package/dist/rebase-KBWFDZCN.js +95 -0
- package/dist/rebase-KBWFDZCN.js.map +1 -0
- package/dist/remote-GJEZWRCC.js +14 -0
- package/dist/{run-2JCPQAX3.js → run-4SVQ3WEU.js} +15 -17
- package/dist/{run-2JCPQAX3.js.map → run-4SVQ3WEU.js.map} +1 -1
- package/dist/schema/settings.schema.json +51 -1
- package/dist/{start-LWVRBJ6S.js → start-2NEZU7SE.js} +54 -53
- package/dist/{start-LWVRBJ6S.js.map → start-2NEZU7SE.js.map} +1 -1
- package/dist/{test-git-XPF4SZXJ.js → test-git-MKZATGZN.js} +3 -3
- package/dist/{test-prefix-XGFXFAYN.js → test-prefix-ZNLWDI3K.js} +3 -3
- package/dist/{update-DN3FSNKY.js → update-4TDDUR5K.js} +10 -4
- package/dist/{update-DN3FSNKY.js.map → update-4TDDUR5K.js.map} +1 -1
- package/package.json +1 -1
- package/dist/ClaudeContextManager-XOSXQ67R.js +0 -13
- package/dist/ClaudeService-YSZ6EXWP.js +0 -12
- package/dist/NeonProvider-PAGPUH7F.js +0 -12
- package/dist/add-issue-22JBNOML.js.map +0 -1
- package/dist/chunk-37DYYFVK.js +0 -29
- package/dist/chunk-37DYYFVK.js.map +0 -1
- package/dist/chunk-F3XBU2R7.js.map +0 -1
- package/dist/chunk-JBH2ZYYZ.js.map +0 -1
- package/dist/chunk-KQDEK2ZW.js.map +0 -1
- package/dist/chunk-O2QWO64Z.js.map +0 -1
- package/dist/chunk-QEPVTTHD.js.map +0 -1
- package/dist/chunk-SJUQ2NDR.js.map +0 -1
- package/dist/chunk-SSR5AVRJ.js.map +0 -1
- package/dist/chunk-T7QPXANZ.js.map +0 -1
- package/dist/chunk-YYSKGAZT.js.map +0 -1
- package/dist/cleanup-3LUWPSM7.js.map +0 -1
- package/dist/enhance-XJIQHVPD.js.map +0 -1
- package/dist/env-MDFL4ZXL.js +0 -23
- package/dist/finish-3CQZIULO.js.map +0 -1
- package/dist/init-RHACUR4E.js +0 -123
- package/dist/init-RHACUR4E.js.map +0 -1
- /package/dist/{ClaudeContextManager-XOSXQ67R.js.map → ClaudeContextManager-LD3VB6EM.js.map} +0 -0
- /package/dist/{ClaudeService-YSZ6EXWP.js.map → ClaudeService-CFFI7DD5.js.map} +0 -0
- /package/dist/{GitHubService-F7Z3XJOS.js.map → GitHubService-SH4H6VS5.js.map} +0 -0
- /package/dist/{LoomLauncher-MODG2SEM.js.map → LoomLauncher-FB2MV2ZI.js.map} +0 -0
- /package/dist/{NeonProvider-PAGPUH7F.js.map → PromptTemplateManager-WM5GIPEF.js.map} +0 -0
- /package/dist/{PromptTemplateManager-7FINLRDE.js.map → SettingsManager-SKLUVE3K.js.map} +0 -0
- /package/dist/{chunk-WKEWRSDB.js.map → chunk-HURVAQRK.js.map} +0 -0
- /package/dist/{chunk-JQ7VOSTC.js.map → chunk-KOCQAD2E.js.map} +0 -0
- /package/dist/{chunk-Y7SAGNUT.js.map → chunk-SLIMABFA.js.map} +0 -0
- /package/dist/{chunk-W3DQTW63.js.map → chunk-USVVV3FP.js.map} +0 -0
- /package/dist/{feedback-23CLXKFT.js.map → feedback-AKHD7QIM.js.map} +0 -0
- /package/dist/{SettingsManager-VAZF26S2.js.map → git-OUYMVYJX.js.map} +0 -0
- /package/dist/{ignite-WXEF2ID5.js.map → ignite-JEN3K3OT.js.map} +0 -0
- /package/dist/{env-MDFL4ZXL.js.map → neon-helpers-ZVIRPKCI.js.map} +0 -0
- /package/dist/{git-LVRZ57GJ.js.map → remote-GJEZWRCC.js.map} +0 -0
- /package/dist/{test-git-XPF4SZXJ.js.map → test-git-MKZATGZN.js.map} +0 -0
- /package/dist/{test-prefix-XGFXFAYN.js.map → test-prefix-ZNLWDI3K.js.map} +0 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
MergeManager
|
|
4
|
+
} from "./chunk-VVH3ANF2.js";
|
|
5
|
+
import "./chunk-PXZBAC2M.js";
|
|
6
|
+
import {
|
|
7
|
+
GitWorktreeManager
|
|
8
|
+
} from "./chunk-IO4WFTL2.js";
|
|
9
|
+
import {
|
|
10
|
+
SettingsManager
|
|
11
|
+
} from "./chunk-VYQLLHZ7.js";
|
|
12
|
+
import {
|
|
13
|
+
getRepoRoot,
|
|
14
|
+
isValidGitRepo
|
|
15
|
+
} from "./chunk-KOCQAD2E.js";
|
|
16
|
+
import {
|
|
17
|
+
logger
|
|
18
|
+
} from "./chunk-GEHQXLEI.js";
|
|
19
|
+
|
|
20
|
+
// src/commands/rebase.ts
|
|
21
|
+
var WorktreeValidationError = class extends Error {
|
|
22
|
+
constructor(message, suggestion) {
|
|
23
|
+
super(message);
|
|
24
|
+
this.suggestion = suggestion;
|
|
25
|
+
this.name = "WorktreeValidationError";
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
var RebaseCommand = class {
|
|
29
|
+
constructor(mergeManager, gitWorktreeManager, settingsManager) {
|
|
30
|
+
this.mergeManager = mergeManager ?? new MergeManager();
|
|
31
|
+
this.gitWorktreeManager = gitWorktreeManager ?? new GitWorktreeManager();
|
|
32
|
+
this.settingsManager = settingsManager ?? new SettingsManager();
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Validate that the current directory is within an iloom-managed worktree
|
|
36
|
+
* Returns the worktree root path if valid
|
|
37
|
+
* @throws WorktreeValidationError if validation fails
|
|
38
|
+
*/
|
|
39
|
+
async validateWorktreeContext() {
|
|
40
|
+
const currentDir = process.cwd();
|
|
41
|
+
const isGitRepo = await isValidGitRepo(currentDir);
|
|
42
|
+
if (!isGitRepo) {
|
|
43
|
+
throw new WorktreeValidationError(
|
|
44
|
+
"Not a git repository.",
|
|
45
|
+
"Run 'il rebase' from within an iloom worktree created by 'il start'."
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
const repoRoot = await getRepoRoot(currentDir);
|
|
49
|
+
if (!repoRoot) {
|
|
50
|
+
throw new WorktreeValidationError(
|
|
51
|
+
"Could not determine repository root.",
|
|
52
|
+
"Run 'il rebase' from within an iloom worktree created by 'il start'."
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
const worktrees = await this.gitWorktreeManager.listWorktrees();
|
|
56
|
+
const currentWorktree = worktrees.find((wt) => wt.path === repoRoot);
|
|
57
|
+
if (!currentWorktree) {
|
|
58
|
+
throw new WorktreeValidationError(
|
|
59
|
+
"This directory is not an iloom worktree.",
|
|
60
|
+
"Run 'il rebase' from within a worktree created by 'il start <issue>'. Use 'il list' to see available worktrees."
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
const isMain = await this.gitWorktreeManager.isMainWorktree(currentWorktree, this.settingsManager);
|
|
64
|
+
if (isMain) {
|
|
65
|
+
throw new WorktreeValidationError(
|
|
66
|
+
"Cannot rebase from the main worktree.",
|
|
67
|
+
"Navigate to a feature worktree created by 'il start <issue>' and run 'il rebase' from there."
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
return repoRoot;
|
|
71
|
+
}
|
|
72
|
+
async execute(options = {}) {
|
|
73
|
+
let worktreePath;
|
|
74
|
+
try {
|
|
75
|
+
worktreePath = await this.validateWorktreeContext();
|
|
76
|
+
} catch (error) {
|
|
77
|
+
if (error instanceof WorktreeValidationError) {
|
|
78
|
+
logger.error(error.message);
|
|
79
|
+
logger.info(error.suggestion);
|
|
80
|
+
throw error;
|
|
81
|
+
}
|
|
82
|
+
throw error;
|
|
83
|
+
}
|
|
84
|
+
const mergeOptions = {
|
|
85
|
+
dryRun: options.dryRun ?? false,
|
|
86
|
+
force: options.force ?? false
|
|
87
|
+
};
|
|
88
|
+
await this.mergeManager.rebaseOnMain(worktreePath, mergeOptions);
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
export {
|
|
92
|
+
RebaseCommand,
|
|
93
|
+
WorktreeValidationError
|
|
94
|
+
};
|
|
95
|
+
//# sourceMappingURL=rebase-KBWFDZCN.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/rebase.ts"],"sourcesContent":["import { logger } from '../utils/logger.js'\nimport { MergeManager } from '../lib/MergeManager.js'\nimport { GitWorktreeManager } from '../lib/GitWorktreeManager.js'\nimport { SettingsManager } from '../lib/SettingsManager.js'\nimport { isValidGitRepo, getRepoRoot } from '../utils/git.js'\nimport type { MergeOptions } from '../types/index.js'\n\nexport interface RebaseOptions {\n\tforce?: boolean\n\tdryRun?: boolean\n}\n\n/**\n * Error thrown when the rebase command is run from an invalid location\n */\nexport class WorktreeValidationError extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic readonly suggestion: string\n\t) {\n\t\tsuper(message)\n\t\tthis.name = 'WorktreeValidationError'\n\t}\n}\n\n/**\n * RebaseCommand: Rebase current branch on main with Claude-assisted conflict resolution\n *\n * This command:\n * 1. Validates the current directory is an iloom-managed worktree\n * 2. Detects the worktree root (supports running from subdirectories)\n * 3. Delegates to MergeManager.rebaseOnMain() which handles:\n * - Checking main branch exists\n * - Detecting uncommitted changes (throws if found)\n * - Checking if already up-to-date\n * - Executing rebase\n * - Claude-assisted conflict resolution\n * 4. Reports success\n */\nexport class RebaseCommand {\n\tprivate mergeManager: MergeManager\n\tprivate gitWorktreeManager: GitWorktreeManager\n\tprivate settingsManager: SettingsManager\n\n\tconstructor(mergeManager?: MergeManager, gitWorktreeManager?: GitWorktreeManager, settingsManager?: SettingsManager) {\n\t\tthis.mergeManager = mergeManager ?? new MergeManager()\n\t\tthis.gitWorktreeManager = gitWorktreeManager ?? new GitWorktreeManager()\n\t\tthis.settingsManager = settingsManager ?? new SettingsManager()\n\t}\n\n\t/**\n\t * Validate that the current directory is within an iloom-managed worktree\n\t * Returns the worktree root path if valid\n\t * @throws WorktreeValidationError if validation fails\n\t */\n\tprivate async validateWorktreeContext(): Promise<string> {\n\t\tconst currentDir = process.cwd()\n\n\t\t// Step 1: Check if we're in a git repository at all\n\t\tconst isGitRepo = await isValidGitRepo(currentDir)\n\t\tif (!isGitRepo) {\n\t\t\tthrow new WorktreeValidationError(\n\t\t\t\t'Not a git repository.',\n\t\t\t\t\"Run 'il rebase' from within an iloom worktree created by 'il start'.\"\n\t\t\t)\n\t\t}\n\n\t\t// Step 2: Get the repository root (handles subdirectories)\n\t\tconst repoRoot = await getRepoRoot(currentDir)\n\t\tif (!repoRoot) {\n\t\t\tthrow new WorktreeValidationError(\n\t\t\t\t'Could not determine repository root.',\n\t\t\t\t\"Run 'il rebase' from within an iloom worktree created by 'il start'.\"\n\t\t\t)\n\t\t}\n\n\t\t// Step 3: Check if this path is a registered git worktree\n\t\tconst worktrees = await this.gitWorktreeManager.listWorktrees()\n\t\tconst currentWorktree = worktrees.find(wt => wt.path === repoRoot)\n\n\t\tif (!currentWorktree) {\n\t\t\tthrow new WorktreeValidationError(\n\t\t\t\t'This directory is not an iloom worktree.',\n\t\t\t\t\"Run 'il rebase' from within a worktree created by 'il start <issue>'. Use 'il list' to see available worktrees.\"\n\t\t\t)\n\t\t}\n\n\t\t// Step 4: Check if this is the main worktree (we shouldn't rebase from main)\n\t\tconst isMain = await this.gitWorktreeManager.isMainWorktree(currentWorktree, this.settingsManager)\n\t\tif (isMain) {\n\t\t\tthrow new WorktreeValidationError(\n\t\t\t\t'Cannot rebase from the main worktree.',\n\t\t\t\t\"Navigate to a feature worktree created by 'il start <issue>' and run 'il rebase' from there.\"\n\t\t\t)\n\t\t}\n\n\t\treturn repoRoot\n\t}\n\n\tasync execute(options: RebaseOptions = {}): Promise<void> {\n\t\t// Step 1: Validate we're in a valid iloom worktree\n\t\tlet worktreePath: string\n\t\ttry {\n\t\t\tworktreePath = await this.validateWorktreeContext()\n\t\t} catch (error) {\n\t\t\tif (error instanceof WorktreeValidationError) {\n\t\t\t\tlogger.error(error.message)\n\t\t\t\tlogger.info(error.suggestion)\n\t\t\t\tthrow error\n\t\t\t}\n\t\t\tthrow error\n\t\t}\n\n\t\tconst mergeOptions: MergeOptions = {\n\t\t\tdryRun: options.dryRun ?? false,\n\t\t\tforce: options.force ?? false,\n\t\t}\n\n\t\t// MergeManager.rebaseOnMain() handles:\n\t\t// - Checking main branch exists\n\t\t// - Detecting uncommitted changes (throws if found)\n\t\t// - Checking if already up-to-date\n\t\t// - Executing rebase\n\t\t// - Claude-assisted conflict resolution\n\t\tawait this.mergeManager.rebaseOnMain(worktreePath, mergeOptions)\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAeO,IAAM,0BAAN,cAAsC,MAAM;AAAA,EAClD,YACC,SACgB,YACf;AACD,UAAM,OAAO;AAFG;AAGhB,SAAK,OAAO;AAAA,EACb;AACD;AAgBO,IAAM,gBAAN,MAAoB;AAAA,EAK1B,YAAY,cAA6B,oBAAyC,iBAAmC;AACpH,SAAK,eAAe,gBAAgB,IAAI,aAAa;AACrD,SAAK,qBAAqB,sBAAsB,IAAI,mBAAmB;AACvE,SAAK,kBAAkB,mBAAmB,IAAI,gBAAgB;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,0BAA2C;AACxD,UAAM,aAAa,QAAQ,IAAI;AAG/B,UAAM,YAAY,MAAM,eAAe,UAAU;AACjD,QAAI,CAAC,WAAW;AACf,YAAM,IAAI;AAAA,QACT;AAAA,QACA;AAAA,MACD;AAAA,IACD;AAGA,UAAM,WAAW,MAAM,YAAY,UAAU;AAC7C,QAAI,CAAC,UAAU;AACd,YAAM,IAAI;AAAA,QACT;AAAA,QACA;AAAA,MACD;AAAA,IACD;AAGA,UAAM,YAAY,MAAM,KAAK,mBAAmB,cAAc;AAC9D,UAAM,kBAAkB,UAAU,KAAK,QAAM,GAAG,SAAS,QAAQ;AAEjE,QAAI,CAAC,iBAAiB;AACrB,YAAM,IAAI;AAAA,QACT;AAAA,QACA;AAAA,MACD;AAAA,IACD;AAGA,UAAM,SAAS,MAAM,KAAK,mBAAmB,eAAe,iBAAiB,KAAK,eAAe;AACjG,QAAI,QAAQ;AACX,YAAM,IAAI;AAAA,QACT;AAAA,QACA;AAAA,MACD;AAAA,IACD;AAEA,WAAO;AAAA,EACR;AAAA,EAEA,MAAM,QAAQ,UAAyB,CAAC,GAAkB;AAEzD,QAAI;AACJ,QAAI;AACH,qBAAe,MAAM,KAAK,wBAAwB;AAAA,IACnD,SAAS,OAAO;AACf,UAAI,iBAAiB,yBAAyB;AAC7C,eAAO,MAAM,MAAM,OAAO;AAC1B,eAAO,KAAK,MAAM,UAAU;AAC5B,cAAM;AAAA,MACP;AACA,YAAM;AAAA,IACP;AAEA,UAAM,eAA6B;AAAA,MAClC,QAAQ,QAAQ,UAAU;AAAA,MAC1B,OAAO,QAAQ,SAAS;AAAA,IACzB;AAQA,UAAM,KAAK,aAAa,aAAa,cAAc,YAAY;AAAA,EAChE;AACD;","names":[]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
getConfiguredRepoFromSettings,
|
|
4
|
+
hasMultipleRemotes,
|
|
5
|
+
parseGitRemotes,
|
|
6
|
+
validateConfiguredRemote
|
|
7
|
+
} from "./chunk-FXV24OYZ.js";
|
|
8
|
+
export {
|
|
9
|
+
getConfiguredRepoFromSettings,
|
|
10
|
+
hasMultipleRemotes,
|
|
11
|
+
parseGitRemotes,
|
|
12
|
+
validateConfiguredRemote
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=remote-GJEZWRCC.js.map
|
|
@@ -1,37 +1,35 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
DevServerManager
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-GZP4UGGM.js";
|
|
6
|
-
import {
|
|
7
|
-
extractSettingsOverrides
|
|
8
|
-
} from "./chunk-GYCR2LOU.js";
|
|
9
|
-
import {
|
|
10
|
-
openBrowser
|
|
11
|
-
} from "./chunk-YETJNRQM.js";
|
|
4
|
+
} from "./chunk-USVVV3FP.js";
|
|
12
5
|
import {
|
|
13
6
|
IdentifierParser
|
|
14
7
|
} from "./chunk-H4E4THUZ.js";
|
|
15
8
|
import "./chunk-SPYPLHMK.js";
|
|
9
|
+
import "./chunk-GZP4UGGM.js";
|
|
16
10
|
import {
|
|
17
|
-
calculatePortForBranch
|
|
18
|
-
|
|
11
|
+
calculatePortForBranch,
|
|
12
|
+
extractPort,
|
|
13
|
+
parseEnvFile
|
|
14
|
+
} from "./chunk-ZMNQBJUI.js";
|
|
19
15
|
import "./chunk-BLCTGFZN.js";
|
|
16
|
+
import {
|
|
17
|
+
extractSettingsOverrides
|
|
18
|
+
} from "./chunk-GYCR2LOU.js";
|
|
20
19
|
import {
|
|
21
20
|
ProjectCapabilityDetector
|
|
22
21
|
} from "./chunk-CWR2SANQ.js";
|
|
23
22
|
import "./chunk-2ZPFJQ3B.js";
|
|
24
23
|
import {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
} from "./chunk-SJUQ2NDR.js";
|
|
24
|
+
openBrowser
|
|
25
|
+
} from "./chunk-YETJNRQM.js";
|
|
28
26
|
import {
|
|
29
27
|
GitWorktreeManager
|
|
30
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-IO4WFTL2.js";
|
|
31
29
|
import {
|
|
32
30
|
SettingsManager
|
|
33
|
-
} from "./chunk-
|
|
34
|
-
import "./chunk-
|
|
31
|
+
} from "./chunk-VYQLLHZ7.js";
|
|
32
|
+
import "./chunk-KOCQAD2E.js";
|
|
35
33
|
import {
|
|
36
34
|
logger
|
|
37
35
|
} from "./chunk-GEHQXLEI.js";
|
|
@@ -275,4 +273,4 @@ Make sure the project is built (run 'il start' first)`
|
|
|
275
273
|
export {
|
|
276
274
|
RunCommand
|
|
277
275
|
};
|
|
278
|
-
//# sourceMappingURL=run-
|
|
276
|
+
//# sourceMappingURL=run-4SVQ3WEU.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/run.ts"],"sourcesContent":["import path from 'path'\nimport fs from 'fs-extra'\nimport { execa } from 'execa'\nimport { GitWorktreeManager } from '../lib/GitWorktreeManager.js'\nimport { ProjectCapabilityDetector } from '../lib/ProjectCapabilityDetector.js'\nimport { DevServerManager } from '../lib/DevServerManager.js'\nimport { SettingsManager } from '../lib/SettingsManager.js'\nimport { IdentifierParser } from '../utils/IdentifierParser.js'\nimport { openBrowser } from '../utils/browser.js'\nimport { parseEnvFile, extractPort } from '../utils/env.js'\nimport { calculatePortForBranch } from '../utils/port.js'\nimport { logger } from '../utils/logger.js'\nimport { extractSettingsOverrides } from '../utils/cli-overrides.js'\nimport type { GitWorktree } from '../types/worktree.js'\n\nexport interface RunCommandInput {\n\tidentifier?: string\n\targs?: string[]\n}\n\ninterface ParsedRunInput {\n\ttype: 'issue' | 'pr' | 'branch'\n\tnumber?: number // For issues and PRs\n\tbranchName?: string // For branches\n\toriginalInput: string\n\tautoDetected: boolean\n}\n\n/**\n * RunCommand - Runs CLI tool or opens workspace in browser\n * Priority: CLI first, Web fallback\n */\nexport class RunCommand {\n\tconstructor(\n\t\tprivate gitWorktreeManager = new GitWorktreeManager(),\n\t\tprivate capabilityDetector = new ProjectCapabilityDetector(),\n\t\tprivate identifierParser = new IdentifierParser(new GitWorktreeManager()),\n\t\tprivate devServerManager = new DevServerManager(),\n\t\tprivate settingsManager = new SettingsManager()\n\t) {}\n\n\tasync execute(input: RunCommandInput): Promise<void> {\n\t\t// 1. Parse or auto-detect identifier\n\t\tconst parsed = input.identifier\n\t\t\t? await this.parseExplicitInput(input.identifier)\n\t\t\t: await this.autoDetectFromCurrentDirectory()\n\n\t\tlogger.debug(`Parsed input: ${JSON.stringify(parsed)}`)\n\n\t\t// 2. Find worktree path based on identifier\n\t\tconst worktree = await this.findWorktreeForIdentifier(parsed)\n\n\t\tlogger.info(`Found worktree at: ${worktree.path}`)\n\n\t\t// 3. Detect project capabilities\n\t\tconst { capabilities, binEntries } =\n\t\t\tawait this.capabilityDetector.detectCapabilities(worktree.path)\n\n\t\tlogger.debug(`Detected capabilities: ${capabilities.join(', ')}`)\n\n\t\t// 4. Execute based on capabilities (CLI first, web fallback)\n\t\tif (capabilities.includes('cli')) {\n\t\t\tawait this.runCLITool(worktree.path, binEntries, input.args ?? [])\n\t\t} else if (capabilities.includes('web')) {\n\t\t\tawait this.openWebBrowser(worktree.path)\n\t\t} else {\n\t\t\tthrow new Error(\n\t\t\t\t`No CLI or web capabilities detected for workspace at ${worktree.path}`\n\t\t\t)\n\t\t}\n\t}\n\n\t/**\n\t * Parse explicit identifier input\n\t */\n\tprivate async parseExplicitInput(identifier: string): Promise<ParsedRunInput> {\n\t\tconst parsed = await this.identifierParser.parseForPatternDetection(identifier)\n\n\t\t// Description type should never reach run command (converted in start)\n\t\tif (parsed.type === 'description') {\n\t\t\tthrow new Error('Description input type is not supported in run command')\n\t\t}\n\n\t\tconst result: ParsedRunInput = {\n\t\t\ttype: parsed.type,\n\t\t\toriginalInput: parsed.originalInput,\n\t\t\tautoDetected: false,\n\t\t}\n\n\t\tif (parsed.number !== undefined) {\n\t\t\tresult.number = parsed.number\n\t\t}\n\t\tif (parsed.branchName !== undefined) {\n\t\t\tresult.branchName = parsed.branchName\n\t\t}\n\n\t\treturn result\n\t}\n\n\t/**\n\t * Auto-detect identifier from current directory\n\t * Same logic as FinishCommand.autoDetectFromCurrentDirectory()\n\t */\n\tprivate async autoDetectFromCurrentDirectory(): Promise<ParsedRunInput> {\n\t\tconst currentDir = path.basename(process.cwd())\n\n\t\t// Check for PR worktree pattern: _pr_N suffix\n\t\tconst prPattern = /_pr_(\\d+)$/\n\t\tconst prMatch = currentDir.match(prPattern)\n\n\t\tif (prMatch?.[1]) {\n\t\t\tconst prNumber = parseInt(prMatch[1], 10)\n\t\t\tlogger.debug(`Auto-detected PR #${prNumber} from directory: ${currentDir}`)\n\t\t\treturn {\n\t\t\t\ttype: 'pr',\n\t\t\t\tnumber: prNumber,\n\t\t\t\toriginalInput: currentDir,\n\t\t\t\tautoDetected: true,\n\t\t\t}\n\t\t}\n\n\t\t// Check for issue pattern in directory\n\t\tconst issuePattern = /issue-(\\d+)/\n\t\tconst issueMatch = currentDir.match(issuePattern)\n\n\t\tif (issueMatch?.[1]) {\n\t\t\tconst issueNumber = parseInt(issueMatch[1], 10)\n\t\t\tlogger.debug(`Auto-detected issue #${issueNumber} from directory: ${currentDir}`)\n\t\t\treturn {\n\t\t\t\ttype: 'issue',\n\t\t\t\tnumber: issueNumber,\n\t\t\t\toriginalInput: currentDir,\n\t\t\t\tautoDetected: true,\n\t\t\t}\n\t\t}\n\n\t\t// Fallback: get current branch name\n\t\tconst repoInfo = await this.gitWorktreeManager.getRepoInfo()\n\t\tconst currentBranch = repoInfo.currentBranch\n\n\t\tif (!currentBranch) {\n\t\t\tthrow new Error(\n\t\t\t\t'Could not auto-detect identifier. Please provide an issue number, PR number, or branch name.\\n' +\n\t\t\t\t\t'Expected directory pattern: feat/issue-XX-description OR worktree with _pr_N suffix'\n\t\t\t)\n\t\t}\n\n\t\t// Try to extract issue from branch name\n\t\tconst branchIssueMatch = currentBranch.match(issuePattern)\n\t\tif (branchIssueMatch?.[1]) {\n\t\t\tconst issueNumber = parseInt(branchIssueMatch[1], 10)\n\t\t\tlogger.debug(`Auto-detected issue #${issueNumber} from branch: ${currentBranch}`)\n\t\t\treturn {\n\t\t\t\ttype: 'issue',\n\t\t\t\tnumber: issueNumber,\n\t\t\t\toriginalInput: currentBranch,\n\t\t\t\tautoDetected: true,\n\t\t\t}\n\t\t}\n\n\t\t// Last resort: use branch name\n\t\treturn {\n\t\t\ttype: 'branch',\n\t\t\tbranchName: currentBranch,\n\t\t\toriginalInput: currentBranch,\n\t\t\tautoDetected: true,\n\t\t}\n\t}\n\n\t/**\n\t * Find worktree for the given identifier\n\t */\n\tprivate async findWorktreeForIdentifier(parsed: ParsedRunInput): Promise<GitWorktree> {\n\t\tlet worktree: GitWorktree | null = null\n\n\t\tif (parsed.type === 'issue' && parsed.number !== undefined) {\n\t\t\tworktree = await this.gitWorktreeManager.findWorktreeForIssue(parsed.number)\n\t\t} else if (parsed.type === 'pr' && parsed.number !== undefined) {\n\t\t\t// Pass empty string for branch name since we don't know it yet\n\t\t\tworktree = await this.gitWorktreeManager.findWorktreeForPR(parsed.number, '')\n\t\t} else if (parsed.type === 'branch' && parsed.branchName) {\n\t\t\tworktree = await this.gitWorktreeManager.findWorktreeForBranch(\n\t\t\t\tparsed.branchName\n\t\t\t)\n\t\t}\n\n\t\tif (!worktree) {\n\t\t\tthrow new Error(\n\t\t\t\t`No worktree found for ${this.formatParsedInput(parsed)}. ` +\n\t\t\t\t\t`Run 'il start ${parsed.originalInput}' to create one.`\n\t\t\t)\n\t\t}\n\n\t\treturn worktree\n\t}\n\n\t/**\n\t * Format parsed input for display\n\t */\n\tprivate formatParsedInput(parsed: ParsedRunInput): string {\n\t\tconst autoLabel = parsed.autoDetected ? ' (auto-detected)' : ''\n\n\t\tif (parsed.type === 'issue') {\n\t\t\treturn `issue #${parsed.number}${autoLabel}`\n\t\t}\n\t\tif (parsed.type === 'pr') {\n\t\t\treturn `PR #${parsed.number}${autoLabel}`\n\t\t}\n\t\treturn `branch \"${parsed.branchName}\"${autoLabel}`\n\t}\n\n\t/**\n\t * Run CLI tool directly from worktree bin path (NO SYMLINKS!)\n\t */\n\tprivate async runCLITool(\n\t\tworktreePath: string,\n\t\tbinEntries: Record<string, string>,\n\t\targs: string[]\n\t): Promise<void> {\n\t\t// Validate binEntries exist\n\t\tif (Object.keys(binEntries).length === 0) {\n\t\t\tthrow new Error('No bin entries found in package.json')\n\t\t}\n\n\t\t// Get first bin entry (deterministic)\n\t\tconst firstEntry = Object.entries(binEntries)[0]\n\t\tif (!firstEntry) {\n\t\t\tthrow new Error('No bin entries found in package.json')\n\t\t}\n\t\tconst [binName, binPath] = firstEntry\n\t\tlogger.debug(`Using bin entry: ${binName} -> ${binPath}`)\n\n\t\t// CRITICAL: Construct absolute path (NO SYMLINKS!)\n\t\tconst binFilePath = path.resolve(worktreePath, binPath)\n\t\tlogger.debug(`Resolved bin file path: ${binFilePath}`)\n\n\t\t// Verify file exists\n\t\tif (!(await fs.pathExists(binFilePath))) {\n\t\t\tthrow new Error(\n\t\t\t\t`CLI executable not found: ${binFilePath}\\n` +\n\t\t\t\t\t`Make sure the project is built (run 'il start' first)`\n\t\t\t)\n\t\t}\n\n\t\t// Execute with Node.js\n\t\tlogger.info(`Running CLI: node ${binFilePath} ${args.join(' ')}`)\n\t\tawait execa('node', [binFilePath, ...args], {\n\t\t\tstdio: 'inherit', // Allow interactive CLIs (prompts, colors, etc.)\n\t\t\tcwd: worktreePath, // Execute in worktree context\n\t\t\tenv: process.env, // Inherit environment\n\t\t})\n\t}\n\n\t/**\n\t * Open web browser with workspace URL\n\t * Auto-starts dev server if not already running\n\t */\n\tprivate async openWebBrowser(worktreePath: string): Promise<void> {\n\t\tconst port = await this.getWorkspacePort(worktreePath)\n\n\t\t// Ensure dev server is running on the port\n\t\tconst serverReady = await this.devServerManager.ensureServerRunning(\n\t\t\tworktreePath,\n\t\t\tport\n\t\t)\n\n\t\tif (!serverReady) {\n\t\t\tlogger.warn(\n\t\t\t\t`Dev server failed to start on port ${port}. Opening browser anyway...`\n\t\t\t)\n\t\t}\n\n\t\t// Construct URL and open browser\n\t\tconst url = `http://localhost:${port}`\n\t\tlogger.info(`Opening browser: ${url}`)\n\t\tawait openBrowser(url)\n\t\tlogger.success('Browser opened')\n\t}\n\n\t/**\n\t * Get port for workspace - reads from .env or calculates based on workspace type\n\t */\n\tprivate async getWorkspacePort(worktreePath: string): Promise<number> {\n\t\t// Load base port from settings with CLI overrides\n\t\tconst cliOverrides = extractSettingsOverrides()\n\t\tconst settings = await this.settingsManager.loadSettings(undefined, cliOverrides)\n\t\tconst basePort = settings.capabilities?.web?.basePort ?? 3000\n\n\t\t// Try to read PORT from .env file (as override)\n\t\tconst envPath = path.join(worktreePath, '.env')\n\t\tif (await fs.pathExists(envPath)) {\n\t\t\tconst envContent = await fs.readFile(envPath, 'utf8')\n\t\t\tconst envMap = parseEnvFile(envContent)\n\t\t\tconst port = extractPort(envMap)\n\n\t\t\tif (port) {\n\t\t\t\tlogger.debug(`Using PORT from .env: ${port}`)\n\t\t\t\treturn port\n\t\t\t}\n\t\t}\n\n\t\t// PORT not in .env, calculate based on workspace identifier\n\t\tlogger.debug('PORT not found in .env, calculating from workspace identifier')\n\n\t\t// Get worktree to determine type\n\t\tconst worktrees = await this.gitWorktreeManager.listWorktrees()\n\t\tconst worktree = worktrees.find(wt => wt.path === worktreePath)\n\n\t\tif (!worktree) {\n\t\t\tthrow new Error(`Could not find worktree for path: ${worktreePath}`)\n\t\t}\n\n\t\t// Extract identifier from worktree path/branch\n\t\tconst dirName = path.basename(worktreePath)\n\n\t\t// Check for PR pattern: _pr_N\n\t\tconst prPattern = /_pr_(\\d+)$/\n\t\tconst prMatch = dirName.match(prPattern)\n\t\tif (prMatch?.[1]) {\n\t\t\tconst prNumber = parseInt(prMatch[1], 10)\n\t\t\tconst port = basePort + prNumber\n\t\t\tlogger.debug(`Calculated PORT for PR #${prNumber}: ${port}`)\n\t\t\treturn port\n\t\t}\n\n\t\t// Check for issue pattern: issue-N\n\t\tconst issuePattern = /issue-(\\d+)/\n\t\tconst issueMatch = dirName.match(issuePattern) ?? worktree.branch.match(issuePattern)\n\t\tif (issueMatch?.[1]) {\n\t\t\tconst issueNumber = parseInt(issueMatch[1], 10)\n\t\t\tconst port = basePort + issueNumber\n\t\t\tlogger.debug(`Calculated PORT for issue #${issueNumber}: ${port}`)\n\t\t\treturn port\n\t\t}\n\n\t\t// Branch-based workspace - use deterministic hash\n\t\tconst port = calculatePortForBranch(worktree.branch, basePort)\n\t\tlogger.debug(`Calculated PORT for branch \"${worktree.branch}\": ${port}`)\n\t\treturn port\n\t}\n}\n"],"mappings":"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","names":["port"]}
|
|
1
|
+
{"version":3,"sources":["../src/commands/run.ts"],"sourcesContent":["import path from 'path'\nimport fs from 'fs-extra'\nimport { execa } from 'execa'\nimport { GitWorktreeManager } from '../lib/GitWorktreeManager.js'\nimport { ProjectCapabilityDetector } from '../lib/ProjectCapabilityDetector.js'\nimport { DevServerManager } from '../lib/DevServerManager.js'\nimport { SettingsManager } from '../lib/SettingsManager.js'\nimport { IdentifierParser } from '../utils/IdentifierParser.js'\nimport { openBrowser } from '../utils/browser.js'\nimport { parseEnvFile, extractPort } from '../utils/env.js'\nimport { calculatePortForBranch } from '../utils/port.js'\nimport { logger } from '../utils/logger.js'\nimport { extractSettingsOverrides } from '../utils/cli-overrides.js'\nimport type { GitWorktree } from '../types/worktree.js'\n\nexport interface RunCommandInput {\n\tidentifier?: string\n\targs?: string[]\n}\n\ninterface ParsedRunInput {\n\ttype: 'issue' | 'pr' | 'branch'\n\tnumber?: number // For issues and PRs\n\tbranchName?: string // For branches\n\toriginalInput: string\n\tautoDetected: boolean\n}\n\n/**\n * RunCommand - Runs CLI tool or opens workspace in browser\n * Priority: CLI first, Web fallback\n */\nexport class RunCommand {\n\tconstructor(\n\t\tprivate gitWorktreeManager = new GitWorktreeManager(),\n\t\tprivate capabilityDetector = new ProjectCapabilityDetector(),\n\t\tprivate identifierParser = new IdentifierParser(new GitWorktreeManager()),\n\t\tprivate devServerManager = new DevServerManager(),\n\t\tprivate settingsManager = new SettingsManager()\n\t) {}\n\n\tasync execute(input: RunCommandInput): Promise<void> {\n\t\t// 1. Parse or auto-detect identifier\n\t\tconst parsed = input.identifier\n\t\t\t? await this.parseExplicitInput(input.identifier)\n\t\t\t: await this.autoDetectFromCurrentDirectory()\n\n\t\tlogger.debug(`Parsed input: ${JSON.stringify(parsed)}`)\n\n\t\t// 2. Find worktree path based on identifier\n\t\tconst worktree = await this.findWorktreeForIdentifier(parsed)\n\n\t\tlogger.info(`Found worktree at: ${worktree.path}`)\n\n\t\t// 3. Detect project capabilities\n\t\tconst { capabilities, binEntries } =\n\t\t\tawait this.capabilityDetector.detectCapabilities(worktree.path)\n\n\t\tlogger.debug(`Detected capabilities: ${capabilities.join(', ')}`)\n\n\t\t// 4. Execute based on capabilities (CLI first, web fallback)\n\t\tif (capabilities.includes('cli')) {\n\t\t\tawait this.runCLITool(worktree.path, binEntries, input.args ?? [])\n\t\t} else if (capabilities.includes('web')) {\n\t\t\tawait this.openWebBrowser(worktree.path)\n\t\t} else {\n\t\t\tthrow new Error(\n\t\t\t\t`No CLI or web capabilities detected for workspace at ${worktree.path}`\n\t\t\t)\n\t\t}\n\t}\n\n\t/**\n\t * Parse explicit identifier input\n\t */\n\tprivate async parseExplicitInput(identifier: string): Promise<ParsedRunInput> {\n\t\tconst parsed = await this.identifierParser.parseForPatternDetection(identifier)\n\n\t\t// Description type should never reach run command (converted in start)\n\t\tif (parsed.type === 'description') {\n\t\t\tthrow new Error('Description input type is not supported in run command')\n\t\t}\n\n\t\tconst result: ParsedRunInput = {\n\t\t\ttype: parsed.type,\n\t\t\toriginalInput: parsed.originalInput,\n\t\t\tautoDetected: false,\n\t\t}\n\n\t\tif (parsed.number !== undefined) {\n\t\t\tresult.number = parsed.number\n\t\t}\n\t\tif (parsed.branchName !== undefined) {\n\t\t\tresult.branchName = parsed.branchName\n\t\t}\n\n\t\treturn result\n\t}\n\n\t/**\n\t * Auto-detect identifier from current directory\n\t * Same logic as FinishCommand.autoDetectFromCurrentDirectory()\n\t */\n\tprivate async autoDetectFromCurrentDirectory(): Promise<ParsedRunInput> {\n\t\tconst currentDir = path.basename(process.cwd())\n\n\t\t// Check for PR worktree pattern: _pr_N suffix\n\t\tconst prPattern = /_pr_(\\d+)$/\n\t\tconst prMatch = currentDir.match(prPattern)\n\n\t\tif (prMatch?.[1]) {\n\t\t\tconst prNumber = parseInt(prMatch[1], 10)\n\t\t\tlogger.debug(`Auto-detected PR #${prNumber} from directory: ${currentDir}`)\n\t\t\treturn {\n\t\t\t\ttype: 'pr',\n\t\t\t\tnumber: prNumber,\n\t\t\t\toriginalInput: currentDir,\n\t\t\t\tautoDetected: true,\n\t\t\t}\n\t\t}\n\n\t\t// Check for issue pattern in directory\n\t\tconst issuePattern = /issue-(\\d+)/\n\t\tconst issueMatch = currentDir.match(issuePattern)\n\n\t\tif (issueMatch?.[1]) {\n\t\t\tconst issueNumber = parseInt(issueMatch[1], 10)\n\t\t\tlogger.debug(`Auto-detected issue #${issueNumber} from directory: ${currentDir}`)\n\t\t\treturn {\n\t\t\t\ttype: 'issue',\n\t\t\t\tnumber: issueNumber,\n\t\t\t\toriginalInput: currentDir,\n\t\t\t\tautoDetected: true,\n\t\t\t}\n\t\t}\n\n\t\t// Fallback: get current branch name\n\t\tconst repoInfo = await this.gitWorktreeManager.getRepoInfo()\n\t\tconst currentBranch = repoInfo.currentBranch\n\n\t\tif (!currentBranch) {\n\t\t\tthrow new Error(\n\t\t\t\t'Could not auto-detect identifier. Please provide an issue number, PR number, or branch name.\\n' +\n\t\t\t\t\t'Expected directory pattern: feat/issue-XX-description OR worktree with _pr_N suffix'\n\t\t\t)\n\t\t}\n\n\t\t// Try to extract issue from branch name\n\t\tconst branchIssueMatch = currentBranch.match(issuePattern)\n\t\tif (branchIssueMatch?.[1]) {\n\t\t\tconst issueNumber = parseInt(branchIssueMatch[1], 10)\n\t\t\tlogger.debug(`Auto-detected issue #${issueNumber} from branch: ${currentBranch}`)\n\t\t\treturn {\n\t\t\t\ttype: 'issue',\n\t\t\t\tnumber: issueNumber,\n\t\t\t\toriginalInput: currentBranch,\n\t\t\t\tautoDetected: true,\n\t\t\t}\n\t\t}\n\n\t\t// Last resort: use branch name\n\t\treturn {\n\t\t\ttype: 'branch',\n\t\t\tbranchName: currentBranch,\n\t\t\toriginalInput: currentBranch,\n\t\t\tautoDetected: true,\n\t\t}\n\t}\n\n\t/**\n\t * Find worktree for the given identifier\n\t */\n\tprivate async findWorktreeForIdentifier(parsed: ParsedRunInput): Promise<GitWorktree> {\n\t\tlet worktree: GitWorktree | null = null\n\n\t\tif (parsed.type === 'issue' && parsed.number !== undefined) {\n\t\t\tworktree = await this.gitWorktreeManager.findWorktreeForIssue(parsed.number)\n\t\t} else if (parsed.type === 'pr' && parsed.number !== undefined) {\n\t\t\t// Pass empty string for branch name since we don't know it yet\n\t\t\tworktree = await this.gitWorktreeManager.findWorktreeForPR(parsed.number, '')\n\t\t} else if (parsed.type === 'branch' && parsed.branchName) {\n\t\t\tworktree = await this.gitWorktreeManager.findWorktreeForBranch(\n\t\t\t\tparsed.branchName\n\t\t\t)\n\t\t}\n\n\t\tif (!worktree) {\n\t\t\tthrow new Error(\n\t\t\t\t`No worktree found for ${this.formatParsedInput(parsed)}. ` +\n\t\t\t\t\t`Run 'il start ${parsed.originalInput}' to create one.`\n\t\t\t)\n\t\t}\n\n\t\treturn worktree\n\t}\n\n\t/**\n\t * Format parsed input for display\n\t */\n\tprivate formatParsedInput(parsed: ParsedRunInput): string {\n\t\tconst autoLabel = parsed.autoDetected ? ' (auto-detected)' : ''\n\n\t\tif (parsed.type === 'issue') {\n\t\t\treturn `issue #${parsed.number}${autoLabel}`\n\t\t}\n\t\tif (parsed.type === 'pr') {\n\t\t\treturn `PR #${parsed.number}${autoLabel}`\n\t\t}\n\t\treturn `branch \"${parsed.branchName}\"${autoLabel}`\n\t}\n\n\t/**\n\t * Run CLI tool directly from worktree bin path (NO SYMLINKS!)\n\t */\n\tprivate async runCLITool(\n\t\tworktreePath: string,\n\t\tbinEntries: Record<string, string>,\n\t\targs: string[]\n\t): Promise<void> {\n\t\t// Validate binEntries exist\n\t\tif (Object.keys(binEntries).length === 0) {\n\t\t\tthrow new Error('No bin entries found in package.json')\n\t\t}\n\n\t\t// Get first bin entry (deterministic)\n\t\tconst firstEntry = Object.entries(binEntries)[0]\n\t\tif (!firstEntry) {\n\t\t\tthrow new Error('No bin entries found in package.json')\n\t\t}\n\t\tconst [binName, binPath] = firstEntry\n\t\tlogger.debug(`Using bin entry: ${binName} -> ${binPath}`)\n\n\t\t// CRITICAL: Construct absolute path (NO SYMLINKS!)\n\t\tconst binFilePath = path.resolve(worktreePath, binPath)\n\t\tlogger.debug(`Resolved bin file path: ${binFilePath}`)\n\n\t\t// Verify file exists\n\t\tif (!(await fs.pathExists(binFilePath))) {\n\t\t\tthrow new Error(\n\t\t\t\t`CLI executable not found: ${binFilePath}\\n` +\n\t\t\t\t\t`Make sure the project is built (run 'il start' first)`\n\t\t\t)\n\t\t}\n\n\t\t// Execute with Node.js\n\t\tlogger.info(`Running CLI: node ${binFilePath} ${args.join(' ')}`)\n\t\tawait execa('node', [binFilePath, ...args], {\n\t\t\tstdio: 'inherit', // Allow interactive CLIs (prompts, colors, etc.)\n\t\t\tcwd: worktreePath, // Execute in worktree context\n\t\t\tenv: process.env, // Inherit environment\n\t\t})\n\t}\n\n\t/**\n\t * Open web browser with workspace URL\n\t * Auto-starts dev server if not already running\n\t */\n\tprivate async openWebBrowser(worktreePath: string): Promise<void> {\n\t\tconst port = await this.getWorkspacePort(worktreePath)\n\n\t\t// Ensure dev server is running on the port\n\t\tconst serverReady = await this.devServerManager.ensureServerRunning(\n\t\t\tworktreePath,\n\t\t\tport\n\t\t)\n\n\t\tif (!serverReady) {\n\t\t\tlogger.warn(\n\t\t\t\t`Dev server failed to start on port ${port}. Opening browser anyway...`\n\t\t\t)\n\t\t}\n\n\t\t// Construct URL and open browser\n\t\tconst url = `http://localhost:${port}`\n\t\tlogger.info(`Opening browser: ${url}`)\n\t\tawait openBrowser(url)\n\t\tlogger.success('Browser opened')\n\t}\n\n\t/**\n\t * Get port for workspace - reads from .env or calculates based on workspace type\n\t */\n\tprivate async getWorkspacePort(worktreePath: string): Promise<number> {\n\t\t// Load base port from settings with CLI overrides\n\t\tconst cliOverrides = extractSettingsOverrides()\n\t\tconst settings = await this.settingsManager.loadSettings(undefined, cliOverrides)\n\t\tconst basePort = settings.capabilities?.web?.basePort ?? 3000\n\n\t\t// Try to read PORT from .env file (as override)\n\t\tconst envPath = path.join(worktreePath, '.env')\n\t\tif (await fs.pathExists(envPath)) {\n\t\t\tconst envContent = await fs.readFile(envPath, 'utf8')\n\t\t\tconst envMap = parseEnvFile(envContent)\n\t\t\tconst port = extractPort(envMap)\n\n\t\t\tif (port) {\n\t\t\t\tlogger.debug(`Using PORT from .env: ${port}`)\n\t\t\t\treturn port\n\t\t\t}\n\t\t}\n\n\t\t// PORT not in .env, calculate based on workspace identifier\n\t\tlogger.debug('PORT not found in .env, calculating from workspace identifier')\n\n\t\t// Get worktree to determine type\n\t\tconst worktrees = await this.gitWorktreeManager.listWorktrees()\n\t\tconst worktree = worktrees.find(wt => wt.path === worktreePath)\n\n\t\tif (!worktree) {\n\t\t\tthrow new Error(`Could not find worktree for path: ${worktreePath}`)\n\t\t}\n\n\t\t// Extract identifier from worktree path/branch\n\t\tconst dirName = path.basename(worktreePath)\n\n\t\t// Check for PR pattern: _pr_N\n\t\tconst prPattern = /_pr_(\\d+)$/\n\t\tconst prMatch = dirName.match(prPattern)\n\t\tif (prMatch?.[1]) {\n\t\t\tconst prNumber = parseInt(prMatch[1], 10)\n\t\t\tconst port = basePort + prNumber\n\t\t\tlogger.debug(`Calculated PORT for PR #${prNumber}: ${port}`)\n\t\t\treturn port\n\t\t}\n\n\t\t// Check for issue pattern: issue-N\n\t\tconst issuePattern = /issue-(\\d+)/\n\t\tconst issueMatch = dirName.match(issuePattern) ?? worktree.branch.match(issuePattern)\n\t\tif (issueMatch?.[1]) {\n\t\t\tconst issueNumber = parseInt(issueMatch[1], 10)\n\t\t\tconst port = basePort + issueNumber\n\t\t\tlogger.debug(`Calculated PORT for issue #${issueNumber}: ${port}`)\n\t\t\treturn port\n\t\t}\n\n\t\t// Branch-based workspace - use deterministic hash\n\t\tconst port = calculatePortForBranch(worktree.branch, basePort)\n\t\tlogger.debug(`Calculated PORT for branch \"${worktree.branch}\": ${port}`)\n\t\treturn port\n\t}\n}\n"],"mappings":"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","names":["port"]}
|
|
@@ -179,7 +179,7 @@
|
|
|
179
179
|
"type": "null"
|
|
180
180
|
}
|
|
181
181
|
],
|
|
182
|
-
"description": "Per-agent configuration overrides"
|
|
182
|
+
"description": "Per-agent configuration overrides. Available agents: iloom-issue-analyzer (analyzes issues), iloom-issue-planner (creates implementation plans), iloom-issue-analyze-and-plan (combined analysis and planning), iloom-issue-complexity-evaluator (evaluates complexity), iloom-issue-enhancer (enhances issue descriptions), iloom-issue-implementer (implements code changes), iloom-issue-reviewer (reviews code changes against requirements)"
|
|
183
183
|
},
|
|
184
184
|
"capabilities": {
|
|
185
185
|
"type": "object",
|
|
@@ -212,6 +212,56 @@
|
|
|
212
212
|
},
|
|
213
213
|
"additionalProperties": false,
|
|
214
214
|
"description": "Project capability configurations"
|
|
215
|
+
},
|
|
216
|
+
"databaseProviders": {
|
|
217
|
+
"type": "object",
|
|
218
|
+
"properties": {
|
|
219
|
+
"neon": {
|
|
220
|
+
"type": "object",
|
|
221
|
+
"properties": {
|
|
222
|
+
"projectId": {
|
|
223
|
+
"type": "string",
|
|
224
|
+
"minLength": 1,
|
|
225
|
+
"pattern": "^[a-zA-Z0-9-]+$",
|
|
226
|
+
"description": "Neon project ID found in your project URL (e.g., \"fantastic-fox-3566354\")"
|
|
227
|
+
},
|
|
228
|
+
"parentBranch": {
|
|
229
|
+
"type": "string",
|
|
230
|
+
"minLength": 1,
|
|
231
|
+
"description": "Branch from which new database branches are created"
|
|
232
|
+
}
|
|
233
|
+
},
|
|
234
|
+
"required": [
|
|
235
|
+
"projectId",
|
|
236
|
+
"parentBranch"
|
|
237
|
+
],
|
|
238
|
+
"additionalProperties": false,
|
|
239
|
+
"description": "Neon database configuration. Requires Neon CLI installed and authenticated for database branching."
|
|
240
|
+
}
|
|
241
|
+
},
|
|
242
|
+
"additionalProperties": false,
|
|
243
|
+
"description": "Database provider configurations"
|
|
244
|
+
},
|
|
245
|
+
"issueManagement": {
|
|
246
|
+
"type": "object",
|
|
247
|
+
"properties": {
|
|
248
|
+
"github": {
|
|
249
|
+
"type": "object",
|
|
250
|
+
"properties": {
|
|
251
|
+
"remote": {
|
|
252
|
+
"type": "string",
|
|
253
|
+
"minLength": 1,
|
|
254
|
+
"description": "Git remote name to use for GitHub operations"
|
|
255
|
+
}
|
|
256
|
+
},
|
|
257
|
+
"required": [
|
|
258
|
+
"remote"
|
|
259
|
+
],
|
|
260
|
+
"additionalProperties": false
|
|
261
|
+
}
|
|
262
|
+
},
|
|
263
|
+
"additionalProperties": false,
|
|
264
|
+
"description": "Issue management configuration"
|
|
215
265
|
}
|
|
216
266
|
},
|
|
217
267
|
"additionalProperties": false
|
|
@@ -1,30 +1,39 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
extractSettingsOverrides
|
|
4
|
-
} from "./chunk-GYCR2LOU.js";
|
|
5
|
-
import {
|
|
6
|
-
IssueEnhancementService
|
|
7
|
-
} from "./chunk-PR7FKQBG.js";
|
|
8
|
-
import {
|
|
9
|
-
AgentManager
|
|
10
|
-
} from "./chunk-OC4H6HJD.js";
|
|
11
|
-
import "./chunk-YETJNRQM.js";
|
|
12
2
|
import {
|
|
13
3
|
CLIIsolationManager,
|
|
14
4
|
DatabaseManager,
|
|
15
5
|
EnvironmentManager
|
|
16
|
-
} from "./chunk-
|
|
17
|
-
import
|
|
6
|
+
} from "./chunk-H5LDRGVK.js";
|
|
7
|
+
import {
|
|
8
|
+
loadEnvIntoProcess
|
|
9
|
+
} from "./chunk-ZMNQBJUI.js";
|
|
18
10
|
import {
|
|
19
11
|
installDependencies
|
|
20
12
|
} from "./chunk-BLCTGFZN.js";
|
|
21
13
|
import {
|
|
22
|
-
|
|
23
|
-
} from "./chunk-
|
|
14
|
+
ClaudeContextManager
|
|
15
|
+
} from "./chunk-SLIMABFA.js";
|
|
16
|
+
import {
|
|
17
|
+
extractSettingsOverrides
|
|
18
|
+
} from "./chunk-GYCR2LOU.js";
|
|
19
|
+
import {
|
|
20
|
+
createNeonProviderFromSettings
|
|
21
|
+
} from "./chunk-LAPY6NAE.js";
|
|
24
22
|
import {
|
|
25
23
|
ProjectCapabilityDetector
|
|
26
24
|
} from "./chunk-CWR2SANQ.js";
|
|
27
25
|
import "./chunk-2ZPFJQ3B.js";
|
|
26
|
+
import {
|
|
27
|
+
IssueEnhancementService
|
|
28
|
+
} from "./chunk-PR7FKQBG.js";
|
|
29
|
+
import {
|
|
30
|
+
AgentManager
|
|
31
|
+
} from "./chunk-OC4H6HJD.js";
|
|
32
|
+
import "./chunk-YETJNRQM.js";
|
|
33
|
+
import {
|
|
34
|
+
getConfiguredRepoFromSettings,
|
|
35
|
+
hasMultipleRemotes
|
|
36
|
+
} from "./chunk-FXV24OYZ.js";
|
|
28
37
|
import {
|
|
29
38
|
calculateForegroundColor,
|
|
30
39
|
generateColorFromBranchName,
|
|
@@ -34,29 +43,23 @@ import {
|
|
|
34
43
|
} from "./chunk-ZZZWQGTS.js";
|
|
35
44
|
import {
|
|
36
45
|
GitHubService
|
|
37
|
-
} from "./chunk-
|
|
38
|
-
import "./chunk-
|
|
39
|
-
import
|
|
40
|
-
loadEnvIntoProcess
|
|
41
|
-
} from "./chunk-SJUQ2NDR.js";
|
|
42
|
-
import {
|
|
43
|
-
ClaudeContextManager
|
|
44
|
-
} from "./chunk-Y7SAGNUT.js";
|
|
45
|
-
import "./chunk-WKEWRSDB.js";
|
|
46
|
+
} from "./chunk-IIPTBZQW.js";
|
|
47
|
+
import "./chunk-DGEKUT7Q.js";
|
|
48
|
+
import "./chunk-HURVAQRK.js";
|
|
46
49
|
import "./chunk-PXZBAC2M.js";
|
|
47
|
-
import "./chunk-
|
|
50
|
+
import "./chunk-L4QGC27H.js";
|
|
48
51
|
import {
|
|
49
52
|
GitWorktreeManager
|
|
50
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-IO4WFTL2.js";
|
|
51
54
|
import {
|
|
52
55
|
SettingsManager
|
|
53
|
-
} from "./chunk-
|
|
56
|
+
} from "./chunk-VYQLLHZ7.js";
|
|
54
57
|
import {
|
|
55
58
|
branchExists,
|
|
56
59
|
ensureRepositoryHasCommits,
|
|
57
60
|
executeGitCommand,
|
|
58
61
|
findMainWorktreePathWithSettings
|
|
59
|
-
} from "./chunk-
|
|
62
|
+
} from "./chunk-KOCQAD2E.js";
|
|
60
63
|
import "./chunk-JNKJ7NJV.js";
|
|
61
64
|
import {
|
|
62
65
|
logger
|
|
@@ -308,8 +311,8 @@ var LoomManager = class {
|
|
|
308
311
|
const setArguments = (_j = input.options) == null ? void 0 : _j.setArguments;
|
|
309
312
|
const executablePath = (_k = input.options) == null ? void 0 : _k.executablePath;
|
|
310
313
|
if (enableClaude || enableCode || enableDevServer || enableTerminal) {
|
|
311
|
-
const { LoomLauncher } = await import("./LoomLauncher-
|
|
312
|
-
const { ClaudeContextManager: ClaudeContextManager2 } = await import("./ClaudeContextManager-
|
|
314
|
+
const { LoomLauncher } = await import("./LoomLauncher-FB2MV2ZI.js");
|
|
315
|
+
const { ClaudeContextManager: ClaudeContextManager2 } = await import("./ClaudeContextManager-LD3VB6EM.js");
|
|
313
316
|
const claudeContext = new ClaudeContextManager2(void 0, void 0, this.settings);
|
|
314
317
|
const launcher = new LoomLauncher(claudeContext);
|
|
315
318
|
await launcher.launchLoom({
|
|
@@ -651,8 +654,8 @@ var LoomManager = class {
|
|
|
651
654
|
const executablePath = (_i = input.options) == null ? void 0 : _i.executablePath;
|
|
652
655
|
if (enableClaude || enableCode || enableDevServer || enableTerminal) {
|
|
653
656
|
logger.info("Launching workspace components...");
|
|
654
|
-
const { LoomLauncher } = await import("./LoomLauncher-
|
|
655
|
-
const { ClaudeContextManager: ClaudeContextManager2 } = await import("./ClaudeContextManager-
|
|
657
|
+
const { LoomLauncher } = await import("./LoomLauncher-FB2MV2ZI.js");
|
|
658
|
+
const { ClaudeContextManager: ClaudeContextManager2 } = await import("./ClaudeContextManager-LD3VB6EM.js");
|
|
656
659
|
const claudeContext = new ClaudeContextManager2(void 0, void 0, this.settings);
|
|
657
660
|
const launcher = new LoomLauncher(claudeContext);
|
|
658
661
|
await launcher.launchLoom({
|
|
@@ -725,7 +728,7 @@ var StartCommand = class {
|
|
|
725
728
|
* Uses lazy initialization to ensure we have the correct path
|
|
726
729
|
*/
|
|
727
730
|
async initializeLoomManager() {
|
|
728
|
-
var _a, _b
|
|
731
|
+
var _a, _b;
|
|
729
732
|
if (this.loomManager) {
|
|
730
733
|
return this.loomManager;
|
|
731
734
|
}
|
|
@@ -734,20 +737,10 @@ var StartCommand = class {
|
|
|
734
737
|
return this.loomManager;
|
|
735
738
|
}
|
|
736
739
|
const mainWorktreePath = await findMainWorktreePathWithSettings();
|
|
737
|
-
const environmentManager = new EnvironmentManager();
|
|
738
|
-
logger.debug("Environment variables for Neon:", {
|
|
739
|
-
NEON_PROJECT_ID: process.env.NEON_PROJECT_ID,
|
|
740
|
-
NEON_PARENT_BRANCH: process.env.NEON_PARENT_BRANCH,
|
|
741
|
-
hasNeonProjectId: !!process.env.NEON_PROJECT_ID,
|
|
742
|
-
hasNeonParentBranch: !!process.env.NEON_PARENT_BRANCH,
|
|
743
|
-
neonProjectIdLength: ((_a = process.env.NEON_PROJECT_ID) == null ? void 0 : _a.length) ?? 0
|
|
744
|
-
});
|
|
745
|
-
const neonProvider = new NeonProvider({
|
|
746
|
-
projectId: process.env.NEON_PROJECT_ID ?? "",
|
|
747
|
-
parentBranch: process.env.NEON_PARENT_BRANCH ?? ""
|
|
748
|
-
});
|
|
749
740
|
const settings = await this.settingsManager.loadSettings();
|
|
750
|
-
const
|
|
741
|
+
const environmentManager = new EnvironmentManager();
|
|
742
|
+
const neonProvider = createNeonProviderFromSettings(settings);
|
|
743
|
+
const databaseUrlEnvVarName = ((_b = (_a = settings.capabilities) == null ? void 0 : _a.database) == null ? void 0 : _b.databaseUrlEnvVarName) ?? "DATABASE_URL";
|
|
751
744
|
const databaseManager = new DatabaseManager(neonProvider, environmentManager, databaseUrlEnvVarName);
|
|
752
745
|
this.loomManager = new LoomManager(
|
|
753
746
|
new GitWorktreeManager(mainWorktreePath),
|
|
@@ -770,9 +763,16 @@ var StartCommand = class {
|
|
|
770
763
|
async execute(input) {
|
|
771
764
|
var _a, _b, _c;
|
|
772
765
|
try {
|
|
766
|
+
const initialSettings = await this.settingsManager.loadSettings();
|
|
767
|
+
let repo;
|
|
768
|
+
const multipleRemotes = await hasMultipleRemotes();
|
|
769
|
+
if (multipleRemotes) {
|
|
770
|
+
repo = await getConfiguredRepoFromSettings(initialSettings);
|
|
771
|
+
logger.info(`Using GitHub repository: ${repo}`);
|
|
772
|
+
}
|
|
773
773
|
const loomManager = await this.initializeLoomManager();
|
|
774
|
-
const parsed = await this.parseInput(input.identifier);
|
|
775
|
-
await this.validateInput(parsed);
|
|
774
|
+
const parsed = await this.parseInput(input.identifier, repo);
|
|
775
|
+
await this.validateInput(parsed, repo);
|
|
776
776
|
if (parsed.type === "description") {
|
|
777
777
|
const issueNumber = await this.enhanceAndCreateIssue(parsed.originalInput);
|
|
778
778
|
parsed.type = "issue";
|
|
@@ -841,7 +841,7 @@ var StartCommand = class {
|
|
|
841
841
|
/**
|
|
842
842
|
* Parse input to determine type and extract relevant data
|
|
843
843
|
*/
|
|
844
|
-
async parseInput(identifier) {
|
|
844
|
+
async parseInput(identifier, repo) {
|
|
845
845
|
const trimmedIdentifier = identifier.trim();
|
|
846
846
|
if (!trimmedIdentifier) {
|
|
847
847
|
throw new Error("Missing required argument: identifier");
|
|
@@ -867,7 +867,8 @@ var StartCommand = class {
|
|
|
867
867
|
if (numericMatch == null ? void 0 : numericMatch[1]) {
|
|
868
868
|
const number = parseInt(numericMatch[1], 10);
|
|
869
869
|
const detection = await this.gitHubService.detectInputType(
|
|
870
|
-
trimmedIdentifier
|
|
870
|
+
trimmedIdentifier,
|
|
871
|
+
repo
|
|
871
872
|
);
|
|
872
873
|
if (detection.type === "pr") {
|
|
873
874
|
return {
|
|
@@ -894,13 +895,13 @@ var StartCommand = class {
|
|
|
894
895
|
/**
|
|
895
896
|
* Validate the parsed input based on its type
|
|
896
897
|
*/
|
|
897
|
-
async validateInput(parsed) {
|
|
898
|
+
async validateInput(parsed, repo) {
|
|
898
899
|
switch (parsed.type) {
|
|
899
900
|
case "pr": {
|
|
900
901
|
if (!parsed.number) {
|
|
901
902
|
throw new Error("Invalid PR number");
|
|
902
903
|
}
|
|
903
|
-
const pr = await this.gitHubService.fetchPR(parsed.number);
|
|
904
|
+
const pr = await this.gitHubService.fetchPR(parsed.number, repo);
|
|
904
905
|
await this.gitHubService.validatePRState(pr);
|
|
905
906
|
logger.debug(`Validated PR #${parsed.number}`);
|
|
906
907
|
break;
|
|
@@ -909,7 +910,7 @@ var StartCommand = class {
|
|
|
909
910
|
if (!parsed.number) {
|
|
910
911
|
throw new Error("Invalid issue number");
|
|
911
912
|
}
|
|
912
|
-
const issue = await this.gitHubService.fetchIssue(parsed.number);
|
|
913
|
+
const issue = await this.gitHubService.fetchIssue(parsed.number, repo);
|
|
913
914
|
await this.gitHubService.validateIssueState(issue);
|
|
914
915
|
logger.debug(`Validated issue #${parsed.number}`);
|
|
915
916
|
break;
|
|
@@ -979,4 +980,4 @@ var StartCommand = class {
|
|
|
979
980
|
export {
|
|
980
981
|
StartCommand
|
|
981
982
|
};
|
|
982
|
-
//# sourceMappingURL=start-
|
|
983
|
+
//# sourceMappingURL=start-2NEZU7SE.js.map
|