lattice-orchestrator 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +58 -0
- package/config/logrotate.conf +15 -0
- package/dist/cli-parser.d.ts +11 -0
- package/dist/cli-parser.d.ts.map +1 -0
- package/dist/cli-parser.js +48 -0
- package/dist/cli-parser.js.map +1 -0
- package/dist/lattice-server.d.ts +70 -0
- package/dist/lattice-server.d.ts.map +1 -0
- package/dist/lattice-server.js +969 -0
- package/dist/lattice-server.js.map +1 -0
- package/dist/mcp-server/index.d.ts +3 -0
- package/dist/mcp-server/index.d.ts.map +1 -0
- package/dist/mcp-server/index.js +190 -0
- package/dist/mcp-server/index.js.map +1 -0
- package/dist/mcp-server/lattice-tools.d.ts +15 -0
- package/dist/mcp-server/lattice-tools.d.ts.map +1 -0
- package/dist/mcp-server/lattice-tools.js +366 -0
- package/dist/mcp-server/lattice-tools.js.map +1 -0
- package/dist/middleware/cors-setup.d.ts +7 -0
- package/dist/middleware/cors-setup.d.ts.map +1 -0
- package/dist/middleware/cors-setup.js +8 -0
- package/dist/middleware/cors-setup.js.map +1 -0
- package/dist/middleware/error-handler.d.ts +4 -0
- package/dist/middleware/error-handler.d.ts.map +1 -0
- package/dist/middleware/error-handler.js +27 -0
- package/dist/middleware/error-handler.js.map +1 -0
- package/dist/middleware/query-parser.d.ts +11 -0
- package/dist/middleware/query-parser.d.ts.map +1 -0
- package/dist/middleware/query-parser.js +68 -0
- package/dist/middleware/query-parser.js.map +1 -0
- package/dist/middleware/request-logger.d.ts +4 -0
- package/dist/middleware/request-logger.d.ts.map +1 -0
- package/dist/middleware/request-logger.js +6 -0
- package/dist/middleware/request-logger.js.map +1 -0
- package/dist/process-daemon/index.d.ts +14 -0
- package/dist/process-daemon/index.d.ts.map +1 -0
- package/dist/process-daemon/index.js +51 -0
- package/dist/process-daemon/index.js.map +1 -0
- package/dist/process-daemon/process-daemon.d.ts +101 -0
- package/dist/process-daemon/process-daemon.d.ts.map +1 -0
- package/dist/process-daemon/process-daemon.js +846 -0
- package/dist/process-daemon/process-daemon.js.map +1 -0
- package/dist/process-daemon/process-manager-client.d.ts +123 -0
- package/dist/process-daemon/process-manager-client.d.ts.map +1 -0
- package/dist/process-daemon/process-manager-client.js +329 -0
- package/dist/process-daemon/process-manager-client.js.map +1 -0
- package/dist/process-daemon/process-manager-interface.d.ts +61 -0
- package/dist/process-daemon/process-manager-interface.d.ts.map +1 -0
- package/dist/process-daemon/process-manager-interface.js +8 -0
- package/dist/process-daemon/process-manager-interface.js.map +1 -0
- package/dist/process-daemon/test-daemon.d.ts +12 -0
- package/dist/process-daemon/test-daemon.d.ts.map +1 -0
- package/dist/process-daemon/test-daemon.js +81 -0
- package/dist/process-daemon/test-daemon.js.map +1 -0
- package/dist/process-daemon/types.d.ts +97 -0
- package/dist/process-daemon/types.d.ts.map +1 -0
- package/dist/process-daemon/types.js +8 -0
- package/dist/process-daemon/types.js.map +1 -0
- package/dist/routes/analysis.routes.d.ts +13 -0
- package/dist/routes/analysis.routes.d.ts.map +1 -0
- package/dist/routes/analysis.routes.js +520 -0
- package/dist/routes/analysis.routes.js.map +1 -0
- package/dist/routes/config.routes.d.ts +4 -0
- package/dist/routes/config.routes.d.ts.map +1 -0
- package/dist/routes/config.routes.js +27 -0
- package/dist/routes/config.routes.js.map +1 -0
- package/dist/routes/conversation.routes.d.ts +43 -0
- package/dist/routes/conversation.routes.d.ts.map +1 -0
- package/dist/routes/conversation.routes.js +79 -0
- package/dist/routes/conversation.routes.js.map +1 -0
- package/dist/routes/filesystem.routes.d.ts +4 -0
- package/dist/routes/filesystem.routes.d.ts.map +1 -0
- package/dist/routes/filesystem.routes.js +86 -0
- package/dist/routes/filesystem.routes.js.map +1 -0
- package/dist/routes/insights.routes.d.ts +17 -0
- package/dist/routes/insights.routes.d.ts.map +1 -0
- package/dist/routes/insights.routes.js +633 -0
- package/dist/routes/insights.routes.js.map +1 -0
- package/dist/routes/lattice.routes.d.ts +10 -0
- package/dist/routes/lattice.routes.d.ts.map +1 -0
- package/dist/routes/lattice.routes.js +123 -0
- package/dist/routes/lattice.routes.js.map +1 -0
- package/dist/routes/license.routes.d.ts +3 -0
- package/dist/routes/license.routes.d.ts.map +1 -0
- package/dist/routes/license.routes.js +95 -0
- package/dist/routes/license.routes.js.map +1 -0
- package/dist/routes/log.routes.d.ts +3 -0
- package/dist/routes/log.routes.d.ts.map +1 -0
- package/dist/routes/log.routes.js +184 -0
- package/dist/routes/log.routes.js.map +1 -0
- package/dist/routes/pending-question.routes.d.ts +9 -0
- package/dist/routes/pending-question.routes.d.ts.map +1 -0
- package/dist/routes/pending-question.routes.js +162 -0
- package/dist/routes/pending-question.routes.js.map +1 -0
- package/dist/routes/permission.routes.d.ts +18 -0
- package/dist/routes/permission.routes.d.ts.map +1 -0
- package/dist/routes/permission.routes.js +370 -0
- package/dist/routes/permission.routes.js.map +1 -0
- package/dist/routes/process-events.routes.d.ts +9 -0
- package/dist/routes/process-events.routes.d.ts.map +1 -0
- package/dist/routes/process-events.routes.js +141 -0
- package/dist/routes/process-events.routes.js.map +1 -0
- package/dist/routes/prototype.routes.d.ts +9 -0
- package/dist/routes/prototype.routes.d.ts.map +1 -0
- package/dist/routes/prototype.routes.js +757 -0
- package/dist/routes/prototype.routes.js.map +1 -0
- package/dist/routes/question.routes.d.ts +8 -0
- package/dist/routes/question.routes.d.ts.map +1 -0
- package/dist/routes/question.routes.js +83 -0
- package/dist/routes/question.routes.js.map +1 -0
- package/dist/routes/session-control.routes.d.ts +29 -0
- package/dist/routes/session-control.routes.d.ts.map +1 -0
- package/dist/routes/session-control.routes.js +455 -0
- package/dist/routes/session-control.routes.js.map +1 -0
- package/dist/routes/session-lifecycle.routes.d.ts +21 -0
- package/dist/routes/session-lifecycle.routes.d.ts.map +1 -0
- package/dist/routes/session-lifecycle.routes.js +256 -0
- package/dist/routes/session-lifecycle.routes.js.map +1 -0
- package/dist/routes/session-query.routes.d.ts +25 -0
- package/dist/routes/session-query.routes.d.ts.map +1 -0
- package/dist/routes/session-query.routes.js +363 -0
- package/dist/routes/session-query.routes.js.map +1 -0
- package/dist/routes/session-stream.routes.d.ts +21 -0
- package/dist/routes/session-stream.routes.d.ts.map +1 -0
- package/dist/routes/session-stream.routes.js +235 -0
- package/dist/routes/session-stream.routes.js.map +1 -0
- package/dist/routes/streaming.routes.d.ts +4 -0
- package/dist/routes/streaming.routes.d.ts.map +1 -0
- package/dist/routes/streaming.routes.js +33 -0
- package/dist/routes/streaming.routes.js.map +1 -0
- package/dist/routes/system.routes.d.ts +7 -0
- package/dist/routes/system.routes.d.ts.map +1 -0
- package/dist/routes/system.routes.js +214 -0
- package/dist/routes/system.routes.js.map +1 -0
- package/dist/routes/walkthrough.routes.d.ts +19 -0
- package/dist/routes/walkthrough.routes.d.ts.map +1 -0
- package/dist/routes/walkthrough.routes.js +688 -0
- package/dist/routes/walkthrough.routes.js.map +1 -0
- package/dist/routes/working-directories.routes.d.ts +4 -0
- package/dist/routes/working-directories.routes.d.ts.map +1 -0
- package/dist/routes/working-directories.routes.js +25 -0
- package/dist/routes/working-directories.routes.js.map +1 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +34 -0
- package/dist/server.js.map +1 -0
- package/dist/services/ToolMetricsService.d.ts +53 -0
- package/dist/services/ToolMetricsService.d.ts.map +1 -0
- package/dist/services/ToolMetricsService.js +230 -0
- package/dist/services/ToolMetricsService.js.map +1 -0
- package/dist/services/claude-router-service.d.ts +19 -0
- package/dist/services/claude-router-service.d.ts.map +1 -0
- package/dist/services/claude-router-service.js +160 -0
- package/dist/services/claude-router-service.js.map +1 -0
- package/dist/services/commands-service.d.ts +20 -0
- package/dist/services/commands-service.d.ts.map +1 -0
- package/dist/services/commands-service.js +115 -0
- package/dist/services/commands-service.js.map +1 -0
- package/dist/services/connection-debug-logger.d.ts +85 -0
- package/dist/services/connection-debug-logger.d.ts.map +1 -0
- package/dist/services/connection-debug-logger.js +221 -0
- package/dist/services/connection-debug-logger.js.map +1 -0
- package/dist/services/debug-log.d.ts +6 -0
- package/dist/services/debug-log.d.ts.map +1 -0
- package/dist/services/debug-log.js +27 -0
- package/dist/services/debug-log.js.map +1 -0
- package/dist/services/gemini-service.d.ts +35 -0
- package/dist/services/gemini-service.d.ts.map +1 -0
- package/dist/services/gemini-service.js +256 -0
- package/dist/services/gemini-service.js.map +1 -0
- package/dist/services/infrastructure/config-service.d.ts +79 -0
- package/dist/services/infrastructure/config-service.d.ts.map +1 -0
- package/dist/services/infrastructure/config-service.js +431 -0
- package/dist/services/infrastructure/config-service.js.map +1 -0
- package/dist/services/infrastructure/cost-tracker.d.ts +112 -0
- package/dist/services/infrastructure/cost-tracker.d.ts.map +1 -0
- package/dist/services/infrastructure/cost-tracker.js +423 -0
- package/dist/services/infrastructure/cost-tracker.js.map +1 -0
- package/dist/services/infrastructure/file-system-service.d.ts +61 -0
- package/dist/services/infrastructure/file-system-service.d.ts.map +1 -0
- package/dist/services/infrastructure/file-system-service.js +348 -0
- package/dist/services/infrastructure/file-system-service.js.map +1 -0
- package/dist/services/infrastructure/log-formatter.d.ts +5 -0
- package/dist/services/infrastructure/log-formatter.d.ts.map +1 -0
- package/dist/services/infrastructure/log-formatter.js +77 -0
- package/dist/services/infrastructure/log-formatter.js.map +1 -0
- package/dist/services/infrastructure/log-stream-buffer.d.ts +11 -0
- package/dist/services/infrastructure/log-stream-buffer.d.ts.map +1 -0
- package/dist/services/infrastructure/log-stream-buffer.js +36 -0
- package/dist/services/infrastructure/log-stream-buffer.js.map +1 -0
- package/dist/services/infrastructure/logger.d.ts +71 -0
- package/dist/services/infrastructure/logger.d.ts.map +1 -0
- package/dist/services/infrastructure/logger.js +215 -0
- package/dist/services/infrastructure/logger.js.map +1 -0
- package/dist/services/infrastructure/service-registry.d.ts +86 -0
- package/dist/services/infrastructure/service-registry.d.ts.map +1 -0
- package/dist/services/infrastructure/service-registry.js +162 -0
- package/dist/services/infrastructure/service-registry.js.map +1 -0
- package/dist/services/infrastructure/stream-manager.d.ts +87 -0
- package/dist/services/infrastructure/stream-manager.d.ts.map +1 -0
- package/dist/services/infrastructure/stream-manager.js +436 -0
- package/dist/services/infrastructure/stream-manager.js.map +1 -0
- package/dist/services/infrastructure/timing.d.ts +72 -0
- package/dist/services/infrastructure/timing.d.ts.map +1 -0
- package/dist/services/infrastructure/timing.js +115 -0
- package/dist/services/infrastructure/timing.js.map +1 -0
- package/dist/services/insights/anthropic-service.d.ts +224 -0
- package/dist/services/insights/anthropic-service.d.ts.map +1 -0
- package/dist/services/insights/anthropic-service.js +1062 -0
- package/dist/services/insights/anthropic-service.js.map +1 -0
- package/dist/services/insights/insight-audit-repository.d.ts +119 -0
- package/dist/services/insights/insight-audit-repository.d.ts.map +1 -0
- package/dist/services/insights/insight-audit-repository.js +242 -0
- package/dist/services/insights/insight-audit-repository.js.map +1 -0
- package/dist/services/insights/insight-queue.d.ts +99 -0
- package/dist/services/insights/insight-queue.d.ts.map +1 -0
- package/dist/services/insights/insight-queue.js +277 -0
- package/dist/services/insights/insight-queue.js.map +1 -0
- package/dist/services/insights/insights-computer.d.ts +132 -0
- package/dist/services/insights/insights-computer.d.ts.map +1 -0
- package/dist/services/insights/insights-computer.js +936 -0
- package/dist/services/insights/insights-computer.js.map +1 -0
- package/dist/services/insights/insights-coordinator.d.ts +165 -0
- package/dist/services/insights/insights-coordinator.d.ts.map +1 -0
- package/dist/services/insights/insights-coordinator.js +1678 -0
- package/dist/services/insights/insights-coordinator.js.map +1 -0
- package/dist/services/insights/insights-event-log.d.ts +196 -0
- package/dist/services/insights/insights-event-log.d.ts.map +1 -0
- package/dist/services/insights/insights-event-log.js +319 -0
- package/dist/services/insights/insights-event-log.js.map +1 -0
- package/dist/services/lattice-service.d.ts +77 -0
- package/dist/services/lattice-service.d.ts.map +1 -0
- package/dist/services/lattice-service.js +195 -0
- package/dist/services/lattice-service.js.map +1 -0
- package/dist/services/license-service.d.ts +69 -0
- package/dist/services/license-service.d.ts.map +1 -0
- package/dist/services/license-service.js +330 -0
- package/dist/services/license-service.js.map +1 -0
- package/dist/services/mcp-config-generator.d.ts +32 -0
- package/dist/services/mcp-config-generator.d.ts.map +1 -0
- package/dist/services/mcp-config-generator.js +126 -0
- package/dist/services/mcp-config-generator.js.map +1 -0
- package/dist/services/message-filter.d.ts +22 -0
- package/dist/services/message-filter.d.ts.map +1 -0
- package/dist/services/message-filter.js +57 -0
- package/dist/services/message-filter.js.map +1 -0
- package/dist/services/notification-service.d.ts +45 -0
- package/dist/services/notification-service.d.ts.map +1 -0
- package/dist/services/notification-service.js +184 -0
- package/dist/services/notification-service.js.map +1 -0
- package/dist/services/pending-question-service.d.ts +97 -0
- package/dist/services/pending-question-service.d.ts.map +1 -0
- package/dist/services/pending-question-service.js +223 -0
- package/dist/services/pending-question-service.js.map +1 -0
- package/dist/services/permission-event-log.d.ts +136 -0
- package/dist/services/permission-event-log.d.ts.map +1 -0
- package/dist/services/permission-event-log.js +252 -0
- package/dist/services/permission-event-log.js.map +1 -0
- package/dist/services/permission-pattern-matcher.d.ts +82 -0
- package/dist/services/permission-pattern-matcher.d.ts.map +1 -0
- package/dist/services/permission-pattern-matcher.js +294 -0
- package/dist/services/permission-pattern-matcher.js.map +1 -0
- package/dist/services/permission-tracker.d.ts +67 -0
- package/dist/services/permission-tracker.d.ts.map +1 -0
- package/dist/services/permission-tracker.js +162 -0
- package/dist/services/permission-tracker.js.map +1 -0
- package/dist/services/process/claude-process-manager.d.ts +142 -0
- package/dist/services/process/claude-process-manager.d.ts.map +1 -0
- package/dist/services/process/claude-process-manager.js +1218 -0
- package/dist/services/process/claude-process-manager.js.map +1 -0
- package/dist/services/process/conversation-status-manager.d.ts +110 -0
- package/dist/services/process/conversation-status-manager.d.ts.map +1 -0
- package/dist/services/process/conversation-status-manager.js +349 -0
- package/dist/services/process/conversation-status-manager.js.map +1 -0
- package/dist/services/process/json-lines-parser.d.ts +19 -0
- package/dist/services/process/json-lines-parser.d.ts.map +1 -0
- package/dist/services/process/json-lines-parser.js +59 -0
- package/dist/services/process/json-lines-parser.js.map +1 -0
- package/dist/services/process/process-event-log.d.ts +263 -0
- package/dist/services/process/process-event-log.d.ts.map +1 -0
- package/dist/services/process/process-event-log.js +509 -0
- package/dist/services/process/process-event-log.js.map +1 -0
- package/dist/services/process/process-manager-factory.d.ts +109 -0
- package/dist/services/process/process-manager-factory.d.ts.map +1 -0
- package/dist/services/process/process-manager-factory.js +338 -0
- package/dist/services/process/process-manager-factory.js.map +1 -0
- package/dist/services/question-tracker.d.ts +51 -0
- package/dist/services/question-tracker.d.ts.map +1 -0
- package/dist/services/question-tracker.js +111 -0
- package/dist/services/question-tracker.js.map +1 -0
- package/dist/services/sessions/claude-history-reader.d.ts +139 -0
- package/dist/services/sessions/claude-history-reader.d.ts.map +1 -0
- package/dist/services/sessions/claude-history-reader.js +864 -0
- package/dist/services/sessions/claude-history-reader.js.map +1 -0
- package/dist/services/sessions/conversation-cache.d.ts +98 -0
- package/dist/services/sessions/conversation-cache.d.ts.map +1 -0
- package/dist/services/sessions/conversation-cache.js +329 -0
- package/dist/services/sessions/conversation-cache.js.map +1 -0
- package/dist/services/sessions/session-activity-watcher.d.ts +67 -0
- package/dist/services/sessions/session-activity-watcher.d.ts.map +1 -0
- package/dist/services/sessions/session-activity-watcher.js +236 -0
- package/dist/services/sessions/session-activity-watcher.js.map +1 -0
- package/dist/services/sessions/session-analysis-service.d.ts +72 -0
- package/dist/services/sessions/session-analysis-service.d.ts.map +1 -0
- package/dist/services/sessions/session-analysis-service.js +373 -0
- package/dist/services/sessions/session-analysis-service.js.map +1 -0
- package/dist/services/sessions/session-branch-service.d.ts +76 -0
- package/dist/services/sessions/session-branch-service.d.ts.map +1 -0
- package/dist/services/sessions/session-branch-service.js +355 -0
- package/dist/services/sessions/session-branch-service.js.map +1 -0
- package/dist/services/sessions/session-info-service.d.ts +455 -0
- package/dist/services/sessions/session-info-service.d.ts.map +1 -0
- package/dist/services/sessions/session-info-service.js +1640 -0
- package/dist/services/sessions/session-info-service.js.map +1 -0
- package/dist/services/sessions/session-marks-repository.d.ts +78 -0
- package/dist/services/sessions/session-marks-repository.d.ts.map +1 -0
- package/dist/services/sessions/session-marks-repository.js +263 -0
- package/dist/services/sessions/session-marks-repository.js.map +1 -0
- package/dist/services/sessions/session-marks-service.d.ts +137 -0
- package/dist/services/sessions/session-marks-service.d.ts.map +1 -0
- package/dist/services/sessions/session-marks-service.js +562 -0
- package/dist/services/sessions/session-marks-service.js.map +1 -0
- package/dist/services/sessions/session-review-service.d.ts +98 -0
- package/dist/services/sessions/session-review-service.d.ts.map +1 -0
- package/dist/services/sessions/session-review-service.js +629 -0
- package/dist/services/sessions/session-review-service.js.map +1 -0
- package/dist/services/sessions/turn-capture-service.d.ts +83 -0
- package/dist/services/sessions/turn-capture-service.d.ts.map +1 -0
- package/dist/services/sessions/turn-capture-service.js +477 -0
- package/dist/services/sessions/turn-capture-service.js.map +1 -0
- package/dist/services/sessions/turn-repository.d.ts +48 -0
- package/dist/services/sessions/turn-repository.d.ts.map +1 -0
- package/dist/services/sessions/turn-repository.js +103 -0
- package/dist/services/sessions/turn-repository.js.map +1 -0
- package/dist/services/walkthrough-service.d.ts +226 -0
- package/dist/services/walkthrough-service.d.ts.map +1 -0
- package/dist/services/walkthrough-service.js +1112 -0
- package/dist/services/walkthrough-service.js.map +1 -0
- package/dist/services/walkthrough-skill-prompt.d.ts +34 -0
- package/dist/services/walkthrough-skill-prompt.d.ts.map +1 -0
- package/dist/services/walkthrough-skill-prompt.js +313 -0
- package/dist/services/walkthrough-skill-prompt.js.map +1 -0
- package/dist/services/web-push-service.d.ts +48 -0
- package/dist/services/web-push-service.d.ts.map +1 -0
- package/dist/services/web-push-service.js +186 -0
- package/dist/services/web-push-service.js.map +1 -0
- package/dist/services/working-directories-service.d.ts +19 -0
- package/dist/services/working-directories-service.d.ts.map +1 -0
- package/dist/services/working-directories-service.js +103 -0
- package/dist/services/working-directories-service.js.map +1 -0
- package/dist/types/config.d.ts +122 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +21 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/express.d.ts +5 -0
- package/dist/types/express.d.ts.map +1 -0
- package/dist/types/express.js +2 -0
- package/dist/types/express.js.map +1 -0
- package/dist/types/index.d.ts +400 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +41 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/insights.d.ts +176 -0
- package/dist/types/insights.d.ts.map +1 -0
- package/dist/types/insights.js +23 -0
- package/dist/types/insights.js.map +1 -0
- package/dist/types/license.d.ts +70 -0
- package/dist/types/license.d.ts.map +1 -0
- package/dist/types/license.js +5 -0
- package/dist/types/license.js.map +1 -0
- package/dist/types/router-config.d.ts +13 -0
- package/dist/types/router-config.d.ts.map +1 -0
- package/dist/types/router-config.js +2 -0
- package/dist/types/router-config.js.map +1 -0
- package/dist/utils/constants.d.ts +26 -0
- package/dist/utils/constants.d.ts.map +1 -0
- package/dist/utils/constants.js +28 -0
- package/dist/utils/constants.js.map +1 -0
- package/dist/utils/machine-id.d.ts +7 -0
- package/dist/utils/machine-id.d.ts.map +1 -0
- package/dist/utils/machine-id.js +76 -0
- package/dist/utils/machine-id.js.map +1 -0
- package/dist/utils/server-startup.d.ts +11 -0
- package/dist/utils/server-startup.d.ts.map +1 -0
- package/dist/utils/server-startup.js +9 -0
- package/dist/utils/server-startup.js.map +1 -0
- package/dist/utils/update-check.d.ts +13 -0
- package/dist/utils/update-check.d.ts.map +1 -0
- package/dist/utils/update-check.js +90 -0
- package/dist/utils/update-check.js.map +1 -0
- package/dist/web/assets/ArchivedCardPrototype-S9ifiasa.js +5 -0
- package/dist/web/assets/BannerGallery-B__rJV6F.js +1 -0
- package/dist/web/assets/BannerPrototype-DBKP9Uiu.js +52 -0
- package/dist/web/assets/CodeHikeExperiment-B8jjWAFy.js +15 -0
- package/dist/web/assets/ContextTooltipVariations-DzklAFam.js +1 -0
- package/dist/web/assets/FontShowcasePrototype-KIMEWeP2.js +13 -0
- package/dist/web/assets/GeometricGallery-DddlWhHK.js +1 -0
- package/dist/web/assets/HistoryWalkthroughPrototype-DeniRRdw.js +18 -0
- package/dist/web/assets/InlineWalkthroughPrototype-Csd5r_Hk.js +1 -0
- package/dist/web/assets/MarkButtonPrototype-CxhxE0RP.js +1 -0
- package/dist/web/assets/MenuStylesPrototype-D7neA6YM.js +1 -0
- package/dist/web/assets/MomentCardVariations-2GT7GyFn.js +1 -0
- package/dist/web/assets/MomentHeaderVariations-DhGEw4XC.js +1 -0
- package/dist/web/assets/NarrativeWalkthroughDemo-B5C566fu.js +389 -0
- package/dist/web/assets/OutcomeVariations-BrZfsVcs.js +1 -0
- package/dist/web/assets/PermissionPatternPickerPrototype-CBOhe2Me.js +1 -0
- package/dist/web/assets/PermissionPrototype-BcF-a5an.js +1 -0
- package/dist/web/assets/PipelineGallery-BJhyM0rx.js +1 -0
- package/dist/web/assets/ScopeHeaderPrototype-GD1HNfaO.js +1 -0
- package/dist/web/assets/ScopeHeaderStylesPrototype-aa4uNJJ1.js +1 -0
- package/dist/web/assets/ScrollycodingPrototype-CKW1bf72.js +70 -0
- package/dist/web/assets/SectionHeaderVariations-DM8vUwfj.js +1 -0
- package/dist/web/assets/SemanticGallery-CtQEo7St.js +1 -0
- package/dist/web/assets/SessionCardPrototype-CgHCIMHe.js +1 -0
- package/dist/web/assets/SessionSidebarVariations-DMQL3Azj.js +3 -0
- package/dist/web/assets/SessionStartPrototype-Cwsv01Rr.js +1 -0
- package/dist/web/assets/SmartMenuPrototype-Br37Qbs_.js +1 -0
- package/dist/web/assets/StyleGallery-rZgrploB.js +1 -0
- package/dist/web/assets/TimelineCardPrototype-lzPc5mhe.js +19 -0
- package/dist/web/assets/ToolbarPrototype-Dm4BNZra.js +1 -0
- package/dist/web/assets/TooltipExperiment-Dy8QzTIP.js +13 -0
- package/dist/web/assets/WalkthroughCTAPrototype-uHoovujd.js +1 -0
- package/dist/web/assets/WalkthroughHeaderVariations-Do7Di1g1.js +1 -0
- package/dist/web/assets/WalkthroughShowcase-sGmRoPoM.js +112 -0
- package/dist/web/assets/arrow-right-D46Nx1mC.js +1 -0
- package/dist/web/assets/brain-BXIZKtOZ.js +1 -0
- package/dist/web/assets/grid-3x3-Cb81B62m.js +1 -0
- package/dist/web/assets/main-B1fyog77.js +321 -0
- package/dist/web/assets/main-C2PK2Klg.css +1 -0
- package/dist/web/assets/semantic-variations-Bd-W7ea2.js +1 -0
- package/dist/web/assets/target-Cf92wDTW.js +1 -0
- package/dist/web/favicon.png +0 -0
- package/dist/web/favicon.svg +22 -0
- package/dist/web/icon-192x192.png +0 -0
- package/dist/web/icon-512x512.png +0 -0
- package/dist/web/index.html +45 -0
- package/dist/web/manifest.json +61 -0
- package/package.json +192 -0
- package/scripts/postinstall.js +60 -0
|
@@ -0,0 +1,688 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Walkthrough Routes - API for generating AI-narrated code walkthroughs
|
|
3
|
+
*
|
|
4
|
+
* Two generation modes:
|
|
5
|
+
* 1. Inline (legacy): POST /generate - Single LLM call, fast but annotations don't work
|
|
6
|
+
* 2. Agentic: POST /spawn - Spawns hidden Claude session with walkthrough skill
|
|
7
|
+
*/
|
|
8
|
+
import { Router } from 'express';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
import os from 'os';
|
|
11
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
|
|
12
|
+
import { WalkthroughService, validateWalkthrough, fixLinkedPhraseLines } from '../services/walkthrough-service.js';
|
|
13
|
+
import { SessionInfoService } from '../services/sessions/session-info-service.js';
|
|
14
|
+
import { buildWalkthroughSkillPrompt, buildWalkthroughInitialPrompt, formatPrecomputedDataFile } from '../services/walkthrough-skill-prompt.js';
|
|
15
|
+
import { createLogger } from '../services/infrastructure/logger.js';
|
|
16
|
+
import { asStreamingId, asClaudeSessionId } from '../types/index.js';
|
|
17
|
+
const logger = createLogger('WalkthroughRoutes');
|
|
18
|
+
// Directory for walkthrough output files
|
|
19
|
+
const WALKTHROUGH_DIR = path.join(os.homedir(), '.claudia', 'walkthroughs');
|
|
20
|
+
// Track active walkthrough generations (scopeId -> generation info)
|
|
21
|
+
const activeWalkthroughGenerations = new Map();
|
|
22
|
+
export function createWalkthroughRoutes(deps) {
|
|
23
|
+
const { historyReader, processManager, streamManager, conversationStatusManager } = deps;
|
|
24
|
+
const router = Router();
|
|
25
|
+
const walkthroughService = new WalkthroughService(historyReader);
|
|
26
|
+
// Ensure walkthrough directory exists
|
|
27
|
+
if (!existsSync(WALKTHROUGH_DIR)) {
|
|
28
|
+
mkdirSync(WALKTHROUGH_DIR, { recursive: true });
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* GET /api/walkthrough/list
|
|
32
|
+
*
|
|
33
|
+
* List all generated walkthroughs across all sessions.
|
|
34
|
+
* Returns metadata about each walkthrough including session info.
|
|
35
|
+
*
|
|
36
|
+
* IMPORTANT: This must be defined BEFORE /:sessionId/* routes to avoid
|
|
37
|
+
* "list" being interpreted as a sessionId.
|
|
38
|
+
*/
|
|
39
|
+
router.get('/list', async (_req, res, next) => {
|
|
40
|
+
try {
|
|
41
|
+
const walkthroughs = await listAllWalkthroughs(historyReader);
|
|
42
|
+
res.json({ walkthroughs });
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
logger.error('Failed to list walkthroughs', {
|
|
46
|
+
error: error instanceof Error ? error.message : String(error),
|
|
47
|
+
});
|
|
48
|
+
next(error);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
/**
|
|
52
|
+
* POST /api/walkthrough/:sessionId/spawn
|
|
53
|
+
*
|
|
54
|
+
* Spawn a hidden Claude session to generate a walkthrough.
|
|
55
|
+
* The session runs with the walkthrough skill and writes output to a file.
|
|
56
|
+
*
|
|
57
|
+
* Request body:
|
|
58
|
+
* - scopeId: string - Identifier for this walkthrough scope
|
|
59
|
+
* - editIndices: number[] - Which edit calls to include
|
|
60
|
+
* - writeIndices: number[] - Which write calls to include
|
|
61
|
+
*
|
|
62
|
+
* Response:
|
|
63
|
+
* - streamingId: string - ID of the spawned session
|
|
64
|
+
* - outputPath: string - Where the walkthrough will be written
|
|
65
|
+
*/
|
|
66
|
+
router.post('/:sessionId/spawn', async (req, res, next) => {
|
|
67
|
+
const { sessionId } = req.params;
|
|
68
|
+
const { scopeId, editIndices, writeIndices } = req.body || {};
|
|
69
|
+
if (!scopeId) {
|
|
70
|
+
return res.status(400).json({ error: 'scopeId is required' });
|
|
71
|
+
}
|
|
72
|
+
// Check if already generating
|
|
73
|
+
const existing = activeWalkthroughGenerations.get(scopeId);
|
|
74
|
+
if (existing) {
|
|
75
|
+
logger.info('Walkthrough generation already in progress', {
|
|
76
|
+
scopeId,
|
|
77
|
+
streamingId: existing.streamingId,
|
|
78
|
+
elapsedMs: Date.now() - existing.startedAt,
|
|
79
|
+
});
|
|
80
|
+
return res.json({
|
|
81
|
+
status: 'in_progress',
|
|
82
|
+
streamingId: existing.streamingId,
|
|
83
|
+
outputPath: getOutputPath(sessionId, scopeId),
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
// Find the session JSONL file path
|
|
88
|
+
const sessionJsonlPath = await historyReader.getSessionFilePath(sessionId);
|
|
89
|
+
if (!sessionJsonlPath) {
|
|
90
|
+
return res.status(404).json({ error: 'Session file not found' });
|
|
91
|
+
}
|
|
92
|
+
const outputPath = getOutputPath(sessionId, scopeId);
|
|
93
|
+
const workingDirectory = path.dirname(sessionJsonlPath);
|
|
94
|
+
// Pre-compute file change data, filtered by scope if provided
|
|
95
|
+
const scope = (editIndices?.length || writeIndices?.length)
|
|
96
|
+
? { editIndices, writeIndices }
|
|
97
|
+
: undefined;
|
|
98
|
+
logger.info('Pre-computing walkthrough data', { sessionId, hasScope: !!scope });
|
|
99
|
+
const precomputedData = await walkthroughService.precomputeWalkthroughData(sessionId, scope);
|
|
100
|
+
// Write full pre-computed data to a file the model can read
|
|
101
|
+
const precomputedDataPath = path.join(WALKTHROUGH_DIR, `${sessionId}-${scopeId}-data.md`);
|
|
102
|
+
const dataFileContent = formatPrecomputedDataFile(precomputedData);
|
|
103
|
+
writeFileSync(precomputedDataPath, dataFileContent);
|
|
104
|
+
logger.info('Wrote pre-computed data file', {
|
|
105
|
+
path: precomputedDataPath,
|
|
106
|
+
sizeBytes: dataFileContent.length,
|
|
107
|
+
fileCount: precomputedData.files.length,
|
|
108
|
+
});
|
|
109
|
+
// Build the skill context with pre-computed data
|
|
110
|
+
const context = {
|
|
111
|
+
targetSessionId: sessionId,
|
|
112
|
+
scopeId,
|
|
113
|
+
editIndices: editIndices || [],
|
|
114
|
+
writeIndices: writeIndices || [],
|
|
115
|
+
outputPath,
|
|
116
|
+
sessionJsonlPath,
|
|
117
|
+
precomputedData,
|
|
118
|
+
precomputedDataPath,
|
|
119
|
+
};
|
|
120
|
+
const systemPrompt = buildWalkthroughSkillPrompt(context);
|
|
121
|
+
const initialPrompt = buildWalkthroughInitialPrompt(context);
|
|
122
|
+
logger.info('Spawning walkthrough generation session', {
|
|
123
|
+
targetSessionId: sessionId,
|
|
124
|
+
scopeId,
|
|
125
|
+
editCount: context.editIndices.length,
|
|
126
|
+
writeCount: context.writeIndices.length,
|
|
127
|
+
outputPath,
|
|
128
|
+
sessionJsonlPath,
|
|
129
|
+
workingDirectory,
|
|
130
|
+
});
|
|
131
|
+
// Spawn a hidden Claude session with Opus for quality walkthroughs
|
|
132
|
+
const result = await processManager.startConversation({
|
|
133
|
+
workingDirectory,
|
|
134
|
+
initialPrompt,
|
|
135
|
+
systemPrompt,
|
|
136
|
+
model: 'claude-opus-4-5-20251101',
|
|
137
|
+
permissionMode: 'bypassPermissions', // Let it read/write freely
|
|
138
|
+
});
|
|
139
|
+
// Track this generation
|
|
140
|
+
const streamingId = asStreamingId(result.streamingId);
|
|
141
|
+
const claudeSessionId = asClaudeSessionId(result.systemInit.session_id);
|
|
142
|
+
logger.info('Walkthrough session spawned successfully', {
|
|
143
|
+
streamingId,
|
|
144
|
+
claudeSessionId,
|
|
145
|
+
scopeId,
|
|
146
|
+
targetSessionId: sessionId,
|
|
147
|
+
});
|
|
148
|
+
// Mark session as archived immediately so it doesn't appear in sidebar
|
|
149
|
+
// Walkthrough generations are internal - users access them via the walkthrough UI
|
|
150
|
+
const sessionInfo = SessionInfoService.getInstance();
|
|
151
|
+
try {
|
|
152
|
+
await sessionInfo.updateSessionInfo(claudeSessionId, { archived: true });
|
|
153
|
+
logger.debug('Walkthrough session marked as archived (hidden from sidebar)', { claudeSessionId });
|
|
154
|
+
}
|
|
155
|
+
catch (e) {
|
|
156
|
+
logger.warn('Failed to archive walkthrough session', { claudeSessionId, error: e });
|
|
157
|
+
}
|
|
158
|
+
// Register with conversation status manager for tracking (but won't show in sidebar due to archived: true)
|
|
159
|
+
conversationStatusManager.registerActiveSession(streamingId, claudeSessionId, {
|
|
160
|
+
initialPrompt: `[Walkthrough] Generating for scope: ${scopeId}`,
|
|
161
|
+
workingDirectory: result.systemInit.cwd,
|
|
162
|
+
model: result.systemInit.model,
|
|
163
|
+
});
|
|
164
|
+
activeWalkthroughGenerations.set(scopeId, {
|
|
165
|
+
streamingId,
|
|
166
|
+
targetSessionId: sessionId,
|
|
167
|
+
scopeId,
|
|
168
|
+
startedAt: Date.now(),
|
|
169
|
+
});
|
|
170
|
+
// Listen for session completion to broadcast event
|
|
171
|
+
const handleProcessEnd = () => {
|
|
172
|
+
const generation = activeWalkthroughGenerations.get(scopeId);
|
|
173
|
+
if (generation?.streamingId === streamingId) {
|
|
174
|
+
activeWalkthroughGenerations.delete(scopeId);
|
|
175
|
+
const durationMs = Date.now() - generation.startedAt;
|
|
176
|
+
logger.info('Walkthrough generation completed', {
|
|
177
|
+
scopeId,
|
|
178
|
+
targetSessionId: sessionId,
|
|
179
|
+
durationMs,
|
|
180
|
+
});
|
|
181
|
+
// Validate the generated walkthrough
|
|
182
|
+
let validationPassed = false;
|
|
183
|
+
let validationErrors = [];
|
|
184
|
+
let validationWarnings = [];
|
|
185
|
+
if (existsSync(outputPath)) {
|
|
186
|
+
try {
|
|
187
|
+
const content = readFileSync(outputPath, 'utf-8');
|
|
188
|
+
const walkthrough = JSON.parse(content);
|
|
189
|
+
const validation = validateWalkthrough(walkthrough);
|
|
190
|
+
validationPassed = validation.passed;
|
|
191
|
+
validationErrors = validation.errors;
|
|
192
|
+
validationWarnings = validation.warnings;
|
|
193
|
+
logger.info('Post-generation validation', {
|
|
194
|
+
scopeId,
|
|
195
|
+
targetSessionId: sessionId,
|
|
196
|
+
passed: validationPassed,
|
|
197
|
+
errorCount: validationErrors.length,
|
|
198
|
+
warningCount: validationWarnings.length,
|
|
199
|
+
errors: validationErrors,
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
catch (parseError) {
|
|
203
|
+
validationErrors = ['Failed to parse generated walkthrough JSON'];
|
|
204
|
+
logger.error('Failed to parse generated walkthrough', {
|
|
205
|
+
scopeId,
|
|
206
|
+
targetSessionId: sessionId,
|
|
207
|
+
error: parseError instanceof Error ? parseError.message : String(parseError),
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
validationErrors = ['Output file not created'];
|
|
213
|
+
logger.warn('Walkthrough output file not created', { scopeId, outputPath });
|
|
214
|
+
}
|
|
215
|
+
// Broadcast completion event with validation results
|
|
216
|
+
streamManager.broadcast(streamingId, {
|
|
217
|
+
type: validationPassed ? 'walkthrough_complete' : 'walkthrough_validation_failed',
|
|
218
|
+
targetSessionId: sessionId,
|
|
219
|
+
scopeId,
|
|
220
|
+
outputPath,
|
|
221
|
+
validation: {
|
|
222
|
+
passed: validationPassed,
|
|
223
|
+
errors: validationErrors,
|
|
224
|
+
warnings: validationWarnings,
|
|
225
|
+
},
|
|
226
|
+
durationMs,
|
|
227
|
+
timestamp: new Date().toISOString(),
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
// Set up cleanup when process ends
|
|
232
|
+
logger.info('Setting up process-end listener', { streamingId, scopeId });
|
|
233
|
+
processManager.on('process-end', ({ streamingId: endedId }) => {
|
|
234
|
+
logger.info('process-end event received', { endedId, expectedId: streamingId, matches: endedId === streamingId });
|
|
235
|
+
if (endedId === streamingId) {
|
|
236
|
+
handleProcessEnd();
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
res.json({
|
|
240
|
+
status: 'started',
|
|
241
|
+
streamingId,
|
|
242
|
+
outputPath,
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
catch (error) {
|
|
246
|
+
logger.error('Failed to spawn walkthrough generation', {
|
|
247
|
+
sessionId,
|
|
248
|
+
scopeId,
|
|
249
|
+
error: error instanceof Error ? error.message : String(error),
|
|
250
|
+
});
|
|
251
|
+
next(error);
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
/**
|
|
255
|
+
* GET /api/walkthrough/:sessionId/status/:scopeId
|
|
256
|
+
*
|
|
257
|
+
* Check the status of a walkthrough generation.
|
|
258
|
+
* File-first: if output exists, it's complete (handles server restarts)
|
|
259
|
+
*/
|
|
260
|
+
router.get('/:sessionId/status/:scopeId', async (req, res) => {
|
|
261
|
+
const { sessionId, scopeId } = req.params;
|
|
262
|
+
const outputPath = getOutputPath(sessionId, scopeId);
|
|
263
|
+
// File-first: if output exists, it's complete regardless of in-memory state
|
|
264
|
+
// This handles server restarts during generation
|
|
265
|
+
if (existsSync(outputPath)) {
|
|
266
|
+
// Clean up stale in-memory tracking if present
|
|
267
|
+
if (activeWalkthroughGenerations.has(scopeId)) {
|
|
268
|
+
logger.info('Cleaning up stale generation tracking (file exists)', { scopeId });
|
|
269
|
+
activeWalkthroughGenerations.delete(scopeId);
|
|
270
|
+
}
|
|
271
|
+
// Include validation results so frontend can show warnings/errors
|
|
272
|
+
let validation = { passed: true, errors: [], warnings: [] };
|
|
273
|
+
try {
|
|
274
|
+
const content = readFileSync(outputPath, 'utf-8');
|
|
275
|
+
const walkthrough = JSON.parse(content);
|
|
276
|
+
validation = validateWalkthrough(walkthrough);
|
|
277
|
+
}
|
|
278
|
+
catch (error) {
|
|
279
|
+
validation = { passed: false, errors: ['Failed to parse walkthrough'], warnings: [] };
|
|
280
|
+
}
|
|
281
|
+
return res.json({
|
|
282
|
+
status: validation.passed ? 'complete' : 'complete_with_errors',
|
|
283
|
+
outputPath,
|
|
284
|
+
validation,
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
// Check in-memory tracking for in-progress generations
|
|
288
|
+
const generation = activeWalkthroughGenerations.get(scopeId);
|
|
289
|
+
if (generation) {
|
|
290
|
+
// Verify the session is still running
|
|
291
|
+
const isRunning = processManager.isSessionActive(generation.streamingId);
|
|
292
|
+
logger.debug('Checking generation status', {
|
|
293
|
+
scopeId,
|
|
294
|
+
streamingId: generation.streamingId,
|
|
295
|
+
isRunning,
|
|
296
|
+
elapsedMs: Date.now() - generation.startedAt,
|
|
297
|
+
});
|
|
298
|
+
if (!isRunning) {
|
|
299
|
+
// Session ended without writing file - clean up
|
|
300
|
+
logger.warn('Generation session ended without output', {
|
|
301
|
+
scopeId,
|
|
302
|
+
streamingId: generation.streamingId,
|
|
303
|
+
elapsedMs: Date.now() - generation.startedAt,
|
|
304
|
+
});
|
|
305
|
+
activeWalkthroughGenerations.delete(scopeId);
|
|
306
|
+
return res.json({
|
|
307
|
+
status: 'not_started',
|
|
308
|
+
outputPath,
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
return res.json({
|
|
312
|
+
status: 'in_progress',
|
|
313
|
+
streamingId: generation.streamingId,
|
|
314
|
+
elapsedMs: Date.now() - generation.startedAt,
|
|
315
|
+
outputPath,
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
return res.json({
|
|
319
|
+
status: 'not_started',
|
|
320
|
+
outputPath,
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
/**
|
|
324
|
+
* GET /api/walkthrough/:sessionId/result/:scopeId
|
|
325
|
+
*
|
|
326
|
+
* Get the generated walkthrough (reads from output file).
|
|
327
|
+
* Automatically injects computed diffs from the database for the full diff view.
|
|
328
|
+
* Optionally validates the walkthrough and includes validation results.
|
|
329
|
+
*/
|
|
330
|
+
router.get('/:sessionId/result/:scopeId', async (req, res) => {
|
|
331
|
+
const { sessionId, scopeId } = req.params;
|
|
332
|
+
const includeValidation = req.query.validate === 'true';
|
|
333
|
+
const outputPath = getOutputPath(sessionId, scopeId);
|
|
334
|
+
if (!existsSync(outputPath)) {
|
|
335
|
+
return res.status(404).json({ error: 'Walkthrough not found' });
|
|
336
|
+
}
|
|
337
|
+
try {
|
|
338
|
+
const content = readFileSync(outputPath, 'utf-8');
|
|
339
|
+
let walkthrough = JSON.parse(content);
|
|
340
|
+
// Fix linkedPhrase line numbers (LLMs often produce off-by-one errors)
|
|
341
|
+
walkthrough = fixLinkedPhraseLines(walkthrough);
|
|
342
|
+
// Inject computed diffs from database for full diff view
|
|
343
|
+
walkthrough = injectComputedDiffs(walkthrough, sessionId);
|
|
344
|
+
if (includeValidation) {
|
|
345
|
+
const validation = validateWalkthrough(walkthrough);
|
|
346
|
+
return res.json({ walkthrough, validation });
|
|
347
|
+
}
|
|
348
|
+
res.json(walkthrough);
|
|
349
|
+
}
|
|
350
|
+
catch (error) {
|
|
351
|
+
logger.error('Failed to read walkthrough file', {
|
|
352
|
+
sessionId,
|
|
353
|
+
scopeId,
|
|
354
|
+
outputPath,
|
|
355
|
+
error: error instanceof Error ? error.message : String(error),
|
|
356
|
+
});
|
|
357
|
+
res.status(500).json({ error: 'Failed to read walkthrough file' });
|
|
358
|
+
}
|
|
359
|
+
});
|
|
360
|
+
/**
|
|
361
|
+
* GET /api/walkthrough/:sessionId/validate/:scopeId
|
|
362
|
+
*
|
|
363
|
+
* Validate an existing walkthrough against quality requirements.
|
|
364
|
+
*/
|
|
365
|
+
router.get('/:sessionId/validate/:scopeId', async (req, res) => {
|
|
366
|
+
const { sessionId, scopeId } = req.params;
|
|
367
|
+
const outputPath = getOutputPath(sessionId, scopeId);
|
|
368
|
+
if (!existsSync(outputPath)) {
|
|
369
|
+
return res.status(404).json({ error: 'Walkthrough not found' });
|
|
370
|
+
}
|
|
371
|
+
try {
|
|
372
|
+
const content = readFileSync(outputPath, 'utf-8');
|
|
373
|
+
const walkthrough = JSON.parse(content);
|
|
374
|
+
const validation = validateWalkthrough(walkthrough);
|
|
375
|
+
logger.info('Validated walkthrough', {
|
|
376
|
+
sessionId,
|
|
377
|
+
scopeId,
|
|
378
|
+
passed: validation.passed,
|
|
379
|
+
errorCount: validation.errors.length,
|
|
380
|
+
warningCount: validation.warnings.length,
|
|
381
|
+
});
|
|
382
|
+
res.json(validation);
|
|
383
|
+
}
|
|
384
|
+
catch (error) {
|
|
385
|
+
logger.error('Failed to validate walkthrough', {
|
|
386
|
+
sessionId,
|
|
387
|
+
scopeId,
|
|
388
|
+
outputPath,
|
|
389
|
+
error: error instanceof Error ? error.message : String(error),
|
|
390
|
+
});
|
|
391
|
+
res.status(500).json({ error: 'Failed to validate walkthrough' });
|
|
392
|
+
}
|
|
393
|
+
});
|
|
394
|
+
/**
|
|
395
|
+
* POST /api/walkthrough/:sessionId/generate (LEGACY)
|
|
396
|
+
*
|
|
397
|
+
* Generate a walkthrough with a single LLM call.
|
|
398
|
+
* Kept for backwards compatibility but annotations don't work reliably.
|
|
399
|
+
*/
|
|
400
|
+
router.post('/:sessionId/generate', async (req, res, next) => {
|
|
401
|
+
const { sessionId } = req.params;
|
|
402
|
+
const { scopeId, editIndices, writeIndices } = req.body || {};
|
|
403
|
+
try {
|
|
404
|
+
logger.info('Generating walkthrough (inline mode)', { sessionId, scopeId, editCount: editIndices?.length, writeCount: writeIndices?.length });
|
|
405
|
+
const walkthrough = await walkthroughService.generateWalkthrough(sessionId, { editIndices, writeIndices });
|
|
406
|
+
res.json(walkthrough);
|
|
407
|
+
}
|
|
408
|
+
catch (error) {
|
|
409
|
+
logger.error('Failed to generate walkthrough', {
|
|
410
|
+
sessionId,
|
|
411
|
+
error: error instanceof Error ? error.message : String(error),
|
|
412
|
+
});
|
|
413
|
+
next(error);
|
|
414
|
+
}
|
|
415
|
+
});
|
|
416
|
+
/**
|
|
417
|
+
* GET /api/walkthrough/:sessionId/scope
|
|
418
|
+
*
|
|
419
|
+
* Analyze the session and suggest conceptual groupings for walkthroughs.
|
|
420
|
+
* Uses Haiku for fast analysis (~2-3s). Results are cached.
|
|
421
|
+
*
|
|
422
|
+
* Query params:
|
|
423
|
+
* refresh=true - Force re-analysis, ignore cache
|
|
424
|
+
*
|
|
425
|
+
* Response includes:
|
|
426
|
+
* cachedAt: ISO timestamp when analysis was generated (if from cache)
|
|
427
|
+
* cachedAtTurn: Turn count when analysis was generated (if from cache)
|
|
428
|
+
* currentTurnCount: Current session turn count
|
|
429
|
+
* isStale: true if session has more turns than when cached
|
|
430
|
+
*/
|
|
431
|
+
router.get('/:sessionId/scope', async (req, res, next) => {
|
|
432
|
+
const { sessionId } = req.params;
|
|
433
|
+
// Express may parse query as boolean or string depending on qs settings
|
|
434
|
+
const forceRefresh = req.query.refresh === 'true' || req.query.refresh === true;
|
|
435
|
+
const sessionInfoService = SessionInfoService.getInstance();
|
|
436
|
+
try {
|
|
437
|
+
// Get current session turn count
|
|
438
|
+
const details = await historyReader.fetchConversationDirect(sessionId);
|
|
439
|
+
const currentTurnCount = details?.messages?.filter((m) => m.type === 'user').length || 0;
|
|
440
|
+
// Check cache
|
|
441
|
+
const cached = sessionInfoService.getWalkthroughScopeCache(sessionId);
|
|
442
|
+
// Return cached if not forcing refresh
|
|
443
|
+
if (!forceRefresh && cached) {
|
|
444
|
+
const isStale = currentTurnCount > cached.turnCount;
|
|
445
|
+
logger.info('Returning cached walkthrough scope', {
|
|
446
|
+
sessionId,
|
|
447
|
+
cachedAtTurn: cached.turnCount,
|
|
448
|
+
currentTurnCount,
|
|
449
|
+
isStale
|
|
450
|
+
});
|
|
451
|
+
return res.json({
|
|
452
|
+
...cached.analysis,
|
|
453
|
+
cachedAt: cached.generatedAt,
|
|
454
|
+
cachedAtTurn: cached.turnCount,
|
|
455
|
+
currentTurnCount,
|
|
456
|
+
isStale,
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
// Extract previous groupings for stability (skip 'complete-session')
|
|
460
|
+
let previousGroupings;
|
|
461
|
+
if (cached?.analysis) {
|
|
462
|
+
const cachedAnalysis = cached.analysis;
|
|
463
|
+
if (cachedAnalysis.options) {
|
|
464
|
+
previousGroupings = cachedAnalysis.options
|
|
465
|
+
.filter(o => o.id !== 'complete-session')
|
|
466
|
+
.map(o => ({
|
|
467
|
+
id: o.id,
|
|
468
|
+
title: o.title,
|
|
469
|
+
description: o.description,
|
|
470
|
+
editIndices: o.editIndices || [],
|
|
471
|
+
writeIndices: o.writeIndices || [],
|
|
472
|
+
}));
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
logger.info('Analyzing walkthrough scope', {
|
|
476
|
+
sessionId,
|
|
477
|
+
forceRefresh,
|
|
478
|
+
previousGroupingCount: previousGroupings?.length || 0,
|
|
479
|
+
});
|
|
480
|
+
const analysis = await walkthroughService.analyzeScope(sessionId, previousGroupings);
|
|
481
|
+
// Cache the result
|
|
482
|
+
sessionInfoService.setWalkthroughScopeCache(sessionId, currentTurnCount, analysis);
|
|
483
|
+
res.json({
|
|
484
|
+
...analysis,
|
|
485
|
+
cachedAt: new Date().toISOString(),
|
|
486
|
+
cachedAtTurn: currentTurnCount,
|
|
487
|
+
currentTurnCount,
|
|
488
|
+
isStale: false,
|
|
489
|
+
});
|
|
490
|
+
}
|
|
491
|
+
catch (error) {
|
|
492
|
+
logger.error('Failed to analyze walkthrough scope', {
|
|
493
|
+
sessionId,
|
|
494
|
+
error: error instanceof Error ? error.message : String(error),
|
|
495
|
+
});
|
|
496
|
+
next(error);
|
|
497
|
+
}
|
|
498
|
+
});
|
|
499
|
+
/**
|
|
500
|
+
* GET /api/walkthrough/:sessionId/preview
|
|
501
|
+
*
|
|
502
|
+
* Quick preview - stats about the session's changes.
|
|
503
|
+
*/
|
|
504
|
+
router.get('/:sessionId/preview', async (req, res, next) => {
|
|
505
|
+
const { sessionId } = req.params;
|
|
506
|
+
try {
|
|
507
|
+
const details = await historyReader.fetchConversationDirect(sessionId);
|
|
508
|
+
if (!details || !details.messages) {
|
|
509
|
+
return res.status(404).json({ error: 'Session not found' });
|
|
510
|
+
}
|
|
511
|
+
const messages = details.messages;
|
|
512
|
+
// Count edits and writes
|
|
513
|
+
let editCount = 0;
|
|
514
|
+
let writeCount = 0;
|
|
515
|
+
const filesModified = new Set();
|
|
516
|
+
for (const msg of messages) {
|
|
517
|
+
if (msg.type === 'assistant') {
|
|
518
|
+
const content = msg.message.content;
|
|
519
|
+
if (Array.isArray(content)) {
|
|
520
|
+
for (const block of content) {
|
|
521
|
+
if (block.type === 'tool_use') {
|
|
522
|
+
if (block.name === 'Edit' && block.input) {
|
|
523
|
+
editCount++;
|
|
524
|
+
filesModified.add(block.input.file_path);
|
|
525
|
+
}
|
|
526
|
+
else if (block.name === 'Write' && block.input) {
|
|
527
|
+
writeCount++;
|
|
528
|
+
filesModified.add(block.input.file_path);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
// Get first user message as title
|
|
536
|
+
let userRequest = '';
|
|
537
|
+
for (const msg of messages) {
|
|
538
|
+
if (msg.type === 'user') {
|
|
539
|
+
const content = msg.message.content;
|
|
540
|
+
if (typeof content === 'string') {
|
|
541
|
+
userRequest = content.slice(0, 200);
|
|
542
|
+
break;
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
res.json({
|
|
547
|
+
sessionId,
|
|
548
|
+
editCount,
|
|
549
|
+
writeCount,
|
|
550
|
+
totalChanges: editCount + writeCount,
|
|
551
|
+
filesModified: Array.from(filesModified).map((f) => f.replace(/^\/home\/jason\/(claudia|cui-custom)\//, '')),
|
|
552
|
+
userRequest,
|
|
553
|
+
canGenerate: editCount + writeCount > 0,
|
|
554
|
+
});
|
|
555
|
+
}
|
|
556
|
+
catch (error) {
|
|
557
|
+
logger.error('Failed to preview walkthrough', {
|
|
558
|
+
sessionId,
|
|
559
|
+
error: error instanceof Error ? error.message : String(error),
|
|
560
|
+
});
|
|
561
|
+
next(error);
|
|
562
|
+
}
|
|
563
|
+
});
|
|
564
|
+
return router;
|
|
565
|
+
}
|
|
566
|
+
async function listAllWalkthroughs(historyReader) {
|
|
567
|
+
const { readdirSync, statSync } = await import('fs');
|
|
568
|
+
const sessionInfo = SessionInfoService.getInstance();
|
|
569
|
+
if (!existsSync(WALKTHROUGH_DIR)) {
|
|
570
|
+
return [];
|
|
571
|
+
}
|
|
572
|
+
const files = readdirSync(WALKTHROUGH_DIR).filter(f => f.endsWith('.json') && !f.includes('-data'));
|
|
573
|
+
const walkthroughs = [];
|
|
574
|
+
for (const file of files) {
|
|
575
|
+
try {
|
|
576
|
+
const filePath = path.join(WALKTHROUGH_DIR, file);
|
|
577
|
+
const stat = statSync(filePath);
|
|
578
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
579
|
+
const walkthrough = JSON.parse(content);
|
|
580
|
+
// Parse filename: {sessionId}-{scopeId}.json
|
|
581
|
+
const baseName = file.replace('.json', '');
|
|
582
|
+
// Session IDs are UUIDs (36 chars), scope IDs follow
|
|
583
|
+
const sessionId = baseName.slice(0, 36);
|
|
584
|
+
const scopeId = baseName.slice(37); // Skip the hyphen after UUID
|
|
585
|
+
// Get session info for context (both are async)
|
|
586
|
+
const session = await sessionInfo.getSessionInfo(sessionId);
|
|
587
|
+
const insights = await sessionInfo.getInsights(sessionId);
|
|
588
|
+
walkthroughs.push({
|
|
589
|
+
sessionId,
|
|
590
|
+
scopeId,
|
|
591
|
+
title: walkthrough.title || scopeId,
|
|
592
|
+
summary: walkthrough.summary || '',
|
|
593
|
+
generatedAt: stat.mtime.toISOString(),
|
|
594
|
+
fileSizeKb: Math.round(stat.size / 1024),
|
|
595
|
+
sectionCount: walkthrough.sections?.length || 0,
|
|
596
|
+
sessionPurpose: insights?.purpose || undefined,
|
|
597
|
+
sessionName: session?.custom_name || undefined,
|
|
598
|
+
url: `/session/${sessionId}/walkthrough?scope=${encodeURIComponent(scopeId)}`,
|
|
599
|
+
});
|
|
600
|
+
}
|
|
601
|
+
catch (error) {
|
|
602
|
+
logger.warn('Failed to parse walkthrough file', { file, error });
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
// Sort by generation date, newest first
|
|
606
|
+
walkthroughs.sort((a, b) => new Date(b.generatedAt).getTime() - new Date(a.generatedAt).getTime());
|
|
607
|
+
return walkthroughs;
|
|
608
|
+
}
|
|
609
|
+
/**
|
|
610
|
+
* Get the output file path for a walkthrough
|
|
611
|
+
*/
|
|
612
|
+
function getOutputPath(sessionId, scopeId) {
|
|
613
|
+
const safeScope = scopeId.replace(/[^a-zA-Z0-9_-]/g, '_');
|
|
614
|
+
return path.join(WALKTHROUGH_DIR, `${sessionId}-${safeScope}.json`);
|
|
615
|
+
}
|
|
616
|
+
/**
|
|
617
|
+
* Compute file diffs from the turn_file_changes table.
|
|
618
|
+
* Returns a map of file path -> computed diff data.
|
|
619
|
+
*/
|
|
620
|
+
function computeFileDiffs(sessionId) {
|
|
621
|
+
const sessionInfo = SessionInfoService.getInstance();
|
|
622
|
+
const fileChanges = sessionInfo.getFileChanges(sessionId);
|
|
623
|
+
const diffsByFile = new Map();
|
|
624
|
+
for (const change of fileChanges) {
|
|
625
|
+
const relativePath = change.filePath
|
|
626
|
+
.replace(/^\/home\/jason\/(claudia|cui-custom)\//, '')
|
|
627
|
+
.replace(/^\/home\/jason\//, '~/');
|
|
628
|
+
if (!diffsByFile.has(change.filePath)) {
|
|
629
|
+
diffsByFile.set(change.filePath, {
|
|
630
|
+
file: change.filePath,
|
|
631
|
+
relativePath,
|
|
632
|
+
allBefore: '',
|
|
633
|
+
allAfter: '',
|
|
634
|
+
linesAdded: 0,
|
|
635
|
+
linesRemoved: 0,
|
|
636
|
+
editCount: 0,
|
|
637
|
+
writeCount: 0,
|
|
638
|
+
});
|
|
639
|
+
}
|
|
640
|
+
const diff = diffsByFile.get(change.filePath);
|
|
641
|
+
// Accumulate before/after content
|
|
642
|
+
if (change.oldString) {
|
|
643
|
+
diff.allBefore += (diff.allBefore ? '\n// ---\n' : '') + change.oldString;
|
|
644
|
+
}
|
|
645
|
+
diff.allAfter += (diff.allAfter ? '\n// ---\n' : '') + change.newString;
|
|
646
|
+
// Count changes
|
|
647
|
+
if (change.toolName === 'Edit') {
|
|
648
|
+
diff.editCount++;
|
|
649
|
+
}
|
|
650
|
+
else {
|
|
651
|
+
diff.writeCount++;
|
|
652
|
+
}
|
|
653
|
+
// Compute line stats
|
|
654
|
+
const newLines = (change.newString.match(/\n/g) || []).length + 1;
|
|
655
|
+
const oldLines = change.oldString ? (change.oldString.match(/\n/g) || []).length + 1 : 0;
|
|
656
|
+
if (change.toolName === 'Write') {
|
|
657
|
+
diff.linesAdded += newLines;
|
|
658
|
+
}
|
|
659
|
+
else {
|
|
660
|
+
diff.linesAdded += Math.max(0, newLines - oldLines);
|
|
661
|
+
diff.linesRemoved += Math.max(0, oldLines - newLines);
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
return diffsByFile;
|
|
665
|
+
}
|
|
666
|
+
/**
|
|
667
|
+
* Inject computed diffs into a walkthrough response.
|
|
668
|
+
* Adds `computedDiffs` field with aggregated file change data.
|
|
669
|
+
*/
|
|
670
|
+
function injectComputedDiffs(walkthrough, sessionId) {
|
|
671
|
+
const diffs = computeFileDiffs(sessionId);
|
|
672
|
+
// Convert to array for JSON
|
|
673
|
+
const computedDiffs = Array.from(diffs.values()).map(d => ({
|
|
674
|
+
file: d.relativePath,
|
|
675
|
+
fullPath: d.file,
|
|
676
|
+
allBefore: d.allBefore,
|
|
677
|
+
allAfter: d.allAfter,
|
|
678
|
+
linesAdded: d.linesAdded,
|
|
679
|
+
linesRemoved: d.linesRemoved,
|
|
680
|
+
editCount: d.editCount,
|
|
681
|
+
writeCount: d.writeCount,
|
|
682
|
+
}));
|
|
683
|
+
return {
|
|
684
|
+
...walkthrough,
|
|
685
|
+
computedDiffs,
|
|
686
|
+
};
|
|
687
|
+
}
|
|
688
|
+
//# sourceMappingURL=walkthrough.routes.js.map
|