claude-code-workflow 6.1.4 → 6.2.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/README.md +145 -274
- package/bin/ccw-mcp.js +7 -0
- package/bin/ccw.js +10 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +219 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/cli.d.ts +32 -0
- package/dist/commands/cli.d.ts.map +1 -0
- package/dist/commands/cli.js +619 -0
- package/dist/commands/cli.js.map +1 -0
- package/dist/commands/core-memory.d.ts +32 -0
- package/dist/commands/core-memory.d.ts.map +1 -0
- package/dist/commands/core-memory.js +640 -0
- package/dist/commands/core-memory.js.map +1 -0
- package/dist/commands/hook.d.ts +16 -0
- package/dist/commands/hook.d.ts.map +1 -0
- package/dist/commands/hook.js +276 -0
- package/dist/commands/hook.js.map +1 -0
- package/dist/commands/install.d.ts +12 -0
- package/dist/commands/install.d.ts.map +1 -0
- package/dist/commands/install.js +443 -0
- package/dist/commands/install.js.map +1 -0
- package/dist/commands/list.d.ts +5 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +32 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/memory.d.ts +57 -0
- package/dist/commands/memory.d.ts.map +1 -0
- package/dist/commands/memory.js +890 -0
- package/dist/commands/memory.js.map +1 -0
- package/dist/commands/serve.d.ts +12 -0
- package/dist/commands/serve.d.ts.map +1 -0
- package/dist/commands/serve.js +63 -0
- package/dist/commands/serve.js.map +1 -0
- package/dist/commands/session-path-resolver.d.ts +45 -0
- package/dist/commands/session-path-resolver.d.ts.map +1 -0
- package/dist/commands/session-path-resolver.js +302 -0
- package/dist/commands/session-path-resolver.js.map +1 -0
- package/dist/commands/session.d.ts +12 -0
- package/dist/commands/session.d.ts.map +1 -0
- package/dist/commands/session.js +954 -0
- package/dist/commands/session.js.map +1 -0
- package/dist/commands/stop.d.ts +11 -0
- package/dist/commands/stop.d.ts.map +1 -0
- package/dist/commands/stop.js +96 -0
- package/dist/commands/stop.js.map +1 -0
- package/dist/commands/tool.d.ts +29 -0
- package/dist/commands/tool.d.ts.map +1 -0
- package/dist/commands/tool.js +173 -0
- package/dist/commands/tool.js.map +1 -0
- package/dist/commands/uninstall.d.ts +9 -0
- package/dist/commands/uninstall.d.ts.map +1 -0
- package/dist/commands/uninstall.js +239 -0
- package/dist/commands/uninstall.js.map +1 -0
- package/dist/commands/upgrade.d.ts +10 -0
- package/dist/commands/upgrade.d.ts.map +1 -0
- package/dist/commands/upgrade.js +288 -0
- package/dist/commands/upgrade.js.map +1 -0
- package/dist/commands/view.d.ts +14 -0
- package/dist/commands/view.d.ts.map +1 -0
- package/dist/commands/view.js +100 -0
- package/dist/commands/view.js.map +1 -0
- package/dist/config/storage-paths.d.ts +184 -0
- package/dist/config/storage-paths.d.ts.map +1 -0
- package/dist/config/storage-paths.js +536 -0
- package/dist/config/storage-paths.js.map +1 -0
- package/dist/core/cache-manager.d.ts +80 -0
- package/dist/core/cache-manager.d.ts.map +1 -0
- package/dist/core/cache-manager.js +260 -0
- package/dist/core/cache-manager.js.map +1 -0
- package/dist/core/claude-freshness.d.ts +53 -0
- package/dist/core/claude-freshness.d.ts.map +1 -0
- package/dist/core/claude-freshness.js +232 -0
- package/dist/core/claude-freshness.js.map +1 -0
- package/dist/core/core-memory-store.d.ts +320 -0
- package/dist/core/core-memory-store.d.ts.map +1 -0
- package/dist/core/core-memory-store.js +1177 -0
- package/dist/core/core-memory-store.js.map +1 -0
- package/dist/core/dashboard-generator-patch.d.ts +2 -0
- package/dist/core/dashboard-generator-patch.d.ts.map +1 -0
- package/dist/core/dashboard-generator-patch.js +48 -0
- package/dist/core/dashboard-generator-patch.js.map +1 -0
- package/dist/core/dashboard-generator.d.ts +8 -0
- package/dist/core/dashboard-generator.d.ts.map +1 -0
- package/dist/core/dashboard-generator.js +695 -0
- package/dist/core/dashboard-generator.js.map +1 -0
- package/dist/core/data-aggregator.d.ts +145 -0
- package/dist/core/data-aggregator.d.ts.map +1 -0
- package/dist/core/data-aggregator.js +416 -0
- package/dist/core/data-aggregator.js.map +1 -0
- package/dist/core/history-importer.d.ts +102 -0
- package/dist/core/history-importer.d.ts.map +1 -0
- package/dist/core/history-importer.js +493 -0
- package/dist/core/history-importer.js.map +1 -0
- package/dist/core/lite-scanner-complete.d.ts +81 -0
- package/dist/core/lite-scanner-complete.d.ts.map +1 -0
- package/dist/core/lite-scanner-complete.js +368 -0
- package/dist/core/lite-scanner-complete.js.map +1 -0
- package/dist/core/lite-scanner.d.ts +81 -0
- package/dist/core/lite-scanner.d.ts.map +1 -0
- package/dist/core/lite-scanner.js +368 -0
- package/dist/core/lite-scanner.js.map +1 -0
- package/dist/core/manifest.d.ts +88 -0
- package/dist/core/manifest.d.ts.map +1 -0
- package/dist/core/manifest.js +214 -0
- package/dist/core/manifest.js.map +1 -0
- package/dist/core/memory-embedder-bridge.d.ts +83 -0
- package/dist/core/memory-embedder-bridge.d.ts.map +1 -0
- package/dist/core/memory-embedder-bridge.js +181 -0
- package/dist/core/memory-embedder-bridge.js.map +1 -0
- package/dist/core/memory-store.d.ts +249 -0
- package/dist/core/memory-store.d.ts.map +1 -0
- package/dist/core/memory-store.js +781 -0
- package/dist/core/memory-store.js.map +1 -0
- package/dist/core/routes/ccw-routes.d.ts +20 -0
- package/dist/core/routes/ccw-routes.d.ts.map +1 -0
- package/dist/core/routes/ccw-routes.js +70 -0
- package/dist/core/routes/ccw-routes.js.map +1 -0
- package/dist/core/routes/claude-routes.d.ts +19 -0
- package/dist/core/routes/claude-routes.d.ts.map +1 -0
- package/dist/core/routes/claude-routes.js +1017 -0
- package/dist/core/routes/claude-routes.js.map +1 -0
- package/dist/core/routes/cli-routes.d.ts +20 -0
- package/dist/core/routes/cli-routes.d.ts.map +1 -0
- package/dist/core/routes/cli-routes.js +468 -0
- package/dist/core/routes/cli-routes.js.map +1 -0
- package/dist/core/routes/codexlens-routes.d.ts +20 -0
- package/dist/core/routes/codexlens-routes.d.ts.map +1 -0
- package/dist/core/routes/codexlens-routes.js +754 -0
- package/dist/core/routes/codexlens-routes.js.map +1 -0
- package/dist/core/routes/core-memory-routes.d.ts +21 -0
- package/dist/core/routes/core-memory-routes.d.ts.map +1 -0
- package/dist/core/routes/core-memory-routes.js +520 -0
- package/dist/core/routes/core-memory-routes.js.map +1 -0
- package/dist/core/routes/files-routes.d.ts +20 -0
- package/dist/core/routes/files-routes.d.ts.map +1 -0
- package/dist/core/routes/files-routes.js +374 -0
- package/dist/core/routes/files-routes.js.map +1 -0
- package/dist/core/routes/graph-routes.d.ts +20 -0
- package/dist/core/routes/graph-routes.d.ts.map +1 -0
- package/dist/core/routes/graph-routes.js +517 -0
- package/dist/core/routes/graph-routes.js.map +1 -0
- package/dist/core/routes/help-routes.d.ts +20 -0
- package/dist/core/routes/help-routes.d.ts.map +1 -0
- package/dist/core/routes/help-routes.js +250 -0
- package/dist/core/routes/help-routes.js.map +1 -0
- package/dist/core/routes/hooks-routes.d.ts +21 -0
- package/dist/core/routes/hooks-routes.d.ts.map +1 -0
- package/dist/core/routes/hooks-routes.js +346 -0
- package/dist/core/routes/hooks-routes.js.map +1 -0
- package/dist/core/routes/mcp-routes.d.ts +20 -0
- package/dist/core/routes/mcp-routes.d.ts.map +1 -0
- package/dist/core/routes/mcp-routes.js +1129 -0
- package/dist/core/routes/mcp-routes.js.map +1 -0
- package/dist/core/routes/mcp-templates-db.d.ts +54 -0
- package/dist/core/routes/mcp-templates-db.d.ts.map +1 -0
- package/dist/core/routes/mcp-templates-db.js +226 -0
- package/dist/core/routes/mcp-templates-db.js.map +1 -0
- package/dist/core/routes/memory-routes.d.ts +21 -0
- package/dist/core/routes/memory-routes.d.ts.map +1 -0
- package/dist/core/routes/memory-routes.js +1095 -0
- package/dist/core/routes/memory-routes.js.map +1 -0
- package/dist/core/routes/rules-routes.d.ts +20 -0
- package/dist/core/routes/rules-routes.d.ts.map +1 -0
- package/dist/core/routes/rules-routes.js +442 -0
- package/dist/core/routes/rules-routes.js.map +1 -0
- package/dist/core/routes/session-routes.d.ts +20 -0
- package/dist/core/routes/session-routes.d.ts.map +1 -0
- package/dist/core/routes/session-routes.js +423 -0
- package/dist/core/routes/session-routes.js.map +1 -0
- package/dist/core/routes/skills-routes.d.ts +20 -0
- package/dist/core/routes/skills-routes.d.ts.map +1 -0
- package/dist/core/routes/skills-routes.js +533 -0
- package/dist/core/routes/skills-routes.js.map +1 -0
- package/dist/core/routes/status-routes.d.ts +20 -0
- package/dist/core/routes/status-routes.d.ts.map +1 -0
- package/dist/core/routes/status-routes.js +38 -0
- package/dist/core/routes/status-routes.js.map +1 -0
- package/dist/core/routes/system-routes.d.ts +22 -0
- package/dist/core/routes/system-routes.d.ts.map +1 -0
- package/dist/core/routes/system-routes.js +354 -0
- package/dist/core/routes/system-routes.js.map +1 -0
- package/dist/core/server.d.ts +17 -0
- package/dist/core/server.d.ts.map +1 -0
- package/dist/core/server.js +386 -0
- package/dist/core/server.js.map +1 -0
- package/dist/core/session-clustering-service.d.ts +153 -0
- package/dist/core/session-clustering-service.d.ts.map +1 -0
- package/dist/core/session-clustering-service.js +1065 -0
- package/dist/core/session-clustering-service.js.map +1 -0
- package/dist/core/session-scanner.d.ts +32 -0
- package/dist/core/session-scanner.d.ts.map +1 -0
- package/dist/core/session-scanner.js +253 -0
- package/dist/core/session-scanner.js.map +1 -0
- package/dist/core/websocket.d.ts +23 -0
- package/dist/core/websocket.d.ts.map +1 -0
- package/dist/core/websocket.js +168 -0
- package/dist/core/websocket.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-server/index.d.ts +7 -0
- package/dist/mcp-server/index.d.ts.map +1 -0
- package/dist/mcp-server/index.js +157 -0
- package/dist/mcp-server/index.js.map +1 -0
- package/dist/tools/classify-folders.d.ts +26 -0
- package/dist/tools/classify-folders.d.ts.map +1 -0
- package/dist/tools/classify-folders.js +201 -0
- package/dist/tools/classify-folders.js.map +1 -0
- package/dist/tools/cli-config-manager.d.ts +62 -0
- package/dist/tools/cli-config-manager.d.ts.map +1 -0
- package/dist/tools/cli-config-manager.js +221 -0
- package/dist/tools/cli-config-manager.js.map +1 -0
- package/dist/tools/cli-executor.d.ts +373 -0
- package/dist/tools/cli-executor.d.ts.map +1 -0
- package/dist/tools/cli-executor.js +1625 -0
- package/dist/tools/cli-executor.js.map +1 -0
- package/dist/tools/cli-history-store.d.ts +330 -0
- package/dist/tools/cli-history-store.d.ts.map +1 -0
- package/dist/tools/cli-history-store.js +916 -0
- package/dist/tools/cli-history-store.js.map +1 -0
- package/dist/tools/codex-lens.d.ts +118 -0
- package/dist/tools/codex-lens.d.ts.map +1 -0
- package/dist/tools/codex-lens.js +962 -0
- package/dist/tools/codex-lens.js.map +1 -0
- package/dist/tools/convert-tokens-to-css.d.ts +14 -0
- package/dist/tools/convert-tokens-to-css.d.ts.map +1 -0
- package/dist/tools/convert-tokens-to-css.js +244 -0
- package/dist/tools/convert-tokens-to-css.js.map +1 -0
- package/dist/tools/core-memory.d.ts +66 -0
- package/dist/tools/core-memory.d.ts.map +1 -0
- package/dist/tools/core-memory.js +324 -0
- package/dist/tools/core-memory.js.map +1 -0
- package/dist/tools/detect-changed-modules.d.ts +24 -0
- package/dist/tools/detect-changed-modules.d.ts.map +1 -0
- package/dist/tools/detect-changed-modules.js +277 -0
- package/dist/tools/detect-changed-modules.js.map +1 -0
- package/dist/tools/discover-design-files.d.ts +36 -0
- package/dist/tools/discover-design-files.d.ts.map +1 -0
- package/dist/tools/discover-design-files.js +147 -0
- package/dist/tools/discover-design-files.js.map +1 -0
- package/dist/tools/edit-file.d.ts +28 -0
- package/dist/tools/edit-file.d.ts.map +1 -0
- package/dist/tools/edit-file.js +479 -0
- package/dist/tools/edit-file.js.map +1 -0
- package/dist/tools/generate-module-docs.d.ts +22 -0
- package/dist/tools/generate-module-docs.d.ts.map +1 -0
- package/dist/tools/generate-module-docs.js +379 -0
- package/dist/tools/generate-module-docs.js.map +1 -0
- package/dist/tools/get-modules-by-depth.d.ts +15 -0
- package/dist/tools/get-modules-by-depth.d.ts.map +1 -0
- package/dist/tools/get-modules-by-depth.js +296 -0
- package/dist/tools/get-modules-by-depth.js.map +1 -0
- package/dist/tools/index.d.ts +55 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +304 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/native-session-discovery.d.ts +97 -0
- package/dist/tools/native-session-discovery.d.ts.map +1 -0
- package/dist/tools/native-session-discovery.js +700 -0
- package/dist/tools/native-session-discovery.js.map +1 -0
- package/dist/tools/notifier.d.ts +50 -0
- package/dist/tools/notifier.d.ts.map +1 -0
- package/dist/tools/notifier.js +90 -0
- package/dist/tools/notifier.js.map +1 -0
- package/dist/tools/read-file.d.ts +32 -0
- package/dist/tools/read-file.d.ts.map +1 -0
- package/dist/tools/read-file.js +329 -0
- package/dist/tools/read-file.js.map +1 -0
- package/dist/tools/resume-strategy.d.ts +48 -0
- package/dist/tools/resume-strategy.d.ts.map +1 -0
- package/dist/tools/resume-strategy.js +248 -0
- package/dist/tools/resume-strategy.js.map +1 -0
- package/dist/tools/session-content-parser.d.ts +58 -0
- package/dist/tools/session-content-parser.d.ts.map +1 -0
- package/dist/tools/session-content-parser.js +420 -0
- package/dist/tools/session-content-parser.js.map +1 -0
- package/dist/tools/session-manager.d.ts +9 -0
- package/dist/tools/session-manager.d.ts.map +1 -0
- package/dist/tools/session-manager.js +834 -0
- package/dist/tools/session-manager.js.map +1 -0
- package/dist/tools/smart-context.d.ts +35 -0
- package/dist/tools/smart-context.d.ts.map +1 -0
- package/dist/tools/smart-context.js +182 -0
- package/dist/tools/smart-context.js.map +1 -0
- package/dist/tools/smart-search.d.ts +105 -0
- package/dist/tools/smart-search.d.ts.map +1 -0
- package/dist/tools/smart-search.js +1753 -0
- package/dist/tools/smart-search.js.map +1 -0
- package/dist/tools/storage-manager.d.ts +114 -0
- package/dist/tools/storage-manager.d.ts.map +1 -0
- package/dist/tools/storage-manager.js +392 -0
- package/dist/tools/storage-manager.js.map +1 -0
- package/dist/tools/ui-generate-preview.d.ts +39 -0
- package/dist/tools/ui-generate-preview.d.ts.map +1 -0
- package/dist/tools/ui-generate-preview.js +300 -0
- package/dist/tools/ui-generate-preview.js.map +1 -0
- package/dist/tools/ui-instantiate-prototypes.d.ts +75 -0
- package/dist/tools/ui-instantiate-prototypes.d.ts.map +1 -0
- package/dist/tools/ui-instantiate-prototypes.js +256 -0
- package/dist/tools/ui-instantiate-prototypes.js.map +1 -0
- package/dist/tools/update-module-claude.d.ts +80 -0
- package/dist/tools/update-module-claude.d.ts.map +1 -0
- package/dist/tools/update-module-claude.js +351 -0
- package/dist/tools/update-module-claude.js.map +1 -0
- package/dist/tools/write-file.d.ts +19 -0
- package/dist/tools/write-file.d.ts.map +1 -0
- package/dist/tools/write-file.js +193 -0
- package/dist/tools/write-file.js.map +1 -0
- package/dist/types/config.d.ts +11 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +2 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +4 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/session.d.ts +20 -0
- package/dist/types/session.d.ts.map +1 -0
- package/dist/types/session.js +2 -0
- package/dist/types/session.js.map +1 -0
- package/dist/types/tool.d.ts +36 -0
- package/dist/types/tool.d.ts.map +1 -0
- package/dist/types/tool.js +11 -0
- package/dist/types/tool.js.map +1 -0
- package/dist/utils/browser-launcher.d.ts +13 -0
- package/dist/utils/browser-launcher.d.ts.map +1 -0
- package/dist/utils/browser-launcher.js +60 -0
- package/dist/utils/browser-launcher.js.map +1 -0
- package/dist/utils/file-utils.d.ts +25 -0
- package/dist/utils/file-utils.d.ts.map +1 -0
- package/dist/utils/file-utils.js +48 -0
- package/dist/utils/file-utils.js.map +1 -0
- package/dist/utils/path-resolver.d.ts +80 -0
- package/dist/utils/path-resolver.d.ts.map +1 -0
- package/dist/utils/path-resolver.js +260 -0
- package/dist/utils/path-resolver.js.map +1 -0
- package/dist/utils/path-validator.d.ts +49 -0
- package/dist/utils/path-validator.d.ts.map +1 -0
- package/dist/utils/path-validator.js +123 -0
- package/dist/utils/path-validator.js.map +1 -0
- package/dist/utils/ui.d.ts +62 -0
- package/dist/utils/ui.d.ts.map +1 -0
- package/dist/utils/ui.js +129 -0
- package/dist/utils/ui.js.map +1 -0
- package/package.json +32 -34
- package/src/.workflow/.cli-history/history.db +0 -0
- package/src/.workflow/.cli-history/history.db-shm +0 -0
- package/src/.workflow/.cli-history/history.db-wal +0 -0
- package/src/cli.ts +244 -0
- package/src/commands/cli.ts +740 -0
- package/src/commands/core-memory.ts +770 -0
- package/src/commands/hook.ts +315 -0
- package/src/commands/install.ts +519 -0
- package/src/commands/list.ts +37 -0
- package/src/commands/memory.ts +1090 -0
- package/src/commands/serve.ts +76 -0
- package/src/commands/session-path-resolver.ts +372 -0
- package/src/commands/session.ts +1141 -0
- package/src/commands/stop.ts +111 -0
- package/src/commands/tool.ts +201 -0
- package/src/commands/uninstall.ts +287 -0
- package/src/commands/upgrade.ts +352 -0
- package/src/commands/view.ts +119 -0
- package/src/config/storage-paths.ts +670 -0
- package/src/core/cache-manager.ts +294 -0
- package/src/core/claude-freshness.ts +319 -0
- package/src/core/core-memory-store.ts +1528 -0
- package/src/core/dashboard-generator-patch.ts +47 -0
- package/src/core/dashboard-generator.ts +739 -0
- package/src/core/data-aggregator.ts +584 -0
- package/src/core/history-importer.ts +625 -0
- package/src/core/lite-scanner-complete.ts +469 -0
- package/src/core/lite-scanner.ts +469 -0
- package/src/core/manifest.ts +271 -0
- package/src/core/memory-embedder-bridge.ts +262 -0
- package/src/core/memory-store.ts +978 -0
- package/src/core/routes/ccw-routes.ts +96 -0
- package/src/core/routes/claude-routes.ts +1183 -0
- package/src/core/routes/cli-routes.ts +561 -0
- package/src/core/routes/codexlens-routes.ts +806 -0
- package/src/core/routes/core-memory-routes.ts +605 -0
- package/src/core/routes/files-routes.ts +428 -0
- package/src/core/routes/graph-routes.md +164 -0
- package/src/core/routes/graph-routes.ts +626 -0
- package/src/core/routes/help-routes.ts +308 -0
- package/src/core/routes/hooks-routes.ts +405 -0
- package/src/core/routes/mcp-routes.ts +1271 -0
- package/src/core/routes/mcp-routes.ts.backup +550 -0
- package/src/core/routes/mcp-templates-db.ts +268 -0
- package/src/core/routes/memory-routes.ts +1206 -0
- package/src/core/routes/rules-routes.ts +526 -0
- package/src/core/routes/session-routes.ts +467 -0
- package/src/core/routes/skills-routes.ts +599 -0
- package/src/core/routes/status-routes.ts +57 -0
- package/src/core/routes/system-routes.ts +427 -0
- package/src/core/server.ts +431 -0
- package/src/core/session-clustering-service.ts +1258 -0
- package/src/core/session-scanner.ts +283 -0
- package/src/core/websocket.ts +190 -0
- package/src/index.ts +10 -0
- package/src/mcp-server/index.ts +186 -0
- package/src/templates/assets/css/github-dark.min.css +10 -0
- package/src/templates/assets/css/github.min.css +10 -0
- package/src/templates/assets/js/cytoscape.min.js +32 -0
- package/src/templates/assets/js/d3.min.js +2 -0
- package/src/templates/assets/js/highlight.min.js +1244 -0
- package/src/templates/assets/js/lucide.min.js +12 -0
- package/src/templates/assets/js/marked.min.js +69 -0
- package/src/templates/assets/js/tailwind.js +83 -0
- package/src/templates/dashboard-css/01-base.css +302 -0
- package/src/templates/dashboard-css/02-session.css +748 -0
- package/src/templates/dashboard-css/04-lite-tasks.css +1181 -0
- package/src/templates/dashboard-css/06-cards.css +1576 -0
- package/src/templates/dashboard-css/07-managers.css +2107 -0
- package/src/templates/dashboard-css/09-explorer.css +1408 -0
- package/src/templates/dashboard-css/10-cli-status.css +337 -0
- package/src/templates/dashboard-css/11-cli-history.css +271 -0
- package/src/templates/dashboard-css/12-cli-legacy.css +796 -0
- package/src/templates/dashboard-css/13-cli-ccw.css +199 -0
- package/src/templates/dashboard-css/14-cli-modals.css +258 -0
- package/src/templates/dashboard-css/15-cli-endpoints.css +305 -0
- package/src/templates/dashboard-css/16-cli-session.css +241 -0
- package/src/templates/dashboard-css/17-cli-conversation.css +283 -0
- package/src/templates/dashboard-css/18-cli-settings.css +160 -0
- package/src/templates/dashboard-css/19-cli-native-session.css +496 -0
- package/src/templates/dashboard-css/20-cli-taskqueue.css +188 -0
- package/src/templates/dashboard-css/21-cli-toolmgmt.css +310 -0
- package/src/templates/dashboard-css/22-cli-semantic.css +240 -0
- package/src/templates/dashboard-css/23-memory.css +2390 -0
- package/src/templates/dashboard-css/24-prompt-history.css +1089 -0
- package/src/templates/dashboard-css/25-skills-rules.css +326 -0
- package/src/templates/dashboard-css/26-claude-manager.css +908 -0
- package/src/templates/dashboard-css/27-graph-explorer.css +1678 -0
- package/src/templates/dashboard-css/28-mcp-manager.css +748 -0
- package/src/templates/dashboard-css/29-help.css +264 -0
- package/src/templates/dashboard-css/30-core-memory.css +1700 -0
- package/src/templates/dashboard-js/api.js +220 -0
- package/src/templates/dashboard-js/components/carousel.js +398 -0
- package/src/templates/dashboard-js/components/cli-history.js +876 -0
- package/src/templates/dashboard-js/components/cli-status.js +978 -0
- package/src/templates/dashboard-js/components/global-notifications.js +508 -0
- package/src/templates/dashboard-js/components/hook-manager.js +1278 -0
- package/src/templates/dashboard-js/components/index-manager.js +302 -0
- package/src/templates/dashboard-js/components/mcp-manager.js +1219 -0
- package/src/templates/dashboard-js/components/modals.js +326 -0
- package/src/templates/dashboard-js/components/navigation.js +313 -0
- package/src/templates/dashboard-js/components/notifications.js +758 -0
- package/src/templates/dashboard-js/components/storage-manager.js +478 -0
- package/src/templates/dashboard-js/components/tabs-other.js +424 -0
- package/src/templates/dashboard-js/components/task-queue-sidebar.js +716 -0
- package/src/templates/dashboard-js/help-i18n.js +272 -0
- package/src/templates/dashboard-js/i18n.js +2807 -0
- package/src/templates/dashboard-js/main.js +87 -0
- package/src/templates/dashboard-js/state.js +243 -0
- package/src/templates/dashboard-js/utils.js +199 -0
- package/src/templates/dashboard-js/views/claude-manager.js +912 -0
- package/src/templates/dashboard-js/views/cli-manager.js +2272 -0
- package/src/templates/dashboard-js/views/codexlens-manager.js +964 -0
- package/src/templates/dashboard-js/views/core-memory-clusters.js +503 -0
- package/src/templates/dashboard-js/views/core-memory.js +782 -0
- package/src/templates/dashboard-js/views/explorer.js +888 -0
- package/src/templates/dashboard-js/views/graph-explorer.js +1157 -0
- package/src/templates/dashboard-js/views/help.js +856 -0
- package/src/templates/dashboard-js/views/history.js +337 -0
- package/src/templates/dashboard-js/views/home.js +243 -0
- package/src/templates/dashboard-js/views/hook-manager.js +660 -0
- package/src/templates/dashboard-js/views/lite-tasks.js +861 -0
- package/src/templates/dashboard-js/views/mcp-manager.js +2187 -0
- package/src/templates/dashboard-js/views/mcp-manager.js.backup +1729 -0
- package/src/templates/dashboard-js/views/mcp-manager.js.new +928 -0
- package/src/templates/dashboard-js/views/memory.js +1221 -0
- package/src/templates/dashboard-js/views/prompt-history.js +713 -0
- package/src/templates/dashboard-js/views/rules-manager.js +828 -0
- package/src/templates/dashboard-js/views/session-detail.js +781 -0
- package/src/templates/dashboard-js/views/skills-manager.js +819 -0
- package/src/templates/dashboard.html +831 -0
- package/src/templates/hooks-config-example.json +60 -0
- package/src/tools/classify-folders.ts +245 -0
- package/src/tools/cli-config-manager.ts +268 -0
- package/src/tools/cli-executor.ts +2014 -0
- package/src/tools/cli-history-store.ts +1195 -0
- package/src/tools/codex-lens.ts +1141 -0
- package/src/tools/convert-tokens-to-css.ts +300 -0
- package/src/tools/core-memory.ts +444 -0
- package/src/tools/detect-changed-modules.ts +325 -0
- package/src/tools/discover-design-files.ts +184 -0
- package/src/tools/edit-file.ts +568 -0
- package/src/tools/generate-module-docs.ts +438 -0
- package/src/tools/get-modules-by-depth.ts +349 -0
- package/src/tools/index.ts +370 -0
- package/src/tools/native-session-discovery.ts +795 -0
- package/src/tools/notifier.ts +129 -0
- package/src/tools/read-file.ts +410 -0
- package/src/tools/resume-strategy.ts +345 -0
- package/src/tools/session-content-parser.ts +619 -0
- package/src/tools/session-manager.ts +1026 -0
- package/src/tools/smart-context.ts +228 -0
- package/src/tools/smart-search.ts +2065 -0
- package/src/tools/smart-search.ts.backup +1233 -0
- package/src/tools/storage-manager.ts +455 -0
- package/src/tools/write-file.ts +222 -0
- package/src/types/config.ts +11 -0
- package/src/types/index.ts +3 -0
- package/src/types/session.ts +25 -0
- package/src/types/tool.ts +41 -0
- package/src/utils/browser-launcher.ts +62 -0
- package/src/utils/file-utils.ts +48 -0
- package/src/utils/path-resolver.ts +315 -0
- package/src/utils/path-validator.ts +153 -0
- package/src/utils/ui.ts +155 -0
- package/.claude/agents/action-planning-agent.md +0 -778
- package/.claude/agents/cli-execution-agent.md +0 -270
- package/.claude/agents/cli-explore-agent.md +0 -182
- package/.claude/agents/cli-lite-planning-agent.md +0 -396
- package/.claude/agents/cli-planning-agent.md +0 -558
- package/.claude/agents/code-developer.md +0 -310
- package/.claude/agents/conceptual-planning-agent.md +0 -308
- package/.claude/agents/context-search-agent.md +0 -582
- package/.claude/agents/doc-generator.md +0 -330
- package/.claude/agents/memory-bridge.md +0 -94
- package/.claude/agents/test-context-search-agent.md +0 -399
- package/.claude/agents/test-fix-agent.md +0 -343
- package/.claude/agents/ui-design-agent.md +0 -593
- package/.claude/agents/universal-executor.md +0 -131
- package/.claude/commands/cli/cli-init.md +0 -440
- package/.claude/commands/enhance-prompt.md +0 -93
- package/.claude/commands/memory/code-map-memory.md +0 -687
- package/.claude/commands/memory/docs-full-cli.md +0 -471
- package/.claude/commands/memory/docs-related-cli.md +0 -386
- package/.claude/commands/memory/docs.md +0 -615
- package/.claude/commands/memory/load-skill-memory.md +0 -182
- package/.claude/commands/memory/load.md +0 -240
- package/.claude/commands/memory/skill-memory.md +0 -525
- package/.claude/commands/memory/style-skill-memory.md +0 -396
- package/.claude/commands/memory/tech-research.md +0 -477
- package/.claude/commands/memory/update-full.md +0 -332
- package/.claude/commands/memory/update-related.md +0 -332
- package/.claude/commands/memory/workflow-skill-memory.md +0 -517
- package/.claude/commands/task/breakdown.md +0 -204
- package/.claude/commands/task/create.md +0 -152
- package/.claude/commands/task/execute.md +0 -270
- package/.claude/commands/task/replan.md +0 -437
- package/.claude/commands/version.md +0 -254
- package/.claude/commands/workflow/action-plan-verify.md +0 -447
- package/.claude/commands/workflow/brainstorm/api-designer.md +0 -585
- package/.claude/commands/workflow/brainstorm/artifacts.md +0 -452
- package/.claude/commands/workflow/brainstorm/auto-parallel.md +0 -443
- package/.claude/commands/workflow/brainstorm/data-architect.md +0 -220
- package/.claude/commands/workflow/brainstorm/product-manager.md +0 -200
- package/.claude/commands/workflow/brainstorm/product-owner.md +0 -200
- package/.claude/commands/workflow/brainstorm/scrum-master.md +0 -200
- package/.claude/commands/workflow/brainstorm/subject-matter-expert.md +0 -200
- package/.claude/commands/workflow/brainstorm/synthesis.md +0 -398
- package/.claude/commands/workflow/brainstorm/system-architect.md +0 -387
- package/.claude/commands/workflow/brainstorm/ui-designer.md +0 -221
- package/.claude/commands/workflow/brainstorm/ux-expert.md +0 -221
- package/.claude/commands/workflow/execute.md +0 -462
- package/.claude/commands/workflow/init.md +0 -164
- package/.claude/commands/workflow/lite-execute.md +0 -686
- package/.claude/commands/workflow/lite-fix.md +0 -621
- package/.claude/commands/workflow/lite-plan.md +0 -592
- package/.claude/commands/workflow/plan.md +0 -551
- package/.claude/commands/workflow/replan.md +0 -515
- package/.claude/commands/workflow/review-fix.md +0 -606
- package/.claude/commands/workflow/review-module-cycle.md +0 -765
- package/.claude/commands/workflow/review-session-cycle.md +0 -776
- package/.claude/commands/workflow/review.md +0 -291
- package/.claude/commands/workflow/session/complete.md +0 -500
- package/.claude/commands/workflow/session/list.md +0 -96
- package/.claude/commands/workflow/session/resume.md +0 -61
- package/.claude/commands/workflow/session/start.md +0 -200
- package/.claude/commands/workflow/tdd-plan.md +0 -460
- package/.claude/commands/workflow/tdd-verify.md +0 -386
- package/.claude/commands/workflow/test-cycle-execute.md +0 -498
- package/.claude/commands/workflow/test-fix-gen.md +0 -699
- package/.claude/commands/workflow/test-gen.md +0 -529
- package/.claude/commands/workflow/tools/conflict-resolution.md +0 -680
- package/.claude/commands/workflow/tools/context-gather.md +0 -434
- package/.claude/commands/workflow/tools/task-generate-agent.md +0 -291
- package/.claude/commands/workflow/tools/task-generate-tdd.md +0 -518
- package/.claude/commands/workflow/tools/tdd-coverage-analysis.md +0 -309
- package/.claude/commands/workflow/tools/test-concept-enhanced.md +0 -163
- package/.claude/commands/workflow/tools/test-context-gather.md +0 -235
- package/.claude/commands/workflow/tools/test-task-generate.md +0 -256
- package/.claude/commands/workflow/ui-design/animation-extract.md +0 -1150
- package/.claude/commands/workflow/ui-design/codify-style.md +0 -652
- package/.claude/commands/workflow/ui-design/design-sync.md +0 -454
- package/.claude/commands/workflow/ui-design/explore-auto.md +0 -678
- package/.claude/commands/workflow/ui-design/generate.md +0 -504
- package/.claude/commands/workflow/ui-design/imitate-auto.md +0 -745
- package/.claude/commands/workflow/ui-design/import-from-code.md +0 -537
- package/.claude/commands/workflow/ui-design/layout-extract.md +0 -788
- package/.claude/commands/workflow/ui-design/reference-page-generator.md +0 -356
- package/.claude/commands/workflow/ui-design/style-extract.md +0 -773
- package/.claude/scripts/classify-folders.sh +0 -39
- package/.claude/scripts/convert_tokens_to_css.sh +0 -229
- package/.claude/scripts/detect_changed_modules.sh +0 -161
- package/.claude/scripts/discover-design-files.sh +0 -87
- package/.claude/scripts/extract-animations.js +0 -243
- package/.claude/scripts/extract-computed-styles.js +0 -118
- package/.claude/scripts/extract-layout-structure.js +0 -411
- package/.claude/scripts/generate_module_docs.sh +0 -717
- package/.claude/scripts/get_modules_by_depth.sh +0 -170
- package/.claude/scripts/ui-generate-preview.sh +0 -395
- package/.claude/scripts/ui-instantiate-prototypes.sh +0 -815
- package/.claude/scripts/update_module_claude.sh +0 -337
- package/.claude/skills/command-guide/SKILL.md +0 -388
- package/.claude/skills/command-guide/UPDATE-GUIDELINE.md +0 -592
- package/.claude/skills/command-guide/guides/cli-tools-guide.md +0 -410
- package/.claude/skills/command-guide/guides/examples.md +0 -537
- package/.claude/skills/command-guide/guides/getting-started.md +0 -242
- package/.claude/skills/command-guide/guides/implementation-details.md +0 -1010
- package/.claude/skills/command-guide/guides/index-structure.md +0 -326
- package/.claude/skills/command-guide/guides/troubleshooting.md +0 -92
- package/.claude/skills/command-guide/guides/ui-design-workflow-guide.md +0 -316
- package/.claude/skills/command-guide/guides/workflow-patterns.md +0 -662
- package/.claude/skills/command-guide/index/all-commands.json +0 -772
- package/.claude/skills/command-guide/index/by-category.json +0 -800
- package/.claude/skills/command-guide/index/by-use-case.json +0 -786
- package/.claude/skills/command-guide/index/command-relationships.json +0 -307
- package/.claude/skills/command-guide/index/essential-commands.json +0 -112
- package/.claude/skills/command-guide/reference/agents/action-planning-agent.md +0 -778
- package/.claude/skills/command-guide/reference/agents/cli-execution-agent.md +0 -270
- package/.claude/skills/command-guide/reference/agents/cli-explore-agent.md +0 -182
- package/.claude/skills/command-guide/reference/agents/cli-lite-planning-agent.md +0 -396
- package/.claude/skills/command-guide/reference/agents/cli-planning-agent.md +0 -558
- package/.claude/skills/command-guide/reference/agents/code-developer.md +0 -310
- package/.claude/skills/command-guide/reference/agents/conceptual-planning-agent.md +0 -308
- package/.claude/skills/command-guide/reference/agents/context-search-agent.md +0 -582
- package/.claude/skills/command-guide/reference/agents/doc-generator.md +0 -330
- package/.claude/skills/command-guide/reference/agents/memory-bridge.md +0 -94
- package/.claude/skills/command-guide/reference/agents/test-context-search-agent.md +0 -399
- package/.claude/skills/command-guide/reference/agents/test-fix-agent.md +0 -343
- package/.claude/skills/command-guide/reference/agents/ui-design-agent.md +0 -593
- package/.claude/skills/command-guide/reference/agents/universal-executor.md +0 -131
- package/.claude/skills/command-guide/reference/commands/cli/cli-init.md +0 -440
- package/.claude/skills/command-guide/reference/commands/enhance-prompt.md +0 -93
- package/.claude/skills/command-guide/reference/commands/memory/code-map-memory.md +0 -687
- package/.claude/skills/command-guide/reference/commands/memory/docs-full-cli.md +0 -471
- package/.claude/skills/command-guide/reference/commands/memory/docs-related-cli.md +0 -386
- package/.claude/skills/command-guide/reference/commands/memory/docs.md +0 -615
- package/.claude/skills/command-guide/reference/commands/memory/load-skill-memory.md +0 -182
- package/.claude/skills/command-guide/reference/commands/memory/load.md +0 -240
- package/.claude/skills/command-guide/reference/commands/memory/skill-memory.md +0 -525
- package/.claude/skills/command-guide/reference/commands/memory/style-skill-memory.md +0 -396
- package/.claude/skills/command-guide/reference/commands/memory/tech-research.md +0 -477
- package/.claude/skills/command-guide/reference/commands/memory/update-full.md +0 -332
- package/.claude/skills/command-guide/reference/commands/memory/update-related.md +0 -332
- package/.claude/skills/command-guide/reference/commands/memory/workflow-skill-memory.md +0 -517
- package/.claude/skills/command-guide/reference/commands/task/breakdown.md +0 -204
- package/.claude/skills/command-guide/reference/commands/task/create.md +0 -152
- package/.claude/skills/command-guide/reference/commands/task/execute.md +0 -270
- package/.claude/skills/command-guide/reference/commands/task/replan.md +0 -437
- package/.claude/skills/command-guide/reference/commands/version.md +0 -254
- package/.claude/skills/command-guide/reference/commands/workflow/action-plan-verify.md +0 -447
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/api-designer.md +0 -585
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/artifacts.md +0 -452
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/auto-parallel.md +0 -443
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/data-architect.md +0 -220
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/product-manager.md +0 -200
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/product-owner.md +0 -200
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/scrum-master.md +0 -200
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/subject-matter-expert.md +0 -200
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/synthesis.md +0 -398
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/system-architect.md +0 -387
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/ui-designer.md +0 -221
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/ux-expert.md +0 -221
- package/.claude/skills/command-guide/reference/commands/workflow/execute.md +0 -460
- package/.claude/skills/command-guide/reference/commands/workflow/init.md +0 -164
- package/.claude/skills/command-guide/reference/commands/workflow/lite-execute.md +0 -686
- package/.claude/skills/command-guide/reference/commands/workflow/lite-fix.md +0 -621
- package/.claude/skills/command-guide/reference/commands/workflow/lite-plan.md +0 -592
- package/.claude/skills/command-guide/reference/commands/workflow/plan.md +0 -551
- package/.claude/skills/command-guide/reference/commands/workflow/replan.md +0 -515
- package/.claude/skills/command-guide/reference/commands/workflow/review-fix.md +0 -606
- package/.claude/skills/command-guide/reference/commands/workflow/review-module-cycle.md +0 -765
- package/.claude/skills/command-guide/reference/commands/workflow/review-session-cycle.md +0 -776
- package/.claude/skills/command-guide/reference/commands/workflow/review.md +0 -291
- package/.claude/skills/command-guide/reference/commands/workflow/session/complete.md +0 -500
- package/.claude/skills/command-guide/reference/commands/workflow/session/list.md +0 -96
- package/.claude/skills/command-guide/reference/commands/workflow/session/resume.md +0 -61
- package/.claude/skills/command-guide/reference/commands/workflow/session/start.md +0 -200
- package/.claude/skills/command-guide/reference/commands/workflow/tdd-plan.md +0 -460
- package/.claude/skills/command-guide/reference/commands/workflow/tdd-verify.md +0 -386
- package/.claude/skills/command-guide/reference/commands/workflow/test-cycle-execute.md +0 -498
- package/.claude/skills/command-guide/reference/commands/workflow/test-fix-gen.md +0 -699
- package/.claude/skills/command-guide/reference/commands/workflow/test-gen.md +0 -529
- package/.claude/skills/command-guide/reference/commands/workflow/tools/conflict-resolution.md +0 -680
- package/.claude/skills/command-guide/reference/commands/workflow/tools/context-gather.md +0 -434
- package/.claude/skills/command-guide/reference/commands/workflow/tools/task-generate-agent.md +0 -291
- package/.claude/skills/command-guide/reference/commands/workflow/tools/task-generate-tdd.md +0 -518
- package/.claude/skills/command-guide/reference/commands/workflow/tools/tdd-coverage-analysis.md +0 -309
- package/.claude/skills/command-guide/reference/commands/workflow/tools/test-concept-enhanced.md +0 -163
- package/.claude/skills/command-guide/reference/commands/workflow/tools/test-context-gather.md +0 -235
- package/.claude/skills/command-guide/reference/commands/workflow/tools/test-task-generate.md +0 -256
- package/.claude/skills/command-guide/reference/commands/workflow/ui-design/animation-extract.md +0 -1150
- package/.claude/skills/command-guide/reference/commands/workflow/ui-design/codify-style.md +0 -652
- package/.claude/skills/command-guide/reference/commands/workflow/ui-design/design-sync.md +0 -454
- package/.claude/skills/command-guide/reference/commands/workflow/ui-design/explore-auto.md +0 -678
- package/.claude/skills/command-guide/reference/commands/workflow/ui-design/generate.md +0 -504
- package/.claude/skills/command-guide/reference/commands/workflow/ui-design/imitate-auto.md +0 -745
- package/.claude/skills/command-guide/reference/commands/workflow/ui-design/import-from-code.md +0 -537
- package/.claude/skills/command-guide/reference/commands/workflow/ui-design/layout-extract.md +0 -788
- package/.claude/skills/command-guide/reference/commands/workflow/ui-design/reference-page-generator.md +0 -356
- package/.claude/skills/command-guide/reference/commands/workflow/ui-design/style-extract.md +0 -773
- package/.claude/skills/command-guide/scripts/analyze_commands.py +0 -502
- package/.claude/skills/command-guide/scripts/update-index.sh +0 -130
- package/.claude/skills/command-guide/templates/issue-bug.md +0 -104
- package/.claude/skills/command-guide/templates/issue-diagnosis.md +0 -275
- package/.claude/skills/command-guide/templates/issue-feature.md +0 -97
- package/.claude/skills/command-guide/templates/issue-question.md +0 -141
- package/.claude/skills/prompt-enhancer/SKILL.md +0 -124
- package/.claude/workflows/_template-compare-matrix.html +0 -692
- package/.claude/workflows/cli-templates/fix-plan-template.json +0 -75
- package/.claude/workflows/cli-templates/fix-progress-template.json +0 -48
- package/.claude/workflows/cli-templates/memory/style-skill-memory/skill-md-template.md +0 -299
- package/.claude/workflows/cli-templates/planning-roles/data-architect.md +0 -120
- package/.claude/workflows/cli-templates/planning-roles/product-manager.md +0 -119
- package/.claude/workflows/cli-templates/planning-roles/product-owner.md +0 -261
- package/.claude/workflows/cli-templates/planning-roles/scrum-master.md +0 -186
- package/.claude/workflows/cli-templates/planning-roles/subject-matter-expert.md +0 -281
- package/.claude/workflows/cli-templates/planning-roles/synthesis-role.md +0 -414
- package/.claude/workflows/cli-templates/planning-roles/system-architect.md +0 -106
- package/.claude/workflows/cli-templates/planning-roles/test-strategist.md +0 -124
- package/.claude/workflows/cli-templates/planning-roles/ui-designer.md +0 -379
- package/.claude/workflows/cli-templates/planning-roles/ux-expert.md +0 -240
- package/.claude/workflows/cli-templates/prompts/analysis/01-diagnose-bug-root-cause.txt +0 -127
- package/.claude/workflows/cli-templates/prompts/analysis/01-trace-code-execution.txt +0 -115
- package/.claude/workflows/cli-templates/prompts/analysis/02-analyze-code-patterns.txt +0 -37
- package/.claude/workflows/cli-templates/prompts/analysis/02-analyze-technical-document.txt +0 -33
- package/.claude/workflows/cli-templates/prompts/analysis/02-review-architecture.txt +0 -29
- package/.claude/workflows/cli-templates/prompts/analysis/02-review-code-quality.txt +0 -28
- package/.claude/workflows/cli-templates/prompts/analysis/03-analyze-performance.txt +0 -29
- package/.claude/workflows/cli-templates/prompts/analysis/03-assess-security-risks.txt +0 -29
- package/.claude/workflows/cli-templates/prompts/analysis/03-review-quality-standards.txt +0 -29
- package/.claude/workflows/cli-templates/prompts/development/02-generate-tests.txt +0 -70
- package/.claude/workflows/cli-templates/prompts/development/02-implement-component-ui.txt +0 -55
- package/.claude/workflows/cli-templates/prompts/development/02-implement-feature.txt +0 -58
- package/.claude/workflows/cli-templates/prompts/development/02-refactor-codebase.txt +0 -55
- package/.claude/workflows/cli-templates/prompts/development/03-debug-runtime-issues.txt +0 -55
- package/.claude/workflows/cli-templates/prompts/documentation/api.txt +0 -15
- package/.claude/workflows/cli-templates/prompts/documentation/folder-navigation.txt +0 -27
- package/.claude/workflows/cli-templates/prompts/documentation/module-readme.txt +0 -49
- package/.claude/workflows/cli-templates/prompts/documentation/project-architecture.txt +0 -41
- package/.claude/workflows/cli-templates/prompts/documentation/project-examples.txt +0 -35
- package/.claude/workflows/cli-templates/prompts/documentation/project-readme.txt +0 -35
- package/.claude/workflows/cli-templates/prompts/memory/02-document-module-structure.txt +0 -165
- package/.claude/workflows/cli-templates/prompts/planning/01-plan-architecture-design.txt +0 -109
- package/.claude/workflows/cli-templates/prompts/planning/02-breakdown-task-steps.txt +0 -30
- package/.claude/workflows/cli-templates/prompts/planning/02-design-component-spec.txt +0 -28
- package/.claude/workflows/cli-templates/prompts/planning/03-evaluate-concept-feasibility.txt +0 -127
- package/.claude/workflows/cli-templates/prompts/planning/03-plan-migration-strategy.txt +0 -30
- package/.claude/workflows/cli-templates/prompts/tech/tech-module-format.txt +0 -359
- package/.claude/workflows/cli-templates/prompts/tech/tech-skill-index.txt +0 -185
- package/.claude/workflows/cli-templates/prompts/test/test-concept-analysis.txt +0 -179
- package/.claude/workflows/cli-templates/prompts/universal/00-universal-creative-style.txt +0 -95
- package/.claude/workflows/cli-templates/prompts/universal/00-universal-rigorous-style.txt +0 -92
- package/.claude/workflows/cli-templates/prompts/verification/codex-technical.txt +0 -28
- package/.claude/workflows/cli-templates/prompts/verification/cross-validation.txt +0 -28
- package/.claude/workflows/cli-templates/prompts/verification/gemini-strategic.txt +0 -27
- package/.claude/workflows/cli-templates/prompts/workflow/analysis-results-structure.txt +0 -224
- package/.claude/workflows/cli-templates/prompts/workflow/codex-feasibility-validation.txt +0 -176
- package/.claude/workflows/cli-templates/prompts/workflow/gemini-solution-design.txt +0 -131
- package/.claude/workflows/cli-templates/prompts/workflow/impl-plan-template.txt +0 -286
- package/.claude/workflows/cli-templates/prompts/workflow/skill-aggregation.txt +0 -172
- package/.claude/workflows/cli-templates/prompts/workflow/skill-conflict-patterns.txt +0 -98
- package/.claude/workflows/cli-templates/prompts/workflow/skill-index.txt +0 -224
- package/.claude/workflows/cli-templates/prompts/workflow/skill-lessons-learned.txt +0 -98
- package/.claude/workflows/cli-templates/prompts/workflow/skill-sessions-timeline.txt +0 -53
- package/.claude/workflows/cli-templates/prompts/workflow/task-json-agent-mode.txt +0 -123
- package/.claude/workflows/cli-templates/prompts/workflow/task-json-cli-mode.txt +0 -182
- package/.claude/workflows/cli-templates/schemas/diagnosis-json-schema.json +0 -234
- package/.claude/workflows/cli-templates/schemas/explore-json-schema.json +0 -124
- package/.claude/workflows/cli-templates/schemas/fix-plan-json-schema.json +0 -273
- package/.claude/workflows/cli-templates/schemas/plan-json-schema.json +0 -219
- package/.claude/workflows/cli-templates/schemas/project-json-schema.json +0 -221
- package/.claude/workflows/cli-templates/schemas/review-deep-dive-results-schema.json +0 -82
- package/.claude/workflows/cli-templates/schemas/review-dimension-results-schema.json +0 -51
- package/.claude/workflows/cli-templates/tech-stacks/go-dev.md +0 -91
- package/.claude/workflows/cli-templates/tech-stacks/java-dev.md +0 -107
- package/.claude/workflows/cli-templates/tech-stacks/javascript-dev.md +0 -58
- package/.claude/workflows/cli-templates/tech-stacks/python-dev.md +0 -79
- package/.claude/workflows/cli-templates/tech-stacks/react-dev.md +0 -103
- package/.claude/workflows/cli-templates/tech-stacks/typescript-dev.md +0 -83
- package/.claude/workflows/cli-templates/ui-design/systems/animation-tokens.json +0 -247
- package/.claude/workflows/cli-templates/ui-design/systems/design-tokens.json +0 -342
- package/.claude/workflows/cli-templates/ui-design/systems/layout-templates.json +0 -145
- package/.claude/workflows/context-search-strategy.md +0 -77
- package/.claude/workflows/intelligent-tools-strategy.md +0 -662
- package/.claude/workflows/review-directory-specification.md +0 -336
- package/.claude/workflows/task-core.md +0 -214
- package/.claude/workflows/tool-strategy.md +0 -79
- package/.claude/workflows/workflow-architecture.md +0 -942
- package/.codex/AGENTS.md +0 -330
- package/.gemini/GEMINI.md +0 -164
- package/.qwen/QWEN.md +0 -164
- package/CLAUDE.md +0 -91
- package/LICENSE +0 -21
- package/ccw/README.md +0 -121
- package/ccw/bin/ccw.js +0 -10
- package/ccw/package.json +0 -47
- package/ccw/src/cli.js +0 -119
- package/ccw/src/commands/install.js +0 -324
- package/ccw/src/commands/list.js +0 -37
- package/ccw/src/commands/serve.js +0 -67
- package/ccw/src/commands/stop.js +0 -101
- package/ccw/src/commands/tool.js +0 -138
- package/ccw/src/commands/uninstall.js +0 -238
- package/ccw/src/commands/upgrade.js +0 -307
- package/ccw/src/commands/view.js +0 -105
- package/ccw/src/core/dashboard-generator-patch.js +0 -29
- package/ccw/src/core/dashboard-generator.js +0 -682
- package/ccw/src/core/data-aggregator.js +0 -409
- package/ccw/src/core/lite-scanner.js +0 -373
- package/ccw/src/core/manifest.js +0 -201
- package/ccw/src/core/server.js +0 -2063
- package/ccw/src/core/session-scanner.js +0 -235
- package/ccw/src/index.js +0 -9
- package/ccw/src/templates/dashboard-css/01-base.css +0 -291
- package/ccw/src/templates/dashboard-css/02-session.css +0 -726
- package/ccw/src/templates/dashboard-css/04-lite-tasks.css +0 -1171
- package/ccw/src/templates/dashboard-css/06-cards.css +0 -1570
- package/ccw/src/templates/dashboard-css/07-managers.css +0 -936
- package/ccw/src/templates/dashboard-css/09-explorer.css +0 -1397
- package/ccw/src/templates/dashboard-js/api.js +0 -200
- package/ccw/src/templates/dashboard-js/components/carousel.js +0 -398
- package/ccw/src/templates/dashboard-js/components/global-notifications.js +0 -219
- package/ccw/src/templates/dashboard-js/components/hook-manager.js +0 -283
- package/ccw/src/templates/dashboard-js/components/mcp-manager.js +0 -528
- package/ccw/src/templates/dashboard-js/components/modals.js +0 -260
- package/ccw/src/templates/dashboard-js/components/navigation.js +0 -245
- package/ccw/src/templates/dashboard-js/components/notifications.js +0 -194
- package/ccw/src/templates/dashboard-js/components/tabs-other.js +0 -273
- package/ccw/src/templates/dashboard-js/main.js +0 -72
- package/ccw/src/templates/dashboard-js/state.js +0 -42
- package/ccw/src/templates/dashboard-js/utils.js +0 -153
- package/ccw/src/templates/dashboard-js/views/explorer.js +0 -852
- package/ccw/src/templates/dashboard-js/views/home.js +0 -197
- package/ccw/src/templates/dashboard-js/views/hook-manager.js +0 -392
- package/ccw/src/templates/dashboard-js/views/lite-tasks.js +0 -685
- package/ccw/src/templates/dashboard-js/views/mcp-manager.js +0 -411
- package/ccw/src/templates/dashboard-js/views/session-detail.js +0 -780
- package/ccw/src/templates/dashboard.html +0 -731
- package/ccw/src/tools/classify-folders.js +0 -204
- package/ccw/src/tools/convert-tokens-to-css.js +0 -250
- package/ccw/src/tools/detect-changed-modules.js +0 -288
- package/ccw/src/tools/discover-design-files.js +0 -134
- package/ccw/src/tools/edit-file.js +0 -266
- package/ccw/src/tools/generate-module-docs.js +0 -416
- package/ccw/src/tools/get-modules-by-depth.js +0 -308
- package/ccw/src/tools/index.js +0 -176
- package/ccw/src/utils/browser-launcher.js +0 -60
- package/ccw/src/utils/file-utils.js +0 -48
- package/ccw/src/utils/path-resolver.js +0 -279
- package/ccw/src/utils/ui.js +0 -148
- /package/{ccw/src → src}/templates/dashboard-css/03-tasks.css +0 -0
- /package/{ccw/src → src}/templates/dashboard-css/05-context.css +0 -0
- /package/{ccw/src → src}/templates/dashboard-css/08-review.css +0 -0
- /package/{ccw/src → src}/templates/dashboard-js/components/_conflict_tab.js +0 -0
- /package/{ccw/src → src}/templates/dashboard-js/components/_exp_helpers.js +0 -0
- /package/{ccw/src → src}/templates/dashboard-js/components/_review_tab.js +0 -0
- /package/{ccw/src → src}/templates/dashboard-js/components/flowchart.js +0 -0
- /package/{ccw/src → src}/templates/dashboard-js/components/sidebar.js +0 -0
- /package/{ccw/src → src}/templates/dashboard-js/components/tabs-context.js +0 -0
- /package/{ccw/src → src}/templates/dashboard-js/components/task-drawer-core.js +0 -0
- /package/{ccw/src → src}/templates/dashboard-js/components/task-drawer-renderers.js +0 -0
- /package/{ccw/src → src}/templates/dashboard-js/components/theme.js +0 -0
- /package/{ccw/src → src}/templates/dashboard-js/components/version-check.js +0 -0
- /package/{ccw/src → src}/templates/dashboard-js/views/fix-session.js +0 -0
- /package/{ccw/src → src}/templates/dashboard-js/views/project-overview.js +0 -0
- /package/{ccw/src → src}/templates/dashboard-js/views/review-session.js +0 -0
- /package/{ccw/src → src}/templates/review-cycle-dashboard.html +0 -0
- /package/{ccw/src → src}/templates/workflow-dashboard.html +0 -0
- /package/{ccw/src → src}/tools/ui-generate-preview.js +0 -0
- /package/{ccw/src → src}/tools/ui-instantiate-prototypes.js +0 -0
- /package/{ccw/src → src}/tools/update-module-claude.js +0 -0
|
@@ -0,0 +1,1625 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI Executor Tool - Unified execution for external CLI tools
|
|
3
|
+
* Supports Gemini, Qwen, and Codex with streaming output
|
|
4
|
+
*/
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { spawn } from 'child_process';
|
|
7
|
+
import { existsSync, readdirSync } from 'fs';
|
|
8
|
+
import { join } from 'path';
|
|
9
|
+
// Native resume support
|
|
10
|
+
import { trackNewSession, supportsNativeResume } from './native-session-discovery.js';
|
|
11
|
+
import { determineResumeStrategy, buildContextPrefix, getResumeModeDescription } from './resume-strategy.js';
|
|
12
|
+
import { isToolEnabled as isToolEnabledFromConfig, enableTool as enableToolFromConfig, disableTool as disableToolFromConfig, getPrimaryModel } from './cli-config-manager.js';
|
|
13
|
+
import { StoragePaths, ensureStorageDir } from '../config/storage-paths.js';
|
|
14
|
+
// Lazy-loaded SQLite store module
|
|
15
|
+
let sqliteStoreModule = null;
|
|
16
|
+
/**
|
|
17
|
+
* Get or initialize SQLite store (async)
|
|
18
|
+
*/
|
|
19
|
+
async function getSqliteStore(baseDir) {
|
|
20
|
+
if (!sqliteStoreModule) {
|
|
21
|
+
sqliteStoreModule = await import('./cli-history-store.js');
|
|
22
|
+
}
|
|
23
|
+
return sqliteStoreModule.getHistoryStore(baseDir);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Get SQLite store (sync - uses cached module)
|
|
27
|
+
*/
|
|
28
|
+
function getSqliteStoreSync(baseDir) {
|
|
29
|
+
if (!sqliteStoreModule) {
|
|
30
|
+
throw new Error('SQLite store not initialized. Call an async function first.');
|
|
31
|
+
}
|
|
32
|
+
return sqliteStoreModule.getHistoryStore(baseDir);
|
|
33
|
+
}
|
|
34
|
+
// Define Zod schema for validation
|
|
35
|
+
const ParamsSchema = z.object({
|
|
36
|
+
tool: z.enum(['gemini', 'qwen', 'codex']),
|
|
37
|
+
prompt: z.string().min(1, 'Prompt is required'),
|
|
38
|
+
mode: z.enum(['analysis', 'write', 'auto']).default('analysis'),
|
|
39
|
+
format: z.enum(['plain', 'yaml', 'json']).default('plain'), // Multi-turn prompt concatenation format
|
|
40
|
+
model: z.string().optional(),
|
|
41
|
+
cd: z.string().optional(),
|
|
42
|
+
includeDirs: z.string().optional(),
|
|
43
|
+
timeout: z.number().default(300000),
|
|
44
|
+
resume: z.union([z.boolean(), z.string()]).optional(), // true = last, string = single ID or comma-separated IDs
|
|
45
|
+
id: z.string().optional(), // Custom execution ID (e.g., IMPL-001-step1)
|
|
46
|
+
noNative: z.boolean().optional(), // Force prompt concatenation instead of native resume
|
|
47
|
+
category: z.enum(['user', 'internal', 'insight']).default('user'), // Execution category for tracking
|
|
48
|
+
parentExecutionId: z.string().optional(), // Parent execution ID for fork/retry scenarios
|
|
49
|
+
});
|
|
50
|
+
// Cache storage: Map<toolName, CachedToolAvailability>
|
|
51
|
+
const toolAvailabilityCache = new Map();
|
|
52
|
+
const CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes
|
|
53
|
+
/**
|
|
54
|
+
* Check if cache entry is still valid
|
|
55
|
+
*/
|
|
56
|
+
function isCacheValid(cached) {
|
|
57
|
+
return Date.now() - cached.timestamp < CACHE_TTL_MS;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Clear expired cache entries
|
|
61
|
+
*/
|
|
62
|
+
function clearExpiredCache() {
|
|
63
|
+
const now = Date.now();
|
|
64
|
+
const entriesToDelete = [];
|
|
65
|
+
toolAvailabilityCache.forEach((cached, tool) => {
|
|
66
|
+
if (now - cached.timestamp >= CACHE_TTL_MS) {
|
|
67
|
+
entriesToDelete.push(tool);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
entriesToDelete.forEach(tool => toolAvailabilityCache.delete(tool));
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Clear all cache entries (useful for testing or forced refresh)
|
|
74
|
+
*/
|
|
75
|
+
export function clearToolCache() {
|
|
76
|
+
toolAvailabilityCache.clear();
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Check if a CLI tool is available (with caching)
|
|
80
|
+
*/
|
|
81
|
+
async function checkToolAvailability(tool) {
|
|
82
|
+
// Check cache first
|
|
83
|
+
const cached = toolAvailabilityCache.get(tool);
|
|
84
|
+
if (cached && isCacheValid(cached)) {
|
|
85
|
+
return cached.result;
|
|
86
|
+
}
|
|
87
|
+
// Clear expired entries periodically
|
|
88
|
+
clearExpiredCache();
|
|
89
|
+
// Perform actual check
|
|
90
|
+
return new Promise((resolve) => {
|
|
91
|
+
const isWindows = process.platform === 'win32';
|
|
92
|
+
const command = isWindows ? 'where' : 'which';
|
|
93
|
+
// Direct spawn - where/which are system commands that don't need shell wrapper
|
|
94
|
+
const child = spawn(command, [tool], {
|
|
95
|
+
shell: false,
|
|
96
|
+
stdio: ['ignore', 'pipe', 'pipe']
|
|
97
|
+
});
|
|
98
|
+
let stdout = '';
|
|
99
|
+
child.stdout.on('data', (data) => { stdout += data.toString(); });
|
|
100
|
+
child.on('close', (code) => {
|
|
101
|
+
const result = code === 0 && stdout.trim()
|
|
102
|
+
? { available: true, path: stdout.trim().split('\n')[0] }
|
|
103
|
+
: { available: false, path: null };
|
|
104
|
+
// Only cache positive results to avoid caching transient failures
|
|
105
|
+
if (result.available) {
|
|
106
|
+
toolAvailabilityCache.set(tool, {
|
|
107
|
+
result,
|
|
108
|
+
timestamp: Date.now()
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
resolve(result);
|
|
112
|
+
});
|
|
113
|
+
child.on('error', () => {
|
|
114
|
+
// Don't cache errors - they may be transient
|
|
115
|
+
resolve({ available: false, path: null });
|
|
116
|
+
});
|
|
117
|
+
// Timeout after 5 seconds
|
|
118
|
+
setTimeout(() => {
|
|
119
|
+
child.kill();
|
|
120
|
+
// Don't cache timeouts - they may be transient
|
|
121
|
+
resolve({ available: false, path: null });
|
|
122
|
+
}, 5000);
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Build command arguments based on tool and options
|
|
127
|
+
*/
|
|
128
|
+
function buildCommand(params) {
|
|
129
|
+
const { tool, prompt, mode = 'analysis', model, dir, include, nativeResume } = params;
|
|
130
|
+
let command = tool;
|
|
131
|
+
let args = [];
|
|
132
|
+
// Default to stdin for all tools to avoid escaping issues on Windows
|
|
133
|
+
let useStdin = true;
|
|
134
|
+
switch (tool) {
|
|
135
|
+
case 'gemini':
|
|
136
|
+
// Native resume: gemini -r <uuid> or -r latest
|
|
137
|
+
if (nativeResume?.enabled) {
|
|
138
|
+
if (nativeResume.isLatest) {
|
|
139
|
+
args.push('-r', 'latest');
|
|
140
|
+
}
|
|
141
|
+
else if (nativeResume.sessionId) {
|
|
142
|
+
args.push('-r', nativeResume.sessionId);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
if (model) {
|
|
146
|
+
args.push('-m', model);
|
|
147
|
+
}
|
|
148
|
+
if (mode === 'write') {
|
|
149
|
+
args.push('--approval-mode', 'yolo');
|
|
150
|
+
}
|
|
151
|
+
if (include) {
|
|
152
|
+
args.push('--include-directories', include);
|
|
153
|
+
}
|
|
154
|
+
break;
|
|
155
|
+
case 'qwen':
|
|
156
|
+
// Native resume: qwen --continue (latest) or --resume <uuid>
|
|
157
|
+
if (nativeResume?.enabled) {
|
|
158
|
+
if (nativeResume.isLatest) {
|
|
159
|
+
args.push('--continue');
|
|
160
|
+
}
|
|
161
|
+
else if (nativeResume.sessionId) {
|
|
162
|
+
args.push('--resume', nativeResume.sessionId);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
if (model) {
|
|
166
|
+
args.push('-m', model);
|
|
167
|
+
}
|
|
168
|
+
if (mode === 'write') {
|
|
169
|
+
args.push('--approval-mode', 'yolo');
|
|
170
|
+
}
|
|
171
|
+
if (include) {
|
|
172
|
+
args.push('--include-directories', include);
|
|
173
|
+
}
|
|
174
|
+
break;
|
|
175
|
+
case 'codex':
|
|
176
|
+
// Codex supports stdin when using `-` as prompt argument
|
|
177
|
+
// Using stdin avoids Windows command line escaping issues with multi-line/special char prompts
|
|
178
|
+
useStdin = true;
|
|
179
|
+
// Native resume: codex resume <uuid> [prompt] or --last
|
|
180
|
+
if (nativeResume?.enabled) {
|
|
181
|
+
args.push('resume');
|
|
182
|
+
if (nativeResume.isLatest) {
|
|
183
|
+
args.push('--last');
|
|
184
|
+
}
|
|
185
|
+
else if (nativeResume.sessionId) {
|
|
186
|
+
args.push(nativeResume.sessionId);
|
|
187
|
+
}
|
|
188
|
+
// Codex resume still supports additional flags
|
|
189
|
+
if (dir) {
|
|
190
|
+
args.push('-C', dir);
|
|
191
|
+
}
|
|
192
|
+
// Permission configuration based on mode:
|
|
193
|
+
// - analysis: --full-auto (read-only sandbox, no prompts) - safer for read operations
|
|
194
|
+
// - write/auto: --dangerously-bypass-approvals-and-sandbox (full access for modifications)
|
|
195
|
+
if (mode === 'write' || mode === 'auto') {
|
|
196
|
+
args.push('--dangerously-bypass-approvals-and-sandbox');
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
args.push('--full-auto');
|
|
200
|
+
}
|
|
201
|
+
if (model) {
|
|
202
|
+
args.push('-m', model);
|
|
203
|
+
}
|
|
204
|
+
if (include) {
|
|
205
|
+
const dirs = include.split(',').map(d => d.trim()).filter(d => d);
|
|
206
|
+
for (const addDir of dirs) {
|
|
207
|
+
args.push('--add-dir', addDir);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
// Use `-` to indicate reading prompt from stdin
|
|
211
|
+
args.push('-');
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
// Standard exec mode
|
|
215
|
+
args.push('exec');
|
|
216
|
+
if (dir) {
|
|
217
|
+
args.push('-C', dir);
|
|
218
|
+
}
|
|
219
|
+
// Permission configuration based on mode:
|
|
220
|
+
// - analysis: --full-auto (read-only sandbox, no prompts) - safer for read operations
|
|
221
|
+
// - write/auto: --dangerously-bypass-approvals-and-sandbox (full access for modifications)
|
|
222
|
+
if (mode === 'write' || mode === 'auto') {
|
|
223
|
+
args.push('--dangerously-bypass-approvals-and-sandbox');
|
|
224
|
+
}
|
|
225
|
+
else {
|
|
226
|
+
args.push('--full-auto');
|
|
227
|
+
}
|
|
228
|
+
if (model) {
|
|
229
|
+
args.push('-m', model);
|
|
230
|
+
}
|
|
231
|
+
if (include) {
|
|
232
|
+
const dirs = include.split(',').map(d => d.trim()).filter(d => d);
|
|
233
|
+
for (const addDir of dirs) {
|
|
234
|
+
args.push('--add-dir', addDir);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
// Use `-` to indicate reading prompt from stdin (avoids Windows escaping issues)
|
|
238
|
+
args.push('-');
|
|
239
|
+
}
|
|
240
|
+
break;
|
|
241
|
+
case 'claude':
|
|
242
|
+
// Claude Code: claude -p "prompt" for non-interactive mode
|
|
243
|
+
args.push('-p'); // Print mode (non-interactive)
|
|
244
|
+
// Native resume: claude --resume <session-id> or --continue
|
|
245
|
+
if (nativeResume?.enabled) {
|
|
246
|
+
if (nativeResume.isLatest) {
|
|
247
|
+
args.push('--continue');
|
|
248
|
+
}
|
|
249
|
+
else if (nativeResume.sessionId) {
|
|
250
|
+
args.push('--resume', nativeResume.sessionId);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
if (model) {
|
|
254
|
+
args.push('--model', model);
|
|
255
|
+
}
|
|
256
|
+
// Permission modes: write/auto → bypassPermissions, analysis → default
|
|
257
|
+
if (mode === 'write' || mode === 'auto') {
|
|
258
|
+
args.push('--permission-mode', 'bypassPermissions');
|
|
259
|
+
}
|
|
260
|
+
else {
|
|
261
|
+
args.push('--permission-mode', 'default');
|
|
262
|
+
}
|
|
263
|
+
// Output format for better parsing
|
|
264
|
+
args.push('--output-format', 'text');
|
|
265
|
+
// Add directories
|
|
266
|
+
if (include) {
|
|
267
|
+
const dirs = include.split(',').map(d => d.trim()).filter(d => d);
|
|
268
|
+
for (const addDir of dirs) {
|
|
269
|
+
args.push('--add-dir', addDir);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
break;
|
|
273
|
+
default:
|
|
274
|
+
throw new Error(`Unknown CLI tool: ${tool}`);
|
|
275
|
+
}
|
|
276
|
+
return { command, args, useStdin };
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Ensure history directory exists (uses centralized storage)
|
|
280
|
+
*/
|
|
281
|
+
function ensureHistoryDir(baseDir) {
|
|
282
|
+
const paths = StoragePaths.project(baseDir);
|
|
283
|
+
ensureStorageDir(paths.cliHistory);
|
|
284
|
+
return paths.cliHistory;
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Save conversation to SQLite
|
|
288
|
+
* @param baseDir - Project base directory (NOT historyDir)
|
|
289
|
+
*/
|
|
290
|
+
async function saveConversationAsync(baseDir, conversation) {
|
|
291
|
+
const store = await getSqliteStore(baseDir);
|
|
292
|
+
store.saveConversation(conversation);
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Sync wrapper for saveConversation (uses cached SQLite module)
|
|
296
|
+
* @param baseDir - Project base directory (NOT historyDir)
|
|
297
|
+
*/
|
|
298
|
+
function saveConversation(baseDir, conversation) {
|
|
299
|
+
try {
|
|
300
|
+
const store = getSqliteStoreSync(baseDir);
|
|
301
|
+
store.saveConversation(conversation);
|
|
302
|
+
}
|
|
303
|
+
catch {
|
|
304
|
+
// If sync not available, queue for async save
|
|
305
|
+
saveConversationAsync(baseDir, conversation).catch(err => {
|
|
306
|
+
console.error('[CLI Executor] Failed to save conversation:', err.message);
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Load existing conversation by ID from SQLite
|
|
312
|
+
* @param baseDir - Project base directory (NOT historyDir)
|
|
313
|
+
*/
|
|
314
|
+
async function loadConversationAsync(baseDir, conversationId) {
|
|
315
|
+
const store = await getSqliteStore(baseDir);
|
|
316
|
+
return store.getConversation(conversationId);
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Sync wrapper for loadConversation (uses cached SQLite module)
|
|
320
|
+
* @param baseDir - Project base directory (NOT historyDir)
|
|
321
|
+
*/
|
|
322
|
+
function loadConversation(baseDir, conversationId) {
|
|
323
|
+
try {
|
|
324
|
+
const store = getSqliteStoreSync(baseDir);
|
|
325
|
+
return store.getConversation(conversationId);
|
|
326
|
+
}
|
|
327
|
+
catch {
|
|
328
|
+
// SQLite not initialized yet, return null
|
|
329
|
+
return null;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Convert legacy ExecutionRecord to ConversationRecord
|
|
334
|
+
*/
|
|
335
|
+
function convertToConversation(record) {
|
|
336
|
+
return {
|
|
337
|
+
id: record.id,
|
|
338
|
+
created_at: record.timestamp,
|
|
339
|
+
updated_at: record.timestamp,
|
|
340
|
+
tool: record.tool,
|
|
341
|
+
model: record.model,
|
|
342
|
+
mode: record.mode,
|
|
343
|
+
category: 'user', // Legacy records default to user category
|
|
344
|
+
total_duration_ms: record.duration_ms,
|
|
345
|
+
turn_count: 1,
|
|
346
|
+
latest_status: record.status,
|
|
347
|
+
turns: [{
|
|
348
|
+
turn: 1,
|
|
349
|
+
timestamp: record.timestamp,
|
|
350
|
+
prompt: record.prompt,
|
|
351
|
+
duration_ms: record.duration_ms,
|
|
352
|
+
status: record.status,
|
|
353
|
+
exit_code: record.exit_code,
|
|
354
|
+
output: record.output
|
|
355
|
+
}]
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
function mergeConversations(conversations) {
|
|
359
|
+
const mergedTurns = [];
|
|
360
|
+
// Collect all turns with source tracking
|
|
361
|
+
for (const conv of conversations) {
|
|
362
|
+
for (const turn of conv.turns) {
|
|
363
|
+
mergedTurns.push({
|
|
364
|
+
...turn,
|
|
365
|
+
source_id: conv.id
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
// Sort by timestamp
|
|
370
|
+
mergedTurns.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
|
|
371
|
+
// Re-number turns
|
|
372
|
+
mergedTurns.forEach((turn, idx) => {
|
|
373
|
+
turn.turn = idx + 1;
|
|
374
|
+
});
|
|
375
|
+
// Calculate total duration
|
|
376
|
+
const totalDuration = mergedTurns.reduce((sum, t) => sum + t.duration_ms, 0);
|
|
377
|
+
return {
|
|
378
|
+
mergedTurns,
|
|
379
|
+
sourceConversations: conversations,
|
|
380
|
+
totalDuration
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* Build prompt from merged conversations
|
|
385
|
+
*/
|
|
386
|
+
function buildMergedPrompt(mergeResult, newPrompt, format = 'plain') {
|
|
387
|
+
const concatenator = createPromptConcatenator({ format });
|
|
388
|
+
// Set metadata for merged conversations
|
|
389
|
+
concatenator.setMetadata('merged_sources', mergeResult.sourceConversations.map(c => c.id).join(', '));
|
|
390
|
+
// Add all merged turns with source tracking
|
|
391
|
+
for (const turn of mergeResult.mergedTurns) {
|
|
392
|
+
concatenator.addFromConversationTurn(turn, turn.source_id);
|
|
393
|
+
}
|
|
394
|
+
return concatenator.build(newPrompt);
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Execute CLI tool with streaming output
|
|
398
|
+
*/
|
|
399
|
+
async function executeCliTool(params, onOutput) {
|
|
400
|
+
const parsed = ParamsSchema.safeParse(params);
|
|
401
|
+
if (!parsed.success) {
|
|
402
|
+
throw new Error(`Invalid params: ${parsed.error.message}`);
|
|
403
|
+
}
|
|
404
|
+
const { tool, prompt, mode, format, model, cd, includeDirs, timeout, resume, id: customId, noNative, category, parentExecutionId } = parsed.data;
|
|
405
|
+
// Determine working directory early (needed for conversation lookup)
|
|
406
|
+
const workingDir = cd || process.cwd();
|
|
407
|
+
ensureHistoryDir(workingDir); // Ensure history directory exists
|
|
408
|
+
// Get SQLite store for native session lookup
|
|
409
|
+
const store = await getSqliteStore(workingDir);
|
|
410
|
+
// Determine conversation ID and load existing conversation
|
|
411
|
+
// Logic:
|
|
412
|
+
// - If --resume <id1,id2,...> (multiple IDs): merge conversations
|
|
413
|
+
// - With --id: create new merged conversation
|
|
414
|
+
// - Without --id: append to ALL source conversations
|
|
415
|
+
// - If --resume <id> AND --id <newId>: fork - read context from resume ID, create new conversation with newId
|
|
416
|
+
// - If --id provided (no resume): use that ID (create new or append)
|
|
417
|
+
// - If --resume <id> without --id: use resume ID (append to existing)
|
|
418
|
+
// - No params: create new with auto-generated ID
|
|
419
|
+
let conversationId;
|
|
420
|
+
let existingConversation = null;
|
|
421
|
+
let contextConversation = null; // For fork scenario
|
|
422
|
+
let mergeResult = null; // For merge scenario
|
|
423
|
+
let sourceConversations = []; // All source conversations for merge
|
|
424
|
+
// Parse resume IDs (can be comma-separated for merge)
|
|
425
|
+
const resumeIds = resume
|
|
426
|
+
? (typeof resume === 'string' ? resume.split(',').map(id => id.trim()).filter(Boolean) : [])
|
|
427
|
+
: [];
|
|
428
|
+
const isMerge = resumeIds.length > 1;
|
|
429
|
+
const resumeId = resumeIds.length === 1 ? resumeIds[0] : null;
|
|
430
|
+
if (isMerge) {
|
|
431
|
+
// Merge scenario: multiple resume IDs
|
|
432
|
+
sourceConversations = resumeIds
|
|
433
|
+
.map(id => loadConversation(workingDir, id))
|
|
434
|
+
.filter((c) => c !== null);
|
|
435
|
+
if (sourceConversations.length === 0) {
|
|
436
|
+
throw new Error('No valid conversations found for merge');
|
|
437
|
+
}
|
|
438
|
+
mergeResult = mergeConversations(sourceConversations);
|
|
439
|
+
if (customId) {
|
|
440
|
+
// Create new merged conversation with custom ID
|
|
441
|
+
conversationId = customId;
|
|
442
|
+
existingConversation = loadConversation(workingDir, customId);
|
|
443
|
+
}
|
|
444
|
+
else {
|
|
445
|
+
// Will append to ALL source conversations (handled in save logic)
|
|
446
|
+
// Use first source conversation ID as primary
|
|
447
|
+
conversationId = sourceConversations[0].id;
|
|
448
|
+
existingConversation = sourceConversations[0];
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
else if (customId && resumeId) {
|
|
452
|
+
// Fork: read context from resume ID, but create new conversation with custom ID
|
|
453
|
+
conversationId = customId;
|
|
454
|
+
contextConversation = loadConversation(workingDir, resumeId);
|
|
455
|
+
existingConversation = loadConversation(workingDir, customId);
|
|
456
|
+
}
|
|
457
|
+
else if (customId) {
|
|
458
|
+
// Use custom ID - may be new or existing
|
|
459
|
+
conversationId = customId;
|
|
460
|
+
existingConversation = loadConversation(workingDir, customId);
|
|
461
|
+
}
|
|
462
|
+
else if (resumeId) {
|
|
463
|
+
// Resume single ID without new ID - append to existing conversation
|
|
464
|
+
conversationId = resumeId;
|
|
465
|
+
existingConversation = loadConversation(workingDir, resumeId);
|
|
466
|
+
}
|
|
467
|
+
else if (resume) {
|
|
468
|
+
// resume=true: get last conversation for this tool
|
|
469
|
+
const history = getExecutionHistory(workingDir, { limit: 1, tool });
|
|
470
|
+
if (history.executions.length > 0) {
|
|
471
|
+
conversationId = history.executions[0].id;
|
|
472
|
+
existingConversation = loadConversation(workingDir, conversationId);
|
|
473
|
+
}
|
|
474
|
+
else {
|
|
475
|
+
// No previous conversation, create new
|
|
476
|
+
conversationId = `${Date.now()}-${tool}`;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
else {
|
|
480
|
+
// New conversation with auto-generated ID
|
|
481
|
+
conversationId = `${Date.now()}-${tool}`;
|
|
482
|
+
}
|
|
483
|
+
// Determine resume strategy (native vs prompt-concat vs hybrid)
|
|
484
|
+
let resumeDecision = null;
|
|
485
|
+
let nativeResumeConfig;
|
|
486
|
+
// resume=true (latest) - use native latest if supported
|
|
487
|
+
if (resume === true && !noNative && supportsNativeResume(tool)) {
|
|
488
|
+
resumeDecision = {
|
|
489
|
+
strategy: 'native',
|
|
490
|
+
isLatest: true,
|
|
491
|
+
primaryConversationId: conversationId
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
// Use strategy engine for complex scenarios
|
|
495
|
+
else if (resumeIds.length > 0 && !noNative) {
|
|
496
|
+
resumeDecision = determineResumeStrategy({
|
|
497
|
+
tool,
|
|
498
|
+
resumeIds,
|
|
499
|
+
customId,
|
|
500
|
+
forcePromptConcat: noNative,
|
|
501
|
+
getNativeSessionId: (ccwId) => store.getNativeSessionId(ccwId),
|
|
502
|
+
getConversation: (ccwId) => loadConversation(workingDir, ccwId),
|
|
503
|
+
getConversationTool: (ccwId) => {
|
|
504
|
+
const conv = loadConversation(workingDir, ccwId);
|
|
505
|
+
return conv?.tool || null;
|
|
506
|
+
}
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
// Configure native resume if strategy decided to use it
|
|
510
|
+
if (resumeDecision && (resumeDecision.strategy === 'native' || resumeDecision.strategy === 'hybrid')) {
|
|
511
|
+
nativeResumeConfig = {
|
|
512
|
+
enabled: true,
|
|
513
|
+
sessionId: resumeDecision.nativeSessionId,
|
|
514
|
+
isLatest: resumeDecision.isLatest
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
// Build final prompt with conversation context
|
|
518
|
+
// For native: minimal prompt (native tool handles context)
|
|
519
|
+
// For hybrid: context prefix from other conversations + new prompt
|
|
520
|
+
// For prompt-concat: full multi-turn prompt
|
|
521
|
+
let finalPrompt = prompt;
|
|
522
|
+
if (resumeDecision?.strategy === 'native') {
|
|
523
|
+
// Native mode: just use the new prompt, tool handles context
|
|
524
|
+
finalPrompt = prompt;
|
|
525
|
+
}
|
|
526
|
+
else if (resumeDecision?.strategy === 'hybrid' && resumeDecision.contextTurns?.length) {
|
|
527
|
+
// Hybrid mode: add context prefix from other conversations
|
|
528
|
+
const contextPrefix = buildContextPrefix(resumeDecision.contextTurns, format);
|
|
529
|
+
finalPrompt = contextPrefix + prompt;
|
|
530
|
+
}
|
|
531
|
+
else if (mergeResult && mergeResult.mergedTurns.length > 0) {
|
|
532
|
+
// Full merge: use merged prompt
|
|
533
|
+
finalPrompt = buildMergedPrompt(mergeResult, prompt, format);
|
|
534
|
+
}
|
|
535
|
+
else {
|
|
536
|
+
// Standard prompt-concat
|
|
537
|
+
const conversationForContext = contextConversation || existingConversation;
|
|
538
|
+
if (conversationForContext && conversationForContext.turns.length > 0) {
|
|
539
|
+
finalPrompt = buildMultiTurnPrompt(conversationForContext, prompt, format);
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
// Check tool availability
|
|
543
|
+
const toolStatus = await checkToolAvailability(tool);
|
|
544
|
+
if (!toolStatus.available) {
|
|
545
|
+
throw new Error(`CLI tool not available: ${tool}. Please ensure it is installed and in PATH.`);
|
|
546
|
+
}
|
|
547
|
+
// Log resume mode for debugging
|
|
548
|
+
if (resumeDecision) {
|
|
549
|
+
const modeDesc = getResumeModeDescription(resumeDecision);
|
|
550
|
+
if (onOutput) {
|
|
551
|
+
onOutput({ type: 'stderr', data: `[Resume mode: ${modeDesc}]\n` });
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
// Use configured primary model if no explicit model provided
|
|
555
|
+
const effectiveModel = model || getPrimaryModel(workingDir, tool);
|
|
556
|
+
// Build command
|
|
557
|
+
const { command, args, useStdin } = buildCommand({
|
|
558
|
+
tool,
|
|
559
|
+
prompt: finalPrompt,
|
|
560
|
+
mode,
|
|
561
|
+
model: effectiveModel,
|
|
562
|
+
dir: cd,
|
|
563
|
+
include: includeDirs,
|
|
564
|
+
nativeResume: nativeResumeConfig
|
|
565
|
+
});
|
|
566
|
+
const startTime = Date.now();
|
|
567
|
+
return new Promise((resolve, reject) => {
|
|
568
|
+
// Windows requires shell: true for npm global commands (.cmd files)
|
|
569
|
+
// Unix-like systems can use shell: false for direct execution
|
|
570
|
+
const isWindows = process.platform === 'win32';
|
|
571
|
+
const child = spawn(command, args, {
|
|
572
|
+
cwd: workingDir,
|
|
573
|
+
shell: isWindows, // Enable shell on Windows for .cmd files
|
|
574
|
+
stdio: [useStdin ? 'pipe' : 'ignore', 'pipe', 'pipe']
|
|
575
|
+
});
|
|
576
|
+
// Write prompt to stdin if using stdin mode (for gemini/qwen)
|
|
577
|
+
if (useStdin && child.stdin) {
|
|
578
|
+
child.stdin.write(finalPrompt);
|
|
579
|
+
child.stdin.end();
|
|
580
|
+
}
|
|
581
|
+
let stdout = '';
|
|
582
|
+
let stderr = '';
|
|
583
|
+
let timedOut = false;
|
|
584
|
+
// Handle stdout
|
|
585
|
+
child.stdout.on('data', (data) => {
|
|
586
|
+
const text = data.toString();
|
|
587
|
+
stdout += text;
|
|
588
|
+
if (onOutput) {
|
|
589
|
+
onOutput({ type: 'stdout', data: text });
|
|
590
|
+
}
|
|
591
|
+
});
|
|
592
|
+
// Handle stderr
|
|
593
|
+
child.stderr.on('data', (data) => {
|
|
594
|
+
const text = data.toString();
|
|
595
|
+
stderr += text;
|
|
596
|
+
if (onOutput) {
|
|
597
|
+
onOutput({ type: 'stderr', data: text });
|
|
598
|
+
}
|
|
599
|
+
});
|
|
600
|
+
// Handle completion
|
|
601
|
+
child.on('close', async (code) => {
|
|
602
|
+
const endTime = Date.now();
|
|
603
|
+
const duration = endTime - startTime;
|
|
604
|
+
// Determine status
|
|
605
|
+
let status = 'success';
|
|
606
|
+
if (timedOut) {
|
|
607
|
+
status = 'timeout';
|
|
608
|
+
}
|
|
609
|
+
else if (code !== 0) {
|
|
610
|
+
// Check if HTTP 429 but results exist (Gemini quirk)
|
|
611
|
+
if (stderr.includes('429') && stdout.trim()) {
|
|
612
|
+
status = 'success';
|
|
613
|
+
}
|
|
614
|
+
else {
|
|
615
|
+
status = 'error';
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
// Create new turn
|
|
619
|
+
const newTurnOutput = {
|
|
620
|
+
stdout: stdout.substring(0, 10240), // Truncate to 10KB
|
|
621
|
+
stderr: stderr.substring(0, 2048), // Truncate to 2KB
|
|
622
|
+
truncated: stdout.length > 10240 || stderr.length > 2048
|
|
623
|
+
};
|
|
624
|
+
// Determine base turn number for merge scenarios
|
|
625
|
+
const baseTurnNumber = isMerge && mergeResult
|
|
626
|
+
? mergeResult.mergedTurns.length + 1
|
|
627
|
+
: (existingConversation ? existingConversation.turns.length + 1 : 1);
|
|
628
|
+
const newTurn = {
|
|
629
|
+
turn: baseTurnNumber,
|
|
630
|
+
timestamp: new Date(startTime).toISOString(),
|
|
631
|
+
prompt,
|
|
632
|
+
duration_ms: duration,
|
|
633
|
+
status,
|
|
634
|
+
exit_code: code,
|
|
635
|
+
output: newTurnOutput
|
|
636
|
+
};
|
|
637
|
+
// Create or update conversation record
|
|
638
|
+
let conversation;
|
|
639
|
+
if (isMerge && mergeResult && !customId) {
|
|
640
|
+
// Merge without --id: append to ALL source conversations
|
|
641
|
+
// Save new turn to each source conversation
|
|
642
|
+
const savedConversations = [];
|
|
643
|
+
for (const srcConv of sourceConversations) {
|
|
644
|
+
const turnForSrc = {
|
|
645
|
+
...newTurn,
|
|
646
|
+
turn: srcConv.turns.length + 1 // Use each conversation's turn count
|
|
647
|
+
};
|
|
648
|
+
const updatedConv = {
|
|
649
|
+
...srcConv,
|
|
650
|
+
updated_at: new Date().toISOString(),
|
|
651
|
+
total_duration_ms: srcConv.total_duration_ms + duration,
|
|
652
|
+
turn_count: srcConv.turns.length + 1,
|
|
653
|
+
latest_status: status,
|
|
654
|
+
turns: [...srcConv.turns, turnForSrc]
|
|
655
|
+
};
|
|
656
|
+
savedConversations.push(updatedConv);
|
|
657
|
+
}
|
|
658
|
+
// Use first conversation as primary
|
|
659
|
+
conversation = savedConversations[0];
|
|
660
|
+
// Save all source conversations
|
|
661
|
+
try {
|
|
662
|
+
for (const conv of savedConversations) {
|
|
663
|
+
saveConversation(workingDir, conv);
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
catch (err) {
|
|
667
|
+
console.error('[CLI Executor] Failed to save merged histories:', err.message);
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
else if (isMerge && mergeResult && customId) {
|
|
671
|
+
// Merge with --id: create new conversation with merged turns + new turn
|
|
672
|
+
// Convert merged turns to regular turns (without source_id)
|
|
673
|
+
const mergedTurns = mergeResult.mergedTurns.map((mt, idx) => ({
|
|
674
|
+
turn: idx + 1,
|
|
675
|
+
timestamp: mt.timestamp,
|
|
676
|
+
prompt: mt.prompt,
|
|
677
|
+
duration_ms: mt.duration_ms,
|
|
678
|
+
status: mt.status,
|
|
679
|
+
exit_code: mt.exit_code,
|
|
680
|
+
output: mt.output
|
|
681
|
+
}));
|
|
682
|
+
conversation = existingConversation
|
|
683
|
+
? {
|
|
684
|
+
...existingConversation,
|
|
685
|
+
updated_at: new Date().toISOString(),
|
|
686
|
+
total_duration_ms: existingConversation.total_duration_ms + duration,
|
|
687
|
+
turn_count: existingConversation.turns.length + 1,
|
|
688
|
+
latest_status: status,
|
|
689
|
+
turns: [...existingConversation.turns, newTurn]
|
|
690
|
+
}
|
|
691
|
+
: {
|
|
692
|
+
id: conversationId,
|
|
693
|
+
created_at: new Date(startTime).toISOString(),
|
|
694
|
+
updated_at: new Date().toISOString(),
|
|
695
|
+
tool,
|
|
696
|
+
model: model || 'default',
|
|
697
|
+
mode,
|
|
698
|
+
category,
|
|
699
|
+
total_duration_ms: mergeResult.totalDuration + duration,
|
|
700
|
+
turn_count: mergedTurns.length + 1,
|
|
701
|
+
latest_status: status,
|
|
702
|
+
turns: [...mergedTurns, newTurn]
|
|
703
|
+
};
|
|
704
|
+
// Save merged conversation
|
|
705
|
+
try {
|
|
706
|
+
saveConversation(workingDir, conversation);
|
|
707
|
+
}
|
|
708
|
+
catch (err) {
|
|
709
|
+
console.error('[CLI Executor] Failed to save merged conversation:', err.message);
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
else {
|
|
713
|
+
// Normal scenario: single conversation
|
|
714
|
+
conversation = existingConversation
|
|
715
|
+
? {
|
|
716
|
+
...existingConversation,
|
|
717
|
+
updated_at: new Date().toISOString(),
|
|
718
|
+
total_duration_ms: existingConversation.total_duration_ms + duration,
|
|
719
|
+
turn_count: existingConversation.turns.length + 1,
|
|
720
|
+
latest_status: status,
|
|
721
|
+
turns: [...existingConversation.turns, newTurn]
|
|
722
|
+
}
|
|
723
|
+
: {
|
|
724
|
+
id: conversationId,
|
|
725
|
+
created_at: new Date(startTime).toISOString(),
|
|
726
|
+
updated_at: new Date().toISOString(),
|
|
727
|
+
tool,
|
|
728
|
+
model: model || 'default',
|
|
729
|
+
mode,
|
|
730
|
+
category,
|
|
731
|
+
total_duration_ms: duration,
|
|
732
|
+
turn_count: 1,
|
|
733
|
+
latest_status: status,
|
|
734
|
+
turns: [newTurn],
|
|
735
|
+
parent_execution_id: parentExecutionId
|
|
736
|
+
};
|
|
737
|
+
// Try to save conversation to history
|
|
738
|
+
try {
|
|
739
|
+
saveConversation(workingDir, conversation);
|
|
740
|
+
}
|
|
741
|
+
catch (err) {
|
|
742
|
+
// Non-fatal: continue even if history save fails
|
|
743
|
+
console.error('[CLI Executor] Failed to save history:', err.message);
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
// Track native session after execution (awaited to prevent process hang)
|
|
747
|
+
// Pass prompt for precise matching in parallel execution scenarios
|
|
748
|
+
try {
|
|
749
|
+
const nativeSession = await trackNewSession(tool, new Date(startTime), workingDir, prompt);
|
|
750
|
+
if (nativeSession) {
|
|
751
|
+
// Save native session mapping
|
|
752
|
+
try {
|
|
753
|
+
store.saveNativeSessionMapping({
|
|
754
|
+
ccw_id: conversationId,
|
|
755
|
+
tool,
|
|
756
|
+
native_session_id: nativeSession.sessionId,
|
|
757
|
+
native_session_path: nativeSession.filePath,
|
|
758
|
+
project_hash: nativeSession.projectHash,
|
|
759
|
+
created_at: new Date().toISOString()
|
|
760
|
+
});
|
|
761
|
+
}
|
|
762
|
+
catch (err) {
|
|
763
|
+
console.error('[CLI Executor] Failed to save native session mapping:', err.message);
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
catch (err) {
|
|
768
|
+
console.error('[CLI Executor] Failed to track native session:', err.message);
|
|
769
|
+
}
|
|
770
|
+
// Create legacy execution record for backward compatibility
|
|
771
|
+
const execution = {
|
|
772
|
+
id: conversationId,
|
|
773
|
+
timestamp: new Date(startTime).toISOString(),
|
|
774
|
+
tool,
|
|
775
|
+
model: model || 'default',
|
|
776
|
+
mode,
|
|
777
|
+
prompt,
|
|
778
|
+
status,
|
|
779
|
+
exit_code: code,
|
|
780
|
+
duration_ms: duration,
|
|
781
|
+
output: newTurnOutput
|
|
782
|
+
};
|
|
783
|
+
resolve({
|
|
784
|
+
success: status === 'success',
|
|
785
|
+
execution,
|
|
786
|
+
conversation,
|
|
787
|
+
stdout,
|
|
788
|
+
stderr
|
|
789
|
+
});
|
|
790
|
+
});
|
|
791
|
+
// Handle errors
|
|
792
|
+
child.on('error', (error) => {
|
|
793
|
+
reject(new Error(`Failed to spawn ${tool}: ${error.message}`));
|
|
794
|
+
});
|
|
795
|
+
// Timeout handling
|
|
796
|
+
const timeoutId = setTimeout(() => {
|
|
797
|
+
timedOut = true;
|
|
798
|
+
child.kill('SIGTERM');
|
|
799
|
+
setTimeout(() => {
|
|
800
|
+
if (!child.killed) {
|
|
801
|
+
child.kill('SIGKILL');
|
|
802
|
+
}
|
|
803
|
+
}, 5000);
|
|
804
|
+
}, timeout);
|
|
805
|
+
child.on('close', () => {
|
|
806
|
+
clearTimeout(timeoutId);
|
|
807
|
+
});
|
|
808
|
+
});
|
|
809
|
+
}
|
|
810
|
+
// Tool schema for MCP
|
|
811
|
+
export const schema = {
|
|
812
|
+
name: 'cli_executor',
|
|
813
|
+
description: `Execute external CLI tools (gemini/qwen/codex) with unified interface.
|
|
814
|
+
Modes:
|
|
815
|
+
- analysis: Read-only operations (default)
|
|
816
|
+
- write: File modifications allowed
|
|
817
|
+
- auto: Full autonomous operations (codex only)`,
|
|
818
|
+
inputSchema: {
|
|
819
|
+
type: 'object',
|
|
820
|
+
properties: {
|
|
821
|
+
tool: {
|
|
822
|
+
type: 'string',
|
|
823
|
+
enum: ['gemini', 'qwen', 'codex'],
|
|
824
|
+
description: 'CLI tool to execute'
|
|
825
|
+
},
|
|
826
|
+
prompt: {
|
|
827
|
+
type: 'string',
|
|
828
|
+
description: 'Prompt to send to the CLI tool'
|
|
829
|
+
},
|
|
830
|
+
mode: {
|
|
831
|
+
type: 'string',
|
|
832
|
+
enum: ['analysis', 'write', 'auto'],
|
|
833
|
+
description: 'Execution mode (default: analysis)',
|
|
834
|
+
default: 'analysis'
|
|
835
|
+
},
|
|
836
|
+
model: {
|
|
837
|
+
type: 'string',
|
|
838
|
+
description: 'Model override (tool-specific)'
|
|
839
|
+
},
|
|
840
|
+
cd: {
|
|
841
|
+
type: 'string',
|
|
842
|
+
description: 'Working directory for execution (-C for codex)'
|
|
843
|
+
},
|
|
844
|
+
includeDirs: {
|
|
845
|
+
type: 'string',
|
|
846
|
+
description: 'Additional directories (comma-separated). Maps to --include-directories for gemini/qwen, --add-dir for codex'
|
|
847
|
+
},
|
|
848
|
+
timeout: {
|
|
849
|
+
type: 'number',
|
|
850
|
+
description: 'Timeout in milliseconds (default: 300000 = 5 minutes)',
|
|
851
|
+
default: 300000
|
|
852
|
+
}
|
|
853
|
+
},
|
|
854
|
+
required: ['tool', 'prompt']
|
|
855
|
+
}
|
|
856
|
+
};
|
|
857
|
+
// Handler function
|
|
858
|
+
export async function handler(params) {
|
|
859
|
+
try {
|
|
860
|
+
const result = await executeCliTool(params);
|
|
861
|
+
return {
|
|
862
|
+
success: result.success,
|
|
863
|
+
result
|
|
864
|
+
};
|
|
865
|
+
}
|
|
866
|
+
catch (error) {
|
|
867
|
+
return {
|
|
868
|
+
success: false,
|
|
869
|
+
error: `CLI execution failed: ${error.message}`
|
|
870
|
+
};
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
/**
|
|
874
|
+
* Find all project directories with CLI history in centralized storage
|
|
875
|
+
* Returns list of project base directories (NOT history directories)
|
|
876
|
+
*/
|
|
877
|
+
function findProjectsWithHistory() {
|
|
878
|
+
const projectDirs = [];
|
|
879
|
+
const projectsRoot = join(StoragePaths.global.root(), 'projects');
|
|
880
|
+
if (!existsSync(projectsRoot)) {
|
|
881
|
+
return projectDirs;
|
|
882
|
+
}
|
|
883
|
+
try {
|
|
884
|
+
const entries = readdirSync(projectsRoot, { withFileTypes: true });
|
|
885
|
+
for (const entry of entries) {
|
|
886
|
+
if (entry.isDirectory()) {
|
|
887
|
+
const paths = StoragePaths.projectById(entry.name);
|
|
888
|
+
if (existsSync(paths.historyDb)) {
|
|
889
|
+
// Return project ID as identifier (actual project path is hashed)
|
|
890
|
+
projectDirs.push(entry.name);
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
catch {
|
|
896
|
+
// Ignore permission errors
|
|
897
|
+
}
|
|
898
|
+
return projectDirs;
|
|
899
|
+
}
|
|
900
|
+
/**
|
|
901
|
+
* Get execution history from SQLite (centralized storage)
|
|
902
|
+
*/
|
|
903
|
+
export async function getExecutionHistoryAsync(baseDir, options = {}) {
|
|
904
|
+
const { limit = 50, tool = null, status = null, category = null, search = null, recursive = false } = options;
|
|
905
|
+
// Recursive mode: aggregate data from parent and all child projects
|
|
906
|
+
if (recursive) {
|
|
907
|
+
const { scanChildProjectsAsync } = await import('../config/storage-paths.js');
|
|
908
|
+
const childProjects = await scanChildProjectsAsync(baseDir);
|
|
909
|
+
let allExecutions = [];
|
|
910
|
+
let totalCount = 0;
|
|
911
|
+
// Query parent project - apply limit at source to reduce memory footprint
|
|
912
|
+
try {
|
|
913
|
+
const parentStore = await getSqliteStore(baseDir);
|
|
914
|
+
const parentResult = parentStore.getHistory({ limit, tool, status, category, search });
|
|
915
|
+
totalCount += parentResult.total;
|
|
916
|
+
for (const exec of parentResult.executions) {
|
|
917
|
+
allExecutions.push({ ...exec, sourceDir: baseDir });
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
catch (error) {
|
|
921
|
+
if (process.env.DEBUG) {
|
|
922
|
+
console.error(`[CLI History] Failed to query parent project ${baseDir}:`, error);
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
// Query all child projects - apply limit to each child
|
|
926
|
+
for (const child of childProjects) {
|
|
927
|
+
try {
|
|
928
|
+
const childStore = await getSqliteStore(child.projectPath);
|
|
929
|
+
const childResult = childStore.getHistory({ limit, tool, status, category, search });
|
|
930
|
+
totalCount += childResult.total;
|
|
931
|
+
for (const exec of childResult.executions) {
|
|
932
|
+
allExecutions.push({
|
|
933
|
+
...exec,
|
|
934
|
+
sourceDir: child.relativePath // Show relative path for clarity
|
|
935
|
+
});
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
catch (error) {
|
|
939
|
+
if (process.env.DEBUG) {
|
|
940
|
+
console.error(`[CLI History] Failed to query child project ${child.projectPath}:`, error);
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
// Sort by timestamp (newest first) and apply limit
|
|
945
|
+
allExecutions.sort((a, b) => Number(b.timestamp) - Number(a.timestamp));
|
|
946
|
+
const limitedExecutions = allExecutions.slice(0, limit);
|
|
947
|
+
return {
|
|
948
|
+
total: totalCount,
|
|
949
|
+
count: limitedExecutions.length,
|
|
950
|
+
executions: limitedExecutions
|
|
951
|
+
};
|
|
952
|
+
}
|
|
953
|
+
// Non-recursive mode: only query current project
|
|
954
|
+
const store = await getSqliteStore(baseDir);
|
|
955
|
+
return store.getHistory({ limit, tool, status, category, search });
|
|
956
|
+
}
|
|
957
|
+
/**
|
|
958
|
+
* Get execution history (sync version - uses cached SQLite module)
|
|
959
|
+
*/
|
|
960
|
+
export function getExecutionHistory(baseDir, options = {}) {
|
|
961
|
+
const { limit = 50, tool = null, status = null, recursive = false } = options;
|
|
962
|
+
try {
|
|
963
|
+
if (recursive) {
|
|
964
|
+
const { scanChildProjects } = require('../config/storage-paths.js');
|
|
965
|
+
const childProjects = scanChildProjects(baseDir);
|
|
966
|
+
let allExecutions = [];
|
|
967
|
+
let totalCount = 0;
|
|
968
|
+
// Query parent project - apply limit at source
|
|
969
|
+
try {
|
|
970
|
+
const parentStore = getSqliteStoreSync(baseDir);
|
|
971
|
+
const parentResult = parentStore.getHistory({ limit, tool, status });
|
|
972
|
+
totalCount += parentResult.total;
|
|
973
|
+
for (const exec of parentResult.executions) {
|
|
974
|
+
allExecutions.push({ ...exec, sourceDir: baseDir });
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
catch (error) {
|
|
978
|
+
if (process.env.DEBUG) {
|
|
979
|
+
console.error(`[CLI History Sync] Failed to query parent project ${baseDir}:`, error);
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
// Query all child projects - apply limit to each child
|
|
983
|
+
for (const child of childProjects) {
|
|
984
|
+
try {
|
|
985
|
+
const childStore = getSqliteStoreSync(child.projectPath);
|
|
986
|
+
const childResult = childStore.getHistory({ limit, tool, status });
|
|
987
|
+
totalCount += childResult.total;
|
|
988
|
+
for (const exec of childResult.executions) {
|
|
989
|
+
allExecutions.push({
|
|
990
|
+
...exec,
|
|
991
|
+
sourceDir: child.relativePath
|
|
992
|
+
});
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
catch (error) {
|
|
996
|
+
if (process.env.DEBUG) {
|
|
997
|
+
console.error(`[CLI History Sync] Failed to query child project ${child.projectPath}:`, error);
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
// Sort by timestamp (newest first) and apply limit
|
|
1002
|
+
allExecutions.sort((a, b) => Number(b.timestamp) - Number(a.timestamp));
|
|
1003
|
+
return {
|
|
1004
|
+
total: totalCount,
|
|
1005
|
+
count: Math.min(allExecutions.length, limit),
|
|
1006
|
+
executions: allExecutions.slice(0, limit)
|
|
1007
|
+
};
|
|
1008
|
+
}
|
|
1009
|
+
const store = getSqliteStoreSync(baseDir);
|
|
1010
|
+
return store.getHistory({ limit, tool, status });
|
|
1011
|
+
}
|
|
1012
|
+
catch {
|
|
1013
|
+
// SQLite not initialized, return empty
|
|
1014
|
+
return { total: 0, count: 0, executions: [] };
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
/**
|
|
1018
|
+
* Get conversation detail by ID (returns ConversationRecord)
|
|
1019
|
+
*/
|
|
1020
|
+
export function getConversationDetail(baseDir, conversationId) {
|
|
1021
|
+
// Pass baseDir directly - loadConversation will resolve the correct storage path
|
|
1022
|
+
return loadConversation(baseDir, conversationId);
|
|
1023
|
+
}
|
|
1024
|
+
/**
|
|
1025
|
+
* Get conversation detail with native session info
|
|
1026
|
+
*/
|
|
1027
|
+
export function getConversationDetailWithNativeInfo(baseDir, conversationId) {
|
|
1028
|
+
try {
|
|
1029
|
+
const store = getSqliteStoreSync(baseDir);
|
|
1030
|
+
return store.getConversationWithNativeInfo(conversationId);
|
|
1031
|
+
}
|
|
1032
|
+
catch {
|
|
1033
|
+
// SQLite not initialized, return null
|
|
1034
|
+
return null;
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
/**
|
|
1038
|
+
* Get execution detail by ID (legacy, returns ExecutionRecord for backward compatibility)
|
|
1039
|
+
*/
|
|
1040
|
+
export function getExecutionDetail(baseDir, executionId) {
|
|
1041
|
+
const conversation = getConversationDetail(baseDir, executionId);
|
|
1042
|
+
if (!conversation)
|
|
1043
|
+
return null;
|
|
1044
|
+
// Convert to legacy ExecutionRecord format (using latest turn)
|
|
1045
|
+
const latestTurn = conversation.turns[conversation.turns.length - 1];
|
|
1046
|
+
return {
|
|
1047
|
+
id: conversation.id,
|
|
1048
|
+
timestamp: conversation.created_at,
|
|
1049
|
+
tool: conversation.tool,
|
|
1050
|
+
model: conversation.model,
|
|
1051
|
+
mode: conversation.mode,
|
|
1052
|
+
prompt: latestTurn.prompt,
|
|
1053
|
+
status: conversation.latest_status,
|
|
1054
|
+
exit_code: latestTurn.exit_code,
|
|
1055
|
+
duration_ms: conversation.total_duration_ms,
|
|
1056
|
+
output: latestTurn.output
|
|
1057
|
+
};
|
|
1058
|
+
}
|
|
1059
|
+
/**
|
|
1060
|
+
* Delete execution by ID (async version)
|
|
1061
|
+
*/
|
|
1062
|
+
export async function deleteExecutionAsync(baseDir, executionId) {
|
|
1063
|
+
const store = await getSqliteStore(baseDir);
|
|
1064
|
+
return store.deleteConversation(executionId);
|
|
1065
|
+
}
|
|
1066
|
+
/**
|
|
1067
|
+
* Delete execution by ID (sync version - uses cached SQLite module)
|
|
1068
|
+
*/
|
|
1069
|
+
export function deleteExecution(baseDir, executionId) {
|
|
1070
|
+
try {
|
|
1071
|
+
const store = getSqliteStoreSync(baseDir);
|
|
1072
|
+
return store.deleteConversation(executionId);
|
|
1073
|
+
}
|
|
1074
|
+
catch {
|
|
1075
|
+
return { success: false, error: 'SQLite store not initialized' };
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
/**
|
|
1079
|
+
* Batch delete executions (async)
|
|
1080
|
+
*/
|
|
1081
|
+
export async function batchDeleteExecutionsAsync(baseDir, ids) {
|
|
1082
|
+
const store = await getSqliteStore(baseDir);
|
|
1083
|
+
const result = store.batchDelete(ids);
|
|
1084
|
+
return { ...result, total: ids.length };
|
|
1085
|
+
}
|
|
1086
|
+
/**
|
|
1087
|
+
* Get status of all CLI tools
|
|
1088
|
+
*/
|
|
1089
|
+
export async function getCliToolsStatus() {
|
|
1090
|
+
const tools = ['gemini', 'qwen', 'codex', 'claude'];
|
|
1091
|
+
const results = {};
|
|
1092
|
+
await Promise.all(tools.map(async (tool) => {
|
|
1093
|
+
results[tool] = await checkToolAvailability(tool);
|
|
1094
|
+
}));
|
|
1095
|
+
return results;
|
|
1096
|
+
}
|
|
1097
|
+
// CLI tool package mapping
|
|
1098
|
+
const CLI_TOOL_PACKAGES = {
|
|
1099
|
+
gemini: '@google/gemini-cli',
|
|
1100
|
+
qwen: '@qwen-code/qwen-code',
|
|
1101
|
+
codex: '@openai/codex',
|
|
1102
|
+
claude: '@anthropic-ai/claude-code'
|
|
1103
|
+
};
|
|
1104
|
+
// Disabled tools storage (in-memory fallback, main storage is in cli-config.json)
|
|
1105
|
+
const disabledTools = new Set();
|
|
1106
|
+
// Default working directory for config operations
|
|
1107
|
+
let configBaseDir = process.cwd();
|
|
1108
|
+
/**
|
|
1109
|
+
* Set the base directory for config operations
|
|
1110
|
+
*/
|
|
1111
|
+
export function setConfigBaseDir(dir) {
|
|
1112
|
+
configBaseDir = dir;
|
|
1113
|
+
}
|
|
1114
|
+
/**
|
|
1115
|
+
* Install a CLI tool via npm
|
|
1116
|
+
*/
|
|
1117
|
+
export async function installCliTool(tool) {
|
|
1118
|
+
const packageName = CLI_TOOL_PACKAGES[tool];
|
|
1119
|
+
if (!packageName) {
|
|
1120
|
+
return { success: false, error: `Unknown tool: ${tool}` };
|
|
1121
|
+
}
|
|
1122
|
+
return new Promise((resolve) => {
|
|
1123
|
+
const child = spawn('npm', ['install', '-g', packageName], {
|
|
1124
|
+
shell: true,
|
|
1125
|
+
stdio: ['ignore', 'pipe', 'pipe']
|
|
1126
|
+
});
|
|
1127
|
+
let stderr = '';
|
|
1128
|
+
child.stderr?.on('data', (data) => { stderr += data.toString(); });
|
|
1129
|
+
child.on('close', (code) => {
|
|
1130
|
+
// Clear cache to force re-check
|
|
1131
|
+
toolAvailabilityCache.delete(tool);
|
|
1132
|
+
if (code === 0) {
|
|
1133
|
+
resolve({ success: true });
|
|
1134
|
+
}
|
|
1135
|
+
else {
|
|
1136
|
+
resolve({ success: false, error: stderr || `npm install failed with code ${code}` });
|
|
1137
|
+
}
|
|
1138
|
+
});
|
|
1139
|
+
child.on('error', (err) => {
|
|
1140
|
+
resolve({ success: false, error: err.message });
|
|
1141
|
+
});
|
|
1142
|
+
// Timeout after 2 minutes
|
|
1143
|
+
setTimeout(() => {
|
|
1144
|
+
child.kill();
|
|
1145
|
+
resolve({ success: false, error: 'Installation timed out' });
|
|
1146
|
+
}, 120000);
|
|
1147
|
+
});
|
|
1148
|
+
}
|
|
1149
|
+
/**
|
|
1150
|
+
* Uninstall a CLI tool via npm
|
|
1151
|
+
*/
|
|
1152
|
+
export async function uninstallCliTool(tool) {
|
|
1153
|
+
const packageName = CLI_TOOL_PACKAGES[tool];
|
|
1154
|
+
if (!packageName) {
|
|
1155
|
+
return { success: false, error: `Unknown tool: ${tool}` };
|
|
1156
|
+
}
|
|
1157
|
+
return new Promise((resolve) => {
|
|
1158
|
+
const child = spawn('npm', ['uninstall', '-g', packageName], {
|
|
1159
|
+
shell: true,
|
|
1160
|
+
stdio: ['ignore', 'pipe', 'pipe']
|
|
1161
|
+
});
|
|
1162
|
+
let stderr = '';
|
|
1163
|
+
child.stderr?.on('data', (data) => { stderr += data.toString(); });
|
|
1164
|
+
child.on('close', (code) => {
|
|
1165
|
+
// Clear cache to force re-check
|
|
1166
|
+
toolAvailabilityCache.delete(tool);
|
|
1167
|
+
if (code === 0) {
|
|
1168
|
+
resolve({ success: true });
|
|
1169
|
+
}
|
|
1170
|
+
else {
|
|
1171
|
+
resolve({ success: false, error: stderr || `npm uninstall failed with code ${code}` });
|
|
1172
|
+
}
|
|
1173
|
+
});
|
|
1174
|
+
child.on('error', (err) => {
|
|
1175
|
+
resolve({ success: false, error: err.message });
|
|
1176
|
+
});
|
|
1177
|
+
// Timeout after 1 minute
|
|
1178
|
+
setTimeout(() => {
|
|
1179
|
+
child.kill();
|
|
1180
|
+
resolve({ success: false, error: 'Uninstallation timed out' });
|
|
1181
|
+
}, 60000);
|
|
1182
|
+
});
|
|
1183
|
+
}
|
|
1184
|
+
/**
|
|
1185
|
+
* Enable a CLI tool (updates config file)
|
|
1186
|
+
*/
|
|
1187
|
+
export function enableCliTool(tool) {
|
|
1188
|
+
try {
|
|
1189
|
+
enableToolFromConfig(configBaseDir, tool);
|
|
1190
|
+
disabledTools.delete(tool); // Also update in-memory fallback
|
|
1191
|
+
return { success: true };
|
|
1192
|
+
}
|
|
1193
|
+
catch (err) {
|
|
1194
|
+
console.error('[cli-executor] Error enabling tool:', err);
|
|
1195
|
+
disabledTools.delete(tool); // Fallback to in-memory
|
|
1196
|
+
return { success: true };
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
/**
|
|
1200
|
+
* Disable a CLI tool (updates config file)
|
|
1201
|
+
*/
|
|
1202
|
+
export function disableCliTool(tool) {
|
|
1203
|
+
try {
|
|
1204
|
+
disableToolFromConfig(configBaseDir, tool);
|
|
1205
|
+
disabledTools.add(tool); // Also update in-memory fallback
|
|
1206
|
+
return { success: true };
|
|
1207
|
+
}
|
|
1208
|
+
catch (err) {
|
|
1209
|
+
console.error('[cli-executor] Error disabling tool:', err);
|
|
1210
|
+
disabledTools.add(tool); // Fallback to in-memory
|
|
1211
|
+
return { success: true };
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1214
|
+
/**
|
|
1215
|
+
* Check if a tool is enabled (reads from config file)
|
|
1216
|
+
*/
|
|
1217
|
+
export function isToolEnabled(tool) {
|
|
1218
|
+
try {
|
|
1219
|
+
return isToolEnabledFromConfig(configBaseDir, tool);
|
|
1220
|
+
}
|
|
1221
|
+
catch {
|
|
1222
|
+
// Fallback to in-memory check
|
|
1223
|
+
return !disabledTools.has(tool);
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
/**
|
|
1227
|
+
* Get full status of all CLI tools including enabled state
|
|
1228
|
+
*/
|
|
1229
|
+
export async function getCliToolsFullStatus() {
|
|
1230
|
+
const tools = Object.keys(CLI_TOOL_PACKAGES);
|
|
1231
|
+
const results = {};
|
|
1232
|
+
await Promise.all(tools.map(async (tool) => {
|
|
1233
|
+
const availability = await checkToolAvailability(tool);
|
|
1234
|
+
results[tool] = {
|
|
1235
|
+
available: availability.available,
|
|
1236
|
+
enabled: isToolEnabled(tool),
|
|
1237
|
+
path: availability.path,
|
|
1238
|
+
packageName: CLI_TOOL_PACKAGES[tool]
|
|
1239
|
+
};
|
|
1240
|
+
}));
|
|
1241
|
+
return results;
|
|
1242
|
+
}
|
|
1243
|
+
/**
|
|
1244
|
+
* PromptConcatenator - Dedicated class for building multi-turn prompts
|
|
1245
|
+
* Supports multiple output formats: plain text, YAML, JSON
|
|
1246
|
+
*/
|
|
1247
|
+
class PromptConcatenator {
|
|
1248
|
+
turns = [];
|
|
1249
|
+
options;
|
|
1250
|
+
metadata = {};
|
|
1251
|
+
constructor(options = {}) {
|
|
1252
|
+
this.options = {
|
|
1253
|
+
format: options.format || 'plain',
|
|
1254
|
+
includeMetadata: options.includeMetadata ?? true,
|
|
1255
|
+
includeTurnMarkers: options.includeTurnMarkers ?? true,
|
|
1256
|
+
maxOutputLength: options.maxOutputLength || 8192
|
|
1257
|
+
};
|
|
1258
|
+
}
|
|
1259
|
+
/**
|
|
1260
|
+
* Set metadata for the conversation
|
|
1261
|
+
*/
|
|
1262
|
+
setMetadata(key, value) {
|
|
1263
|
+
this.metadata[key] = value;
|
|
1264
|
+
return this;
|
|
1265
|
+
}
|
|
1266
|
+
/**
|
|
1267
|
+
* Add a user turn
|
|
1268
|
+
*/
|
|
1269
|
+
addUserTurn(content, options = {}) {
|
|
1270
|
+
this.turns.push({
|
|
1271
|
+
turn: this.turns.length + 1,
|
|
1272
|
+
role: 'user',
|
|
1273
|
+
content,
|
|
1274
|
+
...options
|
|
1275
|
+
});
|
|
1276
|
+
return this;
|
|
1277
|
+
}
|
|
1278
|
+
/**
|
|
1279
|
+
* Add an assistant turn
|
|
1280
|
+
*/
|
|
1281
|
+
addAssistantTurn(content, options = {}) {
|
|
1282
|
+
// Truncate output if needed
|
|
1283
|
+
const truncatedContent = content.length > this.options.maxOutputLength
|
|
1284
|
+
? content.substring(0, this.options.maxOutputLength) + '\n... [truncated]'
|
|
1285
|
+
: content;
|
|
1286
|
+
this.turns.push({
|
|
1287
|
+
turn: this.turns.length + 1,
|
|
1288
|
+
role: 'assistant',
|
|
1289
|
+
content: truncatedContent,
|
|
1290
|
+
...options
|
|
1291
|
+
});
|
|
1292
|
+
return this;
|
|
1293
|
+
}
|
|
1294
|
+
/**
|
|
1295
|
+
* Add a conversation turn from ConversationTurn
|
|
1296
|
+
*/
|
|
1297
|
+
addFromConversationTurn(turn, sourceId) {
|
|
1298
|
+
this.addUserTurn(turn.prompt, {
|
|
1299
|
+
turn: turn.turn * 2 - 1,
|
|
1300
|
+
timestamp: turn.timestamp,
|
|
1301
|
+
source_id: sourceId
|
|
1302
|
+
});
|
|
1303
|
+
this.addAssistantTurn(turn.output.stdout || '[No output]', {
|
|
1304
|
+
turn: turn.turn * 2,
|
|
1305
|
+
timestamp: turn.timestamp,
|
|
1306
|
+
status: turn.status,
|
|
1307
|
+
duration_ms: turn.duration_ms,
|
|
1308
|
+
source_id: sourceId
|
|
1309
|
+
});
|
|
1310
|
+
return this;
|
|
1311
|
+
}
|
|
1312
|
+
/**
|
|
1313
|
+
* Load turns from an existing conversation
|
|
1314
|
+
*/
|
|
1315
|
+
loadConversation(conversation) {
|
|
1316
|
+
for (const turn of conversation.turns) {
|
|
1317
|
+
this.addFromConversationTurn(turn);
|
|
1318
|
+
}
|
|
1319
|
+
return this;
|
|
1320
|
+
}
|
|
1321
|
+
/**
|
|
1322
|
+
* Build the final prompt in plain text format
|
|
1323
|
+
*/
|
|
1324
|
+
buildPlainText(newPrompt) {
|
|
1325
|
+
const parts = [];
|
|
1326
|
+
// Metadata section
|
|
1327
|
+
if (this.options.includeMetadata && Object.keys(this.metadata).length > 0) {
|
|
1328
|
+
parts.push('=== CONTEXT ===');
|
|
1329
|
+
for (const [key, value] of Object.entries(this.metadata)) {
|
|
1330
|
+
parts.push(`${key}: ${String(value)}`);
|
|
1331
|
+
}
|
|
1332
|
+
parts.push('');
|
|
1333
|
+
}
|
|
1334
|
+
// Conversation history
|
|
1335
|
+
if (this.turns.length > 0) {
|
|
1336
|
+
parts.push('=== CONVERSATION HISTORY ===');
|
|
1337
|
+
parts.push('');
|
|
1338
|
+
let currentTurn = 0;
|
|
1339
|
+
for (let i = 0; i < this.turns.length; i += 2) {
|
|
1340
|
+
currentTurn++;
|
|
1341
|
+
const userTurn = this.turns[i];
|
|
1342
|
+
const assistantTurn = this.turns[i + 1];
|
|
1343
|
+
if (this.options.includeTurnMarkers) {
|
|
1344
|
+
const sourceMarker = userTurn.source_id ? ` [${userTurn.source_id}]` : '';
|
|
1345
|
+
parts.push(`--- Turn ${currentTurn}${sourceMarker} ---`);
|
|
1346
|
+
}
|
|
1347
|
+
parts.push('USER:');
|
|
1348
|
+
parts.push(userTurn.content);
|
|
1349
|
+
parts.push('');
|
|
1350
|
+
if (assistantTurn) {
|
|
1351
|
+
parts.push('ASSISTANT:');
|
|
1352
|
+
parts.push(assistantTurn.content);
|
|
1353
|
+
parts.push('');
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
1357
|
+
// New request
|
|
1358
|
+
parts.push('=== NEW REQUEST ===');
|
|
1359
|
+
parts.push('');
|
|
1360
|
+
parts.push(newPrompt);
|
|
1361
|
+
return parts.join('\n');
|
|
1362
|
+
}
|
|
1363
|
+
/**
|
|
1364
|
+
* Build the final prompt in YAML format
|
|
1365
|
+
*/
|
|
1366
|
+
buildYaml(newPrompt) {
|
|
1367
|
+
const yamlLines = [];
|
|
1368
|
+
// Metadata
|
|
1369
|
+
if (this.options.includeMetadata && Object.keys(this.metadata).length > 0) {
|
|
1370
|
+
yamlLines.push('context:');
|
|
1371
|
+
for (const [key, value] of Object.entries(this.metadata)) {
|
|
1372
|
+
yamlLines.push(` ${key}: ${this.yamlValue(value)}`);
|
|
1373
|
+
}
|
|
1374
|
+
yamlLines.push('');
|
|
1375
|
+
}
|
|
1376
|
+
// Conversation history
|
|
1377
|
+
if (this.turns.length > 0) {
|
|
1378
|
+
yamlLines.push('conversation:');
|
|
1379
|
+
let currentTurn = 0;
|
|
1380
|
+
for (let i = 0; i < this.turns.length; i += 2) {
|
|
1381
|
+
currentTurn++;
|
|
1382
|
+
const userTurn = this.turns[i];
|
|
1383
|
+
const assistantTurn = this.turns[i + 1];
|
|
1384
|
+
yamlLines.push(` - turn: ${currentTurn}`);
|
|
1385
|
+
if (userTurn.source_id) {
|
|
1386
|
+
yamlLines.push(` source: ${userTurn.source_id}`);
|
|
1387
|
+
}
|
|
1388
|
+
if (userTurn.timestamp) {
|
|
1389
|
+
yamlLines.push(` timestamp: ${userTurn.timestamp}`);
|
|
1390
|
+
}
|
|
1391
|
+
// User message
|
|
1392
|
+
yamlLines.push(' user: |');
|
|
1393
|
+
const userLines = userTurn.content.split('\n');
|
|
1394
|
+
for (const line of userLines) {
|
|
1395
|
+
yamlLines.push(` ${line}`);
|
|
1396
|
+
}
|
|
1397
|
+
// Assistant message
|
|
1398
|
+
if (assistantTurn) {
|
|
1399
|
+
if (assistantTurn.status) {
|
|
1400
|
+
yamlLines.push(` status: ${assistantTurn.status}`);
|
|
1401
|
+
}
|
|
1402
|
+
if (assistantTurn.duration_ms) {
|
|
1403
|
+
yamlLines.push(` duration_ms: ${assistantTurn.duration_ms}`);
|
|
1404
|
+
}
|
|
1405
|
+
yamlLines.push(' assistant: |');
|
|
1406
|
+
const assistantLines = assistantTurn.content.split('\n');
|
|
1407
|
+
for (const line of assistantLines) {
|
|
1408
|
+
yamlLines.push(` ${line}`);
|
|
1409
|
+
}
|
|
1410
|
+
}
|
|
1411
|
+
yamlLines.push('');
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
// New request
|
|
1415
|
+
yamlLines.push('new_request: |');
|
|
1416
|
+
const requestLines = newPrompt.split('\n');
|
|
1417
|
+
for (const line of requestLines) {
|
|
1418
|
+
yamlLines.push(` ${line}`);
|
|
1419
|
+
}
|
|
1420
|
+
return yamlLines.join('\n');
|
|
1421
|
+
}
|
|
1422
|
+
/**
|
|
1423
|
+
* Build the final prompt in JSON format
|
|
1424
|
+
*/
|
|
1425
|
+
buildJson(newPrompt) {
|
|
1426
|
+
const data = {};
|
|
1427
|
+
// Metadata
|
|
1428
|
+
if (this.options.includeMetadata && Object.keys(this.metadata).length > 0) {
|
|
1429
|
+
data.context = this.metadata;
|
|
1430
|
+
}
|
|
1431
|
+
// Conversation history
|
|
1432
|
+
if (this.turns.length > 0) {
|
|
1433
|
+
const conversation = [];
|
|
1434
|
+
for (let i = 0; i < this.turns.length; i += 2) {
|
|
1435
|
+
const userTurn = this.turns[i];
|
|
1436
|
+
const assistantTurn = this.turns[i + 1];
|
|
1437
|
+
const turnData = {
|
|
1438
|
+
turn: Math.ceil((i + 1) / 2),
|
|
1439
|
+
user: userTurn.content
|
|
1440
|
+
};
|
|
1441
|
+
if (userTurn.source_id)
|
|
1442
|
+
turnData.source = userTurn.source_id;
|
|
1443
|
+
if (userTurn.timestamp)
|
|
1444
|
+
turnData.timestamp = userTurn.timestamp;
|
|
1445
|
+
if (assistantTurn) {
|
|
1446
|
+
turnData.assistant = assistantTurn.content;
|
|
1447
|
+
if (assistantTurn.status)
|
|
1448
|
+
turnData.status = assistantTurn.status;
|
|
1449
|
+
if (assistantTurn.duration_ms)
|
|
1450
|
+
turnData.duration_ms = assistantTurn.duration_ms;
|
|
1451
|
+
}
|
|
1452
|
+
conversation.push(turnData);
|
|
1453
|
+
}
|
|
1454
|
+
data.conversation = conversation;
|
|
1455
|
+
}
|
|
1456
|
+
data.new_request = newPrompt;
|
|
1457
|
+
return JSON.stringify(data, null, 2);
|
|
1458
|
+
}
|
|
1459
|
+
/**
|
|
1460
|
+
* Helper to format YAML values
|
|
1461
|
+
*/
|
|
1462
|
+
yamlValue(value) {
|
|
1463
|
+
if (typeof value === 'string') {
|
|
1464
|
+
// Quote strings that might be interpreted as other types
|
|
1465
|
+
if (/[:\[\]{}#&*!|>'"@`]/.test(value) || value === '') {
|
|
1466
|
+
return `"${value.replace(/"/g, '\\"')}"`;
|
|
1467
|
+
}
|
|
1468
|
+
return value;
|
|
1469
|
+
}
|
|
1470
|
+
if (typeof value === 'number' || typeof value === 'boolean') {
|
|
1471
|
+
return String(value);
|
|
1472
|
+
}
|
|
1473
|
+
if (value === null || value === undefined) {
|
|
1474
|
+
return 'null';
|
|
1475
|
+
}
|
|
1476
|
+
return JSON.stringify(value);
|
|
1477
|
+
}
|
|
1478
|
+
/**
|
|
1479
|
+
* Build the final prompt string
|
|
1480
|
+
*/
|
|
1481
|
+
build(newPrompt) {
|
|
1482
|
+
switch (this.options.format) {
|
|
1483
|
+
case 'yaml':
|
|
1484
|
+
return this.buildYaml(newPrompt);
|
|
1485
|
+
case 'json':
|
|
1486
|
+
return this.buildJson(newPrompt);
|
|
1487
|
+
case 'plain':
|
|
1488
|
+
default:
|
|
1489
|
+
return this.buildPlainText(newPrompt);
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1492
|
+
/**
|
|
1493
|
+
* Reset the concatenator for reuse
|
|
1494
|
+
*/
|
|
1495
|
+
reset() {
|
|
1496
|
+
this.turns = [];
|
|
1497
|
+
this.metadata = {};
|
|
1498
|
+
return this;
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1501
|
+
/**
|
|
1502
|
+
* Create a prompt concatenator with specified options
|
|
1503
|
+
*/
|
|
1504
|
+
function createPromptConcatenator(options) {
|
|
1505
|
+
return new PromptConcatenator(options);
|
|
1506
|
+
}
|
|
1507
|
+
/**
|
|
1508
|
+
* Quick helper to build a multi-turn prompt in any format
|
|
1509
|
+
*/
|
|
1510
|
+
function buildPrompt(conversation, newPrompt, format = 'plain') {
|
|
1511
|
+
return createPromptConcatenator({ format })
|
|
1512
|
+
.loadConversation(conversation)
|
|
1513
|
+
.build(newPrompt);
|
|
1514
|
+
}
|
|
1515
|
+
/**
|
|
1516
|
+
* Build multi-turn prompt with full conversation history
|
|
1517
|
+
* Uses the PromptConcatenator with plain text format by default
|
|
1518
|
+
*/
|
|
1519
|
+
function buildMultiTurnPrompt(conversation, newPrompt, format = 'plain') {
|
|
1520
|
+
return buildPrompt(conversation, newPrompt, format);
|
|
1521
|
+
}
|
|
1522
|
+
/**
|
|
1523
|
+
* Build continuation prompt with previous conversation context (legacy)
|
|
1524
|
+
*/
|
|
1525
|
+
function buildContinuationPrompt(previous, additionalPrompt) {
|
|
1526
|
+
const parts = [];
|
|
1527
|
+
// Add previous conversation context
|
|
1528
|
+
parts.push('=== PREVIOUS CONVERSATION ===');
|
|
1529
|
+
parts.push('');
|
|
1530
|
+
parts.push('USER PROMPT:');
|
|
1531
|
+
parts.push(previous.prompt);
|
|
1532
|
+
parts.push('');
|
|
1533
|
+
parts.push('ASSISTANT RESPONSE:');
|
|
1534
|
+
parts.push(previous.output.stdout || '[No output recorded]');
|
|
1535
|
+
parts.push('');
|
|
1536
|
+
parts.push('=== CONTINUATION ===');
|
|
1537
|
+
parts.push('');
|
|
1538
|
+
if (additionalPrompt) {
|
|
1539
|
+
parts.push(additionalPrompt);
|
|
1540
|
+
}
|
|
1541
|
+
else {
|
|
1542
|
+
parts.push('Continue from where we left off. What should we do next?');
|
|
1543
|
+
}
|
|
1544
|
+
return parts.join('\n');
|
|
1545
|
+
}
|
|
1546
|
+
/**
|
|
1547
|
+
* Get previous execution for resume
|
|
1548
|
+
* @param baseDir - Working directory
|
|
1549
|
+
* @param tool - Tool to filter by
|
|
1550
|
+
* @param resume - true for last, or execution ID string
|
|
1551
|
+
*/
|
|
1552
|
+
function getPreviousExecution(baseDir, tool, resume) {
|
|
1553
|
+
if (typeof resume === 'string') {
|
|
1554
|
+
// Resume specific execution by ID
|
|
1555
|
+
return getExecutionDetail(baseDir, resume);
|
|
1556
|
+
}
|
|
1557
|
+
else if (resume === true) {
|
|
1558
|
+
// Resume last execution for this tool
|
|
1559
|
+
const history = getExecutionHistory(baseDir, { limit: 1, tool });
|
|
1560
|
+
if (history.executions.length === 0) {
|
|
1561
|
+
return null;
|
|
1562
|
+
}
|
|
1563
|
+
return getExecutionDetail(baseDir, history.executions[0].id);
|
|
1564
|
+
}
|
|
1565
|
+
return null;
|
|
1566
|
+
}
|
|
1567
|
+
/**
|
|
1568
|
+
* Get latest execution for a specific tool
|
|
1569
|
+
*/
|
|
1570
|
+
export function getLatestExecution(baseDir, tool) {
|
|
1571
|
+
const history = getExecutionHistory(baseDir, { limit: 1, tool: tool || null });
|
|
1572
|
+
if (history.executions.length === 0) {
|
|
1573
|
+
return null;
|
|
1574
|
+
}
|
|
1575
|
+
return getExecutionDetail(baseDir, history.executions[0].id);
|
|
1576
|
+
}
|
|
1577
|
+
// ========== Native Session Content Functions ==========
|
|
1578
|
+
/**
|
|
1579
|
+
* Get native session content by CCW ID
|
|
1580
|
+
* Parses the native session file and returns full conversation data
|
|
1581
|
+
*/
|
|
1582
|
+
export async function getNativeSessionContent(baseDir, ccwId) {
|
|
1583
|
+
const store = await getSqliteStore(baseDir);
|
|
1584
|
+
return store.getNativeSessionContent(ccwId);
|
|
1585
|
+
}
|
|
1586
|
+
/**
|
|
1587
|
+
* Get formatted native conversation text
|
|
1588
|
+
*/
|
|
1589
|
+
export async function getFormattedNativeConversation(baseDir, ccwId, options) {
|
|
1590
|
+
const store = await getSqliteStore(baseDir);
|
|
1591
|
+
return store.getFormattedNativeConversation(ccwId, options);
|
|
1592
|
+
}
|
|
1593
|
+
/**
|
|
1594
|
+
* Get conversation pairs from native session
|
|
1595
|
+
*/
|
|
1596
|
+
export async function getNativeConversationPairs(baseDir, ccwId) {
|
|
1597
|
+
const store = await getSqliteStore(baseDir);
|
|
1598
|
+
return store.getNativeConversationPairs(ccwId);
|
|
1599
|
+
}
|
|
1600
|
+
/**
|
|
1601
|
+
* Get enriched conversation (CCW + native session merged)
|
|
1602
|
+
*/
|
|
1603
|
+
export async function getEnrichedConversation(baseDir, ccwId) {
|
|
1604
|
+
const store = await getSqliteStore(baseDir);
|
|
1605
|
+
return store.getEnrichedConversation(ccwId);
|
|
1606
|
+
}
|
|
1607
|
+
/**
|
|
1608
|
+
* Get history with native session info
|
|
1609
|
+
*/
|
|
1610
|
+
export async function getHistoryWithNativeInfo(baseDir, options) {
|
|
1611
|
+
const store = await getSqliteStore(baseDir);
|
|
1612
|
+
return store.getHistoryWithNativeInfo(options || {});
|
|
1613
|
+
}
|
|
1614
|
+
// Export utility functions and tool definition for backward compatibility
|
|
1615
|
+
export { executeCliTool, checkToolAvailability };
|
|
1616
|
+
// Export prompt concatenation utilities
|
|
1617
|
+
export { PromptConcatenator, createPromptConcatenator, buildPrompt, buildMultiTurnPrompt };
|
|
1618
|
+
// Note: Async storage functions (getExecutionHistoryAsync, deleteExecutionAsync,
|
|
1619
|
+
// batchDeleteExecutionsAsync) are exported at declaration site - SQLite storage only
|
|
1620
|
+
// Export tool definition (for legacy imports) - This allows direct calls to execute with onOutput
|
|
1621
|
+
export const cliExecutorTool = {
|
|
1622
|
+
schema,
|
|
1623
|
+
execute: executeCliTool // Use executeCliTool directly which supports onOutput callback
|
|
1624
|
+
};
|
|
1625
|
+
//# sourceMappingURL=cli-executor.js.map
|