hungry-ghost-hive 0.3.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 +111 -0
- package/README.md +352 -0
- package/dist/agents/base-agent.d.ts +63 -0
- package/dist/agents/base-agent.d.ts.map +1 -0
- package/dist/agents/base-agent.js +189 -0
- package/dist/agents/base-agent.js.map +1 -0
- package/dist/agents/index.d.ts +7 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/index.js +7 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/intermediate.d.ts +15 -0
- package/dist/agents/intermediate.d.ts.map +1 -0
- package/dist/agents/intermediate.js +142 -0
- package/dist/agents/intermediate.js.map +1 -0
- package/dist/agents/junior.d.ts +15 -0
- package/dist/agents/junior.d.ts.map +1 -0
- package/dist/agents/junior.js +147 -0
- package/dist/agents/junior.js.map +1 -0
- package/dist/agents/qa.d.ts +23 -0
- package/dist/agents/qa.d.ts.map +1 -0
- package/dist/agents/qa.js +238 -0
- package/dist/agents/qa.js.map +1 -0
- package/dist/agents/senior.d.ts +18 -0
- package/dist/agents/senior.d.ts.map +1 -0
- package/dist/agents/senior.js +267 -0
- package/dist/agents/senior.js.map +1 -0
- package/dist/agents/tech-lead.d.ts +17 -0
- package/dist/agents/tech-lead.d.ts.map +1 -0
- package/dist/agents/tech-lead.js +274 -0
- package/dist/agents/tech-lead.js.map +1 -0
- package/dist/cli/commands/add-repo.d.ts +3 -0
- package/dist/cli/commands/add-repo.d.ts.map +1 -0
- package/dist/cli/commands/add-repo.js +84 -0
- package/dist/cli/commands/add-repo.js.map +1 -0
- package/dist/cli/commands/agents.d.ts +3 -0
- package/dist/cli/commands/agents.d.ts.map +1 -0
- package/dist/cli/commands/agents.js +214 -0
- package/dist/cli/commands/agents.js.map +1 -0
- package/dist/cli/commands/assign.d.ts +3 -0
- package/dist/cli/commands/assign.d.ts.map +1 -0
- package/dist/cli/commands/assign.js +81 -0
- package/dist/cli/commands/assign.js.map +1 -0
- package/dist/cli/commands/config.d.ts +3 -0
- package/dist/cli/commands/config.d.ts.map +1 -0
- package/dist/cli/commands/config.js +118 -0
- package/dist/cli/commands/config.js.map +1 -0
- package/dist/cli/commands/escalations.d.ts +3 -0
- package/dist/cli/commands/escalations.d.ts.map +1 -0
- package/dist/cli/commands/escalations.js +157 -0
- package/dist/cli/commands/escalations.js.map +1 -0
- package/dist/cli/commands/index.d.ts +17 -0
- package/dist/cli/commands/index.d.ts.map +1 -0
- package/dist/cli/commands/index.js +17 -0
- package/dist/cli/commands/index.js.map +1 -0
- package/dist/cli/commands/init.d.ts +3 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +59 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/manager.d.ts +3 -0
- package/dist/cli/commands/manager.d.ts.map +1 -0
- package/dist/cli/commands/manager.js +775 -0
- package/dist/cli/commands/manager.js.map +1 -0
- package/dist/cli/commands/manager.test.d.ts +2 -0
- package/dist/cli/commands/manager.test.d.ts.map +1 -0
- package/dist/cli/commands/manager.test.js +45 -0
- package/dist/cli/commands/manager.test.js.map +1 -0
- package/dist/cli/commands/msg.d.ts +3 -0
- package/dist/cli/commands/msg.d.ts.map +1 -0
- package/dist/cli/commands/msg.js +190 -0
- package/dist/cli/commands/msg.js.map +1 -0
- package/dist/cli/commands/my-stories.d.ts +3 -0
- package/dist/cli/commands/my-stories.d.ts.map +1 -0
- package/dist/cli/commands/my-stories.js +174 -0
- package/dist/cli/commands/my-stories.js.map +1 -0
- package/dist/cli/commands/nuke.d.ts +3 -0
- package/dist/cli/commands/nuke.d.ts.map +1 -0
- package/dist/cli/commands/nuke.js +189 -0
- package/dist/cli/commands/nuke.js.map +1 -0
- package/dist/cli/commands/pr.d.ts +3 -0
- package/dist/cli/commands/pr.d.ts.map +1 -0
- package/dist/cli/commands/pr.js +488 -0
- package/dist/cli/commands/pr.js.map +1 -0
- package/dist/cli/commands/req.d.ts +3 -0
- package/dist/cli/commands/req.d.ts.map +1 -0
- package/dist/cli/commands/req.js +212 -0
- package/dist/cli/commands/req.js.map +1 -0
- package/dist/cli/commands/resume.d.ts +3 -0
- package/dist/cli/commands/resume.d.ts.map +1 -0
- package/dist/cli/commands/resume.js +114 -0
- package/dist/cli/commands/resume.js.map +1 -0
- package/dist/cli/commands/status.d.ts +3 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/status.js +259 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/commands/stories.d.ts +3 -0
- package/dist/cli/commands/stories.d.ts.map +1 -0
- package/dist/cli/commands/stories.js +111 -0
- package/dist/cli/commands/stories.js.map +1 -0
- package/dist/cli/commands/teams.d.ts +3 -0
- package/dist/cli/commands/teams.d.ts.map +1 -0
- package/dist/cli/commands/teams.js +137 -0
- package/dist/cli/commands/teams.js.map +1 -0
- package/dist/cli/dashboard/index.d.ts +5 -0
- package/dist/cli/dashboard/index.d.ts.map +1 -0
- package/dist/cli/dashboard/index.js +128 -0
- package/dist/cli/dashboard/index.js.map +1 -0
- package/dist/cli/dashboard/panels/activity.d.ts +5 -0
- package/dist/cli/dashboard/panels/activity.d.ts.map +1 -0
- package/dist/cli/dashboard/panels/activity.js +64 -0
- package/dist/cli/dashboard/panels/activity.js.map +1 -0
- package/dist/cli/dashboard/panels/agents.d.ts +5 -0
- package/dist/cli/dashboard/panels/agents.d.ts.map +1 -0
- package/dist/cli/dashboard/panels/agents.js +196 -0
- package/dist/cli/dashboard/panels/agents.js.map +1 -0
- package/dist/cli/dashboard/panels/escalations.d.ts +5 -0
- package/dist/cli/dashboard/panels/escalations.d.ts.map +1 -0
- package/dist/cli/dashboard/panels/escalations.js +93 -0
- package/dist/cli/dashboard/panels/escalations.js.map +1 -0
- package/dist/cli/dashboard/panels/merge-queue.d.ts +5 -0
- package/dist/cli/dashboard/panels/merge-queue.d.ts.map +1 -0
- package/dist/cli/dashboard/panels/merge-queue.js +57 -0
- package/dist/cli/dashboard/panels/merge-queue.js.map +1 -0
- package/dist/cli/dashboard/panels/pipeline.d.ts +5 -0
- package/dist/cli/dashboard/panels/pipeline.d.ts.map +1 -0
- package/dist/cli/dashboard/panels/pipeline.js +54 -0
- package/dist/cli/dashboard/panels/pipeline.js.map +1 -0
- package/dist/cli/dashboard/panels/stories.d.ts +5 -0
- package/dist/cli/dashboard/panels/stories.d.ts.map +1 -0
- package/dist/cli/dashboard/panels/stories.js +79 -0
- package/dist/cli/dashboard/panels/stories.js.map +1 -0
- package/dist/cli-runtimes/claude.d.ts +8 -0
- package/dist/cli-runtimes/claude.d.ts.map +1 -0
- package/dist/cli-runtimes/claude.js +27 -0
- package/dist/cli-runtimes/claude.js.map +1 -0
- package/dist/cli-runtimes/codex.d.ts +8 -0
- package/dist/cli-runtimes/codex.d.ts.map +1 -0
- package/dist/cli-runtimes/codex.js +27 -0
- package/dist/cli-runtimes/codex.js.map +1 -0
- package/dist/cli-runtimes/gemini.d.ts +8 -0
- package/dist/cli-runtimes/gemini.d.ts.map +1 -0
- package/dist/cli-runtimes/gemini.js +29 -0
- package/dist/cli-runtimes/gemini.js.map +1 -0
- package/dist/cli-runtimes/index.d.ts +25 -0
- package/dist/cli-runtimes/index.d.ts.map +1 -0
- package/dist/cli-runtimes/index.js +48 -0
- package/dist/cli-runtimes/index.js.map +1 -0
- package/dist/cli-runtimes/index.test.d.ts +2 -0
- package/dist/cli-runtimes/index.test.d.ts.map +1 -0
- package/dist/cli-runtimes/index.test.js +216 -0
- package/dist/cli-runtimes/index.test.js.map +1 -0
- package/dist/cli-runtimes/types.d.ts +27 -0
- package/dist/cli-runtimes/types.d.ts.map +1 -0
- package/dist/cli-runtimes/types.js +2 -0
- package/dist/cli-runtimes/types.js.map +1 -0
- package/dist/config/index.d.ts +3 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +3 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/loader.d.ts +11 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +72 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/schema.d.ts +660 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +217 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/config/schema.test.d.ts +2 -0
- package/dist/config/schema.test.d.ts.map +1 -0
- package/dist/config/schema.test.js +123 -0
- package/dist/config/schema.test.js.map +1 -0
- package/dist/context-files/generator.d.ts +32 -0
- package/dist/context-files/generator.d.ts.map +1 -0
- package/dist/context-files/generator.js +120 -0
- package/dist/context-files/generator.js.map +1 -0
- package/dist/context-files/index.d.ts +38 -0
- package/dist/context-files/index.d.ts.map +1 -0
- package/dist/context-files/index.js +76 -0
- package/dist/context-files/index.js.map +1 -0
- package/dist/context-files/index.test.d.ts +2 -0
- package/dist/context-files/index.test.d.ts.map +1 -0
- package/dist/context-files/index.test.js +265 -0
- package/dist/context-files/index.test.js.map +1 -0
- package/dist/context-files/templates.d.ts +19 -0
- package/dist/context-files/templates.d.ts.map +1 -0
- package/dist/context-files/templates.js +266 -0
- package/dist/context-files/templates.js.map +1 -0
- package/dist/db/client.d.ts +95 -0
- package/dist/db/client.d.ts.map +1 -0
- package/dist/db/client.js +343 -0
- package/dist/db/client.js.map +1 -0
- package/dist/db/lock.d.ts +25 -0
- package/dist/db/lock.d.ts.map +1 -0
- package/dist/db/lock.js +56 -0
- package/dist/db/lock.js.map +1 -0
- package/dist/db/lock.test.d.ts +2 -0
- package/dist/db/lock.test.d.ts.map +1 -0
- package/dist/db/lock.test.js +73 -0
- package/dist/db/lock.test.js.map +1 -0
- package/dist/db/queries/agents.d.ts +31 -0
- package/dist/db/queries/agents.d.ts.map +1 -0
- package/dist/db/queries/agents.js +76 -0
- package/dist/db/queries/agents.js.map +1 -0
- package/dist/db/queries/escalations.d.ts +29 -0
- package/dist/db/queries/escalations.d.ts.map +1 -0
- package/dist/db/queries/escalations.js +105 -0
- package/dist/db/queries/escalations.js.map +1 -0
- package/dist/db/queries/heartbeat.d.ts +20 -0
- package/dist/db/queries/heartbeat.d.ts.map +1 -0
- package/dist/db/queries/heartbeat.js +61 -0
- package/dist/db/queries/heartbeat.js.map +1 -0
- package/dist/db/queries/index.d.ts +8 -0
- package/dist/db/queries/index.d.ts.map +1 -0
- package/dist/db/queries/index.js +8 -0
- package/dist/db/queries/index.js.map +1 -0
- package/dist/db/queries/logs.d.ts +21 -0
- package/dist/db/queries/logs.d.ts.map +1 -0
- package/dist/db/queries/logs.js +72 -0
- package/dist/db/queries/logs.js.map +1 -0
- package/dist/db/queries/messages.d.ts +17 -0
- package/dist/db/queries/messages.d.ts.map +1 -0
- package/dist/db/queries/messages.js +22 -0
- package/dist/db/queries/messages.js.map +1 -0
- package/dist/db/queries/pull-requests.d.ts +33 -0
- package/dist/db/queries/pull-requests.d.ts.map +1 -0
- package/dist/db/queries/pull-requests.js +130 -0
- package/dist/db/queries/pull-requests.js.map +1 -0
- package/dist/db/queries/requirements.d.ts +22 -0
- package/dist/db/queries/requirements.d.ts.map +1 -0
- package/dist/db/queries/requirements.js +53 -0
- package/dist/db/queries/requirements.js.map +1 -0
- package/dist/db/queries/stories.d.ts +42 -0
- package/dist/db/queries/stories.d.ts.map +1 -0
- package/dist/db/queries/stories.js +163 -0
- package/dist/db/queries/stories.js.map +1 -0
- package/dist/db/queries/teams.d.ts +14 -0
- package/dist/db/queries/teams.d.ts.map +1 -0
- package/dist/db/queries/teams.js +24 -0
- package/dist/db/queries/teams.js.map +1 -0
- package/dist/git/branches.d.ts +52 -0
- package/dist/git/branches.d.ts.map +1 -0
- package/dist/git/branches.js +133 -0
- package/dist/git/branches.js.map +1 -0
- package/dist/git/github.d.ts +75 -0
- package/dist/git/github.d.ts.map +1 -0
- package/dist/git/github.js +162 -0
- package/dist/git/github.js.map +1 -0
- package/dist/git/index.d.ts +4 -0
- package/dist/git/index.d.ts.map +1 -0
- package/dist/git/index.js +4 -0
- package/dist/git/index.js.map +1 -0
- package/dist/git/submodules.d.ts +47 -0
- package/dist/git/submodules.d.ts.map +1 -0
- package/dist/git/submodules.js +115 -0
- package/dist/git/submodules.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +62 -0
- package/dist/index.js.map +1 -0
- package/dist/llm/anthropic.d.ts +18 -0
- package/dist/llm/anthropic.d.ts.map +1 -0
- package/dist/llm/anthropic.js +111 -0
- package/dist/llm/anthropic.js.map +1 -0
- package/dist/llm/index.d.ts +6 -0
- package/dist/llm/index.d.ts.map +1 -0
- package/dist/llm/index.js +24 -0
- package/dist/llm/index.js.map +1 -0
- package/dist/llm/openai.d.ts +18 -0
- package/dist/llm/openai.d.ts.map +1 -0
- package/dist/llm/openai.js +103 -0
- package/dist/llm/openai.js.map +1 -0
- package/dist/llm/provider.d.ts +38 -0
- package/dist/llm/provider.d.ts.map +1 -0
- package/dist/llm/provider.js +17 -0
- package/dist/llm/provider.js.map +1 -0
- package/dist/orchestrator/index.d.ts +4 -0
- package/dist/orchestrator/index.d.ts.map +1 -0
- package/dist/orchestrator/index.js +4 -0
- package/dist/orchestrator/index.js.map +1 -0
- package/dist/orchestrator/scaler.d.ts +42 -0
- package/dist/orchestrator/scaler.d.ts.map +1 -0
- package/dist/orchestrator/scaler.js +154 -0
- package/dist/orchestrator/scaler.js.map +1 -0
- package/dist/orchestrator/scheduler.d.ts +90 -0
- package/dist/orchestrator/scheduler.d.ts.map +1 -0
- package/dist/orchestrator/scheduler.js +1003 -0
- package/dist/orchestrator/scheduler.js.map +1 -0
- package/dist/orchestrator/scheduler.test.d.ts +2 -0
- package/dist/orchestrator/scheduler.test.d.ts.map +1 -0
- package/dist/orchestrator/scheduler.test.js +242 -0
- package/dist/orchestrator/scheduler.test.js.map +1 -0
- package/dist/orchestrator/workflow.d.ts +18 -0
- package/dist/orchestrator/workflow.d.ts.map +1 -0
- package/dist/orchestrator/workflow.js +106 -0
- package/dist/orchestrator/workflow.js.map +1 -0
- package/dist/state-detectors/claude.d.ts +33 -0
- package/dist/state-detectors/claude.d.ts.map +1 -0
- package/dist/state-detectors/claude.js +237 -0
- package/dist/state-detectors/claude.js.map +1 -0
- package/dist/state-detectors/claude.test.d.ts +2 -0
- package/dist/state-detectors/claude.test.d.ts.map +1 -0
- package/dist/state-detectors/claude.test.js +127 -0
- package/dist/state-detectors/claude.test.js.map +1 -0
- package/dist/state-detectors/codex.d.ts +34 -0
- package/dist/state-detectors/codex.d.ts.map +1 -0
- package/dist/state-detectors/codex.js +233 -0
- package/dist/state-detectors/codex.js.map +1 -0
- package/dist/state-detectors/codex.test.d.ts +2 -0
- package/dist/state-detectors/codex.test.d.ts.map +1 -0
- package/dist/state-detectors/codex.test.js +85 -0
- package/dist/state-detectors/codex.test.js.map +1 -0
- package/dist/state-detectors/factory.d.ts +22 -0
- package/dist/state-detectors/factory.d.ts.map +1 -0
- package/dist/state-detectors/factory.js +37 -0
- package/dist/state-detectors/factory.js.map +1 -0
- package/dist/state-detectors/factory.test.d.ts +2 -0
- package/dist/state-detectors/factory.test.d.ts.map +1 -0
- package/dist/state-detectors/factory.test.js +44 -0
- package/dist/state-detectors/factory.test.js.map +1 -0
- package/dist/state-detectors/gemini.d.ts +34 -0
- package/dist/state-detectors/gemini.d.ts.map +1 -0
- package/dist/state-detectors/gemini.js +236 -0
- package/dist/state-detectors/gemini.js.map +1 -0
- package/dist/state-detectors/gemini.test.d.ts +2 -0
- package/dist/state-detectors/gemini.test.d.ts.map +1 -0
- package/dist/state-detectors/gemini.test.js +93 -0
- package/dist/state-detectors/gemini.test.js.map +1 -0
- package/dist/state-detectors/index.d.ts +20 -0
- package/dist/state-detectors/index.d.ts.map +1 -0
- package/dist/state-detectors/index.js +21 -0
- package/dist/state-detectors/index.js.map +1 -0
- package/dist/state-detectors/types.d.ts +67 -0
- package/dist/state-detectors/types.d.ts.map +1 -0
- package/dist/state-detectors/types.js +28 -0
- package/dist/state-detectors/types.js.map +1 -0
- package/dist/tmux/index.d.ts +2 -0
- package/dist/tmux/index.d.ts.map +1 -0
- package/dist/tmux/index.js +2 -0
- package/dist/tmux/index.js.map +1 -0
- package/dist/tmux/manager.d.ts +45 -0
- package/dist/tmux/manager.d.ts.map +1 -0
- package/dist/tmux/manager.js +252 -0
- package/dist/tmux/manager.js.map +1 -0
- package/dist/utils/claude-code-state.d.ts +46 -0
- package/dist/utils/claude-code-state.d.ts.map +1 -0
- package/dist/utils/claude-code-state.js +252 -0
- package/dist/utils/claude-code-state.js.map +1 -0
- package/dist/utils/cli-builder.d.ts +19 -0
- package/dist/utils/cli-builder.d.ts.map +1 -0
- package/dist/utils/cli-builder.js +58 -0
- package/dist/utils/cli-builder.js.map +1 -0
- package/dist/utils/cli-commands.d.ts +27 -0
- package/dist/utils/cli-commands.d.ts.map +1 -0
- package/dist/utils/cli-commands.js +69 -0
- package/dist/utils/cli-commands.js.map +1 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +3 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/logger.d.ts +13 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +77 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/paths.d.ts +17 -0
- package/dist/utils/paths.d.ts.map +1 -0
- package/dist/utils/paths.js +33 -0
- package/dist/utils/paths.js.map +1 -0
- package/dist/utils/timeout.d.ts +25 -0
- package/dist/utils/timeout.d.ts.map +1 -0
- package/dist/utils/timeout.js +57 -0
- package/dist/utils/timeout.js.map +1 -0
- package/package.json +78 -0
- package/src/agents/base-agent.ts +255 -0
- package/src/agents/index.ts +6 -0
- package/src/agents/intermediate.ts +161 -0
- package/src/agents/junior.ts +166 -0
- package/src/agents/qa.ts +272 -0
- package/src/agents/senior.ts +307 -0
- package/src/agents/tech-lead.ts +324 -0
- package/src/cli/commands/add-repo.ts +89 -0
- package/src/cli/commands/agents.ts +247 -0
- package/src/cli/commands/assign.ts +86 -0
- package/src/cli/commands/config.ts +121 -0
- package/src/cli/commands/escalations.ts +179 -0
- package/src/cli/commands/index.ts +16 -0
- package/src/cli/commands/init.ts +66 -0
- package/src/cli/commands/manager.test.ts +52 -0
- package/src/cli/commands/manager.ts +916 -0
- package/src/cli/commands/msg.ts +232 -0
- package/src/cli/commands/my-stories.ts +198 -0
- package/src/cli/commands/nuke.ts +223 -0
- package/src/cli/commands/pr.ts +559 -0
- package/src/cli/commands/req.ts +231 -0
- package/src/cli/commands/resume.ts +129 -0
- package/src/cli/commands/status.ts +284 -0
- package/src/cli/commands/stories.ts +131 -0
- package/src/cli/commands/teams.ts +158 -0
- package/src/cli/dashboard/index.ts +141 -0
- package/src/cli/dashboard/panels/activity.ts +77 -0
- package/src/cli/dashboard/panels/agents.ts +244 -0
- package/src/cli/dashboard/panels/escalations.ts +109 -0
- package/src/cli/dashboard/panels/merge-queue.ts +65 -0
- package/src/cli/dashboard/panels/pipeline.ts +65 -0
- package/src/cli/dashboard/panels/stories.ts +87 -0
- package/src/cli-runtimes/claude.ts +31 -0
- package/src/cli-runtimes/codex.ts +31 -0
- package/src/cli-runtimes/gemini.ts +33 -0
- package/src/cli-runtimes/index.test.ts +261 -0
- package/src/cli-runtimes/index.ts +52 -0
- package/src/cli-runtimes/types.ts +30 -0
- package/src/config/index.ts +2 -0
- package/src/config/loader.ts +89 -0
- package/src/config/schema.test.ts +135 -0
- package/src/config/schema.ts +238 -0
- package/src/context-files/generator.ts +132 -0
- package/src/context-files/index.test.ts +323 -0
- package/src/context-files/index.ts +102 -0
- package/src/context-files/templates.ts +279 -0
- package/src/db/client.ts +475 -0
- package/src/db/lock.test.ts +93 -0
- package/src/db/lock.ts +74 -0
- package/src/db/migrations/001-initial.sql +121 -0
- package/src/db/migrations/005-add-agent-heartbeat.sql +4 -0
- package/src/db/queries/agents.ts +113 -0
- package/src/db/queries/escalations.ts +140 -0
- package/src/db/queries/heartbeat.ts +92 -0
- package/src/db/queries/index.ts +7 -0
- package/src/db/queries/logs.ts +136 -0
- package/src/db/queries/messages.ts +38 -0
- package/src/db/queries/pull-requests.ts +170 -0
- package/src/db/queries/requirements.ts +81 -0
- package/src/db/queries/stories.ts +223 -0
- package/src/db/queries/teams.ts +39 -0
- package/src/git/branches.ts +186 -0
- package/src/git/github.ts +247 -0
- package/src/git/index.ts +3 -0
- package/src/git/submodules.ts +141 -0
- package/src/index.ts +93 -0
- package/src/llm/anthropic.ts +134 -0
- package/src/llm/index.ts +26 -0
- package/src/llm/openai.ts +125 -0
- package/src/llm/provider.ts +60 -0
- package/src/orchestrator/index.ts +3 -0
- package/src/orchestrator/scaler.ts +201 -0
- package/src/orchestrator/scheduler.test.ts +288 -0
- package/src/orchestrator/scheduler.ts +1130 -0
- package/src/orchestrator/workflow.ts +137 -0
- package/src/state-detectors/claude.test.ts +149 -0
- package/src/state-detectors/claude.ts +256 -0
- package/src/state-detectors/codex.test.ts +100 -0
- package/src/state-detectors/codex.ts +252 -0
- package/src/state-detectors/factory.test.ts +51 -0
- package/src/state-detectors/factory.ts +40 -0
- package/src/state-detectors/gemini.test.ts +110 -0
- package/src/state-detectors/gemini.ts +255 -0
- package/src/state-detectors/index.ts +25 -0
- package/src/state-detectors/types.ts +80 -0
- package/src/tmux/index.ts +1 -0
- package/src/tmux/manager.ts +310 -0
- package/src/types/sql.js.d.ts +34 -0
- package/src/utils/claude-code-state.ts +281 -0
- package/src/utils/cli-builder.ts +78 -0
- package/src/utils/cli-commands.ts +84 -0
- package/src/utils/index.ts +2 -0
- package/src/utils/logger.ts +93 -0
- package/src/utils/paths.ts +49 -0
- package/src/utils/timeout.ts +84 -0
- package/tsconfig.json +25 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { findHiveRoot, getHivePaths } from '../../utils/paths.js';
|
|
4
|
+
import { getDatabase } from '../../db/client.js';
|
|
5
|
+
import { getAllStories, getStoryById, getStoriesByStatus, getStoryDependencies, type StoryStatus } from '../../db/queries/stories.js';
|
|
6
|
+
import { statusColor } from '../../utils/logger.js';
|
|
7
|
+
|
|
8
|
+
export const storiesCommand = new Command('stories')
|
|
9
|
+
.description('Manage stories');
|
|
10
|
+
|
|
11
|
+
storiesCommand
|
|
12
|
+
.command('list')
|
|
13
|
+
.description('List all stories')
|
|
14
|
+
.option('--status <status>', 'Filter by status')
|
|
15
|
+
.option('--json', 'Output as JSON')
|
|
16
|
+
.action(async (options: { status?: string; json?: boolean }) => {
|
|
17
|
+
const root = findHiveRoot();
|
|
18
|
+
if (!root) {
|
|
19
|
+
console.error(chalk.red('Not in a Hive workspace. Run "hive init" first.'));
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const paths = getHivePaths(root);
|
|
24
|
+
const db = await getDatabase(paths.hiveDir);
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
let stories;
|
|
28
|
+
if (options.status) {
|
|
29
|
+
stories = getStoriesByStatus(db.db, options.status as StoryStatus);
|
|
30
|
+
} else {
|
|
31
|
+
stories = getAllStories(db.db);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (options.json) {
|
|
35
|
+
console.log(JSON.stringify(stories, null, 2));
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (stories.length === 0) {
|
|
40
|
+
console.log(chalk.yellow('No stories found.'));
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
console.log(chalk.bold('\nStories:\n'));
|
|
45
|
+
|
|
46
|
+
// Header
|
|
47
|
+
console.log(
|
|
48
|
+
chalk.gray(
|
|
49
|
+
`${'ID'.padEnd(15)} ${'Title'.padEnd(40)} ${'Status'.padEnd(15)} ${'Points'.padEnd(8)} ${'Assigned'}`
|
|
50
|
+
)
|
|
51
|
+
);
|
|
52
|
+
console.log(chalk.gray('─'.repeat(100)));
|
|
53
|
+
|
|
54
|
+
for (const story of stories) {
|
|
55
|
+
const title = story.title.length > 37 ? story.title.substring(0, 37) + '...' : story.title;
|
|
56
|
+
const points = story.story_points?.toString() || '-';
|
|
57
|
+
const assigned = story.assigned_agent_id || '-';
|
|
58
|
+
|
|
59
|
+
console.log(
|
|
60
|
+
`${chalk.cyan(story.id.padEnd(15))} ${title.padEnd(40)} ${statusColor(story.status).padEnd(15)} ${points.padEnd(8)} ${assigned}`
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
console.log();
|
|
64
|
+
} finally {
|
|
65
|
+
db.close();
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
storiesCommand
|
|
70
|
+
.command('show <story-id>')
|
|
71
|
+
.description('Show story details')
|
|
72
|
+
.action(async (storyId: string) => {
|
|
73
|
+
const root = findHiveRoot();
|
|
74
|
+
if (!root) {
|
|
75
|
+
console.error(chalk.red('Not in a Hive workspace. Run "hive init" first.'));
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const paths = getHivePaths(root);
|
|
80
|
+
const db = await getDatabase(paths.hiveDir);
|
|
81
|
+
|
|
82
|
+
try {
|
|
83
|
+
const story = getStoryById(db.db, storyId);
|
|
84
|
+
if (!story) {
|
|
85
|
+
console.error(chalk.red(`Story not found: ${storyId}`));
|
|
86
|
+
process.exit(1);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const dependencies = getStoryDependencies(db.db, story.id);
|
|
90
|
+
|
|
91
|
+
console.log(chalk.bold(`\nStory: ${story.id}\n`));
|
|
92
|
+
console.log(chalk.bold('Title:'), story.title);
|
|
93
|
+
console.log(chalk.bold('Status:'), statusColor(story.status));
|
|
94
|
+
|
|
95
|
+
console.log(chalk.bold('\nDescription:'));
|
|
96
|
+
console.log(chalk.gray(story.description));
|
|
97
|
+
|
|
98
|
+
if (story.acceptance_criteria) {
|
|
99
|
+
console.log(chalk.bold('\nAcceptance Criteria:'));
|
|
100
|
+
try {
|
|
101
|
+
const criteria = JSON.parse(story.acceptance_criteria) as string[];
|
|
102
|
+
for (const c of criteria) {
|
|
103
|
+
console.log(chalk.gray(` • ${c}`));
|
|
104
|
+
}
|
|
105
|
+
} catch {
|
|
106
|
+
console.log(chalk.gray(story.acceptance_criteria));
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
console.log(chalk.bold('\nDetails:'));
|
|
111
|
+
console.log(chalk.gray(` Requirement: ${story.requirement_id || '-'}`));
|
|
112
|
+
console.log(chalk.gray(` Team: ${story.team_id || '-'}`));
|
|
113
|
+
console.log(chalk.gray(` Complexity: ${story.complexity_score || '-'}`));
|
|
114
|
+
console.log(chalk.gray(` Story Points: ${story.story_points || '-'}`));
|
|
115
|
+
console.log(chalk.gray(` Assigned Agent: ${story.assigned_agent_id || '-'}`));
|
|
116
|
+
console.log(chalk.gray(` Branch: ${story.branch_name || '-'}`));
|
|
117
|
+
console.log(chalk.gray(` PR URL: ${story.pr_url || '-'}`));
|
|
118
|
+
console.log(chalk.gray(` Created: ${story.created_at}`));
|
|
119
|
+
console.log(chalk.gray(` Updated: ${story.updated_at}`));
|
|
120
|
+
|
|
121
|
+
if (dependencies.length > 0) {
|
|
122
|
+
console.log(chalk.bold('\nDependencies:'));
|
|
123
|
+
for (const dep of dependencies) {
|
|
124
|
+
console.log(` ${chalk.cyan(dep.id)} - ${dep.title.substring(0, 40)}... - ${statusColor(dep.status)}`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
console.log();
|
|
128
|
+
} finally {
|
|
129
|
+
db.close();
|
|
130
|
+
}
|
|
131
|
+
});
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { findHiveRoot, getHivePaths } from '../../utils/paths.js';
|
|
4
|
+
import { getDatabase } from '../../db/client.js';
|
|
5
|
+
import { getAllTeams, getTeamByName, deleteTeam } from '../../db/queries/teams.js';
|
|
6
|
+
import { getAgentsByTeam } from '../../db/queries/agents.js';
|
|
7
|
+
import { getStoriesByTeam, getStoryPointsByTeam } from '../../db/queries/stories.js';
|
|
8
|
+
|
|
9
|
+
export const teamsCommand = new Command('teams')
|
|
10
|
+
.description('Manage teams');
|
|
11
|
+
|
|
12
|
+
teamsCommand
|
|
13
|
+
.command('list')
|
|
14
|
+
.description('List all teams')
|
|
15
|
+
.option('--json', 'Output as JSON')
|
|
16
|
+
.action(async (options: { json?: boolean }) => {
|
|
17
|
+
const root = findHiveRoot();
|
|
18
|
+
if (!root) {
|
|
19
|
+
console.error(chalk.red('Not in a Hive workspace. Run "hive init" first.'));
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const paths = getHivePaths(root);
|
|
24
|
+
const db = await getDatabase(paths.hiveDir);
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
const teams = getAllTeams(db.db);
|
|
28
|
+
|
|
29
|
+
if (options.json) {
|
|
30
|
+
console.log(JSON.stringify(teams, null, 2));
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (teams.length === 0) {
|
|
35
|
+
console.log(chalk.yellow('No teams found.'));
|
|
36
|
+
console.log(chalk.gray('Use "hive add-repo --url <url> --team <name>" to add a team.'));
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
console.log(chalk.bold('\nTeams:\n'));
|
|
41
|
+
|
|
42
|
+
for (const team of teams) {
|
|
43
|
+
const agents = getAgentsByTeam(db.db, team.id);
|
|
44
|
+
const stories = getStoriesByTeam(db.db, team.id);
|
|
45
|
+
const storyPoints = getStoryPointsByTeam(db.db, team.id);
|
|
46
|
+
|
|
47
|
+
console.log(chalk.cyan(` ${team.name}`));
|
|
48
|
+
console.log(chalk.gray(` ID: ${team.id}`));
|
|
49
|
+
console.log(chalk.gray(` Repository: ${team.repo_url}`));
|
|
50
|
+
console.log(chalk.gray(` Path: ${team.repo_path}`));
|
|
51
|
+
console.log(chalk.gray(` Agents: ${agents.length}`));
|
|
52
|
+
console.log(chalk.gray(` Stories: ${stories.length}`));
|
|
53
|
+
console.log(chalk.gray(` Story Points: ${storyPoints}`));
|
|
54
|
+
console.log();
|
|
55
|
+
}
|
|
56
|
+
} finally {
|
|
57
|
+
db.close();
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
teamsCommand
|
|
62
|
+
.command('show <name>')
|
|
63
|
+
.description('Show team details')
|
|
64
|
+
.action(async (name: string) => {
|
|
65
|
+
const root = findHiveRoot();
|
|
66
|
+
if (!root) {
|
|
67
|
+
console.error(chalk.red('Not in a Hive workspace. Run "hive init" first.'));
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const paths = getHivePaths(root);
|
|
72
|
+
const db = await getDatabase(paths.hiveDir);
|
|
73
|
+
|
|
74
|
+
try {
|
|
75
|
+
const team = getTeamByName(db.db, name);
|
|
76
|
+
|
|
77
|
+
if (!team) {
|
|
78
|
+
console.error(chalk.red(`Team not found: ${name}`));
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const agents = getAgentsByTeam(db.db, team.id);
|
|
83
|
+
const stories = getStoriesByTeam(db.db, team.id);
|
|
84
|
+
const storyPoints = getStoryPointsByTeam(db.db, team.id);
|
|
85
|
+
|
|
86
|
+
console.log(chalk.bold(`\nTeam: ${team.name}\n`));
|
|
87
|
+
console.log(chalk.gray(`ID: ${team.id}`));
|
|
88
|
+
console.log(chalk.gray(`Repository: ${team.repo_url}`));
|
|
89
|
+
console.log(chalk.gray(`Path: ${team.repo_path}`));
|
|
90
|
+
console.log(chalk.gray(`Created: ${team.created_at}`));
|
|
91
|
+
console.log();
|
|
92
|
+
|
|
93
|
+
if (agents.length > 0) {
|
|
94
|
+
console.log(chalk.bold('Agents:'));
|
|
95
|
+
for (const agent of agents) {
|
|
96
|
+
const statusColor = agent.status === 'working' ? chalk.yellow : agent.status === 'idle' ? chalk.gray : chalk.red;
|
|
97
|
+
console.log(` ${chalk.cyan(agent.id)} - ${agent.type} - ${statusColor(agent.status)}`);
|
|
98
|
+
}
|
|
99
|
+
console.log();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (stories.length > 0) {
|
|
103
|
+
console.log(chalk.bold('Stories:'));
|
|
104
|
+
for (const story of stories) {
|
|
105
|
+
const statusColor = story.status === 'merged' ? chalk.green : story.status === 'in_progress' ? chalk.yellow : chalk.gray;
|
|
106
|
+
console.log(` ${chalk.cyan(story.id)} - ${story.title.substring(0, 40)}... - ${statusColor(story.status)}`);
|
|
107
|
+
}
|
|
108
|
+
console.log();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
console.log(chalk.bold('Summary:'));
|
|
112
|
+
console.log(` Total Stories: ${stories.length}`);
|
|
113
|
+
console.log(` Active Story Points: ${storyPoints}`);
|
|
114
|
+
console.log(` Active Agents: ${agents.filter(a => a.status !== 'terminated').length}`);
|
|
115
|
+
} finally {
|
|
116
|
+
db.close();
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
teamsCommand
|
|
121
|
+
.command('remove <name>')
|
|
122
|
+
.description('Remove a team')
|
|
123
|
+
.option('--force', 'Force removal even if team has active stories')
|
|
124
|
+
.action(async (name: string, options: { force?: boolean }) => {
|
|
125
|
+
const root = findHiveRoot();
|
|
126
|
+
if (!root) {
|
|
127
|
+
console.error(chalk.red('Not in a Hive workspace. Run "hive init" first.'));
|
|
128
|
+
process.exit(1);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const paths = getHivePaths(root);
|
|
132
|
+
const db = await getDatabase(paths.hiveDir);
|
|
133
|
+
|
|
134
|
+
try {
|
|
135
|
+
const team = getTeamByName(db.db, name);
|
|
136
|
+
|
|
137
|
+
if (!team) {
|
|
138
|
+
console.error(chalk.red(`Team not found: ${name}`));
|
|
139
|
+
process.exit(1);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const stories = getStoriesByTeam(db.db, team.id);
|
|
143
|
+
const activeStories = stories.filter(s => !['merged', 'draft'].includes(s.status));
|
|
144
|
+
|
|
145
|
+
if (activeStories.length > 0 && !options.force) {
|
|
146
|
+
console.error(chalk.red(`Team has ${activeStories.length} active stories. Use --force to remove anyway.`));
|
|
147
|
+
process.exit(1);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
deleteTeam(db.db, team.id);
|
|
151
|
+
console.log(chalk.green(`Team "${name}" removed successfully.`));
|
|
152
|
+
console.log(chalk.yellow('Note: Git submodule was not removed. Run the following to remove it:'));
|
|
153
|
+
console.log(chalk.gray(` git submodule deinit -f ${team.repo_path}`));
|
|
154
|
+
console.log(chalk.gray(` git rm -f ${team.repo_path}`));
|
|
155
|
+
} finally {
|
|
156
|
+
db.close();
|
|
157
|
+
}
|
|
158
|
+
});
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import blessed from 'blessed';
|
|
2
|
+
import { appendFileSync, statSync } from 'fs';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { getDatabase, type DatabaseClient } from '../../db/client.js';
|
|
5
|
+
import { findHiveRoot, getHivePaths } from '../../utils/paths.js';
|
|
6
|
+
|
|
7
|
+
function debugLog(msg: string) {
|
|
8
|
+
appendFileSync('/tmp/hive-dashboard-debug.log', `${new Date().toISOString()} ${msg}\n`);
|
|
9
|
+
}
|
|
10
|
+
import { createAgentsPanel, updateAgentsPanel } from './panels/agents.js';
|
|
11
|
+
import { createStoriesPanel, updateStoriesPanel } from './panels/stories.js';
|
|
12
|
+
import { createPipelinePanel, updatePipelinePanel } from './panels/pipeline.js';
|
|
13
|
+
import { createActivityPanel, updateActivityPanel } from './panels/activity.js';
|
|
14
|
+
import { createMergeQueuePanel, updateMergeQueuePanel } from './panels/merge-queue.js';
|
|
15
|
+
import { createEscalationsPanel, updateEscalationsPanel } from './panels/escalations.js';
|
|
16
|
+
|
|
17
|
+
export interface DashboardOptions {
|
|
18
|
+
refreshInterval?: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export async function startDashboard(options: DashboardOptions = {}): Promise<void> {
|
|
22
|
+
const root = findHiveRoot();
|
|
23
|
+
if (!root) {
|
|
24
|
+
console.error('Not in a Hive workspace. Run "hive init" first.');
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const paths = getHivePaths(root);
|
|
29
|
+
const dbPath = join(paths.hiveDir, 'hive.db');
|
|
30
|
+
debugLog(`Dashboard starting - root: ${root}, hiveDir: ${paths.hiveDir}`);
|
|
31
|
+
let db: DatabaseClient = await getDatabase(paths.hiveDir);
|
|
32
|
+
let lastDbMtime = statSync(dbPath).mtimeMs;
|
|
33
|
+
const refreshInterval = options.refreshInterval || 5000;
|
|
34
|
+
|
|
35
|
+
// Create screen
|
|
36
|
+
const screen = blessed.screen({
|
|
37
|
+
smartCSR: true,
|
|
38
|
+
title: 'Hive Orchestrator Dashboard',
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// Header
|
|
42
|
+
blessed.box({
|
|
43
|
+
parent: screen,
|
|
44
|
+
top: 0,
|
|
45
|
+
left: 0,
|
|
46
|
+
width: '100%',
|
|
47
|
+
height: 1,
|
|
48
|
+
content: ' {bold}HIVE ORCHESTRATOR{/bold} [R]efresh [Q]uit',
|
|
49
|
+
style: {
|
|
50
|
+
bg: 'blue',
|
|
51
|
+
fg: 'white',
|
|
52
|
+
},
|
|
53
|
+
tags: true,
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// Create panels
|
|
57
|
+
const agentsPanel = createAgentsPanel(screen, db.db);
|
|
58
|
+
const storiesPanel = createStoriesPanel(screen, db.db);
|
|
59
|
+
const pipelinePanel = createPipelinePanel(screen, db.db);
|
|
60
|
+
const activityPanel = createActivityPanel(screen, db.db);
|
|
61
|
+
const mergeQueuePanel = createMergeQueuePanel(screen, db.db);
|
|
62
|
+
const escalationsPanel = createEscalationsPanel(screen, db.db);
|
|
63
|
+
|
|
64
|
+
// Footer
|
|
65
|
+
blessed.box({
|
|
66
|
+
parent: screen,
|
|
67
|
+
bottom: 0,
|
|
68
|
+
left: 0,
|
|
69
|
+
width: '100%',
|
|
70
|
+
height: 1,
|
|
71
|
+
content: ' Tab: Switch panels | ↑↓: Navigate | Enter: Attach to tmux | Ctrl+B,D: Detach | Q: Quit',
|
|
72
|
+
style: {
|
|
73
|
+
bg: 'blue',
|
|
74
|
+
fg: 'white',
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// Focus management
|
|
79
|
+
const panels = [agentsPanel, storiesPanel, activityPanel, mergeQueuePanel, escalationsPanel];
|
|
80
|
+
let focusIndex = 0;
|
|
81
|
+
panels[focusIndex].focus();
|
|
82
|
+
|
|
83
|
+
// Refresh function - only reloads database when file has changed
|
|
84
|
+
const refresh = async () => {
|
|
85
|
+
try {
|
|
86
|
+
// Check if database file has been modified
|
|
87
|
+
const currentMtime = statSync(dbPath).mtimeMs;
|
|
88
|
+
if (currentMtime !== lastDbMtime) {
|
|
89
|
+
debugLog(`Database changed - reloading from ${paths.hiveDir}`);
|
|
90
|
+
lastDbMtime = currentMtime;
|
|
91
|
+
|
|
92
|
+
// Get new database connection first, then close old one
|
|
93
|
+
const newDb = await getDatabase(paths.hiveDir);
|
|
94
|
+
try { db.db.close(); } catch { /* ignore close errors */ }
|
|
95
|
+
db = newDb;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
await updateAgentsPanel(agentsPanel, db.db);
|
|
99
|
+
updateStoriesPanel(storiesPanel, db.db);
|
|
100
|
+
updatePipelinePanel(pipelinePanel, db.db);
|
|
101
|
+
updateActivityPanel(activityPanel, db.db);
|
|
102
|
+
updateMergeQueuePanel(mergeQueuePanel, db.db);
|
|
103
|
+
updateEscalationsPanel(escalationsPanel, db.db);
|
|
104
|
+
screen.render();
|
|
105
|
+
} catch (err) {
|
|
106
|
+
debugLog(`Refresh error: ${err}`);
|
|
107
|
+
process.stderr.write(`Dashboard refresh error: ${err}\n`);
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
// Auto-refresh - wrap in arrow function to handle async properly
|
|
112
|
+
const timer = setInterval(() => { refresh(); }, refreshInterval);
|
|
113
|
+
|
|
114
|
+
// Key bindings
|
|
115
|
+
screen.key(['q', 'C-c', 'escape'], () => {
|
|
116
|
+
clearInterval(timer);
|
|
117
|
+
try { db.db.close(); } catch { /* ignore */ }
|
|
118
|
+
screen.destroy();
|
|
119
|
+
process.exit(0);
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
screen.key(['r'], () => {
|
|
123
|
+
refresh();
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
screen.key(['tab'], () => {
|
|
127
|
+
focusIndex = (focusIndex + 1) % panels.length;
|
|
128
|
+
panels[focusIndex].focus();
|
|
129
|
+
screen.render();
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
screen.key(['S-tab'], () => {
|
|
133
|
+
focusIndex = (focusIndex - 1 + panels.length) % panels.length;
|
|
134
|
+
panels[focusIndex].focus();
|
|
135
|
+
screen.render();
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
// Initial refresh and render
|
|
139
|
+
await refresh();
|
|
140
|
+
screen.render();
|
|
141
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { Database } from 'sql.js';
|
|
2
|
+
import blessed, { type Widgets } from 'blessed';
|
|
3
|
+
import { getRecentLogs } from '../../../db/queries/logs.js';
|
|
4
|
+
|
|
5
|
+
export function createActivityPanel(screen: Widgets.Screen, db: Database): Widgets.BoxElement {
|
|
6
|
+
|
|
7
|
+
const box = blessed.box({
|
|
8
|
+
parent: screen,
|
|
9
|
+
top: '55%+5',
|
|
10
|
+
left: 0,
|
|
11
|
+
width: '50%',
|
|
12
|
+
height: '35%',
|
|
13
|
+
border: { type: 'line' },
|
|
14
|
+
label: ' Recent Activity ',
|
|
15
|
+
scrollable: true,
|
|
16
|
+
alwaysScroll: true,
|
|
17
|
+
keys: true,
|
|
18
|
+
vi: true,
|
|
19
|
+
mouse: true,
|
|
20
|
+
style: {
|
|
21
|
+
border: { fg: 'cyan' },
|
|
22
|
+
},
|
|
23
|
+
tags: true,
|
|
24
|
+
scrollbar: {
|
|
25
|
+
ch: ' ',
|
|
26
|
+
track: { bg: 'gray' },
|
|
27
|
+
style: { bg: 'white' },
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
updateActivityPanel(box, db);
|
|
32
|
+
|
|
33
|
+
return box;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function updateActivityPanel(box: Widgets.BoxElement, db: Database): void {
|
|
37
|
+
const logs = getRecentLogs(db, 50);
|
|
38
|
+
|
|
39
|
+
const lines: string[] = [];
|
|
40
|
+
|
|
41
|
+
for (const entry of logs.reverse()) {
|
|
42
|
+
const time = formatTimestamp(entry.timestamp);
|
|
43
|
+
const agent = entry.agent_id.padEnd(15).substring(0, 15);
|
|
44
|
+
const event = formatEventType(entry.event_type);
|
|
45
|
+
const message = entry.message ? `: ${entry.message.substring(0, 40)}` : '';
|
|
46
|
+
|
|
47
|
+
lines.push(`{gray-fg}${time}{/} {cyan-fg}${agent}{/} ${event}${message}`);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
box.setContent(lines.join('\n'));
|
|
51
|
+
|
|
52
|
+
// Always scroll to the latest (bottom) entries
|
|
53
|
+
box.setScrollPerc(100);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function formatTimestamp(timestamp: string): string {
|
|
57
|
+
return timestamp.substring(11, 19);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function formatEventType(event: string): string {
|
|
61
|
+
const colors: Record<string, string> = {
|
|
62
|
+
AGENT_SPAWNED: 'green',
|
|
63
|
+
AGENT_TERMINATED: 'red',
|
|
64
|
+
AGENT_RESUMED: 'yellow',
|
|
65
|
+
STORY_STARTED: 'blue',
|
|
66
|
+
STORY_COMPLETED: 'green',
|
|
67
|
+
STORY_QA_PASSED: 'green',
|
|
68
|
+
STORY_QA_FAILED: 'red',
|
|
69
|
+
STORY_PR_CREATED: 'magenta',
|
|
70
|
+
ESCALATION_CREATED: 'red',
|
|
71
|
+
BUILD_PASSED: 'green',
|
|
72
|
+
BUILD_FAILED: 'red',
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const color = colors[event] || 'white';
|
|
76
|
+
return `{${color}-fg}${event}{/}`;
|
|
77
|
+
}
|