@polderlabs/bizar 8.0.0 → 9.0.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/.claude/agents/agent-browser.md +1 -1
- package/.claude/agents/baldr.md +1 -1
- package/.claude/agents/forseti.md +1 -1
- package/.claude/agents/frigg.md +1 -1
- package/.claude/agents/heimdall.md +1 -1
- package/.claude/agents/hermod.md +1 -1
- package/.claude/agents/mimir.md +1 -1
- package/.claude/agents/odin.md +1 -1
- package/.claude/agents/quick.md +1 -1
- package/.claude/agents/semble-search.md +1 -1
- package/.claude/agents/thor.md +1 -1
- package/.claude/agents/tyr.md +1 -1
- package/.claude/agents/vidarr.md +1 -1
- package/.claude/agents/vor.md +1 -1
- package/.claude/commands/goal.md +98 -0
- package/.claude/settings.local.json +1 -2
- package/.claude/worktrees/kanban-overhaul/.claude/CLAUDE.md +15 -0
- package/.claude/worktrees/kanban-overhaul/.claude/agents/_shared/AGENT_BASELINE.md +168 -0
- package/.claude/worktrees/kanban-overhaul/.claude/agents/_shared/CLAUDE_TOOLS.md +412 -0
- package/.claude/worktrees/kanban-overhaul/.claude/agents/_shared/SKILLS.md +109 -0
- package/.claude/worktrees/kanban-overhaul/.claude/agents/agent-browser.md +80 -0
- package/.claude/worktrees/kanban-overhaul/.claude/agents/baldr.md +49 -0
- package/.claude/worktrees/kanban-overhaul/.claude/agents/forseti.md +51 -0
- package/.claude/worktrees/kanban-overhaul/.claude/agents/frigg.md +42 -0
- package/.claude/worktrees/kanban-overhaul/.claude/agents/heimdall.md +33 -0
- package/.claude/worktrees/kanban-overhaul/.claude/agents/hermod.md +53 -0
- package/.claude/worktrees/kanban-overhaul/.claude/agents/mimir.md +49 -0
- package/.claude/worktrees/kanban-overhaul/.claude/agents/odin.md +287 -0
- package/.claude/worktrees/kanban-overhaul/.claude/agents/quick.md +34 -0
- package/.claude/worktrees/kanban-overhaul/.claude/agents/semble-search.md +50 -0
- package/.claude/worktrees/kanban-overhaul/.claude/agents/thor.md +53 -0
- package/.claude/worktrees/kanban-overhaul/.claude/agents/tyr.md +56 -0
- package/.claude/worktrees/kanban-overhaul/.claude/agents/vidarr.md +54 -0
- package/.claude/worktrees/kanban-overhaul/.claude/agents/vor.md +53 -0
- package/.claude/worktrees/kanban-overhaul/.claude/commands/audit.md +25 -0
- package/.claude/worktrees/kanban-overhaul/.claude/commands/bizar.md +22 -0
- package/.claude/worktrees/kanban-overhaul/.claude/commands/explain.md +17 -0
- package/.claude/worktrees/kanban-overhaul/.claude/commands/init.md +29 -0
- package/.claude/worktrees/kanban-overhaul/.claude/commands/learn.md +44 -0
- package/.claude/worktrees/kanban-overhaul/.claude/commands/plan.md +35 -0
- package/.claude/worktrees/kanban-overhaul/.claude/commands/plow-through.md +50 -0
- package/.claude/worktrees/kanban-overhaul/.claude/commands/pr-review.md +49 -0
- package/.claude/worktrees/kanban-overhaul/.claude/commands/setup-provider.md +96 -0
- package/.claude/worktrees/kanban-overhaul/.claude/commands/tailscale-serve.md +100 -0
- package/.claude/worktrees/kanban-overhaul/.claude/commands/team.md +132 -0
- package/.claude/worktrees/kanban-overhaul/.claude/commands/test.md +62 -0
- package/.claude/worktrees/kanban-overhaul/.claude/commands/validate.md +68 -0
- package/.claude/worktrees/kanban-overhaul/.claude/commands/visual-plan.md +24 -0
- package/.claude/worktrees/kanban-overhaul/.claude/hooks/README.md +92 -0
- package/.claude/worktrees/kanban-overhaul/.claude/hooks/posttooluse-editwrite.mjs +91 -0
- package/.claude/worktrees/kanban-overhaul/.claude/hooks/pretooluse-bash.mjs +81 -0
- package/.claude/worktrees/kanban-overhaul/.claude/hooks/pretooluse-editwrite.mjs +139 -0
- package/.claude/worktrees/kanban-overhaul/.claude/hooks/sessionend-recall.mjs +74 -0
- package/.claude/worktrees/kanban-overhaul/.claude/hooks/sessionstart-prime.mjs +80 -0
- package/.claude/worktrees/kanban-overhaul/.claude/hooks/userpromptsubmit-tag.mjs +80 -0
- package/.claude/worktrees/kanban-overhaul/.claude/hooks/worker-suggest.mjs +110 -0
- package/.claude/worktrees/kanban-overhaul/.claude/settings.json +125 -0
- package/.claude/worktrees/kanban-overhaul/.claude/settings.local.json +8 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/9router/SKILL.md +80 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/9router-chat/SKILL.md +73 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/9router-embeddings/SKILL.md +69 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/9router-image/SKILL.md +86 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/9router-stt/SKILL.md +79 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/9router-tts/SKILL.md +80 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/9router-web-fetch/SKILL.md +99 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/9router-web-search/SKILL.md +91 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/bizar/README.md +9 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/bizar/SKILL.md +450 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-coding-standards/README.md +28 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-coding-standards/SKILL.md +634 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-coding-standards/references/concurrency.md +320 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-coding-standards/references/error-handling.md +229 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-coding-standards/references/memory-safety.md +216 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-coding-standards/references/modern-idioms.md +282 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-coding-standards/references/review-checklist.md +96 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-testing/README.md +28 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-testing/SKILL.md +304 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-testing/references/coverage.md +370 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-testing/references/framework-compare.md +175 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-testing/references/host-test-for-embedded.md +499 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-testing/references/mocking.md +364 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-testing/references/tdd-workflow.md +308 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/cubesandbox/SKILL.md +148 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/README.md +41 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/SKILL.md +439 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/references/freertos-patterns.md +214 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/references/host-tests.md +164 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/references/idf-py-commands.md +157 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/references/kconfig.md +159 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/references/logging-discipline.md +118 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/references/memory-and-iram.md +137 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/references/nvs.md +121 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/references/packed-structs.md +192 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/scripts/idf_env.sh +47 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/scripts/size_check.sh +77 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/glyph/SKILL.md +163 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/harness-engineering/SKILL.md +143 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/lightrag/SKILL.md +81 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/memory-protocol/SKILL.md +105 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/obsidian/SKILL.md +306 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/read-the-damn-docs/SKILL.md +113 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/self-improvement/SKILL.md +64 -0
- package/.claude/worktrees/kanban-overhaul/.dockerignore +31 -0
- package/.claude/worktrees/kanban-overhaul/.gitattributes +27 -0
- package/.claude/worktrees/kanban-overhaul/.harness/agents.json +17 -0
- package/.claude/worktrees/kanban-overhaul/.harness/arch-rules.json +69 -0
- package/.claude/worktrees/kanban-overhaul/.harness/topology.json +4 -0
- package/.claude/worktrees/kanban-overhaul/.nvmrc +1 -0
- package/.claude/worktrees/kanban-overhaul/.serena/project.yml +159 -0
- package/.claude/worktrees/kanban-overhaul/AGENTS.md +250 -0
- package/.claude/worktrees/kanban-overhaul/CHANGELOG.md +5410 -0
- package/.claude/worktrees/kanban-overhaul/CLAUDE.md +260 -0
- package/.claude/worktrees/kanban-overhaul/CURRENT_ISSUES_ AND_NEW_FEATURES.md +18 -0
- package/.claude/worktrees/kanban-overhaul/DECISIONS.md +66 -0
- package/.claude/worktrees/kanban-overhaul/Dockerfile +48 -0
- package/.claude/worktrees/kanban-overhaul/FINAL_GOAL.md +397 -0
- package/.claude/worktrees/kanban-overhaul/IMPLEMENTATION_PLAN.md +250 -0
- package/.claude/worktrees/kanban-overhaul/LICENSE +21 -0
- package/.claude/worktrees/kanban-overhaul/MILESTONES.md +257 -0
- package/.claude/worktrees/kanban-overhaul/Makefile +93 -0
- package/.claude/worktrees/kanban-overhaul/PROGRESS.md +1406 -0
- package/.claude/worktrees/kanban-overhaul/README.md +483 -0
- package/.claude/worktrees/kanban-overhaul/ROADMAP.md +609 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/.graphifyignore +40 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/.obsidian/README.md +14 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/.obsidian/daily/2026-06-25.md +9 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/.obsidian/vault.json +7 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/.od-skills/web-prototype-e1429c1737/SKILL.md +103 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/.od-skills/web-prototype-e1429c1737/assets/template.html +338 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/.od-skills/web-prototype-e1429c1737/example.html +81 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/.od-skills/web-prototype-e1429c1737/open-design.json +172 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/.od-skills/web-prototype-e1429c1737/references/checklist.md +44 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/.od-skills/web-prototype-e1429c1737/references/layouts.md +247 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/ARCHITECTURE.md +197 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/CHANGELOG.md +235 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/DESIGN.md +912 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/GLYPH.md +418 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/PLAN.md +1135 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/critique.json +26 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/plans/debug-plan/comments.json +1 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/plans/debug-plan/meta.json +10 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/plans/debug-plan/plan.json +174 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/scripts/smoke-bg-retry.mjs +246 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/agent-baseline/SKILL.md +80 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/agent-browser/SKILL.md +181 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/bizar/SKILL.md +116 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/chat/SKILL.md +74 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/eval/SKILL.md +237 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/headroom/SKILL.md +94 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/lightrag/SKILL.md +86 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/minimax/SKILL.md +80 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/obsidian/SKILL.md +68 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/providers/SKILL.md +75 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/publishing/SKILL.md +146 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/sdk/SKILL.md +138 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/self-improvement/SKILL.md +53 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/skills-cli/SKILL.md +94 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/usage/SKILL.md +62 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/cli/dashboard-ports.mjs +488 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/cli.mjs +537 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/activity-log.mjs +174 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/agents-store.mjs +465 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/api.mjs +223 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/artifact-template.html +810 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/artifacts-store.mjs +733 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/auth.mjs +548 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/background-store.mjs +446 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/backup-store.mjs +530 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/bg-poller.mjs +375 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/bg-retry.mjs +446 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/bg-spawner.mjs +390 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/browser.mjs +40 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/claude-bg-spawner.mjs +390 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/claude-info.mjs +412 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/claude-runner.mjs +284 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/claude-sdk.mjs +191 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/diagnostics-store.mjs +598 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/dialog-poller.mjs +105 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/dialog-store.mjs +177 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/digest-store.mjs +558 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/eval-store.mjs +281 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/eval.mjs +500 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/glyphs/mdx-compiler.mjs +596 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/headroom.mjs +649 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/lib/path-safe.mjs +283 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/lib/rate-limit.mjs +122 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/logger.mjs +71 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/memory-consolidator.mjs +225 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/memory-distillation.mjs +296 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/memory-git.mjs +473 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/memory-lightrag.mjs +1478 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/memory-obsidian.mjs +230 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/memory-schema.mjs +145 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/memory-secrets.mjs +84 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/memory-store.mjs +1093 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/metrics.mjs +268 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/minimax-usage-store.mjs +372 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/minimax.mjs +683 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/mod-security.mjs +398 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/mods-loader.mjs +1243 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/notifications-store.mjs +243 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/obsidian-store.mjs +318 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/ocr.mjs +55 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/otel.mjs +260 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/pair-store.mjs +138 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/progress-parser.mjs +221 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/projects-store.mjs +364 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/providers-store.mjs +1801 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/_shared.mjs +447 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/activity.mjs +195 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/agents-cc.mjs +194 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/agents.mjs +134 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/artifacts.mjs +279 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/auth.mjs +69 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/background.mjs +422 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/backup.mjs +112 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/chat.mjs +727 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/claude-session-detail.mjs +329 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/claude-sessions.mjs +259 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/clipboard.mjs +173 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/config.mjs +180 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/diagnostics.mjs +50 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/dialogs.mjs +86 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/digests.mjs +82 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/distill.mjs +129 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/doctor.mjs +71 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/env-vars.mjs +231 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/eval.mjs +187 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/fs.mjs +429 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/goal-planner.mjs +236 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/goals.mjs +212 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/headroom.mjs +126 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/history.mjs +78 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/lightrag.mjs +169 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/memory.mjs +1524 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/minimax.mjs +133 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/misc.mjs +90 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/mods.mjs +359 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/notifications.mjs +54 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/obsidian.mjs +239 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/ocr.mjs +182 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/overview.mjs +92 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/pair.mjs +67 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/projects.mjs +175 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/providers.mjs +308 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/schedules.mjs +159 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/settings.mjs +51 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/skills.mjs +65 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/tailscale.mjs +46 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/tasks.mjs +518 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/themes.mjs +51 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/update.mjs +340 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/usage.mjs +136 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/users.mjs +102 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/voice.mjs +167 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/workspaces.mjs +299 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes-v2/auth.mjs +59 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes-v2/events.mjs +121 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes-v2/health.mjs +21 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes-v2/index.mjs +90 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes-v2/sessions.mjs +111 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/schedules-runner.mjs +556 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/schedules-store.mjs +268 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/search-store.mjs +220 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/serve-info.mjs +1110 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/server.mjs +966 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/settings-store.mjs +45 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/skills-store.mjs +190 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/state.mjs +437 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/tailscale-store.mjs +113 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/task-delegator.mjs +969 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/tasks-store.mjs +556 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/tui.mjs +923 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/update-store.mjs +168 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/v2-auth-file.mjs +99 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/v2-event-bus.mjs +128 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/voice-store.mjs +229 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/voice-transcribe.mjs +72 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/watcher.mjs +81 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/workers/transcription-worker.mjs +213 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/workspaces.mjs +626 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/yaml.mjs +238 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/App.tsx +200 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/data/fetcher.ts +59 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/data/types.ts +168 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/data/useFetch.ts +62 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/data/useWebSocket.ts +153 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/main.tsx +28 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/shell/AppShell.tsx +90 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/shell/PageSkeleton.tsx +29 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/shell/Sidebar.tsx +361 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/shell/StatusBar.tsx +63 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/shell/Topbar.tsx +113 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/shell/index.ts +15 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/activity/ActivityFeed.tsx +137 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/agents/AgentActivity.tsx +101 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/agents/AgentCard.tsx +158 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/agents/AgentDetail.tsx +232 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/Button.tsx +141 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/ButtonGroup.tsx +32 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/Checkbox.tsx +49 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/Field.tsx +78 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/Form.tsx +23 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/IconButton.tsx +112 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/Input.tsx +94 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/RadioGroup.tsx +74 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/Select.tsx +171 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/Slider.tsx +68 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/Switch.tsx +56 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/Textarea.tsx +64 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/Toggle.tsx +36 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/ToggleGroup.tsx +85 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/Accordion.tsx +134 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/Avatar.tsx +175 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/Badge.tsx +93 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/BarList.tsx +101 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/Card.tsx +140 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/Chip.tsx +96 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/Kbd.tsx +42 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/ProgressBar.tsx +93 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/Sparkline.tsx +98 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/StatTile.tsx +150 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/Table.tsx +170 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/Timeline.tsx +130 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/ViewHeader.tsx +122 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/Alert.tsx +95 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/Banner.tsx +39 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/ContextMenu.tsx +143 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/Dialog.tsx +149 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/Drawer.tsx +8 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/DropdownMenu.tsx +231 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/EmptyState.tsx +48 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/Popover.tsx +56 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/Sheet.tsx +103 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/Skeleton.tsx +67 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/Spinner.tsx +30 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/Toast.tsx +66 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/Tooltip.tsx +89 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/goals/GoalCard.tsx +176 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/goals/GoalDetail.tsx +245 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/goals/KeyResult.tsx +115 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/index.ts +349 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/KanbanBoard.tsx +115 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/KanbanCard.tsx +391 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/KanbanCardBadges.tsx +111 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/KanbanColumn.tsx +181 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/KanbanContextMenu.tsx +126 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/KanbanDetailDialog.tsx +638 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/KanbanEmptyColumn.tsx +43 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/KanbanProgress.tsx +130 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/KanbanQuickAdd.tsx +141 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/KanbanToolbar.tsx +291 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/useKanbanSelection.ts +90 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/libraries/LibraryGrid.tsx +30 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/libraries/LibraryItem.tsx +161 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/memory/MemoryVault.tsx +144 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/navigation/CommandPalette.tsx +224 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/navigation/NavLink.tsx +81 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/navigation/Pagination.tsx +164 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/navigation/Tabs.tsx +128 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/primitives/Box.tsx +144 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/primitives/Center.tsx +40 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/primitives/Cluster.tsx +67 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/primitives/Grid.tsx +104 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/primitives/Inline.tsx +77 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/primitives/Portal.tsx +33 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/primitives/ScrollArea.tsx +62 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/primitives/Separator.tsx +42 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/primitives/Stack.tsx +73 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/primitives/VisuallyHidden.tsx +49 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/settings/SettingsNav.tsx +91 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/settings/SettingsRow.tsx +88 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/settings/SettingsSection.tsx +109 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/styles/globals.css +220 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/styles/reset.css +57 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/styles/tokens.css +217 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/theme/DensityProvider.tsx +66 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/theme/ThemeProvider.tsx +94 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/theme/ThemeToggle.tsx +88 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/theme/useDensity.ts +15 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/theme/useTheme.ts +16 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/utils/cx.ts +19 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/Activity/ActivityView.tsx +71 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/Agents/AgentsView.tsx +172 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/CommandPalette/AppCommandPalette.tsx +247 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/Goals/GoalsView.tsx +137 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/Libraries/LibrariesView.tsx +108 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/Memory/MemoryView.tsx +77 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/Overview/OverviewView.tsx +152 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/Router.tsx +72 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/Settings/SettingsView.tsx +330 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/Tasks/CommandPalettePlaceholder.tsx +106 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/Tasks/TasksView.tsx +792 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/vite-env.d.ts +15 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8.html +17 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/templates/mod/FORMAT.md +76 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/templates/mod/hello-mod/README.md +19 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/templates/mod/hello-mod/agents/greeter.md +8 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/templates/mod/hello-mod/commands/hello.md +6 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/templates/mod/hello-mod/mod.json +20 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/templates/mod/hello-mod/routes/ping.mjs +9 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/templates/mod/hello-mod/views/HelloView.tsx +10 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/tests/setup.ts +63 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/tests/smoke-v2.mjs +212 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/tsconfig.json +23 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/vite.config.ts +66 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/vitest.config.ts +20 -0
- package/.claude/worktrees/kanban-overhaul/bizar-plugins/registry.json +62 -0
- package/.claude/worktrees/kanban-overhaul/bookmarklet/bizar-clipper.js +48 -0
- package/.claude/worktrees/kanban-overhaul/browser-extensions/bizar-clipper/README.md +43 -0
- package/.claude/worktrees/kanban-overhaul/browser-extensions/bizar-clipper/background.js +95 -0
- package/.claude/worktrees/kanban-overhaul/browser-extensions/bizar-clipper/content.js +170 -0
- package/.claude/worktrees/kanban-overhaul/browser-extensions/bizar-clipper/icons/icon-128.png +0 -0
- package/.claude/worktrees/kanban-overhaul/browser-extensions/bizar-clipper/icons/icon-16.png +0 -0
- package/.claude/worktrees/kanban-overhaul/browser-extensions/bizar-clipper/icons/icon-48.png +0 -0
- package/.claude/worktrees/kanban-overhaul/browser-extensions/bizar-clipper/icons/icon.svg +4 -0
- package/.claude/worktrees/kanban-overhaul/browser-extensions/bizar-clipper/manifest.json +32 -0
- package/.claude/worktrees/kanban-overhaul/browser-extensions/bizar-clipper/popup.html +66 -0
- package/.claude/worktrees/kanban-overhaul/browser-extensions/bizar-clipper/popup.js +110 -0
- package/.claude/worktrees/kanban-overhaul/bun.lock +1558 -0
- package/.claude/worktrees/kanban-overhaul/cli/agent-browser-up.sh +152 -0
- package/.claude/worktrees/kanban-overhaul/cli/agent-browser-update.mjs +322 -0
- package/.claude/worktrees/kanban-overhaul/cli/artifact-cli.mjs +605 -0
- package/.claude/worktrees/kanban-overhaul/cli/artifact-render.mjs +621 -0
- package/.claude/worktrees/kanban-overhaul/cli/artifact-server.mjs +847 -0
- package/.claude/worktrees/kanban-overhaul/cli/artifact-templates.mjs +523 -0
- package/.claude/worktrees/kanban-overhaul/cli/artifact.mjs +63 -0
- package/.claude/worktrees/kanban-overhaul/cli/atomic.mjs +73 -0
- package/.claude/worktrees/kanban-overhaul/cli/audit.mjs +141 -0
- package/.claude/worktrees/kanban-overhaul/cli/banner.mjs +41 -0
- package/.claude/worktrees/kanban-overhaul/cli/bg.mjs +471 -0
- package/.claude/worktrees/kanban-overhaul/cli/bin.mjs +698 -0
- package/.claude/worktrees/kanban-overhaul/cli/bootstrap.mjs +77 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/artifact.mjs +20 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/claim.mjs +282 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/claude-cmd.mjs +348 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/clip.mjs +163 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/cost.mjs +279 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/dash.mjs +193 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/deploy/cloudflare.mjs +250 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/deploy/docker.mjs +222 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/deploy/fly.mjs +161 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/deploy/vercel.mjs +225 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/deploy.mjs +240 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/eval.mjs +396 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/headroom.mjs +204 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/install.mjs +170 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/lightrag.mjs +170 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/marketplace.mjs +64 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/memory.mjs +25 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/minimax.mjs +288 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/mod.mjs +185 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/ocr.mjs +182 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/plugin.mjs +358 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/rca.mjs +198 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/sandbox.mjs +220 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/service.mjs +79 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/setup-provider.mjs +466 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/tailscale.mjs +258 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/usage.mjs +113 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/util.mjs +577 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/validate.mjs +541 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/voice.mjs +211 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/workspace.mjs +247 -0
- package/.claude/worktrees/kanban-overhaul/cli/copy.mjs +586 -0
- package/.claude/worktrees/kanban-overhaul/cli/cost-gate.mjs +501 -0
- package/.claude/worktrees/kanban-overhaul/cli/dev-link.mjs +191 -0
- package/.claude/worktrees/kanban-overhaul/cli/digest.mjs +149 -0
- package/.claude/worktrees/kanban-overhaul/cli/doctor.mjs +217 -0
- package/.claude/worktrees/kanban-overhaul/cli/export.mjs +95 -0
- package/.claude/worktrees/kanban-overhaul/cli/feature-list-bridge.mjs +400 -0
- package/.claude/worktrees/kanban-overhaul/cli/heads-up.mjs +295 -0
- package/.claude/worktrees/kanban-overhaul/cli/init.mjs +368 -0
- package/.claude/worktrees/kanban-overhaul/cli/install.mjs +640 -0
- package/.claude/worktrees/kanban-overhaul/cli/memory-constants.mjs +76 -0
- package/.claude/worktrees/kanban-overhaul/cli/memory.mjs +1850 -0
- package/.claude/worktrees/kanban-overhaul/cli/plugin-runtime-deps.mjs +250 -0
- package/.claude/worktrees/kanban-overhaul/cli/post-install-smoke.mjs +256 -0
- package/.claude/worktrees/kanban-overhaul/cli/prompts.mjs +168 -0
- package/.claude/worktrees/kanban-overhaul/cli/providers-detect.mjs +233 -0
- package/.claude/worktrees/kanban-overhaul/cli/provision-claude.mjs +1176 -0
- package/.claude/worktrees/kanban-overhaul/cli/provision.mjs +2233 -0
- package/.claude/worktrees/kanban-overhaul/cli/repair.mjs +209 -0
- package/.claude/worktrees/kanban-overhaul/cli/service-controller.mjs +927 -0
- package/.claude/worktrees/kanban-overhaul/cli/service-env.mjs +139 -0
- package/.claude/worktrees/kanban-overhaul/cli/service.mjs +492 -0
- package/.claude/worktrees/kanban-overhaul/cli/update.mjs +29 -0
- package/.claude/worktrees/kanban-overhaul/cli/utils.mjs +221 -0
- package/.claude/worktrees/kanban-overhaul/cli/worker-dispatcher.mjs +259 -0
- package/.claude/worktrees/kanban-overhaul/config/AGENTS.md +595 -0
- package/.claude/worktrees/kanban-overhaul/config/agents/_shared/AGENT_BASELINE.md +155 -0
- package/.claude/worktrees/kanban-overhaul/config/agents/_shared/CLINE_TOOLS.md +398 -0
- package/.claude/worktrees/kanban-overhaul/config/agents/_shared/SKILLS.md +109 -0
- package/.claude/worktrees/kanban-overhaul/config/agents/agent-browser.md +90 -0
- package/.claude/worktrees/kanban-overhaul/config/agents/baldr.md +60 -0
- package/.claude/worktrees/kanban-overhaul/config/agents/forseti.md +60 -0
- package/.claude/worktrees/kanban-overhaul/config/agents/frigg.md +52 -0
- package/.claude/worktrees/kanban-overhaul/config/agents/heimdall.md +44 -0
- package/.claude/worktrees/kanban-overhaul/config/agents/hermod.md +64 -0
- package/.claude/worktrees/kanban-overhaul/config/agents/mimir.md +60 -0
- package/.claude/worktrees/kanban-overhaul/config/agents/odin.md +310 -0
- package/.claude/worktrees/kanban-overhaul/config/agents/quick.md +47 -0
- package/.claude/worktrees/kanban-overhaul/config/agents/semble-search.md +59 -0
- package/.claude/worktrees/kanban-overhaul/config/agents/thor.md +64 -0
- package/.claude/worktrees/kanban-overhaul/config/agents/tyr.md +67 -0
- package/.claude/worktrees/kanban-overhaul/config/agents/vidarr.md +65 -0
- package/.claude/worktrees/kanban-overhaul/config/agents/vor.md +62 -0
- package/.claude/worktrees/kanban-overhaul/config/commands/audit.md +5 -0
- package/.claude/worktrees/kanban-overhaul/config/commands/bizar.md +22 -0
- package/.claude/worktrees/kanban-overhaul/config/commands/explain.md +5 -0
- package/.claude/worktrees/kanban-overhaul/config/commands/init.md +26 -0
- package/.claude/worktrees/kanban-overhaul/config/commands/learn.md +5 -0
- package/.claude/worktrees/kanban-overhaul/config/commands/plan.md +30 -0
- package/.claude/worktrees/kanban-overhaul/config/commands/plow-through.md +47 -0
- package/.claude/worktrees/kanban-overhaul/config/commands/pr-review.md +5 -0
- package/.claude/worktrees/kanban-overhaul/config/commands/setup-provider.md +95 -0
- package/.claude/worktrees/kanban-overhaul/config/commands/tailscale-serve.md +97 -0
- package/.claude/worktrees/kanban-overhaul/config/commands/team.md +124 -0
- package/.claude/worktrees/kanban-overhaul/config/commands/test.md +60 -0
- package/.claude/worktrees/kanban-overhaul/config/commands/validate.md +66 -0
- package/.claude/worktrees/kanban-overhaul/config/commands/visual-plan.md +19 -0
- package/.claude/worktrees/kanban-overhaul/config/hooks/PostToolUse +66 -0
- package/.claude/worktrees/kanban-overhaul/config/hooks/PreToolUse +82 -0
- package/.claude/worktrees/kanban-overhaul/config/hooks/README.md +68 -0
- package/.claude/worktrees/kanban-overhaul/config/hooks/TaskResume +48 -0
- package/.claude/worktrees/kanban-overhaul/config/hooks/TaskStart +47 -0
- package/.claude/worktrees/kanban-overhaul/config/hooks/UserPromptSubmit +55 -0
- package/.claude/worktrees/kanban-overhaul/config/rules/general.md +9 -0
- package/.claude/worktrees/kanban-overhaul/config/rules/git.md +11 -0
- package/.claude/worktrees/kanban-overhaul/config/rules/javascript.md +10 -0
- package/.claude/worktrees/kanban-overhaul/config/rules/python.md +10 -0
- package/.claude/worktrees/kanban-overhaul/config/rules/testing.md +10 -0
- package/.claude/worktrees/kanban-overhaul/config/rules/thinking.md +56 -0
- package/.claude/worktrees/kanban-overhaul/config/rules/uncertainty.md +70 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/9router/SKILL.md +80 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/9router-chat/SKILL.md +73 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/9router-embeddings/SKILL.md +69 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/9router-image/SKILL.md +86 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/9router-stt/SKILL.md +79 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/9router-tts/SKILL.md +80 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/9router-web-fetch/SKILL.md +99 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/9router-web-search/SKILL.md +91 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/bizar/README.md +9 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/bizar/SKILL.md +447 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/cpp-coding-standards/README.md +28 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/cpp-coding-standards/SKILL.md +634 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/cpp-coding-standards/agents/openai.yaml +4 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/cpp-coding-standards/references/concurrency.md +320 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/cpp-coding-standards/references/error-handling.md +229 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/cpp-coding-standards/references/memory-safety.md +216 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/cpp-coding-standards/references/modern-idioms.md +282 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/cpp-coding-standards/references/review-checklist.md +96 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/cpp-testing/README.md +28 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/cpp-testing/SKILL.md +304 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/cpp-testing/agents/openai.yaml +4 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/cpp-testing/references/coverage.md +370 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/cpp-testing/references/framework-compare.md +175 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/cpp-testing/references/host-test-for-embedded.md +499 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/cpp-testing/references/mocking.md +364 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/cpp-testing/references/tdd-workflow.md +308 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/cubesandbox/SKILL.md +148 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/README.md +41 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/SKILL.md +439 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/agents/openai.yaml +4 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/references/freertos-patterns.md +214 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/references/host-tests.md +164 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/references/idf-py-commands.md +157 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/references/kconfig.md +159 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/references/logging-discipline.md +118 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/references/memory-and-iram.md +137 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/references/nvs.md +121 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/references/packed-structs.md +192 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/scripts/idf_env.sh +47 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/scripts/size_check.sh +77 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/glyph/SKILL.md +163 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/harness-engineering/SKILL.md +142 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/lightrag/SKILL.md +81 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/memory-protocol/SKILL.md +105 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/obsidian/SKILL.md +306 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/read-the-damn-docs/SKILL.md +113 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/self-improvement/SKILL.md +64 -0
- package/.claude/worktrees/kanban-overhaul/config/trigger-patterns.json +186 -0
- package/.claude/worktrees/kanban-overhaul/docker-compose.yml +50 -0
- package/.claude/worktrees/kanban-overhaul/docs/A11Y.md +81 -0
- package/.claude/worktrees/kanban-overhaul/docs/DEPLOY.md +360 -0
- package/.claude/worktrees/kanban-overhaul/docs/DOCKER.md +250 -0
- package/.claude/worktrees/kanban-overhaul/docs/INDEX.md +223 -0
- package/.claude/worktrees/kanban-overhaul/docs/PLUGIN_REGISTRY.md +107 -0
- package/.claude/worktrees/kanban-overhaul/docs/RELEASING.md +693 -0
- package/.claude/worktrees/kanban-overhaul/docs/architecture.md +317 -0
- package/.claude/worktrees/kanban-overhaul/docs/code-review.md +242 -0
- package/.claude/worktrees/kanban-overhaul/docs/curator.md +144 -0
- package/.claude/worktrees/kanban-overhaul/docs/dashboard-ui-migration.md +807 -0
- package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-001-cline-rewrite.md +114 -0
- package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-002-in-process-clinecore.md +139 -0
- package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-003-in-process-memory-vault.md +101 -0
- package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-004-cline-agent-teams.md +112 -0
- package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-005-bg-agents-via-dashboard.md +77 -0
- package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-006-kanban-board.md +69 -0
- package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-007-tool-approval-gate.md +147 -0
- package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-008-skill-curator.md +100 -0
- package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-009-pre-compaction-flush.md +106 -0
- package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-010-knowledge-graph-tools.md +95 -0
- package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-011-claude-code-migration.md +172 -0
- package/.claude/worktrees/kanban-overhaul/docs/graph-tools.md +130 -0
- package/.claude/worktrees/kanban-overhaul/docs/migration-guide.md +471 -0
- package/.claude/worktrees/kanban-overhaul/docs/migrations/cline-replacement.md +118 -0
- package/.claude/worktrees/kanban-overhaul/docs/postmortems/2026-06-18-plugin-state-deadlock.md +250 -0
- package/.claude/worktrees/kanban-overhaul/docs/quality-document.md +74 -0
- package/.claude/worktrees/kanban-overhaul/docs/releases/v0.5.2.md +66 -0
- package/.claude/worktrees/kanban-overhaul/docs/releases/v0.5.4.md +85 -0
- package/.claude/worktrees/kanban-overhaul/docs/releases/v2.3.0.md +96 -0
- package/.claude/worktrees/kanban-overhaul/docs/releases/v3.24.0.md +155 -0
- package/.claude/worktrees/kanban-overhaul/docs/releases/v4.0.0.md +123 -0
- package/.claude/worktrees/kanban-overhaul/docs/releases/v7.0.0.md +173 -0
- package/.claude/worktrees/kanban-overhaul/docs/safety.md +216 -0
- package/.claude/worktrees/kanban-overhaul/feature_list.json +1297 -0
- package/.claude/worktrees/kanban-overhaul/init.sh +211 -0
- package/.claude/worktrees/kanban-overhaul/install.sh +498 -0
- package/.claude/worktrees/kanban-overhaul/mods-examples/impeccable/INSTRUCTIONS.md +82 -0
- package/.claude/worktrees/kanban-overhaul/mods-examples/impeccable/mod.json +37 -0
- package/.claude/worktrees/kanban-overhaul/mods-examples/impeccable/route.mjs +136 -0
- package/.claude/worktrees/kanban-overhaul/mods-examples/impeccable/web/index.html +180 -0
- package/.claude/worktrees/kanban-overhaul/mods-examples/lightrag/INSTRUCTIONS.md +81 -0
- package/.claude/worktrees/kanban-overhaul/mods-examples/lightrag/mod.json +61 -0
- package/.claude/worktrees/kanban-overhaul/mods-examples/lightrag/route.mjs +461 -0
- package/.claude/worktrees/kanban-overhaul/mods-examples/lightrag/web/index.html +263 -0
- package/.claude/worktrees/kanban-overhaul/mods-examples/ponytail/INSTRUCTIONS.md +87 -0
- package/.claude/worktrees/kanban-overhaul/mods-examples/ponytail/agents/thor.md +64 -0
- package/.claude/worktrees/kanban-overhaul/mods-examples/ponytail/mod.json +36 -0
- package/.claude/worktrees/kanban-overhaul/mods-examples/ponytail/route.mjs +98 -0
- package/.claude/worktrees/kanban-overhaul/mods-examples/ponytail/web/index.html +126 -0
- package/.claude/worktrees/kanban-overhaul/package.json +154 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/ARCHITECTURE.md +70 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/LICENSE +21 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/README.md +80 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/package.json +30 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/agent-registry.ts +304 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/consensus/byzantine.ts +587 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/consensus/index.ts +147 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/consensus/queen.ts +173 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/consensus/types.ts +199 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/dangerous-patterns.ts +127 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/federation/audit.ts +156 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/federation/budget.ts +269 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/federation/envelope.ts +144 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/federation/hmac.ts +160 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/federation/index.ts +443 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/federation/pii.ts +241 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/federation/policy.ts +112 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/federation/trust.ts +146 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/fingerprint.ts +0 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/index.ts +114 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/mcp/bin.ts +51 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/mcp/server.ts +848 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/memory/index.ts +160 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/router/codemod-intent.ts +125 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/router/index.ts +247 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/router/memory-distillation-shim.mjs +18 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/router/memory-distillation.ts +249 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/router/model-router.ts +235 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/router/q-learning-router.ts +304 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/swarm-topology.ts +279 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/version.ts +4 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/tsconfig.json +25 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/vitest.config.ts +9 -0
- package/.claude/worktrees/kanban-overhaul/plugins/bizar/ARCHITECTURE.md +72 -0
- package/.claude/worktrees/kanban-overhaul/plugins/bizar/CONSTRAINTS.md +62 -0
- package/.claude/worktrees/kanban-overhaul/plugins/bizar/LICENSE +21 -0
- package/.claude/worktrees/kanban-overhaul/plugins/bizar/README.md +46 -0
- package/.claude/worktrees/kanban-overhaul/plugins/bizar/index.ts +50 -0
- package/.claude/worktrees/kanban-overhaul/plugins/bizar/package.json +18 -0
- package/.claude/worktrees/kanban-overhaul/plugins/bizar/tsconfig.json +29 -0
- package/.claude/worktrees/kanban-overhaul/scripts/bh-full-e2e.mjs +298 -0
- package/.claude/worktrees/kanban-overhaul/scripts/check-agents.mjs +73 -0
- package/.claude/worktrees/kanban-overhaul/scripts/check-arch.sh +80 -0
- package/.claude/worktrees/kanban-overhaul/scripts/check-deps.mjs +492 -0
- package/.claude/worktrees/kanban-overhaul/scripts/clean-state-check.sh +81 -0
- package/.claude/worktrees/kanban-overhaul/scripts/git-hooks/pre-commit +59 -0
- package/.claude/worktrees/kanban-overhaul/scripts/git-hooks/pre-push +54 -0
- package/.claude/worktrees/kanban-overhaul/scripts/install-hooks.sh +29 -0
- package/.claude/worktrees/kanban-overhaul/scripts/install-service.mjs +190 -0
- package/.claude/worktrees/kanban-overhaul/scripts/mirror-claude-md.sh +78 -0
- package/.claude/worktrees/kanban-overhaul/scripts/session-trace.sh +52 -0
- package/.claude/worktrees/kanban-overhaul/scripts/test-in-container.sh +157 -0
- package/.claude/worktrees/kanban-overhaul/scripts/verify-feature.sh +102 -0
- package/.claude/worktrees/kanban-overhaul/skills-lock.json +11 -0
- package/.claude/worktrees/kanban-overhaul/templates/clean-state-checklist.md +55 -0
- package/.claude/worktrees/kanban-overhaul/templates/deploy/cloudflare/README.md +32 -0
- package/.claude/worktrees/kanban-overhaul/templates/deploy/cloudflare/functions-index.template.js +15 -0
- package/.claude/worktrees/kanban-overhaul/templates/deploy/cloudflare/wrangler.toml.template +9 -0
- package/.claude/worktrees/kanban-overhaul/templates/deploy/docker/.env.template +16 -0
- package/.claude/worktrees/kanban-overhaul/templates/deploy/docker/README.md +58 -0
- package/.claude/worktrees/kanban-overhaul/templates/deploy/docker/docker-compose.template.yml +23 -0
- package/.claude/worktrees/kanban-overhaul/templates/deploy/fly/README.md +35 -0
- package/.claude/worktrees/kanban-overhaul/templates/deploy/fly/fly.toml.template +28 -0
- package/.claude/worktrees/kanban-overhaul/templates/deploy/vercel/README.md +29 -0
- package/.claude/worktrees/kanban-overhaul/templates/deploy/vercel/api-index.template.js +18 -0
- package/.claude/worktrees/kanban-overhaul/templates/deploy/vercel/vercel.json.template +16 -0
- package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/README.md +58 -0
- package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/citation.json +16 -0
- package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/code-review.json +16 -0
- package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/code-search-basic.json +28 -0
- package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/concise-output.json +16 -0
- package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/context-window.json +16 -0
- package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/error-recovery.json +16 -0
- package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/json-output.json +20 -0
- package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/latency-bounds.json +16 -0
- package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/multi-language.json +16 -0
- package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/regression-suite.json +79 -0
- package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/response-format.json +30 -0
- package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/safe-paths.json +16 -0
- package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/tool-call-correctness.json +24 -0
- package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/tool-call-multi-step.json +18 -0
- package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/unicode-handling.json +16 -0
- package/.claude/worktrees/kanban-overhaul/templates/evaluator-rubric.md +50 -0
- package/.claude/worktrees/kanban-overhaul/templates/plan/htmx.min.js +1 -0
- package/.claude/worktrees/kanban-overhaul/templates/plan/library/bug-investigation.mdx +79 -0
- package/.claude/worktrees/kanban-overhaul/templates/plan/library/decision-record.mdx +71 -0
- package/.claude/worktrees/kanban-overhaul/templates/plan/library/feature-design.mdx +92 -0
- package/.claude/worktrees/kanban-overhaul/templates/plan/meta.json.template +8 -0
- package/.claude/worktrees/kanban-overhaul/templates/plan/plan.mdx.template +46 -0
- package/.claude/worktrees/kanban-overhaul/templates/plugin-template/README.md +121 -0
- package/.claude/worktrees/kanban-overhaul/templates/plugin-template/index.js +66 -0
- package/.claude/worktrees/kanban-overhaul/templates/plugin-template/plugin.json +42 -0
- package/.claude/worktrees/kanban-overhaul/templates/plugin-template/tests/plugin.test.js +83 -0
- package/.claude/worktrees/kanban-overhaul/templates/schedules/daily-backup.json +12 -0
- package/.claude/worktrees/kanban-overhaul/templates/schedules/daily-cleanup.json +12 -0
- package/.claude/worktrees/kanban-overhaul/templates/schedules/hourly-health-check.json +12 -0
- package/.claude/worktrees/kanban-overhaul/templates/schedules/webhook-on-push.json +13 -0
- package/.claude/worktrees/kanban-overhaul/templates/schedules/weekly-digest.json +13 -0
- package/.claude/worktrees/kanban-overhaul/templates/sprint-contract.md +47 -0
- package/.claude/worktrees/kanban-overhaul/tsconfig.json +44 -0
- package/.claude/worktrees/kanban-overhaul/vite.config.ts +51 -0
- package/bizar-dash/dist/assets/ActivityFeed-BXIkGGQ1.js +16 -0
- package/bizar-dash/dist/assets/ActivityFeed-BXIkGGQ1.js.map +1 -0
- package/bizar-dash/dist/assets/ActivityView-CBxNNrZa.js +12 -0
- package/bizar-dash/dist/assets/ActivityView-CBxNNrZa.js.map +1 -0
- package/bizar-dash/dist/assets/AgentsView-uv4l21AH.js +23 -0
- package/bizar-dash/dist/assets/AgentsView-uv4l21AH.js.map +1 -0
- package/bizar-dash/dist/assets/BackgroundJobsView-CB4WXIpk.js +6 -0
- package/bizar-dash/dist/assets/BackgroundJobsView-CB4WXIpk.js.map +1 -0
- package/bizar-dash/dist/assets/{Card-C_bvqXdQ.js → Card-CeZsWlcP.js} +1 -1
- package/bizar-dash/dist/assets/{Card-C_bvqXdQ.js.map → Card-CeZsWlcP.js.map} +1 -1
- package/bizar-dash/dist/assets/Chip-OPjSKl2I.js +1 -0
- package/bizar-dash/dist/assets/Chip-OPjSKl2I.js.map +1 -0
- package/bizar-dash/dist/assets/{EmptyState-BWQuKnk9.js → EmptyState-BrLA8mbE.js} +1 -1
- package/bizar-dash/dist/assets/{EmptyState-BWQuKnk9.js.map → EmptyState-BrLA8mbE.js.map} +1 -1
- package/bizar-dash/dist/assets/GoalsView-B8R-kxQr.js +11 -0
- package/bizar-dash/dist/assets/GoalsView-B8R-kxQr.js.map +1 -0
- package/bizar-dash/dist/assets/{Grid-C62gCPqt.js → Grid-B7NgNtff.js} +1 -1
- package/bizar-dash/dist/assets/{Grid-C62gCPqt.js.map → Grid-B7NgNtff.js.map} +1 -1
- package/bizar-dash/dist/assets/Input-BW_5Sl6N.js +1 -0
- package/bizar-dash/dist/assets/Input-BW_5Sl6N.js.map +1 -0
- package/bizar-dash/dist/assets/KanbanCard-B-NOSfMN.js +21 -0
- package/bizar-dash/dist/assets/KanbanCard-B-NOSfMN.js.map +1 -0
- package/bizar-dash/dist/assets/LibrariesView-D6eB7B2A.js +67 -0
- package/bizar-dash/dist/assets/LibrariesView-D6eB7B2A.js.map +1 -0
- package/bizar-dash/dist/assets/MemoryView-MK4m1KbR.js +13 -0
- package/bizar-dash/dist/assets/MemoryView-MK4m1KbR.js.map +1 -0
- package/bizar-dash/dist/assets/OverviewView-CHavfYBa.js +1 -0
- package/bizar-dash/dist/assets/OverviewView-CHavfYBa.js.map +1 -0
- package/bizar-dash/dist/assets/SchedulesView-zV-0pbsz.js +1 -0
- package/bizar-dash/dist/assets/SchedulesView-zV-0pbsz.js.map +1 -0
- package/bizar-dash/dist/assets/Select-B6Ho36Tq.js +11 -0
- package/bizar-dash/dist/assets/Select-B6Ho36Tq.js.map +1 -0
- package/bizar-dash/dist/assets/SettingsRow-Br21uRFz.js +1 -0
- package/bizar-dash/dist/assets/SettingsRow-Br21uRFz.js.map +1 -0
- package/bizar-dash/dist/assets/SettingsView-Cx3uJrus.js +38 -0
- package/bizar-dash/dist/assets/SettingsView-Cx3uJrus.js.map +1 -0
- package/bizar-dash/dist/assets/Sheet-Cmu_4Zea.js +1 -0
- package/bizar-dash/dist/assets/Sheet-Cmu_4Zea.js.map +1 -0
- package/bizar-dash/dist/assets/Slider-B_jPr-SR.js +1 -0
- package/bizar-dash/dist/assets/Slider-B_jPr-SR.js.map +1 -0
- package/bizar-dash/dist/assets/Sparkline-Cmqw0N39.js +1 -0
- package/bizar-dash/dist/assets/Sparkline-Cmqw0N39.js.map +1 -0
- package/bizar-dash/dist/assets/Switch-C7Qyu50Y.js +10 -0
- package/bizar-dash/dist/assets/Switch-C7Qyu50Y.js.map +1 -0
- package/bizar-dash/dist/assets/TasksView-BXADmjgb.js +1 -0
- package/bizar-dash/dist/assets/TasksView-BXADmjgb.js.map +1 -0
- package/bizar-dash/dist/assets/Textarea-KIN98DVH.js +1 -0
- package/bizar-dash/dist/assets/Textarea-KIN98DVH.js.map +1 -0
- package/bizar-dash/dist/assets/{ViewHeader-D6c2cw1b.js → ViewHeader-CPbqI-w8.js} +1 -1
- package/bizar-dash/dist/assets/{ViewHeader-D6c2cw1b.js.map → ViewHeader-CPbqI-w8.js.map} +1 -1
- package/bizar-dash/dist/assets/{brain-DeoXNDE2.js → brain-jN_ldx3U.js} +1 -1
- package/bizar-dash/dist/assets/{brain-DeoXNDE2.js.map → brain-jN_ldx3U.js.map} +1 -1
- package/bizar-dash/dist/assets/{calendar-DRlQkGJc.js → calendar-DZGgPP2_.js} +2 -2
- package/bizar-dash/dist/assets/{calendar-DRlQkGJc.js.map → calendar-DZGgPP2_.js.map} +1 -1
- package/bizar-dash/dist/assets/{circle-check-DmYQ3vGp.js → circle-check-XhUtiACZ.js} +1 -1
- package/bizar-dash/dist/assets/{circle-check-DmYQ3vGp.js.map → circle-check-XhUtiACZ.js.map} +1 -1
- package/bizar-dash/dist/assets/clock-BXBnSbox.js +6 -0
- package/bizar-dash/dist/assets/clock-BXBnSbox.js.map +1 -0
- package/bizar-dash/dist/assets/{cmdk-BwN8hcKQ.js → cmdk-D15rXxc5.js} +2 -2
- package/bizar-dash/dist/assets/{cmdk-BwN8hcKQ.js.map → cmdk-D15rXxc5.js.map} +1 -1
- package/bizar-dash/dist/assets/dnd-kit-Bormfg7j.js +5 -0
- package/bizar-dash/dist/assets/{dnd-kit-DR2Qzzxk.js.map → dnd-kit-Bormfg7j.js.map} +1 -1
- package/bizar-dash/dist/assets/git-pull-request-BCt0CEjc.js +11 -0
- package/bizar-dash/dist/assets/git-pull-request-BCt0CEjc.js.map +1 -0
- package/bizar-dash/dist/assets/index-C0JBGB5M.js +1 -0
- package/bizar-dash/dist/assets/index-C0JBGB5M.js.map +1 -0
- package/bizar-dash/dist/assets/index-CrWI7sQR.js +1 -0
- package/bizar-dash/dist/assets/index-CrWI7sQR.js.map +1 -0
- package/bizar-dash/dist/assets/main-CCimEcWH.js +134 -0
- package/bizar-dash/dist/assets/main-CCimEcWH.js.map +1 -0
- package/bizar-dash/dist/assets/{main-COdgjqbZ.css → main-CcQfRfIJ.css} +1 -1
- package/bizar-dash/dist/assets/{minus-CrStJTZ7.js → play-B0rTjpSg.js} +2 -2
- package/bizar-dash/dist/assets/play-B0rTjpSg.js.map +1 -0
- package/bizar-dash/dist/assets/plus-BaTQsS9G.js +6 -0
- package/bizar-dash/dist/assets/plus-BaTQsS9G.js.map +1 -0
- package/bizar-dash/dist/assets/refresh-cw-CoatVcs3.js +6 -0
- package/bizar-dash/dist/assets/refresh-cw-CoatVcs3.js.map +1 -0
- package/bizar-dash/dist/assets/terminal-k-1HFHcN.js +11 -0
- package/bizar-dash/dist/assets/terminal-k-1HFHcN.js.map +1 -0
- package/bizar-dash/dist/assets/trash-2-DtpKnAn2.js +6 -0
- package/bizar-dash/dist/assets/trash-2-DtpKnAn2.js.map +1 -0
- package/bizar-dash/dist/assets/triangle-alert-FHSs_e5b.js +6 -0
- package/bizar-dash/dist/assets/triangle-alert-FHSs_e5b.js.map +1 -0
- package/bizar-dash/dist/assets/{wrench-BJ1WIC4u.js → wrench-CbBE0oQ0.js} +2 -2
- package/bizar-dash/dist/assets/{wrench-BJ1WIC4u.js.map → wrench-CbBE0oQ0.js.map} +1 -1
- package/bizar-dash/dist/v8.html +3 -3
- package/bizar-dash/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
- package/bizar-dash/src/server/api.mjs +15 -0
- package/bizar-dash/src/server/bg-poller.mjs +81 -1
- package/bizar-dash/src/server/bg-poller.test.mjs +28 -0
- package/bizar-dash/src/server/progress-parser.mjs +237 -0
- package/bizar-dash/src/server/progress-parser.test.mjs +105 -0
- package/bizar-dash/src/server/routes/agents-cc.mjs +381 -0
- package/bizar-dash/src/server/routes/agents-cc.test.mjs +35 -0
- package/bizar-dash/src/server/routes/goals.mjs +307 -0
- package/bizar-dash/src/server/routes/spawn.mjs +59 -0
- package/bizar-dash/src/server/routes/tasks.mjs +11 -0
- package/bizar-dash/src/server/server.mjs +1 -1
- package/bizar-dash/src/web/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
- package/bizar-dash/src/web/v8/App.tsx +56 -7
- package/bizar-dash/src/web/v8/__tests__/App.test.tsx +2 -2
- package/bizar-dash/src/web/v8/__tests__/BackgroundJobsView.test.tsx +172 -0
- package/bizar-dash/src/web/v8/__tests__/MemoryView.test.tsx +91 -0
- package/bizar-dash/src/web/v8/__tests__/NotificationsPopover.test.tsx +91 -0
- package/bizar-dash/src/web/v8/__tests__/SchedulesView.test.tsx +157 -0
- package/bizar-dash/src/web/v8/__tests__/Topbar.test.tsx +86 -0
- package/bizar-dash/src/web/v8/__tests__/changelog.test.tsx +79 -0
- package/bizar-dash/src/web/v8/__tests__/control-plane.test.tsx +104 -0
- package/bizar-dash/src/web/v8/__tests__/theme.test.tsx +10 -4
- package/bizar-dash/src/web/v8/__tests__/useFetch.test.ts +92 -0
- package/bizar-dash/src/web/v8/__tests__/useWebSocket.test.ts +87 -0
- package/bizar-dash/src/web/v8/__tests__/views.test.tsx +116 -40
- package/bizar-dash/src/web/v8/data/fetcher.ts +59 -0
- package/bizar-dash/src/web/v8/data/types.ts +156 -0
- package/bizar-dash/src/web/v8/data/useFetch.ts +62 -0
- package/bizar-dash/src/web/v8/data/useWebSocket.ts +161 -0
- package/bizar-dash/src/web/v8/shell/Sidebar.tsx +46 -12
- package/bizar-dash/src/web/v8/shell/Topbar.tsx +30 -4
- package/bizar-dash/src/web/v8/ui/agents/AgentDetail.tsx +283 -0
- package/bizar-dash/src/web/v8/ui/agents/AgentStreamPanel.tsx +371 -0
- package/bizar-dash/src/web/v8/ui/feedback/NotificationsPopover.tsx +239 -0
- package/bizar-dash/src/web/v8/ui/goals/GoalDetail.tsx +251 -0
- package/bizar-dash/src/web/v8/ui/kanban/KanbanBoard.tsx +6 -3
- package/bizar-dash/src/web/v8/ui/kanban/KanbanCard.tsx +3 -3
- package/bizar-dash/src/web/v8/ui/kanban/KanbanColumn.tsx +10 -5
- package/bizar-dash/src/web/v8/ui/styles/globals.css +5 -0
- package/bizar-dash/src/web/v8/views/Activity/ActivityView.tsx +415 -16
- package/bizar-dash/src/web/v8/views/Agents/AgentsView.tsx +151 -87
- package/bizar-dash/src/web/v8/views/BackgroundJobs/BackgroundJobsView.tsx +442 -0
- package/bizar-dash/src/web/v8/views/CommandPalette/AppCommandPalette.test.tsx +1 -1
- package/bizar-dash/src/web/v8/views/CommandPalette/AppCommandPalette.tsx +148 -30
- package/bizar-dash/src/web/v8/views/Goals/GoalsView.tsx +176 -67
- package/bizar-dash/src/web/v8/views/Libraries/LibrariesView.tsx +78 -11
- package/bizar-dash/src/web/v8/views/Memory/MemoryView.tsx +212 -42
- package/bizar-dash/src/web/v8/views/Overview/OverviewView.tsx +112 -52
- package/bizar-dash/src/web/v8/views/Router.tsx +23 -37
- package/bizar-dash/src/web/v8/views/Schedules/SchedulesView.tsx +395 -0
- package/bizar-dash/src/web/v8/views/Settings/SettingsView.tsx +651 -210
- package/bizar-dash/src/web/v8/views/Tasks/TasksView.tsx +142 -49
- package/bizar-dash/tests/components/Button.test.tsx +51 -14
- package/bizar-dash/tests/components/Card.test.tsx +37 -20
- package/bizar-dash/tests/components/Dialog.test.tsx +80 -0
- package/bizar-dash/tests/components/Toast.test.tsx +48 -95
- package/bizar-dash/tests/goals-decompose.test.mjs +179 -0
- package/bizar-dash/tests/setup.ts +21 -0
- package/bizar-dash/tests/ui/primitives/VisuallyHidden.test.tsx +30 -15
- package/bizar-dash/vite.config.ts +15 -0
- package/bizar-dash/vitest.config.ts +4 -1
- package/cli/bin.mjs +32 -0
- package/cli/install.mjs +26 -1
- package/cli/provision-claude.mjs +86 -0
- package/package.json +1 -1
- package/packages/sdk/.harness/agents.json +17 -0
- package/packages/sdk/.harness/topology.json +4 -0
- package/scripts/run-dev.mjs +84 -0
- package/bizar-dash/dist/assets/ActivityFeed-BRBtQOHB.js +0 -6
- package/bizar-dash/dist/assets/ActivityFeed-BRBtQOHB.js.map +0 -1
- package/bizar-dash/dist/assets/ActivityView-CwqhxBfh.js +0 -1
- package/bizar-dash/dist/assets/ActivityView-CwqhxBfh.js.map +0 -1
- package/bizar-dash/dist/assets/AgentActivity-6MxU-a9F.js +0 -1
- package/bizar-dash/dist/assets/AgentActivity-6MxU-a9F.js.map +0 -1
- package/bizar-dash/dist/assets/AgentsView-BYrOFdwl.js +0 -8
- package/bizar-dash/dist/assets/AgentsView-BYrOFdwl.js.map +0 -1
- package/bizar-dash/dist/assets/Badge-Cd61wsBa.js +0 -1
- package/bizar-dash/dist/assets/Badge-Cd61wsBa.js.map +0 -1
- package/bizar-dash/dist/assets/GoalsView-Dok0yt9S.js +0 -11
- package/bizar-dash/dist/assets/GoalsView-Dok0yt9S.js.map +0 -1
- package/bizar-dash/dist/assets/KanbanCard-CtTKP6ZX.js +0 -21
- package/bizar-dash/dist/assets/KanbanCard-CtTKP6ZX.js.map +0 -1
- package/bizar-dash/dist/assets/LibrariesView-BcyBQXiY.js +0 -67
- package/bizar-dash/dist/assets/LibrariesView-BcyBQXiY.js.map +0 -1
- package/bizar-dash/dist/assets/MemoryView-49wR4u-y.js +0 -13
- package/bizar-dash/dist/assets/MemoryView-49wR4u-y.js.map +0 -1
- package/bizar-dash/dist/assets/OverviewView-BtQ_UWYj.js +0 -1
- package/bizar-dash/dist/assets/OverviewView-BtQ_UWYj.js.map +0 -1
- package/bizar-dash/dist/assets/ProgressBar-CpvDeq9F.js +0 -1
- package/bizar-dash/dist/assets/ProgressBar-CpvDeq9F.js.map +0 -1
- package/bizar-dash/dist/assets/SettingsRow-DmIe5OUu.js +0 -30
- package/bizar-dash/dist/assets/SettingsRow-DmIe5OUu.js.map +0 -1
- package/bizar-dash/dist/assets/SettingsView-D1KmGWbi.js +0 -48
- package/bizar-dash/dist/assets/SettingsView-D1KmGWbi.js.map +0 -1
- package/bizar-dash/dist/assets/StatTile-BkIP32gG.js +0 -11
- package/bizar-dash/dist/assets/StatTile-BkIP32gG.js.map +0 -1
- package/bizar-dash/dist/assets/TasksView-Cba3GJ42.js +0 -1
- package/bizar-dash/dist/assets/TasksView-Cba3GJ42.js.map +0 -1
- package/bizar-dash/dist/assets/dnd-kit-DR2Qzzxk.js +0 -5
- package/bizar-dash/dist/assets/git-merge-OoqBKQer.js +0 -6
- package/bizar-dash/dist/assets/git-merge-OoqBKQer.js.map +0 -1
- package/bizar-dash/dist/assets/git-pull-request-CXBQTR2f.js +0 -6
- package/bizar-dash/dist/assets/git-pull-request-CXBQTR2f.js.map +0 -1
- package/bizar-dash/dist/assets/main-Cw6gybzS.js +0 -109
- package/bizar-dash/dist/assets/main-Cw6gybzS.js.map +0 -1
- package/bizar-dash/dist/assets/message-square-DUTeIQAR.js +0 -6
- package/bizar-dash/dist/assets/message-square-DUTeIQAR.js.map +0 -1
- package/bizar-dash/dist/assets/minus-CrStJTZ7.js.map +0 -1
- /package/bizar-dash/tests/{BackgroundAgents.test.tsx → v7-archive/BackgroundAgents.test.tsx} +0 -0
- /package/bizar-dash/tests/{a11y → v7-archive/a11y}/forms.test.tsx +0 -0
- /package/bizar-dash/tests/{a11y.test.tsx → v7-archive/a11y.test.tsx} +0 -0
- /package/bizar-dash/tests/{autosave.test.tsx → v7-archive/autosave.test.tsx} +0 -0
- /package/bizar-dash/tests/{backup-restore.test.tsx → v7-archive/backup-restore.test.tsx} +0 -0
- /package/bizar-dash/tests/{chat-composer.test.tsx → v7-archive/chat-composer.test.tsx} +0 -0
- /package/bizar-dash/tests/{communication-log.test.tsx → v7-archive/communication-log.test.tsx} +0 -0
- /package/bizar-dash/tests/{components → v7-archive/components}/Modal.test.tsx +0 -0
- /package/bizar-dash/tests/{components → v7-archive/components}/Spinner.test.tsx +0 -0
- /package/bizar-dash/tests/{components → v7-archive/components}/StatusBadge.test.tsx +0 -0
- /package/bizar-dash/tests/{components → v7-archive/components}/doctor-panel.test.tsx +0 -0
- /package/bizar-dash/tests/{components → v7-archive/components}/screenshot-ocr.test.tsx +0 -0
- /package/bizar-dash/tests/{components → v7-archive/components}/settings-search.test.tsx +0 -0
- /package/bizar-dash/tests/{components → v7-archive/components}/workspace-selector.test.tsx +0 -0
- /package/bizar-dash/tests/{ui → v7-archive}/controls/Button.test.tsx +0 -0
- /package/bizar-dash/tests/{ui → v7-archive}/controls/Checkbox.test.tsx +0 -0
- /package/bizar-dash/tests/{ui → v7-archive}/controls/IconButton.test.tsx +0 -0
- /package/bizar-dash/tests/{ui → v7-archive}/controls/Kbd.test.tsx +0 -0
- /package/bizar-dash/tests/{ui → v7-archive}/controls/NumberInput.test.tsx +0 -0
- /package/bizar-dash/tests/{ui → v7-archive}/controls/RadioGroup.test.tsx +0 -0
- /package/bizar-dash/tests/{ui → v7-archive}/controls/SearchInput.test.tsx +0 -0
- /package/bizar-dash/tests/{ui → v7-archive}/controls/Select.test.tsx +0 -0
- /package/bizar-dash/tests/{ui → v7-archive}/controls/Slider.test.tsx +0 -0
- /package/bizar-dash/tests/{ui → v7-archive}/controls/TextInput.test.tsx +0 -0
- /package/bizar-dash/tests/{ui → v7-archive}/controls/Textarea.test.tsx +0 -0
- /package/bizar-dash/tests/{ui → v7-archive}/controls/Toggle.test.tsx +0 -0
- /package/bizar-dash/tests/{ui → v7-archive}/data/BarChart.test.tsx +0 -0
- /package/bizar-dash/tests/{ui → v7-archive}/data/DataTable.test.tsx +0 -0
- /package/bizar-dash/tests/{ui → v7-archive}/data/EmptyState.test.tsx +0 -0
- /package/bizar-dash/tests/{ui → v7-archive}/data/ErrorState.test.tsx +0 -0
- /package/bizar-dash/tests/{ui → v7-archive}/data/KeyValueList.test.tsx +0 -0
- /package/bizar-dash/tests/{ui → v7-archive}/data/LoadingState.test.tsx +0 -0
- /package/bizar-dash/tests/{ui → v7-archive}/data/Sparkline.test.tsx +0 -0
- /package/bizar-dash/tests/{ui → v7-archive}/data/StatTile.test.tsx +0 -0
- /package/bizar-dash/tests/{dep-graph.test.tsx → v7-archive/dep-graph.test.tsx} +0 -0
- /package/bizar-dash/tests/{eval-web-ui.test.tsx → v7-archive/eval-web-ui.test.tsx} +0 -0
- /package/bizar-dash/tests/{event-log.test.tsx → v7-archive/event-log.test.tsx} +0 -0
- /package/bizar-dash/tests/{ui → v7-archive}/feedback/Badge.test.tsx +0 -0
- /package/bizar-dash/tests/{ui → v7-archive}/feedback/Dialog.test.tsx +0 -0
- /package/bizar-dash/tests/{ui → v7-archive}/feedback/ProgressBar.test.tsx +0 -0
- /package/bizar-dash/tests/{ui → v7-archive}/feedback/StatusDot.test.tsx +0 -0
- /package/bizar-dash/tests/{ui → v7-archive}/feedback/Toast.test.tsx +0 -0
- /package/bizar-dash/tests/{ui → v7-archive}/feedback/Tooltip.test.tsx +0 -0
- /package/bizar-dash/tests/{goal-input.test.tsx → v7-archive/goal-input.test.tsx} +0 -0
- /package/bizar-dash/tests/{goap-planner.test.ts → v7-archive/goap-planner.test.ts} +0 -0
- /package/bizar-dash/tests/{hooks → v7-archive/hooks}/useModal.test.tsx +0 -0
- /package/bizar-dash/tests/{hooks → v7-archive/hooks}/useToast.test.tsx +0 -0
- /package/bizar-dash/tests/{ui → v7-archive}/layout/AppShell.test.tsx +0 -0
- /package/bizar-dash/tests/{ui → v7-archive}/layout/Breadcrumbs.test.tsx +0 -0
- /package/bizar-dash/tests/{ui → v7-archive}/layout/Panel.test.tsx +0 -0
- /package/bizar-dash/tests/{ui → v7-archive}/layout/PanelHeader.test.tsx +0 -0
- /package/bizar-dash/tests/{ui → v7-archive}/layout/Sidebar.test.tsx +0 -0
- /package/bizar-dash/tests/{ui → v7-archive}/layout/Tabs.test.tsx +0 -0
- /package/bizar-dash/tests/{ui → v7-archive}/layout/Topbar.test.tsx +0 -0
- /package/bizar-dash/tests/{ui → v7-archive}/layout/ViewHeader.test.tsx +0 -0
- /package/bizar-dash/tests/{lib → v7-archive/lib}/i18n.test.ts +0 -0
- /package/bizar-dash/tests/{lib → v7-archive/lib}/search-fuzzy.test.ts +0 -0
- /package/bizar-dash/tests/{lib → v7-archive/lib}/utils.test.ts +0 -0
- /package/bizar-dash/tests/{memory-graph-view.test.tsx → v7-archive/memory-graph-view.test.tsx} +0 -0
- /package/bizar-dash/tests/{mobile-chat.test.tsx → v7-archive/mobile-chat.test.tsx} +0 -0
- /package/bizar-dash/tests/{mobile-layout.test.tsx → v7-archive/mobile-layout.test.tsx} +0 -0
- /package/bizar-dash/tests/{mobile-overview.test.tsx → v7-archive/mobile-overview.test.tsx} +0 -0
- /package/bizar-dash/tests/{mobile-settings.test.tsx → v7-archive/mobile-settings.test.tsx} +0 -0
- /package/bizar-dash/tests/{mobile-tasks.test.tsx → v7-archive/mobile-tasks.test.tsx} +0 -0
- /package/bizar-dash/tests/{ui → v7-archive}/navigation/CommandPalette.test.tsx +0 -0
- /package/bizar-dash/tests/{ui → v7-archive}/navigation/NavGroup.test.tsx +0 -0
- /package/bizar-dash/tests/{ui → v7-archive}/navigation/NavLink.test.tsx +0 -0
- /package/bizar-dash/tests/{quality-gates.test.tsx → v7-archive/quality-gates.test.tsx} +0 -0
- /package/bizar-dash/tests/{settings-layout.test.tsx → v7-archive/settings-layout.test.tsx} +0 -0
- /package/bizar-dash/tests/{settings-mode-wiring.test.tsx → v7-archive/settings-mode-wiring.test.tsx} +0 -0
- /package/bizar-dash/tests/{settings-nav.test.tsx → v7-archive/settings-nav.test.tsx} +0 -0
- /package/bizar-dash/tests/{ui → v7-archive/ui}/primitives/Box.test.tsx +0 -0
- /package/bizar-dash/tests/{ui → v7-archive/ui}/primitives/Grid.test.tsx +0 -0
- /package/bizar-dash/tests/{ui → v7-archive/ui}/primitives/Inline.test.tsx +0 -0
- /package/bizar-dash/tests/{ui → v7-archive/ui}/primitives/Separator.test.tsx +0 -0
- /package/bizar-dash/tests/{ui → v7-archive/ui}/primitives/Stack.test.tsx +0 -0
- /package/bizar-dash/tests/{views → v7-archive/views}/Agents.test.tsx +0 -0
- /package/bizar-dash/tests/{views → v7-archive/views}/Memory.test.tsx +0 -0
- /package/bizar-dash/tests/{views → v7-archive/views}/Overview.test.tsx +0 -0
- /package/bizar-dash/tests/{views → v7-archive/views}/Tasks.test.tsx +0 -0
- /package/bizar-dash/tests/{views → v7-archive/views}/sidebar.test.tsx +0 -0
- /package/bizar-dash/tests/{views → v7-archive/views}/topbar.test.tsx +0 -0
- /package/bizar-dash/tests/{voice-recorder.test.tsx → v7-archive/voice-recorder.test.tsx} +0 -0
|
@@ -0,0 +1,1110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/server/serve-info.mjs
|
|
3
|
+
*
|
|
4
|
+
* v3.5.4 (bug #3) — Out-of-process reader for the plugin's `serve.json`
|
|
5
|
+
* (see plugins/bizar/src/serve-info.ts). The plugin owns the `cline serve`
|
|
6
|
+
* child process; this module lets the dashboard server talk to the same
|
|
7
|
+
* child so it can abort sessions, list sessions, etc.
|
|
8
|
+
*
|
|
9
|
+
* Why a separate file:
|
|
10
|
+
* The plugin is TypeScript, the dashboard is plain `.mjs`. We cannot share
|
|
11
|
+
* code directly. Mirroring the read logic in a small `.mjs` is the
|
|
12
|
+
* lowest-cost bridge and keeps the plugin as the single source of truth
|
|
13
|
+
* for the on-disk contract.
|
|
14
|
+
*
|
|
15
|
+
* Cline HTTP API contract (verified against cline serve 1.17.x):
|
|
16
|
+
* - Auth: `Authorization: Basic base64("cline:<password>")`. cline
|
|
17
|
+
* serves the realm "Secure Area" with Basic auth.
|
|
18
|
+
* - `POST /api/session/{sessionId}/abort?directory={worktree}`
|
|
19
|
+
* — Aborts the session. The directory query param scopes the call to
|
|
20
|
+
* a specific worktree (mirrors how the plugin's HttpClient calls
|
|
21
|
+
* all per-session endpoints). 2xx on success; 404 if the session
|
|
22
|
+
* is unknown; 401 if auth fails.
|
|
23
|
+
* - `GET /api/session`
|
|
24
|
+
* — Lists every session in the cline database, regardless of who
|
|
25
|
+
* started it. Response shape: `{data: Array<SessionView>}` where
|
|
26
|
+
* SessionView is {id, projectID, parentID?, title, agent, model,
|
|
27
|
+
* time:{created,updated,archived}, location:{directory,...}, ...}.
|
|
28
|
+
* - `GET /api/session/{sessionId}/message?directory={worktree}`
|
|
29
|
+
* — Lists every message in a session. Response shape:
|
|
30
|
+
* `{data: Array<{info, parts}>}` where info is
|
|
31
|
+
* {id, role, time:{created,...}} and parts is
|
|
32
|
+
* `Array<{type, text}>` (text-bearing parts only contribute to
|
|
33
|
+
* the chat display; tool/agent parts are ignored by the chat
|
|
34
|
+
* layer but still in the response). Used by the chat endpoint
|
|
35
|
+
* to poll for assistant responses, and by the bg-poller to scan
|
|
36
|
+
* the final assistant message for an `html-artifact` block.
|
|
37
|
+
*
|
|
38
|
+
* Both endpoints are best-effort. Failure to call them does not crash the
|
|
39
|
+
* dashboard — we surface a structured `{ok:false, error}` result and let
|
|
40
|
+
* the UI toast.
|
|
41
|
+
*
|
|
42
|
+
* Discovery:
|
|
43
|
+
* We walk the same multi-path list as BG_DIRS (see background-store.mjs):
|
|
44
|
+
* - ~/.cache/bizar/serve.json (default stateDir)
|
|
45
|
+
* - ~/.config/cline/serve.json (fallback)
|
|
46
|
+
* - ~/.bizar/serve.json (legacy)
|
|
47
|
+
* First file that parses successfully wins.
|
|
48
|
+
*
|
|
49
|
+
* Freshness:
|
|
50
|
+
* We re-read the file on every call so a plugin restart picks up the
|
|
51
|
+
* new port/password automatically. No in-process caching; the file is
|
|
52
|
+
* tiny (< 1 KB).
|
|
53
|
+
*/
|
|
54
|
+
|
|
55
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
56
|
+
import { join } from 'node:path';
|
|
57
|
+
import { homedir } from 'node:os';
|
|
58
|
+
import { createConnection, isIP } from 'node:net';
|
|
59
|
+
import { warn as loggerWarn, error as loggerError } from './logger.mjs';
|
|
60
|
+
|
|
61
|
+
const HOME = homedir();
|
|
62
|
+
|
|
63
|
+
// Mirrors plugins/bizar/src/serve-info.ts → BG_DIRS pattern.
|
|
64
|
+
const DEFAULT_SERVE_INFO_FILES = [
|
|
65
|
+
join(HOME, '.cache', 'bizar', 'serve.json'),
|
|
66
|
+
join(HOME, '.config', 'cline', 'serve.json'),
|
|
67
|
+
join(HOME, '.bizar', 'serve.json'),
|
|
68
|
+
];
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Resolve the serve.json candidate paths at call time so test
|
|
72
|
+
* suites can override with `BIZAR_SERVE_JSON_PATH=/tmp/...json`.
|
|
73
|
+
* Order: env override (if set and exists) → default search list.
|
|
74
|
+
*
|
|
75
|
+
* @returns {string[]}
|
|
76
|
+
*/
|
|
77
|
+
function serveInfoFiles() {
|
|
78
|
+
const override = process.env.BIZAR_SERVE_JSON_PATH;
|
|
79
|
+
if (override && typeof override === 'string' && override.length > 0) {
|
|
80
|
+
return [override];
|
|
81
|
+
}
|
|
82
|
+
return DEFAULT_SERVE_INFO_FILES;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* @typedef {Object} ServeInfo
|
|
87
|
+
* @property {string} baseUrl e.g. "http://127.0.0.1:4097"
|
|
88
|
+
* @property {number} port
|
|
89
|
+
* @property {string} password CLINE_SERVER_PASSWORD (base64 secret)
|
|
90
|
+
* @property {string} worktree the plugin's cwd at start time
|
|
91
|
+
* @property {number} pid
|
|
92
|
+
* @property {number} startedAt epoch ms
|
|
93
|
+
*/
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Read the serve-info file from any of the candidate paths.
|
|
97
|
+
* Returns null when no usable file exists. Never throws.
|
|
98
|
+
*
|
|
99
|
+
* v3.11.0 — schema relaxed to derive missing fields. The plugin's
|
|
100
|
+
* `writeServeInfo` is supposed to write `{baseUrl, port, password,
|
|
101
|
+
* worktree, pid, startedAt}`, but older builds (and the version
|
|
102
|
+
* currently shipping on the user's install) wrote only
|
|
103
|
+
* `{password, pid, port}`. The strict pre-v3.11.0 schema then caused
|
|
104
|
+
* `readServeInfo()` to return `null`, which cascaded into
|
|
105
|
+
* `dispatchToBackground` marking every subtask as `dispatchPending: true`
|
|
106
|
+
* (see `task-delegator.mjs:563`). We now:
|
|
107
|
+
* - Require only `password` (string) and `port` (number)
|
|
108
|
+
* - Derive `baseUrl` from `port` (`http://127.0.0.1:<port>`)
|
|
109
|
+
* when the on-disk file omits it
|
|
110
|
+
* - Treat `worktree` and `startedAt` as optional, defaulting to `''`
|
|
111
|
+
* and `0` respectively when missing. Callers that need a real
|
|
112
|
+
* worktree (the bg-retry loop) must fill it in from their own
|
|
113
|
+
* state — never assume the value here.
|
|
114
|
+
* - Still validate that the derived `baseUrl` is loopback-safe.
|
|
115
|
+
*
|
|
116
|
+
* @returns {ServeInfo|null}
|
|
117
|
+
*/
|
|
118
|
+
export function readServeInfo() {
|
|
119
|
+
for (const file of serveInfoFiles()) {
|
|
120
|
+
if (!existsSync(file)) continue;
|
|
121
|
+
try {
|
|
122
|
+
const raw = readFileSync(file, 'utf8');
|
|
123
|
+
const parsed = JSON.parse(raw);
|
|
124
|
+
if (
|
|
125
|
+
typeof parsed?.password !== 'string' ||
|
|
126
|
+
typeof parsed?.port !== 'number'
|
|
127
|
+
) {
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
// Derive baseUrl from port when the file omits it (older plugin
|
|
131
|
+
// builds write `{password, pid, port}` only).
|
|
132
|
+
let baseUrl = typeof parsed.baseUrl === 'string' && parsed.baseUrl.length > 0
|
|
133
|
+
? parsed.baseUrl
|
|
134
|
+
: `http://127.0.0.1:${parsed.port}`;
|
|
135
|
+
if (!isSafeServeBaseUrl(baseUrl)) continue;
|
|
136
|
+
return {
|
|
137
|
+
baseUrl,
|
|
138
|
+
port: parsed.port,
|
|
139
|
+
password: parsed.password,
|
|
140
|
+
worktree: typeof parsed.worktree === 'string' ? parsed.worktree : '',
|
|
141
|
+
pid: typeof parsed.pid === 'number' ? parsed.pid : 0,
|
|
142
|
+
startedAt: typeof parsed.startedAt === 'number' ? parsed.startedAt : 0,
|
|
143
|
+
};
|
|
144
|
+
} catch {
|
|
145
|
+
// try next candidate
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function isSafeServeBaseUrl(baseUrl) {
|
|
152
|
+
try {
|
|
153
|
+
const url = new URL(baseUrl);
|
|
154
|
+
if (url.protocol !== 'http:' && url.protocol !== 'https:') return false;
|
|
155
|
+
return isLoopbackHostname(url.hostname);
|
|
156
|
+
} catch {
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function isLoopbackHostname(hostname) {
|
|
162
|
+
const host = String(hostname || '').replace(/^\[|\]$/g, '').toLowerCase();
|
|
163
|
+
if (!host) return false;
|
|
164
|
+
if (host === 'localhost' || host === '::1') return true;
|
|
165
|
+
if (host.startsWith('127.')) return true;
|
|
166
|
+
if (host === '::ffff:127.0.0.1' || host === '::ffff:7f00:1') return true;
|
|
167
|
+
const ipVersion = isIP(host);
|
|
168
|
+
if (ipVersion === 4) return host.startsWith('127.');
|
|
169
|
+
if (ipVersion === 6) return host === '::1';
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* @typedef {Object} AbortResult
|
|
175
|
+
* @property {boolean} ok
|
|
176
|
+
* @property {string} [error]
|
|
177
|
+
* @property {number} [status]
|
|
178
|
+
* @property {string} [note]
|
|
179
|
+
*/
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* POST /api/session/{sessionId}/abort?directory={worktree} on the cline
|
|
183
|
+
* serve child described by `info`. Best-effort; never throws.
|
|
184
|
+
*
|
|
185
|
+
* Idempotent: if the session is already gone (404), we treat it as success
|
|
186
|
+
* (the desired terminal state was already achieved).
|
|
187
|
+
*
|
|
188
|
+
* @param {ServeInfo} info
|
|
189
|
+
* @param {string} sessionId
|
|
190
|
+
* @param {string} [worktreeOverride] defaults to info.worktree
|
|
191
|
+
* @param {number} [timeoutMs] defaults to 8000
|
|
192
|
+
* @returns {Promise<AbortResult>}
|
|
193
|
+
*/
|
|
194
|
+
export async function abortSession(info, sessionId, worktreeOverride, timeoutMs = 8000) {
|
|
195
|
+
if (!info || !sessionId) {
|
|
196
|
+
return { ok: false, error: 'missing info or sessionId' };
|
|
197
|
+
}
|
|
198
|
+
const url = `${info.baseUrl}/api/session/${encodeURIComponent(sessionId)}/abort?directory=${encodeURIComponent(
|
|
199
|
+
worktreeOverride || info.worktree || '',
|
|
200
|
+
)}`;
|
|
201
|
+
const auth = `Basic ${Buffer.from(`cline:${info.password}`).toString('base64')}`;
|
|
202
|
+
const ac = new AbortController();
|
|
203
|
+
const timer = setTimeout(() => ac.abort(), timeoutMs);
|
|
204
|
+
try {
|
|
205
|
+
const res = await fetch(url, {
|
|
206
|
+
method: 'POST',
|
|
207
|
+
headers: {
|
|
208
|
+
Authorization: auth,
|
|
209
|
+
Accept: 'application/json',
|
|
210
|
+
},
|
|
211
|
+
signal: ac.signal,
|
|
212
|
+
});
|
|
213
|
+
if (res.ok) {
|
|
214
|
+
return { ok: true, status: res.status };
|
|
215
|
+
}
|
|
216
|
+
// 404: session already gone — treat as idempotent success.
|
|
217
|
+
if (res.status === 404) {
|
|
218
|
+
return { ok: true, status: 404, note: 'session already absent' };
|
|
219
|
+
}
|
|
220
|
+
// Drain for diagnostics
|
|
221
|
+
let detail = '';
|
|
222
|
+
try {
|
|
223
|
+
detail = (await res.text()).slice(0, 500);
|
|
224
|
+
} catch {
|
|
225
|
+
/* ignore */
|
|
226
|
+
}
|
|
227
|
+
return {
|
|
228
|
+
ok: false,
|
|
229
|
+
status: res.status,
|
|
230
|
+
error: `abort failed: ${res.status} ${res.statusText}${detail ? ` — ${detail}` : ''}`,
|
|
231
|
+
};
|
|
232
|
+
} catch (err) {
|
|
233
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
234
|
+
const isAbort = err instanceof Error && err.name === 'AbortError';
|
|
235
|
+
return {
|
|
236
|
+
ok: false,
|
|
237
|
+
error: isAbort ? `abort timed out after ${timeoutMs}ms` : `abort network error: ${msg}`,
|
|
238
|
+
};
|
|
239
|
+
} finally {
|
|
240
|
+
clearTimeout(timer);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* @typedef {Object} ClineSession
|
|
246
|
+
* @property {string} id
|
|
247
|
+
* @property {string} projectID
|
|
248
|
+
* @property {string|null} parentID
|
|
249
|
+
* @property {string} title
|
|
250
|
+
* @property {string} [agent]
|
|
251
|
+
* @property {{id:string,providerID:string,variant?:string}} [model]
|
|
252
|
+
* @property {{created:number,updated:number,archived:number|null}} time
|
|
253
|
+
* @property {{directory:string,workspaceID?:string|null}} location
|
|
254
|
+
*/
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* GET /api/session on the cline serve child. Returns the raw session
|
|
258
|
+
* list (each entry is a SessionView from cline). Returns null when
|
|
259
|
+
* no serve is reachable or auth fails. Never throws.
|
|
260
|
+
*
|
|
261
|
+
* Used by Bug #5 to merge sessions started directly from cline (CLI,
|
|
262
|
+
* MCP, etc.) into the dashboard's bg-instance list.
|
|
263
|
+
*
|
|
264
|
+
* @param {ServeInfo} info
|
|
265
|
+
* @param {number} [timeoutMs]
|
|
266
|
+
* @returns {Promise<ClineSession[]|null>}
|
|
267
|
+
*/
|
|
268
|
+
export async function listClineSessions(info, timeoutMs = 5000) {
|
|
269
|
+
if (!info) return null;
|
|
270
|
+
const url = `${info.baseUrl}/api/session`;
|
|
271
|
+
const auth = `Basic ${Buffer.from(`cline:${info.password}`).toString('base64')}`;
|
|
272
|
+
const ac = new AbortController();
|
|
273
|
+
const timer = setTimeout(() => ac.abort(), timeoutMs);
|
|
274
|
+
try {
|
|
275
|
+
const res = await fetch(url, {
|
|
276
|
+
method: 'GET',
|
|
277
|
+
headers: {
|
|
278
|
+
Authorization: auth,
|
|
279
|
+
Accept: 'application/json',
|
|
280
|
+
},
|
|
281
|
+
signal: ac.signal,
|
|
282
|
+
});
|
|
283
|
+
if (!res.ok) {
|
|
284
|
+
return null;
|
|
285
|
+
}
|
|
286
|
+
const body = await res.json().catch(() => null);
|
|
287
|
+
if (!body) return null;
|
|
288
|
+
// v2 wraps in {data: [...]}; defensive fallback to top-level array.
|
|
289
|
+
const arr = Array.isArray(body) ? body : Array.isArray(body?.data) ? body.data : null;
|
|
290
|
+
if (!arr) return null;
|
|
291
|
+
// Normalize to a flat shape so callers don't have to know about v1/v2.
|
|
292
|
+
return arr.map((s) => ({
|
|
293
|
+
id: s?.id,
|
|
294
|
+
projectID: s?.projectID ?? s?.project_id ?? null,
|
|
295
|
+
parentID: s?.parentID ?? s?.parent_id ?? null,
|
|
296
|
+
title: s?.title ?? '',
|
|
297
|
+
agent: s?.agent ?? null,
|
|
298
|
+
model:
|
|
299
|
+
s?.model && typeof s.model === 'object'
|
|
300
|
+
? {
|
|
301
|
+
id: s.model.id,
|
|
302
|
+
providerID: s.model.providerID ?? s.model.provider_id ?? '',
|
|
303
|
+
variant: s.model.variant ?? null,
|
|
304
|
+
}
|
|
305
|
+
: null,
|
|
306
|
+
time: {
|
|
307
|
+
created: s?.time?.created ?? 0,
|
|
308
|
+
updated: s?.time?.updated ?? 0,
|
|
309
|
+
archived: s?.time?.archived ?? null,
|
|
310
|
+
},
|
|
311
|
+
location: {
|
|
312
|
+
directory: s?.location?.directory ?? '',
|
|
313
|
+
workspaceID: s?.location?.workspaceID ?? s?.location?.workspace_id ?? null,
|
|
314
|
+
},
|
|
315
|
+
}));
|
|
316
|
+
} catch {
|
|
317
|
+
return null;
|
|
318
|
+
} finally {
|
|
319
|
+
clearTimeout(timer);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
export const SERVE_INFO_FILE_PATHS = DEFAULT_SERVE_INFO_FILES;
|
|
324
|
+
|
|
325
|
+
// ── v5.0.0 — bug #4 — directory resolver (shared between route modules) ──
|
|
326
|
+
//
|
|
327
|
+
// Both `routes/cline-sessions.mjs` and `routes/cline-session-detail.mjs`
|
|
328
|
+
// need the same logic: given a sessionId and the plugin's serve-info, figure
|
|
329
|
+
// out which `directory` (worktree) to pass as a `?directory=…` query param
|
|
330
|
+
// to cline's HTTP API. We previously had two copies of this resolver
|
|
331
|
+
// inline in each route; now there's one in serve-info.mjs so a fix here
|
|
332
|
+
// reaches both routes.
|
|
333
|
+
//
|
|
334
|
+
// Strategy (per issue #4 brief):
|
|
335
|
+
// 1. If serve.json has a `worktree` AND a fast probe (`GET
|
|
336
|
+
// /api/session/{id}?directory=<worktree>`) succeeds (HTTP 200), use
|
|
337
|
+
// the worktree — no need to list every cline session.
|
|
338
|
+
// 2. Otherwise, list every session via `GET /api/session` and find the
|
|
339
|
+
// one whose id matches. Use its `location.directory` (or the legacy
|
|
340
|
+
// `worktree` field, if present) as the directory.
|
|
341
|
+
// 3. If neither yields a directory, return null — callers should 503
|
|
342
|
+
// so the UI can show "directory unknown" rather than sending the
|
|
343
|
+
// request with a blank `?directory=` (cline 400s on that).
|
|
344
|
+
//
|
|
345
|
+
// `worktreeHasSession` is a small `GET /api/session/{id}?directory=...`
|
|
346
|
+
// probe used as a fast-path so we don't pay the cost of listing every
|
|
347
|
+
// session on every listMessages call. The endpoint returns 200 when the
|
|
348
|
+
// session exists in that worktree, 404 when it doesn't. We treat 2xx
|
|
349
|
+
// other than 200 as success (cline has shipped both `200` and `204`
|
|
350
|
+
// on this endpoint across versions).
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Lightweight probe — does `sessionId` exist in `worktree`?
|
|
354
|
+
*
|
|
355
|
+
* Implemented as `GET /api/session/{id}?directory={worktree}`. Returns
|
|
356
|
+
* `true` on 2xx, `false` on 404, `null` on network / auth / other
|
|
357
|
+
* errors (the caller should fall back to the slower list path and
|
|
358
|
+
* trust THAT result).
|
|
359
|
+
*
|
|
360
|
+
* Never throws.
|
|
361
|
+
*
|
|
362
|
+
* @param {ServeInfo} info
|
|
363
|
+
* @param {string} sessionId
|
|
364
|
+
* @param {string} worktree
|
|
365
|
+
* @param {number} [timeoutMs]
|
|
366
|
+
* @returns {Promise<boolean|null>}
|
|
367
|
+
*/
|
|
368
|
+
async function worktreeHasSession(info, sessionId, worktree, timeoutMs = 2_500) {
|
|
369
|
+
if (!info || !sessionId || !worktree) return null;
|
|
370
|
+
const url = `${info.baseUrl}/api/session/${encodeURIComponent(sessionId)}?directory=${encodeURIComponent(worktree)}`;
|
|
371
|
+
const ac = new AbortController();
|
|
372
|
+
const timer = setTimeout(() => ac.abort(), timeoutMs);
|
|
373
|
+
try {
|
|
374
|
+
const res = await fetch(url, {
|
|
375
|
+
method: 'GET',
|
|
376
|
+
headers: {
|
|
377
|
+
Authorization: buildAuthHeader(info),
|
|
378
|
+
Accept: 'application/json',
|
|
379
|
+
},
|
|
380
|
+
signal: ac.signal,
|
|
381
|
+
});
|
|
382
|
+
if (res.status >= 200 && res.status < 300) return true;
|
|
383
|
+
if (res.status === 404) return false;
|
|
384
|
+
// 401/403/5xx → don't trust the result, let the fallback path decide.
|
|
385
|
+
return null;
|
|
386
|
+
} catch {
|
|
387
|
+
return null;
|
|
388
|
+
} finally {
|
|
389
|
+
clearTimeout(timer);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* Resolve the cline `directory` (worktree) for a session.
|
|
395
|
+
*
|
|
396
|
+
* Per the brief:
|
|
397
|
+
* 1. If we have a worktree AND a fast probe confirms the session
|
|
398
|
+
* lives there, return it.
|
|
399
|
+
* 2. Otherwise, list every session and find the matching one; use
|
|
400
|
+
* its `location.directory` (or legacy `worktree`).
|
|
401
|
+
* 3. Return null if neither yields a directory.
|
|
402
|
+
*
|
|
403
|
+
* Signature is `(sessionId, serveInfo)` (positional, sessionId first)
|
|
404
|
+
* to match the brief. Callers that only have `serveInfo` can pass
|
|
405
|
+
* `null` for `sessionId` and the function will fall through to the
|
|
406
|
+
* list path.
|
|
407
|
+
*
|
|
408
|
+
* Never throws.
|
|
409
|
+
*
|
|
410
|
+
* @param {string|null|undefined} sessionId
|
|
411
|
+
* @param {ServeInfo|null|undefined} serveInfo
|
|
412
|
+
* @returns {Promise<string|null>}
|
|
413
|
+
*/
|
|
414
|
+
export async function resolveSessionDirectory(sessionId, serveInfo) {
|
|
415
|
+
if (!serveInfo) return null;
|
|
416
|
+
|
|
417
|
+
// Fast path: probe the recorded worktree first. If the session lives
|
|
418
|
+
// there, we save the round-trip to /api/session.
|
|
419
|
+
if (typeof serveInfo.worktree === 'string' && serveInfo.worktree.length > 0) {
|
|
420
|
+
const probe = await worktreeHasSession(serveInfo, sessionId || '', serveInfo.worktree);
|
|
421
|
+
if (probe === true) return serveInfo.worktree;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// Slower fallback: list every session and find the match.
|
|
425
|
+
try {
|
|
426
|
+
const sessions = await listClineSessions(serveInfo, 5_000);
|
|
427
|
+
if (Array.isArray(sessions)) {
|
|
428
|
+
const entry = sessionId
|
|
429
|
+
? sessions.find(
|
|
430
|
+
(s) =>
|
|
431
|
+
s && (s.id === sessionId || (typeof s.sessionId === 'string' && s.sessionId === sessionId)),
|
|
432
|
+
)
|
|
433
|
+
: null;
|
|
434
|
+
if (entry) {
|
|
435
|
+
const dir = entry?.location?.directory;
|
|
436
|
+
if (typeof dir === 'string' && dir.length > 0) return dir;
|
|
437
|
+
// Defensive: some cline builds store the worktree on the
|
|
438
|
+
// session at the top level instead of under `location`.
|
|
439
|
+
const legacy = entry?.worktree;
|
|
440
|
+
if (typeof legacy === 'string' && legacy.length > 0) return legacy;
|
|
441
|
+
}
|
|
442
|
+
// No matching session, but we have a worktree from serve.json —
|
|
443
|
+
// last-chance fallback. This mirrors the pre-v5.0.0 inline
|
|
444
|
+
// resolver behaviour so an unmatched session still routes to
|
|
445
|
+
// the plugin's recorded cwd rather than 503'ing.
|
|
446
|
+
if (!entry && typeof serveInfo.worktree === 'string' && serveInfo.worktree.length > 0) {
|
|
447
|
+
return serveInfo.worktree;
|
|
448
|
+
}
|
|
449
|
+
} else if (typeof serveInfo.worktree === 'string' && serveInfo.worktree.length > 0) {
|
|
450
|
+
// listClineSessions returned null (serve offline / auth fail).
|
|
451
|
+
// Fall back to the worktree so we at least try the same
|
|
452
|
+
// directory the plugin recorded — the upstream 404/502 will
|
|
453
|
+
// surface a clearer error than a 503 directory_unknown.
|
|
454
|
+
return serveInfo.worktree;
|
|
455
|
+
}
|
|
456
|
+
} catch (err) {
|
|
457
|
+
loggerWarn('resolveSessionDirectory: listClineSessions failed', {
|
|
458
|
+
sessionId: sessionId || null,
|
|
459
|
+
err: err instanceof Error ? err.message : String(err),
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
return null;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
// ── v3.5.4 (bug: dispatch stuck) — spawn helpers ─────────────────────────
|
|
467
|
+
//
|
|
468
|
+
// The dashboard's task delegator used to shell out to
|
|
469
|
+
// `node plugins/bizar/dist/cli.js bg enqueue`. That CLI does not exist
|
|
470
|
+
// (the plugin is a Bun-native TS project with no compiled dist), so every
|
|
471
|
+
// spawn silently failed and subtasks got stuck at `doing 5% Dispatched`
|
|
472
|
+
// forever.
|
|
473
|
+
//
|
|
474
|
+
// The fix is to talk to the cline serve child the plugin owns directly
|
|
475
|
+
// — the plugin already spawns `cline serve` on init and publishes the
|
|
476
|
+
// port + password via serve-info. The endpoints below mirror what the
|
|
477
|
+
// plugin's own `bizar_spawn_background` MCP tool does in-process
|
|
478
|
+
// (plugins/bizar/src/http-client.ts → `createSession` + `sendPrompt`).
|
|
479
|
+
//
|
|
480
|
+
// All helpers are best-effort. A failure to reach the serve child
|
|
481
|
+
// returns a structured `{ ok: false, error, status? }` so callers can log
|
|
482
|
+
// the cause instead of swallowing it.
|
|
483
|
+
|
|
484
|
+
const DEFAULT_TIMEOUT_MS = 8_000;
|
|
485
|
+
|
|
486
|
+
/**
|
|
487
|
+
* Build the Authorization header for the cline serve child. The wire
|
|
488
|
+
* format is `Basic base64("cline:<password>")` (matches what the
|
|
489
|
+
* plugin's own HttpClient uses; see plugins/bizar/src/http-client.ts).
|
|
490
|
+
*
|
|
491
|
+
* v4.2.4 — exported so the SSE proxy in `routes/cline-session-detail.mjs`
|
|
492
|
+
* can authenticate upstream fetches without duplicating the formula.
|
|
493
|
+
*/
|
|
494
|
+
export function buildAuthHeader(info) {
|
|
495
|
+
if (!info || typeof info.password !== 'string') return '';
|
|
496
|
+
const creds = `cline:${info.password}`;
|
|
497
|
+
return `Basic ${Buffer.from(creds).toString('base64')}`;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* `POST /api/session?directory=...` — create a new background session.
|
|
502
|
+
*
|
|
503
|
+
* v2 wire format (per plugins/bizar/src/http-client.ts): request body is
|
|
504
|
+
* `{ title, agent, parentID?, model? }`; response is `{ data: { id, ... } }`
|
|
505
|
+
* or the session at top level. We unwrap defensively.
|
|
506
|
+
*
|
|
507
|
+
* @param {ServeInfo} info
|
|
508
|
+
* @param {{ title: string, agent: string, parentID?: string }} opts
|
|
509
|
+
* @param {string} [directory] defaults to info.worktree
|
|
510
|
+
* @param {number} [timeoutMs]
|
|
511
|
+
* @returns {Promise<{ok:true,sessionId:string}|{ok:false,error:string,status?:number}>}
|
|
512
|
+
*/
|
|
513
|
+
export async function createClineSession(info, opts, directory, timeoutMs = DEFAULT_TIMEOUT_MS) {
|
|
514
|
+
if (!info) return { ok: false, error: 'serve-info not available — plugin is not running' };
|
|
515
|
+
if (!opts || typeof opts.agent !== 'string' || opts.agent.length === 0) {
|
|
516
|
+
return { ok: false, error: 'agent is required' };
|
|
517
|
+
}
|
|
518
|
+
const title = (opts.title || `${opts.agent}: bg-session`).toString().slice(0, 200);
|
|
519
|
+
const dir = directory || info.worktree || '';
|
|
520
|
+
const url = `${info.baseUrl}/api/session?directory=${encodeURIComponent(dir)}`;
|
|
521
|
+
const ac = new AbortController();
|
|
522
|
+
const timer = setTimeout(() => ac.abort(), timeoutMs);
|
|
523
|
+
try {
|
|
524
|
+
const body = { title, agent: opts.agent };
|
|
525
|
+
if (opts.parentID) body.parentID = opts.parentID;
|
|
526
|
+
const res = await fetch(url, {
|
|
527
|
+
method: 'POST',
|
|
528
|
+
headers: {
|
|
529
|
+
Authorization: buildAuthHeader(info),
|
|
530
|
+
'Content-Type': 'application/json',
|
|
531
|
+
Accept: 'application/json',
|
|
532
|
+
},
|
|
533
|
+
body: JSON.stringify(body),
|
|
534
|
+
signal: ac.signal,
|
|
535
|
+
});
|
|
536
|
+
if (!res.ok) {
|
|
537
|
+
let detail = '';
|
|
538
|
+
try { detail = (await res.text()).slice(0, 500); } catch { /* ignore */ }
|
|
539
|
+
return {
|
|
540
|
+
ok: false,
|
|
541
|
+
status: res.status,
|
|
542
|
+
error: `POST /api/session failed: ${res.status} ${res.statusText}${detail ? ` — ${detail}` : ''}`,
|
|
543
|
+
};
|
|
544
|
+
}
|
|
545
|
+
const parsed = await res.json().catch(() => null);
|
|
546
|
+
const sessionId =
|
|
547
|
+
(parsed && typeof parsed === 'object' && (parsed.data?.id || parsed.id)) ||
|
|
548
|
+
null;
|
|
549
|
+
if (!sessionId) {
|
|
550
|
+
return { ok: false, status: res.status, error: 'POST /api/session: response missing id' };
|
|
551
|
+
}
|
|
552
|
+
return { ok: true, sessionId: String(sessionId) };
|
|
553
|
+
} catch (err) {
|
|
554
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
555
|
+
const isAbort = err instanceof Error && err.name === 'AbortError';
|
|
556
|
+
return {
|
|
557
|
+
ok: false,
|
|
558
|
+
error: isAbort ? `createSession timed out after ${timeoutMs}ms` : `createSession network error: ${msg}`,
|
|
559
|
+
};
|
|
560
|
+
} finally {
|
|
561
|
+
clearTimeout(timer);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
/**
|
|
566
|
+
* `POST /api/session/{id}/prompt?directory=...` — fire the prompt.
|
|
567
|
+
*
|
|
568
|
+
* v2 wire format (per plugins/bizar/src/http-client.ts): body is
|
|
569
|
+
* `{ id: <messageID>, prompt: { text }, agent, model? }`. The `id` is a
|
|
570
|
+
* client-generated message ID; the dashboard already has its own task ID
|
|
571
|
+
* scheme, so we just synthesize a unique one.
|
|
572
|
+
*
|
|
573
|
+
* @param {ServeInfo} info
|
|
574
|
+
* @param {{ sessionId: string, agent: string, text: string, messageID?: string }} opts
|
|
575
|
+
* @param {string} [directory]
|
|
576
|
+
* @param {number} [timeoutMs]
|
|
577
|
+
* @returns {Promise<{ok:true,messageId:string}|{ok:false,error:string,status?:number}>}
|
|
578
|
+
*/
|
|
579
|
+
export async function sendClinePrompt(info, opts, directory, timeoutMs = DEFAULT_TIMEOUT_MS) {
|
|
580
|
+
if (!info) return { ok: false, error: 'serve-info not available — plugin is not running' };
|
|
581
|
+
if (!opts || !opts.sessionId || !opts.agent || !opts.text) {
|
|
582
|
+
return { ok: false, error: 'sessionId, agent, and text are required' };
|
|
583
|
+
}
|
|
584
|
+
const dir = directory || info.worktree || '';
|
|
585
|
+
const messageID = opts.messageID || `msg_${Date.now().toString(36)}${Math.random().toString(36).slice(2, 8)}`;
|
|
586
|
+
const url = `${info.baseUrl}/api/session/${encodeURIComponent(opts.sessionId)}/prompt?directory=${encodeURIComponent(dir)}`;
|
|
587
|
+
const ac = new AbortController();
|
|
588
|
+
const timer = setTimeout(() => ac.abort(), timeoutMs);
|
|
589
|
+
try {
|
|
590
|
+
const body = {
|
|
591
|
+
id: messageID,
|
|
592
|
+
prompt: { text: String(opts.text).slice(0, 200_000) },
|
|
593
|
+
agent: opts.agent,
|
|
594
|
+
};
|
|
595
|
+
const res = await fetch(url, {
|
|
596
|
+
method: 'POST',
|
|
597
|
+
headers: {
|
|
598
|
+
Authorization: buildAuthHeader(info),
|
|
599
|
+
'Content-Type': 'application/json',
|
|
600
|
+
Accept: 'application/json',
|
|
601
|
+
},
|
|
602
|
+
body: JSON.stringify(body),
|
|
603
|
+
signal: ac.signal,
|
|
604
|
+
});
|
|
605
|
+
if (!res.ok) {
|
|
606
|
+
let detail = '';
|
|
607
|
+
try { detail = (await res.text()).slice(0, 500); } catch { /* ignore */ }
|
|
608
|
+
return {
|
|
609
|
+
ok: false,
|
|
610
|
+
status: res.status,
|
|
611
|
+
error: `POST /api/session/${opts.sessionId}/prompt failed: ${res.status} ${res.statusText}${detail ? ` — ${detail}` : ''}`,
|
|
612
|
+
};
|
|
613
|
+
}
|
|
614
|
+
return { ok: true, messageId: messageID };
|
|
615
|
+
} catch (err) {
|
|
616
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
617
|
+
const isAbort = err instanceof Error && err.name === 'AbortError';
|
|
618
|
+
let cause = 'unknown';
|
|
619
|
+
if (isAbort) cause = 'timeout';
|
|
620
|
+
else if (err && typeof err === 'object') {
|
|
621
|
+
const code = /** @type {any} */ (err).code;
|
|
622
|
+
if (typeof code === 'string' && code.length > 0) {
|
|
623
|
+
cause = code.startsWith('ECONN') || code.startsWith('UND_ERR') || code === 'ENOTFOUND'
|
|
624
|
+
? 'network'
|
|
625
|
+
: code;
|
|
626
|
+
} else {
|
|
627
|
+
cause = 'network';
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
return {
|
|
631
|
+
ok: false,
|
|
632
|
+
cause,
|
|
633
|
+
error: isAbort ? `sendPrompt timed out after ${timeoutMs}ms` : `sendPrompt network error: ${msg}`,
|
|
634
|
+
};
|
|
635
|
+
} finally {
|
|
636
|
+
clearTimeout(timer);
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
// ── v3.5.5 — chat + artifact integration ──────────────────────────────
|
|
641
|
+
//
|
|
642
|
+
// The chat endpoint (POST /api/chat) and the bg-poller both need to
|
|
643
|
+
// read the cline session's message list so they can:
|
|
644
|
+
// 1. Capture the assistant's reply to a user prompt (chat polling).
|
|
645
|
+
// 2. Scan the final assistant message for an `html-artifact` block
|
|
646
|
+
// that the agent emitted to declare a tangible artifact.
|
|
647
|
+
//
|
|
648
|
+
// `listClineMessages` is a thin fetch wrapper over
|
|
649
|
+
// `GET /api/session/{id}/message?directory=...`. The response shape
|
|
650
|
+
// (per the plugin's own http-client.ts → listMessages()) is either a
|
|
651
|
+
// raw `Array<{ info, parts }>` or `{ data: Array<{ info, parts }> }`.
|
|
652
|
+
// We accept both.
|
|
653
|
+
//
|
|
654
|
+
// `extractContentFromClineMessage` flattens the `parts[]` array
|
|
655
|
+
// into a single string for chat persistence and artifact detection.
|
|
656
|
+
|
|
657
|
+
/**
|
|
658
|
+
* GET /api/session/{id}/message — list the messages of a session.
|
|
659
|
+
*
|
|
660
|
+
* v2 wire format (per plugins/bizar/src/http-client.ts): response is
|
|
661
|
+
* `{ data: Array<{ info, parts }> }` or a bare array. We accept both.
|
|
662
|
+
*
|
|
663
|
+
* @param {ServeInfo} info
|
|
664
|
+
* @param {string} sessionId
|
|
665
|
+
* @param {string} [directory]
|
|
666
|
+
* @param {number} [timeoutMs]
|
|
667
|
+
* @returns {Promise<{ok:true,messages:Array}|{ok:false,error:string,status?:number}>}
|
|
668
|
+
*/
|
|
669
|
+
export async function listClineMessages(info, sessionId, directory, timeoutMs = 8_000) {
|
|
670
|
+
if (!info) return { ok: false, error: 'serve-info not available — plugin is not running' };
|
|
671
|
+
if (!sessionId) return { ok: false, error: 'sessionId is required' };
|
|
672
|
+
const dir = directory || info.worktree || '';
|
|
673
|
+
const url = `${info.baseUrl}/api/session/${encodeURIComponent(sessionId)}/message?directory=${encodeURIComponent(dir)}`;
|
|
674
|
+
const ac = new AbortController();
|
|
675
|
+
const timer = setTimeout(() => ac.abort(), timeoutMs);
|
|
676
|
+
try {
|
|
677
|
+
const res = await fetch(url, {
|
|
678
|
+
method: 'GET',
|
|
679
|
+
headers: {
|
|
680
|
+
Authorization: buildAuthHeader(info),
|
|
681
|
+
Accept: 'application/json',
|
|
682
|
+
},
|
|
683
|
+
signal: ac.signal,
|
|
684
|
+
});
|
|
685
|
+
if (!res.ok) {
|
|
686
|
+
let detail = '';
|
|
687
|
+
try { detail = (await res.text()).slice(0, 500); } catch { /* ignore */ }
|
|
688
|
+
return {
|
|
689
|
+
ok: false,
|
|
690
|
+
status: res.status,
|
|
691
|
+
error: `GET /api/session/.../message failed: ${res.status} ${res.statusText}${detail ? ` — ${detail}` : ''}`,
|
|
692
|
+
};
|
|
693
|
+
}
|
|
694
|
+
const body = await res.json().catch(() => null);
|
|
695
|
+
if (!body) return { ok: true, messages: [] };
|
|
696
|
+
const messages = Array.isArray(body) ? body : Array.isArray(body?.data) ? body.data : [];
|
|
697
|
+
return { ok: true, messages };
|
|
698
|
+
} catch (err) {
|
|
699
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
700
|
+
const isAbort = err instanceof Error && err.name === 'AbortError';
|
|
701
|
+
// v5.0.0 — bug #4: surface a structured `cause` to the route so it
|
|
702
|
+
// can render a useful suggestion without substring-sniffing the
|
|
703
|
+
// error message. Prefers the underlying network error code
|
|
704
|
+
// (ECONNREFUSED, UND_ERR_SOCKET, …) when present.
|
|
705
|
+
let cause = 'unknown';
|
|
706
|
+
if (isAbort) cause = 'timeout';
|
|
707
|
+
else if (err && typeof err === 'object') {
|
|
708
|
+
const code = /** @type {any} */ (err).code;
|
|
709
|
+
if (typeof code === 'string' && code.length > 0) {
|
|
710
|
+
cause = code.startsWith('ECONN') || code.startsWith('UND_ERR') || code === 'ENOTFOUND'
|
|
711
|
+
? 'network'
|
|
712
|
+
: code;
|
|
713
|
+
} else {
|
|
714
|
+
cause = 'network';
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
return {
|
|
718
|
+
ok: false,
|
|
719
|
+
cause,
|
|
720
|
+
error: isAbort ? `listMessages timed out after ${timeoutMs}ms` : `listMessages network error: ${msg}`,
|
|
721
|
+
};
|
|
722
|
+
} finally {
|
|
723
|
+
clearTimeout(timer);
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
/**
|
|
728
|
+
* Flatten an cline message's `parts[]` into a single string.
|
|
729
|
+
*
|
|
730
|
+
* Cline v2 messages look like:
|
|
731
|
+
* { info: { id, role, time }, parts: [{type, text}, {type, text}, ...] }
|
|
732
|
+
*
|
|
733
|
+
* We concatenate every `text` part in order, joined by `\n\n`. Non-text
|
|
734
|
+
* parts (tool calls, etc.) are skipped — they don't contribute to a
|
|
735
|
+
* human-readable chat or artifact scan.
|
|
736
|
+
*
|
|
737
|
+
* @param {object} msg one entry from `listClineMessages().messages`
|
|
738
|
+
* @returns {string}
|
|
739
|
+
*/
|
|
740
|
+
export function extractContentFromClineMessage(msg) {
|
|
741
|
+
if (!msg) return '';
|
|
742
|
+
// Some cline v1 builds put text directly on the message itself.
|
|
743
|
+
if (typeof msg.text === 'string') return finalizeText(msg.text);
|
|
744
|
+
if (typeof msg.content === 'string') return finalizeText(msg.content);
|
|
745
|
+
const parts = Array.isArray(msg.parts) ? msg.parts : [];
|
|
746
|
+
const textParts = parts
|
|
747
|
+
.filter((p) => p && (p.type === 'text' || typeof p.text === 'string'))
|
|
748
|
+
.map((p) => (typeof p.text === 'string' ? p.text : ''))
|
|
749
|
+
.filter(Boolean);
|
|
750
|
+
return finalizeText(textParts.join('\n\n'));
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
/**
|
|
754
|
+
* Strip `<thinking>...</thinking>` blocks from model output.
|
|
755
|
+
*
|
|
756
|
+
* Some cline builds (and the M3 model specifically) emit inline
|
|
757
|
+
* `<thinking>` reasoning tags directly in the assistant text content.
|
|
758
|
+
* React-markdown renders those as visible escaped HTML, so the chat UI
|
|
759
|
+
* ends up showing the raw tag. The reasoning itself is also captured
|
|
760
|
+
* separately as `reasoning_details` parts — we are not losing data by
|
|
761
|
+
* hiding the inline tag from the rendered text.
|
|
762
|
+
*
|
|
763
|
+
* Handles:
|
|
764
|
+
* - `<thinking>...</thinking>` blocks (case-insensitive, multiline)
|
|
765
|
+
* - `<thinking ...attrs>` and `<thinking/>` self-closing variants
|
|
766
|
+
* - Stray closing tags like `</thinking>` with no matching opener
|
|
767
|
+
* - Multiple blocks in the same string
|
|
768
|
+
* - Empty input → empty output
|
|
769
|
+
*
|
|
770
|
+
* After stripping, collapses runs of 3+ newlines to 2 so we don't
|
|
771
|
+
* leave huge blank gaps in the rendered output.
|
|
772
|
+
*/
|
|
773
|
+
export function stripThinkingTags(text) {
|
|
774
|
+
if (typeof text !== 'string') return '';
|
|
775
|
+
const cleaned = text
|
|
776
|
+
.replace(/<thinking\b[^>]*>[\s\S]*?<\/thinking>/gi, '')
|
|
777
|
+
.replace(/<thinking\b[^>]*\/?>/gi, '')
|
|
778
|
+
.replace(/<\/thinking>/gi, '');
|
|
779
|
+
return cleaned.replace(/\n{3,}/g, '\n\n').trim();
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
function finalizeText(text) {
|
|
783
|
+
return stripThinkingTags(text);
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
/**
|
|
787
|
+
* Normalize an cline message into the dashboard's chat shape:
|
|
788
|
+
* { id, role, content, ts, agent? }
|
|
789
|
+
*
|
|
790
|
+
* Used by GET /api/tasks/:id/chat to surface a bg instance's cline
|
|
791
|
+
* session inside the chat UI.
|
|
792
|
+
*
|
|
793
|
+
* @param {object} msg
|
|
794
|
+
* @returns {{id:string,role:string,content:string,ts:number}}
|
|
795
|
+
*/
|
|
796
|
+
export function normalizeClineMessage(msg) {
|
|
797
|
+
if (!msg) return { id: '', role: 'assistant', content: '', ts: Date.now() };
|
|
798
|
+
const id = msg?.info?.id || msg?.id || '';
|
|
799
|
+
const role = msg?.info?.role || msg?.role || 'assistant';
|
|
800
|
+
const ts = msg?.info?.time?.created
|
|
801
|
+
|| (typeof msg?.info?.time === 'object' ? msg.info.time.created : null)
|
|
802
|
+
|| (typeof msg?.time?.created === 'number' ? msg.time.created : null)
|
|
803
|
+
|| Date.now();
|
|
804
|
+
return {
|
|
805
|
+
id: String(id),
|
|
806
|
+
role: String(role),
|
|
807
|
+
content: extractContentFromClineMessage(msg),
|
|
808
|
+
ts: typeof ts === 'number' ? ts : Date.now(),
|
|
809
|
+
};
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
/**
|
|
813
|
+
* `DELETE /api/session/{id}?directory=...` — delete a session on the
|
|
814
|
+
* cline serve child. v4.2.4 dashboard feature parity: the rail
|
|
815
|
+
* menu offers delete and the chat info panel can prune finished
|
|
816
|
+
* sessions from inside the dashboard.
|
|
817
|
+
*
|
|
818
|
+
* Idempotent: a 404 (already gone) is treated as a successful delete.
|
|
819
|
+
*
|
|
820
|
+
* @param {ServeInfo} info
|
|
821
|
+
* @param {string} sessionId
|
|
822
|
+
* @param {string} [directory]
|
|
823
|
+
* @param {number} [timeoutMs]
|
|
824
|
+
* @returns {Promise<{ok:true,status:number}|{ok:false,error:string,status?:number}>}
|
|
825
|
+
*/
|
|
826
|
+
export async function deleteClineSession(info, sessionId, directory, timeoutMs = DEFAULT_TIMEOUT_MS) {
|
|
827
|
+
if (!info) return { ok: false, error: 'serve-info not available — plugin is not running' };
|
|
828
|
+
if (!sessionId) return { ok: false, error: 'sessionId is required' };
|
|
829
|
+
const dir = directory || info.worktree || '';
|
|
830
|
+
const url = `${info.baseUrl}/api/session/${encodeURIComponent(sessionId)}?directory=${encodeURIComponent(dir)}`;
|
|
831
|
+
const ac = new AbortController();
|
|
832
|
+
const timer = setTimeout(() => ac.abort(), timeoutMs);
|
|
833
|
+
try {
|
|
834
|
+
const res = await fetch(url, {
|
|
835
|
+
method: 'DELETE',
|
|
836
|
+
headers: {
|
|
837
|
+
Authorization: buildAuthHeader(info),
|
|
838
|
+
Accept: 'application/json',
|
|
839
|
+
},
|
|
840
|
+
signal: ac.signal,
|
|
841
|
+
});
|
|
842
|
+
if (res.ok || res.status === 404) {
|
|
843
|
+
return { ok: true, status: res.status };
|
|
844
|
+
}
|
|
845
|
+
let detail = '';
|
|
846
|
+
try { detail = (await res.text()).slice(0, 500); } catch { /* ignore */ }
|
|
847
|
+
return {
|
|
848
|
+
ok: false,
|
|
849
|
+
status: res.status,
|
|
850
|
+
error: `DELETE /api/session/${sessionId} failed: ${res.status} ${res.statusText}${detail ? ` — ${detail}` : ''}`,
|
|
851
|
+
};
|
|
852
|
+
} catch (err) {
|
|
853
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
854
|
+
const isAbort = err instanceof Error && err.name === 'AbortError';
|
|
855
|
+
return {
|
|
856
|
+
ok: false,
|
|
857
|
+
error: isAbort ? `deleteSession timed out after ${timeoutMs}ms` : `deleteSession network error: ${msg}`,
|
|
858
|
+
};
|
|
859
|
+
} finally {
|
|
860
|
+
clearTimeout(timer);
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
/**
|
|
865
|
+
* `PATCH /api/session/{id}?directory=...` — update session fields
|
|
866
|
+
* (currently just `title`) on the cline serve child. Used by the
|
|
867
|
+
* rail row-menu "Rename" affordance.
|
|
868
|
+
*
|
|
869
|
+
* @param {ServeInfo} info
|
|
870
|
+
* @param {string} sessionId
|
|
871
|
+
* @param {{ title?: string }} patch
|
|
872
|
+
* @param {string} [directory]
|
|
873
|
+
* @param {number} [timeoutMs]
|
|
874
|
+
* @returns {Promise<{ok:true,session:object}|{ok:false,error:string,status?:number}>}
|
|
875
|
+
*/
|
|
876
|
+
export async function updateClineSession(info, sessionId, patch, directory, timeoutMs = DEFAULT_TIMEOUT_MS) {
|
|
877
|
+
if (!info) return { ok: false, error: 'serve-info not available — plugin is not running' };
|
|
878
|
+
if (!sessionId) return { ok: false, error: 'sessionId is required' };
|
|
879
|
+
if (!patch || typeof patch !== 'object') return { ok: false, error: 'patch is required' };
|
|
880
|
+
const dir = directory || info.worktree || '';
|
|
881
|
+
const url = `${info.baseUrl}/api/session/${encodeURIComponent(sessionId)}?directory=${encodeURIComponent(dir)}`;
|
|
882
|
+
const ac = new AbortController();
|
|
883
|
+
const timer = setTimeout(() => ac.abort(), timeoutMs);
|
|
884
|
+
try {
|
|
885
|
+
const body = {};
|
|
886
|
+
if (typeof patch.title === 'string') {
|
|
887
|
+
const t = patch.title.trim();
|
|
888
|
+
if (!t) return { ok: false, error: 'title cannot be empty' };
|
|
889
|
+
if (t.length > 200) return { ok: false, error: 'title too long (> 200 chars)' };
|
|
890
|
+
body.title = t;
|
|
891
|
+
} else {
|
|
892
|
+
return { ok: false, error: 'no supported fields in patch (only `title` is wired)' };
|
|
893
|
+
}
|
|
894
|
+
const res = await fetch(url, {
|
|
895
|
+
method: 'PATCH',
|
|
896
|
+
headers: {
|
|
897
|
+
Authorization: buildAuthHeader(info),
|
|
898
|
+
'Content-Type': 'application/json',
|
|
899
|
+
Accept: 'application/json',
|
|
900
|
+
},
|
|
901
|
+
body: JSON.stringify(body),
|
|
902
|
+
signal: ac.signal,
|
|
903
|
+
});
|
|
904
|
+
if (!res.ok) {
|
|
905
|
+
let detail = '';
|
|
906
|
+
try { detail = (await res.text()).slice(0, 500); } catch { /* ignore */ }
|
|
907
|
+
return {
|
|
908
|
+
ok: false,
|
|
909
|
+
status: res.status,
|
|
910
|
+
error: `PATCH /api/session/${sessionId} failed: ${res.status} ${res.statusText}${detail ? ` — ${detail}` : ''}`,
|
|
911
|
+
};
|
|
912
|
+
}
|
|
913
|
+
let session = null;
|
|
914
|
+
try { session = await res.json(); } catch { /* non-JSON body is fine — we still got 2xx */ }
|
|
915
|
+
return { ok: true, session };
|
|
916
|
+
} catch (err) {
|
|
917
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
918
|
+
const isAbort = err instanceof Error && err.name === 'AbortError';
|
|
919
|
+
return {
|
|
920
|
+
ok: false,
|
|
921
|
+
error: isAbort ? `updateSession timed out after ${timeoutMs}ms` : `updateSession network error: ${msg}`,
|
|
922
|
+
};
|
|
923
|
+
} finally {
|
|
924
|
+
clearTimeout(timer);
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
/**
|
|
929
|
+
* GET /health — used by the dispatcher startup check to verify the
|
|
930
|
+
* serve child is actually reachable before we try to enqueue work.
|
|
931
|
+
*
|
|
932
|
+
* v3.11.0 — Replaced the HTTP `GET /health` probe with a TCP-connect
|
|
933
|
+
* port-open check via `net.createConnection`. Rationale:
|
|
934
|
+
* - The pre-v3.11.0 implementation sent `GET /health` with the
|
|
935
|
+
* Basic-auth header from `serve.json`. If the cline serve
|
|
936
|
+
* instance rejected the auth (e.g. a stale password file, a
|
|
937
|
+
* plugin version mismatch, or a 401 from a different auth realm),
|
|
938
|
+
* the probe returned `false` even when the cline process was
|
|
939
|
+
* perfectly healthy and answering other requests. That cascaded
|
|
940
|
+
* into every background dispatch short-circuiting on the
|
|
941
|
+
* `if (serveInfo && serveReachable)` guard at
|
|
942
|
+
* `task-delegator.mjs:563` and being marked `dispatchPending: true`.
|
|
943
|
+
* - TCP-connect is the standard "is this port alive" check. It does
|
|
944
|
+
* not depend on HTTP auth, the cline version's endpoint shape,
|
|
945
|
+
* or the path being correct. If the cline process is bound to
|
|
946
|
+
* the port, we can talk to it (auth on the actual endpoints will
|
|
947
|
+
* still be validated when we issue those calls).
|
|
948
|
+
* - 1.5s default timeout — long enough to survive a slow CI host,
|
|
949
|
+
* short enough that the dispatch path doesn't stall the user
|
|
950
|
+
* when the plugin is genuinely down.
|
|
951
|
+
*
|
|
952
|
+
* @param {ServeInfo} info
|
|
953
|
+
* @param {number} [timeoutMs]
|
|
954
|
+
* @returns {Promise<boolean>}
|
|
955
|
+
*/
|
|
956
|
+
export function pingClineServe(info, timeoutMs = 1_500) {
|
|
957
|
+
return new Promise((resolve) => {
|
|
958
|
+
if (!info || typeof info.port !== 'number') {
|
|
959
|
+
resolve(false);
|
|
960
|
+
return;
|
|
961
|
+
}
|
|
962
|
+
// We connect to 127.0.0.1 explicitly — the TCP probe must not
|
|
963
|
+
// accidentally hit a remote host if the baseUrl were ever wrong.
|
|
964
|
+
const host = '127.0.0.1';
|
|
965
|
+
const port = info.port;
|
|
966
|
+
let settled = false;
|
|
967
|
+
const finish = (ok) => {
|
|
968
|
+
if (settled) return;
|
|
969
|
+
settled = true;
|
|
970
|
+
try { socket.destroy(); } catch { /* ignore */ }
|
|
971
|
+
resolve(ok);
|
|
972
|
+
};
|
|
973
|
+
const socket = createConnection({ host, port });
|
|
974
|
+
const timer = setTimeout(() => finish(false), Math.max(50, timeoutMs));
|
|
975
|
+
socket.once('connect', () => {
|
|
976
|
+
clearTimeout(timer);
|
|
977
|
+
finish(true);
|
|
978
|
+
});
|
|
979
|
+
socket.once('error', () => {
|
|
980
|
+
clearTimeout(timer);
|
|
981
|
+
finish(false);
|
|
982
|
+
});
|
|
983
|
+
// Surface any unexpected socket-level error so it doesn't crash
|
|
984
|
+
// the process. `error` is already handled above, but `close`
|
|
985
|
+
// can fire after `connect`/`error` without indicating failure.
|
|
986
|
+
socket.once('close', () => {
|
|
987
|
+
clearTimeout(timer);
|
|
988
|
+
finish(settled ? false : false);
|
|
989
|
+
});
|
|
990
|
+
});
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
// ── v4.2.4 — SSE event unwrap (port from plugins/bizar/src/event-stream.ts) ──
|
|
994
|
+
//
|
|
995
|
+
// The dashboard's chat UI subscribes to cline's `/event?directory=...`
|
|
996
|
+
// SSE stream to receive live updates for a chosen session. The wire
|
|
997
|
+
// format has changed across cline versions; this helper normalizes
|
|
998
|
+
// both shapes into a single `{type, sessionID?, messageID?, part?, data}`
|
|
999
|
+
// envelope that the SSE proxy can filter on `sessionID` and forward.
|
|
1000
|
+
//
|
|
1001
|
+
// Wire format 1 (direct, older cline):
|
|
1002
|
+
// event: session.created
|
|
1003
|
+
// data: {"type":"session.created","properties":{"sessionID":"abc","title":"…"}}
|
|
1004
|
+
//
|
|
1005
|
+
// Wire format 2 (sync envelope, newer cline):
|
|
1006
|
+
// event: sync
|
|
1007
|
+
// data: {"type":"sync","syncEvent":{"type":"session.created.1","data":{"sessionID":"abc"}}}
|
|
1008
|
+
//
|
|
1009
|
+
// Sync event `type` carries a `.<n>` version suffix (e.g. `session.created.1`).
|
|
1010
|
+
// We strip it so downstream code can match on `session.created`.
|
|
1011
|
+
// Field names inside the payload have also varied across builds:
|
|
1012
|
+
// - `sessionID` vs `sessionId` vs `session_id` (and nested under `properties`)
|
|
1013
|
+
// - `messageID` vs `messageId` vs `message_id`
|
|
1014
|
+
// We accept any of them defensively.
|
|
1015
|
+
//
|
|
1016
|
+
// Reference: plugins/bizar/src/event-stream.ts:340-399 (the TS plugin's
|
|
1017
|
+
// `dispatchEvent` method). We re-implement the same logic in plain JS
|
|
1018
|
+
// here so the dashboard server can use it without importing TS code.
|
|
1019
|
+
|
|
1020
|
+
/**
|
|
1021
|
+
* Unwrap and normalize a raw cline SSE event payload.
|
|
1022
|
+
*
|
|
1023
|
+
* v0.4.3 wire formats accepted (see plugins/bizar/src/event-stream.ts:365-400):
|
|
1024
|
+
* 1. Direct: `{type, properties: {sessionID, ...}}` — newer cline uses
|
|
1025
|
+
* `data` instead of `properties`. We accept either field name.
|
|
1026
|
+
* 2. Sync envelope: `{type: "sync", syncEvent: {type: "x.y.1", data: {...}}}`.
|
|
1027
|
+
* Unwrap to inner data; strip the `.1` version suffix from the type.
|
|
1028
|
+
*
|
|
1029
|
+
* Returns `null` if the event isn't a recognizable cline event shape
|
|
1030
|
+
* (e.g. non-object, missing type).
|
|
1031
|
+
*
|
|
1032
|
+
* @param {string|null} eventName the SSE `event:` field (may be null)
|
|
1033
|
+
* @param {unknown} data the parsed JSON `data:` payload
|
|
1034
|
+
* @returns {{type:string, sessionID?:string, messageID?:string, part?:object, data?:object}|null}
|
|
1035
|
+
*/
|
|
1036
|
+
export function unwrapClineSseEvent(eventName, data) {
|
|
1037
|
+
if (!data || typeof data !== 'object' || Array.isArray(data)) return null;
|
|
1038
|
+
let obj = /** @type {Record<string, unknown>} */ (data);
|
|
1039
|
+
|
|
1040
|
+
// Step 1: detect sync wrapper and unwrap. After this, `obj` points at
|
|
1041
|
+
// the inner `syncEvent.data` (or remains the original on partial shape).
|
|
1042
|
+
let innerType = null;
|
|
1043
|
+
if (obj.type === 'sync' && obj.syncEvent && typeof obj.syncEvent === 'object') {
|
|
1044
|
+
const syncEvent = /** @type {Record<string, unknown>} */ (obj.syncEvent);
|
|
1045
|
+
if (typeof syncEvent.type === 'string') innerType = syncEvent.type;
|
|
1046
|
+
if (syncEvent.data && typeof syncEvent.data === 'object') {
|
|
1047
|
+
obj = /** @type {Record<string, unknown>} */ (syncEvent.data);
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
// Step 2: resolve the event type, preferring the inner sync type.
|
|
1052
|
+
// Strip the trailing `.<digits>` version suffix.
|
|
1053
|
+
const typeFromObj = innerType ?? (typeof obj.type === 'string' ? obj.type : null);
|
|
1054
|
+
const rawType = typeFromObj ?? eventName ?? null;
|
|
1055
|
+
if (typeof rawType !== 'string' || rawType.length === 0) return null;
|
|
1056
|
+
const type = stripVersionSuffix(rawType);
|
|
1057
|
+
|
|
1058
|
+
// Step 3: extract identifiers from any of the common key spellings.
|
|
1059
|
+
const sessionID = pickString(obj, [
|
|
1060
|
+
'sessionID', 'sessionId', 'session_id',
|
|
1061
|
+
], ['properties']);
|
|
1062
|
+
const messageID = pickString(obj, [
|
|
1063
|
+
'messageID', 'messageId', 'message_id',
|
|
1064
|
+
], ['properties']);
|
|
1065
|
+
const part = obj.part && typeof obj.part === 'object'
|
|
1066
|
+
? /** @type {object} */ (obj.part)
|
|
1067
|
+
: undefined;
|
|
1068
|
+
|
|
1069
|
+
return { type, sessionID, messageID, part, data: obj };
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
/**
|
|
1073
|
+
* Strip the trailing `.<digits>` version suffix from an event type
|
|
1074
|
+
* (e.g. `session.created.1` → `session.created`).
|
|
1075
|
+
*
|
|
1076
|
+
* @param {string} s
|
|
1077
|
+
* @returns {string}
|
|
1078
|
+
*/
|
|
1079
|
+
export function stripVersionSuffix(s) {
|
|
1080
|
+
if (typeof s !== 'string') return '';
|
|
1081
|
+
return s.replace(/\.\d+$/, '');
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
/**
|
|
1085
|
+
* Look up a string field on `obj`, falling back to any nested object
|
|
1086
|
+
* whose key is in `nestedKeys` (e.g. `['properties']`).
|
|
1087
|
+
*
|
|
1088
|
+
* @param {Record<string, unknown>} obj
|
|
1089
|
+
* @param {string[]} keys top-level keys to check first
|
|
1090
|
+
* @param {string[]} [nestedKeys] optional parents to recurse into
|
|
1091
|
+
* @returns {string|undefined}
|
|
1092
|
+
*/
|
|
1093
|
+
function pickString(obj, keys, nestedKeys) {
|
|
1094
|
+
for (const k of keys) {
|
|
1095
|
+
const v = obj[k];
|
|
1096
|
+
if (typeof v === 'string' && v.length > 0) return v;
|
|
1097
|
+
}
|
|
1098
|
+
if (nestedKeys) {
|
|
1099
|
+
for (const nk of nestedKeys) {
|
|
1100
|
+
const nested = obj[nk];
|
|
1101
|
+
if (nested && typeof nested === 'object') {
|
|
1102
|
+
for (const k of keys) {
|
|
1103
|
+
const v = /** @type {Record<string, unknown>} */ (nested)[k];
|
|
1104
|
+
if (typeof v === 'string' && v.length > 0) return v;
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
return undefined;
|
|
1110
|
+
}
|