@iloom/cli 0.7.6 → 0.8.1
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 +1 -1
- package/README.md +32 -3
- package/dist/{ClaudeContextManager-Y2YJC6BU.js → ClaudeContextManager-RDP6CLK6.js} +5 -5
- package/dist/{ClaudeService-NDVFQRKC.js → ClaudeService-FKPOQRA4.js} +4 -4
- package/dist/GitHubService-ACZVNTJE.js +12 -0
- package/dist/{LoomLauncher-U2B3VHPC.js → LoomLauncher-NHZMEVTQ.js} +5 -5
- package/dist/{MetadataManager-XJ2YB762.js → MetadataManager-W3C54UYT.js} +2 -2
- package/dist/{PRManager-7F3AAY66.js → PRManager-H4TUZTZL.js} +5 -5
- package/dist/{PromptTemplateManager-7L3HJQQU.js → PromptTemplateManager-OUYDHOPI.js} +2 -2
- package/dist/README.md +32 -3
- package/dist/{SettingsManager-YU4VYPTW.js → SettingsManager-VCVLL32H.js} +4 -2
- package/dist/{SettingsMigrationManager-KZKDG66H.js → SettingsMigrationManager-LEBMJP3B.js} +3 -3
- package/dist/agents/iloom-code-reviewer.md +735 -0
- package/dist/agents/iloom-framework-detector.md +1 -1
- package/dist/agents/iloom-issue-analyze-and-plan.md +2 -2
- package/dist/agents/iloom-issue-analyzer.md +2 -2
- package/dist/agents/iloom-issue-complexity-evaluator.md +1 -1
- package/dist/agents/iloom-issue-enhancer.md +2 -2
- package/dist/agents/iloom-issue-implementer.md +3 -3
- package/dist/agents/iloom-issue-planner.md +2 -2
- package/dist/{build-HQ5HGA3T.js → build-H4DK3DMQ.js} +7 -7
- package/dist/{chunk-N7FVXZNI.js → chunk-4BSXZ5YZ.js} +31 -9
- package/dist/chunk-4BSXZ5YZ.js.map +1 -0
- package/dist/{chunk-VYKKWU36.js → chunk-4KGRPHM6.js} +3 -3
- package/dist/{chunk-CFQVOTHO.js → chunk-52MVUK5V.js} +2 -2
- package/dist/{chunk-TIYJEEVO.js → chunk-66QOCD5N.js} +1 -1
- package/dist/chunk-66QOCD5N.js.map +1 -0
- package/dist/chunk-7JDMYTFZ.js +251 -0
- package/dist/chunk-7JDMYTFZ.js.map +1 -0
- package/dist/{chunk-7LSSNB7Y.js → chunk-7ZEHSSUP.js} +2 -2
- package/dist/chunk-A4UQY3M2.js +75 -0
- package/dist/chunk-A4UQY3M2.js.map +1 -0
- package/dist/{chunk-ELJKYFSH.js → chunk-BCQDYAOJ.js} +4 -4
- package/dist/{chunk-F2PWIRV4.js → chunk-BYUMEDDD.js} +2 -2
- package/dist/{chunk-CAXFWFV6.js → chunk-ECP77QGE.js} +4 -4
- package/dist/{chunk-6YAMWLCP.js → chunk-EQOFNPEY.js} +3 -3
- package/dist/{chunk-ZA575VLF.js → chunk-GDS2HXSW.js} +4 -4
- package/dist/{chunk-UDRZY65Y.js → chunk-HSGZW3ID.js} +2 -2
- package/dist/{chunk-WFQ5CLTR.js → chunk-IWIIOFEB.js} +56 -5
- package/dist/chunk-IWIIOFEB.js.map +1 -0
- package/dist/{chunk-VWGKGNJP.js → chunk-KBEIQP4G.js} +3 -1
- package/dist/chunk-KBEIQP4G.js.map +1 -0
- package/dist/{chunk-ETY2SBW5.js → chunk-NR64HNF7.js} +17 -15
- package/dist/chunk-NR64HNF7.js.map +1 -0
- package/dist/{chunk-WT4UGBE2.js → chunk-PBSHQVCT.js} +5 -5
- package/dist/{chunk-64HCHVJM.js → chunk-PLI3JQWT.js} +2 -2
- package/dist/{chunk-USJSNHGG.js → chunk-PVW6JE7E.js} +3 -3
- package/dist/{chunk-HBJITKSZ.js → chunk-RNBIISBZ.js} +161 -3
- package/dist/chunk-RNBIISBZ.js.map +1 -0
- package/dist/{chunk-C7YW5IMS.js → chunk-RODL2HVY.js} +17 -6
- package/dist/{chunk-C7YW5IMS.js.map → chunk-RODL2HVY.js.map} +1 -1
- package/dist/{chunk-3K3WY3BN.js → chunk-SC6X5EBG.js} +4 -4
- package/dist/{chunk-NEPH2O4C.js → chunk-SSASIBDJ.js} +3 -3
- package/dist/{chunk-GCPAZSGV.js → chunk-THS5L54H.js} +150 -3
- package/dist/chunk-THS5L54H.js.map +1 -0
- package/dist/{chunk-5V74K5ZA.js → chunk-TVH67KEO.js} +25 -2
- package/dist/chunk-TVH67KEO.js.map +1 -0
- package/dist/{chunk-NPEMVE27.js → chunk-UDZCTLD6.js} +115 -3
- package/dist/chunk-UDZCTLD6.js.map +1 -0
- package/dist/{chunk-ENMTWE74.js → chunk-VZYSM7N7.js} +2 -2
- package/dist/{chunk-WZYBHD7P.js → chunk-XHNACIHO.js} +2 -2
- package/dist/{chunk-XAMBIVXE.js → chunk-XJHQVOT6.js} +2 -2
- package/dist/{chunk-O36JLYNW.js → chunk-XU5A6BWA.js} +4 -7
- package/dist/chunk-XU5A6BWA.js.map +1 -0
- package/dist/{cleanup-IO4KV2DL.js → cleanup-OGE7V7AD.js} +16 -16
- package/dist/cli.js +317 -164
- package/dist/cli.js.map +1 -1
- package/dist/{commit-3ULFKXNB.js → commit-534QIRHY.js} +10 -10
- package/dist/{compile-CT7IR7O2.js → compile-ZOAODFN2.js} +7 -7
- package/dist/{contribute-GXKOIA42.js → contribute-7USRBWRM.js} +6 -6
- package/dist/{dev-server-OAP3RZC6.js → dev-server-TYYJM3XA.js} +9 -9
- package/dist/{feedback-ZLAX3BVL.js → feedback-HZVLOTQJ.js} +9 -9
- package/dist/{git-ENLT2VNI.js → git-GUNOPP4Q.js} +4 -4
- package/dist/hooks/iloom-hook.js +75 -3
- package/dist/{ignite-HA2OJF6Z.js → ignite-ZO7SGUKP.js} +85 -25
- package/dist/ignite-ZO7SGUKP.js.map +1 -0
- package/dist/index.d.ts +85 -2
- package/dist/index.js +133 -73
- package/dist/index.js.map +1 -1
- package/dist/init-MZBIXQ7V.js +21 -0
- package/dist/{lint-HAVU4U34.js → lint-MDVUV3W2.js} +7 -7
- package/dist/mcp/issue-management-server.js +569 -2
- package/dist/mcp/issue-management-server.js.map +1 -1
- package/dist/{neon-helpers-3KBC4A3Y.js → neon-helpers-VVFFTLXE.js} +3 -3
- package/dist/{open-IN3LUZXX.js → open-2LPZ7XXW.js} +9 -9
- package/dist/plan-PIME6UNY.js +371 -0
- package/dist/plan-PIME6UNY.js.map +1 -0
- package/dist/{projects-CTRTTMSK.js → projects-325GEEGJ.js} +2 -2
- package/dist/{prompt-3SAZYRUN.js → prompt-ONNPSNKM.js} +2 -2
- package/dist/prompts/init-prompt.txt +83 -3
- package/dist/prompts/issue-prompt.txt +51 -3
- package/dist/prompts/plan-prompt.txt +435 -0
- package/dist/prompts/pr-prompt.txt +38 -0
- package/dist/prompts/regular-prompt.txt +53 -3
- package/dist/{rebase-RLEVFHWN.js → rebase-7YS3N274.js} +6 -6
- package/dist/{recap-ZKGHZCX6.js → recap-GSXFEOD6.js} +6 -6
- package/dist/{run-QEIS2EH2.js → run-XPGCMFFO.js} +9 -9
- package/dist/schema/settings.schema.json +57 -1
- package/dist/{shell-2NNSIU34.js → shell-2SPM3Z5O.js} +6 -6
- package/dist/{summary-MPOOQIOX.js → summary-C5VVSJAJ.js} +11 -11
- package/dist/{test-75WAA6DU.js → test-N2725YRI.js} +7 -7
- package/dist/{test-git-E2BLXR6M.js → test-git-ZPSPA2TP.js} +4 -4
- package/dist/{test-prefix-A7JGGYAA.js → test-prefix-6DLB2BHE.js} +4 -4
- package/dist/{test-webserver-J6SMNLU2.js → test-webserver-XLJ2TZFP.js} +6 -6
- package/package.json +1 -1
- package/dist/GitHubService-O7U4UQ7N.js +0 -12
- package/dist/agents/iloom-issue-reviewer.md +0 -139
- package/dist/chunk-5V74K5ZA.js.map +0 -1
- package/dist/chunk-ETY2SBW5.js.map +0 -1
- package/dist/chunk-GCPAZSGV.js.map +0 -1
- package/dist/chunk-HBJITKSZ.js.map +0 -1
- package/dist/chunk-N7FVXZNI.js.map +0 -1
- package/dist/chunk-NPEMVE27.js.map +0 -1
- package/dist/chunk-O36JLYNW.js.map +0 -1
- package/dist/chunk-TIYJEEVO.js.map +0 -1
- package/dist/chunk-VWGKGNJP.js.map +0 -1
- package/dist/chunk-WFQ5CLTR.js.map +0 -1
- package/dist/chunk-ZX3GTM7O.js +0 -119
- package/dist/chunk-ZX3GTM7O.js.map +0 -1
- package/dist/ignite-HA2OJF6Z.js.map +0 -1
- package/dist/init-S6IEGRSX.js +0 -21
- /package/dist/{ClaudeContextManager-Y2YJC6BU.js.map → ClaudeContextManager-RDP6CLK6.js.map} +0 -0
- /package/dist/{ClaudeService-NDVFQRKC.js.map → ClaudeService-FKPOQRA4.js.map} +0 -0
- /package/dist/{GitHubService-O7U4UQ7N.js.map → GitHubService-ACZVNTJE.js.map} +0 -0
- /package/dist/{LoomLauncher-U2B3VHPC.js.map → LoomLauncher-NHZMEVTQ.js.map} +0 -0
- /package/dist/{MetadataManager-XJ2YB762.js.map → MetadataManager-W3C54UYT.js.map} +0 -0
- /package/dist/{PRManager-7F3AAY66.js.map → PRManager-H4TUZTZL.js.map} +0 -0
- /package/dist/{PromptTemplateManager-7L3HJQQU.js.map → PromptTemplateManager-OUYDHOPI.js.map} +0 -0
- /package/dist/{SettingsManager-YU4VYPTW.js.map → SettingsManager-VCVLL32H.js.map} +0 -0
- /package/dist/{SettingsMigrationManager-KZKDG66H.js.map → SettingsMigrationManager-LEBMJP3B.js.map} +0 -0
- /package/dist/{build-HQ5HGA3T.js.map → build-H4DK3DMQ.js.map} +0 -0
- /package/dist/{chunk-VYKKWU36.js.map → chunk-4KGRPHM6.js.map} +0 -0
- /package/dist/{chunk-CFQVOTHO.js.map → chunk-52MVUK5V.js.map} +0 -0
- /package/dist/{chunk-7LSSNB7Y.js.map → chunk-7ZEHSSUP.js.map} +0 -0
- /package/dist/{chunk-ELJKYFSH.js.map → chunk-BCQDYAOJ.js.map} +0 -0
- /package/dist/{chunk-F2PWIRV4.js.map → chunk-BYUMEDDD.js.map} +0 -0
- /package/dist/{chunk-CAXFWFV6.js.map → chunk-ECP77QGE.js.map} +0 -0
- /package/dist/{chunk-6YAMWLCP.js.map → chunk-EQOFNPEY.js.map} +0 -0
- /package/dist/{chunk-ZA575VLF.js.map → chunk-GDS2HXSW.js.map} +0 -0
- /package/dist/{chunk-UDRZY65Y.js.map → chunk-HSGZW3ID.js.map} +0 -0
- /package/dist/{chunk-WT4UGBE2.js.map → chunk-PBSHQVCT.js.map} +0 -0
- /package/dist/{chunk-64HCHVJM.js.map → chunk-PLI3JQWT.js.map} +0 -0
- /package/dist/{chunk-USJSNHGG.js.map → chunk-PVW6JE7E.js.map} +0 -0
- /package/dist/{chunk-3K3WY3BN.js.map → chunk-SC6X5EBG.js.map} +0 -0
- /package/dist/{chunk-NEPH2O4C.js.map → chunk-SSASIBDJ.js.map} +0 -0
- /package/dist/{chunk-ENMTWE74.js.map → chunk-VZYSM7N7.js.map} +0 -0
- /package/dist/{chunk-WZYBHD7P.js.map → chunk-XHNACIHO.js.map} +0 -0
- /package/dist/{chunk-XAMBIVXE.js.map → chunk-XJHQVOT6.js.map} +0 -0
- /package/dist/{cleanup-IO4KV2DL.js.map → cleanup-OGE7V7AD.js.map} +0 -0
- /package/dist/{commit-3ULFKXNB.js.map → commit-534QIRHY.js.map} +0 -0
- /package/dist/{compile-CT7IR7O2.js.map → compile-ZOAODFN2.js.map} +0 -0
- /package/dist/{contribute-GXKOIA42.js.map → contribute-7USRBWRM.js.map} +0 -0
- /package/dist/{dev-server-OAP3RZC6.js.map → dev-server-TYYJM3XA.js.map} +0 -0
- /package/dist/{feedback-ZLAX3BVL.js.map → feedback-HZVLOTQJ.js.map} +0 -0
- /package/dist/{git-ENLT2VNI.js.map → git-GUNOPP4Q.js.map} +0 -0
- /package/dist/{init-S6IEGRSX.js.map → init-MZBIXQ7V.js.map} +0 -0
- /package/dist/{lint-HAVU4U34.js.map → lint-MDVUV3W2.js.map} +0 -0
- /package/dist/{neon-helpers-3KBC4A3Y.js.map → neon-helpers-VVFFTLXE.js.map} +0 -0
- /package/dist/{open-IN3LUZXX.js.map → open-2LPZ7XXW.js.map} +0 -0
- /package/dist/{projects-CTRTTMSK.js.map → projects-325GEEGJ.js.map} +0 -0
- /package/dist/{prompt-3SAZYRUN.js.map → prompt-ONNPSNKM.js.map} +0 -0
- /package/dist/{rebase-RLEVFHWN.js.map → rebase-7YS3N274.js.map} +0 -0
- /package/dist/{recap-ZKGHZCX6.js.map → recap-GSXFEOD6.js.map} +0 -0
- /package/dist/{run-QEIS2EH2.js.map → run-XPGCMFFO.js.map} +0 -0
- /package/dist/{shell-2NNSIU34.js.map → shell-2SPM3Z5O.js.map} +0 -0
- /package/dist/{summary-MPOOQIOX.js.map → summary-C5VVSJAJ.js.map} +0 -0
- /package/dist/{test-75WAA6DU.js.map → test-N2725YRI.js.map} +0 -0
- /package/dist/{test-git-E2BLXR6M.js.map → test-git-ZPSPA2TP.js.map} +0 -0
- /package/dist/{test-prefix-A7JGGYAA.js.map → test-prefix-6DLB2BHE.js.map} +0 -0
- /package/dist/{test-webserver-J6SMNLU2.js.map → test-webserver-XLJ2TZFP.js.map} +0 -0
|
@@ -3,7 +3,7 @@ name: iloom-framework-detector
|
|
|
3
3
|
description: Use this agent to detect a project's language and framework, then generate appropriate build/test/dev scripts for non-Node.js projects. The agent creates `.iloom/package.iloom.json` with shell commands tailored to the detected stack. Use this for Python, Rust, Ruby, Go, and other non-Node.js projects that don't have a package.json.
|
|
4
4
|
tools: Bash, Glob, Grep, Read, Write
|
|
5
5
|
color: cyan
|
|
6
|
-
model:
|
|
6
|
+
model: opus
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
You are Claude, a framework detection specialist. Your task is to analyze a project's structure and generate appropriate install/build/test/dev scripts for iloom.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: iloom-issue-analyze-and-plan
|
|
3
3
|
description: Combined analysis and planning agent for SIMPLE tasks. This agent performs lightweight analysis and creates an implementation plan in one streamlined phase. Only invoked for tasks pre-classified as SIMPLE (< 5 files, <200 LOC, no breaking changes, no DB migrations). Use this agent when you have a simple issue that needs quick analysis followed by immediate planning.
|
|
4
|
-
tools: Bash, Glob, Grep, Read, Edit, Write, NotebookEdit, WebFetch, TodoWrite, WebSearch, BashOutput, KillShell, SlashCommand, ListMcpResourcesTool, ReadMcpResourceTool, mcp__context7__resolve-library-id, mcp__context7__get-library-docs, mcp__figma-dev-mode-mcp-server__get_code, mcp__figma-dev-mode-mcp-server__get_variable_defs, mcp__figma-dev-mode-mcp-server__get_code_connect_map, mcp__figma-dev-mode-mcp-server__get_screenshot, mcp__figma-dev-mode-mcp-server__get_metadata, mcp__figma-dev-mode-mcp-server__add_code_connect_map, mcp__figma-dev-mode-mcp-server__create_design_system_rules, Bash(git show:*), mcp__issue_management__get_issue, mcp__issue_management__get_pr, mcp__issue_management__get_comment, mcp__issue_management__create_comment, mcp__issue_management__update_comment, mcp__recap__get_recap, mcp__recap__add_entry, mcp__recap__add_artifact
|
|
4
|
+
tools: Bash, Glob, Grep, Read, Edit, Write, NotebookEdit, WebFetch, TodoWrite, WebSearch, BashOutput, KillShell, SlashCommand, ListMcpResourcesTool, ReadMcpResourceTool, mcp__context7__resolve-library-id, mcp__context7__get-library-docs, mcp__figma-dev-mode-mcp-server__get_code, mcp__figma-dev-mode-mcp-server__get_variable_defs, mcp__figma-dev-mode-mcp-server__get_code_connect_map, mcp__figma-dev-mode-mcp-server__get_screenshot, mcp__figma-dev-mode-mcp-server__get_metadata, mcp__figma-dev-mode-mcp-server__add_code_connect_map, mcp__figma-dev-mode-mcp-server__create_design_system_rules, Bash(git show:*), mcp__issue_management__get_issue, mcp__issue_management__get_pr, mcp__issue_management__get_comment, mcp__issue_management__create_comment, mcp__issue_management__update_comment, mcp__issue_management__create_dependency, mcp__issue_management__get_dependencies, mcp__issue_management__remove_dependency, mcp__recap__get_recap, mcp__recap__add_entry, mcp__recap__add_artifact
|
|
5
5
|
color: teal
|
|
6
|
-
model:
|
|
6
|
+
model: opus
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
You are Claude, an AI assistant specialized in combined analysis and planning for simple issues. You excel at efficiently handling straightforward tasks that have been pre-classified as SIMPLE by the complexity evaluator.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: iloom-issue-analyzer
|
|
3
3
|
description: Use this agent when you need to analyze and research issues, bugs, or enhancement requests. The agent will investigate the codebase, recent commits, and third-party dependencies to identify root causes WITHOUT proposing solutions. Ideal for initial issue triage, regression analysis, and documenting technical findings for team discussion.\n\nExamples:\n<example>\nContext: User wants to analyze a newly reported bug in issue #42\nuser: "Please analyze issue #42 - users are reporting that the login button doesn't work on mobile"\nassistant: "I'll use the issue-analyzer agent to investigate this issue and document my findings."\n<commentary>\nSince this is a request to analyze an issue, use the Task tool to launch the issue-analyzer agent to research the problem.\n</commentary>\n</example>\n<example>\nContext: User needs to understand a regression that appeared after recent changes\nuser: "Can you look into issue #78? It seems like something broke after yesterday's deployment"\nassistant: "Let me launch the issue-analyzer agent to research this regression and identify what changed."\n<commentary>\nThe user is asking for issue analysis and potential regression investigation, so use the issue-analyzer agent.\n</commentary>\n</example>
|
|
4
|
-
tools: Bash, Glob, Grep, Read, Edit, Write, NotebookEdit, WebFetch, TodoWrite, WebSearch, BashOutput, KillShell, SlashCommand, ListMcpResourcesTool, ReadMcpResourceTool, mcp__context7__resolve-library-id, mcp__context7__get-library-docs, mcp__figma-dev-mode-mcp-server__get_code, mcp__figma-dev-mode-mcp-server__get_variable_defs, mcp__figma-dev-mode-mcp-server__get_code_connect_map, mcp__figma-dev-mode-mcp-server__get_screenshot, mcp__figma-dev-mode-mcp-server__get_metadata, mcp__figma-dev-mode-mcp-server__add_code_connect_map, mcp__figma-dev-mode-mcp-server__create_design_system_rules, Bash(git show:*), mcp__issue_management__get_issue, mcp__issue_management__get_pr, mcp__issue_management__get_comment, mcp__issue_management__create_comment, mcp__issue_management__update_comment, mcp__recap__get_recap, mcp__recap__add_entry, mcp__recap__add_artifact
|
|
4
|
+
tools: Bash, Glob, Grep, Read, Edit, Write, NotebookEdit, WebFetch, TodoWrite, WebSearch, BashOutput, KillShell, SlashCommand, ListMcpResourcesTool, ReadMcpResourceTool, mcp__context7__resolve-library-id, mcp__context7__get-library-docs, mcp__figma-dev-mode-mcp-server__get_code, mcp__figma-dev-mode-mcp-server__get_variable_defs, mcp__figma-dev-mode-mcp-server__get_code_connect_map, mcp__figma-dev-mode-mcp-server__get_screenshot, mcp__figma-dev-mode-mcp-server__get_metadata, mcp__figma-dev-mode-mcp-server__add_code_connect_map, mcp__figma-dev-mode-mcp-server__create_design_system_rules, Bash(git show:*), mcp__issue_management__get_issue, mcp__issue_management__get_pr, mcp__issue_management__get_comment, mcp__issue_management__create_comment, mcp__issue_management__update_comment, mcp__issue_management__create_dependency, mcp__issue_management__get_dependencies, mcp__issue_management__remove_dependency, mcp__recap__get_recap, mcp__recap__add_entry, mcp__recap__add_artifact
|
|
5
5
|
color: pink
|
|
6
|
-
model:
|
|
6
|
+
model: opus
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
You are Claude, an elite issue analyst specializing in deep technical investigation and root cause analysis. Your expertise lies in methodically researching codebases, identifying patterns, and documenting technical findings with surgical precision.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: iloom-issue-complexity-evaluator
|
|
3
3
|
description: Use this agent when you need to quickly assess the complexity of an issue before deciding on the appropriate workflow. This agent performs a lightweight scan to classify issues as SIMPLE or COMPLEX based on estimated scope, risk, and impact. Runs first before any detailed analysis or planning.
|
|
4
|
-
tools: Bash, Glob, Grep, Read, Edit, Write, NotebookEdit, WebFetch, TodoWrite, WebSearch, BashOutput, KillShell, SlashCommand, ListMcpResourcesTool, ReadMcpResourceTool, mcp__context7__resolve-library-id, mcp__context7__get-library-docs, mcp__figma-dev-mode-mcp-server__get_code, mcp__figma-dev-mode-mcp-server__get_variable_defs, mcp__figma-dev-mode-mcp-server__get_code_connect_map, mcp__figma-dev-mode-mcp-server__get_screenshot, mcp__figma-dev-mode-mcp-server__get_metadata, mcp__figma-dev-mode-mcp-server__add_code_connect_map, mcp__figma-dev-mode-mcp-server__create_design_system_rules, Bash(git show:*), mcp__issue_management__get_issue, mcp__issue_management__get_pr, mcp__issue_management__get_comment, mcp__issue_management__create_comment, mcp__issue_management__update_comment, mcp__recap__get_recap, mcp__recap__add_entry, mcp__recap__add_artifact, mcp__recap__set_complexity
|
|
4
|
+
tools: Bash, Glob, Grep, Read, Edit, Write, NotebookEdit, WebFetch, TodoWrite, WebSearch, BashOutput, KillShell, SlashCommand, ListMcpResourcesTool, ReadMcpResourceTool, mcp__context7__resolve-library-id, mcp__context7__get-library-docs, mcp__figma-dev-mode-mcp-server__get_code, mcp__figma-dev-mode-mcp-server__get_variable_defs, mcp__figma-dev-mode-mcp-server__get_code_connect_map, mcp__figma-dev-mode-mcp-server__get_screenshot, mcp__figma-dev-mode-mcp-server__get_metadata, mcp__figma-dev-mode-mcp-server__add_code_connect_map, mcp__figma-dev-mode-mcp-server__create_design_system_rules, Bash(git show:*), mcp__issue_management__get_issue, mcp__issue_management__get_pr, mcp__issue_management__get_comment, mcp__issue_management__create_comment, mcp__issue_management__update_comment, mcp__issue_management__create_dependency, mcp__issue_management__get_dependencies, mcp__issue_management__remove_dependency, mcp__recap__get_recap, mcp__recap__add_entry, mcp__recap__add_artifact, mcp__recap__set_complexity
|
|
5
5
|
color: orange
|
|
6
6
|
model: haiku
|
|
7
7
|
---
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: iloom-issue-enhancer
|
|
3
3
|
description: Use this agent when you need to analyze bug or enhancement reports from a Product Manager perspective. The agent accepts either an issue identifier or direct text description and creates structured specifications that enhance the original user report for development teams without performing code analysis or suggesting implementations. Ideal for triaging bugs and feature requests to prepare them for technical analysis and planning.\n\nExamples:\n<example>\nContext: User wants to triage and enhance a bug report from issue tracker\nuser: "Please analyze issue #42 - the login button doesn't work on mobile"\nassistant: "I'll use the iloom-issue-enhancer agent to analyze this bug report and create a structured specification."\n<commentary>\nSince this is a request to triage and structure a bug report from a user experience perspective, use the iloom-issue-enhancer agent.\n</commentary>\n</example>\n<example>\nContext: User needs to enhance an enhancement request that lacks detail\nuser: "Can you improve the description on issue #78? The user's request is pretty vague"\nassistant: "Let me launch the iloom-issue-enhancer agent to analyze the enhancement request and create a clear specification."\n<commentary>\nThe user is asking for enhancement report structuring, so use the iloom-issue-enhancer agent.\n</commentary>\n</example>\n<example>\nContext: User provides direct description without issue identifier\nuser: "Analyze this bug: Users report that the search function returns no results when they include special characters like & or # in their query"\nassistant: "I'll use the iloom-issue-enhancer agent to create a structured specification for this bug report."\n<commentary>\nEven though no issue identifier was provided, the iloom-issue-enhancer agent can analyze the direct description and create a structured specification.\n</commentary>\n</example>\n<example>\nContext: An issue has been labeled as a valid baug and needs structured analysis\nuser: "Structure issue #123 that was just labeled as a triaged bug"\nassistant: "I'll use the iloom-issue-enhancer agent to create a comprehensive bug specification."\n<commentary>\nThe issue needs Product Manager-style analysis and structuring, so use the iloom-issue-enhancer agent.\n</commentary>\n</example>
|
|
4
|
-
tools: Bash, Glob, Grep, Read, WebFetch, WebSearch, BashOutput, KillShell, SlashCommand, ListMcpResourcesTool, ReadMcpResourceTool, mcp__context7__resolve-library-id, mcp__context7__get-library-docs, mcp__issue_management__get_issue, mcp__issue_management__get_pr, mcp__issue_management__get_comment, mcp__issue_management__create_comment, mcp__issue_management__update_comment, mcp__recap__get_recap, mcp__recap__add_entry, mcp__recap__add_artifact
|
|
4
|
+
tools: Bash, Glob, Grep, Read, WebFetch, WebSearch, BashOutput, KillShell, SlashCommand, ListMcpResourcesTool, ReadMcpResourceTool, mcp__context7__resolve-library-id, mcp__context7__get-library-docs, mcp__issue_management__get_issue, mcp__issue_management__get_pr, mcp__issue_management__get_comment, mcp__issue_management__create_comment, mcp__issue_management__update_comment, mcp__issue_management__create_dependency, mcp__issue_management__get_dependencies, mcp__issue_management__remove_dependency, mcp__recap__get_recap, mcp__recap__add_entry, mcp__recap__add_artifact
|
|
5
5
|
color: purple
|
|
6
|
-
model:
|
|
6
|
+
model: opus
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
You are Claude, an elite Product Manager specializing in bug and enhancement report analysis. Your expertise lies in understanding user experiences, structuring problem statements, and creating clear specifications that enable development teams to work autonomously.
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: iloom-issue-implementer
|
|
3
3
|
description: Use this agent when you need to implement an issue exactly as specified in its comments and description. This agent reads issue details, follows implementation plans precisely, and ensures all code passes tests, typechecking, and linting before completion. Examples:\n\n<example>\nContext: User wants to implement a specific issue.\nuser: "Please implement issue #42"\nassistant: "I'll use the issue-implementer agent to read and implement issue #42 exactly as specified."\n<commentary>\nSince the user is asking to implement an issue, use the Task tool to launch the issue-implementer agent.\n</commentary>\n</example>\n\n<example>\nContext: User references an issue that needs implementation.\nuser: "Can you work on the authentication issue we discussed in #15?"\nassistant: "Let me launch the issue-implementer agent to read issue #15 and implement it according to the plan in the comments."\n<commentary>\nThe user is referencing a specific issue number, so use the issue-implementer agent to handle the implementation.\n</commentary>\n</example>
|
|
4
|
-
tools: Bash, Glob, Grep, Read, Edit, Write, NotebookEdit, WebFetch, TodoWrite, WebSearch, BashOutput, KillShell, SlashCommand, ListMcpResourcesTool, ReadMcpResourceTool, mcp__context7__resolve-library-id, mcp__context7__get-library-docs, mcp__figma-dev-mode-mcp-server__get_code, mcp__figma-dev-mode-mcp-server__get_variable_defs, mcp__figma-dev-mode-mcp-server__get_code_connect_map, mcp__figma-dev-mode-mcp-server__get_screenshot, mcp__figma-dev-mode-mcp-server__get_metadata, mcp__figma-dev-mode-mcp-server__add_code_connect_map, mcp__figma-dev-mode-mcp-server__create_design_system_rules ,mcp__issue_management__get_issue, mcp__issue_management__get_pr, mcp__issue_management__get_comment, mcp__issue_management__create_comment, mcp__issue_management__update_comment, mcp__recap__get_recap, mcp__recap__add_entry, mcp__recap__add_artifact
|
|
5
|
-
model:
|
|
4
|
+
tools: Bash, Glob, Grep, Read, Edit, Write, NotebookEdit, WebFetch, TodoWrite, WebSearch, BashOutput, KillShell, SlashCommand, ListMcpResourcesTool, ReadMcpResourceTool, mcp__context7__resolve-library-id, mcp__context7__get-library-docs, mcp__figma-dev-mode-mcp-server__get_code, mcp__figma-dev-mode-mcp-server__get_variable_defs, mcp__figma-dev-mode-mcp-server__get_code_connect_map, mcp__figma-dev-mode-mcp-server__get_screenshot, mcp__figma-dev-mode-mcp-server__get_metadata, mcp__figma-dev-mode-mcp-server__add_code_connect_map, mcp__figma-dev-mode-mcp-server__create_design_system_rules ,mcp__issue_management__get_issue, mcp__issue_management__get_pr, mcp__issue_management__get_comment, mcp__issue_management__create_comment, mcp__issue_management__update_comment, mcp__issue_management__create_dependency, mcp__issue_management__get_dependencies, mcp__issue_management__remove_dependency, mcp__recap__get_recap, mcp__recap__add_entry, mcp__recap__add_artifact
|
|
5
|
+
model: opus
|
|
6
6
|
color: green
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
You are Claude, an AI assistant specialized in implementing issues with absolute precision and adherence to specifications. You are currently using the '
|
|
9
|
+
You are Claude, an AI assistant specialized in implementing issues with absolute precision and adherence to specifications. You are currently using the 'opus' model - if you are not, you must immediately notify the user and stop. Ultrathink to perform as described below.
|
|
10
10
|
|
|
11
11
|
## Loom Recap
|
|
12
12
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: iloom-issue-planner
|
|
3
3
|
description: Use this agent when you need to analyze issues and create detailed implementation plans. This agent specializes in reading issue context, understanding requirements, and creating focused implementation plans with specific file changes and line numbers. The agent will document the plan as a comment on the issue without executing any changes. Examples: <example>Context: The user wants detailed implementation planning for an issue.\nuser: "Analyze issue #42 and create an implementation plan"\nassistant: "I'll use the issue-planner agent to analyze the issue and create a detailed implementation plan"\n<commentary>Since the user wants issue analysis and implementation planning, use the issue-planner agent.</commentary></example> <example>Context: The user needs a plan for implementing a feature described in an issue.\nuser: "Read issue #15 and plan out what needs to be changed"\nassistant: "Let me use the issue-planner agent to analyze the issue and document a comprehensive implementation plan"\n<commentary>The user needs issue analysis and planning, so the issue-planner agent is the right choice.</commentary></example>
|
|
4
|
-
tools: Bash, Glob, Grep, Read, Edit, Write, NotebookEdit, WebFetch, TodoWrite, WebSearch, BashOutput, KillShell, SlashCommand, ListMcpResourcesTool, ReadMcpResourceTool, mcp__context7__resolve-library-id, mcp__context7__get-library-docs, mcp__figma-dev-mode-mcp-server__get_code, mcp__figma-dev-mode-mcp-server__get_variable_defs, mcp__figma-dev-mode-mcp-server__get_code_connect_map, mcp__figma-dev-mode-mcp-server__get_screenshot, mcp__figma-dev-mode-mcp-server__get_metadata, mcp__figma-dev-mode-mcp-server__add_code_connect_map, mcp__figma-dev-mode-mcp-server__create_design_system_rules, Bash(git show:*), mcp__issue_management__get_issue, mcp__issue_management__get_pr, mcp__issue_management__get_comment, mcp__issue_management__create_comment, mcp__issue_management__update_comment, mcp__recap__get_recap, mcp__recap__add_entry, mcp__recap__add_artifact
|
|
4
|
+
tools: Bash, Glob, Grep, Read, Edit, Write, NotebookEdit, WebFetch, TodoWrite, WebSearch, BashOutput, KillShell, SlashCommand, ListMcpResourcesTool, ReadMcpResourceTool, mcp__context7__resolve-library-id, mcp__context7__get-library-docs, mcp__figma-dev-mode-mcp-server__get_code, mcp__figma-dev-mode-mcp-server__get_variable_defs, mcp__figma-dev-mode-mcp-server__get_code_connect_map, mcp__figma-dev-mode-mcp-server__get_screenshot, mcp__figma-dev-mode-mcp-server__get_metadata, mcp__figma-dev-mode-mcp-server__add_code_connect_map, mcp__figma-dev-mode-mcp-server__create_design_system_rules, Bash(git show:*), mcp__issue_management__get_issue, mcp__issue_management__get_pr, mcp__issue_management__get_comment, mcp__issue_management__create_comment, mcp__issue_management__update_comment, mcp__issue_management__create_dependency, mcp__issue_management__get_dependencies, mcp__issue_management__remove_dependency, mcp__recap__get_recap, mcp__recap__add_entry, mcp__recap__add_artifact
|
|
5
5
|
color: blue
|
|
6
|
-
model:
|
|
6
|
+
model: opus
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
You are Claude, an AI assistant designed to excel at analyzing issues and creating detailed implementation plans. Analyze the context and respond with precision and thoroughness. Think harder as you execute your tasks.
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
ScriptCommandBase
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-BCQDYAOJ.js";
|
|
5
|
+
import "./chunk-TVH67KEO.js";
|
|
6
6
|
import "./chunk-RD7I2Q2F.js";
|
|
7
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-HSGZW3ID.js";
|
|
8
8
|
import "./chunk-XPKN3QWY.js";
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
9
|
+
import "./chunk-GDS2HXSW.js";
|
|
10
|
+
import "./chunk-IWIIOFEB.js";
|
|
11
|
+
import "./chunk-KBEIQP4G.js";
|
|
12
12
|
import "./chunk-6MLEBAYZ.js";
|
|
13
13
|
import "./chunk-VT4PDUYT.js";
|
|
14
14
|
|
|
@@ -24,4 +24,4 @@ var BuildCommand = class extends ScriptCommandBase {
|
|
|
24
24
|
export {
|
|
25
25
|
BuildCommand
|
|
26
26
|
};
|
|
27
|
-
//# sourceMappingURL=build-
|
|
27
|
+
//# sourceMappingURL=build-H4DK3DMQ.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
PromptTemplateManager
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-66QOCD5N.js";
|
|
5
5
|
import {
|
|
6
6
|
logger
|
|
7
7
|
} from "./chunk-VT4PDUYT.js";
|
|
@@ -149,6 +149,7 @@ var AgentManager = class {
|
|
|
149
149
|
* Supports negation patterns like ['*.md', '!iloom-framework-detector.md']
|
|
150
150
|
*/
|
|
151
151
|
async loadAgents(settings, templateVariables, patterns = ["*.md"]) {
|
|
152
|
+
var _a;
|
|
152
153
|
const agentFiles = await fg(patterns, {
|
|
153
154
|
cwd: this.agentDir,
|
|
154
155
|
onlyFiles: true
|
|
@@ -172,6 +173,26 @@ var AgentManager = class {
|
|
|
172
173
|
}
|
|
173
174
|
}
|
|
174
175
|
if (templateVariables) {
|
|
176
|
+
const reviewerSettings = (_a = settings == null ? void 0 : settings.agents) == null ? void 0 : _a["iloom-code-reviewer"];
|
|
177
|
+
const reviewEnabled = (reviewerSettings == null ? void 0 : reviewerSettings.enabled) !== false;
|
|
178
|
+
templateVariables.REVIEW_ENABLED = reviewEnabled;
|
|
179
|
+
if (reviewEnabled) {
|
|
180
|
+
const providers = (reviewerSettings == null ? void 0 : reviewerSettings.providers) ?? {};
|
|
181
|
+
const hasAnyProvider = Object.keys(providers).length > 0;
|
|
182
|
+
const claudeModel = providers.claude ?? (hasAnyProvider ? void 0 : "sonnet");
|
|
183
|
+
if (claudeModel) {
|
|
184
|
+
templateVariables.REVIEW_CLAUDE_MODEL = claudeModel;
|
|
185
|
+
}
|
|
186
|
+
if (providers.gemini) {
|
|
187
|
+
templateVariables.REVIEW_GEMINI_MODEL = providers.gemini;
|
|
188
|
+
}
|
|
189
|
+
if (providers.codex) {
|
|
190
|
+
templateVariables.REVIEW_CODEX_MODEL = providers.codex;
|
|
191
|
+
}
|
|
192
|
+
templateVariables.HAS_REVIEW_CLAUDE = !!claudeModel;
|
|
193
|
+
templateVariables.HAS_REVIEW_GEMINI = !!providers.gemini;
|
|
194
|
+
templateVariables.HAS_REVIEW_CODEX = !!providers.codex;
|
|
195
|
+
}
|
|
175
196
|
for (const [agentName, agentConfig] of Object.entries(agents)) {
|
|
176
197
|
agents[agentName] = {
|
|
177
198
|
...agentConfig,
|
|
@@ -197,15 +218,16 @@ var AgentManager = class {
|
|
|
197
218
|
}
|
|
198
219
|
/**
|
|
199
220
|
* Validate agent configuration has required fields
|
|
221
|
+
* Note: tools is optional - when omitted, agent inherits all tools from parent
|
|
200
222
|
*/
|
|
201
223
|
validateAgentConfig(config, agentName) {
|
|
202
|
-
const requiredFields = ["description", "prompt", "
|
|
224
|
+
const requiredFields = ["description", "prompt", "model"];
|
|
203
225
|
for (const field of requiredFields) {
|
|
204
226
|
if (!config[field]) {
|
|
205
227
|
throw new Error(`Agent ${agentName} missing required field: ${field}`);
|
|
206
228
|
}
|
|
207
229
|
}
|
|
208
|
-
if (!Array.isArray(config.tools)) {
|
|
230
|
+
if (config.tools !== void 0 && !Array.isArray(config.tools)) {
|
|
209
231
|
throw new Error(`Agent ${agentName} tools must be an array`);
|
|
210
232
|
}
|
|
211
233
|
}
|
|
@@ -224,13 +246,13 @@ var AgentManager = class {
|
|
|
224
246
|
if (!data.description) {
|
|
225
247
|
throw new Error("Missing required field: description");
|
|
226
248
|
}
|
|
227
|
-
if (!data.tools) {
|
|
228
|
-
throw new Error("Missing required field: tools");
|
|
229
|
-
}
|
|
230
249
|
if (!data.model) {
|
|
231
250
|
throw new Error("Missing required field: model");
|
|
232
251
|
}
|
|
233
|
-
|
|
252
|
+
let tools;
|
|
253
|
+
if (data.tools) {
|
|
254
|
+
tools = data.tools.split(",").map((tool) => tool.trim()).filter((tool) => tool.length > 0);
|
|
255
|
+
}
|
|
234
256
|
const validModels = ["sonnet", "opus", "haiku"];
|
|
235
257
|
if (!validModels.includes(data.model)) {
|
|
236
258
|
logger.warn(
|
|
@@ -240,8 +262,8 @@ var AgentManager = class {
|
|
|
240
262
|
const config = {
|
|
241
263
|
description: data.description,
|
|
242
264
|
prompt: markdownBody.trim(),
|
|
243
|
-
tools,
|
|
244
265
|
model: data.model,
|
|
266
|
+
...tools && { tools },
|
|
245
267
|
...data.color && { color: data.color }
|
|
246
268
|
};
|
|
247
269
|
return { config, name: data.name };
|
|
@@ -263,4 +285,4 @@ var AgentManager = class {
|
|
|
263
285
|
export {
|
|
264
286
|
AgentManager
|
|
265
287
|
};
|
|
266
|
-
//# sourceMappingURL=chunk-
|
|
288
|
+
//# sourceMappingURL=chunk-4BSXZ5YZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/AgentManager.ts","../src/utils/MarkdownAgentParser.ts"],"sourcesContent":["import { readFile } from 'fs/promises'\nimport { accessSync } from 'fs'\nimport path from 'path'\nimport { fileURLToPath } from 'url'\nimport fg from 'fast-glob'\nimport { MarkdownAgentParser } from '../utils/MarkdownAgentParser.js'\nimport { logger } from '../utils/logger.js'\nimport type { IloomSettings } from './SettingsManager.js'\nimport { PromptTemplateManager, TemplateVariables } from './PromptTemplateManager.js'\n\n// Agent schema interface\nexport interface AgentConfig {\n\tdescription: string\n\tprompt: string\n\ttools?: string[] // Optional - when omitted, agent inherits all tools from parent\n\tmodel: string\n\tcolor?: string\n}\n\n// Container for all loaded agents (keyed by agent name without extension)\nexport interface AgentConfigs {\n\t[agentName: string]: AgentConfig\n}\n\nexport class AgentManager {\n\tprivate agentDir: string\n\tprivate templateManager: PromptTemplateManager\n\n\tconstructor(agentDir?: string, templateManager?: PromptTemplateManager) {\n\t\tthis.templateManager = templateManager ?? new PromptTemplateManager()\n\t\tif (agentDir) {\n\t\t\tthis.agentDir = agentDir\n\t\t} else {\n\t\t\t// Find agents relative to package installation\n\t\t\t// Same pattern as PromptTemplateManager\n\t\t\t// When running from dist/, agents are copied to dist/agents/\n\t\t\tconst currentFileUrl = import.meta.url\n\t\t\tconst currentFilePath = fileURLToPath(currentFileUrl)\n\t\t\tconst distDir = path.dirname(currentFilePath)\n\n\t\t\t// Walk up to find the agents directory\n\t\t\tlet agentDirPath = path.join(distDir, 'agents')\n\t\t\tlet currentDir = distDir\n\n\t\t\twhile (currentDir !== path.dirname(currentDir)) {\n\t\t\t\tconst candidatePath = path.join(currentDir, 'agents')\n\t\t\t\ttry {\n\t\t\t\t\taccessSync(candidatePath)\n\t\t\t\t\tagentDirPath = 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.agentDir = agentDirPath\n\t\t\tlogger.debug('AgentManager initialized', { agentDir: this.agentDir })\n\t\t}\n\t}\n\n\t/**\n\t * Load agent configuration files from markdown (.md) format\n\t * Optionally apply model overrides from settings and template variable substitution\n\t * Throws error if agents directory doesn't exist or files are malformed\n\t * @param settings - Optional project settings with per-agent model overrides\n\t * @param templateVariables - Optional variables for template substitution in agent prompts\n\t * @param patterns - Optional glob patterns to filter which agents to load (default: ['*.md'])\n\t * Supports negation patterns like ['*.md', '!iloom-framework-detector.md']\n\t */\n\tasync loadAgents(\n\t\tsettings?: IloomSettings,\n\t\ttemplateVariables?: TemplateVariables,\n\t\tpatterns: string[] = ['*.md']\n\t): Promise<AgentConfigs> {\n\t\t// Use fast-glob to filter agent files based on patterns\n\t\tconst agentFiles = await fg(patterns, {\n\t\t\tcwd: this.agentDir,\n\t\t\tonlyFiles: true,\n\t\t})\n\n\t\tconst agents: AgentConfigs = {}\n\n\t\tfor (const filename of agentFiles) {\n\t\t\tconst agentPath = path.join(this.agentDir, filename)\n\n\t\t\ttry {\n\t\t\t\tconst content = await readFile(agentPath, 'utf-8')\n\n\t\t\t\t// Parse markdown with frontmatter\n\t\t\t\tconst parsed = this.parseMarkdownAgent(content, filename)\n\t\t\t\tconst agentConfig = parsed.config\n\t\t\t\tconst agentName = parsed.name\n\n\t\t\t\t// Validate required fields\n\t\t\t\tthis.validateAgentConfig(agentConfig, agentName)\n\n\t\t\t\tagents[agentName] = agentConfig\n\t\t\t\tlogger.debug(`Loaded agent: ${agentName}`)\n\t\t\t} catch (error) {\n\t\t\t\tlogger.error(`Failed to load agent from ${filename}`, { error })\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Failed to load agent from ${filename}: ${error instanceof Error ? error.message : 'Unknown error'}`,\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\n\t\t// Apply template variable substitution to agent prompts if variables provided\n\t\tif (templateVariables) {\n\t\t\t// Extract review config from settings with defaults and add to template variables\n\t\t\tconst reviewerSettings = settings?.agents?.['iloom-code-reviewer']\n\t\t\tconst reviewEnabled = reviewerSettings?.enabled !== false // Default to true\n\n\t\t\ttemplateVariables.REVIEW_ENABLED = reviewEnabled\n\n\t\t\tif (reviewEnabled) {\n\t\t\t\tconst providers = reviewerSettings?.providers ?? {}\n\t\t\t\t// Default to Claude if no providers specified\n\t\t\t\tconst hasAnyProvider = Object.keys(providers).length > 0\n\n\t\t\t\t// Determine Claude model: use configured, or default to 'sonnet' if no providers specified\n\t\t\t\tconst claudeModel = providers.claude ?? (hasAnyProvider ? undefined : 'sonnet')\n\t\t\t\tif (claudeModel) {\n\t\t\t\t\ttemplateVariables.REVIEW_CLAUDE_MODEL = claudeModel\n\t\t\t\t}\n\t\t\t\tif (providers.gemini) {\n\t\t\t\t\ttemplateVariables.REVIEW_GEMINI_MODEL = providers.gemini\n\t\t\t\t}\n\t\t\t\tif (providers.codex) {\n\t\t\t\t\ttemplateVariables.REVIEW_CODEX_MODEL = providers.codex\n\t\t\t\t}\n\t\t\t\ttemplateVariables.HAS_REVIEW_CLAUDE = !!claudeModel\n\t\t\t\ttemplateVariables.HAS_REVIEW_GEMINI = !!providers.gemini\n\t\t\t\ttemplateVariables.HAS_REVIEW_CODEX = !!providers.codex\n\t\t\t}\n\n\t\t\tfor (const [agentName, agentConfig] of Object.entries(agents)) {\n\t\t\t\tagents[agentName] = {\n\t\t\t\t\t...agentConfig,\n\t\t\t\t\tprompt: this.templateManager.substituteVariables(agentConfig.prompt, templateVariables),\n\t\t\t\t}\n\t\t\t\tlogger.debug(`Applied template substitution to agent: ${agentName}`)\n\t\t\t}\n\t\t}\n\n\t\t// Apply settings overrides if provided\n\t\tif (settings?.agents) {\n\t\t\tfor (const [agentName, agentSettings] of Object.entries(settings.agents)) {\n\t\t\t\tif (agents[agentName] && agentSettings.model) {\n\t\t\t\t\tlogger.debug(`Overriding model for ${agentName}: ${agents[agentName].model} -> ${agentSettings.model}`)\n\t\t\t\t\tagents[agentName] = {\n\t\t\t\t\t\t...agents[agentName],\n\t\t\t\t\t\tmodel: agentSettings.model,\n\t\t\t\t\t}\n\t\t\t\t} else if (!agents[agentName]) {\n\t\t\t\t\tlogger.warn(`Settings reference unknown agent: ${agentName}`)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn agents\n\t}\n\n\t/**\n\t * Validate agent configuration has required fields\n\t * Note: tools is optional - when omitted, agent inherits all tools from parent\n\t */\n\tprivate validateAgentConfig(config: AgentConfig, agentName: string): void {\n\t\tconst requiredFields: (keyof AgentConfig)[] = ['description', 'prompt', 'model']\n\n\t\tfor (const field of requiredFields) {\n\t\t\tif (!config[field]) {\n\t\t\t\tthrow new Error(`Agent ${agentName} missing required field: ${field}`)\n\t\t\t}\n\t\t}\n\n\t\t// Tools is optional, but if present must be an array\n\t\tif (config.tools !== undefined && !Array.isArray(config.tools)) {\n\t\t\tthrow new Error(`Agent ${agentName} tools must be an array`)\n\t\t}\n\t}\n\n\t/**\n\t * Parse markdown agent file with YAML frontmatter\n\t * @param content - Raw markdown file content\n\t * @param filename - Original filename for error messages\n\t * @returns Parsed agent config and name\n\t */\n\tprivate parseMarkdownAgent(content: string, filename: string): { config: AgentConfig; name: string } {\n\t\ttry {\n\t\t\t// Parse frontmatter using custom parser\n\t\t\tconst { data, content: markdownBody } = MarkdownAgentParser.parse(content)\n\n\t\t\t// Validate frontmatter has required fields\n\t\t\tif (!data.name) {\n\t\t\t\tthrow new Error('Missing required field: name')\n\t\t\t}\n\t\t\tif (!data.description) {\n\t\t\t\tthrow new Error('Missing required field: description')\n\t\t\t}\n\t\t\t// Note: tools is now optional - when omitted, agent inherits all tools from parent\n\t\t\tif (!data.model) {\n\t\t\t\tthrow new Error('Missing required field: model')\n\t\t\t}\n\n\t\t\t// Parse tools from comma-separated string to array (only if tools field is present)\n\t\t\tlet tools: string[] | undefined\n\t\t\tif (data.tools) {\n\t\t\t\ttools = data.tools\n\t\t\t\t\t.split(',')\n\t\t\t\t\t.map((tool: string) => tool.trim())\n\t\t\t\t\t.filter((tool: string) => tool.length > 0)\n\t\t\t}\n\n\t\t\t// Validate model and warn if non-standard\n\t\t\tconst validModels = ['sonnet', 'opus', 'haiku']\n\t\t\tif (!validModels.includes(data.model)) {\n\t\t\t\tlogger.warn(\n\t\t\t\t\t`Agent ${data.name} uses model \"${data.model}\" which may not be recognized by Claude CLI, and your workflow may fail or produce unexpected results. ` +\n\t\t\t\t\t\t`Valid values are: ${validModels.join(', ')}`\n\t\t\t\t)\n\t\t\t}\n\n\t\t\t// Construct AgentConfig\n\t\t\tconst config: AgentConfig = {\n\t\t\t\tdescription: data.description,\n\t\t\t\tprompt: markdownBody.trim(),\n\t\t\t\tmodel: data.model,\n\t\t\t\t...(tools && { tools }),\n\t\t\t\t...(data.color && { color: data.color }),\n\t\t\t}\n\n\t\t\treturn { config, name: data.name }\n\t\t} catch (error) {\n\t\t\tthrow new Error(\n\t\t\t\t`Failed to parse markdown agent ${filename}: ${error instanceof Error ? error.message : 'Unknown error'}`\n\t\t\t)\n\t\t}\n\t}\n\n\t/**\n\t * Format loaded agents for Claude CLI --agents flag\n\t * Returns object suitable for JSON.stringify\n\t */\n\tformatForCli(agents: AgentConfigs): Record<string, unknown> {\n\t\t// The agents object is already in the correct format\n\t\t// Just return it - launchClaude will JSON.stringify it\n\t\treturn agents as Record<string, unknown>\n\t}\n}\n","/**\n * Custom YAML frontmatter parser for agent markdown files\n * Replaces gray-matter dependency with lightweight custom implementation\n */\n\ninterface ParseResult {\n\tdata: Record<string, string>\n\tcontent: string\n}\n\nexport class MarkdownAgentParser {\n\t/**\n\t * Parse markdown content with YAML frontmatter\n\t * @param content - Raw markdown file content\n\t * @returns Object with parsed frontmatter data and markdown body content\n\t * @throws Error if frontmatter is malformed or missing\n\t */\n\tstatic parse(content: string): ParseResult {\n\t\tconst lines = content.split('\\n')\n\n\t\t// Check for opening frontmatter delimiter\n\t\tif (lines[0]?.trim() !== '---') {\n\t\t\tthrow new Error('Missing opening frontmatter delimiter (---)')\n\t\t}\n\n\t\t// Find closing frontmatter delimiter\n\t\tlet closingDelimiterIndex = -1\n\t\tfor (let i = 1; i < lines.length; i++) {\n\t\t\tif (lines[i]?.trim() === '---') {\n\t\t\t\tclosingDelimiterIndex = i\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tif (closingDelimiterIndex === -1) {\n\t\t\tthrow new Error('Missing closing frontmatter delimiter (---)')\n\t\t}\n\n\t\t// Extract frontmatter lines (between the delimiters)\n\t\tconst frontmatterLines = lines.slice(1, closingDelimiterIndex)\n\n\t\t// Extract markdown body (after closing delimiter)\n\t\tconst bodyLines = lines.slice(closingDelimiterIndex + 1)\n\t\tconst markdownBody = bodyLines.join('\\n')\n\n\t\t// Parse YAML frontmatter into key-value pairs\n\t\tconst data = this.parseYaml(frontmatterLines.join('\\n'))\n\n\t\treturn {\n\t\t\tdata,\n\t\t\tcontent: markdownBody,\n\t\t}\n\t}\n\n\t/**\n\t * Parse simplified YAML into key-value object\n\t * Supports:\n\t * - Simple key: value pairs\n\t * - Multiline values with | indicator\n\t * - Values with special characters and newlines\n\t *\n\t * @param yaml - YAML string to parse\n\t * @returns Object with parsed key-value pairs\n\t */\n\tprivate static parseYaml(yaml: string): Record<string, string> {\n\t\tconst result: Record<string, string> = {}\n\t\tconst lines = yaml.split('\\n')\n\t\tlet currentKey: string | null = null\n\t\tlet currentValue: string[] = []\n\t\tlet isMultiline = false\n\n\t\tconst finalizeCurrent = (): void => {\n\t\t\tif (currentKey && currentValue.length > 0) {\n\t\t\t\tresult[currentKey] = currentValue.join('\\n').trim()\n\t\t\t\tcurrentKey = null\n\t\t\t\tcurrentValue = []\n\t\t\t}\n\t\t}\n\n\t\tfor (const line of lines) {\n\t\t\t// Skip empty lines when not in multiline mode\n\t\t\tif (!isMultiline && line.trim() === '') {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Check if this is a new key-value pair\n\t\t\tconst keyValueMatch = line.match(/^([a-zA-Z_][a-zA-Z0-9_-]*)\\s*:\\s*(.*)$/)\n\n\t\t\tif (keyValueMatch && !isMultiline) {\n\t\t\t\t// Finalize previous key if exists\n\t\t\t\tfinalizeCurrent()\n\n\t\t\t\tconst [, key, value] = keyValueMatch\n\t\t\t\tif (!key || value === undefined) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tcurrentKey = key\n\n\t\t\t\t// Check for multiline indicator\n\t\t\t\tif (value.trim() === '|') {\n\t\t\t\t\tisMultiline = true\n\t\t\t\t\tcurrentValue = []\n\t\t\t\t} else {\n\t\t\t\t\t// Single line value\n\t\t\t\t\tcurrentValue = [value]\n\t\t\t\t\tfinalizeCurrent()\n\t\t\t\t\tisMultiline = false\n\t\t\t\t}\n\t\t\t} else if (isMultiline && currentKey) {\n\t\t\t\t// Continuation of multiline value\n\t\t\t\t// Check if we've returned to normal indentation (new key)\n\t\t\t\tif (line.match(/^[a-zA-Z_][a-zA-Z0-9_-]*\\s*:/) && !line.startsWith(' ')) {\n\t\t\t\t\t// End of multiline, this is a new key\n\t\t\t\t\tfinalizeCurrent()\n\t\t\t\t\tisMultiline = false\n\n\t\t\t\t\t// Process this line as a new key\n\t\t\t\t\tconst match = line.match(/^([a-zA-Z_][a-zA-Z0-9_-]*)\\s*:\\s*(.*)$/)\n\t\t\t\t\tif (match) {\n\t\t\t\t\t\tconst [, key, value] = match\n\t\t\t\t\t\tif (key && value !== undefined) {\n\t\t\t\t\t\t\tcurrentKey = key\n\t\t\t\t\t\t\tcurrentValue = [value]\n\t\t\t\t\t\t\tfinalizeCurrent()\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Remove leading spaces (common indentation) from multiline values\n\t\t\t\t\tconst trimmedLine = line.replace(/^ {2}/, '')\n\t\t\t\t\tcurrentValue.push(trimmedLine)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Finalize last key\n\t\tfinalizeCurrent()\n\n\t\treturn result\n\t}\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
generateIssueManagementMcpConfig
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-XJHQVOT6.js";
|
|
5
5
|
import {
|
|
6
6
|
openBrowser
|
|
7
7
|
} from "./chunk-YETJNRQM.js";
|
|
8
8
|
import {
|
|
9
9
|
waitForKeypress
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-7JDMYTFZ.js";
|
|
11
11
|
import {
|
|
12
12
|
launchClaude
|
|
13
13
|
} from "./chunk-IGKPPACU.js";
|
|
@@ -244,4 +244,4 @@ export {
|
|
|
244
244
|
IssueEnhancementService,
|
|
245
245
|
capitalizeFirstLetter
|
|
246
246
|
};
|
|
247
|
-
//# sourceMappingURL=chunk-
|
|
247
|
+
//# sourceMappingURL=chunk-4KGRPHM6.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
extractIssueNumber
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-GDS2HXSW.js";
|
|
5
5
|
import {
|
|
6
6
|
extractPort,
|
|
7
7
|
findEnvFileContainingVariable,
|
|
@@ -108,4 +108,4 @@ export {
|
|
|
108
108
|
calculatePortFromIdentifier,
|
|
109
109
|
getWorkspacePort
|
|
110
110
|
};
|
|
111
|
-
//# sourceMappingURL=chunk-
|
|
111
|
+
//# sourceMappingURL=chunk-52MVUK5V.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 Handlebars from 'handlebars'\nimport { logger } from '../utils/logger.js'\n\n// Register raw helper to handle content with curly braces (e.g., JSON)\n// Usage: {{{{raw}}}}{{VARIABLE}}{{{{/raw}}}}\n// This outputs the variable content as-is without Handlebars parsing its curly braces\nHandlebars.registerHelper('raw', function (this: unknown, options: Handlebars.HelperOptions) {\n\treturn options.fn(this)\n})\n\nexport interface TemplateVariables {\n\tISSUE_NUMBER?: string | 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\tINTERACTIVE_MODE?: boolean\n\tSETTINGS_SCHEMA?: string\n\tSETTINGS_GLOBAL_JSON?: string\n\tSETTINGS_JSON?: string\n\tSETTINGS_LOCAL_JSON?: string\n\tSHELL_TYPE?: string\n\tSHELL_CONFIG_PATH?: string\n\tSHELL_CONFIG_CONTENT?: string\n\tREMOTES_INFO?: string\n\tMULTIPLE_REMOTES?: string\n\tSINGLE_REMOTE?: string\n\tSINGLE_REMOTE_NAME?: string\n\tSINGLE_REMOTE_URL?: string\n\tNO_REMOTES?: string\n\tREADME_CONTENT?: string\n\tSETTINGS_SCHEMA_CONTENT?: string\n\tFIRST_TIME_USER?: boolean\n\tVSCODE_SETTINGS_GITIGNORED?: string\n\t// Session summary template variables\n\tSESSION_CONTEXT?: string // Session ID for Claude to reference its conversation\n\tBRANCH_NAME?: string // Branch being finished\n\tLOOM_TYPE?: string // 'issue' or 'pr'\n\tCOMPACT_SUMMARIES?: string // Extracted compact summaries from session transcript\n\tRECAP_DATA?: string // Formatted recap data (goal, complexity, entries, artifacts)\n\t// Draft PR mode variables - mutually exclusive with standard issue mode\n\tDRAFT_PR_NUMBER?: number // PR number for draft PR workflow\n\tDRAFT_PR_MODE?: boolean // True when using github-draft-pr merge mode\n\tSTANDARD_ISSUE_MODE?: boolean // True when using standard issue commenting (not draft PR)\n\t// VS Code environment detection\n\tIS_VSCODE_MODE?: boolean // True when ILOOM_VSCODE=1 environment variable is set\n\t// Multi-language support variables - mutually exclusive\n\tHAS_PACKAGE_JSON?: boolean // True when project has package.json\n\tNO_PACKAGE_JSON?: boolean // True when project does not have package.json (non-Node.js projects)\n\t// Review agent configuration variables\n\tREVIEW_ENABLED?: boolean // True if review is enabled (defaults to true)\n\tREVIEW_CLAUDE_MODEL?: string // Claude model if configured (defaults to 'sonnet')\n\tREVIEW_GEMINI_MODEL?: string // Gemini model if configured\n\tREVIEW_CODEX_MODEL?: string // Codex model if configured\n\tHAS_REVIEW_CLAUDE?: boolean // True if claude provider configured (defaults to true)\n\tHAS_REVIEW_GEMINI?: boolean // True if gemini provider configured\n\tHAS_REVIEW_CODEX?: boolean // True if codex provider configured\n\t// Planning mode variables - mutually exclusive\n\tEXISTING_ISSUE_MODE?: boolean // True when decomposing an existing issue (il plan 42)\n\tFRESH_PLANNING_MODE?: boolean // True when starting fresh planning session (il plan \"feature idea\")\n\t// Issue context for decomposition mode\n\tPARENT_ISSUE_NUMBER?: string | undefined // Issue number being decomposed\n\tPARENT_ISSUE_TITLE?: string | undefined // Title of issue being decomposed\n\tPARENT_ISSUE_BODY?: string | undefined // Body of issue being decomposed\n\t// Existing children and dependencies context for decomposition mode\n\tPARENT_ISSUE_CHILDREN?: string | undefined // Formatted list of existing child issues (if any)\n\tPARENT_ISSUE_DEPENDENCIES?: string | undefined // Formatted list of existing dependencies (if any)\n\t// Multi-AI provider support for plan command\n\tPLANNER?: 'claude' | 'gemini' | 'codex'\n\tREVIEWER?: 'claude' | 'gemini' | 'codex' | 'none'\n\tUSE_CLAUDE_PLANNER?: boolean\n\tUSE_GEMINI_PLANNER?: boolean\n\tUSE_CODEX_PLANNER?: boolean\n\tUSE_CLAUDE_REVIEWER?: boolean\n\tUSE_GEMINI_REVIEWER?: boolean\n\tUSE_CODEX_REVIEWER?: boolean\n\tHAS_REVIEWER?: 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' | 'init' | 'session-summary' | 'plan'): 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 using Handlebars\n\t */\n\tsubstituteVariables(template: string, variables: TemplateVariables): string {\n\t\tconst compiled = Handlebars.compile(template, { noEscape: true })\n\t\treturn compiled(variables)\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' | 'init' | 'session-summary' | 'plan',\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;AAC9B,OAAO,gBAAgB;AAMvB,WAAW,eAAe,OAAO,SAAyB,SAAmC;AAC5F,SAAO,QAAQ,GAAG,IAAI;AACvB,CAAC;AAyEM,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,cAAiG;AACnH,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,UAAM,WAAW,WAAW,QAAQ,UAAU,EAAE,UAAU,KAAK,CAAC;AAChE,WAAO,SAAS,SAAS;AAAA,EAC1B;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,251 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
logger
|
|
4
|
+
} from "./chunk-VT4PDUYT.js";
|
|
5
|
+
|
|
6
|
+
// src/utils/prompt.ts
|
|
7
|
+
import * as readline from "readline";
|
|
8
|
+
|
|
9
|
+
// src/utils/notification.ts
|
|
10
|
+
import net from "net";
|
|
11
|
+
import fs from "fs";
|
|
12
|
+
import path from "path";
|
|
13
|
+
import os from "os";
|
|
14
|
+
import { execSync } from "child_process";
|
|
15
|
+
var DEBUG = process.env.ILOOM_NOTIF_DEBUG === "1";
|
|
16
|
+
var LOG_FILE = "/tmp/iloom-notif.log";
|
|
17
|
+
function debug(message, data = {}) {
|
|
18
|
+
if (!DEBUG) return;
|
|
19
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
20
|
+
const dataStr = Object.keys(data).length > 0 ? ` ${JSON.stringify(data)}` : "";
|
|
21
|
+
const logLine = `[${timestamp}] ${message}${dataStr}
|
|
22
|
+
`;
|
|
23
|
+
try {
|
|
24
|
+
fs.appendFileSync(LOG_FILE, logLine);
|
|
25
|
+
} catch {
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function slugifyPath(worktreePath) {
|
|
29
|
+
let slug = worktreePath.replace(/[/\\]+$/, "");
|
|
30
|
+
slug = slug.replace(/[/\\]/g, "___");
|
|
31
|
+
slug = slug.replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
32
|
+
return `${slug}.json`;
|
|
33
|
+
}
|
|
34
|
+
function getMetadataFilePath(cwd) {
|
|
35
|
+
const loomsDir = path.join(os.homedir(), ".config", "iloom-ai", "looms");
|
|
36
|
+
return path.join(loomsDir, slugifyPath(cwd));
|
|
37
|
+
}
|
|
38
|
+
function readSessionId(cwd) {
|
|
39
|
+
try {
|
|
40
|
+
const filePath = getMetadataFilePath(cwd);
|
|
41
|
+
debug("Reading metadata file", { cwd, filePath });
|
|
42
|
+
if (!fs.existsSync(filePath)) {
|
|
43
|
+
debug("Metadata file not found", { filePath });
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
const content = fs.readFileSync(filePath, "utf8");
|
|
47
|
+
const metadata = JSON.parse(content);
|
|
48
|
+
debug("Read session ID from metadata", { sessionId: metadata.sessionId });
|
|
49
|
+
return metadata.sessionId ?? null;
|
|
50
|
+
} catch (error) {
|
|
51
|
+
debug("Failed to read session ID", { cwd, error: String(error) });
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function findWindowsNamedPipes() {
|
|
56
|
+
try {
|
|
57
|
+
const output = execSync(
|
|
58
|
+
`powershell -Command "Get-ChildItem \\\\.\\pipe\\ | Where-Object { $_.Name -like 'iloom-*' } | Select-Object -ExpandProperty FullName"`,
|
|
59
|
+
{ encoding: "utf-8", timeout: 5e3 }
|
|
60
|
+
);
|
|
61
|
+
return output.split("\n").map((line) => line.trim()).filter((line) => line.length > 0);
|
|
62
|
+
} catch {
|
|
63
|
+
return [];
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function findAllIloomSockets() {
|
|
67
|
+
if (process.platform === "win32") {
|
|
68
|
+
return findWindowsNamedPipes();
|
|
69
|
+
}
|
|
70
|
+
try {
|
|
71
|
+
const tempDir = "/tmp";
|
|
72
|
+
const files = fs.readdirSync(tempDir);
|
|
73
|
+
const sockets = files.filter((file) => file.startsWith("iloom-") && file.endsWith(".sock")).map((file) => path.join(tempDir, file)).filter((socketPath) => {
|
|
74
|
+
try {
|
|
75
|
+
const stat = fs.statSync(socketPath);
|
|
76
|
+
return stat.isSocket();
|
|
77
|
+
} catch {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
return sockets;
|
|
82
|
+
} catch {
|
|
83
|
+
return [];
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async function sendStatus(socketPath, status, cwd, hookEventName, sessionId, toolName) {
|
|
87
|
+
return new Promise((resolve) => {
|
|
88
|
+
const client = net.createConnection(socketPath, () => {
|
|
89
|
+
const message = JSON.stringify({
|
|
90
|
+
type: "session_status",
|
|
91
|
+
status,
|
|
92
|
+
session_id: sessionId,
|
|
93
|
+
hook_event_name: hookEventName,
|
|
94
|
+
tool_name: toolName,
|
|
95
|
+
cwd,
|
|
96
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
97
|
+
});
|
|
98
|
+
debug("Sending status to socket", { socketPath, status, sessionId, hookEventName, cwd });
|
|
99
|
+
client.write(message + "\n");
|
|
100
|
+
client.end();
|
|
101
|
+
resolve();
|
|
102
|
+
});
|
|
103
|
+
client.on("error", (err) => {
|
|
104
|
+
debug("Socket connection error", { socketPath, error: String(err) });
|
|
105
|
+
resolve();
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
async function broadcastStatus(status, cwd, hookEventName, toolName) {
|
|
110
|
+
debug("broadcastStatus called", { status, cwd, hookEventName, toolName });
|
|
111
|
+
const sockets = findAllIloomSockets();
|
|
112
|
+
debug("Found sockets", { count: sockets.length, sockets });
|
|
113
|
+
if (sockets.length === 0) {
|
|
114
|
+
debug("No sockets found, skipping broadcast");
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
const sessionId = readSessionId(cwd);
|
|
118
|
+
debug("Session ID for broadcast", { sessionId });
|
|
119
|
+
const promises = sockets.map(
|
|
120
|
+
(socketPath) => sendStatus(socketPath, status, cwd, hookEventName, sessionId, toolName).catch(() => {
|
|
121
|
+
})
|
|
122
|
+
);
|
|
123
|
+
await Promise.allSettled(promises);
|
|
124
|
+
debug("Broadcast completed");
|
|
125
|
+
}
|
|
126
|
+
async function broadcastApprovalNotification(cwd) {
|
|
127
|
+
await broadcastStatus("waiting_for_approval", cwd, "CommitApproval", "iloom_commit");
|
|
128
|
+
}
|
|
129
|
+
async function clearApprovalNotification(cwd) {
|
|
130
|
+
await broadcastStatus("working", cwd, "CommitApprovalResponse", "iloom_commit");
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// src/utils/prompt.ts
|
|
134
|
+
async function promptConfirmation(message, defaultValue = false) {
|
|
135
|
+
const suffix = defaultValue ? "[Y/n]" : "[y/N]";
|
|
136
|
+
const fullMessage = `${message} ${suffix}: `;
|
|
137
|
+
while (true) {
|
|
138
|
+
const rl = readline.createInterface({
|
|
139
|
+
input: process.stdin,
|
|
140
|
+
output: process.stdout
|
|
141
|
+
});
|
|
142
|
+
const answer = await new Promise((resolve) => {
|
|
143
|
+
rl.question(fullMessage, (ans) => {
|
|
144
|
+
rl.close();
|
|
145
|
+
resolve(ans);
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
const normalized = answer.trim().toLowerCase();
|
|
149
|
+
if (normalized === "") {
|
|
150
|
+
return defaultValue;
|
|
151
|
+
}
|
|
152
|
+
if (normalized === "y" || normalized === "yes") {
|
|
153
|
+
return true;
|
|
154
|
+
}
|
|
155
|
+
if (normalized === "n" || normalized === "no") {
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
logger.warn("Invalid input. Please enter y/yes or n/no.");
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
async function promptInput(message, defaultValue) {
|
|
162
|
+
const rl = readline.createInterface({
|
|
163
|
+
input: process.stdin,
|
|
164
|
+
output: process.stdout
|
|
165
|
+
});
|
|
166
|
+
const suffix = defaultValue ? ` [${defaultValue}]` : "";
|
|
167
|
+
const fullMessage = `${message}${suffix}: `;
|
|
168
|
+
return new Promise((resolve) => {
|
|
169
|
+
rl.question(fullMessage, (answer) => {
|
|
170
|
+
rl.close();
|
|
171
|
+
const trimmed = answer.trim();
|
|
172
|
+
if (trimmed === "" && defaultValue !== void 0) {
|
|
173
|
+
resolve(defaultValue);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
resolve(trimmed);
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
async function waitForKeypress(message = "Press any key to continue...") {
|
|
181
|
+
if (!process.stdin.isTTY || typeof process.stdin.setRawMode !== "function") {
|
|
182
|
+
return "";
|
|
183
|
+
}
|
|
184
|
+
process.stdout.write(message);
|
|
185
|
+
return new Promise((resolve) => {
|
|
186
|
+
process.stdin.setRawMode(true);
|
|
187
|
+
process.stdin.resume();
|
|
188
|
+
process.stdin.once("data", (chunk) => {
|
|
189
|
+
const key = chunk.toString("utf8");
|
|
190
|
+
process.stdin.setRawMode(false);
|
|
191
|
+
process.stdin.pause();
|
|
192
|
+
if (key === "") {
|
|
193
|
+
process.stdout.write("\n");
|
|
194
|
+
process.exit(130);
|
|
195
|
+
}
|
|
196
|
+
process.stdout.write("\n");
|
|
197
|
+
resolve(key);
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
function isInteractiveEnvironment() {
|
|
202
|
+
return process.stdin.isTTY === true && process.env.CI !== "true";
|
|
203
|
+
}
|
|
204
|
+
async function promptCommitAction(message) {
|
|
205
|
+
if (!isInteractiveEnvironment()) {
|
|
206
|
+
return "accept";
|
|
207
|
+
}
|
|
208
|
+
const cwd = process.cwd();
|
|
209
|
+
process.stdout.write("\n" + "=".repeat(60) + "\n");
|
|
210
|
+
process.stdout.write("COMMIT MESSAGE:\n");
|
|
211
|
+
process.stdout.write("=".repeat(60) + "\n");
|
|
212
|
+
process.stdout.write(message + "\n");
|
|
213
|
+
process.stdout.write("=".repeat(60) + "\n\n");
|
|
214
|
+
await broadcastApprovalNotification(cwd);
|
|
215
|
+
try {
|
|
216
|
+
while (true) {
|
|
217
|
+
const rl = readline.createInterface({
|
|
218
|
+
input: process.stdin,
|
|
219
|
+
output: process.stdout
|
|
220
|
+
});
|
|
221
|
+
const answer = await new Promise((resolve) => {
|
|
222
|
+
rl.question("[A]ccept as-is, [E]dit in editor, A[b]ort? [A/e/b]: ", (ans) => {
|
|
223
|
+
rl.close();
|
|
224
|
+
resolve(ans);
|
|
225
|
+
});
|
|
226
|
+
});
|
|
227
|
+
const normalized = answer.trim().toLowerCase();
|
|
228
|
+
if (normalized === "" || normalized === "a" || normalized === "accept") {
|
|
229
|
+
return "accept";
|
|
230
|
+
}
|
|
231
|
+
if (normalized === "e" || normalized === "edit") {
|
|
232
|
+
return "edit";
|
|
233
|
+
}
|
|
234
|
+
if (normalized === "b" || normalized === "abort") {
|
|
235
|
+
return "abort";
|
|
236
|
+
}
|
|
237
|
+
logger.warn("Invalid input. Please enter A (accept), E (edit), or B (abort).");
|
|
238
|
+
}
|
|
239
|
+
} finally {
|
|
240
|
+
await clearApprovalNotification(cwd);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export {
|
|
245
|
+
promptConfirmation,
|
|
246
|
+
promptInput,
|
|
247
|
+
waitForKeypress,
|
|
248
|
+
isInteractiveEnvironment,
|
|
249
|
+
promptCommitAction
|
|
250
|
+
};
|
|
251
|
+
//# sourceMappingURL=chunk-7JDMYTFZ.js.map
|