@iloom/cli 0.1.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +33 -0
- package/README.md +711 -0
- package/dist/ClaudeContextManager-XOSXQ67R.js +13 -0
- package/dist/ClaudeContextManager-XOSXQ67R.js.map +1 -0
- package/dist/ClaudeService-YSZ6EXWP.js +12 -0
- package/dist/ClaudeService-YSZ6EXWP.js.map +1 -0
- package/dist/GitHubService-F7Z3XJOS.js +11 -0
- package/dist/GitHubService-F7Z3XJOS.js.map +1 -0
- package/dist/LoomLauncher-MODG2SEM.js +263 -0
- package/dist/LoomLauncher-MODG2SEM.js.map +1 -0
- package/dist/NeonProvider-PAGPUH7F.js +12 -0
- package/dist/NeonProvider-PAGPUH7F.js.map +1 -0
- package/dist/PromptTemplateManager-7FINLRDE.js +9 -0
- package/dist/PromptTemplateManager-7FINLRDE.js.map +1 -0
- package/dist/SettingsManager-VAZF26S2.js +19 -0
- package/dist/SettingsManager-VAZF26S2.js.map +1 -0
- package/dist/SettingsMigrationManager-MTQIMI54.js +146 -0
- package/dist/SettingsMigrationManager-MTQIMI54.js.map +1 -0
- package/dist/add-issue-22JBNOML.js +54 -0
- package/dist/add-issue-22JBNOML.js.map +1 -0
- package/dist/agents/iloom-issue-analyze-and-plan.md +580 -0
- package/dist/agents/iloom-issue-analyzer.md +290 -0
- package/dist/agents/iloom-issue-complexity-evaluator.md +224 -0
- package/dist/agents/iloom-issue-enhancer.md +266 -0
- package/dist/agents/iloom-issue-implementer.md +262 -0
- package/dist/agents/iloom-issue-planner.md +358 -0
- package/dist/agents/iloom-issue-reviewer.md +63 -0
- package/dist/chunk-2ZPFJQ3B.js +63 -0
- package/dist/chunk-2ZPFJQ3B.js.map +1 -0
- package/dist/chunk-37DYYFVK.js +29 -0
- package/dist/chunk-37DYYFVK.js.map +1 -0
- package/dist/chunk-BLCTGFZN.js +121 -0
- package/dist/chunk-BLCTGFZN.js.map +1 -0
- package/dist/chunk-CP2NU2JC.js +545 -0
- package/dist/chunk-CP2NU2JC.js.map +1 -0
- package/dist/chunk-CWR2SANQ.js +39 -0
- package/dist/chunk-CWR2SANQ.js.map +1 -0
- package/dist/chunk-F3XBU2R7.js +110 -0
- package/dist/chunk-F3XBU2R7.js.map +1 -0
- package/dist/chunk-GEHQXLEI.js +130 -0
- package/dist/chunk-GEHQXLEI.js.map +1 -0
- package/dist/chunk-GYCR2LOU.js +143 -0
- package/dist/chunk-GYCR2LOU.js.map +1 -0
- package/dist/chunk-GZP4UGGM.js +48 -0
- package/dist/chunk-GZP4UGGM.js.map +1 -0
- package/dist/chunk-H4E4THUZ.js +55 -0
- package/dist/chunk-H4E4THUZ.js.map +1 -0
- package/dist/chunk-HPJJSYNS.js +644 -0
- package/dist/chunk-HPJJSYNS.js.map +1 -0
- package/dist/chunk-JBH2ZYYZ.js +220 -0
- package/dist/chunk-JBH2ZYYZ.js.map +1 -0
- package/dist/chunk-JNKJ7NJV.js +78 -0
- package/dist/chunk-JNKJ7NJV.js.map +1 -0
- package/dist/chunk-JQ7VOSTC.js +437 -0
- package/dist/chunk-JQ7VOSTC.js.map +1 -0
- package/dist/chunk-KQDEK2ZW.js +199 -0
- package/dist/chunk-KQDEK2ZW.js.map +1 -0
- package/dist/chunk-O2QWO64Z.js +179 -0
- package/dist/chunk-O2QWO64Z.js.map +1 -0
- package/dist/chunk-OC4H6HJD.js +248 -0
- package/dist/chunk-OC4H6HJD.js.map +1 -0
- package/dist/chunk-PR7FKQBG.js +120 -0
- package/dist/chunk-PR7FKQBG.js.map +1 -0
- package/dist/chunk-PXZBAC2M.js +250 -0
- package/dist/chunk-PXZBAC2M.js.map +1 -0
- package/dist/chunk-QEPVTTHD.js +383 -0
- package/dist/chunk-QEPVTTHD.js.map +1 -0
- package/dist/chunk-RSRO7564.js +203 -0
- package/dist/chunk-RSRO7564.js.map +1 -0
- package/dist/chunk-SJUQ2NDR.js +146 -0
- package/dist/chunk-SJUQ2NDR.js.map +1 -0
- package/dist/chunk-SPYPLHMK.js +177 -0
- package/dist/chunk-SPYPLHMK.js.map +1 -0
- package/dist/chunk-SSCQCCJ7.js +75 -0
- package/dist/chunk-SSCQCCJ7.js.map +1 -0
- package/dist/chunk-SSR5AVRJ.js +41 -0
- package/dist/chunk-SSR5AVRJ.js.map +1 -0
- package/dist/chunk-T7QPXANZ.js +315 -0
- package/dist/chunk-T7QPXANZ.js.map +1 -0
- package/dist/chunk-U3WU5OWO.js +203 -0
- package/dist/chunk-U3WU5OWO.js.map +1 -0
- package/dist/chunk-W3DQTW63.js +124 -0
- package/dist/chunk-W3DQTW63.js.map +1 -0
- package/dist/chunk-WKEWRSDB.js +151 -0
- package/dist/chunk-WKEWRSDB.js.map +1 -0
- package/dist/chunk-Y7SAGNUT.js +66 -0
- package/dist/chunk-Y7SAGNUT.js.map +1 -0
- package/dist/chunk-YETJNRQM.js +39 -0
- package/dist/chunk-YETJNRQM.js.map +1 -0
- package/dist/chunk-YYSKGAZT.js +384 -0
- package/dist/chunk-YYSKGAZT.js.map +1 -0
- package/dist/chunk-ZZZWQGTS.js +169 -0
- package/dist/chunk-ZZZWQGTS.js.map +1 -0
- package/dist/claude-7LUVDZZ4.js +17 -0
- package/dist/claude-7LUVDZZ4.js.map +1 -0
- package/dist/cleanup-3LUWPSM7.js +412 -0
- package/dist/cleanup-3LUWPSM7.js.map +1 -0
- package/dist/cli-overrides-XFZWY7CM.js +16 -0
- package/dist/cli-overrides-XFZWY7CM.js.map +1 -0
- package/dist/cli.js +603 -0
- package/dist/cli.js.map +1 -0
- package/dist/color-ZVALX37U.js +21 -0
- package/dist/color-ZVALX37U.js.map +1 -0
- package/dist/enhance-XJIQHVPD.js +166 -0
- package/dist/enhance-XJIQHVPD.js.map +1 -0
- package/dist/env-MDFL4ZXL.js +23 -0
- package/dist/env-MDFL4ZXL.js.map +1 -0
- package/dist/feedback-23CLXKFT.js +158 -0
- package/dist/feedback-23CLXKFT.js.map +1 -0
- package/dist/finish-CY4CIH6O.js +1608 -0
- package/dist/finish-CY4CIH6O.js.map +1 -0
- package/dist/git-LVRZ57GJ.js +43 -0
- package/dist/git-LVRZ57GJ.js.map +1 -0
- package/dist/ignite-WXEF2ID5.js +359 -0
- package/dist/ignite-WXEF2ID5.js.map +1 -0
- package/dist/index.d.ts +1341 -0
- package/dist/index.js +3058 -0
- package/dist/index.js.map +1 -0
- package/dist/init-RHACUR4E.js +123 -0
- package/dist/init-RHACUR4E.js.map +1 -0
- package/dist/installation-detector-VARGFFRZ.js +11 -0
- package/dist/installation-detector-VARGFFRZ.js.map +1 -0
- package/dist/logger-MKYH4UDV.js +12 -0
- package/dist/logger-MKYH4UDV.js.map +1 -0
- package/dist/mcp/chunk-6SDFJ42P.js +62 -0
- package/dist/mcp/chunk-6SDFJ42P.js.map +1 -0
- package/dist/mcp/claude-YHHHLSXH.js +249 -0
- package/dist/mcp/claude-YHHHLSXH.js.map +1 -0
- package/dist/mcp/color-QS5BFCNN.js +168 -0
- package/dist/mcp/color-QS5BFCNN.js.map +1 -0
- package/dist/mcp/github-comment-server.js +165 -0
- package/dist/mcp/github-comment-server.js.map +1 -0
- package/dist/mcp/terminal-SDCMDVD7.js +202 -0
- package/dist/mcp/terminal-SDCMDVD7.js.map +1 -0
- package/dist/open-X6BTENPV.js +278 -0
- package/dist/open-X6BTENPV.js.map +1 -0
- package/dist/prompt-ANTQWHUF.js +13 -0
- package/dist/prompt-ANTQWHUF.js.map +1 -0
- package/dist/prompts/issue-prompt.txt +230 -0
- package/dist/prompts/pr-prompt.txt +35 -0
- package/dist/prompts/regular-prompt.txt +14 -0
- package/dist/run-2JCPQAX3.js +278 -0
- package/dist/run-2JCPQAX3.js.map +1 -0
- package/dist/schema/settings.schema.json +221 -0
- package/dist/start-LWVRBJ6S.js +982 -0
- package/dist/start-LWVRBJ6S.js.map +1 -0
- package/dist/terminal-3D6TUAKJ.js +16 -0
- package/dist/terminal-3D6TUAKJ.js.map +1 -0
- package/dist/test-git-XPF4SZXJ.js +52 -0
- package/dist/test-git-XPF4SZXJ.js.map +1 -0
- package/dist/test-prefix-XGFXFAYN.js +68 -0
- package/dist/test-prefix-XGFXFAYN.js.map +1 -0
- package/dist/test-tabs-JRKY3QMM.js +69 -0
- package/dist/test-tabs-JRKY3QMM.js.map +1 -0
- package/dist/test-webserver-M2I3EV4J.js +62 -0
- package/dist/test-webserver-M2I3EV4J.js.map +1 -0
- package/dist/update-3ZT2XX2G.js +79 -0
- package/dist/update-3ZT2XX2G.js.map +1 -0
- package/dist/update-notifier-QSSEB5KC.js +11 -0
- package/dist/update-notifier-QSSEB5KC.js.map +1 -0
- package/package.json +113 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
hasWebDependencies,
|
|
4
|
+
parseBinField,
|
|
5
|
+
readPackageJson
|
|
6
|
+
} from "./chunk-2ZPFJQ3B.js";
|
|
7
|
+
|
|
8
|
+
// src/lib/ProjectCapabilityDetector.ts
|
|
9
|
+
var ProjectCapabilityDetector = class {
|
|
10
|
+
/**
|
|
11
|
+
* Detect project capabilities by analyzing package.json
|
|
12
|
+
* @param worktreePath Path to the worktree directory
|
|
13
|
+
* @returns Project capabilities and bin entries
|
|
14
|
+
*/
|
|
15
|
+
async detectCapabilities(worktreePath) {
|
|
16
|
+
try {
|
|
17
|
+
const pkgJson = await readPackageJson(worktreePath);
|
|
18
|
+
const capabilities = [];
|
|
19
|
+
if (pkgJson.bin) {
|
|
20
|
+
capabilities.push("cli");
|
|
21
|
+
}
|
|
22
|
+
if (hasWebDependencies(pkgJson)) {
|
|
23
|
+
capabilities.push("web");
|
|
24
|
+
}
|
|
25
|
+
const binEntries = pkgJson.bin ? parseBinField(pkgJson.bin, pkgJson.name) : {};
|
|
26
|
+
return { capabilities, binEntries };
|
|
27
|
+
} catch (error) {
|
|
28
|
+
if (error instanceof Error && error.message.includes("package.json not found")) {
|
|
29
|
+
return { capabilities: [], binEntries: {} };
|
|
30
|
+
}
|
|
31
|
+
throw error;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export {
|
|
37
|
+
ProjectCapabilityDetector
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=chunk-CWR2SANQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/ProjectCapabilityDetector.ts"],"sourcesContent":["import { readPackageJson, parseBinField, hasWebDependencies } from '../utils/package-json.js'\nimport type { ProjectCapability } from '../types/loom.js'\n\nexport interface ProjectCapabilities {\n capabilities: ProjectCapability[]\n binEntries: Record<string, string>\n}\n\nexport class ProjectCapabilityDetector {\n /**\n * Detect project capabilities by analyzing package.json\n * @param worktreePath Path to the worktree directory\n * @returns Project capabilities and bin entries\n */\n async detectCapabilities(worktreePath: string): Promise<ProjectCapabilities> {\n try {\n const pkgJson = await readPackageJson(worktreePath)\n const capabilities: ProjectCapability[] = []\n\n // CLI detection: has bin field\n if (pkgJson.bin) {\n capabilities.push('cli')\n }\n\n // Web detection: has web framework dependencies\n if (hasWebDependencies(pkgJson)) {\n capabilities.push('web')\n }\n\n // Parse bin entries for CLI projects\n const binEntries = pkgJson.bin ? parseBinField(pkgJson.bin, pkgJson.name) : {}\n\n return { capabilities, binEntries }\n } catch (error) {\n // Handle missing package.json - return empty capabilities for non-Node.js projects\n if (error instanceof Error && error.message.includes('package.json not found')) {\n return { capabilities: [], binEntries: {} }\n }\n // Re-throw other errors (invalid JSON, etc.)\n throw error\n }\n }\n}\n"],"mappings":";;;;;;;;AAQO,IAAM,4BAAN,MAAgC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMrC,MAAM,mBAAmB,cAAoD;AAC3E,QAAI;AACF,YAAM,UAAU,MAAM,gBAAgB,YAAY;AAClD,YAAM,eAAoC,CAAC;AAG3C,UAAI,QAAQ,KAAK;AACf,qBAAa,KAAK,KAAK;AAAA,MACzB;AAGA,UAAI,mBAAmB,OAAO,GAAG;AAC/B,qBAAa,KAAK,KAAK;AAAA,MACzB;AAGA,YAAM,aAAa,QAAQ,MAAM,cAAc,QAAQ,KAAK,QAAQ,IAAI,IAAI,CAAC;AAE7E,aAAO,EAAE,cAAc,WAAW;AAAA,IACpC,SAAS,OAAO;AAEd,UAAI,iBAAiB,SAAS,MAAM,QAAQ,SAAS,wBAAwB,GAAG;AAC9E,eAAO,EAAE,cAAc,CAAC,GAAG,YAAY,CAAC,EAAE;AAAA,MAC5C;AAEA,YAAM;AAAA,IACR;AAAA,EACF;AACF;","names":[]}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
logger
|
|
4
|
+
} from "./chunk-GEHQXLEI.js";
|
|
5
|
+
|
|
6
|
+
// src/lib/PromptTemplateManager.ts
|
|
7
|
+
import { readFile } from "fs/promises";
|
|
8
|
+
import { accessSync } from "fs";
|
|
9
|
+
import path from "path";
|
|
10
|
+
import { fileURLToPath } from "url";
|
|
11
|
+
var PromptTemplateManager = class {
|
|
12
|
+
constructor(templateDir) {
|
|
13
|
+
if (templateDir) {
|
|
14
|
+
this.templateDir = templateDir;
|
|
15
|
+
} else {
|
|
16
|
+
const currentFileUrl = import.meta.url;
|
|
17
|
+
const currentFilePath = fileURLToPath(currentFileUrl);
|
|
18
|
+
const distDir = path.dirname(currentFilePath);
|
|
19
|
+
let templateDir2 = path.join(distDir, "prompts");
|
|
20
|
+
let currentDir = distDir;
|
|
21
|
+
while (currentDir !== path.dirname(currentDir)) {
|
|
22
|
+
const candidatePath = path.join(currentDir, "prompts");
|
|
23
|
+
try {
|
|
24
|
+
accessSync(candidatePath);
|
|
25
|
+
templateDir2 = candidatePath;
|
|
26
|
+
break;
|
|
27
|
+
} catch {
|
|
28
|
+
currentDir = path.dirname(currentDir);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
this.templateDir = templateDir2;
|
|
32
|
+
logger.debug("PromptTemplateManager initialized", {
|
|
33
|
+
currentFilePath,
|
|
34
|
+
distDir,
|
|
35
|
+
templateDir: this.templateDir
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Load a template file by name
|
|
41
|
+
*/
|
|
42
|
+
async loadTemplate(templateName) {
|
|
43
|
+
const templatePath = path.join(this.templateDir, `${templateName}-prompt.txt`);
|
|
44
|
+
logger.debug("Loading template", {
|
|
45
|
+
templateName,
|
|
46
|
+
templateDir: this.templateDir,
|
|
47
|
+
templatePath
|
|
48
|
+
});
|
|
49
|
+
try {
|
|
50
|
+
return await readFile(templatePath, "utf-8");
|
|
51
|
+
} catch (error) {
|
|
52
|
+
logger.error("Failed to load template", { templateName, templatePath, error });
|
|
53
|
+
throw new Error(`Template not found: ${templatePath}`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Substitute variables in a template string
|
|
58
|
+
*/
|
|
59
|
+
substituteVariables(template, variables) {
|
|
60
|
+
let result = template;
|
|
61
|
+
result = this.processConditionalSections(result, variables);
|
|
62
|
+
if (variables.ISSUE_NUMBER !== void 0) {
|
|
63
|
+
result = result.replace(/ISSUE_NUMBER/g, String(variables.ISSUE_NUMBER));
|
|
64
|
+
}
|
|
65
|
+
if (variables.PR_NUMBER !== void 0) {
|
|
66
|
+
result = result.replace(/PR_NUMBER/g, String(variables.PR_NUMBER));
|
|
67
|
+
}
|
|
68
|
+
if (variables.ISSUE_TITLE !== void 0) {
|
|
69
|
+
result = result.replace(/ISSUE_TITLE/g, variables.ISSUE_TITLE);
|
|
70
|
+
}
|
|
71
|
+
if (variables.PR_TITLE !== void 0) {
|
|
72
|
+
result = result.replace(/PR_TITLE/g, variables.PR_TITLE);
|
|
73
|
+
}
|
|
74
|
+
if (variables.WORKSPACE_PATH !== void 0) {
|
|
75
|
+
result = result.replace(/WORKSPACE_PATH/g, variables.WORKSPACE_PATH);
|
|
76
|
+
}
|
|
77
|
+
if (variables.PORT !== void 0) {
|
|
78
|
+
result = result.replace(/PORT/g, String(variables.PORT));
|
|
79
|
+
}
|
|
80
|
+
return result;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Process conditional sections in template
|
|
84
|
+
* Format: {{#IF ONE_SHOT_MODE}}content{{/IF ONE_SHOT_MODE}}
|
|
85
|
+
*
|
|
86
|
+
* Note: /s flag allows . to match newlines
|
|
87
|
+
*/
|
|
88
|
+
processConditionalSections(template, variables) {
|
|
89
|
+
let result = template;
|
|
90
|
+
const oneShotRegex = /\{\{#IF ONE_SHOT_MODE\}\}(.*?)\{\{\/IF ONE_SHOT_MODE\}\}/gs;
|
|
91
|
+
if (variables.ONE_SHOT_MODE === true) {
|
|
92
|
+
result = result.replace(oneShotRegex, "$1");
|
|
93
|
+
} else {
|
|
94
|
+
result = result.replace(oneShotRegex, "");
|
|
95
|
+
}
|
|
96
|
+
return result;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Get a fully processed prompt for a workflow type
|
|
100
|
+
*/
|
|
101
|
+
async getPrompt(type, variables) {
|
|
102
|
+
const template = await this.loadTemplate(type);
|
|
103
|
+
return this.substituteVariables(template, variables);
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
export {
|
|
108
|
+
PromptTemplateManager
|
|
109
|
+
};
|
|
110
|
+
//# sourceMappingURL=chunk-F3XBU2R7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/PromptTemplateManager.ts"],"sourcesContent":["import { readFile } from 'fs/promises'\nimport { accessSync } from 'fs'\nimport path from 'path'\nimport { fileURLToPath } from 'url'\nimport { logger } from '../utils/logger.js'\n\nexport interface TemplateVariables {\n\tISSUE_NUMBER?: number\n\tPR_NUMBER?: number\n\tISSUE_TITLE?: string\n\tPR_TITLE?: string\n\tWORKSPACE_PATH?: string\n\tPORT?: number\n\tONE_SHOT_MODE?: boolean\n}\n\nexport class PromptTemplateManager {\n\tprivate templateDir: string\n\n\tconstructor(templateDir?: string) {\n\t\tif (templateDir) {\n\t\t\tthis.templateDir = templateDir\n\t\t} else {\n\t\t\t// Find templates relative to the package installation\n\t\t\t// When running from dist/, templates are copied to dist/prompts/\n\t\t\tconst currentFileUrl = import.meta.url\n\t\t\tconst currentFilePath = fileURLToPath(currentFileUrl)\n\t\t\tconst distDir = path.dirname(currentFilePath) // dist directory (may be chunked file location)\n\n\t\t\t// Walk up to find the dist directory (in case of chunked files)\n\t\t\tlet templateDir = path.join(distDir, 'prompts')\n\t\t\tlet currentDir = distDir\n\n\t\t\t// Try to find the prompts directory by walking up\n\t\t\twhile (currentDir !== path.dirname(currentDir)) {\n\t\t\t\tconst candidatePath = path.join(currentDir, 'prompts')\n\t\t\t\ttry {\n\t\t\t\t\t// Check if this directory exists (sync check for constructor)\n\t\t\t\t\taccessSync(candidatePath)\n\t\t\t\t\ttemplateDir = candidatePath\n\t\t\t\t\tbreak\n\t\t\t\t} catch {\n\t\t\t\t\tcurrentDir = path.dirname(currentDir)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.templateDir = templateDir\n\t\t\tlogger.debug('PromptTemplateManager initialized', {\n\t\t\t\tcurrentFilePath,\n\t\t\t\tdistDir,\n\t\t\t\ttemplateDir: this.templateDir\n\t\t\t})\n\t\t}\n\t}\n\n\t/**\n\t * Load a template file by name\n\t */\n\tasync loadTemplate(templateName: 'issue' | 'pr' | 'regular'): Promise<string> {\n\t\tconst templatePath = path.join(this.templateDir, `${templateName}-prompt.txt`)\n\n\t\tlogger.debug('Loading template', {\n\t\t\ttemplateName,\n\t\t\ttemplateDir: this.templateDir,\n\t\t\ttemplatePath\n\t\t})\n\n\t\ttry {\n\t\t\treturn await readFile(templatePath, 'utf-8')\n\t\t} catch (error) {\n\t\t\tlogger.error('Failed to load template', { templateName, templatePath, error })\n\t\t\tthrow new Error(`Template not found: ${templatePath}`)\n\t\t}\n\t}\n\n\t/**\n\t * Substitute variables in a template string\n\t */\n\tsubstituteVariables(template: string, variables: TemplateVariables): string {\n\t\tlet result = template\n\n\t\t// Process conditional sections first\n\t\tresult = this.processConditionalSections(result, variables)\n\n\t\t// Replace each variable if it exists\n\t\tif (variables.ISSUE_NUMBER !== undefined) {\n\t\t\tresult = result.replace(/ISSUE_NUMBER/g, String(variables.ISSUE_NUMBER))\n\t\t}\n\n\t\tif (variables.PR_NUMBER !== undefined) {\n\t\t\tresult = result.replace(/PR_NUMBER/g, String(variables.PR_NUMBER))\n\t\t}\n\n\t\tif (variables.ISSUE_TITLE !== undefined) {\n\t\t\tresult = result.replace(/ISSUE_TITLE/g, variables.ISSUE_TITLE)\n\t\t}\n\n\t\tif (variables.PR_TITLE !== undefined) {\n\t\t\tresult = result.replace(/PR_TITLE/g, variables.PR_TITLE)\n\t\t}\n\n\t\tif (variables.WORKSPACE_PATH !== undefined) {\n\t\t\tresult = result.replace(/WORKSPACE_PATH/g, variables.WORKSPACE_PATH)\n\t\t}\n\n\t\tif (variables.PORT !== undefined) {\n\t\t\tresult = result.replace(/PORT/g, String(variables.PORT))\n\t\t}\n\n\t\treturn result\n\t}\n\n\t/**\n\t * Process conditional sections in template\n\t * Format: {{#IF ONE_SHOT_MODE}}content{{/IF ONE_SHOT_MODE}}\n\t * \n\t * Note: /s flag allows . to match newlines\n\t */\n\tprivate processConditionalSections(template: string, variables: TemplateVariables): string {\n\t\tlet result = template\n\n\t\t// Process ONE_SHOT_MODE conditionals\n\t\tconst oneShotRegex = /\\{\\{#IF ONE_SHOT_MODE\\}\\}(.*?)\\{\\{\\/IF ONE_SHOT_MODE\\}\\}/gs\n\n\t\tif (variables.ONE_SHOT_MODE === true) {\n\t\t\t// Include the content, remove the conditional markers\n\t\t\tresult = result.replace(oneShotRegex, '$1')\n\t\t} else {\n\t\t\t// Remove the entire conditional block\n\t\t\tresult = result.replace(oneShotRegex, '')\n\t\t}\n\n\t\treturn result\n\t}\n\n\t/**\n\t * Get a fully processed prompt for a workflow type\n\t */\n\tasync getPrompt(\n\t\ttype: 'issue' | 'pr' | 'regular',\n\t\tvariables: TemplateVariables\n\t): Promise<string> {\n\t\tconst template = await this.loadTemplate(type)\n\t\treturn this.substituteVariables(template, variables)\n\t}\n}\n"],"mappings":";;;;;;AAAA,SAAS,gBAAgB;AACzB,SAAS,kBAAkB;AAC3B,OAAO,UAAU;AACjB,SAAS,qBAAqB;AAavB,IAAM,wBAAN,MAA4B;AAAA,EAGlC,YAAY,aAAsB;AACjC,QAAI,aAAa;AAChB,WAAK,cAAc;AAAA,IACpB,OAAO;AAGN,YAAM,iBAAiB,YAAY;AACnC,YAAM,kBAAkB,cAAc,cAAc;AACpD,YAAM,UAAU,KAAK,QAAQ,eAAe;AAG5C,UAAIA,eAAc,KAAK,KAAK,SAAS,SAAS;AAC9C,UAAI,aAAa;AAGjB,aAAO,eAAe,KAAK,QAAQ,UAAU,GAAG;AAC/C,cAAM,gBAAgB,KAAK,KAAK,YAAY,SAAS;AACrD,YAAI;AAEH,qBAAW,aAAa;AACxB,UAAAA,eAAc;AACd;AAAA,QACD,QAAQ;AACP,uBAAa,KAAK,QAAQ,UAAU;AAAA,QACrC;AAAA,MACD;AAEA,WAAK,cAAcA;AACnB,aAAO,MAAM,qCAAqC;AAAA,QACjD;AAAA,QACA;AAAA,QACA,aAAa,KAAK;AAAA,MACnB,CAAC;AAAA,IACF;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAAa,cAA2D;AAC7E,UAAM,eAAe,KAAK,KAAK,KAAK,aAAa,GAAG,YAAY,aAAa;AAE7E,WAAO,MAAM,oBAAoB;AAAA,MAChC;AAAA,MACA,aAAa,KAAK;AAAA,MAClB;AAAA,IACD,CAAC;AAED,QAAI;AACH,aAAO,MAAM,SAAS,cAAc,OAAO;AAAA,IAC5C,SAAS,OAAO;AACf,aAAO,MAAM,2BAA2B,EAAE,cAAc,cAAc,MAAM,CAAC;AAC7E,YAAM,IAAI,MAAM,uBAAuB,YAAY,EAAE;AAAA,IACtD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA,oBAAoB,UAAkB,WAAsC;AAC3E,QAAI,SAAS;AAGb,aAAS,KAAK,2BAA2B,QAAQ,SAAS;AAG1D,QAAI,UAAU,iBAAiB,QAAW;AACzC,eAAS,OAAO,QAAQ,iBAAiB,OAAO,UAAU,YAAY,CAAC;AAAA,IACxE;AAEA,QAAI,UAAU,cAAc,QAAW;AACtC,eAAS,OAAO,QAAQ,cAAc,OAAO,UAAU,SAAS,CAAC;AAAA,IAClE;AAEA,QAAI,UAAU,gBAAgB,QAAW;AACxC,eAAS,OAAO,QAAQ,gBAAgB,UAAU,WAAW;AAAA,IAC9D;AAEA,QAAI,UAAU,aAAa,QAAW;AACrC,eAAS,OAAO,QAAQ,aAAa,UAAU,QAAQ;AAAA,IACxD;AAEA,QAAI,UAAU,mBAAmB,QAAW;AAC3C,eAAS,OAAO,QAAQ,mBAAmB,UAAU,cAAc;AAAA,IACpE;AAEA,QAAI,UAAU,SAAS,QAAW;AACjC,eAAS,OAAO,QAAQ,SAAS,OAAO,UAAU,IAAI,CAAC;AAAA,IACxD;AAEA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,2BAA2B,UAAkB,WAAsC;AAC1F,QAAI,SAAS;AAGb,UAAM,eAAe;AAErB,QAAI,UAAU,kBAAkB,MAAM;AAErC,eAAS,OAAO,QAAQ,cAAc,IAAI;AAAA,IAC3C,OAAO;AAEN,eAAS,OAAO,QAAQ,cAAc,EAAE;AAAA,IACzC;AAEA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,UACL,MACA,WACkB;AAClB,UAAM,WAAW,MAAM,KAAK,aAAa,IAAI;AAC7C,WAAO,KAAK,oBAAoB,UAAU,SAAS;AAAA,EACpD;AACD;","names":["templateDir"]}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/utils/logger.ts
|
|
4
|
+
import chalk, { Chalk } from "chalk";
|
|
5
|
+
var stdoutChalk = new Chalk({ level: chalk.level });
|
|
6
|
+
var stderrChalk = new Chalk({ level: chalk.level });
|
|
7
|
+
function formatMessage(message, ...args) {
|
|
8
|
+
const formattedArgs = args.map(
|
|
9
|
+
(arg) => typeof arg === "object" ? JSON.stringify(arg, null, 2) : String(arg)
|
|
10
|
+
);
|
|
11
|
+
return formattedArgs.length > 0 ? `${message} ${formattedArgs.join(" ")}` : message;
|
|
12
|
+
}
|
|
13
|
+
function formatWithEmoji(message, emoji, colorFn) {
|
|
14
|
+
if (message.trim()) {
|
|
15
|
+
return colorFn(`${emoji} ${message}`);
|
|
16
|
+
} else {
|
|
17
|
+
return "";
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
var globalDebugEnabled = false;
|
|
21
|
+
var logger = {
|
|
22
|
+
info: (message, ...args) => {
|
|
23
|
+
const formatted = formatMessage(message, ...args);
|
|
24
|
+
const output = formatWithEmoji(formatted, "\u{1F5C2}\uFE0F ", stdoutChalk.blue);
|
|
25
|
+
console.log(output);
|
|
26
|
+
},
|
|
27
|
+
success: (message, ...args) => {
|
|
28
|
+
const formatted = formatMessage(message, ...args);
|
|
29
|
+
const output = formatWithEmoji(formatted, "\u2705", stdoutChalk.green);
|
|
30
|
+
console.log(output);
|
|
31
|
+
},
|
|
32
|
+
warn: (message, ...args) => {
|
|
33
|
+
const formatted = formatMessage(message, ...args);
|
|
34
|
+
const output = formatWithEmoji(formatted, "\u26A0\uFE0F ", stderrChalk.yellow);
|
|
35
|
+
console.error(output);
|
|
36
|
+
},
|
|
37
|
+
error: (message, ...args) => {
|
|
38
|
+
const formatted = formatMessage(message, ...args);
|
|
39
|
+
const output = formatWithEmoji(formatted, "\u274C", stderrChalk.red);
|
|
40
|
+
console.error(output);
|
|
41
|
+
},
|
|
42
|
+
debug: (message, ...args) => {
|
|
43
|
+
if (globalDebugEnabled) {
|
|
44
|
+
const formatted = formatMessage(message, ...args);
|
|
45
|
+
const output = formatWithEmoji(formatted, "\u{1F50D}", stdoutChalk.gray);
|
|
46
|
+
console.log(output);
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
setDebug: (enabled) => {
|
|
50
|
+
globalDebugEnabled = enabled;
|
|
51
|
+
},
|
|
52
|
+
isDebugEnabled: () => {
|
|
53
|
+
return globalDebugEnabled;
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
function createLogger(options = {}) {
|
|
57
|
+
const { prefix = "", timestamp = false, silent = false, forceColor, debug = globalDebugEnabled } = options;
|
|
58
|
+
let localDebugEnabled = debug;
|
|
59
|
+
const customStdoutChalk = forceColor !== void 0 ? new Chalk({ level: forceColor ? 3 : 0 }) : stdoutChalk;
|
|
60
|
+
const customStderrChalk = forceColor !== void 0 ? new Chalk({ level: forceColor ? 3 : 0 }) : stderrChalk;
|
|
61
|
+
const prefixStr = prefix ? `[${prefix}] ` : "";
|
|
62
|
+
const getTimestamp = () => timestamp ? `[${(/* @__PURE__ */ new Date()).toISOString()}] ` : "";
|
|
63
|
+
if (silent) {
|
|
64
|
+
return {
|
|
65
|
+
info: () => {
|
|
66
|
+
},
|
|
67
|
+
success: () => {
|
|
68
|
+
},
|
|
69
|
+
warn: () => {
|
|
70
|
+
},
|
|
71
|
+
error: () => {
|
|
72
|
+
},
|
|
73
|
+
debug: () => {
|
|
74
|
+
},
|
|
75
|
+
setDebug: () => {
|
|
76
|
+
},
|
|
77
|
+
isDebugEnabled: () => {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
info: (message, ...args) => {
|
|
84
|
+
const formatted = formatMessage(message, ...args);
|
|
85
|
+
const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`;
|
|
86
|
+
const output = formatWithEmoji(fullMessage, "\u{1F5C2}\uFE0F ", customStdoutChalk.blue);
|
|
87
|
+
console.log(output);
|
|
88
|
+
},
|
|
89
|
+
success: (message, ...args) => {
|
|
90
|
+
const formatted = formatMessage(message, ...args);
|
|
91
|
+
const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`;
|
|
92
|
+
const output = formatWithEmoji(fullMessage, "\u2705", customStdoutChalk.green);
|
|
93
|
+
console.log(output);
|
|
94
|
+
},
|
|
95
|
+
warn: (message, ...args) => {
|
|
96
|
+
const formatted = formatMessage(message, ...args);
|
|
97
|
+
const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`;
|
|
98
|
+
const output = formatWithEmoji(fullMessage, "\u26A0\uFE0F ", customStderrChalk.yellow);
|
|
99
|
+
console.error(output);
|
|
100
|
+
},
|
|
101
|
+
error: (message, ...args) => {
|
|
102
|
+
const formatted = formatMessage(message, ...args);
|
|
103
|
+
const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`;
|
|
104
|
+
const output = formatWithEmoji(fullMessage, "\u274C", customStderrChalk.red);
|
|
105
|
+
console.error(output);
|
|
106
|
+
},
|
|
107
|
+
debug: (message, ...args) => {
|
|
108
|
+
if (localDebugEnabled) {
|
|
109
|
+
const formatted = formatMessage(message, ...args);
|
|
110
|
+
const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`;
|
|
111
|
+
const output = formatWithEmoji(fullMessage, "\u{1F50D}", customStdoutChalk.gray);
|
|
112
|
+
console.log(output);
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
setDebug: (enabled) => {
|
|
116
|
+
localDebugEnabled = enabled;
|
|
117
|
+
},
|
|
118
|
+
isDebugEnabled: () => {
|
|
119
|
+
return globalDebugEnabled;
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
var logger_default = logger;
|
|
124
|
+
|
|
125
|
+
export {
|
|
126
|
+
logger,
|
|
127
|
+
createLogger,
|
|
128
|
+
logger_default
|
|
129
|
+
};
|
|
130
|
+
//# sourceMappingURL=chunk-GEHQXLEI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/logger.ts"],"sourcesContent":["// Lines 1-5: Imports\nimport chalk, { Chalk } from 'chalk'\n\n// Lines 7-17: Type definitions\nexport interface LoggerOptions {\n prefix?: string\n timestamp?: boolean\n silent?: boolean\n forceColor?: boolean | undefined | null\n debug?: boolean\n}\n\nexport interface Logger {\n info: (message: string, ...args: unknown[]) => void\n success: (message: string, ...args: unknown[]) => void\n warn: (message: string, ...args: unknown[]) => void\n error: (message: string, ...args: unknown[]) => void\n debug: (message: string, ...args: unknown[]) => void\n setDebug: (enabled: boolean) => void\n isDebugEnabled: () => boolean\n}\n\n// Lines 19-29: Stream-specific chalk instances\nconst stdoutChalk = new Chalk({ level: chalk.level })\nconst stderrChalk = new Chalk({ level: chalk.level })\n\n// Lines 31-45: Helper functions\nfunction formatMessage(message: string, ...args: unknown[]): string {\n // Convert args to strings and append to message\n const formattedArgs = args.map(arg =>\n typeof arg === 'object' ? JSON.stringify(arg, null, 2) : String(arg)\n )\n return formattedArgs.length > 0 ? `${message} ${formattedArgs.join(' ')}` : message\n}\n\nfunction formatWithEmoji(message: string, emoji: string, colorFn: (str: string) => string): string {\n if (message.trim()) {\n return colorFn(`${emoji} ${message}`)\n } else {\n return ''\n }\n}\n\nlet globalDebugEnabled = false\n\n// Lines 47-96: Main logger implementation\n/* eslint-disable no-console */\nexport const logger: Logger = {\n info: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const output = formatWithEmoji(formatted, '🗂️ ', stdoutChalk.blue)\n console.log(output)\n },\n\n success: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const output = formatWithEmoji(formatted, '✅', stdoutChalk.green)\n console.log(output)\n },\n\n warn: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const output = formatWithEmoji(formatted, '⚠️ ', stderrChalk.yellow)\n console.error(output)\n },\n\n error: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const output = formatWithEmoji(formatted, '❌', stderrChalk.red)\n console.error(output)\n },\n\n debug: (message: string, ...args: unknown[]): void => {\n if (globalDebugEnabled) {\n const formatted = formatMessage(message, ...args)\n const output = formatWithEmoji(formatted, '🔍', stdoutChalk.gray)\n console.log(output)\n }\n },\n\n setDebug: (enabled: boolean): void => {\n globalDebugEnabled = enabled\n },\n\n isDebugEnabled: (): boolean => {\n return globalDebugEnabled\n }\n}\n/* eslint-enable no-console */\n\n// Lines 98-145: Factory function for custom logger instances\nexport function createLogger(options: LoggerOptions = {}): Logger {\n const { prefix = '', timestamp = false, silent = false, forceColor, debug = globalDebugEnabled } = options\n\n // Local debug flag for this logger instance\n let localDebugEnabled = debug\n\n // Create chalk instances with forced color if needed\n const customStdoutChalk = forceColor !== undefined\n ? new Chalk({ level: forceColor ? 3 : 0 })\n : stdoutChalk\n const customStderrChalk = forceColor !== undefined\n ? new Chalk({ level: forceColor ? 3 : 0 })\n : stderrChalk\n\n const prefixStr = prefix ? `[${prefix}] ` : ''\n const getTimestamp = (): string => timestamp ? `[${new Date().toISOString()}] ` : ''\n\n if (silent) {\n // Return no-op logger when silent\n return {\n info: (): void => {},\n success: (): void => {},\n warn: (): void => {},\n error: (): void => {},\n debug: (): void => {},\n setDebug: (): void => {},\n isDebugEnabled: (): boolean => {\n return false\n }\n }\n }\n\n /* eslint-disable no-console */\n return {\n info: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '🗂️ ', customStdoutChalk.blue)\n console.log(output)\n },\n success: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '✅', customStdoutChalk.green)\n console.log(output)\n },\n warn: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '⚠️ ', customStderrChalk.yellow)\n console.error(output)\n },\n error: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '❌', customStderrChalk.red)\n console.error(output)\n },\n debug: (message: string, ...args: unknown[]): void => {\n if (localDebugEnabled) {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '🔍', customStdoutChalk.gray)\n console.log(output)\n }\n },\n setDebug: (enabled: boolean): void => {\n localDebugEnabled = enabled\n },\n isDebugEnabled: (): boolean => {\n return globalDebugEnabled\n }\n }\n /* eslint-enable no-console */\n}\n\n// Lines 147-148: Default export\nexport default logger\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/utils/cli-overrides.ts
|
|
4
|
+
import { resolve } from "path";
|
|
5
|
+
function parseCliValue(value) {
|
|
6
|
+
if (value === "true") return true;
|
|
7
|
+
if (value === "false") return false;
|
|
8
|
+
if (/^-?\d+$/.test(value)) {
|
|
9
|
+
return parseInt(value, 10);
|
|
10
|
+
}
|
|
11
|
+
if (/^-?\d+\.\d+$/.test(value)) {
|
|
12
|
+
return parseFloat(value);
|
|
13
|
+
}
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
16
|
+
function parseDotNotation(key, value) {
|
|
17
|
+
if (!key || key.trim() === "") {
|
|
18
|
+
throw new Error("CLI override key cannot be empty");
|
|
19
|
+
}
|
|
20
|
+
const parts = key.split(".");
|
|
21
|
+
const parsedValue = parseCliValue(value);
|
|
22
|
+
let result = {};
|
|
23
|
+
let current = result;
|
|
24
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
25
|
+
const part = parts[i];
|
|
26
|
+
if (!part || part.trim() === "") {
|
|
27
|
+
throw new Error(`Invalid key format: "${key}" - empty segment found`);
|
|
28
|
+
}
|
|
29
|
+
current[part] = {};
|
|
30
|
+
current = current[part];
|
|
31
|
+
}
|
|
32
|
+
const lastPart = parts[parts.length - 1];
|
|
33
|
+
if (!lastPart || lastPart.trim() === "") {
|
|
34
|
+
throw new Error(`Invalid key format: "${key}" - empty segment found`);
|
|
35
|
+
}
|
|
36
|
+
current[lastPart] = parsedValue;
|
|
37
|
+
return result;
|
|
38
|
+
}
|
|
39
|
+
function deepMerge(target, source) {
|
|
40
|
+
const result = { ...target };
|
|
41
|
+
for (const key in source) {
|
|
42
|
+
const sourceValue = source[key];
|
|
43
|
+
const targetValue = result[key];
|
|
44
|
+
if (sourceValue && typeof sourceValue === "object" && !Array.isArray(sourceValue) && targetValue && typeof targetValue === "object" && !Array.isArray(targetValue)) {
|
|
45
|
+
result[key] = deepMerge(targetValue, sourceValue);
|
|
46
|
+
} else {
|
|
47
|
+
result[key] = sourceValue;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
52
|
+
function extractSettingsOverrides(argv = process.argv) {
|
|
53
|
+
let result = {};
|
|
54
|
+
for (let i = 0; i < argv.length; i++) {
|
|
55
|
+
const arg = argv[i];
|
|
56
|
+
if (!arg) continue;
|
|
57
|
+
if (arg === "--set") {
|
|
58
|
+
const nextArg = argv[i + 1];
|
|
59
|
+
if (!nextArg) {
|
|
60
|
+
throw new Error("--set requires a key=value argument");
|
|
61
|
+
}
|
|
62
|
+
const equalsIndex = nextArg.indexOf("=");
|
|
63
|
+
if (equalsIndex === -1) {
|
|
64
|
+
throw new Error(`Invalid --set format: "${nextArg}". Expected key=value`);
|
|
65
|
+
}
|
|
66
|
+
const key = nextArg.substring(0, equalsIndex);
|
|
67
|
+
const value = nextArg.substring(equalsIndex + 1);
|
|
68
|
+
if (!key) {
|
|
69
|
+
throw new Error(`Invalid --set format: "${nextArg}". Key cannot be empty`);
|
|
70
|
+
}
|
|
71
|
+
try {
|
|
72
|
+
const parsed = parseDotNotation(key, value);
|
|
73
|
+
result = deepMerge(result, parsed);
|
|
74
|
+
} catch (error) {
|
|
75
|
+
if (error instanceof Error) {
|
|
76
|
+
throw new Error(`Failed to parse --set ${nextArg}: ${error.message}`);
|
|
77
|
+
}
|
|
78
|
+
throw error;
|
|
79
|
+
}
|
|
80
|
+
i++;
|
|
81
|
+
} else if (arg.startsWith("--set=")) {
|
|
82
|
+
const keyValue = arg.substring(6);
|
|
83
|
+
const equalsIndex = keyValue.indexOf("=");
|
|
84
|
+
if (equalsIndex === -1) {
|
|
85
|
+
throw new Error(`Invalid --set format: "${arg}". Expected --set=key=value`);
|
|
86
|
+
}
|
|
87
|
+
const key = keyValue.substring(0, equalsIndex);
|
|
88
|
+
const value = keyValue.substring(equalsIndex + 1);
|
|
89
|
+
if (!key) {
|
|
90
|
+
throw new Error(`Invalid --set format: "${arg}". Key cannot be empty`);
|
|
91
|
+
}
|
|
92
|
+
try {
|
|
93
|
+
const parsed = parseDotNotation(key, value);
|
|
94
|
+
result = deepMerge(result, parsed);
|
|
95
|
+
} catch (error) {
|
|
96
|
+
if (error instanceof Error) {
|
|
97
|
+
throw new Error(`Failed to parse ${arg}: ${error.message}`);
|
|
98
|
+
}
|
|
99
|
+
throw error;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return result;
|
|
104
|
+
}
|
|
105
|
+
function extractRawSetArguments(argv = process.argv) {
|
|
106
|
+
const rawSetArgs = [];
|
|
107
|
+
for (let i = 0; i < argv.length; i++) {
|
|
108
|
+
const arg = argv[i];
|
|
109
|
+
if (!arg) continue;
|
|
110
|
+
if (arg === "--set") {
|
|
111
|
+
const nextArg = argv[i + 1];
|
|
112
|
+
if (nextArg) {
|
|
113
|
+
rawSetArgs.push(nextArg);
|
|
114
|
+
i++;
|
|
115
|
+
}
|
|
116
|
+
} else if (arg.startsWith("--set=")) {
|
|
117
|
+
const keyValue = arg.substring(6);
|
|
118
|
+
if (keyValue) {
|
|
119
|
+
rawSetArgs.push(keyValue);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return rawSetArgs;
|
|
124
|
+
}
|
|
125
|
+
function getExecutablePath() {
|
|
126
|
+
const argv1 = process.argv[1];
|
|
127
|
+
if (!argv1 || argv1.trim() === "") {
|
|
128
|
+
return "il";
|
|
129
|
+
}
|
|
130
|
+
if (argv1.includes("/")) {
|
|
131
|
+
return resolve(argv1);
|
|
132
|
+
}
|
|
133
|
+
return argv1;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export {
|
|
137
|
+
parseCliValue,
|
|
138
|
+
parseDotNotation,
|
|
139
|
+
extractSettingsOverrides,
|
|
140
|
+
extractRawSetArguments,
|
|
141
|
+
getExecutablePath
|
|
142
|
+
};
|
|
143
|
+
//# sourceMappingURL=chunk-GYCR2LOU.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/cli-overrides.ts"],"sourcesContent":["import { resolve } from 'node:path'\nimport type { IloomSettings } from '../lib/SettingsManager.js'\n\n/**\n * Type for parsed CLI overrides (partial settings)\n */\nexport type CliOverrides = Partial<IloomSettings>\n\n/**\n * Parse CLI value string to appropriate type\n * - \"true\"/\"false\" -> boolean\n * - Numeric strings -> number\n * - Otherwise -> string\n */\nexport function parseCliValue(value: string): string | number | boolean {\n\t// Handle boolean values\n\tif (value === 'true') return true\n\tif (value === 'false') return false\n\n\t// Handle numeric values\n\tif (/^-?\\d+$/.test(value)) {\n\t\treturn parseInt(value, 10)\n\t}\n\tif (/^-?\\d+\\.\\d+$/.test(value)) {\n\t\treturn parseFloat(value)\n\t}\n\n\t// Default: return as string\n\treturn value\n}\n\n/**\n * Parse dot notation key=value into nested object\n * Example: \"workflows.issue.startIde=false\" -> { workflows: { issue: { startIde: false } } }\n */\nexport function parseDotNotation(key: string, value: string): Record<string, unknown> {\n\tif (!key || key.trim() === '') {\n\t\tthrow new Error('CLI override key cannot be empty')\n\t}\n\n\tconst parts = key.split('.')\n\tconst parsedValue = parseCliValue(value)\n\n\t// Build nested object from bottom up\n\tlet result: Record<string, unknown> = {}\n\tlet current = result\n\n\tfor (let i = 0; i < parts.length - 1; i++) {\n\t\tconst part = parts[i]\n\t\tif (!part || part.trim() === '') {\n\t\t\tthrow new Error(`Invalid key format: \"${key}\" - empty segment found`)\n\t\t}\n\t\tcurrent[part] = {}\n\t\tcurrent = current[part] as Record<string, unknown>\n\t}\n\n\t// Set the final value\n\tconst lastPart = parts[parts.length - 1]\n\tif (!lastPart || lastPart.trim() === '') {\n\t\tthrow new Error(`Invalid key format: \"${key}\" - empty segment found`)\n\t}\n\tcurrent[lastPart] = parsedValue\n\n\treturn result\n}\n\n/**\n * Deep merge helper for nested objects\n * Used internally for merging multiple --set arguments\n * Arrays are replaced, not concatenated\n */\nfunction deepMerge(\n\ttarget: Record<string, unknown>,\n\tsource: Record<string, unknown>,\n): Record<string, unknown> {\n\tconst result = { ...target }\n\n\tfor (const key in source) {\n\t\tconst sourceValue = source[key]\n\t\tconst targetValue = result[key]\n\n\t\tif (\n\t\t\tsourceValue &&\n\t\t\ttypeof sourceValue === 'object' &&\n\t\t\t!Array.isArray(sourceValue) &&\n\t\t\ttargetValue &&\n\t\t\ttypeof targetValue === 'object' &&\n\t\t\t!Array.isArray(targetValue)\n\t\t) {\n\t\t\t// Both are objects - recursively merge\n\t\t\tresult[key] = deepMerge(targetValue as Record<string, unknown>, sourceValue as Record<string, unknown>)\n\t\t} else {\n\t\t\t// Replace value (including arrays)\n\t\t\tresult[key] = sourceValue\n\t\t}\n\t}\n\n\treturn result\n}\n\n/**\n * Extract all --set arguments from process.argv\n * Returns merged partial settings object\n *\n * Supports both formats:\n * - --set key=value\n * - --set=key=value\n */\nexport function extractSettingsOverrides(argv: string[] = process.argv): CliOverrides {\n\tlet result: Record<string, unknown> = {}\n\n\tfor (let i = 0; i < argv.length; i++) {\n\t\tconst arg = argv[i]\n\t\tif (!arg) continue // Skip undefined/empty entries (shouldn't happen but satisfies TypeScript)\n\n\t\t// Handle --set key=value format\n\t\tif (arg === '--set') {\n\t\t\tconst nextArg = argv[i + 1]\n\t\t\tif (!nextArg) {\n\t\t\t\tthrow new Error('--set requires a key=value argument')\n\t\t\t}\n\n\t\t\t// Parse key=value\n\t\t\tconst equalsIndex = nextArg.indexOf('=')\n\t\t\tif (equalsIndex === -1) {\n\t\t\t\tthrow new Error(`Invalid --set format: \"${nextArg}\". Expected key=value`)\n\t\t\t}\n\n\t\t\tconst key = nextArg.substring(0, equalsIndex)\n\t\t\tconst value = nextArg.substring(equalsIndex + 1)\n\n\t\t\tif (!key) {\n\t\t\t\tthrow new Error(`Invalid --set format: \"${nextArg}\". Key cannot be empty`)\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst parsed = parseDotNotation(key, value)\n\t\t\t\tresult = deepMerge(result, parsed)\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof Error) {\n\t\t\t\t\tthrow new Error(`Failed to parse --set ${nextArg}: ${error.message}`)\n\t\t\t\t}\n\t\t\t\tthrow error\n\t\t\t}\n\n\t\t\ti++ // Skip the next argument since we consumed it\n\t\t}\n\t\t// Handle --set=key=value format\n\t\telse if (arg.startsWith('--set=')) {\n\t\t\tconst keyValue = arg.substring(6) // Remove \"--set=\"\n\n\t\t\t// Parse key=value\n\t\t\tconst equalsIndex = keyValue.indexOf('=')\n\t\t\tif (equalsIndex === -1) {\n\t\t\t\tthrow new Error(`Invalid --set format: \"${arg}\". Expected --set=key=value`)\n\t\t\t}\n\n\t\t\tconst key = keyValue.substring(0, equalsIndex)\n\t\t\tconst value = keyValue.substring(equalsIndex + 1)\n\n\t\t\tif (!key) {\n\t\t\t\tthrow new Error(`Invalid --set format: \"${arg}\". Key cannot be empty`)\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst parsed = parseDotNotation(key, value)\n\t\t\t\tresult = deepMerge(result, parsed)\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof Error) {\n\t\t\t\t\tthrow new Error(`Failed to parse ${arg}: ${error.message}`)\n\t\t\t\t}\n\t\t\t\tthrow error\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result as CliOverrides\n}\n\n/**\n * Extract raw --set arguments from process.argv for forwarding to other commands\n * Returns array of strings in format [\"key=value\", \"key2=value2\"]\n * This is useful when you need to forward --set arguments to another command\n *\n * Example:\n * - Input: ['node', 'il', 'start', '123', '--set', 'workflows.issue.startIde=false', '--set', 'port=4000']\n * - Output: ['workflows.issue.startIde=false', 'port=4000']\n */\nexport function extractRawSetArguments(argv: string[] = process.argv): string[] {\n\tconst rawSetArgs: string[] = []\n\n\tfor (let i = 0; i < argv.length; i++) {\n\t\tconst arg = argv[i]\n\t\tif (!arg) continue\n\n\t\t// Handle --set key=value format\n\t\tif (arg === '--set') {\n\t\t\tconst nextArg = argv[i + 1]\n\t\t\tif (nextArg) {\n\t\t\t\trawSetArgs.push(nextArg)\n\t\t\t\ti++ // Skip the next argument since we consumed it\n\t\t\t}\n\t\t}\n\t\t// Handle --set=key=value format\n\t\telse if (arg.startsWith('--set=')) {\n\t\t\tconst keyValue = arg.substring(6) // Remove \"--set=\"\n\t\t\tif (keyValue) {\n\t\t\t\trawSetArgs.push(keyValue)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn rawSetArgs\n}\n\n/**\n * Get the executable path used to invoke this CLI\n *\n * Rules:\n * - If process.argv[1] contains \"/\" (path), resolve to absolute path\n * - If process.argv[1] is just a name (no \"/\"), return as-is (in PATH)\n * - Fallback to 'il' if process.argv[1] is undefined\n *\n * Examples:\n * - ./dist/cli.js → /full/path/to/dist/cli.js\n * - dist/cli.js → /full/path/to/dist/cli.js\n * - /usr/local/bin/il → /usr/local/bin/il\n * - il → il\n * - il-125 → il-125\n */\nexport function getExecutablePath(): string {\n\tconst argv1 = process.argv[1]\n\n\tif (!argv1 || argv1.trim() === '') {\n\t\t// Fallback if process.argv[1] is undefined or empty\n\t\treturn 'il'\n\t}\n\n\t// If path contains \"/\", it's a file path - resolve to absolute\n\tif (argv1.includes('/')) {\n\t\treturn resolve(argv1)\n\t}\n\n\t// Otherwise, it's a binary name in PATH - use as-is\n\treturn argv1\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
detectPackageManager
|
|
4
|
+
} from "./chunk-BLCTGFZN.js";
|
|
5
|
+
import {
|
|
6
|
+
logger
|
|
7
|
+
} from "./chunk-GEHQXLEI.js";
|
|
8
|
+
|
|
9
|
+
// src/utils/dev-server.ts
|
|
10
|
+
async function buildDevServerCommand(workspacePath) {
|
|
11
|
+
const packageManager = await detectPackageManager(workspacePath);
|
|
12
|
+
let devCommand;
|
|
13
|
+
switch (packageManager) {
|
|
14
|
+
case "pnpm":
|
|
15
|
+
devCommand = "pnpm dev";
|
|
16
|
+
break;
|
|
17
|
+
case "npm":
|
|
18
|
+
devCommand = "npm run dev";
|
|
19
|
+
break;
|
|
20
|
+
case "yarn":
|
|
21
|
+
devCommand = "yarn dev";
|
|
22
|
+
break;
|
|
23
|
+
default:
|
|
24
|
+
logger.warn(`Unknown or unsupported package manager: ${packageManager}, defaulting to npm`);
|
|
25
|
+
devCommand = "npm run dev";
|
|
26
|
+
}
|
|
27
|
+
logger.debug(`Dev server command: ${devCommand}`);
|
|
28
|
+
return devCommand;
|
|
29
|
+
}
|
|
30
|
+
async function getDevServerLaunchCommand(workspacePath, port, capabilities = []) {
|
|
31
|
+
const devCommand = await buildDevServerCommand(workspacePath);
|
|
32
|
+
const commands = [];
|
|
33
|
+
if (capabilities.includes("web")) {
|
|
34
|
+
if (port !== void 0) {
|
|
35
|
+
commands.push(`echo 'Starting dev server on PORT=${port}...'`);
|
|
36
|
+
} else {
|
|
37
|
+
commands.push(`echo 'Starting dev server...'`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
commands.push(devCommand);
|
|
41
|
+
return commands.join(" && ");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export {
|
|
45
|
+
buildDevServerCommand,
|
|
46
|
+
getDevServerLaunchCommand
|
|
47
|
+
};
|
|
48
|
+
//# sourceMappingURL=chunk-GZP4UGGM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/dev-server.ts"],"sourcesContent":["import { detectPackageManager } from './package-manager.js'\nimport { logger } from './logger.js'\nimport type { Capability } from '../types/loom.js'\n\n/**\n * Build dev server command for workspace\n * Detects package manager and constructs appropriate command\n */\nexport async function buildDevServerCommand(\n\tworkspacePath: string\n): Promise<string> {\n\tconst packageManager = await detectPackageManager(workspacePath)\n\n\tlet devCommand: string\n\n\tswitch (packageManager) {\n\t\tcase 'pnpm':\n\t\t\tdevCommand = 'pnpm dev'\n\t\t\tbreak\n\t\tcase 'npm':\n\t\t\tdevCommand = 'npm run dev'\n\t\t\tbreak\n\t\tcase 'yarn':\n\t\t\tdevCommand = 'yarn dev'\n\t\t\tbreak\n\t\tdefault:\n\t\t\t// Fallback to npm (handles bun and other package managers)\n\t\t\tlogger.warn(`Unknown or unsupported package manager: ${packageManager}, defaulting to npm`)\n\t\t\tdevCommand = 'npm run dev'\n\t}\n\n\tlogger.debug(`Dev server command: ${devCommand}`)\n\treturn devCommand\n}\n\n/**\n * Build complete dev server launch command for terminal\n * Includes VSCode launch, echo message (only for web projects), and dev server start\n */\nexport async function getDevServerLaunchCommand(\n\tworkspacePath: string,\n\tport?: number,\n\tcapabilities: Capability[] = []\n): Promise<string> {\n\tconst devCommand = await buildDevServerCommand(workspacePath)\n\n\tconst commands: string[] = []\n\n\t// // Open VSCode\n\t// commands.push('code .')\n\n\t// Echo message (only for web projects)\n\tif (capabilities.includes('web')) {\n\t\tif (port !== undefined) {\n\t\t\tcommands.push(`echo 'Starting dev server on PORT=${port}...'`)\n\t\t} else {\n\t\t\tcommands.push(`echo 'Starting dev server...'`)\n\t\t}\n\t}\n\n\t// Start dev server\n\tcommands.push(devCommand)\n\n\treturn commands.join(' && ')\n}\n"],"mappings":";;;;;;;;;AAQA,eAAsB,sBACrB,eACkB;AAClB,QAAM,iBAAiB,MAAM,qBAAqB,aAAa;AAE/D,MAAI;AAEJ,UAAQ,gBAAgB;AAAA,IACvB,KAAK;AACJ,mBAAa;AACb;AAAA,IACD,KAAK;AACJ,mBAAa;AACb;AAAA,IACD,KAAK;AACJ,mBAAa;AACb;AAAA,IACD;AAEC,aAAO,KAAK,2CAA2C,cAAc,qBAAqB;AAC1F,mBAAa;AAAA,EACf;AAEA,SAAO,MAAM,uBAAuB,UAAU,EAAE;AAChD,SAAO;AACR;AAMA,eAAsB,0BACrB,eACA,MACA,eAA6B,CAAC,GACZ;AAClB,QAAM,aAAa,MAAM,sBAAsB,aAAa;AAE5D,QAAM,WAAqB,CAAC;AAM5B,MAAI,aAAa,SAAS,KAAK,GAAG;AACjC,QAAI,SAAS,QAAW;AACvB,eAAS,KAAK,qCAAqC,IAAI,MAAM;AAAA,IAC9D,OAAO;AACN,eAAS,KAAK,+BAA+B;AAAA,IAC9C;AAAA,EACD;AAGA,WAAS,KAAK,UAAU;AAExB,SAAO,SAAS,KAAK,MAAM;AAC5B;","names":[]}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/utils/IdentifierParser.ts
|
|
4
|
+
var IdentifierParser = class {
|
|
5
|
+
constructor(gitWorktreeManager) {
|
|
6
|
+
this.gitWorktreeManager = gitWorktreeManager;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Parse identifier using pattern-based detection on existing worktrees.
|
|
10
|
+
* Does NOT make GitHub API calls - only checks local worktree patterns.
|
|
11
|
+
*
|
|
12
|
+
* @param identifier - The identifier to parse (e.g., "42", "#66", "my-branch")
|
|
13
|
+
* @returns ParsedInput with type, number/branchName, and originalInput
|
|
14
|
+
* @throws Error if no matching worktree is found
|
|
15
|
+
*/
|
|
16
|
+
async parseForPatternDetection(identifier) {
|
|
17
|
+
const cleanId = identifier.replace(/^#/, "").trim();
|
|
18
|
+
const originalInput = identifier;
|
|
19
|
+
const numericMatch = cleanId.match(/^(\d+)$/);
|
|
20
|
+
if (numericMatch == null ? void 0 : numericMatch[1]) {
|
|
21
|
+
const number = parseInt(numericMatch[1], 10);
|
|
22
|
+
const prWorktree = await this.gitWorktreeManager.findWorktreeForPR(number, "");
|
|
23
|
+
if (prWorktree) {
|
|
24
|
+
return {
|
|
25
|
+
type: "pr",
|
|
26
|
+
number,
|
|
27
|
+
originalInput
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
const issueWorktree = await this.gitWorktreeManager.findWorktreeForIssue(number);
|
|
31
|
+
if (issueWorktree) {
|
|
32
|
+
return {
|
|
33
|
+
type: "issue",
|
|
34
|
+
number,
|
|
35
|
+
originalInput
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
throw new Error(`No worktree found for identifier: ${identifier}`);
|
|
39
|
+
}
|
|
40
|
+
const branchWorktree = await this.gitWorktreeManager.findWorktreeForBranch(cleanId);
|
|
41
|
+
if (branchWorktree) {
|
|
42
|
+
return {
|
|
43
|
+
type: "branch",
|
|
44
|
+
branchName: cleanId,
|
|
45
|
+
originalInput
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
throw new Error(`No worktree found for identifier: ${identifier}`);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export {
|
|
53
|
+
IdentifierParser
|
|
54
|
+
};
|
|
55
|
+
//# sourceMappingURL=chunk-H4E4THUZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/IdentifierParser.ts"],"sourcesContent":["import type { ParsedInput } from '../commands/start.js'\nimport type { GitWorktreeManager } from '../lib/GitWorktreeManager.js'\n\n/**\n * IdentifierParser provides consistent identifier parsing across commands\n * using pattern-based detection without GitHub API calls.\n *\n * Detection Strategy:\n * 1. For numeric input (e.g., \"42\", \"#66\"):\n * - Check for PR worktree first (_pr_N pattern in path)\n * - Then check for issue worktree (issue-N pattern in branch)\n * 2. For non-numeric input:\n * - Treat as branch name and verify worktree exists\n *\n * This ensures:\n * - No unnecessary GitHub API calls\n * - Consistent behavior across finish/cleanup commands\n * - PR detection takes priority over issue detection\n */\nexport class IdentifierParser {\n\tconstructor(private gitWorktreeManager: GitWorktreeManager) {}\n\n\t/**\n\t * Parse identifier using pattern-based detection on existing worktrees.\n\t * Does NOT make GitHub API calls - only checks local worktree patterns.\n\t *\n\t * @param identifier - The identifier to parse (e.g., \"42\", \"#66\", \"my-branch\")\n\t * @returns ParsedInput with type, number/branchName, and originalInput\n\t * @throws Error if no matching worktree is found\n\t */\n\tasync parseForPatternDetection(identifier: string): Promise<ParsedInput> {\n\t\t// Remove # prefix if present and trim whitespace\n\t\tconst cleanId = identifier.replace(/^#/, '').trim()\n\t\tconst originalInput = identifier\n\n\t\t// Check if input is numeric\n\t\tconst numericMatch = cleanId.match(/^(\\d+)$/)\n\n\t\tif (numericMatch?.[1]) {\n\t\t\tconst number = parseInt(numericMatch[1], 10)\n\n\t\t\t// Priority 1: Check for PR worktree (_pr_N pattern)\n\t\t\t// Pass empty string for branch name since we don't know it yet\n\t\t\tconst prWorktree = await this.gitWorktreeManager.findWorktreeForPR(number, '')\n\t\t\tif (prWorktree) {\n\t\t\t\treturn {\n\t\t\t\t\ttype: 'pr',\n\t\t\t\t\tnumber,\n\t\t\t\t\toriginalInput,\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Priority 2: Check for issue worktree (issue-N pattern)\n\t\t\tconst issueWorktree = await this.gitWorktreeManager.findWorktreeForIssue(number)\n\t\t\tif (issueWorktree) {\n\t\t\t\treturn {\n\t\t\t\t\ttype: 'issue',\n\t\t\t\t\tnumber,\n\t\t\t\t\toriginalInput,\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// No matching worktree found for numeric input\n\t\t\tthrow new Error(`No worktree found for identifier: ${identifier}`)\n\t\t}\n\n\t\t// Non-numeric input: treat as branch name\n\t\tconst branchWorktree = await this.gitWorktreeManager.findWorktreeForBranch(cleanId)\n\t\tif (branchWorktree) {\n\t\t\treturn {\n\t\t\t\ttype: 'branch',\n\t\t\t\tbranchName: cleanId,\n\t\t\t\toriginalInput,\n\t\t\t}\n\t\t}\n\n\t\t// No matching worktree found for branch name\n\t\tthrow new Error(`No worktree found for identifier: ${identifier}`)\n\t}\n}\n"],"mappings":";;;AAmBO,IAAM,mBAAN,MAAuB;AAAA,EAC7B,YAAoB,oBAAwC;AAAxC;AAAA,EAAyC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAU7D,MAAM,yBAAyB,YAA0C;AAExE,UAAM,UAAU,WAAW,QAAQ,MAAM,EAAE,EAAE,KAAK;AAClD,UAAM,gBAAgB;AAGtB,UAAM,eAAe,QAAQ,MAAM,SAAS;AAE5C,QAAI,6CAAe,IAAI;AACtB,YAAM,SAAS,SAAS,aAAa,CAAC,GAAG,EAAE;AAI3C,YAAM,aAAa,MAAM,KAAK,mBAAmB,kBAAkB,QAAQ,EAAE;AAC7E,UAAI,YAAY;AACf,eAAO;AAAA,UACN,MAAM;AAAA,UACN;AAAA,UACA;AAAA,QACD;AAAA,MACD;AAGA,YAAM,gBAAgB,MAAM,KAAK,mBAAmB,qBAAqB,MAAM;AAC/E,UAAI,eAAe;AAClB,eAAO;AAAA,UACN,MAAM;AAAA,UACN;AAAA,UACA;AAAA,QACD;AAAA,MACD;AAGA,YAAM,IAAI,MAAM,qCAAqC,UAAU,EAAE;AAAA,IAClE;AAGA,UAAM,iBAAiB,MAAM,KAAK,mBAAmB,sBAAsB,OAAO;AAClF,QAAI,gBAAgB;AACnB,aAAO;AAAA,QACN,MAAM;AAAA,QACN,YAAY;AAAA,QACZ;AAAA,MACD;AAAA,IACD;AAGA,UAAM,IAAI,MAAM,qCAAqC,UAAU,EAAE;AAAA,EAClE;AACD;","names":[]}
|