crewly 1.0.6 → 1.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +146 -40
- package/config/roles/architect/prompt.md +11 -0
- package/config/roles/backend-developer/prompt.md +11 -0
- package/config/roles/designer/prompt.md +11 -0
- package/config/roles/developer/prompt.md +18 -4
- package/config/roles/frontend-developer/prompt.md +11 -0
- package/config/roles/fullstack-dev/prompt.md +11 -0
- package/config/roles/generalist/prompt.md +11 -0
- package/config/roles/orchestrator/prompt.md +53 -10
- package/config/roles/product-manager/prompt.md +18 -4
- package/config/roles/qa/prompt.md +11 -0
- package/config/roles/qa-engineer/prompt.md +11 -0
- package/config/roles/sales/prompt.md +11 -0
- package/config/roles/support/prompt.md +11 -0
- package/config/roles/tpm/prompt.md +11 -0
- package/config/skills/orchestrator/complete-task/execute.sh +1 -0
- package/config/templates/agent-claude-md.md +16 -0
- package/config/templates/research-team.json +22 -0
- package/config/templates/startup-team.json +22 -0
- package/config/templates/web-dev-team.json +22 -0
- package/dist/backend/backend/src/constants.d.ts +61 -1
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +65 -7
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/controllers/slack/slack.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/slack/slack.controller.js +7 -0
- package/dist/backend/backend/src/controllers/slack/slack.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/task-management/task-management.controller.d.ts +7 -0
- package/dist/backend/backend/src/controllers/task-management/task-management.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/task-management/task-management.controller.js +174 -4
- package/dist/backend/backend/src/controllers/task-management/task-management.controller.js.map +1 -1
- package/dist/backend/backend/src/index.d.ts.map +1 -1
- package/dist/backend/backend/src/index.js +34 -0
- package/dist/backend/backend/src/index.js.map +1 -1
- package/dist/backend/backend/src/routes/modules/task-management.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/routes/modules/task-management.routes.js +2 -0
- package/dist/backend/backend/src/routes/modules/task-management.routes.js.map +1 -1
- package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts +8 -0
- package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/agent-registration.service.js +75 -17
- package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/context-window-monitor.service.d.ts +222 -0
- package/dist/backend/backend/src/services/agent/context-window-monitor.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/agent/context-window-monitor.service.js +621 -0
- package/dist/backend/backend/src/services/agent/context-window-monitor.service.js.map +1 -0
- package/dist/backend/backend/src/services/index.d.ts +3 -0
- package/dist/backend/backend/src/services/index.d.ts.map +1 -1
- package/dist/backend/backend/src/services/index.js +5 -0
- package/dist/backend/backend/src/services/index.js.map +1 -1
- package/dist/backend/backend/src/services/mcp-client.d.ts +233 -0
- package/dist/backend/backend/src/services/mcp-client.d.ts.map +1 -0
- package/dist/backend/backend/src/services/mcp-client.js +297 -0
- package/dist/backend/backend/src/services/mcp-client.js.map +1 -0
- package/dist/backend/backend/src/services/mcp-server.d.ts +167 -0
- package/dist/backend/backend/src/services/mcp-server.d.ts.map +1 -0
- package/dist/backend/backend/src/services/mcp-server.js +586 -0
- package/dist/backend/backend/src/services/mcp-server.js.map +1 -0
- package/dist/backend/backend/src/services/messaging/message-queue.service.d.ts +2 -0
- package/dist/backend/backend/src/services/messaging/message-queue.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/messaging/message-queue.service.js +6 -1
- package/dist/backend/backend/src/services/messaging/message-queue.service.js.map +1 -1
- package/dist/backend/backend/src/services/messaging/queue-processor.service.d.ts +10 -0
- package/dist/backend/backend/src/services/messaging/queue-processor.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/messaging/queue-processor.service.js +94 -38
- package/dist/backend/backend/src/services/messaging/queue-processor.service.js.map +1 -1
- package/dist/backend/backend/src/services/quality/index.d.ts +1 -0
- package/dist/backend/backend/src/services/quality/index.d.ts.map +1 -1
- package/dist/backend/backend/src/services/quality/index.js +1 -0
- package/dist/backend/backend/src/services/quality/index.js.map +1 -1
- package/dist/backend/backend/src/services/quality/task-output-validator.service.d.ts +84 -0
- package/dist/backend/backend/src/services/quality/task-output-validator.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/quality/task-output-validator.service.js +163 -0
- package/dist/backend/backend/src/services/quality/task-output-validator.service.js.map +1 -0
- package/dist/backend/backend/src/services/runtime-adapter.d.ts +234 -0
- package/dist/backend/backend/src/services/runtime-adapter.d.ts.map +1 -0
- package/dist/backend/backend/src/services/runtime-adapter.js +180 -0
- package/dist/backend/backend/src/services/runtime-adapter.js.map +1 -0
- package/dist/backend/backend/src/services/slack/slack-credentials.service.d.ts +33 -0
- package/dist/backend/backend/src/services/slack/slack-credentials.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/slack/slack-credentials.service.js +103 -0
- package/dist/backend/backend/src/services/slack/slack-credentials.service.js.map +1 -0
- package/dist/backend/backend/src/services/slack/slack-initializer.d.ts +9 -1
- package/dist/backend/backend/src/services/slack/slack-initializer.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-initializer.js +31 -2
- package/dist/backend/backend/src/services/slack/slack-initializer.js.map +1 -1
- package/dist/backend/backend/src/types/event-bus.types.d.ts +2 -2
- package/dist/backend/backend/src/types/event-bus.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/event-bus.types.js +2 -0
- package/dist/backend/backend/src/types/event-bus.types.js.map +1 -1
- package/dist/backend/backend/src/types/index.d.ts +1 -0
- package/dist/backend/backend/src/types/index.d.ts.map +1 -1
- package/dist/backend/backend/src/types/index.js +2 -0
- package/dist/backend/backend/src/types/index.js.map +1 -1
- package/dist/backend/backend/src/types/messaging.types.d.ts +9 -6
- package/dist/backend/backend/src/types/messaging.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/messaging.types.js +10 -3
- package/dist/backend/backend/src/types/messaging.types.js.map +1 -1
- package/dist/backend/backend/src/types/task-output.types.d.ts +78 -0
- package/dist/backend/backend/src/types/task-output.types.d.ts.map +1 -0
- package/dist/backend/backend/src/types/task-output.types.js +27 -0
- package/dist/backend/backend/src/types/task-output.types.js.map +1 -0
- package/dist/backend/backend/src/websocket/terminal.gateway.d.ts +13 -0
- package/dist/backend/backend/src/websocket/terminal.gateway.d.ts.map +1 -1
- package/dist/backend/backend/src/websocket/terminal.gateway.js +12 -0
- package/dist/backend/backend/src/websocket/terminal.gateway.js.map +1 -1
- package/dist/cli/backend/src/constants.d.ts +751 -0
- package/dist/cli/backend/src/constants.d.ts.map +1 -0
- package/dist/cli/backend/src/constants.js +550 -0
- package/dist/cli/backend/src/constants.js.map +1 -0
- package/dist/cli/backend/src/models/Project.d.ts +18 -0
- package/dist/cli/backend/src/models/Project.d.ts.map +1 -0
- package/dist/cli/backend/src/models/Project.js +70 -0
- package/dist/cli/backend/src/models/Project.js.map +1 -0
- package/dist/cli/backend/src/models/ScheduledMessage.d.ts +27 -0
- package/dist/cli/backend/src/models/ScheduledMessage.d.ts.map +1 -0
- package/dist/cli/backend/src/models/ScheduledMessage.js +50 -0
- package/dist/cli/backend/src/models/ScheduledMessage.js.map +1 -0
- package/dist/cli/backend/src/models/Team.d.ts +20 -0
- package/dist/cli/backend/src/models/Team.d.ts.map +1 -0
- package/dist/cli/backend/src/models/Team.js +120 -0
- package/dist/cli/backend/src/models/Team.js.map +1 -0
- package/dist/cli/backend/src/models/Ticket.d.ts +24 -0
- package/dist/cli/backend/src/models/Ticket.d.ts.map +1 -0
- package/dist/cli/backend/src/models/Ticket.js +102 -0
- package/dist/cli/backend/src/models/Ticket.js.map +1 -0
- package/dist/cli/backend/src/models/index.d.ts +5 -0
- package/dist/cli/backend/src/models/index.d.ts.map +1 -0
- package/dist/cli/backend/src/models/index.js +5 -0
- package/dist/cli/backend/src/models/index.js.map +1 -0
- package/dist/cli/backend/src/services/core/config.service.d.ts +91 -0
- package/dist/cli/backend/src/services/core/config.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/core/config.service.js +246 -0
- package/dist/cli/backend/src/services/core/config.service.js.map +1 -0
- package/dist/cli/backend/src/services/core/logger.service.d.ts +70 -0
- package/dist/cli/backend/src/services/core/logger.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/core/logger.service.js +350 -0
- package/dist/cli/backend/src/services/core/logger.service.js.map +1 -0
- package/dist/cli/backend/src/services/core/storage.service.d.ts +269 -0
- package/dist/cli/backend/src/services/core/storage.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/core/storage.service.js +1406 -0
- package/dist/cli/backend/src/services/core/storage.service.js.map +1 -0
- package/dist/cli/backend/src/services/core/teams-backup.service.d.ts +92 -0
- package/dist/cli/backend/src/services/core/teams-backup.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/core/teams-backup.service.js +120 -0
- package/dist/cli/backend/src/services/core/teams-backup.service.js.map +1 -0
- package/dist/cli/backend/src/services/knowledge/knowledge-search.service.d.ts +125 -0
- package/dist/cli/backend/src/services/knowledge/knowledge-search.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/knowledge/knowledge-search.service.js +247 -0
- package/dist/cli/backend/src/services/knowledge/knowledge-search.service.js.map +1 -0
- package/dist/cli/backend/src/services/knowledge/knowledge.service.d.ts +153 -0
- package/dist/cli/backend/src/services/knowledge/knowledge.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/knowledge/knowledge.service.js +409 -0
- package/dist/cli/backend/src/services/knowledge/knowledge.service.js.map +1 -0
- package/dist/cli/backend/src/services/mcp-server.d.ts +167 -0
- package/dist/cli/backend/src/services/mcp-server.d.ts.map +1 -0
- package/dist/cli/backend/src/services/mcp-server.js +586 -0
- package/dist/cli/backend/src/services/mcp-server.js.map +1 -0
- package/dist/cli/backend/src/services/memory/agent-memory.service.d.ts +259 -0
- package/dist/cli/backend/src/services/memory/agent-memory.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/memory/agent-memory.service.js +539 -0
- package/dist/cli/backend/src/services/memory/agent-memory.service.js.map +1 -0
- package/dist/cli/backend/src/services/memory/memory.service.d.ts +306 -0
- package/dist/cli/backend/src/services/memory/memory.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/memory/memory.service.js +517 -0
- package/dist/cli/backend/src/services/memory/memory.service.js.map +1 -0
- package/dist/cli/backend/src/services/memory/project-memory.service.d.ts +252 -0
- package/dist/cli/backend/src/services/memory/project-memory.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/memory/project-memory.service.js +600 -0
- package/dist/cli/backend/src/services/memory/project-memory.service.js.map +1 -0
- package/dist/cli/backend/src/types/auto-assign.types.d.ts +271 -0
- package/dist/cli/backend/src/types/auto-assign.types.d.ts.map +1 -0
- package/dist/cli/backend/src/types/auto-assign.types.js +136 -0
- package/dist/cli/backend/src/types/auto-assign.types.js.map +1 -0
- package/dist/cli/backend/src/types/budget.types.d.ts +217 -0
- package/dist/cli/backend/src/types/budget.types.d.ts.map +1 -0
- package/dist/cli/backend/src/types/budget.types.js +82 -0
- package/dist/cli/backend/src/types/budget.types.js.map +1 -0
- package/dist/cli/backend/src/types/chat.types.d.ts +550 -0
- package/dist/cli/backend/src/types/chat.types.d.ts.map +1 -0
- package/dist/cli/backend/src/types/chat.types.js +743 -0
- package/dist/cli/backend/src/types/chat.types.js.map +1 -0
- package/dist/cli/backend/src/types/continuation.types.d.ts +237 -0
- package/dist/cli/backend/src/types/continuation.types.d.ts.map +1 -0
- package/dist/cli/backend/src/types/continuation.types.js +10 -0
- package/dist/cli/backend/src/types/continuation.types.js.map +1 -0
- package/dist/cli/backend/src/types/index.d.ts +164 -0
- package/dist/cli/backend/src/types/index.d.ts.map +1 -0
- package/dist/cli/backend/src/types/index.js +25 -0
- package/dist/cli/backend/src/types/index.js.map +1 -0
- package/dist/cli/backend/src/types/knowledge.types.d.ts +195 -0
- package/dist/cli/backend/src/types/knowledge.types.d.ts.map +1 -0
- package/dist/cli/backend/src/types/knowledge.types.js +38 -0
- package/dist/cli/backend/src/types/knowledge.types.js.map +1 -0
- package/dist/cli/backend/src/types/memory.types.d.ts +587 -0
- package/dist/cli/backend/src/types/memory.types.d.ts.map +1 -0
- package/dist/cli/backend/src/types/memory.types.js +47 -0
- package/dist/cli/backend/src/types/memory.types.js.map +1 -0
- package/dist/cli/backend/src/types/quality-gate.types.d.ts +171 -0
- package/dist/cli/backend/src/types/quality-gate.types.d.ts.map +1 -0
- package/dist/cli/backend/src/types/quality-gate.types.js +42 -0
- package/dist/cli/backend/src/types/quality-gate.types.js.map +1 -0
- package/dist/cli/backend/src/types/role.types.d.ts +260 -0
- package/dist/cli/backend/src/types/role.types.d.ts.map +1 -0
- package/dist/cli/backend/src/types/role.types.js +238 -0
- package/dist/cli/backend/src/types/role.types.js.map +1 -0
- package/dist/cli/backend/src/types/scheduler.types.d.ts +254 -0
- package/dist/cli/backend/src/types/scheduler.types.d.ts.map +1 -0
- package/dist/cli/backend/src/types/scheduler.types.js +32 -0
- package/dist/cli/backend/src/types/scheduler.types.js.map +1 -0
- package/dist/cli/backend/src/types/settings.types.d.ts +178 -0
- package/dist/cli/backend/src/types/settings.types.d.ts.map +1 -0
- package/dist/cli/backend/src/types/settings.types.js +206 -0
- package/dist/cli/backend/src/types/settings.types.js.map +1 -0
- package/dist/cli/backend/src/types/skill.types.d.ts +515 -0
- package/dist/cli/backend/src/types/skill.types.d.ts.map +1 -0
- package/dist/cli/backend/src/types/skill.types.js +481 -0
- package/dist/cli/backend/src/types/skill.types.js.map +1 -0
- package/dist/cli/backend/src/types/sop.types.d.ts +224 -0
- package/dist/cli/backend/src/types/sop.types.d.ts.map +1 -0
- package/dist/cli/backend/src/types/sop.types.js +85 -0
- package/dist/cli/backend/src/types/sop.types.js.map +1 -0
- package/dist/cli/backend/src/types/task-output.types.d.ts +78 -0
- package/dist/cli/backend/src/types/task-output.types.d.ts.map +1 -0
- package/dist/cli/backend/src/types/task-output.types.js +27 -0
- package/dist/cli/backend/src/types/task-output.types.js.map +1 -0
- package/dist/cli/backend/src/utils/file-io.utils.d.ts +102 -0
- package/dist/cli/backend/src/utils/file-io.utils.d.ts.map +1 -0
- package/dist/cli/backend/src/utils/file-io.utils.js +214 -0
- package/dist/cli/backend/src/utils/file-io.utils.js.map +1 -0
- package/dist/cli/backend/src/utils/terminal-output.utils.d.ts +54 -0
- package/dist/cli/backend/src/utils/terminal-output.utils.d.ts.map +1 -0
- package/dist/cli/backend/src/utils/terminal-output.utils.js +97 -0
- package/dist/cli/backend/src/utils/terminal-output.utils.js.map +1 -0
- package/dist/cli/cli/src/commands/mcp-server.d.ts +38 -0
- package/dist/cli/cli/src/commands/mcp-server.d.ts.map +1 -0
- package/dist/cli/cli/src/commands/mcp-server.js +49 -0
- package/dist/cli/cli/src/commands/mcp-server.js.map +1 -0
- package/dist/cli/cli/src/commands/onboard.d.ts +61 -7
- package/dist/cli/cli/src/commands/onboard.d.ts.map +1 -1
- package/dist/cli/cli/src/commands/onboard.js +192 -19
- package/dist/cli/cli/src/commands/onboard.js.map +1 -1
- package/dist/cli/cli/src/commands/publish.d.ts +27 -0
- package/dist/cli/cli/src/commands/publish.d.ts.map +1 -0
- package/dist/cli/cli/src/commands/publish.js +69 -0
- package/dist/cli/cli/src/commands/publish.js.map +1 -0
- package/dist/cli/cli/src/commands/start.d.ts.map +1 -1
- package/dist/cli/cli/src/commands/start.js +12 -2
- package/dist/cli/cli/src/commands/start.js.map +1 -1
- package/dist/cli/cli/src/index.js +14 -0
- package/dist/cli/cli/src/index.js.map +1 -1
- package/dist/cli/cli/src/utils/archive-creator.d.ts +82 -0
- package/dist/cli/cli/src/utils/archive-creator.d.ts.map +1 -0
- package/dist/cli/cli/src/utils/archive-creator.js +105 -0
- package/dist/cli/cli/src/utils/archive-creator.js.map +1 -0
- package/dist/cli/cli/src/utils/package-validator.d.ts +62 -0
- package/dist/cli/cli/src/utils/package-validator.d.ts.map +1 -0
- package/dist/cli/cli/src/utils/package-validator.js +122 -0
- package/dist/cli/cli/src/utils/package-validator.js.map +1 -0
- package/dist/cli/cli/src/utils/process-cleanup.d.ts +15 -0
- package/dist/cli/cli/src/utils/process-cleanup.d.ts.map +1 -0
- package/dist/cli/cli/src/utils/process-cleanup.js +76 -0
- package/dist/cli/cli/src/utils/process-cleanup.js.map +1 -0
- package/dist/cli/cli/src/utils/templates.d.ts +71 -0
- package/dist/cli/cli/src/utils/templates.d.ts.map +1 -0
- package/dist/cli/cli/src/utils/templates.js +91 -0
- package/dist/cli/cli/src/utils/templates.js.map +1 -0
- package/frontend/dist/assets/{index-523c7fce.js → index-68d1eb5a.js} +71 -71
- package/frontend/dist/assets/{index-4c050f52.css → index-c5043a83.css} +1 -1
- package/frontend/dist/assets/nunito-cyrillic-400-normal-e44e669f.woff2 +0 -0
- package/frontend/dist/assets/nunito-cyrillic-400-normal-ff8e8bdd.woff +0 -0
- package/frontend/dist/assets/nunito-cyrillic-500-normal-2159679b.woff +0 -0
- package/frontend/dist/assets/nunito-cyrillic-500-normal-61a3b80e.woff2 +0 -0
- package/frontend/dist/assets/nunito-cyrillic-600-normal-ac046097.woff +0 -0
- package/frontend/dist/assets/nunito-cyrillic-600-normal-e61eb97b.woff2 +0 -0
- package/frontend/dist/assets/nunito-cyrillic-700-normal-8fcefcc9.woff2 +0 -0
- package/frontend/dist/assets/nunito-cyrillic-700-normal-b9684104.woff +0 -0
- package/frontend/dist/assets/nunito-cyrillic-800-normal-40253beb.woff +0 -0
- package/frontend/dist/assets/nunito-cyrillic-800-normal-d80292de.woff2 +0 -0
- package/frontend/dist/assets/nunito-cyrillic-ext-400-normal-20d73ae7.woff2 +0 -0
- package/frontend/dist/assets/nunito-cyrillic-ext-400-normal-d48c37c9.woff +0 -0
- package/frontend/dist/assets/nunito-cyrillic-ext-500-normal-16197abd.woff +0 -0
- package/frontend/dist/assets/nunito-cyrillic-ext-500-normal-9dcfe9b5.woff2 +0 -0
- package/frontend/dist/assets/nunito-cyrillic-ext-600-normal-d53e9851.woff2 +0 -0
- package/frontend/dist/assets/nunito-cyrillic-ext-600-normal-e3d0201f.woff +0 -0
- package/frontend/dist/assets/nunito-cyrillic-ext-700-normal-5936f6ac.woff2 +0 -0
- package/frontend/dist/assets/nunito-cyrillic-ext-700-normal-c8c02775.woff +0 -0
- package/frontend/dist/assets/nunito-cyrillic-ext-800-normal-217b8f51.woff +0 -0
- package/frontend/dist/assets/nunito-cyrillic-ext-800-normal-796cf7bd.woff2 +0 -0
- package/frontend/dist/assets/nunito-latin-400-normal-a5906e15.woff2 +0 -0
- package/frontend/dist/assets/nunito-latin-400-normal-b51e7635.woff +0 -0
- package/frontend/dist/assets/nunito-latin-500-normal-23ae3083.woff2 +0 -0
- package/frontend/dist/assets/nunito-latin-500-normal-be14dbc6.woff +0 -0
- package/frontend/dist/assets/nunito-latin-600-normal-06a9c8b3.woff +0 -0
- package/frontend/dist/assets/nunito-latin-600-normal-45f437de.woff2 +0 -0
- package/frontend/dist/assets/nunito-latin-700-normal-ce9107dc.woff +0 -0
- package/frontend/dist/assets/nunito-latin-700-normal-fa89300b.woff2 +0 -0
- package/frontend/dist/assets/nunito-latin-800-normal-0ca02785.woff +0 -0
- package/frontend/dist/assets/nunito-latin-800-normal-2363d3ed.woff2 +0 -0
- package/frontend/dist/assets/nunito-latin-ext-400-normal-67250a41.woff2 +0 -0
- package/frontend/dist/assets/nunito-latin-ext-400-normal-d7e2415e.woff +0 -0
- package/frontend/dist/assets/nunito-latin-ext-500-normal-06f35d1c.woff +0 -0
- package/frontend/dist/assets/nunito-latin-ext-500-normal-343e7adc.woff2 +0 -0
- package/frontend/dist/assets/nunito-latin-ext-600-normal-5a8efd17.woff +0 -0
- package/frontend/dist/assets/nunito-latin-ext-600-normal-a7ba5f4f.woff2 +0 -0
- package/frontend/dist/assets/nunito-latin-ext-700-normal-0a4e4a02.woff2 +0 -0
- package/frontend/dist/assets/nunito-latin-ext-700-normal-0c607961.woff +0 -0
- package/frontend/dist/assets/nunito-latin-ext-800-normal-39f54b55.woff2 +0 -0
- package/frontend/dist/assets/nunito-latin-ext-800-normal-466d0211.woff +0 -0
- package/frontend/dist/assets/nunito-vietnamese-400-normal-2a755616.woff2 +0 -0
- package/frontend/dist/assets/nunito-vietnamese-400-normal-9c01ea9f.woff +0 -0
- package/frontend/dist/assets/nunito-vietnamese-500-normal-452e5e08.woff +0 -0
- package/frontend/dist/assets/nunito-vietnamese-500-normal-dc98d965.woff2 +0 -0
- package/frontend/dist/assets/nunito-vietnamese-600-normal-2ffbb85f.woff +0 -0
- package/frontend/dist/assets/nunito-vietnamese-600-normal-cf95b95d.woff2 +0 -0
- package/frontend/dist/assets/nunito-vietnamese-700-normal-0e29c28c.woff2 +0 -0
- package/frontend/dist/assets/nunito-vietnamese-700-normal-7793b75e.woff +0 -0
- package/frontend/dist/assets/nunito-vietnamese-800-normal-5baf507e.woff +0 -0
- package/frontend/dist/assets/nunito-vietnamese-800-normal-fac6740e.woff2 +0 -0
- package/frontend/dist/index.html +2 -2
- package/package.json +15 -5
|
@@ -0,0 +1,743 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chat Types Module
|
|
3
|
+
*
|
|
4
|
+
* Type definitions for the chat-based dashboard. Provides a conversational
|
|
5
|
+
* interface with the Orchestrator, transforming raw terminal output into
|
|
6
|
+
* clean, formatted chat messages.
|
|
7
|
+
*
|
|
8
|
+
* @module types/chat
|
|
9
|
+
*/
|
|
10
|
+
import { TERMINAL_FORMATTING_CONSTANTS } from '../constants.js';
|
|
11
|
+
import { stripAnsiCodes } from '../utils/terminal-output.utils.js';
|
|
12
|
+
// =============================================================================
|
|
13
|
+
// Enums and Constants
|
|
14
|
+
// =============================================================================
|
|
15
|
+
/**
|
|
16
|
+
* Valid sender types for chat messages
|
|
17
|
+
*/
|
|
18
|
+
export const CHAT_SENDER_TYPES = ['user', 'orchestrator', 'agent', 'system'];
|
|
19
|
+
/**
|
|
20
|
+
* Valid content types for chat messages
|
|
21
|
+
*/
|
|
22
|
+
export const CHAT_CONTENT_TYPES = [
|
|
23
|
+
'text',
|
|
24
|
+
'status',
|
|
25
|
+
'task',
|
|
26
|
+
'error',
|
|
27
|
+
'system',
|
|
28
|
+
'code',
|
|
29
|
+
'markdown',
|
|
30
|
+
];
|
|
31
|
+
/**
|
|
32
|
+
* Valid message status values
|
|
33
|
+
*/
|
|
34
|
+
export const CHAT_MESSAGE_STATUSES = ['sending', 'sent', 'delivered', 'error'];
|
|
35
|
+
/**
|
|
36
|
+
* Chat-related constants
|
|
37
|
+
*/
|
|
38
|
+
export const CHAT_CONSTANTS = {
|
|
39
|
+
/** Default limits */
|
|
40
|
+
DEFAULTS: {
|
|
41
|
+
/** Default message limit for pagination */
|
|
42
|
+
MESSAGE_LIMIT: 100,
|
|
43
|
+
/** Default conversation limit for pagination */
|
|
44
|
+
CONVERSATION_LIMIT: 50,
|
|
45
|
+
/** Maximum content length for last message preview */
|
|
46
|
+
PREVIEW_LENGTH: 100,
|
|
47
|
+
},
|
|
48
|
+
/** Response extraction patterns */
|
|
49
|
+
PATTERNS: {
|
|
50
|
+
/** Pattern names */
|
|
51
|
+
EXPLICIT: 'explicit',
|
|
52
|
+
CHAT: 'chat',
|
|
53
|
+
CODEBLOCK: 'codeblock',
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* Valid Slack delivery statuses for NOTIFY reconciliation
|
|
58
|
+
*/
|
|
59
|
+
export const SLACK_DELIVERY_STATUSES = ['pending', 'delivered', 'failed'];
|
|
60
|
+
/**
|
|
61
|
+
* Urgency levels for notifications
|
|
62
|
+
*/
|
|
63
|
+
export const NOTIFY_URGENCY_LEVELS = ['low', 'normal', 'high', 'critical'];
|
|
64
|
+
/**
|
|
65
|
+
* Check if a value is a valid NotifyPayload
|
|
66
|
+
*
|
|
67
|
+
* Validates that the payload has a required `message` string field
|
|
68
|
+
* and that optional fields have correct types when present.
|
|
69
|
+
*
|
|
70
|
+
* @param value - Value to check
|
|
71
|
+
* @returns True if value is a valid NotifyPayload
|
|
72
|
+
*/
|
|
73
|
+
export function isValidNotifyPayload(value) {
|
|
74
|
+
if (!value || typeof value !== 'object') {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
const payload = value;
|
|
78
|
+
// message is required and must be a non-empty string
|
|
79
|
+
if (typeof payload.message !== 'string' || !payload.message.trim()) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
// Optional string fields
|
|
83
|
+
const optionalStringFields = ['conversationId', 'channelId', 'threadTs', 'type', 'title'];
|
|
84
|
+
for (const field of optionalStringFields) {
|
|
85
|
+
if (payload[field] !== undefined && typeof payload[field] !== 'string') {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// urgency must be a valid level if present
|
|
90
|
+
if (payload.urgency !== undefined) {
|
|
91
|
+
if (typeof payload.urgency !== 'string' || !NOTIFY_URGENCY_LEVELS.includes(payload.urgency)) {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
/** Known header keys that can appear in NOTIFY blocks */
|
|
98
|
+
const KNOWN_HEADER_KEYS = new Set([
|
|
99
|
+
'conversationId', 'channelId', 'threadTs', 'type', 'title', 'urgency',
|
|
100
|
+
]);
|
|
101
|
+
/**
|
|
102
|
+
* TUI box-drawing and border characters used by Gemini CLI and other TUI tools.
|
|
103
|
+
* Matches common Unicode box-drawing chars and ASCII pipe characters.
|
|
104
|
+
*/
|
|
105
|
+
const TUI_BORDER_CHARS = /[│┃┆┇┊┋╎╏║|]/;
|
|
106
|
+
/**
|
|
107
|
+
* Strip TUI box-drawing border characters from content lines.
|
|
108
|
+
*
|
|
109
|
+
* Gemini CLI wraps terminal output in a TUI with box-drawing borders
|
|
110
|
+
* (│, ┃, |, etc.) that corrupt header parsing and leak into message bodies.
|
|
111
|
+
* This function removes leading/trailing border chars and associated whitespace
|
|
112
|
+
* from each line, plus removes pure border/decoration lines (─, ┌, └, etc.).
|
|
113
|
+
*
|
|
114
|
+
* @param content - Content that may contain TUI border artifacts
|
|
115
|
+
* @returns Content with TUI borders stripped from each line
|
|
116
|
+
*/
|
|
117
|
+
function stripTuiBorders(content) {
|
|
118
|
+
return content
|
|
119
|
+
.split('\n')
|
|
120
|
+
.map((line) => {
|
|
121
|
+
// Preserve --- separator lines (used for header-body split)
|
|
122
|
+
if (/^\s*---\s*$/.test(line)) {
|
|
123
|
+
return '---';
|
|
124
|
+
}
|
|
125
|
+
// Skip pure decoration lines (box corners, horizontal rules)
|
|
126
|
+
// that contain only box-drawing characters, not regular dashes
|
|
127
|
+
if (/^[\s│┃┆┇┊┋╎╏║─━┄┅┈┉╌╍═┌┐└┘├┤┬┴┼╔╗╚╝╠╣╦╩╬╭╮╰╯]+$/.test(line)) {
|
|
128
|
+
return '';
|
|
129
|
+
}
|
|
130
|
+
// Strip leading border chars and adjacent whitespace, and trailing whitespace + border chars.
|
|
131
|
+
// Only strip whitespace that's adjacent to an actual border character to avoid
|
|
132
|
+
// stripping meaningful whitespace from PTY-wrapped JSON continuation lines.
|
|
133
|
+
return line
|
|
134
|
+
.replace(/^[│┃┆┇┊┋╎╏║|]+\s*/, '')
|
|
135
|
+
.replace(/\s*[│┃┆┇┊┋╎╏║|]+$/, '');
|
|
136
|
+
})
|
|
137
|
+
.join('\n');
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Attempt to parse headers from content where a blank line is used as separator
|
|
141
|
+
* instead of `---`. This handles the common LLM behavior of omitting the `---`.
|
|
142
|
+
*
|
|
143
|
+
* Only activates if the first line matches a known header key pattern.
|
|
144
|
+
*
|
|
145
|
+
* @param cleaned - ANSI-stripped, trimmed content
|
|
146
|
+
* @returns Object with headers and body strings, or null if not header-like
|
|
147
|
+
*/
|
|
148
|
+
function parseHeadersWithBlankLineSeparator(cleaned) {
|
|
149
|
+
// Check if first line looks like a known header
|
|
150
|
+
const firstNewline = cleaned.indexOf('\n');
|
|
151
|
+
if (firstNewline === -1)
|
|
152
|
+
return null;
|
|
153
|
+
const firstLine = cleaned.slice(0, firstNewline).trim();
|
|
154
|
+
const colonIdx = firstLine.indexOf(':');
|
|
155
|
+
if (colonIdx === -1)
|
|
156
|
+
return null;
|
|
157
|
+
const firstKey = firstLine.slice(0, colonIdx).trim();
|
|
158
|
+
if (!KNOWN_HEADER_KEYS.has(firstKey))
|
|
159
|
+
return null;
|
|
160
|
+
// Split on first blank line (two consecutive newlines)
|
|
161
|
+
const blankMatch = cleaned.match(/^([\s\S]*?)\n\s*\n([\s\S]*)$/);
|
|
162
|
+
if (!blankMatch)
|
|
163
|
+
return null;
|
|
164
|
+
const headers = blankMatch[1].trim();
|
|
165
|
+
const body = blankMatch[2].trim();
|
|
166
|
+
if (!body)
|
|
167
|
+
return null;
|
|
168
|
+
return { headers, body };
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Parse raw content from a [NOTIFY]...[/NOTIFY] block into a NotifyPayload.
|
|
172
|
+
*
|
|
173
|
+
* Supports three formats:
|
|
174
|
+
* 1. **Header+body with `---`** (preferred): key-value headers before a `---` separator,
|
|
175
|
+
* with the message body after it. Headers are short (~25 chars), so they are
|
|
176
|
+
* never corrupted by PTY line-wrapping.
|
|
177
|
+
* 2. **Header+body with blank line** (fallback): same as above but with a blank
|
|
178
|
+
* line instead of `---`. Activated only when the first line is a known header.
|
|
179
|
+
* 3. **Legacy JSON** (fallback): if the content starts with `{`, it is parsed as
|
|
180
|
+
* JSON with PTY artifact cleanup for backward compatibility.
|
|
181
|
+
*
|
|
182
|
+
* @param raw - Raw content between [NOTIFY] and [/NOTIFY] markers
|
|
183
|
+
* @returns Parsed NotifyPayload or null if content is invalid
|
|
184
|
+
*
|
|
185
|
+
* @example
|
|
186
|
+
* ```typescript
|
|
187
|
+
* // Header+body format
|
|
188
|
+
* const payload = parseNotifyContent(
|
|
189
|
+
* 'conversationId: conv-abc\ntype: task_completed\n---\n## Done\nTask finished.'
|
|
190
|
+
* );
|
|
191
|
+
* // => { message: '## Done\nTask finished.', conversationId: 'conv-abc', type: 'task_completed' }
|
|
192
|
+
*
|
|
193
|
+
* // Legacy JSON format (auto-detected)
|
|
194
|
+
* const legacy = parseNotifyContent('{"message":"Hello","conversationId":"conv-1"}');
|
|
195
|
+
* // => { message: 'Hello', conversationId: 'conv-1' }
|
|
196
|
+
* ```
|
|
197
|
+
*/
|
|
198
|
+
export function parseNotifyContent(raw) {
|
|
199
|
+
// Strip ANSI escape sequences using the canonical utility, then strip
|
|
200
|
+
// TUI box-drawing borders (Gemini CLI wraps output in │...│ borders)
|
|
201
|
+
const cleaned = stripTuiBorders(stripAnsiCodes(raw)).trim();
|
|
202
|
+
if (!cleaned) {
|
|
203
|
+
return null;
|
|
204
|
+
}
|
|
205
|
+
// JSON fallback for transition period
|
|
206
|
+
if (cleaned.startsWith('{')) {
|
|
207
|
+
return parseLegacyJsonNotify(cleaned);
|
|
208
|
+
}
|
|
209
|
+
// Split on --- separator line (separator may be followed by content or end of string)
|
|
210
|
+
// The \n before --- is optional to handle content that starts directly with ---
|
|
211
|
+
const sepMatch = cleaned.match(/^([\s\S]*?)(?:^|\n)---(?:\n([\s\S]*))?$/);
|
|
212
|
+
let headerSection;
|
|
213
|
+
let body;
|
|
214
|
+
if (sepMatch) {
|
|
215
|
+
headerSection = sepMatch[1].trim();
|
|
216
|
+
body = (sepMatch[2] || '').trim();
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
// Fallback: LLMs sometimes use a blank line instead of ---
|
|
220
|
+
// If the content starts with known header-like lines, split on first blank line
|
|
221
|
+
const blankLineResult = parseHeadersWithBlankLineSeparator(cleaned);
|
|
222
|
+
if (blankLineResult) {
|
|
223
|
+
headerSection = blankLineResult.headers;
|
|
224
|
+
body = blankLineResult.body;
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
// No headers — entire content is the message
|
|
228
|
+
const msg = cleaned.trim();
|
|
229
|
+
return msg ? { message: msg } : null;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
if (!body) {
|
|
233
|
+
return null;
|
|
234
|
+
}
|
|
235
|
+
const payload = { message: body };
|
|
236
|
+
for (const line of headerSection.split('\n')) {
|
|
237
|
+
const colonIdx = line.indexOf(':');
|
|
238
|
+
if (colonIdx === -1)
|
|
239
|
+
continue;
|
|
240
|
+
const key = line.slice(0, colonIdx).trim();
|
|
241
|
+
const value = line.slice(colonIdx + 1).trim();
|
|
242
|
+
if (!value)
|
|
243
|
+
continue;
|
|
244
|
+
switch (key) {
|
|
245
|
+
case 'conversationId':
|
|
246
|
+
payload.conversationId = value;
|
|
247
|
+
break;
|
|
248
|
+
case 'channelId':
|
|
249
|
+
payload.channelId = value;
|
|
250
|
+
break;
|
|
251
|
+
case 'threadTs':
|
|
252
|
+
payload.threadTs = value;
|
|
253
|
+
break;
|
|
254
|
+
case 'type':
|
|
255
|
+
payload.type = value;
|
|
256
|
+
break;
|
|
257
|
+
case 'title':
|
|
258
|
+
payload.title = value;
|
|
259
|
+
break;
|
|
260
|
+
case 'urgency':
|
|
261
|
+
if (NOTIFY_URGENCY_LEVELS.includes(value)) {
|
|
262
|
+
payload.urgency = value;
|
|
263
|
+
}
|
|
264
|
+
break;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return payload;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Parse legacy JSON notify content with PTY artifact cleanup.
|
|
271
|
+
*
|
|
272
|
+
* Cleans terminal line-wrapping artifacts (newlines, padding spaces, orphaned
|
|
273
|
+
* ANSI sequences) before parsing as JSON, then validates via isValidNotifyPayload.
|
|
274
|
+
*
|
|
275
|
+
* @param cleaned - Pre-cleaned content that starts with '{'
|
|
276
|
+
* @returns Parsed NotifyPayload or null if parsing/validation fails
|
|
277
|
+
*/
|
|
278
|
+
function parseLegacyJsonNotify(cleaned) {
|
|
279
|
+
const jsonCleaned = cleaned
|
|
280
|
+
.replace(/[\r\n]+\s*/g, '') // remove newlines and trailing padding (PTY indent)
|
|
281
|
+
.replace(/\s{2,}/g, ' '); // collapse remaining multi-space runs
|
|
282
|
+
try {
|
|
283
|
+
const parsed = JSON.parse(jsonCleaned);
|
|
284
|
+
if (!isValidNotifyPayload(parsed)) {
|
|
285
|
+
return null;
|
|
286
|
+
}
|
|
287
|
+
return parsed;
|
|
288
|
+
}
|
|
289
|
+
catch {
|
|
290
|
+
return null;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
// =============================================================================
|
|
294
|
+
// Type Guards
|
|
295
|
+
// =============================================================================
|
|
296
|
+
/**
|
|
297
|
+
* Check if a value is a valid sender type
|
|
298
|
+
*
|
|
299
|
+
* @param value - Value to check
|
|
300
|
+
* @returns True if value is a valid ChatSenderType
|
|
301
|
+
*/
|
|
302
|
+
export function isValidSenderType(value) {
|
|
303
|
+
return CHAT_SENDER_TYPES.includes(value);
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Check if a value is a valid content type
|
|
307
|
+
*
|
|
308
|
+
* @param value - Value to check
|
|
309
|
+
* @returns True if value is a valid ChatContentType
|
|
310
|
+
*/
|
|
311
|
+
export function isValidContentType(value) {
|
|
312
|
+
return CHAT_CONTENT_TYPES.includes(value);
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Check if a value is a valid message status
|
|
316
|
+
*
|
|
317
|
+
* @param value - Value to check
|
|
318
|
+
* @returns True if value is a valid ChatMessageStatus
|
|
319
|
+
*/
|
|
320
|
+
export function isValidMessageStatus(value) {
|
|
321
|
+
return CHAT_MESSAGE_STATUSES.includes(value);
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Check if an object is a valid ChatSender
|
|
325
|
+
*
|
|
326
|
+
* @param value - Value to check
|
|
327
|
+
* @returns True if value is a valid ChatSender object
|
|
328
|
+
*/
|
|
329
|
+
export function isValidChatSender(value) {
|
|
330
|
+
if (!value || typeof value !== 'object') {
|
|
331
|
+
return false;
|
|
332
|
+
}
|
|
333
|
+
const sender = value;
|
|
334
|
+
if (typeof sender.type !== 'string' || !isValidSenderType(sender.type)) {
|
|
335
|
+
return false;
|
|
336
|
+
}
|
|
337
|
+
if (sender.id !== undefined && typeof sender.id !== 'string') {
|
|
338
|
+
return false;
|
|
339
|
+
}
|
|
340
|
+
if (sender.name !== undefined && typeof sender.name !== 'string') {
|
|
341
|
+
return false;
|
|
342
|
+
}
|
|
343
|
+
if (sender.role !== undefined && typeof sender.role !== 'string') {
|
|
344
|
+
return false;
|
|
345
|
+
}
|
|
346
|
+
return true;
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Check if an object is a valid ChatMessage
|
|
350
|
+
*
|
|
351
|
+
* @param value - Value to check
|
|
352
|
+
* @returns True if value is a valid ChatMessage object
|
|
353
|
+
*/
|
|
354
|
+
export function isValidChatMessage(value) {
|
|
355
|
+
if (!value || typeof value !== 'object') {
|
|
356
|
+
return false;
|
|
357
|
+
}
|
|
358
|
+
const message = value;
|
|
359
|
+
if (typeof message.id !== 'string' || !message.id) {
|
|
360
|
+
return false;
|
|
361
|
+
}
|
|
362
|
+
if (typeof message.conversationId !== 'string' || !message.conversationId) {
|
|
363
|
+
return false;
|
|
364
|
+
}
|
|
365
|
+
if (!isValidChatSender(message.from)) {
|
|
366
|
+
return false;
|
|
367
|
+
}
|
|
368
|
+
if (typeof message.content !== 'string') {
|
|
369
|
+
return false;
|
|
370
|
+
}
|
|
371
|
+
if (typeof message.contentType !== 'string' || !isValidContentType(message.contentType)) {
|
|
372
|
+
return false;
|
|
373
|
+
}
|
|
374
|
+
if (typeof message.status !== 'string' || !isValidMessageStatus(message.status)) {
|
|
375
|
+
return false;
|
|
376
|
+
}
|
|
377
|
+
if (typeof message.timestamp !== 'string') {
|
|
378
|
+
return false;
|
|
379
|
+
}
|
|
380
|
+
return true;
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Check if an object is a valid ChatConversation
|
|
384
|
+
*
|
|
385
|
+
* @param value - Value to check
|
|
386
|
+
* @returns True if value is a valid ChatConversation object
|
|
387
|
+
*/
|
|
388
|
+
export function isValidChatConversation(value) {
|
|
389
|
+
if (!value || typeof value !== 'object') {
|
|
390
|
+
return false;
|
|
391
|
+
}
|
|
392
|
+
const conv = value;
|
|
393
|
+
if (typeof conv.id !== 'string' || !conv.id) {
|
|
394
|
+
return false;
|
|
395
|
+
}
|
|
396
|
+
if (!Array.isArray(conv.participantIds)) {
|
|
397
|
+
return false;
|
|
398
|
+
}
|
|
399
|
+
if (typeof conv.createdAt !== 'string') {
|
|
400
|
+
return false;
|
|
401
|
+
}
|
|
402
|
+
if (typeof conv.updatedAt !== 'string') {
|
|
403
|
+
return false;
|
|
404
|
+
}
|
|
405
|
+
if (typeof conv.isArchived !== 'boolean') {
|
|
406
|
+
return false;
|
|
407
|
+
}
|
|
408
|
+
if (typeof conv.messageCount !== 'number') {
|
|
409
|
+
return false;
|
|
410
|
+
}
|
|
411
|
+
return true;
|
|
412
|
+
}
|
|
413
|
+
// =============================================================================
|
|
414
|
+
// Utility Functions
|
|
415
|
+
// =============================================================================
|
|
416
|
+
/**
|
|
417
|
+
* Generate a unique ID for chat entities
|
|
418
|
+
*
|
|
419
|
+
* @returns A unique identifier string
|
|
420
|
+
*/
|
|
421
|
+
export function generateChatId() {
|
|
422
|
+
return crypto.randomUUID();
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Create a chat message with defaults
|
|
426
|
+
*
|
|
427
|
+
* @param input - Partial message input with required fields
|
|
428
|
+
* @returns A complete ChatMessage object
|
|
429
|
+
*
|
|
430
|
+
* @example
|
|
431
|
+
* ```typescript
|
|
432
|
+
* const message = createChatMessage({
|
|
433
|
+
* conversationId: 'conv-1',
|
|
434
|
+
* content: 'Hello!',
|
|
435
|
+
* from: { type: 'user' },
|
|
436
|
+
* });
|
|
437
|
+
* ```
|
|
438
|
+
*/
|
|
439
|
+
export function createChatMessage(input) {
|
|
440
|
+
return {
|
|
441
|
+
id: generateChatId(),
|
|
442
|
+
conversationId: input.conversationId,
|
|
443
|
+
from: input.from,
|
|
444
|
+
content: input.content,
|
|
445
|
+
contentType: input.contentType ?? 'text',
|
|
446
|
+
status: input.status ?? 'sent',
|
|
447
|
+
timestamp: input.timestamp ?? new Date().toISOString(),
|
|
448
|
+
metadata: input.metadata,
|
|
449
|
+
parentId: input.parentId,
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* Create a conversation with defaults
|
|
454
|
+
*
|
|
455
|
+
* @param title - Optional title for the conversation
|
|
456
|
+
* @returns A new ChatConversation object
|
|
457
|
+
*
|
|
458
|
+
* @example
|
|
459
|
+
* ```typescript
|
|
460
|
+
* const conversation = createConversation('Project Discussion');
|
|
461
|
+
* ```
|
|
462
|
+
*/
|
|
463
|
+
export function createConversation(title, idOverride) {
|
|
464
|
+
const now = new Date().toISOString();
|
|
465
|
+
return {
|
|
466
|
+
id: idOverride ?? generateChatId(),
|
|
467
|
+
title,
|
|
468
|
+
participantIds: [],
|
|
469
|
+
createdAt: now,
|
|
470
|
+
updatedAt: now,
|
|
471
|
+
isArchived: false,
|
|
472
|
+
messageCount: 0,
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* Format message content by cleaning terminal output
|
|
477
|
+
*
|
|
478
|
+
* Removes ANSI escape codes, control characters, carriage returns (which cause
|
|
479
|
+
* text to overwrite itself in terminals), and trims whitespace.
|
|
480
|
+
*
|
|
481
|
+
* @param content - Raw content to format
|
|
482
|
+
* @returns Cleaned content string
|
|
483
|
+
*
|
|
484
|
+
* @example
|
|
485
|
+
* ```typescript
|
|
486
|
+
* const clean = formatMessageContent('\x1b[32mGreen text\x1b[0m');
|
|
487
|
+
* // Returns: 'Green text'
|
|
488
|
+
* ```
|
|
489
|
+
*/
|
|
490
|
+
export function formatMessageContent(content) {
|
|
491
|
+
let cleaned = content;
|
|
492
|
+
// IMPORTANT: Convert cursor movement sequences to spaces BEFORE stripping other ANSI codes
|
|
493
|
+
// Terminal uses \x1b[nC (cursor forward n positions) to create visual spacing
|
|
494
|
+
// We need to convert these to actual spaces to preserve word separation
|
|
495
|
+
// Uses TERMINAL_FORMATTING_CONSTANTS.MAX_CURSOR_REPEAT to cap repeat count
|
|
496
|
+
const maxRepeat = TERMINAL_FORMATTING_CONSTANTS.MAX_CURSOR_REPEAT;
|
|
497
|
+
cleaned = cleaned.replace(/\x1b\[(\d+)C/g, (_match, count) => {
|
|
498
|
+
const num = parseInt(count, 10);
|
|
499
|
+
if (Number.isNaN(num) || num < 0)
|
|
500
|
+
return '';
|
|
501
|
+
return ' '.repeat(Math.min(num, maxRepeat));
|
|
502
|
+
});
|
|
503
|
+
// Convert cursor down sequences to newlines
|
|
504
|
+
cleaned = cleaned.replace(/\x1b\[(\d+)B/g, (_match, count) => {
|
|
505
|
+
const num = parseInt(count, 10);
|
|
506
|
+
if (Number.isNaN(num) || num < 0)
|
|
507
|
+
return '';
|
|
508
|
+
return '\n'.repeat(Math.min(num, maxRepeat));
|
|
509
|
+
});
|
|
510
|
+
// Remove ANSI color/style codes (SGR sequences)
|
|
511
|
+
cleaned = cleaned.replace(/\x1b\[[0-9;]*m/g, '');
|
|
512
|
+
// Remove remaining ANSI escape sequences (cursor position, clear screen, etc.)
|
|
513
|
+
cleaned = cleaned.replace(/\x1b\[[0-9;]*[A-Za-z]/g, '');
|
|
514
|
+
// Remove OSC (Operating System Command) sequences (e.g., terminal title changes)
|
|
515
|
+
cleaned = cleaned.replace(/\x1b\][^\x07]*\x07/g, '');
|
|
516
|
+
// Remove CSI sequences that might not be caught above
|
|
517
|
+
cleaned = cleaned.replace(/\x1b\[[\x30-\x3f]*[\x20-\x2f]*[\x40-\x7e]/g, '');
|
|
518
|
+
// Handle carriage returns - terminal uses \r to return cursor to start of line
|
|
519
|
+
// This can cause text overwriting. Split by \r and keep the last segment of each line
|
|
520
|
+
cleaned = cleaned
|
|
521
|
+
.split('\n')
|
|
522
|
+
.map((line) => {
|
|
523
|
+
// If line contains \r, split by it and keep the last non-empty segment
|
|
524
|
+
if (line.includes('\r')) {
|
|
525
|
+
const segments = line.split('\r');
|
|
526
|
+
// Find the last non-empty segment
|
|
527
|
+
for (let i = segments.length - 1; i >= 0; i--) {
|
|
528
|
+
if (segments[i].trim()) {
|
|
529
|
+
return segments[i];
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
return '';
|
|
533
|
+
}
|
|
534
|
+
return line;
|
|
535
|
+
})
|
|
536
|
+
.join('\n');
|
|
537
|
+
// Clean orphaned CSI fragments from PTY buffer boundary splits.
|
|
538
|
+
// When ESC char lands in one chunk and the CSI params in the next,
|
|
539
|
+
// artifacts like "[1C" or "[22m" appear mid-word.
|
|
540
|
+
// Note: \d+ (one or more digits) to avoid matching [C in [CHAT_RESPONSE]
|
|
541
|
+
// Multi-param CSI like [38;2;249;226;175m from Gemini CLI truecolor output
|
|
542
|
+
cleaned = cleaned.replace(/\[\d+C/g, ' ');
|
|
543
|
+
cleaned = cleaned.replace(/\[\d+(?:;\d+)*[A-BJKHfm]/g, '');
|
|
544
|
+
// Remove other control characters except newlines and tabs
|
|
545
|
+
cleaned = cleaned.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, '');
|
|
546
|
+
// Normalize multiple consecutive spaces to single space (but preserve newlines)
|
|
547
|
+
cleaned = cleaned.replace(/ +/g, ' ');
|
|
548
|
+
// Clean up multiple blank lines (more than 2 consecutive newlines become 2)
|
|
549
|
+
cleaned = cleaned.replace(/\n{3,}/g, '\n\n');
|
|
550
|
+
// Trim whitespace from each line and remove leading/trailing whitespace
|
|
551
|
+
cleaned = cleaned
|
|
552
|
+
.split('\n')
|
|
553
|
+
.map((line) => line.trim())
|
|
554
|
+
.join('\n')
|
|
555
|
+
.trim();
|
|
556
|
+
return cleaned;
|
|
557
|
+
}
|
|
558
|
+
/**
|
|
559
|
+
* Default response extraction patterns
|
|
560
|
+
*/
|
|
561
|
+
export const DEFAULT_RESPONSE_PATTERNS = [
|
|
562
|
+
{
|
|
563
|
+
name: CHAT_CONSTANTS.PATTERNS.EXPLICIT,
|
|
564
|
+
pattern: /\[RESPONSE\]([\s\S]*?)\[\/RESPONSE\]/i,
|
|
565
|
+
groupIndex: 1,
|
|
566
|
+
},
|
|
567
|
+
{
|
|
568
|
+
name: CHAT_CONSTANTS.PATTERNS.CHAT,
|
|
569
|
+
pattern: /\[CHAT_RESPONSE(?::[^\]]*)?\]([\s\S]*?)\[\/CHAT_RESPONSE\]/i,
|
|
570
|
+
groupIndex: 1,
|
|
571
|
+
},
|
|
572
|
+
{
|
|
573
|
+
name: CHAT_CONSTANTS.PATTERNS.CODEBLOCK,
|
|
574
|
+
pattern: /```response\n([\s\S]*?)```/i,
|
|
575
|
+
groupIndex: 1,
|
|
576
|
+
},
|
|
577
|
+
];
|
|
578
|
+
/**
|
|
579
|
+
* Extract response from raw output using patterns
|
|
580
|
+
*
|
|
581
|
+
* Tries multiple patterns to extract the clean response from
|
|
582
|
+
* raw terminal output. Returns the original output if no pattern matches.
|
|
583
|
+
*
|
|
584
|
+
* @param rawOutput - Raw terminal output
|
|
585
|
+
* @param customPatterns - Optional custom patterns to use instead of defaults
|
|
586
|
+
* @returns Extracted response content
|
|
587
|
+
*
|
|
588
|
+
* @example
|
|
589
|
+
* ```typescript
|
|
590
|
+
* const response = extractResponseFromOutput(
|
|
591
|
+
* 'some text [RESPONSE]Hello World[/RESPONSE] more text'
|
|
592
|
+
* );
|
|
593
|
+
* // Returns: 'Hello World'
|
|
594
|
+
* ```
|
|
595
|
+
*/
|
|
596
|
+
export function extractResponseFromOutput(rawOutput, customPatterns) {
|
|
597
|
+
const patterns = customPatterns ?? DEFAULT_RESPONSE_PATTERNS;
|
|
598
|
+
for (const { pattern, groupIndex = 1 } of patterns) {
|
|
599
|
+
const match = rawOutput.match(pattern);
|
|
600
|
+
// Check if match exists and has the capture group (even if empty string)
|
|
601
|
+
if (match && match[groupIndex] !== undefined) {
|
|
602
|
+
return match[groupIndex].trim();
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
// No pattern matched, return original output
|
|
606
|
+
return rawOutput;
|
|
607
|
+
}
|
|
608
|
+
/**
|
|
609
|
+
* Detect the content type of a message based on its content
|
|
610
|
+
*
|
|
611
|
+
* @param content - Message content to analyze
|
|
612
|
+
* @returns Detected content type
|
|
613
|
+
*
|
|
614
|
+
* @example
|
|
615
|
+
* ```typescript
|
|
616
|
+
* const type = detectContentType('## Heading\n- Item');
|
|
617
|
+
* // Returns: 'markdown'
|
|
618
|
+
* ```
|
|
619
|
+
*/
|
|
620
|
+
export function detectContentType(content) {
|
|
621
|
+
// Check for markdown indicators
|
|
622
|
+
if (content.includes('```') ||
|
|
623
|
+
content.includes('##') ||
|
|
624
|
+
content.includes('**') ||
|
|
625
|
+
/^[-*] /.test(content) ||
|
|
626
|
+
/^\d+\. /.test(content)) {
|
|
627
|
+
return 'markdown';
|
|
628
|
+
}
|
|
629
|
+
// Check for code patterns
|
|
630
|
+
if (content.includes('function ') ||
|
|
631
|
+
content.includes('const ') ||
|
|
632
|
+
content.includes('import ') ||
|
|
633
|
+
content.includes('export ') ||
|
|
634
|
+
content.includes('class ') ||
|
|
635
|
+
/^(let|var)\s/.test(content)) {
|
|
636
|
+
return 'code';
|
|
637
|
+
}
|
|
638
|
+
// Check for error patterns
|
|
639
|
+
if (content.toLowerCase().includes('error:') ||
|
|
640
|
+
content.toLowerCase().includes('exception:') ||
|
|
641
|
+
content.includes('Error:') ||
|
|
642
|
+
content.includes('Failed:')) {
|
|
643
|
+
return 'error';
|
|
644
|
+
}
|
|
645
|
+
return 'text';
|
|
646
|
+
}
|
|
647
|
+
/**
|
|
648
|
+
* Create a last message preview from a chat message
|
|
649
|
+
*
|
|
650
|
+
* @param message - The chat message to create preview from
|
|
651
|
+
* @param maxLength - Maximum content length (default: CHAT_CONSTANTS.DEFAULTS.PREVIEW_LENGTH)
|
|
652
|
+
* @returns A LastMessagePreview object
|
|
653
|
+
*/
|
|
654
|
+
export function createLastMessagePreview(message, maxLength = CHAT_CONSTANTS.DEFAULTS.PREVIEW_LENGTH) {
|
|
655
|
+
let previewContent = message.content;
|
|
656
|
+
if (previewContent.length > maxLength) {
|
|
657
|
+
previewContent = previewContent.slice(0, maxLength - 3) + '...';
|
|
658
|
+
}
|
|
659
|
+
return {
|
|
660
|
+
content: previewContent,
|
|
661
|
+
timestamp: message.timestamp,
|
|
662
|
+
from: message.from,
|
|
663
|
+
};
|
|
664
|
+
}
|
|
665
|
+
/**
|
|
666
|
+
* Validate SendMessageInput
|
|
667
|
+
*
|
|
668
|
+
* @param input - Input to validate
|
|
669
|
+
* @returns Object with valid flag and optional error message
|
|
670
|
+
*/
|
|
671
|
+
export function validateSendMessageInput(input) {
|
|
672
|
+
if (!input || typeof input !== 'object') {
|
|
673
|
+
return { valid: false, error: 'Input must be an object' };
|
|
674
|
+
}
|
|
675
|
+
const data = input;
|
|
676
|
+
if (typeof data.content !== 'string') {
|
|
677
|
+
return { valid: false, error: 'Content must be a string' };
|
|
678
|
+
}
|
|
679
|
+
if (data.content.trim().length === 0) {
|
|
680
|
+
return { valid: false, error: 'Content cannot be empty' };
|
|
681
|
+
}
|
|
682
|
+
if (data.conversationId !== undefined && typeof data.conversationId !== 'string') {
|
|
683
|
+
return { valid: false, error: 'ConversationId must be a string' };
|
|
684
|
+
}
|
|
685
|
+
if (data.metadata !== undefined && (typeof data.metadata !== 'object' || data.metadata === null)) {
|
|
686
|
+
return { valid: false, error: 'Metadata must be an object' };
|
|
687
|
+
}
|
|
688
|
+
return { valid: true };
|
|
689
|
+
}
|
|
690
|
+
/**
|
|
691
|
+
* Validate ChatMessageFilter
|
|
692
|
+
*
|
|
693
|
+
* @param filter - Filter to validate
|
|
694
|
+
* @returns Object with valid flag and optional error message
|
|
695
|
+
*/
|
|
696
|
+
export function validateChatMessageFilter(filter) {
|
|
697
|
+
if (!filter || typeof filter !== 'object') {
|
|
698
|
+
return { valid: false, error: 'Filter must be an object' };
|
|
699
|
+
}
|
|
700
|
+
const data = filter;
|
|
701
|
+
if (data.conversationId !== undefined && typeof data.conversationId !== 'string') {
|
|
702
|
+
return { valid: false, error: 'ConversationId must be a string' };
|
|
703
|
+
}
|
|
704
|
+
if (data.senderType !== undefined && !isValidSenderType(data.senderType)) {
|
|
705
|
+
return { valid: false, error: 'Invalid sender type' };
|
|
706
|
+
}
|
|
707
|
+
if (data.contentType !== undefined && !isValidContentType(data.contentType)) {
|
|
708
|
+
return { valid: false, error: 'Invalid content type' };
|
|
709
|
+
}
|
|
710
|
+
if (data.limit !== undefined && (typeof data.limit !== 'number' || data.limit < 1)) {
|
|
711
|
+
return { valid: false, error: 'Limit must be a positive number' };
|
|
712
|
+
}
|
|
713
|
+
if (data.offset !== undefined && (typeof data.offset !== 'number' || data.offset < 0)) {
|
|
714
|
+
return { valid: false, error: 'Offset must be a non-negative number' };
|
|
715
|
+
}
|
|
716
|
+
return { valid: true };
|
|
717
|
+
}
|
|
718
|
+
/**
|
|
719
|
+
* Validate ConversationFilter
|
|
720
|
+
*
|
|
721
|
+
* @param filter - Filter to validate
|
|
722
|
+
* @returns Object with valid flag and optional error message
|
|
723
|
+
*/
|
|
724
|
+
export function validateConversationFilter(filter) {
|
|
725
|
+
if (!filter || typeof filter !== 'object') {
|
|
726
|
+
return { valid: false, error: 'Filter must be an object' };
|
|
727
|
+
}
|
|
728
|
+
const data = filter;
|
|
729
|
+
if (data.includeArchived !== undefined && typeof data.includeArchived !== 'boolean') {
|
|
730
|
+
return { valid: false, error: 'IncludeArchived must be a boolean' };
|
|
731
|
+
}
|
|
732
|
+
if (data.search !== undefined && typeof data.search !== 'string') {
|
|
733
|
+
return { valid: false, error: 'Search must be a string' };
|
|
734
|
+
}
|
|
735
|
+
if (data.limit !== undefined && (typeof data.limit !== 'number' || data.limit < 1)) {
|
|
736
|
+
return { valid: false, error: 'Limit must be a positive number' };
|
|
737
|
+
}
|
|
738
|
+
if (data.offset !== undefined && (typeof data.offset !== 'number' || data.offset < 0)) {
|
|
739
|
+
return { valid: false, error: 'Offset must be a non-negative number' };
|
|
740
|
+
}
|
|
741
|
+
return { valid: true };
|
|
742
|
+
}
|
|
743
|
+
//# sourceMappingURL=chat.types.js.map
|