@iloom/cli 0.5.0 → 0.5.2
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/dist/{BranchNamingService-GCCWB3LK.js → BranchNamingService-B5PVRR7F.js} +4 -4
- package/dist/ClaudeContextManager-PQ46VILL.js +14 -0
- package/dist/ClaudeService-6OMO552H.js +13 -0
- package/dist/GitHubService-S2OGUTDR.js +12 -0
- package/dist/{LoomLauncher-4UG2E4CD.js → LoomLauncher-ZHDTPKED.js} +15 -79
- package/dist/LoomLauncher-ZHDTPKED.js.map +1 -0
- package/dist/MetadataManager-DFI73J3G.js +10 -0
- package/dist/PRManager-OCSB2HPT.js +14 -0
- package/dist/PromptTemplateManager-5GNF7FCP.js +9 -0
- package/dist/{SettingsManager-XPR4TEQL.js → SettingsManager-CNYBGXDT.js} +3 -3
- package/dist/SettingsMigrationManager-KZKDG66H.js +10 -0
- package/dist/{chunk-OEGECBFS.js → chunk-3PT7RKL5.js} +4 -4
- package/dist/{chunk-WUQQNE63.js → chunk-433MOLAU.js} +44 -7
- package/dist/chunk-433MOLAU.js.map +1 -0
- package/dist/{chunk-LN4H3A6A.js → chunk-53OMUNUN.js} +5 -5
- package/dist/{chunk-THF25ICZ.js → chunk-5F6IWWRS.js} +2 -2
- package/dist/{chunk-P2ZQ5LKB.js → chunk-5IWU3HXE.js} +5 -5
- package/dist/{chunk-QIUJPPJQ.js → chunk-5TXLVEXT.js} +3 -3
- package/dist/{chunk-RFUOIUQF.js → chunk-66BMJ25W.js} +13 -7
- package/dist/chunk-66BMJ25W.js.map +1 -0
- package/dist/{chunk-6UIGZD2N.js → chunk-6MLEBAYZ.js} +2 -2
- package/dist/{chunk-VTXCGKV5.js → chunk-7HIRPCKU.js} +14 -6
- package/dist/chunk-7HIRPCKU.js.map +1 -0
- package/dist/{chunk-UNXRACJ7.js → chunk-7LSSNB7Y.js} +3 -3
- package/dist/{chunk-QHA67Q7A.js → chunk-7Q66W4OH.js} +2 -2
- package/dist/{chunk-RUC7OULH.js → chunk-AEIMYF4P.js} +6 -8
- package/dist/{chunk-RUC7OULH.js.map → chunk-AEIMYF4P.js.map} +1 -1
- package/dist/{chunk-MD6HA5IK.js → chunk-B2UO6EYE.js} +2 -2
- package/dist/{chunk-YZTDGPFB.js → chunk-CFUWQHCJ.js} +2 -2
- package/dist/{chunk-UYWAESOT.js → chunk-F2PWIRV4.js} +3 -3
- package/dist/{chunk-PSFVTBM7.js → chunk-FXDYIV3K.js} +2 -2
- package/dist/{chunk-CDQEK2WD.js → chunk-FXJKNVZW.js} +5 -5
- package/dist/{chunk-3CMGCRB5.js → chunk-HMMO2LDS.js} +3 -3
- package/dist/{chunk-OOU3DKNT.js → chunk-IDUICCZY.js} +2 -2
- package/dist/{chunk-HABINPX2.js → chunk-J7GHNTYK.js} +67 -11
- package/dist/chunk-J7GHNTYK.js.map +1 -0
- package/dist/{chunk-DKQ4SUII.js → chunk-K5G5SFWY.js} +2 -2
- package/dist/chunk-K5G5SFWY.js.map +1 -0
- package/dist/{chunk-KO2FOMHL.js → chunk-LT3SGBR7.js} +2 -2
- package/dist/{chunk-VBFDVGAE.js → chunk-LVLRMP7V.js} +2 -2
- package/dist/{chunk-RNZMHJK7.js → chunk-N4ZJVATC.js} +3 -3
- package/dist/chunk-NXMDEL3F.js +54 -0
- package/dist/chunk-NXMDEL3F.js.map +1 -0
- package/dist/chunk-O7VL5N6S.js +72 -0
- package/dist/chunk-O7VL5N6S.js.map +1 -0
- package/dist/{chunk-S65T4O6I.js → chunk-QPS6TZUW.js} +3 -3
- package/dist/{chunk-RJKMF6BC.js → chunk-SHVB3EFE.js} +3 -3
- package/dist/chunk-VT4PDUYT.js +578 -0
- package/dist/chunk-VT4PDUYT.js.map +1 -0
- package/dist/{chunk-4YTILIIH.js → chunk-VV66DH6T.js} +8 -8
- package/dist/{chunk-GVRO4PWE.js → chunk-XNNXAAZT.js} +6 -6
- package/dist/{chunk-AS2IRKLU.js → chunk-YU5HVI6B.js} +2 -2
- package/dist/{chunk-T5IIUG4Z.js → chunk-Z5BM4JWB.js} +25 -24
- package/dist/chunk-Z5BM4JWB.js.map +1 -0
- package/dist/{chunk-SJ2GZ6RF.js → chunk-ZX3GTM7O.js} +2 -2
- package/dist/{claude-ACVXNB6N.js → claude-H33OQMXO.js} +4 -6
- package/dist/{cleanup-MIDJVSIU.js → cleanup-Y5W3CNUV.js} +20 -22
- package/dist/{cleanup-MIDJVSIU.js.map → cleanup-Y5W3CNUV.js.map} +1 -1
- package/dist/cli.js +125 -81
- package/dist/cli.js.map +1 -1
- package/dist/{color-ZPIIUADB.js → color-4TJ4P5EY.js} +5 -3
- package/dist/{contribute-RS3DO3WP.js → contribute-K7UXBOML.js} +8 -8
- package/dist/{dev-server-ASH7HJVI.js → dev-server-HNBRWGCD.js} +11 -13
- package/dist/{dev-server-ASH7HJVI.js.map → dev-server-HNBRWGCD.js.map} +1 -1
- package/dist/{feedback-RVIGHBJG.js → feedback-567ZH2O7.js} +16 -14
- package/dist/{feedback-RVIGHBJG.js.map → feedback-567ZH2O7.js.map} +1 -1
- package/dist/{git-OQAPUPLP.js → git-OV6ADVO7.js} +6 -6
- package/dist/{ignite-XJALWFAT.js → ignite-3HB3ZBEW.js} +15 -17
- package/dist/{ignite-XJALWFAT.js.map → ignite-3HB3ZBEW.js.map} +1 -1
- package/dist/index.d.ts +54 -35
- package/dist/index.js +377 -276
- package/dist/index.js.map +1 -1
- package/dist/init-CMIRHFSR.js +19 -0
- package/dist/{installation-detector-6R6YOFVZ.js → installation-detector-VXZOCL6P.js} +3 -3
- package/dist/mcp/issue-management-server.js +62 -7
- package/dist/mcp/issue-management-server.js.map +1 -1
- package/dist/neon-helpers-3KBC4A3Y.js +11 -0
- package/dist/{open-KW4NTLXH.js → open-AXE225Z5.js} +11 -13
- package/dist/{open-KW4NTLXH.js.map → open-AXE225Z5.js.map} +1 -1
- package/dist/{projects-QEAEBAT2.js → projects-GVEMCN5R.js} +4 -4
- package/dist/{prompt-A7GGRHSY.js → prompt-3SAZYRUN.js} +3 -3
- package/dist/prompts/session-summary-prompt.txt +58 -4
- package/dist/{rebase-WZHHE5LU.js → rebase-6UIHMUWS.js} +9 -11
- package/dist/{rebase-WZHHE5LU.js.map → rebase-6UIHMUWS.js.map} +1 -1
- package/dist/{recap-33NPZ3ZO.js → recap-XTBNMEMO.js} +12 -19
- package/dist/recap-XTBNMEMO.js.map +1 -0
- package/dist/{remote-73TZ2ADI.js → remote-IJAMOEAP.js} +3 -3
- package/dist/{run-HRYQ7TR7.js → run-H375EYRB.js} +11 -13
- package/dist/{run-HRYQ7TR7.js.map → run-H375EYRB.js.map} +1 -1
- package/dist/{shell-JMU5XTHW.js → shell-33FJCWJQ.js} +9 -11
- package/dist/{shell-JMU5XTHW.js.map → shell-33FJCWJQ.js.map} +1 -1
- package/dist/{summary-4SSGGH7N.js → summary-JUMOCNLR.js} +14 -15
- package/dist/{summary-4SSGGH7N.js.map → summary-JUMOCNLR.js.map} +1 -1
- package/dist/{test-git-6SAIRBUD.js → test-git-CO3BA4BV.js} +6 -6
- package/dist/{test-prefix-RLVRK5ZD.js → test-prefix-HZYSDQYT.js} +6 -6
- package/dist/{test-tabs-3SCJWRKT.js → test-tabs-D3POYOJ5.js} +3 -6
- package/dist/{test-tabs-3SCJWRKT.js.map → test-tabs-D3POYOJ5.js.map} +1 -1
- package/dist/{test-webserver-VPNLAFZ3.js → test-webserver-YVQD42W6.js} +2 -2
- package/dist/{update-LETF5ASC.js → update-5NOHT4SG.js} +4 -4
- package/dist/{update-notifier-H55ZK7NU.js → update-notifier-ARA5SPUW.js} +3 -3
- package/package.json +1 -1
- package/dist/ClaudeContextManager-DQFKIMEP.js +0 -16
- package/dist/ClaudeService-CJS32WG2.js +0 -15
- package/dist/GitHubService-RPM27GWD.js +0 -12
- package/dist/LoomLauncher-4UG2E4CD.js.map +0 -1
- package/dist/MetadataManager-WXUVXKUS.js +0 -10
- package/dist/PRManager-7DSIMCAD.js +0 -16
- package/dist/PromptTemplateManager-72FEOGT6.js +0 -9
- package/dist/SettingsMigrationManager-EH3J2TCN.js +0 -10
- package/dist/chunk-DKQ4SUII.js.map +0 -1
- package/dist/chunk-HABINPX2.js.map +0 -1
- package/dist/chunk-RFUOIUQF.js.map +0 -1
- package/dist/chunk-T5IIUG4Z.js.map +0 -1
- package/dist/chunk-UYVWLISQ.js +0 -113
- package/dist/chunk-UYVWLISQ.js.map +0 -1
- package/dist/chunk-VAYGNQTE.js +0 -234
- package/dist/chunk-VAYGNQTE.js.map +0 -1
- package/dist/chunk-VTXCGKV5.js.map +0 -1
- package/dist/chunk-WUQQNE63.js.map +0 -1
- package/dist/chunk-Z5NXYJIG.js +0 -207
- package/dist/chunk-Z5NXYJIG.js.map +0 -1
- package/dist/init-F6PFMSU5.js +0 -21
- package/dist/neon-helpers-L5CXQ5CT.js +0 -11
- package/dist/recap-33NPZ3ZO.js.map +0 -1
- /package/dist/{BranchNamingService-GCCWB3LK.js.map → BranchNamingService-B5PVRR7F.js.map} +0 -0
- /package/dist/{ClaudeContextManager-DQFKIMEP.js.map → ClaudeContextManager-PQ46VILL.js.map} +0 -0
- /package/dist/{ClaudeService-CJS32WG2.js.map → ClaudeService-6OMO552H.js.map} +0 -0
- /package/dist/{GitHubService-RPM27GWD.js.map → GitHubService-S2OGUTDR.js.map} +0 -0
- /package/dist/{MetadataManager-WXUVXKUS.js.map → MetadataManager-DFI73J3G.js.map} +0 -0
- /package/dist/{PRManager-7DSIMCAD.js.map → PRManager-OCSB2HPT.js.map} +0 -0
- /package/dist/{PromptTemplateManager-72FEOGT6.js.map → PromptTemplateManager-5GNF7FCP.js.map} +0 -0
- /package/dist/{SettingsManager-XPR4TEQL.js.map → SettingsManager-CNYBGXDT.js.map} +0 -0
- /package/dist/{SettingsMigrationManager-EH3J2TCN.js.map → SettingsMigrationManager-KZKDG66H.js.map} +0 -0
- /package/dist/{chunk-OEGECBFS.js.map → chunk-3PT7RKL5.js.map} +0 -0
- /package/dist/{chunk-LN4H3A6A.js.map → chunk-53OMUNUN.js.map} +0 -0
- /package/dist/{chunk-THF25ICZ.js.map → chunk-5F6IWWRS.js.map} +0 -0
- /package/dist/{chunk-P2ZQ5LKB.js.map → chunk-5IWU3HXE.js.map} +0 -0
- /package/dist/{chunk-QIUJPPJQ.js.map → chunk-5TXLVEXT.js.map} +0 -0
- /package/dist/{chunk-6UIGZD2N.js.map → chunk-6MLEBAYZ.js.map} +0 -0
- /package/dist/{chunk-UNXRACJ7.js.map → chunk-7LSSNB7Y.js.map} +0 -0
- /package/dist/{chunk-QHA67Q7A.js.map → chunk-7Q66W4OH.js.map} +0 -0
- /package/dist/{chunk-MD6HA5IK.js.map → chunk-B2UO6EYE.js.map} +0 -0
- /package/dist/{chunk-YZTDGPFB.js.map → chunk-CFUWQHCJ.js.map} +0 -0
- /package/dist/{chunk-UYWAESOT.js.map → chunk-F2PWIRV4.js.map} +0 -0
- /package/dist/{chunk-PSFVTBM7.js.map → chunk-FXDYIV3K.js.map} +0 -0
- /package/dist/{chunk-CDQEK2WD.js.map → chunk-FXJKNVZW.js.map} +0 -0
- /package/dist/{chunk-3CMGCRB5.js.map → chunk-HMMO2LDS.js.map} +0 -0
- /package/dist/{chunk-OOU3DKNT.js.map → chunk-IDUICCZY.js.map} +0 -0
- /package/dist/{chunk-KO2FOMHL.js.map → chunk-LT3SGBR7.js.map} +0 -0
- /package/dist/{chunk-VBFDVGAE.js.map → chunk-LVLRMP7V.js.map} +0 -0
- /package/dist/{chunk-RNZMHJK7.js.map → chunk-N4ZJVATC.js.map} +0 -0
- /package/dist/{chunk-S65T4O6I.js.map → chunk-QPS6TZUW.js.map} +0 -0
- /package/dist/{chunk-RJKMF6BC.js.map → chunk-SHVB3EFE.js.map} +0 -0
- /package/dist/{chunk-4YTILIIH.js.map → chunk-VV66DH6T.js.map} +0 -0
- /package/dist/{chunk-GVRO4PWE.js.map → chunk-XNNXAAZT.js.map} +0 -0
- /package/dist/{chunk-AS2IRKLU.js.map → chunk-YU5HVI6B.js.map} +0 -0
- /package/dist/{chunk-SJ2GZ6RF.js.map → chunk-ZX3GTM7O.js.map} +0 -0
- /package/dist/{claude-ACVXNB6N.js.map → claude-H33OQMXO.js.map} +0 -0
- /package/dist/{color-ZPIIUADB.js.map → color-4TJ4P5EY.js.map} +0 -0
- /package/dist/{contribute-RS3DO3WP.js.map → contribute-K7UXBOML.js.map} +0 -0
- /package/dist/{git-OQAPUPLP.js.map → git-OV6ADVO7.js.map} +0 -0
- /package/dist/{init-F6PFMSU5.js.map → init-CMIRHFSR.js.map} +0 -0
- /package/dist/{installation-detector-6R6YOFVZ.js.map → installation-detector-VXZOCL6P.js.map} +0 -0
- /package/dist/{neon-helpers-L5CXQ5CT.js.map → neon-helpers-3KBC4A3Y.js.map} +0 -0
- /package/dist/{projects-QEAEBAT2.js.map → projects-GVEMCN5R.js.map} +0 -0
- /package/dist/{prompt-A7GGRHSY.js.map → prompt-3SAZYRUN.js.map} +0 -0
- /package/dist/{remote-73TZ2ADI.js.map → remote-IJAMOEAP.js.map} +0 -0
- /package/dist/{test-git-6SAIRBUD.js.map → test-git-CO3BA4BV.js.map} +0 -0
- /package/dist/{test-prefix-RLVRK5ZD.js.map → test-prefix-HZYSDQYT.js.map} +0 -0
- /package/dist/{test-webserver-VPNLAFZ3.js.map → test-webserver-YVQD42W6.js.map} +0 -0
- /package/dist/{update-LETF5ASC.js.map → update-5NOHT4SG.js.map} +0 -0
- /package/dist/{update-notifier-H55ZK7NU.js.map → update-notifier-ARA5SPUW.js.map} +0 -0
|
@@ -5,23 +5,25 @@ import {
|
|
|
5
5
|
colorDistance,
|
|
6
6
|
generateColorFromBranchName,
|
|
7
7
|
getColorPalette,
|
|
8
|
+
getDarkColorPalette,
|
|
8
9
|
hexToRgb,
|
|
9
10
|
lightenColor,
|
|
10
11
|
rgbToHex,
|
|
11
12
|
saturateColor,
|
|
12
13
|
selectDistinctColor
|
|
13
|
-
} from "./chunk-
|
|
14
|
-
import "./chunk-
|
|
14
|
+
} from "./chunk-433MOLAU.js";
|
|
15
|
+
import "./chunk-VT4PDUYT.js";
|
|
15
16
|
export {
|
|
16
17
|
MIN_COLOR_DISTANCE,
|
|
17
18
|
calculateForegroundColor,
|
|
18
19
|
colorDistance,
|
|
19
20
|
generateColorFromBranchName,
|
|
20
21
|
getColorPalette,
|
|
22
|
+
getDarkColorPalette,
|
|
21
23
|
hexToRgb,
|
|
22
24
|
lightenColor,
|
|
23
25
|
rgbToHex,
|
|
24
26
|
saturateColor,
|
|
25
27
|
selectDistinctColor
|
|
26
28
|
};
|
|
27
|
-
//# sourceMappingURL=color-
|
|
29
|
+
//# sourceMappingURL=color-4TJ4P5EY.js.map
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
executeGitCommand
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
6
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-53OMUNUN.js";
|
|
5
|
+
import "./chunk-IDUICCZY.js";
|
|
6
|
+
import "./chunk-CFUWQHCJ.js";
|
|
7
7
|
import {
|
|
8
8
|
checkGhAuth,
|
|
9
9
|
executeGhCommand
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-LT3SGBR7.js";
|
|
11
11
|
import {
|
|
12
12
|
promptInput
|
|
13
|
-
} from "./chunk-
|
|
14
|
-
import "./chunk-
|
|
13
|
+
} from "./chunk-ZX3GTM7O.js";
|
|
14
|
+
import "./chunk-6MLEBAYZ.js";
|
|
15
15
|
import {
|
|
16
16
|
logger
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-VT4PDUYT.js";
|
|
18
18
|
|
|
19
19
|
// src/commands/contribute.ts
|
|
20
20
|
import { existsSync, accessSync, constants } from "fs";
|
|
@@ -259,4 +259,4 @@ export {
|
|
|
259
259
|
validateDirectoryName,
|
|
260
260
|
validateDirectoryPath
|
|
261
261
|
};
|
|
262
|
-
//# sourceMappingURL=contribute-
|
|
262
|
+
//# sourceMappingURL=contribute-K7UXBOML.js.map
|
|
@@ -1,42 +1,40 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
DevServerManager
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-SHVB3EFE.js";
|
|
5
|
+
import "./chunk-LVLRMP7V.js";
|
|
6
6
|
import {
|
|
7
7
|
calculatePortForBranch
|
|
8
8
|
} from "./chunk-VU3QMIP2.js";
|
|
9
9
|
import {
|
|
10
10
|
IdentifierParser
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-YU5HVI6B.js";
|
|
12
12
|
import {
|
|
13
13
|
ProjectCapabilityDetector
|
|
14
14
|
} from "./chunk-EBISESAP.js";
|
|
15
15
|
import "./chunk-2ZPFJQ3B.js";
|
|
16
16
|
import {
|
|
17
17
|
GitWorktreeManager
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-HMMO2LDS.js";
|
|
19
19
|
import {
|
|
20
20
|
extractSettingsOverrides
|
|
21
21
|
} from "./chunk-GYCR2LOU.js";
|
|
22
22
|
import {
|
|
23
23
|
extractIssueNumber
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-53OMUNUN.js";
|
|
25
25
|
import {
|
|
26
26
|
SettingsManager
|
|
27
|
-
} from "./chunk-
|
|
28
|
-
import "./chunk-
|
|
27
|
+
} from "./chunk-IDUICCZY.js";
|
|
28
|
+
import "./chunk-CFUWQHCJ.js";
|
|
29
|
+
import "./chunk-6MLEBAYZ.js";
|
|
29
30
|
import {
|
|
30
31
|
extractPort,
|
|
31
32
|
findEnvFileContainingVariable,
|
|
32
33
|
isNoEnvFilesFoundError,
|
|
33
34
|
loadWorkspaceEnv,
|
|
35
|
+
logger,
|
|
34
36
|
parseEnvFile
|
|
35
|
-
} from "./chunk-
|
|
36
|
-
import "./chunk-6UIGZD2N.js";
|
|
37
|
-
import {
|
|
38
|
-
logger
|
|
39
|
-
} from "./chunk-UYVWLISQ.js";
|
|
37
|
+
} from "./chunk-VT4PDUYT.js";
|
|
40
38
|
|
|
41
39
|
// src/commands/dev-server.ts
|
|
42
40
|
import path from "path";
|
|
@@ -309,4 +307,4 @@ var DevServerCommand = class {
|
|
|
309
307
|
export {
|
|
310
308
|
DevServerCommand
|
|
311
309
|
};
|
|
312
|
-
//# sourceMappingURL=dev-server-
|
|
310
|
+
//# sourceMappingURL=dev-server-HNBRWGCD.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/dev-server.ts"],"sourcesContent":["import path from 'path'\nimport fs from 'fs-extra'\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 { parseEnvFile, extractPort, findEnvFileContainingVariable, loadWorkspaceEnv, isNoEnvFilesFoundError } from '../utils/env.js'\nimport { calculatePortForBranch } from '../utils/port.js'\nimport { extractIssueNumber } from '../utils/git.js'\nimport { logger } from '../utils/logger.js'\nimport { extractSettingsOverrides } from '../utils/cli-overrides.js'\nimport type { GitWorktree } from '../types/worktree.js'\n\nexport interface DevServerCommandInput {\n\tidentifier?: string | undefined\n\tjson?: boolean | undefined\n}\n\nexport interface DevServerResult {\n\tstatus: 'started' | 'already_running' | 'no_web_capability'\n\turl?: string\n\tport?: number\n\tpid?: number\n\tmessage: string\n}\n\ninterface ParsedDevServerInput {\n\ttype: 'issue' | 'pr' | 'branch'\n\tnumber?: string | number\n\tbranchName?: string\n\toriginalInput: string\n\tautoDetected: boolean\n}\n\n/**\n * DevServerCommand - Start dev server for workspace in foreground mode\n * Runs in foreground (blocking terminal until user stops it)\n */\nexport class DevServerCommand {\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\t/**\n\t * Output JSON to stdout (used for --json flag)\n\t */\n\tprivate outputJson(data: DevServerResult | Record<string, unknown>): void {\n\t\tprocess.stdout.write(JSON.stringify(data, null, 2) + '\\n')\n\t}\n\n\tasync execute(input: DevServerCommandInput): Promise<DevServerResult> {\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.debug(`Found worktree at: ${worktree.path}`)\n\n\t\t// 3. Load settings to check sourceEnvOnStart\n\t\tconst settings = await this.settingsManager.loadSettings()\n\t\tconst shouldLoadEnv = settings.sourceEnvOnStart ?? false\n\n\t\t// Build environment variables\n\t\tlet envOverrides: Record<string, string> = {}\n\n\t\tif (shouldLoadEnv) {\n\t\t\tconst envResult = loadWorkspaceEnv(worktree.path)\n\t\t\tif (envResult.parsed) {\n\t\t\t\tenvOverrides = envResult.parsed\n\t\t\t}\n\t\t\tif (envResult.error && !isNoEnvFilesFoundError(envResult.error)) {\n\t\t\t\tlogger.warn(`Failed to load env files: ${envResult.error.message}`)\n\t\t\t}\n\t\t}\n\n\t\t// 4. Detect project capabilities\n\t\tconst { capabilities } =\n\t\t\tawait this.capabilityDetector.detectCapabilities(worktree.path)\n\n\t\tlogger.debug(`Detected capabilities: ${capabilities.join(', ')}`)\n\n\t\t// 4. If no web capability, return gracefully with info message\n\t\tif (!capabilities.includes('web')) {\n\t\t\tconst message = 'No web capability detected in this workspace. Dev server not started.'\n\t\t\tif (input.json) {\n\t\t\t\tthis.outputJson({\n\t\t\t\t\tstatus: 'no_web_capability',\n\t\t\t\t\tmessage,\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\tlogger.info(message)\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tstatus: 'no_web_capability',\n\t\t\t\tmessage,\n\t\t\t}\n\t\t}\n\n\t\t// 5. Get port for workspace\n\t\tconst port = await this.getWorkspacePort(worktree.path)\n\t\tconst url = `http://localhost:${port}`\n\n\t\t// 6. Check if server already running\n\t\tconst isRunning = await this.devServerManager.isServerRunning(port)\n\n\t\tif (isRunning) {\n\t\t\tconst message = `Dev server already running at ${url}`\n\t\t\tif (input.json) {\n\t\t\t\tthis.outputJson({\n\t\t\t\t\tstatus: 'already_running',\n\t\t\t\t\turl,\n\t\t\t\t\tport,\n\t\t\t\t\tmessage,\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\tlogger.info(message)\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tstatus: 'already_running',\n\t\t\t\turl,\n\t\t\t\tport,\n\t\t\t\tmessage,\n\t\t\t}\n\t\t}\n\n\t\t// 7. Start server in foreground\n\t\tconst message = `Starting dev server at ${url}`\n\t\tif (!input.json) {\n\t\t\tlogger.info(message)\n\t\t}\n\n\t\tlet finalResult: DevServerResult = {\n\t\t\tstatus: 'started',\n\t\t\turl,\n\t\t\tport,\n\t\t\tmessage,\n\t\t}\n\n\t\t// This will block until user stops the server (Ctrl+C)\n\t\t// In JSON mode, redirect npm output to stderr so JSON can go to stdout\n\t\tconst processInfo = await this.devServerManager.runServerForeground(\n\t\t\tworktree.path,\n\t\t\tport,\n\t\t\t!!input.json,\n\t\t\t// Callback called immediately when process starts (for JSON output)\n\t\t\t(pid) => {\n\t\t\t\tif (input.json && pid) {\n\t\t\t\t\tfinalResult.pid = pid\n\t\t\t\t\tthis.outputJson(finalResult)\n\t\t\t\t}\n\t\t\t},\n\t\t\tenvOverrides\n\t\t)\n\n\t\tif (processInfo.pid) {\n\t\t\tfinalResult.pid = processInfo.pid\n\t\t}\n\n\t\treturn finalResult\n\t}\n\n\t/**\n\t * Parse explicit identifier input\n\t */\n\tprivate async parseExplicitInput(identifier: string): Promise<ParsedDevServerInput> {\n\t\tconst parsed = await this.identifierParser.parseForPatternDetection(identifier)\n\n\t\t// Description type should never reach dev-server command\n\t\tif (parsed.type === 'description') {\n\t\t\tthrow new Error('Description input type is not supported in dev-server command')\n\t\t}\n\n\t\tconst result: ParsedDevServerInput = {\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 */\n\tprivate async autoDetectFromCurrentDirectory(): Promise<ParsedDevServerInput> {\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 issueNumber = extractIssueNumber(currentDir)\n\n\t\tif (issueNumber !== null) {\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 branchIssueNumber = extractIssueNumber(currentBranch)\n\t\tif (branchIssueNumber !== null) {\n\t\t\tlogger.debug(`Auto-detected issue #${branchIssueNumber} from branch: ${currentBranch}`)\n\t\t\treturn {\n\t\t\t\ttype: 'issue',\n\t\t\t\tnumber: branchIssueNumber,\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: ParsedDevServerInput): 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\tconst prNumber = typeof parsed.number === 'number' ? parsed.number : Number(parsed.number)\n\t\t\tif (isNaN(prNumber) || !isFinite(prNumber)) {\n\t\t\t\tthrow new Error(`Invalid PR number: ${parsed.number}. PR numbers must be numeric.`)\n\t\t\t}\n\t\t\tworktree = await this.gitWorktreeManager.findWorktreeForPR(prNumber, '')\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: ParsedDevServerInput): 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 * Get port for workspace - reads from dotenv-flow files 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 any dotenv-flow file (as override)\n\t\tconst envFile = await findEnvFileContainingVariable(\n\t\t\tworktreePath,\n\t\t\t'PORT',\n\t\t\tasync (p) => fs.pathExists(p),\n\t\t\tasync (p, varName) => {\n\t\t\t\tconst content = await fs.readFile(p, 'utf8')\n\t\t\t\tconst envMap = parseEnvFile(content)\n\t\t\t\treturn envMap.get(varName) ?? null\n\t\t\t}\n\t\t)\n\n\t\tif (envFile) {\n\t\t\tconst envPath = path.join(worktreePath, envFile)\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 ${envFile}: ${port}`)\n\t\t\t\treturn port\n\t\t\t}\n\t\t}\n\n\t\t// PORT not in any dotenv-flow file, calculate based on workspace identifier\n\t\tlogger.debug('PORT not found in any dotenv-flow file, 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 issueId = extractIssueNumber(dirName) ?? extractIssueNumber(worktree.branch)\n\t\tif (issueId !== null) {\n\t\t\tconst issueNumber = parseInt(issueId, 10)\n\t\t\tif (!isNaN(issueNumber)) {\n\t\t\t\tconst port = basePort + issueNumber\n\t\t\t\tlogger.debug(`Calculated PORT for issue #${issueId}: ${port}`)\n\t\t\t\treturn port\n\t\t\t}\n\t\t\t// For alphanumeric IDs, fall through to branch-based hash\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":["message","port"]}
|
|
1
|
+
{"version":3,"sources":["../src/commands/dev-server.ts"],"sourcesContent":["import path from 'path'\nimport fs from 'fs-extra'\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 { parseEnvFile, extractPort, findEnvFileContainingVariable, loadWorkspaceEnv, isNoEnvFilesFoundError } from '../utils/env.js'\nimport { calculatePortForBranch } from '../utils/port.js'\nimport { extractIssueNumber } from '../utils/git.js'\nimport { logger } from '../utils/logger.js'\nimport { extractSettingsOverrides } from '../utils/cli-overrides.js'\nimport type { GitWorktree } from '../types/worktree.js'\n\nexport interface DevServerCommandInput {\n\tidentifier?: string | undefined\n\tjson?: boolean | undefined\n}\n\nexport interface DevServerResult {\n\tstatus: 'started' | 'already_running' | 'no_web_capability'\n\turl?: string\n\tport?: number\n\tpid?: number\n\tmessage: string\n}\n\ninterface ParsedDevServerInput {\n\ttype: 'issue' | 'pr' | 'branch'\n\tnumber?: string | number\n\tbranchName?: string\n\toriginalInput: string\n\tautoDetected: boolean\n}\n\n/**\n * DevServerCommand - Start dev server for workspace in foreground mode\n * Runs in foreground (blocking terminal until user stops it)\n */\nexport class DevServerCommand {\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\t/**\n\t * Output JSON to stdout (used for --json flag)\n\t */\n\tprivate outputJson(data: DevServerResult | Record<string, unknown>): void {\n\t\tprocess.stdout.write(JSON.stringify(data, null, 2) + '\\n')\n\t}\n\n\tasync execute(input: DevServerCommandInput): Promise<DevServerResult> {\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.debug(`Found worktree at: ${worktree.path}`)\n\n\t\t// 3. Load settings to check sourceEnvOnStart\n\t\tconst settings = await this.settingsManager.loadSettings()\n\t\tconst shouldLoadEnv = settings.sourceEnvOnStart ?? false\n\n\t\t// Build environment variables\n\t\tlet envOverrides: Record<string, string> = {}\n\n\t\tif (shouldLoadEnv) {\n\t\t\tconst envResult = loadWorkspaceEnv(worktree.path)\n\t\t\tif (envResult.parsed) {\n\t\t\t\tenvOverrides = envResult.parsed\n\t\t\t}\n\t\t\tif (envResult.error && !isNoEnvFilesFoundError(envResult.error)) {\n\t\t\t\tlogger.warn(`Failed to load env files: ${envResult.error.message}`)\n\t\t\t}\n\t\t}\n\n\t\t// 4. Detect project capabilities\n\t\tconst { capabilities } =\n\t\t\tawait this.capabilityDetector.detectCapabilities(worktree.path)\n\n\t\tlogger.debug(`Detected capabilities: ${capabilities.join(', ')}`)\n\n\t\t// 4. If no web capability, return gracefully with info message\n\t\tif (!capabilities.includes('web')) {\n\t\t\tconst message = 'No web capability detected in this workspace. Dev server not started.'\n\t\t\tif (input.json) {\n\t\t\t\tthis.outputJson({\n\t\t\t\t\tstatus: 'no_web_capability',\n\t\t\t\t\tmessage,\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\tlogger.info(message)\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tstatus: 'no_web_capability',\n\t\t\t\tmessage,\n\t\t\t}\n\t\t}\n\n\t\t// 5. Get port for workspace\n\t\tconst port = await this.getWorkspacePort(worktree.path)\n\t\tconst url = `http://localhost:${port}`\n\n\t\t// 6. Check if server already running\n\t\tconst isRunning = await this.devServerManager.isServerRunning(port)\n\n\t\tif (isRunning) {\n\t\t\tconst message = `Dev server already running at ${url}`\n\t\t\tif (input.json) {\n\t\t\t\tthis.outputJson({\n\t\t\t\t\tstatus: 'already_running',\n\t\t\t\t\turl,\n\t\t\t\t\tport,\n\t\t\t\t\tmessage,\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\tlogger.info(message)\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tstatus: 'already_running',\n\t\t\t\turl,\n\t\t\t\tport,\n\t\t\t\tmessage,\n\t\t\t}\n\t\t}\n\n\t\t// 7. Start server in foreground\n\t\tconst message = `Starting dev server at ${url}`\n\t\tif (!input.json) {\n\t\t\tlogger.info(message)\n\t\t}\n\n\t\tlet finalResult: DevServerResult = {\n\t\t\tstatus: 'started',\n\t\t\turl,\n\t\t\tport,\n\t\t\tmessage,\n\t\t}\n\n\t\t// This will block until user stops the server (Ctrl+C)\n\t\t// In JSON mode, redirect npm output to stderr so JSON can go to stdout\n\t\tconst processInfo = await this.devServerManager.runServerForeground(\n\t\t\tworktree.path,\n\t\t\tport,\n\t\t\t!!input.json,\n\t\t\t// Callback called immediately when process starts (for JSON output)\n\t\t\t(pid) => {\n\t\t\t\tif (input.json && pid) {\n\t\t\t\t\tfinalResult.pid = pid\n\t\t\t\t\tthis.outputJson(finalResult)\n\t\t\t\t}\n\t\t\t},\n\t\t\tenvOverrides\n\t\t)\n\n\t\tif (processInfo.pid) {\n\t\t\tfinalResult.pid = processInfo.pid\n\t\t}\n\n\t\treturn finalResult\n\t}\n\n\t/**\n\t * Parse explicit identifier input\n\t */\n\tprivate async parseExplicitInput(identifier: string): Promise<ParsedDevServerInput> {\n\t\tconst parsed = await this.identifierParser.parseForPatternDetection(identifier)\n\n\t\t// Description type should never reach dev-server command\n\t\tif (parsed.type === 'description') {\n\t\t\tthrow new Error('Description input type is not supported in dev-server command')\n\t\t}\n\n\t\tconst result: ParsedDevServerInput = {\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 */\n\tprivate async autoDetectFromCurrentDirectory(): Promise<ParsedDevServerInput> {\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 issueNumber = extractIssueNumber(currentDir)\n\n\t\tif (issueNumber !== null) {\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 branchIssueNumber = extractIssueNumber(currentBranch)\n\t\tif (branchIssueNumber !== null) {\n\t\t\tlogger.debug(`Auto-detected issue #${branchIssueNumber} from branch: ${currentBranch}`)\n\t\t\treturn {\n\t\t\t\ttype: 'issue',\n\t\t\t\tnumber: branchIssueNumber,\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: ParsedDevServerInput): 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\tconst prNumber = typeof parsed.number === 'number' ? parsed.number : Number(parsed.number)\n\t\t\tif (isNaN(prNumber) || !isFinite(prNumber)) {\n\t\t\t\tthrow new Error(`Invalid PR number: ${parsed.number}. PR numbers must be numeric.`)\n\t\t\t}\n\t\t\tworktree = await this.gitWorktreeManager.findWorktreeForPR(prNumber, '')\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: ParsedDevServerInput): 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 * Get port for workspace - reads from dotenv-flow files 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 any dotenv-flow file (as override)\n\t\tconst envFile = await findEnvFileContainingVariable(\n\t\t\tworktreePath,\n\t\t\t'PORT',\n\t\t\tasync (p) => fs.pathExists(p),\n\t\t\tasync (p, varName) => {\n\t\t\t\tconst content = await fs.readFile(p, 'utf8')\n\t\t\t\tconst envMap = parseEnvFile(content)\n\t\t\t\treturn envMap.get(varName) ?? null\n\t\t\t}\n\t\t)\n\n\t\tif (envFile) {\n\t\t\tconst envPath = path.join(worktreePath, envFile)\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 ${envFile}: ${port}`)\n\t\t\t\treturn port\n\t\t\t}\n\t\t}\n\n\t\t// PORT not in any dotenv-flow file, calculate based on workspace identifier\n\t\tlogger.debug('PORT not found in any dotenv-flow file, 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 issueId = extractIssueNumber(dirName) ?? extractIssueNumber(worktree.branch)\n\t\tif (issueId !== null) {\n\t\t\tconst issueNumber = parseInt(issueId, 10)\n\t\t\tif (!isNaN(issueNumber)) {\n\t\t\t\tconst port = basePort + issueNumber\n\t\t\t\tlogger.debug(`Calculated PORT for issue #${issueId}: ${port}`)\n\t\t\t\treturn port\n\t\t\t}\n\t\t\t// For alphanumeric IDs, fall through to branch-based hash\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":["message","port"]}
|
|
@@ -2,33 +2,31 @@
|
|
|
2
2
|
import {
|
|
3
3
|
IssueEnhancementService,
|
|
4
4
|
capitalizeFirstLetter
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-7HIRPCKU.js";
|
|
6
6
|
import {
|
|
7
7
|
AgentManager
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-N4ZJVATC.js";
|
|
9
9
|
import {
|
|
10
10
|
ProjectCapabilityDetector
|
|
11
11
|
} from "./chunk-EBISESAP.js";
|
|
12
12
|
import "./chunk-2ZPFJQ3B.js";
|
|
13
13
|
import "./chunk-YETJNRQM.js";
|
|
14
|
-
import "./chunk-
|
|
14
|
+
import "./chunk-K5G5SFWY.js";
|
|
15
15
|
import {
|
|
16
16
|
SettingsManager
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-IDUICCZY.js";
|
|
18
18
|
import {
|
|
19
19
|
GitHubService
|
|
20
|
-
} from "./chunk-
|
|
21
|
-
import "./chunk-
|
|
22
|
-
import "./chunk-
|
|
20
|
+
} from "./chunk-3PT7RKL5.js";
|
|
21
|
+
import "./chunk-LT3SGBR7.js";
|
|
22
|
+
import "./chunk-ZX3GTM7O.js";
|
|
23
23
|
import {
|
|
24
24
|
getClaudeVersion
|
|
25
|
-
} from "./chunk-
|
|
26
|
-
import "./chunk-
|
|
27
|
-
import "./chunk-Z5NXYJIG.js";
|
|
28
|
-
import "./chunk-6UIGZD2N.js";
|
|
25
|
+
} from "./chunk-AEIMYF4P.js";
|
|
26
|
+
import "./chunk-6MLEBAYZ.js";
|
|
29
27
|
import {
|
|
30
28
|
logger
|
|
31
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-VT4PDUYT.js";
|
|
32
30
|
|
|
33
31
|
// src/utils/diagnostics.ts
|
|
34
32
|
import { readFile } from "fs/promises";
|
|
@@ -139,7 +137,11 @@ var FeedbackCommand = class {
|
|
|
139
137
|
async execute(input) {
|
|
140
138
|
const description = capitalizeFirstLetter(input.description);
|
|
141
139
|
const body = input.options.body ? capitalizeFirstLetter(input.options.body) : void 0;
|
|
142
|
-
|
|
140
|
+
const hasBody = !!body;
|
|
141
|
+
if (!description || !this.enhancementService.validateDescription(description, hasBody)) {
|
|
142
|
+
if (hasBody) {
|
|
143
|
+
throw new Error("Description is required and cannot be empty");
|
|
144
|
+
}
|
|
143
145
|
throw new Error("Description is required and must be more than 30 characters with at least 3 words");
|
|
144
146
|
}
|
|
145
147
|
const diagnostics = await gatherDiagnosticInfo();
|
|
@@ -162,4 +164,4 @@ ${userBody}`;
|
|
|
162
164
|
export {
|
|
163
165
|
FeedbackCommand
|
|
164
166
|
};
|
|
165
|
-
//# sourceMappingURL=feedback-
|
|
167
|
+
//# sourceMappingURL=feedback-567ZH2O7.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/diagnostics.ts","../src/commands/feedback.ts"],"sourcesContent":["import { readFile } from 'fs/promises'\nimport { join, dirname } from 'path'\nimport { fileURLToPath } from 'url'\nimport { platform, release, arch } from 'os'\nimport { logger } from './logger'\nimport { ProjectCapabilityDetector } from '../lib/ProjectCapabilityDetector.js'\nimport type { ProjectCapability } from '../types/loom.js'\nimport { getClaudeVersion } from './claude.js'\n\nconst __filename = fileURLToPath(import.meta.url)\nconst __dirname = dirname(__filename)\n\n/**\n * Diagnostic information gathered from the system\n */\nexport interface DiagnosticInfo {\n\tcliVersion: string\n\tnodeVersion: string\n\tosType: string\n\tosVersion: string\n\tarchitecture: string\n\tcapabilities: ProjectCapability[]\n\tclaudeVersion: string | null\n}\n\n/**\n * Gathers diagnostic information about the CLI environment.\n * Fails gracefully with fallback messages if any information cannot be gathered.\n */\nexport async function gatherDiagnosticInfo(): Promise<DiagnosticInfo> {\n\t// Instantiate detector for current directory\n\tconst detector = new ProjectCapabilityDetector()\n\tconst { capabilities } = await detector.detectCapabilities(process.cwd())\n\n\t// Get Claude CLI version (returns null if not available)\n\tconst claudeVersion = await getClaudeVersion()\n\n\tconst diagnostics: DiagnosticInfo = {\n\t\tcliVersion: await getCliVersion(),\n\t\tnodeVersion: getNodeVersion(),\n\t\tosType: getOsType(),\n\t\tosVersion: getOsVersion(),\n\t\tarchitecture: getArchitecture(),\n\t\tcapabilities,\n\t\tclaudeVersion,\n\t}\n\n\treturn diagnostics\n}\n\n/**\n * Formats diagnostic information as markdown for inclusion in GitHub issues\n */\nexport function formatDiagnosticsAsMarkdown(diagnostics: DiagnosticInfo, includeMarker = true): string {\n\tconst marker = includeMarker ? `<!-- CLI GENERATED FEEDBACK v${diagnostics.cliVersion} -->\\n` : ''\n\n\t// Format capabilities as comma-separated string or \"none\"\n\tconst capabilitiesDisplay = diagnostics.capabilities.length > 0\n\t\t? diagnostics.capabilities.join(', ')\n\t\t: 'none'\n\n\t// Format Claude version with fallback for null\n\tconst claudeVersionDisplay = diagnostics.claudeVersion ?? 'not available'\n\n\treturn `${marker}\n<details>\n<summary>Diagnostic Information</summary>\n\n| Property | Value |\n|----------|-------|\n| CLI Version | ${diagnostics.cliVersion} |\n| Node.js Version | ${diagnostics.nodeVersion} |\n| OS | ${diagnostics.osType} |\n| OS Version | ${diagnostics.osVersion} |\n| Architecture | ${diagnostics.architecture} |\n| Capabilities | ${capabilitiesDisplay} |\n| Claude CLI Version | ${claudeVersionDisplay} |\n\n</details>\n`\n}\n\n/**\n * Gets the CLI version from package.json.\n * Falls back to \"unknown\" if package.json cannot be read.\n */\nasync function getCliVersion(): Promise<string> {\n\ttry {\n\t\t// Navigate up from dist/ to root directory (same as cli.ts does)\n\t\tconst packageJsonPath = join(__dirname, '..', 'package.json')\n\t\tconst packageJson = await readFile(packageJsonPath, 'utf-8')\n\t\tconst parsed = JSON.parse(packageJson)\n\t\treturn parsed.version ?? 'unknown'\n\t} catch (error) {\n\t\tlogger.debug('Failed to read CLI version from package.json: ', error)\n\t\treturn 'unknown (failed to read package.json)'\n\t}\n}\n\n/**\n * Gets the Node.js version.\n * Falls back to \"unknown\" if process.version is not available.\n */\nfunction getNodeVersion(): string {\n\ttry {\n\t\treturn process.version ?? 'unknown'\n\t} catch (error) {\n\t\tlogger.debug('Failed to read Node.js version:', error)\n\t\treturn 'unknown (failed to read Node.js version)'\n\t}\n}\n\n/**\n * Gets the operating system type.\n * Falls back to \"unknown\" if os.platform() fails.\n */\nfunction getOsType(): string {\n\ttry {\n\t\treturn platform() ?? 'unknown'\n\t} catch (error) {\n\t\tlogger.debug('Failed to read OS type:', error)\n\t\treturn 'unknown (failed to detect OS)'\n\t}\n}\n\n/**\n * Gets the operating system version.\n * Falls back to \"unknown\" if os.release() fails.\n */\nfunction getOsVersion(): string {\n\ttry {\n\t\treturn release() ?? 'unknown'\n\t} catch (error) {\n\t\tlogger.debug('Failed to read OS version:', error)\n\t\treturn 'unknown (failed to detect OS version)'\n\t}\n}\n\n/**\n * Gets the system architecture.\n * Falls back to \"unknown\" if os.arch() fails.\n */\nfunction getArchitecture(): string {\n\ttry {\n\t\treturn arch() ?? 'unknown'\n\t} catch (error) {\n\t\tlogger.debug('Failed to read system architecture:', error)\n\t\treturn 'unknown (failed to detect architecture)'\n\t}\n}\n","import type { FeedbackOptions } from '../types/index.js'\nimport { IssueEnhancementService } from '../lib/IssueEnhancementService.js'\nimport { GitHubService } from '../lib/GitHubService.js'\nimport { AgentManager } from '../lib/AgentManager.js'\nimport { SettingsManager } from '../lib/SettingsManager.js'\nimport { gatherDiagnosticInfo, formatDiagnosticsAsMarkdown } from '../utils/diagnostics.js'\nimport { capitalizeFirstLetter } from '../utils/text.js'\n\n// Hardcoded target repository for feedback\nconst FEEDBACK_REPOSITORY = 'iloom-ai/iloom-cli'\n\n/**\n * Input structure for FeedbackCommand\n */\nexport interface FeedbackCommandInput {\n\tdescription: string\n\toptions: FeedbackOptions\n}\n\n/**\n * Command to submit feedback/bug reports to the iloom-cli repository.\n * Mirrors add-issue command but targets iloom-ai/iloom-cli repo.\n */\nexport class FeedbackCommand {\n\tprivate enhancementService: IssueEnhancementService\n\n\tconstructor(enhancementService?: IssueEnhancementService) {\n\t\t// Use provided service or create default\n\t\tthis.enhancementService = enhancementService ?? new IssueEnhancementService(\n\t\t\tnew GitHubService(),\n\t\t\tnew AgentManager(),\n\t\t\tnew SettingsManager()\n\t\t)\n\t}\n\n\t/**\n\t * Execute the feedback command workflow:\n\t * 1. Validate description format\n\t * 2. Gather diagnostic information\n\t * 3. Create GitHub issue in iloom-ai/iloom-cli with CLI marker and diagnostics\n\t * 4. Wait for keypress and open browser for review\n\t * 5. Return issue number\n\t */\n\tpublic async execute(input: FeedbackCommandInput): Promise<string | number> {\n\t\t// Apply first-letter capitalization to title (description) and body\n\t\tconst description = capitalizeFirstLetter(input.description)\n\t\tconst body = input.options.body ? capitalizeFirstLetter(input.options.body) : undefined\n\n\t\t// Step 1: Validate description format\n\t\tif (!description || !this.enhancementService.validateDescription(description)) {\n\t\t\tthrow new Error('Description is required and must be more than 30 characters with at least 3 words')\n\t\t}\n\n\t\t// Step 2: Gather diagnostic information\n\t\tconst diagnostics = await gatherDiagnosticInfo()\n\t\tconst diagnosticsMarkdown = formatDiagnosticsAsMarkdown(diagnostics)\n\n\t\t// Step 3: Create enhanced issue body with marker and diagnostics\n\t\tconst userBody = body ?? description\n\t\tconst enhancedBody = `${diagnosticsMarkdown}\n\n${userBody}`\n\n\t\t// Step 4: Create GitHub issue in iloom-cli repo (no label needed)\n\t\t// The GitHub Action workflow will detect the CLI marker and enhance the issue\n\t\tconst result = await this.enhancementService.createEnhancedIssue(\n\t\t\tdescription,\n\t\t\tenhancedBody,\n\t\t\tFEEDBACK_REPOSITORY,\n\t\t\tundefined // No labels needed\n\t\t)\n\n\t\t// Step 5: Wait for keypress and open issue in browser for review\n\t\tawait this.enhancementService.waitForReviewAndOpen(result.number, false, FEEDBACK_REPOSITORY)\n\n\t\t// Step 6: Return issue number for reference\n\t\treturn result.number\n\t}\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/utils/diagnostics.ts","../src/commands/feedback.ts"],"sourcesContent":["import { readFile } from 'fs/promises'\nimport { join, dirname } from 'path'\nimport { fileURLToPath } from 'url'\nimport { platform, release, arch } from 'os'\nimport { logger } from './logger'\nimport { ProjectCapabilityDetector } from '../lib/ProjectCapabilityDetector.js'\nimport type { ProjectCapability } from '../types/loom.js'\nimport { getClaudeVersion } from './claude.js'\n\nconst __filename = fileURLToPath(import.meta.url)\nconst __dirname = dirname(__filename)\n\n/**\n * Diagnostic information gathered from the system\n */\nexport interface DiagnosticInfo {\n\tcliVersion: string\n\tnodeVersion: string\n\tosType: string\n\tosVersion: string\n\tarchitecture: string\n\tcapabilities: ProjectCapability[]\n\tclaudeVersion: string | null\n}\n\n/**\n * Gathers diagnostic information about the CLI environment.\n * Fails gracefully with fallback messages if any information cannot be gathered.\n */\nexport async function gatherDiagnosticInfo(): Promise<DiagnosticInfo> {\n\t// Instantiate detector for current directory\n\tconst detector = new ProjectCapabilityDetector()\n\tconst { capabilities } = await detector.detectCapabilities(process.cwd())\n\n\t// Get Claude CLI version (returns null if not available)\n\tconst claudeVersion = await getClaudeVersion()\n\n\tconst diagnostics: DiagnosticInfo = {\n\t\tcliVersion: await getCliVersion(),\n\t\tnodeVersion: getNodeVersion(),\n\t\tosType: getOsType(),\n\t\tosVersion: getOsVersion(),\n\t\tarchitecture: getArchitecture(),\n\t\tcapabilities,\n\t\tclaudeVersion,\n\t}\n\n\treturn diagnostics\n}\n\n/**\n * Formats diagnostic information as markdown for inclusion in GitHub issues\n */\nexport function formatDiagnosticsAsMarkdown(diagnostics: DiagnosticInfo, includeMarker = true): string {\n\tconst marker = includeMarker ? `<!-- CLI GENERATED FEEDBACK v${diagnostics.cliVersion} -->\\n` : ''\n\n\t// Format capabilities as comma-separated string or \"none\"\n\tconst capabilitiesDisplay = diagnostics.capabilities.length > 0\n\t\t? diagnostics.capabilities.join(', ')\n\t\t: 'none'\n\n\t// Format Claude version with fallback for null\n\tconst claudeVersionDisplay = diagnostics.claudeVersion ?? 'not available'\n\n\treturn `${marker}\n<details>\n<summary>Diagnostic Information</summary>\n\n| Property | Value |\n|----------|-------|\n| CLI Version | ${diagnostics.cliVersion} |\n| Node.js Version | ${diagnostics.nodeVersion} |\n| OS | ${diagnostics.osType} |\n| OS Version | ${diagnostics.osVersion} |\n| Architecture | ${diagnostics.architecture} |\n| Capabilities | ${capabilitiesDisplay} |\n| Claude CLI Version | ${claudeVersionDisplay} |\n\n</details>\n`\n}\n\n/**\n * Gets the CLI version from package.json.\n * Falls back to \"unknown\" if package.json cannot be read.\n */\nasync function getCliVersion(): Promise<string> {\n\ttry {\n\t\t// Navigate up from dist/ to root directory (same as cli.ts does)\n\t\tconst packageJsonPath = join(__dirname, '..', 'package.json')\n\t\tconst packageJson = await readFile(packageJsonPath, 'utf-8')\n\t\tconst parsed = JSON.parse(packageJson)\n\t\treturn parsed.version ?? 'unknown'\n\t} catch (error) {\n\t\tlogger.debug('Failed to read CLI version from package.json: ', error)\n\t\treturn 'unknown (failed to read package.json)'\n\t}\n}\n\n/**\n * Gets the Node.js version.\n * Falls back to \"unknown\" if process.version is not available.\n */\nfunction getNodeVersion(): string {\n\ttry {\n\t\treturn process.version ?? 'unknown'\n\t} catch (error) {\n\t\tlogger.debug('Failed to read Node.js version:', error)\n\t\treturn 'unknown (failed to read Node.js version)'\n\t}\n}\n\n/**\n * Gets the operating system type.\n * Falls back to \"unknown\" if os.platform() fails.\n */\nfunction getOsType(): string {\n\ttry {\n\t\treturn platform() ?? 'unknown'\n\t} catch (error) {\n\t\tlogger.debug('Failed to read OS type:', error)\n\t\treturn 'unknown (failed to detect OS)'\n\t}\n}\n\n/**\n * Gets the operating system version.\n * Falls back to \"unknown\" if os.release() fails.\n */\nfunction getOsVersion(): string {\n\ttry {\n\t\treturn release() ?? 'unknown'\n\t} catch (error) {\n\t\tlogger.debug('Failed to read OS version:', error)\n\t\treturn 'unknown (failed to detect OS version)'\n\t}\n}\n\n/**\n * Gets the system architecture.\n * Falls back to \"unknown\" if os.arch() fails.\n */\nfunction getArchitecture(): string {\n\ttry {\n\t\treturn arch() ?? 'unknown'\n\t} catch (error) {\n\t\tlogger.debug('Failed to read system architecture:', error)\n\t\treturn 'unknown (failed to detect architecture)'\n\t}\n}\n","import type { FeedbackOptions } from '../types/index.js'\nimport { IssueEnhancementService } from '../lib/IssueEnhancementService.js'\nimport { GitHubService } from '../lib/GitHubService.js'\nimport { AgentManager } from '../lib/AgentManager.js'\nimport { SettingsManager } from '../lib/SettingsManager.js'\nimport { gatherDiagnosticInfo, formatDiagnosticsAsMarkdown } from '../utils/diagnostics.js'\nimport { capitalizeFirstLetter } from '../utils/text.js'\n\n// Hardcoded target repository for feedback\nconst FEEDBACK_REPOSITORY = 'iloom-ai/iloom-cli'\n\n/**\n * Input structure for FeedbackCommand\n */\nexport interface FeedbackCommandInput {\n\tdescription: string\n\toptions: FeedbackOptions\n}\n\n/**\n * Command to submit feedback/bug reports to the iloom-cli repository.\n * Mirrors add-issue command but targets iloom-ai/iloom-cli repo.\n */\nexport class FeedbackCommand {\n\tprivate enhancementService: IssueEnhancementService\n\n\tconstructor(enhancementService?: IssueEnhancementService) {\n\t\t// Use provided service or create default\n\t\tthis.enhancementService = enhancementService ?? new IssueEnhancementService(\n\t\t\tnew GitHubService(),\n\t\t\tnew AgentManager(),\n\t\t\tnew SettingsManager()\n\t\t)\n\t}\n\n\t/**\n\t * Execute the feedback command workflow:\n\t * 1. Validate description format\n\t * 2. Gather diagnostic information\n\t * 3. Create GitHub issue in iloom-ai/iloom-cli with CLI marker and diagnostics\n\t * 4. Wait for keypress and open browser for review\n\t * 5. Return issue number\n\t */\n\tpublic async execute(input: FeedbackCommandInput): Promise<string | number> {\n\t\t// Apply first-letter capitalization to title (description) and body\n\t\tconst description = capitalizeFirstLetter(input.description)\n\t\tconst body = input.options.body ? capitalizeFirstLetter(input.options.body) : undefined\n\n\t\t// Step 1: Validate description format\n\t\t// When --body is provided, only require non-empty description (skip strict validation)\n\t\tconst hasBody = !!body\n\t\tif (!description || !this.enhancementService.validateDescription(description, hasBody)) {\n\t\t\tif (hasBody) {\n\t\t\t\tthrow new Error('Description is required and cannot be empty')\n\t\t\t}\n\t\t\tthrow new Error('Description is required and must be more than 30 characters with at least 3 words')\n\t\t}\n\n\t\t// Step 2: Gather diagnostic information\n\t\tconst diagnostics = await gatherDiagnosticInfo()\n\t\tconst diagnosticsMarkdown = formatDiagnosticsAsMarkdown(diagnostics)\n\n\t\t// Step 3: Create enhanced issue body with marker and diagnostics\n\t\tconst userBody = body ?? description\n\t\tconst enhancedBody = `${diagnosticsMarkdown}\n\n${userBody}`\n\n\t\t// Step 4: Create GitHub issue in iloom-cli repo (no label needed)\n\t\t// The GitHub Action workflow will detect the CLI marker and enhance the issue\n\t\tconst result = await this.enhancementService.createEnhancedIssue(\n\t\t\tdescription,\n\t\t\tenhancedBody,\n\t\t\tFEEDBACK_REPOSITORY,\n\t\t\tundefined // No labels needed\n\t\t)\n\n\t\t// Step 5: Wait for keypress and open issue in browser for review\n\t\tawait this.enhancementService.waitForReviewAndOpen(result.number, false, FEEDBACK_REPOSITORY)\n\n\t\t// Step 6: Return issue number for reference\n\t\treturn result.number\n\t}\n}\n"],"mappings":"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","names":[]}
|
|
@@ -32,11 +32,11 @@ import {
|
|
|
32
32
|
pushBranchToRemote,
|
|
33
33
|
removePlaceholderCommitFromHead,
|
|
34
34
|
removePlaceholderCommitFromHistory
|
|
35
|
-
} from "./chunk-
|
|
36
|
-
import "./chunk-
|
|
37
|
-
import "./chunk-
|
|
38
|
-
import "./chunk-
|
|
39
|
-
import "./chunk-
|
|
35
|
+
} from "./chunk-53OMUNUN.js";
|
|
36
|
+
import "./chunk-IDUICCZY.js";
|
|
37
|
+
import "./chunk-CFUWQHCJ.js";
|
|
38
|
+
import "./chunk-6MLEBAYZ.js";
|
|
39
|
+
import "./chunk-VT4PDUYT.js";
|
|
40
40
|
export {
|
|
41
41
|
PLACEHOLDER_COMMIT_PREFIX,
|
|
42
42
|
branchExists,
|
|
@@ -71,4 +71,4 @@ export {
|
|
|
71
71
|
removePlaceholderCommitFromHead,
|
|
72
72
|
removePlaceholderCommitFromHistory
|
|
73
73
|
};
|
|
74
|
-
//# sourceMappingURL=git-
|
|
74
|
+
//# sourceMappingURL=git-OV6ADVO7.js.map
|
|
@@ -4,42 +4,40 @@ import {
|
|
|
4
4
|
IssueTrackerFactory,
|
|
5
5
|
generateIssueManagementMcpConfig,
|
|
6
6
|
generateRecapMcpConfig
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import "./chunk-
|
|
7
|
+
} from "./chunk-66BMJ25W.js";
|
|
8
|
+
import "./chunk-7Q66W4OH.js";
|
|
9
9
|
import {
|
|
10
10
|
AgentManager
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-N4ZJVATC.js";
|
|
12
12
|
import {
|
|
13
13
|
GitWorktreeManager
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-HMMO2LDS.js";
|
|
15
15
|
import {
|
|
16
16
|
PromptTemplateManager
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-K5G5SFWY.js";
|
|
18
18
|
import {
|
|
19
19
|
extractSettingsOverrides
|
|
20
20
|
} from "./chunk-GYCR2LOU.js";
|
|
21
21
|
import {
|
|
22
22
|
extractIssueNumber
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-53OMUNUN.js";
|
|
24
24
|
import {
|
|
25
25
|
SettingsManager
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-IDUICCZY.js";
|
|
27
27
|
import {
|
|
28
28
|
MetadataManager
|
|
29
|
-
} from "./chunk-
|
|
30
|
-
import "./chunk-
|
|
31
|
-
import "./chunk-
|
|
32
|
-
import "./chunk-
|
|
29
|
+
} from "./chunk-CFUWQHCJ.js";
|
|
30
|
+
import "./chunk-3PT7RKL5.js";
|
|
31
|
+
import "./chunk-LT3SGBR7.js";
|
|
32
|
+
import "./chunk-ZX3GTM7O.js";
|
|
33
33
|
import {
|
|
34
34
|
generateDeterministicSessionId,
|
|
35
35
|
launchClaude
|
|
36
|
-
} from "./chunk-
|
|
37
|
-
import "./chunk-
|
|
38
|
-
import "./chunk-Z5NXYJIG.js";
|
|
39
|
-
import "./chunk-6UIGZD2N.js";
|
|
36
|
+
} from "./chunk-AEIMYF4P.js";
|
|
37
|
+
import "./chunk-6MLEBAYZ.js";
|
|
40
38
|
import {
|
|
41
39
|
logger
|
|
42
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-VT4PDUYT.js";
|
|
43
41
|
|
|
44
42
|
// src/commands/ignite.ts
|
|
45
43
|
import path2 from "path";
|
|
@@ -667,4 +665,4 @@ var IgniteCommand = class {
|
|
|
667
665
|
export {
|
|
668
666
|
IgniteCommand
|
|
669
667
|
};
|
|
670
|
-
//# sourceMappingURL=ignite-
|
|
668
|
+
//# sourceMappingURL=ignite-3HB3ZBEW.js.map
|