@iloom/cli 0.3.4 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -3
- package/dist/{BranchNamingService-A77VI6AI.js → BranchNamingService-TOM2KAUT.js} +4 -3
- package/dist/ClaudeContextManager-VEGJTS5E.js +16 -0
- package/dist/ClaudeService-ICSHJMQ5.js +15 -0
- package/dist/GitHubService-RPM27GWD.js +12 -0
- package/dist/{LoomLauncher-ZV3ZZIBA.js → LoomLauncher-SJBZFZXE.js} +25 -22
- package/dist/LoomLauncher-SJBZFZXE.js.map +1 -0
- package/dist/PromptTemplateManager-2TDZAUC6.js +9 -0
- package/dist/README.md +13 -3
- package/dist/{SettingsManager-I2LRCW2A.js → SettingsManager-FJFU6JJD.js} +7 -3
- package/dist/SettingsMigrationManager-EH3J2TCN.js +10 -0
- package/dist/{chunk-UJL4HI2R.js → chunk-3NFBZRPR.js} +2 -2
- package/dist/chunk-6UIGZD2N.js +20 -0
- package/dist/chunk-6UIGZD2N.js.map +1 -0
- package/dist/{chunk-RIEO2WML.js → chunk-74VMN2KC.js} +26 -2
- package/dist/chunk-74VMN2KC.js.map +1 -0
- package/dist/{chunk-OYF4VIFI.js → chunk-75B2HZZ5.js} +147 -22
- package/dist/chunk-75B2HZZ5.js.map +1 -0
- package/dist/{chunk-PGPI5LR4.js → chunk-ADDNFQJ4.js} +7 -21
- package/dist/chunk-ADDNFQJ4.js.map +1 -0
- package/dist/{chunk-AKUJXDNW.js → chunk-F4J6KEL6.js} +3 -3
- package/dist/{chunk-DLHA5VQ3.js → chunk-HD5SUKI2.js} +36 -179
- package/dist/chunk-HD5SUKI2.js.map +1 -0
- package/dist/chunk-HHDSIE72.js +667 -0
- package/dist/chunk-HHDSIE72.js.map +1 -0
- package/dist/{chunk-OXAM2WVC.js → chunk-HVGQP44L.js} +21 -1
- package/dist/chunk-HVGQP44L.js.map +1 -0
- package/dist/{chunk-RW54ZMBM.js → chunk-JJUPY5MM.js} +2 -2
- package/dist/{chunk-UAN4A3YU.js → chunk-KM3W7YQX.js} +11 -11
- package/dist/{chunk-3RUPPQRG.js → chunk-KO2FOMHL.js} +43 -2
- package/dist/{chunk-3RUPPQRG.js.map → chunk-KO2FOMHL.js.map} +1 -1
- package/dist/{chunk-2MAIX45J.js → chunk-LTNDJMTH.js} +104 -43
- package/dist/chunk-LTNDJMTH.js.map +1 -0
- package/dist/{chunk-2CXREBLZ.js → chunk-M5XUCTTJ.js} +8 -6
- package/dist/chunk-M5XUCTTJ.js.map +1 -0
- package/dist/{chunk-4XIDC3NF.js → chunk-MD6HA5IK.js} +2 -2
- package/dist/chunk-MLS5FAV7.js +189 -0
- package/dist/chunk-MLS5FAV7.js.map +1 -0
- package/dist/{chunk-2IJEMXOB.js → chunk-NFVFVYAP.js} +419 -427
- package/dist/chunk-NFVFVYAP.js.map +1 -0
- package/dist/{chunk-OC4H6HJD.js → chunk-O7WHXLCB.js} +2 -2
- package/dist/{chunk-M7JJCX53.js → chunk-OEGECBFS.js} +20 -20
- package/dist/chunk-OEGECBFS.js.map +1 -0
- package/dist/{chunk-MKWYLDFK.js → chunk-OF7BNW4D.js} +43 -3
- package/dist/chunk-OF7BNW4D.js.map +1 -0
- package/dist/{chunk-SUOXY5WJ.js → chunk-P2WZIDF3.js} +5 -5
- package/dist/chunk-P2WZIDF3.js.map +1 -0
- package/dist/{chunk-PA6Q6AWM.js → chunk-PSFVTBM7.js} +2 -2
- package/dist/chunk-QHA67Q7A.js +281 -0
- package/dist/chunk-QHA67Q7A.js.map +1 -0
- package/dist/{chunk-ZM3CFL5L.js → chunk-QRBOPFAA.js} +3 -3
- package/dist/{chunk-IFB4Z76W.js → chunk-S44CHE3G.js} +13 -12
- package/dist/chunk-S44CHE3G.js.map +1 -0
- package/dist/{chunk-CE26YH2U.js → chunk-SJ2GZ6RF.js} +48 -50
- package/dist/chunk-SJ2GZ6RF.js.map +1 -0
- package/dist/{chunk-SSCQCCJ7.js → chunk-THF25ICZ.js} +2 -2
- package/dist/{chunk-5Q3NDNNV.js → chunk-TR5MC2U6.js} +153 -6
- package/dist/chunk-TR5MC2U6.js.map +1 -0
- package/dist/{chunk-5VK4NRSF.js → chunk-UNXRACJ7.js} +35 -36
- package/dist/chunk-UNXRACJ7.js.map +1 -0
- package/dist/{chunk-GEHQXLEI.js → chunk-UYVWLISQ.js} +18 -35
- package/dist/chunk-UYVWLISQ.js.map +1 -0
- package/dist/{chunk-OSCLCMDG.js → chunk-UYWAESOT.js} +3 -3
- package/dist/{chunk-ZT3YZB4K.js → chunk-VBFDVGAE.js} +12 -12
- package/dist/chunk-VBFDVGAE.js.map +1 -0
- package/dist/{chunk-CDZERT7Z.js → chunk-VWNS6DH5.js} +48 -4
- package/dist/chunk-VWNS6DH5.js.map +1 -0
- package/dist/{chunk-CFFQ2Z7A.js → chunk-WUQQNE63.js} +2 -2
- package/dist/{claude-W52VKI6L.js → claude-X7EBJRB2.js} +8 -5
- package/dist/{cleanup-H4VXU3C3.js → cleanup-7QVPYBJJ.js} +133 -122
- package/dist/cleanup-7QVPYBJJ.js.map +1 -0
- package/dist/cli.js +901 -425
- package/dist/cli.js.map +1 -1
- package/dist/{color-F7RU6B6Z.js → color-ZPIIUADB.js} +3 -3
- package/dist/{contribute-Y7IQV5QY.js → contribute-RZYCYUDX.js} +8 -6
- package/dist/{contribute-Y7IQV5QY.js.map → contribute-RZYCYUDX.js.map} +1 -1
- package/dist/dev-server-LOY7YWCP.js +298 -0
- package/dist/dev-server-LOY7YWCP.js.map +1 -0
- package/dist/{feedback-XTUCKJNT.js → feedback-562KPG5U.js} +13 -12
- package/dist/{feedback-XTUCKJNT.js.map → feedback-562KPG5U.js.map} +1 -1
- package/dist/{git-IYA53VIC.js → git-OXJACVAU.js} +16 -4
- package/dist/hooks/iloom-hook.js +258 -0
- package/dist/{ignite-T74RYXCA.js → ignite-VSIPGKKG.js} +245 -39
- package/dist/ignite-VSIPGKKG.js.map +1 -0
- package/dist/index.d.ts +459 -124
- package/dist/index.js +740 -210
- package/dist/index.js.map +1 -1
- package/dist/init-SCR2LQ4A.js +21 -0
- package/dist/{installation-detector-VARGFFRZ.js → installation-detector-6R6YOFVZ.js} +3 -3
- package/dist/mcp/issue-management-server.js +2 -1
- package/dist/mcp/issue-management-server.js.map +1 -1
- package/dist/neon-helpers-L5CXQ5CT.js +11 -0
- package/dist/{open-UMXANW5S.js → open-CX7HUE26.js} +12 -10
- package/dist/{open-UMXANW5S.js.map → open-CX7HUE26.js.map} +1 -1
- package/dist/projects-6DTNDVLH.js +73 -0
- package/dist/projects-6DTNDVLH.js.map +1 -0
- package/dist/{prompt-QALMYTVC.js → prompt-A7GGRHSY.js} +3 -3
- package/dist/prompts/init-prompt.txt +49 -0
- package/dist/prompts/issue-prompt.txt +110 -8
- package/dist/prompts/regular-prompt.txt +90 -0
- package/dist/prompts/session-summary-prompt.txt +82 -0
- package/dist/{rebase-VJ2VKR6R.js → rebase-55URTXZC.js} +11 -9
- package/dist/{rebase-VJ2VKR6R.js.map → rebase-55URTXZC.js.map} +1 -1
- package/dist/{remote-VUNCQZ6J.js → remote-73TZ2ADI.js} +3 -3
- package/dist/{run-MJYY4PUT.js → run-DP2U2CA2.js} +12 -10
- package/dist/{run-MJYY4PUT.js.map → run-DP2U2CA2.js.map} +1 -1
- package/dist/schema/settings.schema.json +49 -0
- package/dist/summary-J3CJSM7L.js +244 -0
- package/dist/summary-J3CJSM7L.js.map +1 -0
- package/dist/{test-git-IT5EWQ5C.js → test-git-QLAIBJLX.js} +6 -4
- package/dist/{test-git-IT5EWQ5C.js.map → test-git-QLAIBJLX.js.map} +1 -1
- package/dist/{test-prefix-NPWDPUUH.js → test-prefix-6YM2ZOON.js} +6 -4
- package/dist/{test-prefix-NPWDPUUH.js.map → test-prefix-6YM2ZOON.js.map} +1 -1
- package/dist/{test-tabs-PRMRSHKI.js → test-tabs-JGO3VOXJ.js} +4 -4
- package/dist/{test-webserver-DAHONWCS.js → test-webserver-VPNLAFZ3.js} +2 -2
- package/dist/{update-4TDDUR5K.js → update-LETF5ASC.js} +4 -4
- package/dist/{update-notifier-QEX3CJHA.js → update-notifier-H55ZK7NU.js} +3 -3
- package/package.json +6 -6
- package/dist/ClaudeContextManager-BN7RE5ZQ.js +0 -15
- package/dist/ClaudeService-DLYLJUPA.js +0 -14
- package/dist/GitHubService-FZHHBOFG.js +0 -11
- package/dist/LoomLauncher-ZV3ZZIBA.js.map +0 -1
- package/dist/PromptTemplateManager-6HH3PVXV.js +0 -9
- package/dist/SettingsMigrationManager-TJ7UWZG5.js +0 -10
- package/dist/chunk-2CXREBLZ.js.map +0 -1
- package/dist/chunk-2IJEMXOB.js.map +0 -1
- package/dist/chunk-2MAIX45J.js.map +0 -1
- package/dist/chunk-5Q3NDNNV.js.map +0 -1
- package/dist/chunk-5VK4NRSF.js.map +0 -1
- package/dist/chunk-CDZERT7Z.js.map +0 -1
- package/dist/chunk-CE26YH2U.js.map +0 -1
- package/dist/chunk-DLHA5VQ3.js.map +0 -1
- package/dist/chunk-GEHQXLEI.js.map +0 -1
- package/dist/chunk-IFB4Z76W.js.map +0 -1
- package/dist/chunk-M7JJCX53.js.map +0 -1
- package/dist/chunk-MKWYLDFK.js.map +0 -1
- package/dist/chunk-OXAM2WVC.js.map +0 -1
- package/dist/chunk-OYF4VIFI.js.map +0 -1
- package/dist/chunk-PGPI5LR4.js.map +0 -1
- package/dist/chunk-RIEO2WML.js.map +0 -1
- package/dist/chunk-SUOXY5WJ.js.map +0 -1
- package/dist/chunk-ZT3YZB4K.js.map +0 -1
- package/dist/cleanup-H4VXU3C3.js.map +0 -1
- package/dist/ignite-T74RYXCA.js.map +0 -1
- package/dist/init-4FHTAM3F.js +0 -19
- package/dist/logger-MKYH4UDV.js +0 -12
- package/dist/neon-helpers-77PBPGJ5.js +0 -10
- package/dist/update-notifier-QEX3CJHA.js.map +0 -1
- /package/dist/{BranchNamingService-A77VI6AI.js.map → BranchNamingService-TOM2KAUT.js.map} +0 -0
- /package/dist/{ClaudeContextManager-BN7RE5ZQ.js.map → ClaudeContextManager-VEGJTS5E.js.map} +0 -0
- /package/dist/{ClaudeService-DLYLJUPA.js.map → ClaudeService-ICSHJMQ5.js.map} +0 -0
- /package/dist/{GitHubService-FZHHBOFG.js.map → GitHubService-RPM27GWD.js.map} +0 -0
- /package/dist/{PromptTemplateManager-6HH3PVXV.js.map → PromptTemplateManager-2TDZAUC6.js.map} +0 -0
- /package/dist/{SettingsManager-I2LRCW2A.js.map → SettingsManager-FJFU6JJD.js.map} +0 -0
- /package/dist/{SettingsMigrationManager-TJ7UWZG5.js.map → SettingsMigrationManager-EH3J2TCN.js.map} +0 -0
- /package/dist/{chunk-UJL4HI2R.js.map → chunk-3NFBZRPR.js.map} +0 -0
- /package/dist/{chunk-AKUJXDNW.js.map → chunk-F4J6KEL6.js.map} +0 -0
- /package/dist/{chunk-RW54ZMBM.js.map → chunk-JJUPY5MM.js.map} +0 -0
- /package/dist/{chunk-UAN4A3YU.js.map → chunk-KM3W7YQX.js.map} +0 -0
- /package/dist/{chunk-4XIDC3NF.js.map → chunk-MD6HA5IK.js.map} +0 -0
- /package/dist/{chunk-OC4H6HJD.js.map → chunk-O7WHXLCB.js.map} +0 -0
- /package/dist/{chunk-PA6Q6AWM.js.map → chunk-PSFVTBM7.js.map} +0 -0
- /package/dist/{chunk-ZM3CFL5L.js.map → chunk-QRBOPFAA.js.map} +0 -0
- /package/dist/{chunk-SSCQCCJ7.js.map → chunk-THF25ICZ.js.map} +0 -0
- /package/dist/{chunk-OSCLCMDG.js.map → chunk-UYWAESOT.js.map} +0 -0
- /package/dist/{chunk-CFFQ2Z7A.js.map → chunk-WUQQNE63.js.map} +0 -0
- /package/dist/{claude-W52VKI6L.js.map → claude-X7EBJRB2.js.map} +0 -0
- /package/dist/{color-F7RU6B6Z.js.map → color-ZPIIUADB.js.map} +0 -0
- /package/dist/{git-IYA53VIC.js.map → git-OXJACVAU.js.map} +0 -0
- /package/dist/{init-4FHTAM3F.js.map → init-SCR2LQ4A.js.map} +0 -0
- /package/dist/{installation-detector-VARGFFRZ.js.map → installation-detector-6R6YOFVZ.js.map} +0 -0
- /package/dist/{logger-MKYH4UDV.js.map → neon-helpers-L5CXQ5CT.js.map} +0 -0
- /package/dist/{neon-helpers-77PBPGJ5.js.map → prompt-A7GGRHSY.js.map} +0 -0
- /package/dist/{prompt-QALMYTVC.js.map → remote-73TZ2ADI.js.map} +0 -0
- /package/dist/{test-tabs-PRMRSHKI.js.map → test-tabs-JGO3VOXJ.js.map} +0 -0
- /package/dist/{test-webserver-DAHONWCS.js.map → test-webserver-VPNLAFZ3.js.map} +0 -0
- /package/dist/{update-4TDDUR5K.js.map → update-LETF5ASC.js.map} +0 -0
- /package/dist/{remote-VUNCQZ6J.js.map → update-notifier-H55ZK7NU.js.map} +0 -0
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/* eslint-env node */
|
|
3
|
+
/* eslint-disable no-undef */
|
|
4
|
+
/**
|
|
5
|
+
* iloom-hook.js - Claude Code hook script for iloom-vscode integration
|
|
6
|
+
*
|
|
7
|
+
* This script is called by Claude Code on various events and broadcasts
|
|
8
|
+
* relevant session state changes to all iloom-vscode extension instances
|
|
9
|
+
* via Unix sockets.
|
|
10
|
+
*
|
|
11
|
+
* Events we handle:
|
|
12
|
+
* - Stop → waiting_for_input (Claude finished turn)
|
|
13
|
+
* - PermissionRequest → waiting_for_approval (needs permission)
|
|
14
|
+
* - PreToolUse → working (tool about to execute)
|
|
15
|
+
* - PostToolUse → working (tool finished, clears approval)
|
|
16
|
+
* - SessionEnd → ended (clear notifications)
|
|
17
|
+
* - Notification(idle_prompt) → idle_reminder (60s reminder)
|
|
18
|
+
* - Notification(elicitation_dialog) → tool_input_needed (MCP tool question)
|
|
19
|
+
*
|
|
20
|
+
* Events we skip (exit without broadcasting):
|
|
21
|
+
* - SessionStart - user just launched, they know
|
|
22
|
+
* - SubagentStop - subagent done but main agent may continue
|
|
23
|
+
* - Notification(permission_prompt) - redundant with PermissionRequest
|
|
24
|
+
* - Notification(auth_success) - user just logged in
|
|
25
|
+
* - Any other notification types
|
|
26
|
+
*
|
|
27
|
+
* This is purely a notification mechanism - it does NOT participate in
|
|
28
|
+
* permission approval/denial. Claude Code handles permission prompts in
|
|
29
|
+
* the terminal as normal.
|
|
30
|
+
*
|
|
31
|
+
* Debug logging: Set ILOOM_HOOK_DEBUG=1 to enable logging to /tmp/iloom-hook.log
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
const fs = require('fs');
|
|
35
|
+
const net = require('net');
|
|
36
|
+
const path = require('path');
|
|
37
|
+
|
|
38
|
+
// Debug logging - writes to /tmp/iloom-hook.log
|
|
39
|
+
// Set ILOOM_HOOK_DEBUG=0 to disable (enabled by default for now)
|
|
40
|
+
const DEBUG = process.env.ILOOM_HOOK_DEBUG !== '0';
|
|
41
|
+
const LOG_FILE = '/tmp/iloom-hook.log';
|
|
42
|
+
|
|
43
|
+
function debug(message, data = {}) {
|
|
44
|
+
if (!DEBUG) return;
|
|
45
|
+
|
|
46
|
+
const timestamp = new Date().toISOString();
|
|
47
|
+
const dataStr = Object.keys(data).length > 0 ? ` ${JSON.stringify(data)}` : '';
|
|
48
|
+
const logLine = `[${timestamp}] ${message}${dataStr}\n`;
|
|
49
|
+
|
|
50
|
+
try {
|
|
51
|
+
fs.appendFileSync(LOG_FILE, logLine);
|
|
52
|
+
} catch {
|
|
53
|
+
// Ignore logging errors
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Read JSON from stdin until EOF
|
|
59
|
+
* @returns {Promise<object>} Parsed JSON data from Claude Code
|
|
60
|
+
*/
|
|
61
|
+
async function readStdin() {
|
|
62
|
+
return new Promise((resolve, reject) => {
|
|
63
|
+
let data = '';
|
|
64
|
+
|
|
65
|
+
process.stdin.setEncoding('utf8');
|
|
66
|
+
process.stdin.on('data', (chunk) => {
|
|
67
|
+
data += chunk;
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
process.stdin.on('end', () => {
|
|
71
|
+
try {
|
|
72
|
+
const parsed = JSON.parse(data);
|
|
73
|
+
resolve(parsed);
|
|
74
|
+
} catch (error) {
|
|
75
|
+
reject(new Error(`Failed to parse stdin JSON: ${error.message}`));
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
process.stdin.on('error', reject);
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Find all iloom sockets in /tmp
|
|
85
|
+
*
|
|
86
|
+
* @returns {string[]} Array of socket paths
|
|
87
|
+
*/
|
|
88
|
+
function findAllIloomSockets() {
|
|
89
|
+
try {
|
|
90
|
+
const tmpDir = '/tmp';
|
|
91
|
+
const files = fs.readdirSync(tmpDir);
|
|
92
|
+
const sockets = files
|
|
93
|
+
.filter(file => file.startsWith('iloom-') && file.endsWith('.sock'))
|
|
94
|
+
.map(file => path.join(tmpDir, file))
|
|
95
|
+
.filter(socketPath => {
|
|
96
|
+
// Verify it's actually a socket
|
|
97
|
+
try {
|
|
98
|
+
const stat = fs.statSync(socketPath);
|
|
99
|
+
return stat.isSocket();
|
|
100
|
+
} catch {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
return sockets;
|
|
106
|
+
} catch (error) {
|
|
107
|
+
debug('Error finding iloom sockets', { error: error.message });
|
|
108
|
+
return [];
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Map hook event name to session status
|
|
114
|
+
*
|
|
115
|
+
* @param {string} eventName - The hook_event_name from Claude Code
|
|
116
|
+
* @param {string|undefined} notificationType - notification_type for Notification events
|
|
117
|
+
* @returns {string|null} Status string for iloom-vscode, or null if event should be skipped
|
|
118
|
+
*/
|
|
119
|
+
function mapEventToStatus(eventName, notificationType) {
|
|
120
|
+
switch (eventName) {
|
|
121
|
+
case 'Stop':
|
|
122
|
+
return 'waiting_for_input';
|
|
123
|
+
|
|
124
|
+
case 'PermissionRequest':
|
|
125
|
+
return 'waiting_for_approval';
|
|
126
|
+
|
|
127
|
+
case 'PreToolUse':
|
|
128
|
+
case 'PostToolUse':
|
|
129
|
+
return 'working';
|
|
130
|
+
|
|
131
|
+
case 'SessionEnd':
|
|
132
|
+
return 'ended';
|
|
133
|
+
|
|
134
|
+
case 'Notification':
|
|
135
|
+
if (notificationType === 'idle_prompt') {
|
|
136
|
+
return 'idle_reminder';
|
|
137
|
+
}
|
|
138
|
+
if (notificationType === 'elicitation_dialog') {
|
|
139
|
+
return 'tool_input_needed';
|
|
140
|
+
}
|
|
141
|
+
// Other notification types - not relevant, skip
|
|
142
|
+
return null;
|
|
143
|
+
|
|
144
|
+
default:
|
|
145
|
+
// Other events (SessionStart, SubagentStop, etc.) - not relevant, skip
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Send status to a single socket (fire and forget)
|
|
152
|
+
*
|
|
153
|
+
* @param {string} socketPath - Path to Unix socket
|
|
154
|
+
* @param {string} status - Session status
|
|
155
|
+
* @param {object} hookData - Full hook data from Claude Code
|
|
156
|
+
* @returns {Promise<void>}
|
|
157
|
+
*/
|
|
158
|
+
async function sendStatus(socketPath, status, hookData) {
|
|
159
|
+
return new Promise((resolve) => {
|
|
160
|
+
const client = net.createConnection(socketPath, () => {
|
|
161
|
+
const message = JSON.stringify({
|
|
162
|
+
type: 'session_status',
|
|
163
|
+
status,
|
|
164
|
+
session_id: hookData.session_id,
|
|
165
|
+
hook_event_name: hookData.hook_event_name,
|
|
166
|
+
cwd: hookData.cwd,
|
|
167
|
+
tool_name: hookData.tool_name,
|
|
168
|
+
tool_input: hookData.tool_input,
|
|
169
|
+
notification_type: hookData.notification_type,
|
|
170
|
+
timestamp: new Date().toISOString()
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
client.write(message + '\n');
|
|
174
|
+
// Fire and forget - close connection immediately after sending
|
|
175
|
+
client.end();
|
|
176
|
+
resolve();
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
// Handle connection errors silently
|
|
180
|
+
client.on('error', () => {
|
|
181
|
+
resolve();
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Broadcast status to all iloom sockets (fire and forget)
|
|
188
|
+
* Each VSCode instance can filter messages by cwd if needed
|
|
189
|
+
*
|
|
190
|
+
* @param {string[]} socketPaths - Array of socket paths to broadcast to
|
|
191
|
+
* @param {string} status - Session status
|
|
192
|
+
* @param {object} hookData - Full hook data from Claude Code
|
|
193
|
+
*/
|
|
194
|
+
async function broadcastStatus(socketPaths, status, hookData) {
|
|
195
|
+
debug('Broadcasting to all sockets', { count: socketPaths.length, socketPaths });
|
|
196
|
+
|
|
197
|
+
const promises = socketPaths.map(socketPath => {
|
|
198
|
+
return sendStatus(socketPath, status, hookData).catch(error => {
|
|
199
|
+
debug('Broadcast failed for socket', { socketPath, error: error.message });
|
|
200
|
+
return null;
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
// Wait for all broadcasts to complete (or fail)
|
|
205
|
+
await Promise.allSettled(promises);
|
|
206
|
+
debug('Broadcast completed');
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Main entry point
|
|
211
|
+
*/
|
|
212
|
+
async function main() {
|
|
213
|
+
debug('Hook invoked', { ILOOM: process.env.ILOOM, ILOOM_HOOK_DEBUG: process.env.ILOOM_HOOK_DEBUG });
|
|
214
|
+
|
|
215
|
+
// Only run when launched via iloom (ILOOM=1)
|
|
216
|
+
// This prevents the hook from doing anything when Claude is run directly
|
|
217
|
+
if (process.env.ILOOM !== '1') {
|
|
218
|
+
debug('ILOOM not set, exiting silently');
|
|
219
|
+
process.exit(0);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
try {
|
|
223
|
+
const hookData = await readStdin();
|
|
224
|
+
const { hook_event_name, cwd, notification_type, session_id } = hookData;
|
|
225
|
+
|
|
226
|
+
debug('Received hook event', { hook_event_name, cwd, notification_type, session_id, tool_name: hookData.tool_name });
|
|
227
|
+
|
|
228
|
+
const status = mapEventToStatus(hook_event_name, notification_type);
|
|
229
|
+
debug('Mapped event to status', { status });
|
|
230
|
+
|
|
231
|
+
// Skip events we don't care about
|
|
232
|
+
if (status === null) {
|
|
233
|
+
debug('Event not relevant, skipping');
|
|
234
|
+
process.exit(0);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Find all iloom sockets for broadcasting
|
|
238
|
+
const allSockets = findAllIloomSockets();
|
|
239
|
+
debug('Found iloom sockets', { count: allSockets.length, sockets: allSockets });
|
|
240
|
+
|
|
241
|
+
// If no sockets exist, exit silently (no VSCode extensions running)
|
|
242
|
+
if (allSockets.length === 0) {
|
|
243
|
+
debug('No iloom sockets found, exiting');
|
|
244
|
+
process.exit(0);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Broadcast status to all sockets (fire and forget)
|
|
248
|
+
// All events including PermissionRequest are just notifications
|
|
249
|
+
await broadcastStatus(allSockets, status, hookData);
|
|
250
|
+
|
|
251
|
+
debug('Hook completed successfully');
|
|
252
|
+
} catch (error) {
|
|
253
|
+
debug('Hook error', { error: error.message, stack: error.stack });
|
|
254
|
+
// Silent failure - don't interrupt Claude
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
main().catch(() => process.exit(0));
|
|
@@ -3,59 +3,261 @@ import {
|
|
|
3
3
|
FirstRunManager,
|
|
4
4
|
IssueTrackerFactory,
|
|
5
5
|
generateIssueManagementMcpConfig
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-HD5SUKI2.js";
|
|
7
|
+
import "./chunk-QHA67Q7A.js";
|
|
7
8
|
import {
|
|
8
9
|
AgentManager
|
|
9
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-O7WHXLCB.js";
|
|
10
11
|
import {
|
|
11
12
|
GitWorktreeManager
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import {
|
|
14
|
-
PromptTemplateManager
|
|
15
|
-
} from "./chunk-RIEO2WML.js";
|
|
13
|
+
} from "./chunk-M5XUCTTJ.js";
|
|
16
14
|
import {
|
|
17
15
|
extractSettingsOverrides
|
|
18
16
|
} from "./chunk-GYCR2LOU.js";
|
|
19
17
|
import {
|
|
20
18
|
extractIssueNumber
|
|
21
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-TR5MC2U6.js";
|
|
20
|
+
import {
|
|
21
|
+
MetadataManager
|
|
22
|
+
} from "./chunk-MLS5FAV7.js";
|
|
22
23
|
import {
|
|
23
24
|
SettingsManager
|
|
24
|
-
} from "./chunk-
|
|
25
|
-
import "./chunk-
|
|
26
|
-
import "./chunk-
|
|
27
|
-
import "./chunk-
|
|
25
|
+
} from "./chunk-VWNS6DH5.js";
|
|
26
|
+
import "./chunk-OEGECBFS.js";
|
|
27
|
+
import "./chunk-KO2FOMHL.js";
|
|
28
|
+
import "./chunk-SJ2GZ6RF.js";
|
|
28
29
|
import {
|
|
30
|
+
generateDeterministicSessionId,
|
|
29
31
|
launchClaude
|
|
30
|
-
} from "./chunk-
|
|
31
|
-
import "./chunk-
|
|
32
|
-
import "./chunk-
|
|
32
|
+
} from "./chunk-75B2HZZ5.js";
|
|
33
|
+
import "./chunk-JJUPY5MM.js";
|
|
34
|
+
import "./chunk-3NFBZRPR.js";
|
|
35
|
+
import "./chunk-6UIGZD2N.js";
|
|
36
|
+
import {
|
|
37
|
+
PromptTemplateManager
|
|
38
|
+
} from "./chunk-74VMN2KC.js";
|
|
33
39
|
import {
|
|
34
40
|
logger
|
|
35
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-UYVWLISQ.js";
|
|
36
42
|
|
|
37
43
|
// src/commands/ignite.ts
|
|
38
|
-
import
|
|
44
|
+
import path2 from "path";
|
|
39
45
|
import { readFile } from "fs/promises";
|
|
46
|
+
|
|
47
|
+
// src/lib/ClaudeHookManager.ts
|
|
48
|
+
import os from "os";
|
|
49
|
+
import path from "path";
|
|
50
|
+
import fs from "fs-extra";
|
|
51
|
+
import { parse, modify, applyEdits } from "jsonc-parser";
|
|
52
|
+
import { fileURLToPath } from "url";
|
|
53
|
+
import { accessSync } from "fs";
|
|
54
|
+
var ClaudeHookManager = class {
|
|
55
|
+
constructor() {
|
|
56
|
+
this.claudeDir = path.join(os.homedir(), ".claude");
|
|
57
|
+
this.hooksDir = path.join(this.claudeDir, "hooks");
|
|
58
|
+
this.settingsPath = path.join(this.claudeDir, "settings.json");
|
|
59
|
+
const currentFileUrl = import.meta.url;
|
|
60
|
+
const currentFilePath = fileURLToPath(currentFileUrl);
|
|
61
|
+
const distDir = path.dirname(currentFilePath);
|
|
62
|
+
let templateDir = path.join(distDir, "hooks");
|
|
63
|
+
let currentDir = distDir;
|
|
64
|
+
while (currentDir !== path.dirname(currentDir)) {
|
|
65
|
+
const candidatePath = path.join(currentDir, "hooks");
|
|
66
|
+
try {
|
|
67
|
+
accessSync(candidatePath);
|
|
68
|
+
templateDir = candidatePath;
|
|
69
|
+
break;
|
|
70
|
+
} catch {
|
|
71
|
+
currentDir = path.dirname(currentDir);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
this.templateDir = templateDir;
|
|
75
|
+
logger.debug("ClaudeHookManager initialized", {
|
|
76
|
+
claudeDir: this.claudeDir,
|
|
77
|
+
hooksDir: this.hooksDir,
|
|
78
|
+
settingsPath: this.settingsPath,
|
|
79
|
+
templateDir: this.templateDir
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Install Claude hooks for VSCode integration
|
|
84
|
+
*
|
|
85
|
+
* This is idempotent - safe to call on every spin.
|
|
86
|
+
* Installs hook script to ~/.claude/hooks/ and merges
|
|
87
|
+
* hook configuration into ~/.claude/settings.json
|
|
88
|
+
*/
|
|
89
|
+
async installHooks() {
|
|
90
|
+
try {
|
|
91
|
+
await fs.ensureDir(this.hooksDir);
|
|
92
|
+
await this.installHookScript();
|
|
93
|
+
await this.mergeHookConfig();
|
|
94
|
+
logger.debug("Claude hooks installed successfully");
|
|
95
|
+
} catch (error) {
|
|
96
|
+
logger.warn(
|
|
97
|
+
`Failed to install Claude hooks: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Check if hooks are already installed
|
|
103
|
+
*/
|
|
104
|
+
async isHooksInstalled() {
|
|
105
|
+
try {
|
|
106
|
+
const hookScriptPath = path.join(this.hooksDir, "iloom-hook.js");
|
|
107
|
+
if (!await fs.pathExists(hookScriptPath)) {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
if (!await fs.pathExists(this.settingsPath)) {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
const content = await fs.readFile(this.settingsPath, "utf8");
|
|
114
|
+
const errors = [];
|
|
115
|
+
const settings = parse(content, errors, { allowTrailingComma: true });
|
|
116
|
+
if (errors.length > 0 || !(settings == null ? void 0 : settings.hooks)) {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
return Array.isArray(settings.hooks.SessionStart);
|
|
120
|
+
} catch {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Install the hook script from bundled templates
|
|
126
|
+
* Skips write if destination already has identical content
|
|
127
|
+
*/
|
|
128
|
+
async installHookScript() {
|
|
129
|
+
const sourcePath = path.join(this.templateDir, "iloom-hook.js");
|
|
130
|
+
const destPath = path.join(this.hooksDir, "iloom-hook.js");
|
|
131
|
+
if (!await fs.pathExists(sourcePath)) {
|
|
132
|
+
throw new Error(`Hook template not found at ${sourcePath}`);
|
|
133
|
+
}
|
|
134
|
+
if (await fs.pathExists(destPath)) {
|
|
135
|
+
const [sourceContent, destContent] = await Promise.all([
|
|
136
|
+
fs.readFile(sourcePath, "utf8"),
|
|
137
|
+
fs.readFile(destPath, "utf8")
|
|
138
|
+
]);
|
|
139
|
+
if (sourceContent === destContent) {
|
|
140
|
+
logger.debug("Hook script already up to date, skipping");
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
await fs.copyFile(sourcePath, destPath);
|
|
145
|
+
logger.debug("Hook script installed", { sourcePath, destPath });
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Merge hook configuration into settings.json
|
|
149
|
+
* Preserves existing user hooks and comments
|
|
150
|
+
*/
|
|
151
|
+
async mergeHookConfig() {
|
|
152
|
+
var _a, _b, _c;
|
|
153
|
+
await fs.ensureDir(this.claudeDir);
|
|
154
|
+
let existingContent = "{}";
|
|
155
|
+
let existingSettings = {};
|
|
156
|
+
if (await fs.pathExists(this.settingsPath)) {
|
|
157
|
+
existingContent = await fs.readFile(this.settingsPath, "utf8");
|
|
158
|
+
const errors = [];
|
|
159
|
+
existingSettings = parse(existingContent, errors, { allowTrailingComma: true });
|
|
160
|
+
if (errors.length > 0) {
|
|
161
|
+
logger.warn("Existing settings.json has parse errors, will attempt to merge anyway");
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
const ourHooks = this.getHookConfig();
|
|
165
|
+
const mergedHooks = { ...existingSettings.hooks ?? {} };
|
|
166
|
+
let hooksAdded = false;
|
|
167
|
+
for (const [eventName, eventConfigs] of Object.entries(ourHooks)) {
|
|
168
|
+
const existing = mergedHooks[eventName] ?? [];
|
|
169
|
+
const ourCommand = (_c = (_b = (_a = eventConfigs[0]) == null ? void 0 : _a.hooks) == null ? void 0 : _b[0]) == null ? void 0 : _c.command;
|
|
170
|
+
const alreadyRegistered = existing.some(
|
|
171
|
+
(config) => {
|
|
172
|
+
var _a2;
|
|
173
|
+
return (_a2 = config.hooks) == null ? void 0 : _a2.some((h) => h.command === ourCommand);
|
|
174
|
+
}
|
|
175
|
+
);
|
|
176
|
+
if (!alreadyRegistered) {
|
|
177
|
+
mergedHooks[eventName] = [...existing, ...eventConfigs];
|
|
178
|
+
hooksAdded = true;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
if (!hooksAdded) {
|
|
182
|
+
logger.debug("All hooks already registered, skipping settings.json update");
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
let content;
|
|
186
|
+
if (existingContent.includes("//") || existingContent.includes("/*")) {
|
|
187
|
+
let modifiedContent = existingContent;
|
|
188
|
+
const edits = modify(modifiedContent, ["hooks"], mergedHooks, {});
|
|
189
|
+
content = applyEdits(modifiedContent, edits);
|
|
190
|
+
} else {
|
|
191
|
+
const updatedSettings = {
|
|
192
|
+
...existingSettings,
|
|
193
|
+
hooks: mergedHooks
|
|
194
|
+
};
|
|
195
|
+
content = JSON.stringify(updatedSettings, null, 2) + "\n";
|
|
196
|
+
}
|
|
197
|
+
const tempPath = `${this.settingsPath}.tmp`;
|
|
198
|
+
await fs.writeFile(tempPath, content, "utf8");
|
|
199
|
+
await fs.rename(tempPath, this.settingsPath);
|
|
200
|
+
logger.debug("Hook configuration merged into settings.json");
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Get the hook configuration to register
|
|
204
|
+
*
|
|
205
|
+
* Each event maps to a hook that runs iloom-hook.js
|
|
206
|
+
*/
|
|
207
|
+
getHookConfig() {
|
|
208
|
+
const hookCommand = `node ${path.join(this.hooksDir, "iloom-hook.js")}`;
|
|
209
|
+
return {
|
|
210
|
+
Notification: [
|
|
211
|
+
{ hooks: [{ type: "command", command: hookCommand }] }
|
|
212
|
+
],
|
|
213
|
+
Stop: [
|
|
214
|
+
{ hooks: [{ type: "command", command: hookCommand }] }
|
|
215
|
+
],
|
|
216
|
+
SubagentStop: [
|
|
217
|
+
{ hooks: [{ type: "command", command: hookCommand }] }
|
|
218
|
+
],
|
|
219
|
+
PermissionRequest: [
|
|
220
|
+
{ matcher: "*", hooks: [{ type: "command", command: hookCommand, timeout: 86400 }] }
|
|
221
|
+
],
|
|
222
|
+
PreToolUse: [
|
|
223
|
+
{ matcher: "*", hooks: [{ type: "command", command: hookCommand }] }
|
|
224
|
+
],
|
|
225
|
+
PostToolUse: [
|
|
226
|
+
{ matcher: "*", hooks: [{ type: "command", command: hookCommand }] }
|
|
227
|
+
],
|
|
228
|
+
SessionStart: [
|
|
229
|
+
{ hooks: [{ type: "command", command: hookCommand }] }
|
|
230
|
+
],
|
|
231
|
+
SessionEnd: [
|
|
232
|
+
{ hooks: [{ type: "command", command: hookCommand }] }
|
|
233
|
+
]
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
// src/commands/ignite.ts
|
|
40
239
|
var IgniteCommand = class {
|
|
41
|
-
constructor(templateManager, gitWorktreeManager, agentManager, settingsManager, firstRunManager) {
|
|
240
|
+
constructor(templateManager, gitWorktreeManager, agentManager, settingsManager, firstRunManager, hookManager) {
|
|
42
241
|
this.templateManager = templateManager ?? new PromptTemplateManager();
|
|
43
242
|
this.gitWorktreeManager = gitWorktreeManager ?? new GitWorktreeManager();
|
|
44
243
|
this.agentManager = agentManager ?? new AgentManager();
|
|
45
244
|
this.settingsManager = settingsManager ?? new SettingsManager();
|
|
46
245
|
this.firstRunManager = firstRunManager ?? new FirstRunManager("spin");
|
|
246
|
+
this.hookManager = hookManager ?? new ClaudeHookManager();
|
|
47
247
|
}
|
|
48
248
|
/**
|
|
49
249
|
* Main entry point for spin command
|
|
50
250
|
*/
|
|
51
251
|
async execute(oneShot = "default") {
|
|
52
252
|
var _a;
|
|
253
|
+
process.env.ILOOM = "1";
|
|
53
254
|
try {
|
|
54
255
|
logger.info("\u{1F680} Your loom is spinning up, please wait...");
|
|
55
256
|
const isFirstRun = await this.firstRunManager.isFirstRun();
|
|
56
257
|
if (isFirstRun) {
|
|
57
258
|
logger.success("Welcome to iloom! Preparing first-time experience...");
|
|
58
259
|
}
|
|
260
|
+
await this.hookManager.installHooks();
|
|
59
261
|
const context = await this.detectWorkspaceContext();
|
|
60
262
|
logger.debug("Auto-detected workspace context", { context });
|
|
61
263
|
this.logDetectedContext(context);
|
|
@@ -72,7 +274,7 @@ var IgniteCommand = class {
|
|
|
72
274
|
const cliOverrides = extractSettingsOverrides();
|
|
73
275
|
this.settings = await this.settingsManager.loadSettings(void 0, cliOverrides);
|
|
74
276
|
}
|
|
75
|
-
const model = this.
|
|
277
|
+
const model = this.settingsManager.getSpinModel(this.settings);
|
|
76
278
|
let permissionMode = this.getPermissionModeForWorkflow(context.type);
|
|
77
279
|
if (oneShot === "bypassPermissions") {
|
|
78
280
|
permissionMode = "bypassPermissions";
|
|
@@ -82,10 +284,22 @@ var IgniteCommand = class {
|
|
|
82
284
|
"\u26A0\uFE0F WARNING: Using bypassPermissions mode - Claude will execute all tool calls without confirmation. This can be dangerous. Use with caution."
|
|
83
285
|
);
|
|
84
286
|
}
|
|
287
|
+
let sessionId;
|
|
288
|
+
const metadataManager = new MetadataManager();
|
|
289
|
+
const metadata = await metadataManager.readMetadata(context.workspacePath);
|
|
290
|
+
if (metadata == null ? void 0 : metadata.sessionId) {
|
|
291
|
+
sessionId = metadata.sessionId;
|
|
292
|
+
logger.debug("Using session ID from metadata", { sessionId });
|
|
293
|
+
} else {
|
|
294
|
+
sessionId = generateDeterministicSessionId(context.workspacePath);
|
|
295
|
+
logger.debug("Generated session ID (no metadata found)", { sessionId, workspacePath: context.workspacePath });
|
|
296
|
+
}
|
|
85
297
|
const claudeOptions = {
|
|
86
298
|
headless: false,
|
|
87
299
|
// Enable stdio: 'inherit' for current terminal
|
|
88
|
-
addDir: context.workspacePath
|
|
300
|
+
addDir: context.workspacePath,
|
|
301
|
+
sessionId
|
|
302
|
+
// Enable Claude Code session resume
|
|
89
303
|
};
|
|
90
304
|
if (model !== void 0) {
|
|
91
305
|
claudeOptions.model = model;
|
|
@@ -200,19 +414,11 @@ var IgniteCommand = class {
|
|
|
200
414
|
}
|
|
201
415
|
if (oneShot === "noReview" || oneShot === "bypassPermissions") {
|
|
202
416
|
variables.ONE_SHOT_MODE = true;
|
|
417
|
+
} else {
|
|
418
|
+
variables.INTERACTIVE_MODE = true;
|
|
203
419
|
}
|
|
204
420
|
return variables;
|
|
205
421
|
}
|
|
206
|
-
/**
|
|
207
|
-
* Get the appropriate model for a workflow type
|
|
208
|
-
* Same logic as ClaudeService.getModelForWorkflow()
|
|
209
|
-
*/
|
|
210
|
-
getModelForWorkflow(type) {
|
|
211
|
-
if (type === "issue") {
|
|
212
|
-
return "claude-sonnet-4-20250514";
|
|
213
|
-
}
|
|
214
|
-
return void 0;
|
|
215
|
-
}
|
|
216
422
|
/**
|
|
217
423
|
* Get the appropriate permission mode for a workflow type
|
|
218
424
|
* Same logic as ClaudeService.getPermissionModeForWorkflow()
|
|
@@ -242,7 +448,7 @@ var IgniteCommand = class {
|
|
|
242
448
|
*/
|
|
243
449
|
async detectWorkspaceContext() {
|
|
244
450
|
const workspacePath = process.cwd();
|
|
245
|
-
const currentDir =
|
|
451
|
+
const currentDir = path2.basename(workspacePath);
|
|
246
452
|
const prPattern = /_pr_(\d+)$/;
|
|
247
453
|
const prMatch = currentDir.match(prPattern);
|
|
248
454
|
if (prMatch == null ? void 0 : prMatch[1]) {
|
|
@@ -380,15 +586,15 @@ var IgniteCommand = class {
|
|
|
380
586
|
*/
|
|
381
587
|
async loadReadmeContent() {
|
|
382
588
|
try {
|
|
383
|
-
let currentDir =
|
|
384
|
-
while (currentDir !==
|
|
385
|
-
const readmePath =
|
|
589
|
+
let currentDir = path2.dirname(new URL(import.meta.url).pathname);
|
|
590
|
+
while (currentDir !== path2.dirname(currentDir)) {
|
|
591
|
+
const readmePath = path2.join(currentDir, "README.md");
|
|
386
592
|
try {
|
|
387
593
|
const content = await readFile(readmePath, "utf-8");
|
|
388
594
|
logger.debug("Loaded README.md for first-time user", { readmePath });
|
|
389
595
|
return content;
|
|
390
596
|
} catch {
|
|
391
|
-
currentDir =
|
|
597
|
+
currentDir = path2.dirname(currentDir);
|
|
392
598
|
}
|
|
393
599
|
}
|
|
394
600
|
logger.debug("README.md not found, returning empty string");
|
|
@@ -404,15 +610,15 @@ var IgniteCommand = class {
|
|
|
404
610
|
*/
|
|
405
611
|
async loadSettingsSchemaContent() {
|
|
406
612
|
try {
|
|
407
|
-
let currentDir =
|
|
408
|
-
while (currentDir !==
|
|
409
|
-
const schemaPath =
|
|
613
|
+
let currentDir = path2.dirname(new URL(import.meta.url).pathname);
|
|
614
|
+
while (currentDir !== path2.dirname(currentDir)) {
|
|
615
|
+
const schemaPath = path2.join(currentDir, ".iloom", "README.md");
|
|
410
616
|
try {
|
|
411
617
|
const content = await readFile(schemaPath, "utf-8");
|
|
412
618
|
logger.debug("Loaded .iloom/README.md for first-time user", { schemaPath });
|
|
413
619
|
return content;
|
|
414
620
|
} catch {
|
|
415
|
-
currentDir =
|
|
621
|
+
currentDir = path2.dirname(currentDir);
|
|
416
622
|
}
|
|
417
623
|
}
|
|
418
624
|
logger.debug(".iloom/README.md not found, returning empty string");
|
|
@@ -426,4 +632,4 @@ var IgniteCommand = class {
|
|
|
426
632
|
export {
|
|
427
633
|
IgniteCommand
|
|
428
634
|
};
|
|
429
|
-
//# sourceMappingURL=ignite-
|
|
635
|
+
//# sourceMappingURL=ignite-VSIPGKKG.js.map
|