@iloom/cli 0.5.1 → 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-JNWBMHES.js → LoomLauncher-ZHDTPKED.js} +13 -16
- package/dist/{LoomLauncher-JNWBMHES.js.map → LoomLauncher-ZHDTPKED.js.map} +1 -1
- 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-TSLKDFAF.js → chunk-66BMJ25W.js} +7 -7
- package/dist/{chunk-6UIGZD2N.js → chunk-6MLEBAYZ.js} +2 -2
- package/dist/{chunk-BVIK2P6P.js → chunk-7HIRPCKU.js} +4 -4
- 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-CDF7ZX2B.js → chunk-O7VL5N6S.js} +2 -2
- 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-6KB7R22U.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-LU6NU2NZ.js → cleanup-Y5W3CNUV.js} +20 -22
- package/dist/{cleanup-LU6NU2NZ.js.map → cleanup-Y5W3CNUV.js.map} +1 -1
- package/dist/cli.js +71 -73
- 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-OFVW22UW.js → feedback-567ZH2O7.js} +11 -13
- package/dist/{feedback-OFVW22UW.js.map → feedback-567ZH2O7.js.map} +1 -1
- package/dist/{git-OQAPUPLP.js → git-OV6ADVO7.js} +6 -6
- package/dist/{ignite-NREQ3JRM.js → ignite-3HB3ZBEW.js} +15 -17
- package/dist/{ignite-NREQ3JRM.js.map → ignite-3HB3ZBEW.js.map} +1 -1
- package/dist/index.d.ts +54 -35
- package/dist/index.js +371 -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/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-6KB7R22U.js.map +0 -1
- package/dist/chunk-DKQ4SUII.js.map +0 -1
- package/dist/chunk-HABINPX2.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-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-TSLKDFAF.js.map → chunk-66BMJ25W.js.map} +0 -0
- /package/dist/{chunk-6UIGZD2N.js.map → chunk-6MLEBAYZ.js.map} +0 -0
- /package/dist/{chunk-BVIK2P6P.js.map → chunk-7HIRPCKU.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-CDF7ZX2B.js.map → chunk-O7VL5N6S.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
package/dist/index.js
CHANGED
|
@@ -8,8 +8,282 @@ var __export = (target, all) => {
|
|
|
8
8
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
9
|
};
|
|
10
10
|
|
|
11
|
+
// src/utils/env.ts
|
|
12
|
+
import path from "path";
|
|
13
|
+
import dotenvFlow from "dotenv-flow";
|
|
14
|
+
function parseEnvFile(content) {
|
|
15
|
+
const envMap = /* @__PURE__ */ new Map();
|
|
16
|
+
const lines = content.split("\n");
|
|
17
|
+
for (const line of lines) {
|
|
18
|
+
const trimmedLine = line.trim();
|
|
19
|
+
if (!trimmedLine || trimmedLine.startsWith("#")) {
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
const cleanLine = trimmedLine.startsWith("export ") ? trimmedLine.substring(7) : trimmedLine;
|
|
23
|
+
const equalsIndex = cleanLine.indexOf("=");
|
|
24
|
+
if (equalsIndex === -1) {
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
const key = cleanLine.substring(0, equalsIndex).trim();
|
|
28
|
+
let value = cleanLine.substring(equalsIndex + 1);
|
|
29
|
+
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
30
|
+
value = value.substring(1, value.length - 1);
|
|
31
|
+
value = value.replace(/\\"/g, '"').replace(/\\'/g, "'");
|
|
32
|
+
value = value.replace(/\\n/g, "\n");
|
|
33
|
+
}
|
|
34
|
+
if (key) {
|
|
35
|
+
envMap.set(key, value);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return envMap;
|
|
39
|
+
}
|
|
40
|
+
function formatEnvLine(key, value) {
|
|
41
|
+
const escapedValue = value.replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r");
|
|
42
|
+
return `${key}="${escapedValue}"`;
|
|
43
|
+
}
|
|
44
|
+
function validateEnvVariable(key, _value) {
|
|
45
|
+
if (!key || key.length === 0) {
|
|
46
|
+
return {
|
|
47
|
+
valid: false,
|
|
48
|
+
error: "Environment variable key cannot be empty"
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
if (!isValidEnvKey(key)) {
|
|
52
|
+
return {
|
|
53
|
+
valid: false,
|
|
54
|
+
error: `Invalid environment variable name: ${key}. Must start with a letter or underscore and contain only letters, numbers, and underscores.`
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
return { valid: true };
|
|
58
|
+
}
|
|
59
|
+
function isValidEnvKey(key) {
|
|
60
|
+
if (!key || key.length === 0) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
const validKeyRegex = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
64
|
+
return validKeyRegex.test(key);
|
|
65
|
+
}
|
|
66
|
+
function getDotenvFlowFiles() {
|
|
67
|
+
return [
|
|
68
|
+
".env",
|
|
69
|
+
".env.local",
|
|
70
|
+
`.env.${DOTENV_FLOW_NODE_ENV}`,
|
|
71
|
+
`.env.${DOTENV_FLOW_NODE_ENV}.local`
|
|
72
|
+
];
|
|
73
|
+
}
|
|
74
|
+
async function buildEnvSourceCommands(workspacePath, fileExists) {
|
|
75
|
+
const files = getDotenvFlowFiles();
|
|
76
|
+
const commands = [];
|
|
77
|
+
for (const file of files) {
|
|
78
|
+
const fullPath = path.join(workspacePath, file);
|
|
79
|
+
const exists = await fileExists(fullPath);
|
|
80
|
+
if (exists) {
|
|
81
|
+
commands.push(`source ${file}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return commands;
|
|
85
|
+
}
|
|
86
|
+
async function findEnvFileContainingVariable(workspacePath, variableName, fileExists, getEnvVariable) {
|
|
87
|
+
const files = getDotenvFlowFiles().reverse();
|
|
88
|
+
for (const file of files) {
|
|
89
|
+
const fullPath = path.join(workspacePath, file);
|
|
90
|
+
if (!await fileExists(fullPath)) {
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
const value = await getEnvVariable(fullPath, variableName);
|
|
94
|
+
if (value !== null) {
|
|
95
|
+
return file;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
async function hasVariableInAnyEnvFile(workspacePath, variableName, fileExists, getEnvVariable) {
|
|
101
|
+
const file = await findEnvFileContainingVariable(workspacePath, variableName, fileExists, getEnvVariable);
|
|
102
|
+
return file !== null;
|
|
103
|
+
}
|
|
104
|
+
var DOTENV_FLOW_NODE_ENV;
|
|
105
|
+
var init_env = __esm({
|
|
106
|
+
"src/utils/env.ts"() {
|
|
107
|
+
"use strict";
|
|
108
|
+
init_logger();
|
|
109
|
+
DOTENV_FLOW_NODE_ENV = process.env.DOTENV_FLOW_NODE_ENV ?? "development";
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// src/utils/terminal.ts
|
|
114
|
+
import { execa } from "execa";
|
|
115
|
+
import { existsSync } from "fs";
|
|
116
|
+
function detectPlatform() {
|
|
117
|
+
const platform = process.platform;
|
|
118
|
+
if (platform === "darwin") return "darwin";
|
|
119
|
+
if (platform === "linux") return "linux";
|
|
120
|
+
if (platform === "win32") return "win32";
|
|
121
|
+
return "unsupported";
|
|
122
|
+
}
|
|
123
|
+
async function detectDarkMode() {
|
|
124
|
+
const platform = detectPlatform();
|
|
125
|
+
if (platform !== "darwin") {
|
|
126
|
+
return "light";
|
|
127
|
+
}
|
|
128
|
+
try {
|
|
129
|
+
const result = await execa("defaults", ["read", "-g", "AppleInterfaceStyle"]);
|
|
130
|
+
return result.stdout.trim().toLowerCase() === "dark" ? "dark" : "light";
|
|
131
|
+
} catch {
|
|
132
|
+
return "light";
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
async function detectITerm2() {
|
|
136
|
+
const platform = detectPlatform();
|
|
137
|
+
if (platform !== "darwin") return false;
|
|
138
|
+
return existsSync("/Applications/iTerm.app");
|
|
139
|
+
}
|
|
140
|
+
async function openTerminalWindow(options) {
|
|
141
|
+
const platform = detectPlatform();
|
|
142
|
+
if (platform !== "darwin") {
|
|
143
|
+
throw new Error(
|
|
144
|
+
`Terminal window launching not yet supported on ${platform}. Currently only macOS is supported.`
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
const hasITerm2 = await detectITerm2();
|
|
148
|
+
const applescript = hasITerm2 ? await buildITerm2SingleTabScript(options) : await buildAppleScript(options);
|
|
149
|
+
try {
|
|
150
|
+
await execa("osascript", ["-e", applescript]);
|
|
151
|
+
if (!hasITerm2) {
|
|
152
|
+
await execa("osascript", ["-e", 'tell application "Terminal" to activate']);
|
|
153
|
+
}
|
|
154
|
+
} catch (error) {
|
|
155
|
+
throw new Error(
|
|
156
|
+
`Failed to open terminal window: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
async function buildAppleScript(options) {
|
|
161
|
+
const {
|
|
162
|
+
workspacePath,
|
|
163
|
+
command,
|
|
164
|
+
backgroundColor,
|
|
165
|
+
port,
|
|
166
|
+
includeEnvSetup,
|
|
167
|
+
includePortExport
|
|
168
|
+
} = options;
|
|
169
|
+
const commands = [];
|
|
170
|
+
if (workspacePath) {
|
|
171
|
+
commands.push(`cd '${escapePathForAppleScript(workspacePath)}'`);
|
|
172
|
+
}
|
|
173
|
+
if (includeEnvSetup && workspacePath) {
|
|
174
|
+
const sourceCommands = await buildEnvSourceCommands(
|
|
175
|
+
workspacePath,
|
|
176
|
+
async (p) => existsSync(p)
|
|
177
|
+
);
|
|
178
|
+
commands.push(...sourceCommands);
|
|
179
|
+
}
|
|
180
|
+
if (includePortExport && port !== void 0) {
|
|
181
|
+
commands.push(`export PORT=${port}`);
|
|
182
|
+
}
|
|
183
|
+
if (command) {
|
|
184
|
+
commands.push(command);
|
|
185
|
+
}
|
|
186
|
+
const fullCommand = commands.join(" && ");
|
|
187
|
+
const historyFreeCommand = ` ${fullCommand}`;
|
|
188
|
+
let script = `tell application "Terminal"
|
|
189
|
+
`;
|
|
190
|
+
script += ` set newTab to do script "${escapeForAppleScript(historyFreeCommand)}"
|
|
191
|
+
`;
|
|
192
|
+
if (backgroundColor) {
|
|
193
|
+
const { r, g, b } = backgroundColor;
|
|
194
|
+
script += ` set background color of newTab to {${Math.round(r * 257)}, ${Math.round(g * 257)}, ${Math.round(b * 257)}}
|
|
195
|
+
`;
|
|
196
|
+
}
|
|
197
|
+
script += `end tell`;
|
|
198
|
+
return script;
|
|
199
|
+
}
|
|
200
|
+
function escapePathForAppleScript(path7) {
|
|
201
|
+
return path7.replace(/'/g, "'\\''");
|
|
202
|
+
}
|
|
203
|
+
function escapeForAppleScript(command) {
|
|
204
|
+
return command.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
205
|
+
}
|
|
206
|
+
async function buildITerm2SingleTabScript(options) {
|
|
207
|
+
const command = await buildCommandSequence(options);
|
|
208
|
+
let script = 'tell application id "com.googlecode.iterm2"\n';
|
|
209
|
+
script += " create window with default profile\n";
|
|
210
|
+
script += " set s1 to current session of current window\n\n";
|
|
211
|
+
if (options.backgroundColor) {
|
|
212
|
+
const { r, g, b } = options.backgroundColor;
|
|
213
|
+
script += ` set background color of s1 to {${Math.round(r * 257)}, ${Math.round(g * 257)}, ${Math.round(b * 257)}}
|
|
214
|
+
`;
|
|
215
|
+
}
|
|
216
|
+
script += ` tell s1 to write text "${escapeForAppleScript(command)}"
|
|
217
|
+
|
|
218
|
+
`;
|
|
219
|
+
if (options.title) {
|
|
220
|
+
script += ` set name of s1 to "${escapeForAppleScript(options.title)}"
|
|
221
|
+
|
|
222
|
+
`;
|
|
223
|
+
}
|
|
224
|
+
script += " activate\n";
|
|
225
|
+
script += "end tell";
|
|
226
|
+
return script;
|
|
227
|
+
}
|
|
228
|
+
async function buildCommandSequence(options) {
|
|
229
|
+
const {
|
|
230
|
+
workspacePath,
|
|
231
|
+
command,
|
|
232
|
+
port,
|
|
233
|
+
includeEnvSetup,
|
|
234
|
+
includePortExport
|
|
235
|
+
} = options;
|
|
236
|
+
const commands = [];
|
|
237
|
+
if (workspacePath) {
|
|
238
|
+
commands.push(`cd '${escapePathForAppleScript(workspacePath)}'`);
|
|
239
|
+
}
|
|
240
|
+
if (includeEnvSetup && workspacePath) {
|
|
241
|
+
const sourceCommands = await buildEnvSourceCommands(
|
|
242
|
+
workspacePath,
|
|
243
|
+
async (p) => existsSync(p)
|
|
244
|
+
);
|
|
245
|
+
commands.push(...sourceCommands);
|
|
246
|
+
}
|
|
247
|
+
if (includePortExport && port !== void 0) {
|
|
248
|
+
commands.push(`export PORT=${port}`);
|
|
249
|
+
}
|
|
250
|
+
if (command) {
|
|
251
|
+
commands.push(command);
|
|
252
|
+
}
|
|
253
|
+
const fullCommand = commands.join(" && ");
|
|
254
|
+
return ` ${fullCommand}`;
|
|
255
|
+
}
|
|
256
|
+
var init_terminal = __esm({
|
|
257
|
+
"src/utils/terminal.ts"() {
|
|
258
|
+
"use strict";
|
|
259
|
+
init_env();
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
|
|
11
263
|
// src/utils/logger.ts
|
|
12
264
|
import chalk, { Chalk } from "chalk";
|
|
265
|
+
async function initializeThemeMode() {
|
|
266
|
+
try {
|
|
267
|
+
currentThemeMode = await detectDarkMode();
|
|
268
|
+
} catch {
|
|
269
|
+
currentThemeMode = "light";
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
function getInfoColor(chalkInstance) {
|
|
273
|
+
return currentThemeMode === "dark" ? chalkInstance.cyan : chalkInstance.blue;
|
|
274
|
+
}
|
|
275
|
+
function getSuccessColor(chalkInstance) {
|
|
276
|
+
return currentThemeMode === "dark" ? chalkInstance.greenBright : chalkInstance.green;
|
|
277
|
+
}
|
|
278
|
+
function getWarnColor(chalkInstance) {
|
|
279
|
+
return currentThemeMode === "dark" ? chalkInstance.yellowBright : chalkInstance.yellow;
|
|
280
|
+
}
|
|
281
|
+
function getErrorColor(chalkInstance) {
|
|
282
|
+
return currentThemeMode === "dark" ? chalkInstance.redBright : chalkInstance.red;
|
|
283
|
+
}
|
|
284
|
+
function getDebugColor(chalkInstance) {
|
|
285
|
+
return currentThemeMode === "dark" ? chalkInstance.gray : chalkInstance.gray;
|
|
286
|
+
}
|
|
13
287
|
function formatMessage(message, ...args) {
|
|
14
288
|
const formattedArgs = args.map(
|
|
15
289
|
(arg) => typeof arg === "object" ? JSON.stringify(arg, null, 2) : String(arg)
|
|
@@ -54,32 +328,32 @@ function createLogger(options = {}) {
|
|
|
54
328
|
info: (message, ...args) => {
|
|
55
329
|
const formatted = formatMessage(message, ...args);
|
|
56
330
|
const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`;
|
|
57
|
-
const output = formatWithEmoji(fullMessage, "\u{1F5C2}\uFE0F ", customStdoutChalk
|
|
331
|
+
const output = formatWithEmoji(fullMessage, "\u{1F5C2}\uFE0F ", getInfoColor(customStdoutChalk));
|
|
58
332
|
console.log(output);
|
|
59
333
|
},
|
|
60
334
|
success: (message, ...args) => {
|
|
61
335
|
const formatted = formatMessage(message, ...args);
|
|
62
336
|
const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`;
|
|
63
|
-
const output = formatWithEmoji(fullMessage, "\u2705", customStdoutChalk
|
|
337
|
+
const output = formatWithEmoji(fullMessage, "\u2705", getSuccessColor(customStdoutChalk));
|
|
64
338
|
console.log(output);
|
|
65
339
|
},
|
|
66
340
|
warn: (message, ...args) => {
|
|
67
341
|
const formatted = formatMessage(message, ...args);
|
|
68
342
|
const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`;
|
|
69
|
-
const output = formatWithEmoji(fullMessage, "\u26A0\uFE0F ", customStderrChalk
|
|
343
|
+
const output = formatWithEmoji(fullMessage, "\u26A0\uFE0F ", getWarnColor(customStderrChalk));
|
|
70
344
|
console.error(output);
|
|
71
345
|
},
|
|
72
346
|
error: (message, ...args) => {
|
|
73
347
|
const formatted = formatMessage(message, ...args);
|
|
74
348
|
const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`;
|
|
75
|
-
const output = formatWithEmoji(fullMessage, "\u274C", customStderrChalk
|
|
349
|
+
const output = formatWithEmoji(fullMessage, "\u274C", getErrorColor(customStderrChalk));
|
|
76
350
|
console.error(output);
|
|
77
351
|
},
|
|
78
352
|
debug: (message, ...args) => {
|
|
79
353
|
if (localDebugEnabled) {
|
|
80
354
|
const formatted = formatMessage(message, ...args);
|
|
81
355
|
const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`;
|
|
82
|
-
const output = formatWithEmoji(fullMessage, "\u{1F50D}", customStdoutChalk
|
|
356
|
+
const output = formatWithEmoji(fullMessage, "\u{1F50D}", getDebugColor(customStdoutChalk));
|
|
83
357
|
console.log(output);
|
|
84
358
|
}
|
|
85
359
|
},
|
|
@@ -102,32 +376,32 @@ function createStderrLogger(options = {}) {
|
|
|
102
376
|
info: (message, ...args) => {
|
|
103
377
|
const formatted = formatMessage(message, ...args);
|
|
104
378
|
const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`;
|
|
105
|
-
const output = formatWithEmoji(fullMessage, "\u{1F5C2}\uFE0F ", customChalk
|
|
379
|
+
const output = formatWithEmoji(fullMessage, "\u{1F5C2}\uFE0F ", getInfoColor(customChalk));
|
|
106
380
|
console.error(output);
|
|
107
381
|
},
|
|
108
382
|
success: (message, ...args) => {
|
|
109
383
|
const formatted = formatMessage(message, ...args);
|
|
110
384
|
const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`;
|
|
111
|
-
const output = formatWithEmoji(fullMessage, "\u2705", customChalk
|
|
385
|
+
const output = formatWithEmoji(fullMessage, "\u2705", getSuccessColor(customChalk));
|
|
112
386
|
console.error(output);
|
|
113
387
|
},
|
|
114
388
|
warn: (message, ...args) => {
|
|
115
389
|
const formatted = formatMessage(message, ...args);
|
|
116
390
|
const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`;
|
|
117
|
-
const output = formatWithEmoji(fullMessage, "\u26A0\uFE0F ", customChalk
|
|
391
|
+
const output = formatWithEmoji(fullMessage, "\u26A0\uFE0F ", getWarnColor(customChalk));
|
|
118
392
|
console.error(output);
|
|
119
393
|
},
|
|
120
394
|
error: (message, ...args) => {
|
|
121
395
|
const formatted = formatMessage(message, ...args);
|
|
122
396
|
const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`;
|
|
123
|
-
const output = formatWithEmoji(fullMessage, "\u274C", customChalk
|
|
397
|
+
const output = formatWithEmoji(fullMessage, "\u274C", getErrorColor(customChalk));
|
|
124
398
|
console.error(output);
|
|
125
399
|
},
|
|
126
400
|
debug: (message, ...args) => {
|
|
127
401
|
if (localDebugEnabled) {
|
|
128
402
|
const formatted = formatMessage(message, ...args);
|
|
129
403
|
const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`;
|
|
130
|
-
const output = formatWithEmoji(fullMessage, "\u{1F50D}", customChalk
|
|
404
|
+
const output = formatWithEmoji(fullMessage, "\u{1F50D}", getDebugColor(customChalk));
|
|
131
405
|
console.error(output);
|
|
132
406
|
}
|
|
133
407
|
},
|
|
@@ -141,38 +415,47 @@ function createStderrLogger(options = {}) {
|
|
|
141
415
|
// Use stderr for progress output in JSON mode
|
|
142
416
|
};
|
|
143
417
|
}
|
|
144
|
-
|
|
418
|
+
function setThemeMode(mode) {
|
|
419
|
+
currentThemeMode = mode;
|
|
420
|
+
}
|
|
421
|
+
function getThemeMode() {
|
|
422
|
+
return currentThemeMode;
|
|
423
|
+
}
|
|
424
|
+
var stdoutChalk, stderrChalk, currentThemeMode, globalDebugEnabled, logger, logger_default;
|
|
145
425
|
var init_logger = __esm({
|
|
146
426
|
"src/utils/logger.ts"() {
|
|
147
427
|
"use strict";
|
|
428
|
+
init_terminal();
|
|
148
429
|
stdoutChalk = new Chalk({ level: chalk.level });
|
|
149
430
|
stderrChalk = new Chalk({ level: chalk.level });
|
|
431
|
+
currentThemeMode = "light";
|
|
432
|
+
void initializeThemeMode();
|
|
150
433
|
globalDebugEnabled = false;
|
|
151
434
|
logger = {
|
|
152
435
|
info: (message, ...args) => {
|
|
153
436
|
const formatted = formatMessage(message, ...args);
|
|
154
|
-
const output = formatWithEmoji(formatted, "\u{1F5C2}\uFE0F ", stdoutChalk
|
|
437
|
+
const output = formatWithEmoji(formatted, "\u{1F5C2}\uFE0F ", getInfoColor(stdoutChalk));
|
|
155
438
|
console.log(output);
|
|
156
439
|
},
|
|
157
440
|
success: (message, ...args) => {
|
|
158
441
|
const formatted = formatMessage(message, ...args);
|
|
159
|
-
const output = formatWithEmoji(formatted, "\u2705", stdoutChalk
|
|
442
|
+
const output = formatWithEmoji(formatted, "\u2705", getSuccessColor(stdoutChalk));
|
|
160
443
|
console.log(output);
|
|
161
444
|
},
|
|
162
445
|
warn: (message, ...args) => {
|
|
163
446
|
const formatted = formatMessage(message, ...args);
|
|
164
|
-
const output = formatWithEmoji(formatted, "\u26A0\uFE0F ", stderrChalk
|
|
447
|
+
const output = formatWithEmoji(formatted, "\u26A0\uFE0F ", getWarnColor(stderrChalk));
|
|
165
448
|
console.error(output);
|
|
166
449
|
},
|
|
167
450
|
error: (message, ...args) => {
|
|
168
451
|
const formatted = formatMessage(message, ...args);
|
|
169
|
-
const output = formatWithEmoji(formatted, "\u274C", stderrChalk
|
|
452
|
+
const output = formatWithEmoji(formatted, "\u274C", getErrorColor(stderrChalk));
|
|
170
453
|
console.error(output);
|
|
171
454
|
},
|
|
172
455
|
debug: (message, ...args) => {
|
|
173
456
|
if (globalDebugEnabled) {
|
|
174
457
|
const formatted = formatMessage(message, ...args);
|
|
175
|
-
const output = formatWithEmoji(formatted, "\u{1F50D}", stdoutChalk
|
|
458
|
+
const output = formatWithEmoji(formatted, "\u{1F50D}", getDebugColor(stdoutChalk));
|
|
176
459
|
console.log(output);
|
|
177
460
|
}
|
|
178
461
|
},
|
|
@@ -207,7 +490,7 @@ __export(SettingsManager_exports, {
|
|
|
207
490
|
WorkflowsSettingsSchemaNoDefaults: () => WorkflowsSettingsSchemaNoDefaults
|
|
208
491
|
});
|
|
209
492
|
import { readFile } from "fs/promises";
|
|
210
|
-
import
|
|
493
|
+
import path2 from "path";
|
|
211
494
|
import os from "os";
|
|
212
495
|
import { z } from "zod";
|
|
213
496
|
import deepmerge from "deepmerge";
|
|
@@ -437,10 +720,10 @@ var init_SettingsManager = __esm({
|
|
|
437
720
|
const globalSettingsPath = this.getGlobalSettingsPath();
|
|
438
721
|
logger.debug(`\u{1F30D} Global settings from ${globalSettingsPath}:`, JSON.stringify(globalSettings, null, 2));
|
|
439
722
|
const baseSettings = await this.loadSettingsFile(root, "settings.json");
|
|
440
|
-
const baseSettingsPath =
|
|
723
|
+
const baseSettingsPath = path2.join(root, ".iloom", "settings.json");
|
|
441
724
|
logger.debug(`\u{1F4C4} Base settings from ${baseSettingsPath}:`, JSON.stringify(baseSettings, null, 2));
|
|
442
725
|
const localSettings = await this.loadSettingsFile(root, "settings.local.json");
|
|
443
|
-
const localSettingsPath =
|
|
726
|
+
const localSettingsPath = path2.join(root, ".iloom", "settings.local.json");
|
|
444
727
|
logger.debug(`\u{1F4C4} Local settings from ${localSettingsPath}:`, JSON.stringify(localSettings, null, 2));
|
|
445
728
|
let merged = this.mergeSettings(this.mergeSettings(globalSettings, baseSettings), localSettings);
|
|
446
729
|
logger.debug("\u{1F504} After merging global + base + local settings:", JSON.stringify(merged, null, 2));
|
|
@@ -478,7 +761,7 @@ Note: CLI overrides were applied. Check your --set arguments.`);
|
|
|
478
761
|
* Uses non-defaulting schema to prevent polluting partial settings with defaults before merge
|
|
479
762
|
*/
|
|
480
763
|
async loadSettingsFile(projectRoot, filename) {
|
|
481
|
-
const settingsPath =
|
|
764
|
+
const settingsPath = path2.join(projectRoot, ".iloom", filename);
|
|
482
765
|
try {
|
|
483
766
|
const content = await readFile(settingsPath, "utf-8");
|
|
484
767
|
let parsed;
|
|
@@ -553,13 +836,13 @@ ${errorMessages.join("\n")}`
|
|
|
553
836
|
* Get global config directory path (~/.config/iloom-ai)
|
|
554
837
|
*/
|
|
555
838
|
getGlobalConfigDir() {
|
|
556
|
-
return
|
|
839
|
+
return path2.join(os.homedir(), ".config", "iloom-ai");
|
|
557
840
|
}
|
|
558
841
|
/**
|
|
559
842
|
* Get global settings file path (~/.config/iloom-ai/settings.json)
|
|
560
843
|
*/
|
|
561
844
|
getGlobalSettingsPath() {
|
|
562
|
-
return
|
|
845
|
+
return path2.join(this.getGlobalConfigDir(), "settings.json");
|
|
563
846
|
}
|
|
564
847
|
/**
|
|
565
848
|
* Load and parse global settings file
|
|
@@ -656,6 +939,7 @@ __export(color_exports, {
|
|
|
656
939
|
colorDistance: () => colorDistance,
|
|
657
940
|
generateColorFromBranchName: () => generateColorFromBranchName,
|
|
658
941
|
getColorPalette: () => getColorPalette,
|
|
942
|
+
getDarkColorPalette: () => getDarkColorPalette,
|
|
659
943
|
hexToRgb: () => hexToRgb,
|
|
660
944
|
lightenColor: () => lightenColor,
|
|
661
945
|
rgbToHex: () => rgbToHex,
|
|
@@ -699,6 +983,42 @@ function getColorPalette() {
|
|
|
699
983
|
// 15: Soft salmon
|
|
700
984
|
];
|
|
701
985
|
}
|
|
986
|
+
function getDarkColorPalette() {
|
|
987
|
+
return [
|
|
988
|
+
{ r: 30, g: 45, b: 85 },
|
|
989
|
+
// 0: Dark blue
|
|
990
|
+
{ r: 85, g: 30, b: 50 },
|
|
991
|
+
// 1: Dark rose
|
|
992
|
+
{ r: 30, g: 75, b: 40 },
|
|
993
|
+
// 2: Dark green
|
|
994
|
+
{ r: 75, g: 65, b: 30 },
|
|
995
|
+
// 3: Dark olive
|
|
996
|
+
{ r: 60, g: 35, b: 85 },
|
|
997
|
+
// 4: Dark lavender
|
|
998
|
+
{ r: 30, g: 65, b: 75 },
|
|
999
|
+
// 5: Dark cyan
|
|
1000
|
+
{ r: 55, g: 55, b: 55 },
|
|
1001
|
+
// 6: Dark grey
|
|
1002
|
+
{ r: 85, g: 40, b: 40 },
|
|
1003
|
+
// 7: Dark coral
|
|
1004
|
+
{ r: 35, g: 80, b: 50 },
|
|
1005
|
+
// 8: Dark mint
|
|
1006
|
+
{ r: 70, g: 50, b: 30 },
|
|
1007
|
+
// 9: Dark brown
|
|
1008
|
+
{ r: 30, g: 75, b: 75 },
|
|
1009
|
+
// 10: Dark aqua
|
|
1010
|
+
{ r: 75, g: 30, b: 75 },
|
|
1011
|
+
// 11: Dark magenta
|
|
1012
|
+
{ r: 75, g: 75, b: 30 },
|
|
1013
|
+
// 12: Dark yellow
|
|
1014
|
+
{ r: 50, g: 35, b: 85 },
|
|
1015
|
+
// 13: Dark violet
|
|
1016
|
+
{ r: 30, g: 80, b: 65 },
|
|
1017
|
+
// 14: Dark sea green
|
|
1018
|
+
{ r: 85, g: 40, b: 30 }
|
|
1019
|
+
// 15: Dark rust
|
|
1020
|
+
];
|
|
1021
|
+
}
|
|
702
1022
|
function rgbToHex(r, g, b) {
|
|
703
1023
|
if (r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255) {
|
|
704
1024
|
throw new Error("RGB values must be between 0 and 255");
|
|
@@ -718,10 +1038,10 @@ function hexToRgb(hex) {
|
|
|
718
1038
|
const b = parseInt(cleanHex.slice(4, 6), 16);
|
|
719
1039
|
return { r, g, b };
|
|
720
1040
|
}
|
|
721
|
-
function generateColorFromBranchName(branchName) {
|
|
1041
|
+
function generateColorFromBranchName(branchName, themeMode = "light") {
|
|
722
1042
|
const hash = createHash2("sha256").update(branchName).digest("hex");
|
|
723
1043
|
const hashPrefix = hash.slice(0, 8);
|
|
724
|
-
const palette = getColorPalette();
|
|
1044
|
+
const palette = themeMode === "dark" ? getDarkColorPalette() : getColorPalette();
|
|
725
1045
|
const hashAsInt = parseInt(hashPrefix, 16);
|
|
726
1046
|
const index = hashAsInt % palette.length;
|
|
727
1047
|
logger_default.debug(`[generateColorFromBranchName] Branch name: ${branchName}, Hash: ${hash}, Hash prefix: ${hashPrefix}, Hash as int: ${hashAsInt}, Index: ${index}`);
|
|
@@ -741,9 +1061,9 @@ function colorDistance(a, b) {
|
|
|
741
1061
|
Math.pow(a.r - b.r, 2) + Math.pow(a.g - b.g, 2) + Math.pow(a.b - b.b, 2)
|
|
742
1062
|
);
|
|
743
1063
|
}
|
|
744
|
-
function selectDistinctColor(branchName, usedHexColors) {
|
|
745
|
-
const palette = getColorPalette();
|
|
746
|
-
const hashBasedColor = generateColorFromBranchName(branchName);
|
|
1064
|
+
function selectDistinctColor(branchName, usedHexColors, themeMode = "light") {
|
|
1065
|
+
const palette = themeMode === "dark" ? getDarkColorPalette() : getColorPalette();
|
|
1066
|
+
const hashBasedColor = generateColorFromBranchName(branchName, themeMode);
|
|
747
1067
|
if (usedHexColors.length === 0) {
|
|
748
1068
|
return hashBasedColor;
|
|
749
1069
|
}
|
|
@@ -824,16 +1144,16 @@ var WorkspaceManager = class {
|
|
|
824
1144
|
};
|
|
825
1145
|
|
|
826
1146
|
// src/lib/GitWorktreeManager.ts
|
|
827
|
-
import
|
|
1147
|
+
import path5 from "path";
|
|
828
1148
|
import fs2 from "fs-extra";
|
|
829
1149
|
|
|
830
1150
|
// src/utils/git.ts
|
|
831
1151
|
init_SettingsManager();
|
|
832
|
-
import
|
|
833
|
-
import { execa } from "execa";
|
|
1152
|
+
import path4 from "path";
|
|
1153
|
+
import { execa as execa2 } from "execa";
|
|
834
1154
|
|
|
835
1155
|
// src/lib/MetadataManager.ts
|
|
836
|
-
import
|
|
1156
|
+
import path3 from "path";
|
|
837
1157
|
import os2 from "os";
|
|
838
1158
|
import fs from "fs-extra";
|
|
839
1159
|
|
|
@@ -848,7 +1168,7 @@ function getLogger() {
|
|
|
848
1168
|
// src/lib/MetadataManager.ts
|
|
849
1169
|
var MetadataManager = class {
|
|
850
1170
|
constructor() {
|
|
851
|
-
this.loomsDir =
|
|
1171
|
+
this.loomsDir = path3.join(os2.homedir(), ".config", "iloom-ai", "looms");
|
|
852
1172
|
}
|
|
853
1173
|
/**
|
|
854
1174
|
* Convert worktree path to filename slug per spec section 2.2
|
|
@@ -874,7 +1194,7 @@ var MetadataManager = class {
|
|
|
874
1194
|
*/
|
|
875
1195
|
getFilePath(worktreePath) {
|
|
876
1196
|
const filename = this.slugifyPath(worktreePath);
|
|
877
|
-
return
|
|
1197
|
+
return path3.join(this.loomsDir, filename);
|
|
878
1198
|
}
|
|
879
1199
|
/**
|
|
880
1200
|
* Get the full path to the metadata file for a worktree (public API)
|
|
@@ -981,7 +1301,7 @@ var MetadataManager = class {
|
|
|
981
1301
|
continue;
|
|
982
1302
|
}
|
|
983
1303
|
try {
|
|
984
|
-
const filePath =
|
|
1304
|
+
const filePath = path3.join(this.loomsDir, file);
|
|
985
1305
|
const content = await fs.readFile(filePath, "utf8");
|
|
986
1306
|
const data = JSON.parse(content);
|
|
987
1307
|
if (!data.description) {
|
|
@@ -1046,7 +1366,7 @@ var MetadataManager = class {
|
|
|
1046
1366
|
init_logger();
|
|
1047
1367
|
async function executeGitCommand(args, options) {
|
|
1048
1368
|
try {
|
|
1049
|
-
const result = await
|
|
1369
|
+
const result = await execa2("git", args, {
|
|
1050
1370
|
cwd: (options == null ? void 0 : options.cwd) ?? process.cwd(),
|
|
1051
1371
|
timeout: (options == null ? void 0 : options.timeout) ?? 3e4,
|
|
1052
1372
|
encoding: "utf8",
|
|
@@ -1211,10 +1531,10 @@ function generateWorktreePath(branchName, rootDir = process.cwd(), options) {
|
|
|
1211
1531
|
if ((options == null ? void 0 : options.isPR) && (options == null ? void 0 : options.prNumber)) {
|
|
1212
1532
|
sanitized = `${sanitized}_pr_${options.prNumber}`;
|
|
1213
1533
|
}
|
|
1214
|
-
const parentDir =
|
|
1534
|
+
const parentDir = path4.dirname(rootDir);
|
|
1215
1535
|
let prefix;
|
|
1216
1536
|
if ((options == null ? void 0 : options.prefix) === void 0) {
|
|
1217
|
-
const mainFolderName =
|
|
1537
|
+
const mainFolderName = path4.basename(rootDir);
|
|
1218
1538
|
prefix = mainFolderName ? `${mainFolderName}-looms/` : "looms/";
|
|
1219
1539
|
} else if (options.prefix === "") {
|
|
1220
1540
|
prefix = "";
|
|
@@ -1234,16 +1554,16 @@ function generateWorktreePath(branchName, rootDir = process.cwd(), options) {
|
|
|
1234
1554
|
}
|
|
1235
1555
|
}
|
|
1236
1556
|
if (prefix === "") {
|
|
1237
|
-
return
|
|
1557
|
+
return path4.join(parentDir, sanitized);
|
|
1238
1558
|
} else if (prefix.endsWith("/")) {
|
|
1239
|
-
return
|
|
1559
|
+
return path4.join(parentDir, prefix, sanitized);
|
|
1240
1560
|
} else if (prefix.includes("/")) {
|
|
1241
1561
|
const lastSlashIndex = prefix.lastIndexOf("/");
|
|
1242
1562
|
const dirPath = prefix.substring(0, lastSlashIndex);
|
|
1243
1563
|
const prefixWithSeparator = prefix.substring(lastSlashIndex + 1);
|
|
1244
|
-
return
|
|
1564
|
+
return path4.join(parentDir, dirPath, `${prefixWithSeparator}${sanitized}`);
|
|
1245
1565
|
} else {
|
|
1246
|
-
return
|
|
1566
|
+
return path4.join(parentDir, `${prefix}${sanitized}`);
|
|
1247
1567
|
}
|
|
1248
1568
|
}
|
|
1249
1569
|
async function isValidGitRepo(path7) {
|
|
@@ -1767,7 +2087,7 @@ var GitWorktreeManager = class {
|
|
|
1767
2087
|
if (!options.branch) {
|
|
1768
2088
|
throw new Error("Branch name is required");
|
|
1769
2089
|
}
|
|
1770
|
-
const absolutePath =
|
|
2090
|
+
const absolutePath = path5.resolve(options.path);
|
|
1771
2091
|
if (await fs2.pathExists(absolutePath)) {
|
|
1772
2092
|
if (!options.force) {
|
|
1773
2093
|
throw new Error(`Path already exists: ${absolutePath}`);
|
|
@@ -2083,9 +2403,9 @@ var GitHubError = class extends Error {
|
|
|
2083
2403
|
|
|
2084
2404
|
// src/utils/github.ts
|
|
2085
2405
|
init_logger();
|
|
2086
|
-
import { execa as
|
|
2406
|
+
import { execa as execa3 } from "execa";
|
|
2087
2407
|
async function executeGhCommand(args, options) {
|
|
2088
|
-
const result = await
|
|
2408
|
+
const result = await execa3("gh", args, {
|
|
2089
2409
|
cwd: (options == null ? void 0 : options.cwd) ?? process.cwd(),
|
|
2090
2410
|
timeout: (options == null ? void 0 : options.timeout) ?? 3e4,
|
|
2091
2411
|
encoding: "utf8"
|
|
@@ -2251,7 +2571,7 @@ async function createIssue(title, body, options) {
|
|
|
2251
2571
|
if (!repo) {
|
|
2252
2572
|
execaOptions.cwd = process.cwd();
|
|
2253
2573
|
}
|
|
2254
|
-
const result = await
|
|
2574
|
+
const result = await execa3("gh", args, execaOptions);
|
|
2255
2575
|
const urlMatch = result.stdout.trim().match(/https:\/\/github\.com\/[^/]+\/[^/]+\/issues\/(\d+)/);
|
|
2256
2576
|
if (!(urlMatch == null ? void 0 : urlMatch[1])) {
|
|
2257
2577
|
throw new Error(`Failed to parse issue URL from gh output: ${result.stdout}`);
|
|
@@ -2936,102 +3256,7 @@ var IssueTrackerFactory = class {
|
|
|
2936
3256
|
|
|
2937
3257
|
// src/lib/EnvironmentManager.ts
|
|
2938
3258
|
import fs3 from "fs-extra";
|
|
2939
|
-
|
|
2940
|
-
// src/utils/env.ts
|
|
2941
|
-
init_logger();
|
|
2942
|
-
import path5 from "path";
|
|
2943
|
-
import dotenvFlow from "dotenv-flow";
|
|
2944
|
-
function parseEnvFile(content) {
|
|
2945
|
-
const envMap = /* @__PURE__ */ new Map();
|
|
2946
|
-
const lines = content.split("\n");
|
|
2947
|
-
for (const line of lines) {
|
|
2948
|
-
const trimmedLine = line.trim();
|
|
2949
|
-
if (!trimmedLine || trimmedLine.startsWith("#")) {
|
|
2950
|
-
continue;
|
|
2951
|
-
}
|
|
2952
|
-
const cleanLine = trimmedLine.startsWith("export ") ? trimmedLine.substring(7) : trimmedLine;
|
|
2953
|
-
const equalsIndex = cleanLine.indexOf("=");
|
|
2954
|
-
if (equalsIndex === -1) {
|
|
2955
|
-
continue;
|
|
2956
|
-
}
|
|
2957
|
-
const key = cleanLine.substring(0, equalsIndex).trim();
|
|
2958
|
-
let value = cleanLine.substring(equalsIndex + 1);
|
|
2959
|
-
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
2960
|
-
value = value.substring(1, value.length - 1);
|
|
2961
|
-
value = value.replace(/\\"/g, '"').replace(/\\'/g, "'");
|
|
2962
|
-
value = value.replace(/\\n/g, "\n");
|
|
2963
|
-
}
|
|
2964
|
-
if (key) {
|
|
2965
|
-
envMap.set(key, value);
|
|
2966
|
-
}
|
|
2967
|
-
}
|
|
2968
|
-
return envMap;
|
|
2969
|
-
}
|
|
2970
|
-
function formatEnvLine(key, value) {
|
|
2971
|
-
const escapedValue = value.replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r");
|
|
2972
|
-
return `${key}="${escapedValue}"`;
|
|
2973
|
-
}
|
|
2974
|
-
function validateEnvVariable(key, _value) {
|
|
2975
|
-
if (!key || key.length === 0) {
|
|
2976
|
-
return {
|
|
2977
|
-
valid: false,
|
|
2978
|
-
error: "Environment variable key cannot be empty"
|
|
2979
|
-
};
|
|
2980
|
-
}
|
|
2981
|
-
if (!isValidEnvKey(key)) {
|
|
2982
|
-
return {
|
|
2983
|
-
valid: false,
|
|
2984
|
-
error: `Invalid environment variable name: ${key}. Must start with a letter or underscore and contain only letters, numbers, and underscores.`
|
|
2985
|
-
};
|
|
2986
|
-
}
|
|
2987
|
-
return { valid: true };
|
|
2988
|
-
}
|
|
2989
|
-
function isValidEnvKey(key) {
|
|
2990
|
-
if (!key || key.length === 0) {
|
|
2991
|
-
return false;
|
|
2992
|
-
}
|
|
2993
|
-
const validKeyRegex = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
2994
|
-
return validKeyRegex.test(key);
|
|
2995
|
-
}
|
|
2996
|
-
var DOTENV_FLOW_NODE_ENV = process.env.DOTENV_FLOW_NODE_ENV ?? "development";
|
|
2997
|
-
function getDotenvFlowFiles() {
|
|
2998
|
-
return [
|
|
2999
|
-
".env",
|
|
3000
|
-
".env.local",
|
|
3001
|
-
`.env.${DOTENV_FLOW_NODE_ENV}`,
|
|
3002
|
-
`.env.${DOTENV_FLOW_NODE_ENV}.local`
|
|
3003
|
-
];
|
|
3004
|
-
}
|
|
3005
|
-
async function buildEnvSourceCommands(workspacePath, fileExists) {
|
|
3006
|
-
const files = getDotenvFlowFiles();
|
|
3007
|
-
const commands = [];
|
|
3008
|
-
for (const file of files) {
|
|
3009
|
-
const fullPath = path5.join(workspacePath, file);
|
|
3010
|
-
const exists = await fileExists(fullPath);
|
|
3011
|
-
if (exists) {
|
|
3012
|
-
commands.push(`source ${file}`);
|
|
3013
|
-
}
|
|
3014
|
-
}
|
|
3015
|
-
return commands;
|
|
3016
|
-
}
|
|
3017
|
-
async function findEnvFileContainingVariable(workspacePath, variableName, fileExists, getEnvVariable) {
|
|
3018
|
-
const files = getDotenvFlowFiles().reverse();
|
|
3019
|
-
for (const file of files) {
|
|
3020
|
-
const fullPath = path5.join(workspacePath, file);
|
|
3021
|
-
if (!await fileExists(fullPath)) {
|
|
3022
|
-
continue;
|
|
3023
|
-
}
|
|
3024
|
-
const value = await getEnvVariable(fullPath, variableName);
|
|
3025
|
-
if (value !== null) {
|
|
3026
|
-
return file;
|
|
3027
|
-
}
|
|
3028
|
-
}
|
|
3029
|
-
return null;
|
|
3030
|
-
}
|
|
3031
|
-
async function hasVariableInAnyEnvFile(workspacePath, variableName, fileExists, getEnvVariable) {
|
|
3032
|
-
const file = await findEnvFileContainingVariable(workspacePath, variableName, fileExists, getEnvVariable);
|
|
3033
|
-
return file !== null;
|
|
3034
|
-
}
|
|
3259
|
+
init_env();
|
|
3035
3260
|
|
|
3036
3261
|
// src/utils/port.ts
|
|
3037
3262
|
import { createHash } from "crypto";
|
|
@@ -3248,6 +3473,7 @@ var EnvironmentManager = class {
|
|
|
3248
3473
|
};
|
|
3249
3474
|
|
|
3250
3475
|
// src/lib/DatabaseManager.ts
|
|
3476
|
+
init_env();
|
|
3251
3477
|
import fs4 from "fs-extra";
|
|
3252
3478
|
var DatabaseManager = class {
|
|
3253
3479
|
constructor(provider, environment, databaseUrlEnvVarName = "DATABASE_URL") {
|
|
@@ -3481,140 +3707,7 @@ import { execa as execa4 } from "execa";
|
|
|
3481
3707
|
import { existsSync as existsSync2 } from "fs";
|
|
3482
3708
|
import { join } from "path";
|
|
3483
3709
|
import { createHash as createHash3 } from "crypto";
|
|
3484
|
-
|
|
3485
|
-
// src/utils/terminal.ts
|
|
3486
|
-
import { execa as execa3 } from "execa";
|
|
3487
|
-
import { existsSync } from "fs";
|
|
3488
|
-
function detectPlatform() {
|
|
3489
|
-
const platform = process.platform;
|
|
3490
|
-
if (platform === "darwin") return "darwin";
|
|
3491
|
-
if (platform === "linux") return "linux";
|
|
3492
|
-
if (platform === "win32") return "win32";
|
|
3493
|
-
return "unsupported";
|
|
3494
|
-
}
|
|
3495
|
-
async function detectITerm2() {
|
|
3496
|
-
const platform = detectPlatform();
|
|
3497
|
-
if (platform !== "darwin") return false;
|
|
3498
|
-
return existsSync("/Applications/iTerm.app");
|
|
3499
|
-
}
|
|
3500
|
-
async function openTerminalWindow(options) {
|
|
3501
|
-
const platform = detectPlatform();
|
|
3502
|
-
if (platform !== "darwin") {
|
|
3503
|
-
throw new Error(
|
|
3504
|
-
`Terminal window launching not yet supported on ${platform}. Currently only macOS is supported.`
|
|
3505
|
-
);
|
|
3506
|
-
}
|
|
3507
|
-
const hasITerm2 = await detectITerm2();
|
|
3508
|
-
const applescript = hasITerm2 ? await buildITerm2SingleTabScript(options) : await buildAppleScript(options);
|
|
3509
|
-
try {
|
|
3510
|
-
await execa3("osascript", ["-e", applescript]);
|
|
3511
|
-
if (!hasITerm2) {
|
|
3512
|
-
await execa3("osascript", ["-e", 'tell application "Terminal" to activate']);
|
|
3513
|
-
}
|
|
3514
|
-
} catch (error) {
|
|
3515
|
-
throw new Error(
|
|
3516
|
-
`Failed to open terminal window: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
3517
|
-
);
|
|
3518
|
-
}
|
|
3519
|
-
}
|
|
3520
|
-
async function buildAppleScript(options) {
|
|
3521
|
-
const {
|
|
3522
|
-
workspacePath,
|
|
3523
|
-
command,
|
|
3524
|
-
backgroundColor,
|
|
3525
|
-
port,
|
|
3526
|
-
includeEnvSetup,
|
|
3527
|
-
includePortExport
|
|
3528
|
-
} = options;
|
|
3529
|
-
const commands = [];
|
|
3530
|
-
if (workspacePath) {
|
|
3531
|
-
commands.push(`cd '${escapePathForAppleScript(workspacePath)}'`);
|
|
3532
|
-
}
|
|
3533
|
-
if (includeEnvSetup && workspacePath) {
|
|
3534
|
-
const sourceCommands = await buildEnvSourceCommands(
|
|
3535
|
-
workspacePath,
|
|
3536
|
-
async (p) => existsSync(p)
|
|
3537
|
-
);
|
|
3538
|
-
commands.push(...sourceCommands);
|
|
3539
|
-
}
|
|
3540
|
-
if (includePortExport && port !== void 0) {
|
|
3541
|
-
commands.push(`export PORT=${port}`);
|
|
3542
|
-
}
|
|
3543
|
-
if (command) {
|
|
3544
|
-
commands.push(command);
|
|
3545
|
-
}
|
|
3546
|
-
const fullCommand = commands.join(" && ");
|
|
3547
|
-
const historyFreeCommand = ` ${fullCommand}`;
|
|
3548
|
-
let script = `tell application "Terminal"
|
|
3549
|
-
`;
|
|
3550
|
-
script += ` set newTab to do script "${escapeForAppleScript(historyFreeCommand)}"
|
|
3551
|
-
`;
|
|
3552
|
-
if (backgroundColor) {
|
|
3553
|
-
const { r, g, b } = backgroundColor;
|
|
3554
|
-
script += ` set background color of newTab to {${Math.round(r * 257)}, ${Math.round(g * 257)}, ${Math.round(b * 257)}}
|
|
3555
|
-
`;
|
|
3556
|
-
}
|
|
3557
|
-
script += `end tell`;
|
|
3558
|
-
return script;
|
|
3559
|
-
}
|
|
3560
|
-
function escapePathForAppleScript(path7) {
|
|
3561
|
-
return path7.replace(/'/g, "'\\''");
|
|
3562
|
-
}
|
|
3563
|
-
function escapeForAppleScript(command) {
|
|
3564
|
-
return command.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
3565
|
-
}
|
|
3566
|
-
async function buildITerm2SingleTabScript(options) {
|
|
3567
|
-
const command = await buildCommandSequence(options);
|
|
3568
|
-
let script = 'tell application id "com.googlecode.iterm2"\n';
|
|
3569
|
-
script += " create window with default profile\n";
|
|
3570
|
-
script += " set s1 to current session of current window\n\n";
|
|
3571
|
-
if (options.backgroundColor) {
|
|
3572
|
-
const { r, g, b } = options.backgroundColor;
|
|
3573
|
-
script += ` set background color of s1 to {${Math.round(r * 257)}, ${Math.round(g * 257)}, ${Math.round(b * 257)}}
|
|
3574
|
-
`;
|
|
3575
|
-
}
|
|
3576
|
-
script += ` tell s1 to write text "${escapeForAppleScript(command)}"
|
|
3577
|
-
|
|
3578
|
-
`;
|
|
3579
|
-
if (options.title) {
|
|
3580
|
-
script += ` set name of s1 to "${escapeForAppleScript(options.title)}"
|
|
3581
|
-
|
|
3582
|
-
`;
|
|
3583
|
-
}
|
|
3584
|
-
script += " activate\n";
|
|
3585
|
-
script += "end tell";
|
|
3586
|
-
return script;
|
|
3587
|
-
}
|
|
3588
|
-
async function buildCommandSequence(options) {
|
|
3589
|
-
const {
|
|
3590
|
-
workspacePath,
|
|
3591
|
-
command,
|
|
3592
|
-
port,
|
|
3593
|
-
includeEnvSetup,
|
|
3594
|
-
includePortExport
|
|
3595
|
-
} = options;
|
|
3596
|
-
const commands = [];
|
|
3597
|
-
if (workspacePath) {
|
|
3598
|
-
commands.push(`cd '${escapePathForAppleScript(workspacePath)}'`);
|
|
3599
|
-
}
|
|
3600
|
-
if (includeEnvSetup && workspacePath) {
|
|
3601
|
-
const sourceCommands = await buildEnvSourceCommands(
|
|
3602
|
-
workspacePath,
|
|
3603
|
-
async (p) => existsSync(p)
|
|
3604
|
-
);
|
|
3605
|
-
commands.push(...sourceCommands);
|
|
3606
|
-
}
|
|
3607
|
-
if (includePortExport && port !== void 0) {
|
|
3608
|
-
commands.push(`export PORT=${port}`);
|
|
3609
|
-
}
|
|
3610
|
-
if (command) {
|
|
3611
|
-
commands.push(command);
|
|
3612
|
-
}
|
|
3613
|
-
const fullCommand = commands.join(" && ");
|
|
3614
|
-
return ` ${fullCommand}`;
|
|
3615
|
-
}
|
|
3616
|
-
|
|
3617
|
-
// src/utils/claude.ts
|
|
3710
|
+
init_terminal();
|
|
3618
3711
|
async function detectClaudeCli() {
|
|
3619
3712
|
try {
|
|
3620
3713
|
await execa4("command", ["-v", "claude"], {
|
|
@@ -4630,6 +4723,7 @@ export {
|
|
|
4630
4723
|
getDefaultBranch,
|
|
4631
4724
|
getMergeTargetBranch,
|
|
4632
4725
|
getRepoRoot,
|
|
4726
|
+
getThemeMode,
|
|
4633
4727
|
getWorktreeRoot,
|
|
4634
4728
|
hasUncommittedChanges,
|
|
4635
4729
|
isBranchMergedIntoMain,
|
|
@@ -4645,6 +4739,7 @@ export {
|
|
|
4645
4739
|
parseWorktreeList,
|
|
4646
4740
|
pushBranchToRemote,
|
|
4647
4741
|
removePlaceholderCommitFromHead,
|
|
4648
|
-
removePlaceholderCommitFromHistory
|
|
4742
|
+
removePlaceholderCommitFromHistory,
|
|
4743
|
+
setThemeMode
|
|
4649
4744
|
};
|
|
4650
4745
|
//# sourceMappingURL=index.js.map
|