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,757 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prototype routes - experimental features for testing and development.
|
|
3
|
+
*
|
|
4
|
+
* In production builds, these routes are gated and return 404 by default.
|
|
5
|
+
* They can be enabled by setting CLAUDIA_ENABLE_PROTOTYPES=true.
|
|
6
|
+
*/
|
|
7
|
+
import { Router } from 'express';
|
|
8
|
+
import sharp from 'sharp';
|
|
9
|
+
import Anthropic from '@anthropic-ai/sdk';
|
|
10
|
+
import { createLogger } from '../services/infrastructure/logger.js';
|
|
11
|
+
import { GoogleGenAI } from '@google/genai';
|
|
12
|
+
import { ConfigService } from '../services/infrastructure/config-service.js';
|
|
13
|
+
import { readFileSync, existsSync } from 'fs';
|
|
14
|
+
const logger = createLogger('PrototypeRoutes');
|
|
15
|
+
/**
|
|
16
|
+
* Middleware to gate prototype routes in production.
|
|
17
|
+
* Returns 404 unless CLAUDIA_ENABLE_PROTOTYPES=true.
|
|
18
|
+
*/
|
|
19
|
+
function prototypeGate(req, res, next) {
|
|
20
|
+
const isProduction = process.env.NODE_ENV === 'production';
|
|
21
|
+
const prototypesEnabled = process.env.CLAUDIA_ENABLE_PROTOTYPES === 'true';
|
|
22
|
+
if (isProduction && !prototypesEnabled) {
|
|
23
|
+
logger.debug('Prototype route blocked in production', {
|
|
24
|
+
path: req.path,
|
|
25
|
+
method: req.method,
|
|
26
|
+
});
|
|
27
|
+
res.status(404).json({ error: 'Not found' });
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
next();
|
|
31
|
+
}
|
|
32
|
+
// Rich color palette for diverse banners
|
|
33
|
+
const COLORS = [
|
|
34
|
+
'electric blue', 'hot pink', 'lime green', 'golden yellow', 'coral orange',
|
|
35
|
+
'deep purple', 'cyan', 'magenta', 'mint green', 'amber',
|
|
36
|
+
'crimson red', 'teal', 'lavender', 'peach', 'electric violet',
|
|
37
|
+
'neon orange', 'sky blue', 'rose pink', 'chartreuse', 'copper'
|
|
38
|
+
];
|
|
39
|
+
// Style seeds - different visual languages
|
|
40
|
+
const STYLE_SEEDS = [
|
|
41
|
+
'flowing and organic',
|
|
42
|
+
'sharp and angular',
|
|
43
|
+
'scattered particles',
|
|
44
|
+
'layered waves',
|
|
45
|
+
'crystalline shards',
|
|
46
|
+
'soft gradients',
|
|
47
|
+
'circuit-like traces',
|
|
48
|
+
'bold geometric',
|
|
49
|
+
'wispy and ethereal',
|
|
50
|
+
'dense and textured',
|
|
51
|
+
'minimal and sparse',
|
|
52
|
+
'dynamic and energetic'
|
|
53
|
+
];
|
|
54
|
+
// Composition hints
|
|
55
|
+
const COMPOSITIONS = [
|
|
56
|
+
'asymmetric, weighted left',
|
|
57
|
+
'asymmetric, weighted right',
|
|
58
|
+
'centered focal point',
|
|
59
|
+
'scattered across the frame',
|
|
60
|
+
'diagonal flow',
|
|
61
|
+
'horizontal bands',
|
|
62
|
+
'clustered elements'
|
|
63
|
+
];
|
|
64
|
+
function pickRandom(arr) {
|
|
65
|
+
return arr[Math.floor(Math.random() * arr.length)];
|
|
66
|
+
}
|
|
67
|
+
function pickTwo(arr) {
|
|
68
|
+
const first = pickRandom(arr);
|
|
69
|
+
let second = pickRandom(arr);
|
|
70
|
+
while (second === first && arr.length > 1) {
|
|
71
|
+
second = pickRandom(arr);
|
|
72
|
+
}
|
|
73
|
+
return [first, second];
|
|
74
|
+
}
|
|
75
|
+
// Prompt templates for banner generation
|
|
76
|
+
const PROMPT_TEMPLATES = {
|
|
77
|
+
neonSymbol: (mission, color) => `Add a glowing neon icon to this black image.
|
|
78
|
+
|
|
79
|
+
TASK: ${mission}
|
|
80
|
+
COLOR: ${color} glow
|
|
81
|
+
|
|
82
|
+
Requirements:
|
|
83
|
+
- Single bold central symbol
|
|
84
|
+
- Neon glow effect
|
|
85
|
+
- Keep the black background intact
|
|
86
|
+
- No text, no faces
|
|
87
|
+
- Tech/circuit aesthetic optional`,
|
|
88
|
+
horizontalNeon: (mission, color) => `Add a horizontal neon design element to this wide black banner.
|
|
89
|
+
|
|
90
|
+
TASK: ${mission}
|
|
91
|
+
COLOR: ${color} neon glow
|
|
92
|
+
|
|
93
|
+
Requirements:
|
|
94
|
+
- Design should flow horizontally across the banner
|
|
95
|
+
- Could be: flowing lines, circuit traces, abstract waves, or a stretched icon
|
|
96
|
+
- Strong neon glow effect with ${color} color
|
|
97
|
+
- Keep the black background
|
|
98
|
+
- No text, no faces
|
|
99
|
+
- Subtle tech/digital aesthetic`,
|
|
100
|
+
minimalGlyph: (mission, color) => `Add a minimal glowing glyph to this black banner.
|
|
101
|
+
|
|
102
|
+
TASK: ${mission}
|
|
103
|
+
COLOR: ${color} glow
|
|
104
|
+
|
|
105
|
+
Create a single, abstract symbol that represents the essence of this work.
|
|
106
|
+
- Centered in the horizontal space
|
|
107
|
+
- Bold but simple - 1-3 strokes maximum
|
|
108
|
+
- Strong ${color} neon glow
|
|
109
|
+
- Pure black background
|
|
110
|
+
- No text`,
|
|
111
|
+
abstractWave: (mission, color) => `Add an abstract wave pattern to this black banner.
|
|
112
|
+
|
|
113
|
+
TASK: ${mission}
|
|
114
|
+
COLOR: ${color}
|
|
115
|
+
|
|
116
|
+
Create a flowing horizontal wave or energy pattern:
|
|
117
|
+
- Spans the full width of the banner
|
|
118
|
+
- ${color} glowing effect
|
|
119
|
+
- Abstract, not literal
|
|
120
|
+
- Subtle gradient from edges to center
|
|
121
|
+
- Pure black background`,
|
|
122
|
+
circuitTrace: (mission, color) => `Add circuit board trace patterns to this black banner.
|
|
123
|
+
|
|
124
|
+
TASK: ${mission}
|
|
125
|
+
COLOR: ${color}
|
|
126
|
+
|
|
127
|
+
Design specifications:
|
|
128
|
+
- Horizontal circuit traces flowing left to right
|
|
129
|
+
- Small nodes/points at intersections
|
|
130
|
+
- ${color} neon glow
|
|
131
|
+
- Technical, digital aesthetic
|
|
132
|
+
- Black background`,
|
|
133
|
+
};
|
|
134
|
+
export function createPrototypeRoutes() {
|
|
135
|
+
const router = Router();
|
|
136
|
+
// Apply gate to all prototype routes
|
|
137
|
+
router.use(prototypeGate);
|
|
138
|
+
// Generate a banner image with custom dimensions and prompt
|
|
139
|
+
router.post('/generate-banner', async (req, res) => {
|
|
140
|
+
const requestId = req.requestId;
|
|
141
|
+
const { mission, color, template, width, height, customPrompt } = req.body;
|
|
142
|
+
logger.info('Generate banner request', {
|
|
143
|
+
requestId,
|
|
144
|
+
mission: mission?.slice(0, 50),
|
|
145
|
+
color,
|
|
146
|
+
template,
|
|
147
|
+
width,
|
|
148
|
+
height,
|
|
149
|
+
hasCustomPrompt: !!customPrompt
|
|
150
|
+
});
|
|
151
|
+
try {
|
|
152
|
+
// Validate inputs
|
|
153
|
+
if (!width || !height) {
|
|
154
|
+
res.status(400).json({ error: 'Missing required fields: width, height' });
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
let prompt;
|
|
158
|
+
if (customPrompt) {
|
|
159
|
+
// Use custom prompt directly
|
|
160
|
+
prompt = customPrompt;
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
// Use template-based prompt
|
|
164
|
+
if (!mission || !color || !template) {
|
|
165
|
+
res.status(400).json({ error: 'Missing required fields: mission, color, template (or provide customPrompt)' });
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
const promptFn = PROMPT_TEMPLATES[template];
|
|
169
|
+
if (!promptFn) {
|
|
170
|
+
res.status(400).json({ error: `Unknown template: ${template}` });
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
prompt = promptFn(mission, color);
|
|
174
|
+
}
|
|
175
|
+
// Get Gemini API key
|
|
176
|
+
const config = ConfigService.getInstance().getConfig();
|
|
177
|
+
const apiKey = config.gemini?.apiKey || process.env.GOOGLE_API_KEY;
|
|
178
|
+
if (!apiKey) {
|
|
179
|
+
res.status(500).json({ error: 'Gemini API key not configured' });
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
// Create black canvas at higher resolution (will resize after)
|
|
183
|
+
// Use 2x or 3x for quality, scaled to max 1024 on any dimension
|
|
184
|
+
const scale = Math.min(3, 1024 / Math.max(width, height));
|
|
185
|
+
const canvasWidth = Math.round(width * scale);
|
|
186
|
+
const canvasHeight = Math.round(height * scale);
|
|
187
|
+
logger.debug('Creating black canvas', { canvasWidth, canvasHeight, scale });
|
|
188
|
+
const blackCanvas = await sharp({
|
|
189
|
+
create: {
|
|
190
|
+
width: canvasWidth,
|
|
191
|
+
height: canvasHeight,
|
|
192
|
+
channels: 3,
|
|
193
|
+
background: { r: 0, g: 0, b: 0 }
|
|
194
|
+
}
|
|
195
|
+
}).png().toBuffer();
|
|
196
|
+
const blackCanvasBase64 = blackCanvas.toString('base64');
|
|
197
|
+
// Call Gemini image generation
|
|
198
|
+
const genAI = new GoogleGenAI({ apiKey });
|
|
199
|
+
logger.debug('Calling Gemini image generation', { prompt: prompt.slice(0, 100) });
|
|
200
|
+
const response = await genAI.models.generateContent({
|
|
201
|
+
model: 'gemini-3-pro-image-preview',
|
|
202
|
+
contents: [
|
|
203
|
+
{
|
|
204
|
+
role: 'user',
|
|
205
|
+
parts: [
|
|
206
|
+
{ inlineData: { mimeType: 'image/png', data: blackCanvasBase64 } },
|
|
207
|
+
{ text: prompt }
|
|
208
|
+
]
|
|
209
|
+
}
|
|
210
|
+
],
|
|
211
|
+
config: {
|
|
212
|
+
responseModalities: ['TEXT', 'IMAGE'],
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
// Extract image from response
|
|
216
|
+
if (response.candidates?.[0]?.content?.parts) {
|
|
217
|
+
for (const part of response.candidates[0].content.parts) {
|
|
218
|
+
if (part.inlineData) {
|
|
219
|
+
const rawImageBuffer = Buffer.from(part.inlineData.data, 'base64');
|
|
220
|
+
// Resize to target dimensions
|
|
221
|
+
const resizedBuffer = await sharp(rawImageBuffer)
|
|
222
|
+
.resize(width, height, { fit: 'cover' })
|
|
223
|
+
.jpeg({ quality: 85 })
|
|
224
|
+
.toBuffer();
|
|
225
|
+
const resizedBase64 = resizedBuffer.toString('base64');
|
|
226
|
+
logger.info('Banner generated successfully', {
|
|
227
|
+
requestId,
|
|
228
|
+
originalSize: rawImageBuffer.length,
|
|
229
|
+
resizedSize: resizedBuffer.length,
|
|
230
|
+
dimensions: `${width}x${height}`
|
|
231
|
+
});
|
|
232
|
+
res.json({
|
|
233
|
+
imageData: resizedBase64,
|
|
234
|
+
mimeType: 'image/jpeg',
|
|
235
|
+
dimensions: { width, height }
|
|
236
|
+
});
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
res.status(500).json({ error: 'No image was generated in the response' });
|
|
242
|
+
}
|
|
243
|
+
catch (error) {
|
|
244
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
245
|
+
logger.error('Banner generation failed', {
|
|
246
|
+
requestId,
|
|
247
|
+
errorMessage,
|
|
248
|
+
errorType: error?.constructor?.name
|
|
249
|
+
});
|
|
250
|
+
res.status(500).json({ error: `Generation failed: ${errorMessage}` });
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
// Full semantic pipeline: extract visual concepts from session context, then generate banner
|
|
254
|
+
router.post('/semantic-banner', async (req, res) => {
|
|
255
|
+
const requestId = req.requestId;
|
|
256
|
+
const { mission, theme, project } = req.body;
|
|
257
|
+
logger.info('Semantic banner pipeline request', {
|
|
258
|
+
requestId,
|
|
259
|
+
mission: mission?.slice(0, 50),
|
|
260
|
+
theme,
|
|
261
|
+
project
|
|
262
|
+
});
|
|
263
|
+
try {
|
|
264
|
+
if (!mission) {
|
|
265
|
+
res.status(400).json({ error: 'Missing required field: mission' });
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
// Get config early since we need API keys
|
|
269
|
+
const config = ConfigService.getInstance().getConfig();
|
|
270
|
+
// Step 1: Extract visual concepts using Claude
|
|
271
|
+
const extractionPrompt = `You are helping generate a visual identity banner for a coding session. Given the session context below, extract visual concepts that could represent this work.
|
|
272
|
+
|
|
273
|
+
<session_context>
|
|
274
|
+
Mission: ${mission}
|
|
275
|
+
Theme: ${theme || 'implementing'}
|
|
276
|
+
Project: ${project || 'Unknown'}
|
|
277
|
+
</session_context>
|
|
278
|
+
|
|
279
|
+
Analyze what this session is fundamentally about and output a JSON object with:
|
|
280
|
+
|
|
281
|
+
1. "primary_metaphor": A concrete visual metaphor for the core work (e.g., "a lock being examined" for auth debugging, "flowing streams merging" for data pipeline work, "tangled wires being organized" for refactoring)
|
|
282
|
+
|
|
283
|
+
2. "visual_elements": 2-3 specific visual elements that could appear in a horizontal banner (e.g., "diagnostic scan lines", "glowing nodes", "geometric shapes reorganizing")
|
|
284
|
+
|
|
285
|
+
3. "mood": The emotional/energy quality (e.g., "urgent and focused", "methodical and precise", "creative and exploratory")
|
|
286
|
+
|
|
287
|
+
4. "color_suggestion": A neon color that fits the mood (choose from: cyan/blue, amber/orange, green/emerald, purple/violet, magenta/pink, gold/yellow)
|
|
288
|
+
|
|
289
|
+
5. "icon_hint": A single simple icon/symbol that captures the essence (e.g., "magnifying glass", "shield", "gear", "lightning bolt", "compass", "lock", "branch", "pulse")
|
|
290
|
+
|
|
291
|
+
Output ONLY the JSON object, no other text.`;
|
|
292
|
+
logger.debug('Extracting visual concepts', { requestId });
|
|
293
|
+
// Get Anthropic API key
|
|
294
|
+
const anthropicApiKey = config.anthropic?.apiKey || process.env.ANTHROPIC_API_KEY;
|
|
295
|
+
if (!anthropicApiKey) {
|
|
296
|
+
res.status(500).json({ error: 'Anthropic API key not configured' });
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
const anthropic = new Anthropic({ apiKey: anthropicApiKey });
|
|
300
|
+
const extractionResponse = await anthropic.messages.create({
|
|
301
|
+
model: 'claude-haiku-4-5-20251001',
|
|
302
|
+
max_tokens: 500,
|
|
303
|
+
messages: [{ role: 'user', content: extractionPrompt }],
|
|
304
|
+
});
|
|
305
|
+
const extractionText = extractionResponse.content[0].type === 'text'
|
|
306
|
+
? extractionResponse.content[0].text
|
|
307
|
+
: '';
|
|
308
|
+
// Parse concepts
|
|
309
|
+
let concepts;
|
|
310
|
+
try {
|
|
311
|
+
concepts = JSON.parse(extractionText);
|
|
312
|
+
}
|
|
313
|
+
catch {
|
|
314
|
+
const jsonMatch = extractionText.match(/\{[\s\S]*\}/);
|
|
315
|
+
if (jsonMatch) {
|
|
316
|
+
concepts = JSON.parse(jsonMatch[0]);
|
|
317
|
+
}
|
|
318
|
+
else {
|
|
319
|
+
throw new Error(`Failed to parse concepts: ${extractionText.slice(0, 200)}`);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
logger.info('Visual concepts extracted', {
|
|
323
|
+
requestId,
|
|
324
|
+
metaphor: concepts.primary_metaphor,
|
|
325
|
+
color: concepts.color_suggestion,
|
|
326
|
+
icon: concepts.icon_hint
|
|
327
|
+
});
|
|
328
|
+
// Step 2: Build image prompt from concepts
|
|
329
|
+
const imagePrompt = `Add a glowing neon design to this black banner image.
|
|
330
|
+
|
|
331
|
+
VISUAL CONCEPT: ${concepts.primary_metaphor}
|
|
332
|
+
|
|
333
|
+
Elements to include:
|
|
334
|
+
${concepts.visual_elements.map(e => `- ${e}`).join('\n')}
|
|
335
|
+
|
|
336
|
+
Style:
|
|
337
|
+
- ${concepts.mood}
|
|
338
|
+
- ${concepts.color_suggestion} neon glow
|
|
339
|
+
- Consider incorporating a ${concepts.icon_hint} motif
|
|
340
|
+
- Horizontal composition flowing across the banner
|
|
341
|
+
- Pure black background
|
|
342
|
+
- No text, no faces
|
|
343
|
+
- Abstract/stylized, not photorealistic`;
|
|
344
|
+
// Step 3: Generate the image
|
|
345
|
+
const apiKey = config.gemini?.apiKey || process.env.GOOGLE_API_KEY;
|
|
346
|
+
if (!apiKey) {
|
|
347
|
+
res.status(500).json({ error: 'Gemini API key not configured' });
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
const width = 401;
|
|
351
|
+
const height = 64;
|
|
352
|
+
const scale = Math.min(3, 1024 / Math.max(width, height));
|
|
353
|
+
const canvasWidth = Math.round(width * scale);
|
|
354
|
+
const canvasHeight = Math.round(height * scale);
|
|
355
|
+
const blackCanvas = await sharp({
|
|
356
|
+
create: {
|
|
357
|
+
width: canvasWidth,
|
|
358
|
+
height: canvasHeight,
|
|
359
|
+
channels: 3,
|
|
360
|
+
background: { r: 0, g: 0, b: 0 }
|
|
361
|
+
}
|
|
362
|
+
}).png().toBuffer();
|
|
363
|
+
const blackCanvasBase64 = blackCanvas.toString('base64');
|
|
364
|
+
const genAI = new GoogleGenAI({ apiKey });
|
|
365
|
+
logger.debug('Generating image with Gemini', { requestId });
|
|
366
|
+
const imageResponse = await genAI.models.generateContent({
|
|
367
|
+
model: 'gemini-3-pro-image-preview',
|
|
368
|
+
contents: [
|
|
369
|
+
{
|
|
370
|
+
role: 'user',
|
|
371
|
+
parts: [
|
|
372
|
+
{ inlineData: { mimeType: 'image/png', data: blackCanvasBase64 } },
|
|
373
|
+
{ text: imagePrompt }
|
|
374
|
+
]
|
|
375
|
+
}
|
|
376
|
+
],
|
|
377
|
+
config: {
|
|
378
|
+
responseModalities: ['TEXT', 'IMAGE'],
|
|
379
|
+
}
|
|
380
|
+
});
|
|
381
|
+
// Extract image from response
|
|
382
|
+
if (imageResponse.candidates?.[0]?.content?.parts) {
|
|
383
|
+
for (const part of imageResponse.candidates[0].content.parts) {
|
|
384
|
+
if (part.inlineData) {
|
|
385
|
+
const rawImageBuffer = Buffer.from(part.inlineData.data, 'base64');
|
|
386
|
+
const resizedBuffer = await sharp(rawImageBuffer)
|
|
387
|
+
.resize(width, height, { fit: 'cover' })
|
|
388
|
+
.jpeg({ quality: 85 })
|
|
389
|
+
.toBuffer();
|
|
390
|
+
const resizedBase64 = resizedBuffer.toString('base64');
|
|
391
|
+
logger.info('Semantic banner generated successfully', {
|
|
392
|
+
requestId,
|
|
393
|
+
dimensions: `${width}x${height}`
|
|
394
|
+
});
|
|
395
|
+
res.json({
|
|
396
|
+
imageData: resizedBase64,
|
|
397
|
+
mimeType: 'image/jpeg',
|
|
398
|
+
dimensions: { width, height },
|
|
399
|
+
concepts,
|
|
400
|
+
imagePrompt,
|
|
401
|
+
});
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
res.status(500).json({ error: 'No image was generated in the response' });
|
|
407
|
+
}
|
|
408
|
+
catch (error) {
|
|
409
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
410
|
+
logger.error('Semantic banner pipeline failed', {
|
|
411
|
+
requestId,
|
|
412
|
+
errorMessage,
|
|
413
|
+
errorType: error?.constructor?.name
|
|
414
|
+
});
|
|
415
|
+
res.status(500).json({ error: `Pipeline failed: ${errorMessage}` });
|
|
416
|
+
}
|
|
417
|
+
});
|
|
418
|
+
// New diversity-focused banner generation
|
|
419
|
+
router.post('/diverse-banner', async (req, res) => {
|
|
420
|
+
const requestId = req.requestId;
|
|
421
|
+
const { context } = req.body;
|
|
422
|
+
// Pick random visual parameters
|
|
423
|
+
const [primaryColor, accentColor] = pickTwo(COLORS);
|
|
424
|
+
const style = pickRandom(STYLE_SEEDS);
|
|
425
|
+
const composition = pickRandom(COMPOSITIONS);
|
|
426
|
+
logger.info('Diverse banner generation request', {
|
|
427
|
+
requestId,
|
|
428
|
+
primaryColor,
|
|
429
|
+
accentColor,
|
|
430
|
+
style,
|
|
431
|
+
composition,
|
|
432
|
+
context: context?.slice(0, 50)
|
|
433
|
+
});
|
|
434
|
+
try {
|
|
435
|
+
const config = ConfigService.getInstance().getConfig();
|
|
436
|
+
const apiKey = config.gemini?.apiKey || process.env.GOOGLE_API_KEY;
|
|
437
|
+
if (!apiKey) {
|
|
438
|
+
res.status(500).json({ error: 'Gemini API key not configured' });
|
|
439
|
+
return;
|
|
440
|
+
}
|
|
441
|
+
const prompt = `Create a unique abstract banner on this black background. No text, no faces, no realistic objects.
|
|
442
|
+
|
|
443
|
+
Colors: ${primaryColor} as primary, ${accentColor} as accent
|
|
444
|
+
Style: ${style}
|
|
445
|
+
Composition: ${composition}
|
|
446
|
+
|
|
447
|
+
${context ? `Inspiration (interpret freely, don't be literal): ${context}` : ''}
|
|
448
|
+
|
|
449
|
+
Be creative and make this visually distinctive. Pure black background must be preserved.`;
|
|
450
|
+
const width = 401;
|
|
451
|
+
const height = 64;
|
|
452
|
+
const scale = Math.min(3, 1024 / Math.max(width, height));
|
|
453
|
+
const canvasWidth = Math.round(width * scale);
|
|
454
|
+
const canvasHeight = Math.round(height * scale);
|
|
455
|
+
const blackCanvas = await sharp({
|
|
456
|
+
create: {
|
|
457
|
+
width: canvasWidth,
|
|
458
|
+
height: canvasHeight,
|
|
459
|
+
channels: 3,
|
|
460
|
+
background: { r: 0, g: 0, b: 0 }
|
|
461
|
+
}
|
|
462
|
+
}).png().toBuffer();
|
|
463
|
+
const blackCanvasBase64 = blackCanvas.toString('base64');
|
|
464
|
+
const genAI = new GoogleGenAI({ apiKey });
|
|
465
|
+
const response = await genAI.models.generateContent({
|
|
466
|
+
model: 'gemini-3-pro-image-preview',
|
|
467
|
+
contents: [
|
|
468
|
+
{
|
|
469
|
+
role: 'user',
|
|
470
|
+
parts: [
|
|
471
|
+
{ inlineData: { mimeType: 'image/png', data: blackCanvasBase64 } },
|
|
472
|
+
{ text: prompt }
|
|
473
|
+
]
|
|
474
|
+
}
|
|
475
|
+
],
|
|
476
|
+
config: {
|
|
477
|
+
responseModalities: ['TEXT', 'IMAGE'],
|
|
478
|
+
}
|
|
479
|
+
});
|
|
480
|
+
if (response.candidates?.[0]?.content?.parts) {
|
|
481
|
+
for (const part of response.candidates[0].content.parts) {
|
|
482
|
+
if (part.inlineData) {
|
|
483
|
+
const rawImageBuffer = Buffer.from(part.inlineData.data, 'base64');
|
|
484
|
+
const resizedBuffer = await sharp(rawImageBuffer)
|
|
485
|
+
.resize(width, height, { fit: 'cover' })
|
|
486
|
+
.jpeg({ quality: 90 })
|
|
487
|
+
.toBuffer();
|
|
488
|
+
const resizedBase64 = resizedBuffer.toString('base64');
|
|
489
|
+
logger.info('Diverse banner generated successfully', {
|
|
490
|
+
requestId,
|
|
491
|
+
dimensions: `${width}x${height}`,
|
|
492
|
+
primaryColor,
|
|
493
|
+
accentColor,
|
|
494
|
+
style
|
|
495
|
+
});
|
|
496
|
+
res.json({
|
|
497
|
+
imageData: resizedBase64,
|
|
498
|
+
mimeType: 'image/jpeg',
|
|
499
|
+
dimensions: { width, height },
|
|
500
|
+
params: { primaryColor, accentColor, style, composition, context }
|
|
501
|
+
});
|
|
502
|
+
return;
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
res.status(500).json({ error: 'No image was generated in the response' });
|
|
507
|
+
}
|
|
508
|
+
catch (error) {
|
|
509
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
510
|
+
logger.error('Diverse banner generation failed', {
|
|
511
|
+
requestId,
|
|
512
|
+
errorMessage,
|
|
513
|
+
errorType: error?.constructor?.name
|
|
514
|
+
});
|
|
515
|
+
res.status(500).json({ error: `Generation failed: ${errorMessage}` });
|
|
516
|
+
}
|
|
517
|
+
});
|
|
518
|
+
// Serve demo walkthrough data
|
|
519
|
+
router.get('/walkthrough/demo', (_req, res) => {
|
|
520
|
+
const demoPath = '/tmp/walkthrough-demo.json';
|
|
521
|
+
if (!existsSync(demoPath)) {
|
|
522
|
+
res.status(404).json({ error: 'Demo walkthrough not found. Generate with: npx tsx scripts/generate-walkthrough.ts <session.jsonl> > /tmp/walkthrough-demo.json' });
|
|
523
|
+
return;
|
|
524
|
+
}
|
|
525
|
+
try {
|
|
526
|
+
const data = JSON.parse(readFileSync(demoPath, 'utf-8'));
|
|
527
|
+
res.json(data);
|
|
528
|
+
}
|
|
529
|
+
catch (_err) {
|
|
530
|
+
res.status(500).json({ error: 'Failed to read demo walkthrough' });
|
|
531
|
+
}
|
|
532
|
+
});
|
|
533
|
+
// Serve the image experiment gallery page
|
|
534
|
+
router.get('/image-gallery', (_req, res) => {
|
|
535
|
+
const html = `<!DOCTYPE html>
|
|
536
|
+
<html>
|
|
537
|
+
<head>
|
|
538
|
+
<title>Banner Diversity Experiment</title>
|
|
539
|
+
<style>
|
|
540
|
+
* { box-sizing: border-box; }
|
|
541
|
+
body {
|
|
542
|
+
background: #0a0a0a;
|
|
543
|
+
color: #eee;
|
|
544
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
545
|
+
padding: 2rem;
|
|
546
|
+
margin: 0;
|
|
547
|
+
}
|
|
548
|
+
h1 {
|
|
549
|
+
text-align: center;
|
|
550
|
+
margin-bottom: 0.5rem;
|
|
551
|
+
font-weight: 400;
|
|
552
|
+
font-size: 1.5rem;
|
|
553
|
+
}
|
|
554
|
+
.subtitle {
|
|
555
|
+
text-align: center;
|
|
556
|
+
color: #666;
|
|
557
|
+
margin-bottom: 2rem;
|
|
558
|
+
font-size: 0.9rem;
|
|
559
|
+
}
|
|
560
|
+
.controls {
|
|
561
|
+
display: flex;
|
|
562
|
+
justify-content: center;
|
|
563
|
+
gap: 1rem;
|
|
564
|
+
margin-bottom: 2rem;
|
|
565
|
+
flex-wrap: wrap;
|
|
566
|
+
}
|
|
567
|
+
button {
|
|
568
|
+
background: #222;
|
|
569
|
+
color: #eee;
|
|
570
|
+
border: 1px solid #444;
|
|
571
|
+
padding: 0.75rem 1.5rem;
|
|
572
|
+
border-radius: 6px;
|
|
573
|
+
cursor: pointer;
|
|
574
|
+
font-size: 0.9rem;
|
|
575
|
+
transition: all 0.15s;
|
|
576
|
+
}
|
|
577
|
+
button:hover {
|
|
578
|
+
background: #333;
|
|
579
|
+
border-color: #666;
|
|
580
|
+
}
|
|
581
|
+
button:disabled {
|
|
582
|
+
opacity: 0.5;
|
|
583
|
+
cursor: not-allowed;
|
|
584
|
+
}
|
|
585
|
+
.gallery {
|
|
586
|
+
display: grid;
|
|
587
|
+
grid-template-columns: repeat(auto-fill, minmax(420px, 1fr));
|
|
588
|
+
gap: 1rem;
|
|
589
|
+
max-width: 1800px;
|
|
590
|
+
margin: 0 auto;
|
|
591
|
+
}
|
|
592
|
+
.card {
|
|
593
|
+
background: #151515;
|
|
594
|
+
border-radius: 8px;
|
|
595
|
+
overflow: hidden;
|
|
596
|
+
border: 1px solid #252525;
|
|
597
|
+
}
|
|
598
|
+
.card img {
|
|
599
|
+
width: 100%;
|
|
600
|
+
height: auto;
|
|
601
|
+
display: block;
|
|
602
|
+
}
|
|
603
|
+
.card.loading {
|
|
604
|
+
min-height: 100px;
|
|
605
|
+
display: flex;
|
|
606
|
+
align-items: center;
|
|
607
|
+
justify-content: center;
|
|
608
|
+
}
|
|
609
|
+
.card.loading::after {
|
|
610
|
+
content: 'Generating...';
|
|
611
|
+
color: #555;
|
|
612
|
+
font-size: 0.85rem;
|
|
613
|
+
}
|
|
614
|
+
.info {
|
|
615
|
+
padding: 0.75rem;
|
|
616
|
+
}
|
|
617
|
+
.params {
|
|
618
|
+
display: flex;
|
|
619
|
+
flex-wrap: wrap;
|
|
620
|
+
gap: 0.4rem;
|
|
621
|
+
}
|
|
622
|
+
.param {
|
|
623
|
+
padding: 0.2rem 0.5rem;
|
|
624
|
+
border-radius: 4px;
|
|
625
|
+
font-size: 0.7rem;
|
|
626
|
+
background: #222;
|
|
627
|
+
color: #888;
|
|
628
|
+
}
|
|
629
|
+
.param.color {
|
|
630
|
+
color: #000;
|
|
631
|
+
font-weight: 500;
|
|
632
|
+
}
|
|
633
|
+
.context {
|
|
634
|
+
margin-top: 0.5rem;
|
|
635
|
+
font-size: 0.8rem;
|
|
636
|
+
color: #666;
|
|
637
|
+
font-style: italic;
|
|
638
|
+
}
|
|
639
|
+
.context-input {
|
|
640
|
+
width: 100%;
|
|
641
|
+
max-width: 500px;
|
|
642
|
+
padding: 0.5rem 0.75rem;
|
|
643
|
+
background: #1a1a1a;
|
|
644
|
+
border: 1px solid #333;
|
|
645
|
+
border-radius: 6px;
|
|
646
|
+
color: #eee;
|
|
647
|
+
font-size: 0.9rem;
|
|
648
|
+
}
|
|
649
|
+
.context-input::placeholder {
|
|
650
|
+
color: #555;
|
|
651
|
+
}
|
|
652
|
+
</style>
|
|
653
|
+
</head>
|
|
654
|
+
<body>
|
|
655
|
+
<h1>Banner Diversity Experiment</h1>
|
|
656
|
+
<p class="subtitle">Random colors + styles + loose context = distinctive banners</p>
|
|
657
|
+
|
|
658
|
+
<div class="controls">
|
|
659
|
+
<input type="text" class="context-input" id="contextInput" placeholder="Optional context (e.g., 'debugging auth flow')">
|
|
660
|
+
<button onclick="generateOne()">Generate 1</button>
|
|
661
|
+
<button onclick="generateBatch(5)">Generate 5</button>
|
|
662
|
+
<button onclick="generateBatch(10)">Generate 10</button>
|
|
663
|
+
<button onclick="clearGallery()">Clear</button>
|
|
664
|
+
</div>
|
|
665
|
+
|
|
666
|
+
<div class="gallery" id="gallery"></div>
|
|
667
|
+
|
|
668
|
+
<script>
|
|
669
|
+
const gallery = document.getElementById('gallery');
|
|
670
|
+
const contextInput = document.getElementById('contextInput');
|
|
671
|
+
|
|
672
|
+
const colorMap = {
|
|
673
|
+
'electric blue': '#0066ff',
|
|
674
|
+
'hot pink': '#ff1493',
|
|
675
|
+
'lime green': '#32cd32',
|
|
676
|
+
'golden yellow': '#ffd700',
|
|
677
|
+
'coral orange': '#ff7f50',
|
|
678
|
+
'deep purple': '#673ab7',
|
|
679
|
+
'cyan': '#00bcd4',
|
|
680
|
+
'magenta': '#e91e63',
|
|
681
|
+
'mint green': '#98ff98',
|
|
682
|
+
'amber': '#ffbf00',
|
|
683
|
+
'crimson red': '#dc143c',
|
|
684
|
+
'teal': '#008080',
|
|
685
|
+
'lavender': '#b57edc',
|
|
686
|
+
'peach': '#ffcba4',
|
|
687
|
+
'electric violet': '#8f00ff',
|
|
688
|
+
'neon orange': '#ff6600',
|
|
689
|
+
'sky blue': '#87ceeb',
|
|
690
|
+
'rose pink': '#ff66b2',
|
|
691
|
+
'chartreuse': '#7fff00',
|
|
692
|
+
'copper': '#b87333'
|
|
693
|
+
};
|
|
694
|
+
|
|
695
|
+
async function generateOne() {
|
|
696
|
+
const card = document.createElement('div');
|
|
697
|
+
card.className = 'card loading';
|
|
698
|
+
gallery.prepend(card);
|
|
699
|
+
|
|
700
|
+
try {
|
|
701
|
+
const context = contextInput.value.trim() || undefined;
|
|
702
|
+
const response = await fetch('/api/prototype/diverse-banner', {
|
|
703
|
+
method: 'POST',
|
|
704
|
+
headers: { 'Content-Type': 'application/json' },
|
|
705
|
+
body: JSON.stringify({ context })
|
|
706
|
+
});
|
|
707
|
+
|
|
708
|
+
const data = await response.json();
|
|
709
|
+
|
|
710
|
+
if (data.error) {
|
|
711
|
+
card.innerHTML = '<div class="info" style="color: #f55;">' + data.error + '</div>';
|
|
712
|
+
card.classList.remove('loading');
|
|
713
|
+
return;
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
const primaryCss = colorMap[data.params.primaryColor] || '#888';
|
|
717
|
+
const accentCss = colorMap[data.params.accentColor] || '#888';
|
|
718
|
+
|
|
719
|
+
card.innerHTML = \`
|
|
720
|
+
<img src="data:\${data.mimeType};base64,\${data.imageData}" alt="Generated banner">
|
|
721
|
+
<div class="info">
|
|
722
|
+
<div class="params">
|
|
723
|
+
<span class="param color" style="background: \${primaryCss}">\${data.params.primaryColor}</span>
|
|
724
|
+
<span class="param color" style="background: \${accentCss}">\${data.params.accentColor}</span>
|
|
725
|
+
<span class="param">\${data.params.style}</span>
|
|
726
|
+
<span class="param">\${data.params.composition}</span>
|
|
727
|
+
</div>
|
|
728
|
+
\${data.params.context ? '<div class="context">' + data.params.context + '</div>' : ''}
|
|
729
|
+
</div>
|
|
730
|
+
\`;
|
|
731
|
+
card.classList.remove('loading');
|
|
732
|
+
} catch (err) {
|
|
733
|
+
card.innerHTML = '<div class="info" style="color: #f55;">Error: ' + err.message + '</div>';
|
|
734
|
+
card.classList.remove('loading');
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
async function generateBatch(count) {
|
|
739
|
+
for (let i = 0; i < count; i++) {
|
|
740
|
+
generateOne();
|
|
741
|
+
if (i < count - 1) {
|
|
742
|
+
await new Promise(r => setTimeout(r, 500));
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
function clearGallery() {
|
|
748
|
+
gallery.innerHTML = '';
|
|
749
|
+
}
|
|
750
|
+
</script>
|
|
751
|
+
</body>
|
|
752
|
+
</html>`;
|
|
753
|
+
res.type('html').send(html);
|
|
754
|
+
});
|
|
755
|
+
return router;
|
|
756
|
+
}
|
|
757
|
+
//# sourceMappingURL=prototype.routes.js.map
|