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,846 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Process Daemon - Long-running process that owns Claude CLI PTY processes
|
|
3
|
+
*
|
|
4
|
+
* This daemon runs independently of the web server and survives nodemon restarts.
|
|
5
|
+
* It communicates with cui-server via Unix socket IPC.
|
|
6
|
+
*/
|
|
7
|
+
import * as pty from 'node-pty';
|
|
8
|
+
import * as net from 'net';
|
|
9
|
+
import * as fs from 'fs';
|
|
10
|
+
import { spawn } from 'child_process';
|
|
11
|
+
import { EventEmitter } from 'events';
|
|
12
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
13
|
+
import path from 'path';
|
|
14
|
+
import os from 'os';
|
|
15
|
+
import { existsSync } from 'fs';
|
|
16
|
+
import { fileURLToPath } from 'url';
|
|
17
|
+
// ESM equivalent of __dirname
|
|
18
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
19
|
+
const __dirname = path.dirname(__filename);
|
|
20
|
+
import { JsonLinesParser } from '../services/process/json-lines-parser.js';
|
|
21
|
+
import { LatticeError } from '../types/index.js';
|
|
22
|
+
import { DEFAULT_SOCKET_PATH, } from './types.js';
|
|
23
|
+
/**
|
|
24
|
+
* Expand tilde (~) in paths to the user's home directory.
|
|
25
|
+
*/
|
|
26
|
+
function expandTilde(filePath) {
|
|
27
|
+
if (filePath === '~' || filePath.startsWith('~/')) {
|
|
28
|
+
return path.join(os.homedir(), filePath.slice(1));
|
|
29
|
+
}
|
|
30
|
+
return filePath;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Simple console logger for daemon (avoids importing pino for standalone operation)
|
|
34
|
+
*/
|
|
35
|
+
const timestamp = () => new Date().toISOString();
|
|
36
|
+
const logger = {
|
|
37
|
+
info: (msg, data) => {
|
|
38
|
+
console.warn(`[${timestamp()}] [DAEMON] ${msg}`, data ? JSON.stringify(data) : '');
|
|
39
|
+
},
|
|
40
|
+
debug: (msg, data) => {
|
|
41
|
+
if (process.env.LOG_LEVEL === 'debug') {
|
|
42
|
+
console.warn(`[${timestamp()}] [DAEMON:DEBUG] ${msg}`, data ? JSON.stringify(data) : '');
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
warn: (msg, data) => {
|
|
46
|
+
console.warn(`[${timestamp()}] [DAEMON:WARN] ${msg}`, data ? JSON.stringify(data) : '');
|
|
47
|
+
},
|
|
48
|
+
error: (msg, error, data) => {
|
|
49
|
+
console.error(`[${timestamp()}] [DAEMON:ERROR] ${msg}`, error, data ? JSON.stringify(data) : '');
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Process Daemon - owns and manages Claude CLI PTY processes
|
|
54
|
+
*/
|
|
55
|
+
export class ProcessDaemon extends EventEmitter {
|
|
56
|
+
processes = new Map();
|
|
57
|
+
outputBuffers = new Map();
|
|
58
|
+
timeouts = new Map();
|
|
59
|
+
conversationConfigs = new Map();
|
|
60
|
+
sessionIds = new Map(); // streamingId -> claude session_id
|
|
61
|
+
killedProcesses = new Set();
|
|
62
|
+
ipcServer = null;
|
|
63
|
+
connectedClients = new Set();
|
|
64
|
+
socketPath;
|
|
65
|
+
claudeExecutablePath;
|
|
66
|
+
envOverrides;
|
|
67
|
+
// Pending system init resolvers (streamingId -> {resolve, reject})
|
|
68
|
+
pendingSystemInits = new Map();
|
|
69
|
+
constructor(config = { socketPath: DEFAULT_SOCKET_PATH }) {
|
|
70
|
+
super();
|
|
71
|
+
this.socketPath = config.socketPath;
|
|
72
|
+
this.claudeExecutablePath = config.claudeExecutablePath || this.findClaudeExecutable();
|
|
73
|
+
this.envOverrides = config.envOverrides || {};
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Find the Claude executable
|
|
77
|
+
*/
|
|
78
|
+
findClaudeExecutable() {
|
|
79
|
+
// Check common installation paths including user-local installs
|
|
80
|
+
const userLocalPath = path.join(os.homedir(), '.local', 'bin', 'claude');
|
|
81
|
+
const candidatePaths = [
|
|
82
|
+
userLocalPath, // ~/.local/bin/claude (common for user installs)
|
|
83
|
+
'/usr/local/bin/claude',
|
|
84
|
+
'/usr/bin/claude',
|
|
85
|
+
];
|
|
86
|
+
for (const candidate of candidatePaths) {
|
|
87
|
+
if (existsSync(candidate)) {
|
|
88
|
+
return candidate;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
const pathEnv = process.env.PATH || '';
|
|
92
|
+
const pathDirs = pathEnv.split(path.delimiter);
|
|
93
|
+
for (const dir of pathDirs) {
|
|
94
|
+
if (dir.includes('node_modules'))
|
|
95
|
+
continue;
|
|
96
|
+
const candidate = path.join(dir, 'claude');
|
|
97
|
+
if (existsSync(candidate)) {
|
|
98
|
+
return candidate;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
throw new Error('Claude CLI not found.\n\n' +
|
|
102
|
+
'Claudia Orchestrator requires Claude Code CLI to be installed.\n' +
|
|
103
|
+
'Install it with: npm install -g @anthropic-ai/claude-code\n' +
|
|
104
|
+
'Then authenticate with: claude\n\n' +
|
|
105
|
+
'More info: https://docs.anthropic.com/en/docs/claude-code');
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Check if another daemon is already running by attempting to connect to the socket.
|
|
109
|
+
* Returns true if a daemon is actively listening, false if socket is stale or missing.
|
|
110
|
+
*/
|
|
111
|
+
async isExistingDaemonRunning() {
|
|
112
|
+
if (!fs.existsSync(this.socketPath)) {
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
return new Promise((resolve) => {
|
|
116
|
+
const testSocket = new net.Socket();
|
|
117
|
+
const timeout = setTimeout(() => {
|
|
118
|
+
testSocket.destroy();
|
|
119
|
+
resolve(false); // Timeout = no daemon responding
|
|
120
|
+
}, 1000);
|
|
121
|
+
testSocket.on('connect', () => {
|
|
122
|
+
clearTimeout(timeout);
|
|
123
|
+
testSocket.destroy();
|
|
124
|
+
resolve(true); // Connected = daemon is running
|
|
125
|
+
});
|
|
126
|
+
testSocket.on('error', () => {
|
|
127
|
+
clearTimeout(timeout);
|
|
128
|
+
testSocket.destroy();
|
|
129
|
+
resolve(false); // Error = socket is stale
|
|
130
|
+
});
|
|
131
|
+
testSocket.connect(this.socketPath);
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Start the IPC server
|
|
136
|
+
*/
|
|
137
|
+
async start() {
|
|
138
|
+
// Check if another daemon is already running
|
|
139
|
+
const existingDaemon = await this.isExistingDaemonRunning();
|
|
140
|
+
if (existingDaemon) {
|
|
141
|
+
logger.warn('Another daemon is already running on this socket', { socketPath: this.socketPath });
|
|
142
|
+
throw new Error(`Another daemon is already listening on ${this.socketPath}. Kill the existing daemon first or use a different socket path.`);
|
|
143
|
+
}
|
|
144
|
+
// Clean up stale socket file (we know no daemon is listening now)
|
|
145
|
+
if (fs.existsSync(this.socketPath)) {
|
|
146
|
+
logger.info('Removing stale socket file', { path: this.socketPath });
|
|
147
|
+
fs.unlinkSync(this.socketPath);
|
|
148
|
+
}
|
|
149
|
+
return new Promise((resolve, reject) => {
|
|
150
|
+
this.ipcServer = net.createServer((socket) => {
|
|
151
|
+
this.handleClientConnection(socket);
|
|
152
|
+
});
|
|
153
|
+
this.ipcServer.on('error', (err) => {
|
|
154
|
+
logger.error('IPC server error', err);
|
|
155
|
+
reject(err);
|
|
156
|
+
});
|
|
157
|
+
this.ipcServer.listen(this.socketPath, () => {
|
|
158
|
+
// Set socket permissions so any local user can connect
|
|
159
|
+
fs.chmodSync(this.socketPath, 0o777);
|
|
160
|
+
logger.info('Process daemon started', {
|
|
161
|
+
socketPath: this.socketPath,
|
|
162
|
+
claudePath: this.claudeExecutablePath,
|
|
163
|
+
});
|
|
164
|
+
resolve();
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Stop the daemon gracefully
|
|
170
|
+
*/
|
|
171
|
+
async stop() {
|
|
172
|
+
logger.info('Stopping process daemon...');
|
|
173
|
+
// Stop all active processes
|
|
174
|
+
const sessions = Array.from(this.processes.keys());
|
|
175
|
+
for (const streamingId of sessions) {
|
|
176
|
+
await this.stopConversation(streamingId);
|
|
177
|
+
}
|
|
178
|
+
// Close all client connections
|
|
179
|
+
for (const client of this.connectedClients) {
|
|
180
|
+
client.destroy();
|
|
181
|
+
}
|
|
182
|
+
this.connectedClients.clear();
|
|
183
|
+
// Close IPC server
|
|
184
|
+
if (this.ipcServer) {
|
|
185
|
+
await new Promise((resolve) => {
|
|
186
|
+
this.ipcServer.close(() => {
|
|
187
|
+
logger.info('IPC server closed');
|
|
188
|
+
resolve();
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
// Clean up socket file
|
|
193
|
+
if (fs.existsSync(this.socketPath)) {
|
|
194
|
+
fs.unlinkSync(this.socketPath);
|
|
195
|
+
}
|
|
196
|
+
logger.info('Process daemon stopped');
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Handle a new client connection
|
|
200
|
+
*/
|
|
201
|
+
handleClientConnection(socket) {
|
|
202
|
+
logger.info('Client connected');
|
|
203
|
+
this.connectedClients.add(socket);
|
|
204
|
+
let buffer = '';
|
|
205
|
+
socket.on('data', (data) => {
|
|
206
|
+
buffer += data.toString();
|
|
207
|
+
// Parse newline-delimited JSON messages
|
|
208
|
+
const lines = buffer.split('\n');
|
|
209
|
+
buffer = lines.pop() || '';
|
|
210
|
+
for (const line of lines) {
|
|
211
|
+
if (line.trim()) {
|
|
212
|
+
try {
|
|
213
|
+
const request = JSON.parse(line);
|
|
214
|
+
this.handleRequest(socket, request);
|
|
215
|
+
}
|
|
216
|
+
catch (err) {
|
|
217
|
+
logger.error('Failed to parse IPC message', err, { line });
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
socket.on('close', () => {
|
|
223
|
+
logger.info('Client disconnected');
|
|
224
|
+
this.connectedClients.delete(socket);
|
|
225
|
+
});
|
|
226
|
+
socket.on('error', (err) => {
|
|
227
|
+
logger.error('Client socket error', err);
|
|
228
|
+
this.connectedClients.delete(socket);
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Handle an IPC request
|
|
233
|
+
*/
|
|
234
|
+
async handleRequest(socket, request) {
|
|
235
|
+
logger.debug('Received request', { method: request.method, id: request.id });
|
|
236
|
+
try {
|
|
237
|
+
let result;
|
|
238
|
+
switch (request.method) {
|
|
239
|
+
case 'spawn':
|
|
240
|
+
result = await this.handleSpawn(request.params);
|
|
241
|
+
break;
|
|
242
|
+
case 'stop':
|
|
243
|
+
result = await this.handleStop(request.params);
|
|
244
|
+
break;
|
|
245
|
+
case 'forceKill':
|
|
246
|
+
result = this.handleForceKill(request.params);
|
|
247
|
+
break;
|
|
248
|
+
case 'interrupt':
|
|
249
|
+
result = this.handleInterrupt(request.params);
|
|
250
|
+
break;
|
|
251
|
+
case 'write':
|
|
252
|
+
result = this.handleWrite(request.params);
|
|
253
|
+
break;
|
|
254
|
+
case 'sendQuestionAnswer':
|
|
255
|
+
result = this.handleSendQuestionAnswer(request.params);
|
|
256
|
+
break;
|
|
257
|
+
case 'list':
|
|
258
|
+
result = { sessions: this.getActiveSessions() };
|
|
259
|
+
break;
|
|
260
|
+
case 'isActive':
|
|
261
|
+
result = { active: this.isSessionActive(request.params.streamingId) };
|
|
262
|
+
break;
|
|
263
|
+
default:
|
|
264
|
+
throw new Error(`Unknown method: ${request.method}`);
|
|
265
|
+
}
|
|
266
|
+
this.sendResponse(socket, { id: request.id, result });
|
|
267
|
+
}
|
|
268
|
+
catch (error) {
|
|
269
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
270
|
+
this.sendResponse(socket, {
|
|
271
|
+
id: request.id,
|
|
272
|
+
error: {
|
|
273
|
+
code: error instanceof LatticeError ? error.code : 'INTERNAL_ERROR',
|
|
274
|
+
message: err.message,
|
|
275
|
+
},
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Send a response to a specific client
|
|
281
|
+
*/
|
|
282
|
+
sendResponse(socket, response) {
|
|
283
|
+
socket.write(JSON.stringify(response) + '\n');
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Broadcast an event to all connected clients
|
|
287
|
+
*/
|
|
288
|
+
broadcastEvent(event) {
|
|
289
|
+
const message = JSON.stringify(event) + '\n';
|
|
290
|
+
for (const client of this.connectedClients) {
|
|
291
|
+
try {
|
|
292
|
+
client.write(message);
|
|
293
|
+
}
|
|
294
|
+
catch (err) {
|
|
295
|
+
logger.error('Failed to broadcast to client', err);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
// ============================================================================
|
|
300
|
+
// Process Management (extracted from ClaudeProcessManager)
|
|
301
|
+
// ============================================================================
|
|
302
|
+
async handleSpawn(params) {
|
|
303
|
+
const { config } = params;
|
|
304
|
+
const isResume = !!config.resumedSessionId;
|
|
305
|
+
const streamingId = uuidv4();
|
|
306
|
+
const spawnStartTime = Date.now();
|
|
307
|
+
logger.info('Spawning conversation', { streamingId, isResume });
|
|
308
|
+
// Store config
|
|
309
|
+
this.conversationConfigs.set(streamingId, config);
|
|
310
|
+
try {
|
|
311
|
+
const hasMultimodalContent = !!(config.initialContent && config.initialContent.length > 0);
|
|
312
|
+
// For multimodal, don't pass message as CLI arg - we'll send via stdin
|
|
313
|
+
const args = isResume && config.resumedSessionId
|
|
314
|
+
? this.buildResumeArgs({ sessionId: config.resumedSessionId, message: config.initialPrompt, permissionMode: config.permissionMode, streamingId, hasMultimodalContent })
|
|
315
|
+
: this.buildStartArgs(config, streamingId);
|
|
316
|
+
const cwd = expandTilde(config.workingDirectory || process.cwd());
|
|
317
|
+
logger.info('Spawn cwd', { streamingId, configWorkingDirectory: config.workingDirectory, resolvedCwd: cwd, processCwd: process.cwd() });
|
|
318
|
+
// Clean environment - destructure to remove unwanted vars
|
|
319
|
+
const { NODE_OPTIONS: _NO, VSCODE_INSPECTOR_OPTIONS: _VIO, CLAUDECODE: _CC, CLAUDE_CODE_ENTRYPOINT: _CCE, ...cleanEnv } = process.env;
|
|
320
|
+
const env = {
|
|
321
|
+
...cleanEnv,
|
|
322
|
+
...this.envOverrides,
|
|
323
|
+
CUI_STREAMING_ID: streamingId,
|
|
324
|
+
PWD: cwd,
|
|
325
|
+
INIT_CWD: cwd,
|
|
326
|
+
};
|
|
327
|
+
let managedProcess;
|
|
328
|
+
if (hasMultimodalContent) {
|
|
329
|
+
// Use piped spawn for multimodal - stdin will be a pipe, not a TTY
|
|
330
|
+
// This allows CLI to block waiting for stdin input
|
|
331
|
+
logger.info('Using piped spawn for multimodal content', { streamingId });
|
|
332
|
+
const childProcess = spawn(this.claudeExecutablePath, args, {
|
|
333
|
+
cwd,
|
|
334
|
+
env: env,
|
|
335
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
336
|
+
});
|
|
337
|
+
if (!childProcess.pid) {
|
|
338
|
+
throw new LatticeError('PROCESS_SPAWN_FAILED', 'Failed to spawn Claude process - no PID assigned', 500);
|
|
339
|
+
}
|
|
340
|
+
managedProcess = {
|
|
341
|
+
type: 'pipe',
|
|
342
|
+
child: childProcess,
|
|
343
|
+
pid: childProcess.pid,
|
|
344
|
+
write: (data) => childProcess.stdin?.write(data),
|
|
345
|
+
kill: (signal) => childProcess.kill(signal),
|
|
346
|
+
endStdin: () => childProcess.stdin?.end(),
|
|
347
|
+
};
|
|
348
|
+
this.processes.set(streamingId, managedProcess);
|
|
349
|
+
this.setupPipedProcessHandlers(streamingId, childProcess);
|
|
350
|
+
}
|
|
351
|
+
else {
|
|
352
|
+
// Use PTY for regular text - provides better terminal experience
|
|
353
|
+
const ptyProcess = pty.spawn(this.claudeExecutablePath, args, {
|
|
354
|
+
name: 'xterm-256color',
|
|
355
|
+
cols: 200,
|
|
356
|
+
rows: 50,
|
|
357
|
+
cwd,
|
|
358
|
+
env: env,
|
|
359
|
+
});
|
|
360
|
+
if (!ptyProcess.pid) {
|
|
361
|
+
throw new LatticeError('PROCESS_SPAWN_FAILED', 'Failed to spawn Claude process - no PID assigned', 500);
|
|
362
|
+
}
|
|
363
|
+
managedProcess = {
|
|
364
|
+
type: 'pty',
|
|
365
|
+
pty: ptyProcess,
|
|
366
|
+
pid: ptyProcess.pid,
|
|
367
|
+
write: (data) => ptyProcess.write(data),
|
|
368
|
+
kill: (signal) => ptyProcess.kill(signal),
|
|
369
|
+
};
|
|
370
|
+
this.processes.set(streamingId, managedProcess);
|
|
371
|
+
this.setupPtyProcessHandlers(streamingId, ptyProcess);
|
|
372
|
+
}
|
|
373
|
+
// Broadcast process-spawned event so clients can start buffering
|
|
374
|
+
this.broadcastEvent({
|
|
375
|
+
event: 'process-spawned',
|
|
376
|
+
data: { streamingId },
|
|
377
|
+
});
|
|
378
|
+
const spawnMs = Date.now() - spawnStartTime;
|
|
379
|
+
logger.info('Process spawned', { streamingId, pid: managedProcess.pid, spawnMs, type: managedProcess.type });
|
|
380
|
+
// For multimodal, send stdin message BEFORE waiting for init
|
|
381
|
+
// The CLI will process this and emit system init
|
|
382
|
+
if (hasMultimodalContent && config.initialContent) {
|
|
383
|
+
const contentBlocks = [
|
|
384
|
+
...config.initialContent,
|
|
385
|
+
...(config.initialPrompt ? [{ type: 'text', text: config.initialPrompt }] : [])
|
|
386
|
+
];
|
|
387
|
+
const stdinMessage = JSON.stringify({
|
|
388
|
+
type: 'user',
|
|
389
|
+
message: {
|
|
390
|
+
role: 'user',
|
|
391
|
+
content: contentBlocks
|
|
392
|
+
},
|
|
393
|
+
session_id: config.resumedSessionId || ''
|
|
394
|
+
});
|
|
395
|
+
logger.info('Sending multimodal content via stdin', {
|
|
396
|
+
streamingId,
|
|
397
|
+
contentBlockCount: contentBlocks.length,
|
|
398
|
+
messageLength: stdinMessage.length
|
|
399
|
+
});
|
|
400
|
+
managedProcess.write(stdinMessage + '\n');
|
|
401
|
+
// Close stdin to signal end of input - CLI will process and exit
|
|
402
|
+
managedProcess.endStdin?.();
|
|
403
|
+
}
|
|
404
|
+
// Wait for system init message
|
|
405
|
+
const systemInit = await this.waitForSystemInit(streamingId);
|
|
406
|
+
const totalSpawnMs = Date.now() - spawnStartTime;
|
|
407
|
+
logger.info('System init received', { streamingId, totalSpawnMs, waitForInitMs: totalSpawnMs - spawnMs });
|
|
408
|
+
// Store session ID mapping
|
|
409
|
+
this.sessionIds.set(streamingId, systemInit.session_id);
|
|
410
|
+
return { streamingId, systemInit };
|
|
411
|
+
}
|
|
412
|
+
catch (error) {
|
|
413
|
+
// Cleanup on failure
|
|
414
|
+
this.cleanup(streamingId);
|
|
415
|
+
throw error;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
async handleStop(params) {
|
|
419
|
+
const success = await this.stopConversation(params.streamingId);
|
|
420
|
+
return { success };
|
|
421
|
+
}
|
|
422
|
+
handleForceKill(params) {
|
|
423
|
+
const success = this.forceKillConversation(params.streamingId);
|
|
424
|
+
return { success };
|
|
425
|
+
}
|
|
426
|
+
handleInterrupt(params) {
|
|
427
|
+
const success = this.interruptConversation(params.streamingId);
|
|
428
|
+
return { success };
|
|
429
|
+
}
|
|
430
|
+
handleWrite(params) {
|
|
431
|
+
const process = this.processes.get(params.streamingId);
|
|
432
|
+
if (!process) {
|
|
433
|
+
logger.warn('handleWrite: process not found', { streamingId: params.streamingId });
|
|
434
|
+
return { success: false };
|
|
435
|
+
}
|
|
436
|
+
logger.info('handleWrite: writing to PTY', {
|
|
437
|
+
streamingId: params.streamingId,
|
|
438
|
+
messageLength: params.message.length,
|
|
439
|
+
messagePreview: params.message.slice(0, 100)
|
|
440
|
+
});
|
|
441
|
+
process.write(params.message + '\n');
|
|
442
|
+
return { success: true };
|
|
443
|
+
}
|
|
444
|
+
handleSendQuestionAnswer(params) {
|
|
445
|
+
const process = this.processes.get(params.streamingId);
|
|
446
|
+
const sessionId = this.sessionIds.get(params.streamingId);
|
|
447
|
+
if (!process || !sessionId) {
|
|
448
|
+
return { success: false };
|
|
449
|
+
}
|
|
450
|
+
// Build the tool result content per SDK docs:
|
|
451
|
+
// { questions: [...], answers: { "Question text?": "Selected label" } }
|
|
452
|
+
const toolResultContent = JSON.stringify({
|
|
453
|
+
questions: params.questions,
|
|
454
|
+
answers: params.answers
|
|
455
|
+
});
|
|
456
|
+
// Format as a tool_result message per Claude CLI stream-json protocol
|
|
457
|
+
const stdinMessage = JSON.stringify({
|
|
458
|
+
type: 'user',
|
|
459
|
+
message: {
|
|
460
|
+
role: 'user',
|
|
461
|
+
content: [{
|
|
462
|
+
type: 'tool_result',
|
|
463
|
+
tool_use_id: params.toolUseId,
|
|
464
|
+
content: toolResultContent
|
|
465
|
+
}]
|
|
466
|
+
},
|
|
467
|
+
session_id: sessionId,
|
|
468
|
+
});
|
|
469
|
+
process.write(stdinMessage + '\n');
|
|
470
|
+
return { success: true };
|
|
471
|
+
}
|
|
472
|
+
async stopConversation(streamingId) {
|
|
473
|
+
const process = this.processes.get(streamingId);
|
|
474
|
+
if (!process) {
|
|
475
|
+
return false;
|
|
476
|
+
}
|
|
477
|
+
try {
|
|
478
|
+
if (!this.killedProcesses.has(streamingId)) {
|
|
479
|
+
logger.info('Sending SIGTERM to process', { streamingId, pid: process.pid });
|
|
480
|
+
process.kill('SIGTERM');
|
|
481
|
+
this.killedProcesses.add(streamingId);
|
|
482
|
+
// Force kill after 3s if process hasn't exited
|
|
483
|
+
const killTimeout = setTimeout(() => {
|
|
484
|
+
try {
|
|
485
|
+
if (this.processes.has(streamingId)) {
|
|
486
|
+
logger.warn('Process not responding to SIGTERM, sending SIGKILL', { streamingId, pid: process.pid });
|
|
487
|
+
process.kill('SIGKILL');
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
catch {
|
|
491
|
+
// Process may have already exited
|
|
492
|
+
}
|
|
493
|
+
}, 3000);
|
|
494
|
+
const sessionTimeouts = this.timeouts.get(streamingId) || [];
|
|
495
|
+
sessionTimeouts.push(killTimeout);
|
|
496
|
+
this.timeouts.set(streamingId, sessionTimeouts);
|
|
497
|
+
}
|
|
498
|
+
// Note: cleanup happens in onExit handler, not here
|
|
499
|
+
logger.info('Stop signal sent', { streamingId });
|
|
500
|
+
return true;
|
|
501
|
+
}
|
|
502
|
+
catch (error) {
|
|
503
|
+
logger.error('Error stopping conversation', error, { streamingId });
|
|
504
|
+
return false;
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
forceKillConversation(streamingId) {
|
|
508
|
+
const process = this.processes.get(streamingId);
|
|
509
|
+
if (!process) {
|
|
510
|
+
return false;
|
|
511
|
+
}
|
|
512
|
+
try {
|
|
513
|
+
logger.warn('Force killing process with SIGKILL', { streamingId, pid: process.pid });
|
|
514
|
+
process.kill('SIGKILL');
|
|
515
|
+
this.killedProcesses.add(streamingId);
|
|
516
|
+
return true;
|
|
517
|
+
}
|
|
518
|
+
catch (error) {
|
|
519
|
+
logger.error('Error force killing conversation', error, { streamingId });
|
|
520
|
+
return false;
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
interruptConversation(streamingId) {
|
|
524
|
+
const process = this.processes.get(streamingId);
|
|
525
|
+
if (!process) {
|
|
526
|
+
return false;
|
|
527
|
+
}
|
|
528
|
+
try {
|
|
529
|
+
logger.info('Sending SIGINT to process', { streamingId, pid: process.pid });
|
|
530
|
+
process.kill('SIGINT');
|
|
531
|
+
return true;
|
|
532
|
+
}
|
|
533
|
+
catch (error) {
|
|
534
|
+
logger.error('Error interrupting conversation', error, { streamingId });
|
|
535
|
+
return false;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
getActiveSessions() {
|
|
539
|
+
return Array.from(this.processes.keys()).map(streamingId => ({
|
|
540
|
+
streamingId,
|
|
541
|
+
sessionId: this.sessionIds.get(streamingId) || ''
|
|
542
|
+
})).filter(s => s.sessionId); // Only return sessions we have IDs for
|
|
543
|
+
}
|
|
544
|
+
isSessionActive(streamingId) {
|
|
545
|
+
return this.processes.has(streamingId);
|
|
546
|
+
}
|
|
547
|
+
cleanup(streamingId) {
|
|
548
|
+
const timeouts = this.timeouts.get(streamingId);
|
|
549
|
+
if (timeouts) {
|
|
550
|
+
timeouts.forEach((t) => clearTimeout(t));
|
|
551
|
+
this.timeouts.delete(streamingId);
|
|
552
|
+
}
|
|
553
|
+
this.processes.delete(streamingId);
|
|
554
|
+
this.outputBuffers.delete(streamingId);
|
|
555
|
+
this.conversationConfigs.delete(streamingId);
|
|
556
|
+
this.sessionIds.delete(streamingId);
|
|
557
|
+
this.killedProcesses.delete(streamingId);
|
|
558
|
+
}
|
|
559
|
+
// ============================================================================
|
|
560
|
+
// Process Handlers
|
|
561
|
+
// ============================================================================
|
|
562
|
+
/**
|
|
563
|
+
* Setup handlers for PTY-based processes (normal text conversations)
|
|
564
|
+
*/
|
|
565
|
+
setupPtyProcessHandlers(streamingId, process) {
|
|
566
|
+
const parser = new JsonLinesParser();
|
|
567
|
+
this.outputBuffers.set(streamingId, '');
|
|
568
|
+
parser.on('data', (message) => {
|
|
569
|
+
// Skip echoed stdin messages - PTY echoes our input back
|
|
570
|
+
// BUT: tool_result messages are also type: 'user' (Claude API protocol:
|
|
571
|
+
// user = input TO Claude, assistant = output FROM Claude)
|
|
572
|
+
// We need to let tool_result messages through so the UI can update tool status
|
|
573
|
+
if (message?.type === 'user') {
|
|
574
|
+
const content = message.message?.content;
|
|
575
|
+
if (!content) {
|
|
576
|
+
return;
|
|
577
|
+
}
|
|
578
|
+
const isToolResult = Array.isArray(content) &&
|
|
579
|
+
content.some((block) => block.type === 'tool_result');
|
|
580
|
+
if (!isToolResult) {
|
|
581
|
+
// Filter non-tool-result user messages (echoed stdin)
|
|
582
|
+
return;
|
|
583
|
+
}
|
|
584
|
+
// Fall through to emit tool_result messages
|
|
585
|
+
logger.debug('Allowing tool_result message through', {
|
|
586
|
+
streamingId,
|
|
587
|
+
toolResultCount: content.filter(b => b.type === 'tool_result').length
|
|
588
|
+
});
|
|
589
|
+
}
|
|
590
|
+
this.handleClaudeMessage(streamingId, message);
|
|
591
|
+
});
|
|
592
|
+
parser.on('error', (error) => {
|
|
593
|
+
this.handleProcessError(streamingId, error);
|
|
594
|
+
});
|
|
595
|
+
process.onData((data) => {
|
|
596
|
+
// Strip ANSI escape sequences
|
|
597
|
+
const cleanedData = data.replace(/\x1b\[[0-9;]*[a-zA-Z]|\x1b\][^\x07]*\x07/g, '');
|
|
598
|
+
if (cleanedData.trim()) {
|
|
599
|
+
// Debug: log first chunk to see if we're getting any output
|
|
600
|
+
if (!this.outputBuffers.get(streamingId)) {
|
|
601
|
+
logger.debug('First PTY data received', {
|
|
602
|
+
streamingId,
|
|
603
|
+
dataLength: data.length,
|
|
604
|
+
cleanedLength: cleanedData.length,
|
|
605
|
+
preview: cleanedData.substring(0, 200)
|
|
606
|
+
});
|
|
607
|
+
this.outputBuffers.set(streamingId, 'received');
|
|
608
|
+
}
|
|
609
|
+
parser.write(cleanedData);
|
|
610
|
+
}
|
|
611
|
+
});
|
|
612
|
+
process.onExit(({ exitCode }) => {
|
|
613
|
+
this.handleProcessClose(streamingId, exitCode);
|
|
614
|
+
});
|
|
615
|
+
}
|
|
616
|
+
/**
|
|
617
|
+
* Setup handlers for piped child processes (multimodal with images)
|
|
618
|
+
* No stdin echo filtering needed since pipes don't echo
|
|
619
|
+
*/
|
|
620
|
+
setupPipedProcessHandlers(streamingId, childProcess) {
|
|
621
|
+
const parser = new JsonLinesParser();
|
|
622
|
+
this.outputBuffers.set(streamingId, '');
|
|
623
|
+
parser.on('data', (message) => {
|
|
624
|
+
// Piped processes don't echo stdin, but still filter non-tool-result user messages
|
|
625
|
+
if (message?.type === 'user') {
|
|
626
|
+
const content = message.message?.content;
|
|
627
|
+
if (!content) {
|
|
628
|
+
return;
|
|
629
|
+
}
|
|
630
|
+
const isToolResult = Array.isArray(content) &&
|
|
631
|
+
content.some((block) => block.type === 'tool_result');
|
|
632
|
+
if (!isToolResult) {
|
|
633
|
+
return;
|
|
634
|
+
}
|
|
635
|
+
logger.debug('Allowing tool_result message through (piped)', {
|
|
636
|
+
streamingId,
|
|
637
|
+
toolResultCount: content.filter(b => b.type === 'tool_result').length
|
|
638
|
+
});
|
|
639
|
+
}
|
|
640
|
+
this.handleClaudeMessage(streamingId, message);
|
|
641
|
+
});
|
|
642
|
+
parser.on('error', (error) => {
|
|
643
|
+
this.handleProcessError(streamingId, error);
|
|
644
|
+
});
|
|
645
|
+
childProcess.stdout?.on('data', (data) => {
|
|
646
|
+
const str = data.toString();
|
|
647
|
+
if (str.trim()) {
|
|
648
|
+
if (!this.outputBuffers.get(streamingId)) {
|
|
649
|
+
logger.debug('First piped stdout data received', {
|
|
650
|
+
streamingId,
|
|
651
|
+
dataLength: str.length,
|
|
652
|
+
preview: str.substring(0, 200)
|
|
653
|
+
});
|
|
654
|
+
this.outputBuffers.set(streamingId, 'received');
|
|
655
|
+
}
|
|
656
|
+
parser.write(str);
|
|
657
|
+
}
|
|
658
|
+
});
|
|
659
|
+
childProcess.stderr?.on('data', (data) => {
|
|
660
|
+
logger.warn('Claude CLI stderr (piped)', { streamingId, stderr: data.toString() });
|
|
661
|
+
});
|
|
662
|
+
childProcess.on('close', (code) => {
|
|
663
|
+
this.handleProcessClose(streamingId, code);
|
|
664
|
+
});
|
|
665
|
+
childProcess.on('error', (error) => {
|
|
666
|
+
this.handleProcessError(streamingId, error);
|
|
667
|
+
});
|
|
668
|
+
}
|
|
669
|
+
handleClaudeMessage(streamingId, message) {
|
|
670
|
+
// Check if this is the system init we're waiting for
|
|
671
|
+
if (message?.type === 'system' && 'subtype' in message && message.subtype === 'init') {
|
|
672
|
+
const initMessage = message;
|
|
673
|
+
logger.info('System init message received with MCP servers', {
|
|
674
|
+
streamingId,
|
|
675
|
+
mcpServerCount: initMessage.mcp_servers?.length || 0,
|
|
676
|
+
mcpServers: initMessage.mcp_servers,
|
|
677
|
+
});
|
|
678
|
+
const pending = this.pendingSystemInits.get(streamingId);
|
|
679
|
+
if (pending) {
|
|
680
|
+
clearTimeout(pending.timeout);
|
|
681
|
+
this.pendingSystemInits.delete(streamingId);
|
|
682
|
+
pending.resolve(initMessage);
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
// Broadcast to all connected clients
|
|
686
|
+
this.broadcastEvent({
|
|
687
|
+
event: 'claude-message',
|
|
688
|
+
data: { streamingId, message },
|
|
689
|
+
});
|
|
690
|
+
// Also emit locally for internal handlers
|
|
691
|
+
this.emit('claude-message', { streamingId, message });
|
|
692
|
+
}
|
|
693
|
+
handleProcessClose(streamingId, code) {
|
|
694
|
+
// Capture sessionId and pid BEFORE cleanup deletes them
|
|
695
|
+
const sessionId = this.sessionIds.get(streamingId);
|
|
696
|
+
const process = this.processes.get(streamingId);
|
|
697
|
+
const pid = process?.pid;
|
|
698
|
+
logger.info('Process closed', { streamingId, code, sessionId, pid });
|
|
699
|
+
// Reject any pending system init
|
|
700
|
+
const pending = this.pendingSystemInits.get(streamingId);
|
|
701
|
+
if (pending) {
|
|
702
|
+
clearTimeout(pending.timeout);
|
|
703
|
+
this.pendingSystemInits.delete(streamingId);
|
|
704
|
+
pending.reject(new LatticeError('CLAUDE_PROCESS_EXITED_EARLY', 'Claude CLI process exited before sending system init', 500));
|
|
705
|
+
}
|
|
706
|
+
this.cleanup(streamingId);
|
|
707
|
+
this.broadcastEvent({
|
|
708
|
+
event: 'process-closed',
|
|
709
|
+
data: { streamingId, code, sessionId, pid },
|
|
710
|
+
});
|
|
711
|
+
this.emit('process-closed', { streamingId, code, sessionId, pid });
|
|
712
|
+
}
|
|
713
|
+
handleProcessError(streamingId, error) {
|
|
714
|
+
logger.error('Process error', error, { streamingId });
|
|
715
|
+
this.broadcastEvent({
|
|
716
|
+
event: 'process-error',
|
|
717
|
+
data: { streamingId, error: error.message },
|
|
718
|
+
});
|
|
719
|
+
this.emit('process-error', { streamingId, error: error.message });
|
|
720
|
+
}
|
|
721
|
+
// ============================================================================
|
|
722
|
+
// Argument Building
|
|
723
|
+
// ============================================================================
|
|
724
|
+
buildBaseArgs() {
|
|
725
|
+
return ['-p'];
|
|
726
|
+
}
|
|
727
|
+
buildResumeArgs(config) {
|
|
728
|
+
const args = this.buildBaseArgs();
|
|
729
|
+
// For multimodal: no CLI arg message - full content sent via piped stdin
|
|
730
|
+
// For text-only: use the actual message as CLI arg (PTY spawn)
|
|
731
|
+
if (config.message && !config.hasMultimodalContent) {
|
|
732
|
+
args.push(config.message);
|
|
733
|
+
}
|
|
734
|
+
args.push('--resume', config.sessionId, '--output-format', 'stream-json', '--input-format', 'stream-json', '--verbose');
|
|
735
|
+
// Apply permission mode
|
|
736
|
+
this.applyPermissionMode(args, config.permissionMode, config.streamingId);
|
|
737
|
+
return args;
|
|
738
|
+
}
|
|
739
|
+
/**
|
|
740
|
+
* Apply permission mode flags to CLI args
|
|
741
|
+
* Modes:
|
|
742
|
+
* - "bypassPermissions" (default): Skip all permission prompts (--dangerously-skip-permissions)
|
|
743
|
+
* - "default": Delegate to MCP permission server via --permission-prompt-tool
|
|
744
|
+
* - "acceptEdits": Auto-accept file edits but prompt for other tools
|
|
745
|
+
* - "plan": Plan mode - research only, no edits
|
|
746
|
+
*/
|
|
747
|
+
applyPermissionMode(args, permissionMode, streamingId) {
|
|
748
|
+
switch (permissionMode) {
|
|
749
|
+
case 'default':
|
|
750
|
+
// Delegate permission decisions to our MCP permission server
|
|
751
|
+
this.applyMcpPermissionPrompt(args, streamingId);
|
|
752
|
+
break;
|
|
753
|
+
case 'acceptEdits':
|
|
754
|
+
args.push('--permission-mode', 'acceptEdits');
|
|
755
|
+
break;
|
|
756
|
+
case 'plan':
|
|
757
|
+
args.push('--permission-mode', 'plan');
|
|
758
|
+
break;
|
|
759
|
+
case 'bypassPermissions':
|
|
760
|
+
default:
|
|
761
|
+
// Default to bypass for backwards compatibility
|
|
762
|
+
args.push('--dangerously-skip-permissions');
|
|
763
|
+
break;
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
/**
|
|
767
|
+
* Configure MCP permission prompt tool for interactive permission handling
|
|
768
|
+
*/
|
|
769
|
+
applyMcpPermissionPrompt(args, streamingId) {
|
|
770
|
+
// Paths to our MCP servers
|
|
771
|
+
const mcpServerPath = path.join(__dirname, '..', 'mcp-server', 'index.js');
|
|
772
|
+
const claudiaToolsPath = path.join(__dirname, '..', 'mcp-server', 'claudia-tools.js');
|
|
773
|
+
// MCP server config - the server needs CUI_STREAMING_ID to associate permissions
|
|
774
|
+
const mcpConfig = {
|
|
775
|
+
mcpServers: {
|
|
776
|
+
'claudia-permissions': {
|
|
777
|
+
command: 'node',
|
|
778
|
+
args: [mcpServerPath],
|
|
779
|
+
env: {
|
|
780
|
+
CUI_STREAMING_ID: streamingId || 'unknown',
|
|
781
|
+
CUI_SERVER_URL: `http://localhost:${process.env.PORT || 3001}`,
|
|
782
|
+
},
|
|
783
|
+
},
|
|
784
|
+
'claudia-orchestrator': {
|
|
785
|
+
command: 'node',
|
|
786
|
+
args: [claudiaToolsPath],
|
|
787
|
+
env: {
|
|
788
|
+
CUI_STREAMING_ID: streamingId || 'unknown',
|
|
789
|
+
CUI_SERVER_URL: `http://localhost:${process.env.PORT || 3001}`,
|
|
790
|
+
},
|
|
791
|
+
},
|
|
792
|
+
},
|
|
793
|
+
};
|
|
794
|
+
args.push('--mcp-config', JSON.stringify(mcpConfig));
|
|
795
|
+
args.push('--permission-prompt-tool', 'mcp__claudia-permissions__permission_prompt');
|
|
796
|
+
logger.info('Applied MCP config', { streamingId, mcpServerPath, claudiaToolsPath });
|
|
797
|
+
}
|
|
798
|
+
buildStartArgs(config, streamingId) {
|
|
799
|
+
const args = this.buildBaseArgs();
|
|
800
|
+
// Add initial prompt as CLI arg - skip if multimodal content will be sent via stdin
|
|
801
|
+
const hasMultimodalContent = !!(config.initialContent && config.initialContent.length > 0);
|
|
802
|
+
if (config.initialPrompt && !hasMultimodalContent) {
|
|
803
|
+
args.push(config.initialPrompt);
|
|
804
|
+
}
|
|
805
|
+
args.push('--output-format', 'stream-json', '--input-format', 'stream-json', '--verbose');
|
|
806
|
+
if (config.model) {
|
|
807
|
+
args.push('--model', config.model);
|
|
808
|
+
}
|
|
809
|
+
if (config.allowedTools?.length) {
|
|
810
|
+
args.push('--allowedTools', config.allowedTools.join(','));
|
|
811
|
+
}
|
|
812
|
+
if (config.disallowedTools?.length) {
|
|
813
|
+
args.push('--disallowedTools', config.disallowedTools.join(','));
|
|
814
|
+
}
|
|
815
|
+
// Add system prompt with Claudia environment info
|
|
816
|
+
const claudiaEnvInfo = `
|
|
817
|
+
## Claudia Orchestrator Environment
|
|
818
|
+
|
|
819
|
+
You are running inside the Claudia orchestrator dashboard.
|
|
820
|
+
|
|
821
|
+
**Server logs** (for debugging issues):
|
|
822
|
+
- \`~/.claudia/logs/server.log\` - Express server logs
|
|
823
|
+
- \`~/.claudia/logs/daemon.log\` - Process daemon logs
|
|
824
|
+
`;
|
|
825
|
+
const systemPrompt = config.systemPrompt
|
|
826
|
+
? `${config.systemPrompt}\n${claudiaEnvInfo}`
|
|
827
|
+
: claudiaEnvInfo;
|
|
828
|
+
args.push('--system-prompt', systemPrompt);
|
|
829
|
+
// Apply permission mode
|
|
830
|
+
this.applyPermissionMode(args, config.permissionMode, streamingId);
|
|
831
|
+
return args;
|
|
832
|
+
}
|
|
833
|
+
// ============================================================================
|
|
834
|
+
// System Init Waiting
|
|
835
|
+
// ============================================================================
|
|
836
|
+
waitForSystemInit(streamingId) {
|
|
837
|
+
return new Promise((resolve, reject) => {
|
|
838
|
+
const timeout = setTimeout(() => {
|
|
839
|
+
this.pendingSystemInits.delete(streamingId);
|
|
840
|
+
reject(new LatticeError('SYSTEM_INIT_TIMEOUT', 'Timeout waiting for system initialization from Claude CLI', 500));
|
|
841
|
+
}, 60000);
|
|
842
|
+
this.pendingSystemInits.set(streamingId, { resolve, reject, timeout });
|
|
843
|
+
});
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
//# sourceMappingURL=process-daemon.js.map
|