@polderlabs/bizar 3.23.1 → 4.2.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/README.md +83 -16
- package/bizar-dash/.bizar/activity.log +3 -0
- package/bizar-dash/.bizar/graph/.graphify_analysis.json +1540 -0
- package/bizar-dash/.bizar/graph/.graphify_labels.json +1 -0
- package/bizar-dash/.bizar/graph/GRAPH_REPORT.md +404 -0
- package/bizar-dash/.bizar/graph/cache/ast/v0.8.46/0661b816358db84dfdb7f10443db8a61152fd20b3fee950caf8fbf32920a1790.json +1 -0
- package/bizar-dash/.bizar/graph/cache/ast/v0.8.46/16da06d774142a6e5d74829ad982531286a6193ef798de8f593db029e123ec32.json +1 -0
- package/bizar-dash/.bizar/graph/cache/ast/v0.8.46/27e5697c01254c69c64c5a33896669073b40afb5ba88375102ae77fa5404136d.json +1 -0
- package/bizar-dash/.bizar/graph/cache/ast/v0.8.46/532997898027254aa4c0932243dc71d2f55888181232b65974961934997dc85b.json +1 -0
- package/bizar-dash/.bizar/graph/cache/ast/v0.8.46/84e3451a64c7f99f0cd6a88b0748d7426780486f53ab4935b7476b28c08f8293.json +1 -0
- package/bizar-dash/.bizar/graph/cache/ast/v0.8.46/88e5ea5f3e78fa69353fe9e6a8d1a05391d54605e25600cb125531eb5a6432ff.json +1 -0
- package/bizar-dash/.bizar/graph/cache/stat-index.json +1 -0
- package/bizar-dash/.bizar/graph/graph.html +307 -0
- package/bizar-dash/.bizar/graph/graph.json +40267 -0
- package/bizar-dash/.bizar/graph/manifest.json +762 -0
- package/bizar-dash/.graphifyignore +40 -0
- package/bizar-dash/.obsidian/README.md +14 -0
- package/bizar-dash/.obsidian/daily/2026-06-25.md +9 -0
- package/bizar-dash/.obsidian/vault.json +7 -0
- package/bizar-dash/.od-skills/web-prototype-e1429c1737/SKILL.md +103 -0
- package/bizar-dash/.od-skills/web-prototype-e1429c1737/assets/template.html +338 -0
- package/bizar-dash/.od-skills/web-prototype-e1429c1737/example.html +81 -0
- package/bizar-dash/.od-skills/web-prototype-e1429c1737/open-design.json +172 -0
- package/bizar-dash/.od-skills/web-prototype-e1429c1737/references/checklist.md +44 -0
- package/bizar-dash/.od-skills/web-prototype-e1429c1737/references/layouts.md +247 -0
- package/bizar-dash/CHANGELOG.md +474 -0
- package/bizar-dash/DESIGN.md +136 -0
- package/bizar-dash/dist/assets/main-B3RgW6FS.js +331 -0
- package/bizar-dash/dist/assets/main-B3RgW6FS.js.map +1 -0
- package/bizar-dash/dist/assets/main-DlJ8wgLR.css +1 -0
- package/bizar-dash/dist/assets/mobile-CsZQAswA.css +1 -0
- package/bizar-dash/dist/assets/mobile-DbxIw8BG.js +2 -0
- package/bizar-dash/dist/assets/mobile-DbxIw8BG.js.map +1 -0
- package/bizar-dash/dist/assets/mobile-Dvq2d53Y.js +354 -0
- package/bizar-dash/dist/assets/mobile-Dvq2d53Y.js.map +1 -0
- package/bizar-dash/dist/index.html +40 -0
- package/bizar-dash/dist/mobile.html +22 -0
- package/bizar-dash/plans/debug-plan/comments.json +1 -0
- package/bizar-dash/plans/debug-plan/meta.json +10 -0
- package/bizar-dash/plans/debug-plan/plan.json +174 -0
- package/bizar-dash/scripts/smoke-bg-retry.mjs +246 -0
- package/bizar-dash/src/cli/dashboard-ports.mjs +488 -0
- package/bizar-dash/src/cli.mjs +522 -0
- package/bizar-dash/src/server/activity-log.mjs +174 -0
- package/bizar-dash/src/server/agents-store.mjs +465 -0
- package/bizar-dash/src/server/api.mjs +138 -0
- package/bizar-dash/src/server/artifact-template.html +810 -0
- package/bizar-dash/src/server/artifacts-store.mjs +733 -0
- package/bizar-dash/src/server/auth.mjs +381 -0
- package/bizar-dash/src/server/background-store.mjs +447 -0
- package/bizar-dash/src/server/bg-poller.mjs +305 -0
- package/bizar-dash/src/server/bg-retry.mjs +574 -0
- package/bizar-dash/src/server/browser.mjs +40 -0
- package/bizar-dash/src/server/diagnostics-store.mjs +148 -0
- package/bizar-dash/src/server/dialog-poller.mjs +105 -0
- package/bizar-dash/src/server/dialog-store.mjs +177 -0
- package/bizar-dash/src/server/glyphs/mdx-compiler.mjs +583 -0
- package/bizar-dash/src/server/lib/path-safe.mjs +283 -0
- package/bizar-dash/src/server/memory-git.mjs +329 -0
- package/bizar-dash/src/server/memory-lightrag.mjs +767 -0
- package/bizar-dash/src/server/memory-schema.mjs +145 -0
- package/bizar-dash/src/server/memory-secrets.mjs +84 -0
- package/bizar-dash/src/server/memory-store.mjs +471 -0
- package/bizar-dash/src/server/mod-security.mjs +398 -0
- package/bizar-dash/src/server/mods-loader.mjs +1067 -0
- package/bizar-dash/src/server/notifications-store.mjs +243 -0
- package/bizar-dash/src/server/obsidian-store.mjs +318 -0
- package/bizar-dash/src/server/opencode-runner.mjs +279 -0
- package/bizar-dash/src/server/pair-store.mjs +138 -0
- package/bizar-dash/src/server/projects-store.mjs +364 -0
- package/bizar-dash/src/server/providers-store.mjs +789 -0
- package/bizar-dash/src/server/routes/_shared.mjs +415 -0
- package/bizar-dash/src/server/routes/activity.mjs +110 -0
- package/bizar-dash/src/server/routes/agents.mjs +134 -0
- package/bizar-dash/src/server/routes/artifacts.mjs +279 -0
- package/bizar-dash/src/server/routes/auth.mjs +69 -0
- package/bizar-dash/src/server/routes/background.mjs +165 -0
- package/bizar-dash/src/server/routes/chat.mjs +485 -0
- package/bizar-dash/src/server/routes/config.mjs +129 -0
- package/bizar-dash/src/server/routes/diagnostics.mjs +50 -0
- package/bizar-dash/src/server/routes/dialogs.mjs +86 -0
- package/bizar-dash/src/server/routes/fs.mjs +429 -0
- package/bizar-dash/src/server/routes/history.mjs +78 -0
- package/bizar-dash/src/server/routes/memory.mjs +658 -0
- package/bizar-dash/src/server/routes/misc.mjs +89 -0
- package/bizar-dash/src/server/routes/mods.mjs +359 -0
- package/bizar-dash/src/server/routes/notifications.mjs +54 -0
- package/bizar-dash/src/server/routes/obsidian.mjs +239 -0
- package/bizar-dash/src/server/routes/opencode-sessions.mjs +55 -0
- package/bizar-dash/src/server/routes/overview.mjs +91 -0
- package/bizar-dash/src/server/routes/pair.mjs +67 -0
- package/bizar-dash/src/server/routes/projects.mjs +175 -0
- package/bizar-dash/src/server/routes/providers.mjs +47 -0
- package/bizar-dash/src/server/routes/schedules.mjs +104 -0
- package/bizar-dash/src/server/routes/settings.mjs +51 -0
- package/bizar-dash/src/server/routes/skills.mjs +76 -0
- package/bizar-dash/src/server/routes/tasks.mjs +468 -0
- package/bizar-dash/src/server/routes/themes.mjs +51 -0
- package/bizar-dash/src/server/routes-v2/auth.mjs +59 -0
- package/bizar-dash/src/server/routes-v2/events.mjs +107 -0
- package/bizar-dash/src/server/routes-v2/health.mjs +21 -0
- package/bizar-dash/src/server/routes-v2/index.mjs +90 -0
- package/bizar-dash/src/server/routes-v2/sessions.mjs +111 -0
- package/bizar-dash/src/server/schedules-runner.mjs +369 -0
- package/bizar-dash/src/server/schedules-store.mjs +268 -0
- package/bizar-dash/src/server/search-store.mjs +220 -0
- package/bizar-dash/src/server/serve-info.mjs +684 -0
- package/bizar-dash/src/server/server.mjs +796 -0
- package/bizar-dash/src/server/settings-store.mjs +45 -0
- package/bizar-dash/src/server/skills-store.mjs +300 -0
- package/bizar-dash/src/server/state.mjs +437 -0
- package/bizar-dash/src/server/tailscale-store.mjs +113 -0
- package/bizar-dash/src/server/task-delegator.mjs +824 -0
- package/bizar-dash/src/server/tasks-store.mjs +508 -0
- package/bizar-dash/src/server/tui.mjs +923 -0
- package/bizar-dash/src/server/update-store.mjs +168 -0
- package/bizar-dash/src/server/v2-auth-file.mjs +99 -0
- package/bizar-dash/src/server/v2-event-bus.mjs +128 -0
- package/bizar-dash/src/server/watcher.mjs +81 -0
- package/bizar-dash/src/server/yaml.mjs +238 -0
- package/bizar-dash/src/web/App.tsx +718 -0
- package/bizar-dash/src/web/MobileApp.tsx +408 -0
- package/bizar-dash/src/web/components/ArtifactCreateDialog.tsx +95 -0
- package/bizar-dash/src/web/components/ArtifactListDialog.tsx +55 -0
- package/bizar-dash/src/web/components/ArtifactViewer.tsx +143 -0
- package/bizar-dash/src/web/components/AuditDialog.tsx +79 -0
- package/bizar-dash/src/web/components/BgStatusBadge.tsx +32 -0
- package/bizar-dash/src/web/components/Button.tsx +56 -0
- package/bizar-dash/src/web/components/CanvasContextMenu.tsx +68 -0
- package/bizar-dash/src/web/components/Card.tsx +40 -0
- package/bizar-dash/src/web/components/CollapsibleSection.tsx +72 -0
- package/bizar-dash/src/web/components/CommandDialog.tsx +66 -0
- package/bizar-dash/src/web/components/EmptyState.tsx +30 -0
- package/bizar-dash/src/web/components/FileBrowser.tsx +633 -0
- package/bizar-dash/src/web/components/HelpDialog.tsx +55 -0
- package/bizar-dash/src/web/components/KillConfirmDialog.tsx +88 -0
- package/bizar-dash/src/web/components/Modal.tsx +215 -0
- package/bizar-dash/src/web/components/Notifications.tsx +241 -0
- package/bizar-dash/src/web/components/SearchModal.tsx +224 -0
- package/bizar-dash/src/web/components/Sidebar.tsx +66 -0
- package/bizar-dash/src/web/components/Spinner.tsx +19 -0
- package/bizar-dash/src/web/components/StatusBadge.tsx +25 -0
- package/bizar-dash/src/web/components/Tag.tsx +28 -0
- package/bizar-dash/src/web/components/Toast.tsx +150 -0
- package/bizar-dash/src/web/components/Topbar.tsx +368 -0
- package/bizar-dash/src/web/components/VisualPlanDialog.tsx +58 -0
- package/bizar-dash/src/web/components/chat/AgentChip.tsx +68 -0
- package/bizar-dash/src/web/components/chat/ChatBubble.tsx +60 -0
- package/bizar-dash/src/web/components/chat/ChatThread.tsx +88 -0
- package/bizar-dash/src/web/components/chat/ChatTopBar.tsx +50 -0
- package/bizar-dash/src/web/components/chat/Composer.tsx +164 -0
- package/bizar-dash/src/web/components/chat/ConfirmModal.tsx +54 -0
- package/bizar-dash/src/web/components/chat/EmptyState.tsx +21 -0
- package/bizar-dash/src/web/components/chat/FirstRunGreeting.tsx +18 -0
- package/bizar-dash/src/web/components/chat/FloatingComposer.tsx +32 -0
- package/bizar-dash/src/web/components/chat/InfoPanel.tsx +119 -0
- package/bizar-dash/src/web/components/chat/LoadingSkeleton.tsx +19 -0
- package/bizar-dash/src/web/components/chat/MessageBubble.tsx +60 -0
- package/bizar-dash/src/web/components/chat/SessionList.tsx +153 -0
- package/bizar-dash/src/web/components/chat/StreamingIndicator.tsx +9 -0
- package/bizar-dash/src/web/components/chat/SuggestionCards.tsx +55 -0
- package/bizar-dash/src/web/components/chat/WelcomeScreen.tsx +36 -0
- package/bizar-dash/src/web/components/chat/index.ts +20 -0
- package/bizar-dash/src/web/components/chat/useAutoGrowTextarea.ts +18 -0
- package/bizar-dash/src/web/components/chat/useChat.ts +219 -0
- package/bizar-dash/src/web/components/chat/useSlashCommands.ts +47 -0
- package/bizar-dash/src/web/index.html +37 -0
- package/bizar-dash/src/web/lib/api.ts +193 -0
- package/bizar-dash/src/web/lib/markdown.tsx +59 -0
- package/bizar-dash/src/web/lib/types.ts +668 -0
- package/bizar-dash/src/web/lib/utils.ts +114 -0
- package/bizar-dash/src/web/lib/ws.ts +176 -0
- package/bizar-dash/src/web/main.tsx +34 -0
- package/bizar-dash/src/web/mobile/MobileApp.tsx +278 -0
- package/bizar-dash/src/web/mobile/MobileBottomNav.tsx +38 -0
- package/bizar-dash/src/web/mobile/MobileTopbar.tsx +115 -0
- package/bizar-dash/src/web/mobile/components/MobileBottomSheet.tsx +182 -0
- package/bizar-dash/src/web/mobile/components/MobileListItem.tsx +64 -0
- package/bizar-dash/src/web/mobile/components/MobileModal.tsx +123 -0
- package/bizar-dash/src/web/mobile/views/MobileActivity.tsx +273 -0
- package/bizar-dash/src/web/mobile/views/MobileAgents.tsx +374 -0
- package/bizar-dash/src/web/mobile/views/MobileArtifactCanvas.tsx +439 -0
- package/bizar-dash/src/web/mobile/views/MobileArtifacts.tsx +143 -0
- package/bizar-dash/src/web/mobile/views/MobileChat.tsx +180 -0
- package/bizar-dash/src/web/mobile/views/MobileConfig.tsx +175 -0
- package/bizar-dash/src/web/mobile/views/MobileHistory.tsx +191 -0
- package/bizar-dash/src/web/mobile/views/MobileMods.tsx +149 -0
- package/bizar-dash/src/web/mobile/views/MobileMore.tsx +121 -0
- package/bizar-dash/src/web/mobile/views/MobileNotifications.tsx +137 -0
- package/bizar-dash/src/web/mobile/views/MobilePlans.tsx +26 -0
- package/bizar-dash/src/web/mobile/views/MobileSchedules.tsx +685 -0
- package/bizar-dash/src/web/mobile/views/MobileSearchModal.tsx +172 -0
- package/bizar-dash/src/web/mobile/views/MobileSettings.tsx +388 -0
- package/bizar-dash/src/web/mobile/views/MobileSkills.tsx +153 -0
- package/bizar-dash/src/web/mobile/views/MobileTasks.tsx +564 -0
- package/bizar-dash/src/web/mobile.html +20 -0
- package/bizar-dash/src/web/mobile.tsx +13 -0
- package/bizar-dash/src/web/styles/chat.css +198 -0
- package/bizar-dash/src/web/styles/glyphs.css +960 -0
- package/bizar-dash/src/web/styles/main.css +8855 -0
- package/bizar-dash/src/web/styles/mobile-chat.css +5 -0
- package/bizar-dash/src/web/styles/mobile.css +1960 -0
- package/bizar-dash/src/web/views/Activity.tsx +1203 -0
- package/bizar-dash/src/web/views/Agents.tsx +701 -0
- package/bizar-dash/src/web/views/Artifacts.tsx +1480 -0
- package/bizar-dash/src/web/views/BackgroundAgents.tsx +450 -0
- package/bizar-dash/src/web/views/Chat.tsx +190 -0
- package/bizar-dash/src/web/views/Config.tsx +2063 -0
- package/bizar-dash/src/web/views/History.tsx +335 -0
- package/bizar-dash/src/web/views/ModView.tsx +207 -0
- package/bizar-dash/src/web/views/Mods.tsx +693 -0
- package/bizar-dash/src/web/views/Overview.tsx +812 -0
- package/bizar-dash/src/web/views/Providers.tsx +302 -0
- package/bizar-dash/src/web/views/Schedules.tsx +802 -0
- package/bizar-dash/src/web/views/Settings.tsx +1787 -0
- package/bizar-dash/src/web/views/Skills.tsx +431 -0
- package/bizar-dash/src/web/views/Tasks.tsx +1523 -0
- package/bizar-dash/src/web/views/glyphs/GlyphRenderer.tsx +613 -0
- package/bizar-dash/src/web/views/glyphs/components.tsx +1098 -0
- package/bizar-dash/templates/mod/FORMAT.md +76 -0
- package/bizar-dash/templates/mod/hello-mod/README.md +19 -0
- package/bizar-dash/templates/mod/hello-mod/agents/greeter.md +8 -0
- package/bizar-dash/templates/mod/hello-mod/commands/hello.md +6 -0
- package/bizar-dash/templates/mod/hello-mod/mod.json +20 -0
- package/bizar-dash/templates/mod/hello-mod/routes/ping.mjs +9 -0
- package/bizar-dash/templates/mod/hello-mod/views/HelloView.tsx +10 -0
- package/bizar-dash/tests/dashboard-ports.test.mjs +138 -0
- package/bizar-dash/tests/graphify-mod-spawn.node.test.mjs +90 -0
- package/bizar-dash/tests/memory-cli.test.mjs +542 -0
- package/bizar-dash/tests/memory-config.test.mjs +422 -0
- package/bizar-dash/tests/memory-git.test.mjs +246 -0
- package/bizar-dash/tests/memory-lightrag.test.mjs +153 -0
- package/bizar-dash/tests/memory-protocol-drift.test.mjs +45 -0
- package/bizar-dash/tests/memory-schema.test.mjs +198 -0
- package/bizar-dash/tests/memory-secrets.test.mjs +121 -0
- package/bizar-dash/tests/memory-store.test.mjs +390 -0
- package/bizar-dash/tests/memory-sync.test.mjs +141 -0
- package/bizar-dash/tests/mod-instructions.node.test.mjs +188 -0
- package/bizar-dash/tests/mod-security.test.mjs +273 -0
- package/bizar-dash/tests/mod-upgrade.node.test.mjs +357 -0
- package/bizar-dash/tests/no-agent-browser.node.test.mjs +98 -0
- package/bizar-dash/tests/obsidian-back-compat.test.mjs +199 -0
- package/bizar-dash/tests/opencode-runner.test.mjs +172 -0
- package/bizar-dash/tests/path-safe.test.mjs +108 -0
- package/bizar-dash/tests/providers-store-backup-keys.node.test.mjs +333 -0
- package/bizar-dash/tests/smoke-v2.mjs +212 -0
- package/bizar-dash/tests/strip-thinking.test.mjs +175 -0
- package/bizar-dash/tests/submit-feedback.test.mjs +353 -0
- package/bizar-dash/tests/tmux-wrap.test.mjs +145 -0
- package/bizar-dash/tests/yaml.test.mjs +128 -0
- package/bizar-dash/tsconfig.json +23 -0
- package/bizar-dash/vite.config.ts +27 -0
- package/cli/atomic.mjs +73 -0
- package/cli/banner.mjs +1 -1
- package/cli/bin.mjs +44 -47
- package/cli/bootstrap.mjs +1 -1
- package/cli/copy.mjs +25 -16
- package/cli/dev-link.mjs +17 -1
- package/cli/doctor.mjs +4 -4
- package/cli/doctor.test.mjs +2 -2
- package/cli/init.mjs +135 -1
- package/cli/install.mjs +31 -39
- package/cli/memory-constants.mjs +59 -0
- package/cli/memory.mjs +1436 -0
- package/cli/service.mjs +5 -6
- package/cli/utils.mjs +6 -3
- package/config/AGENTS.md +7 -7
- package/config/agents/_shared/AGENT_BASELINE.md +59 -61
- package/config/opencode.json +13 -38
- package/config/skills/memory-protocol/SKILL.md +105 -0
- package/config/skills/obsidian/SKILL.md +270 -65
- package/install.sh +59 -19
- package/package.json +49 -14
- package/packages/sdk/LICENSE +21 -0
- package/packages/sdk/README.md +80 -0
- package/packages/sdk/src/client.ts +183 -0
- package/packages/sdk/src/errors.ts +120 -0
- package/packages/sdk/src/events.ts +153 -0
- package/packages/sdk/src/index.ts +63 -0
- package/packages/sdk/src/types.ts +176 -0
- package/packages/sdk/src/version.ts +4 -0
- package/packages/sdk/tests/client.test.ts +217 -0
- package/packages/sdk/tests/errors.test.ts +108 -0
- package/packages/sdk/tests/events.test.ts +139 -0
- package/packages/sdk/tests/fixtures/fetch-mock.ts +152 -0
- package/packages/sdk/tests/fixtures/sse-mock.ts +30 -0
- package/packages/sdk/tsconfig.json +25 -0
- package/packages/sdk/vitest.config.ts +9 -0
- package/plugins/bizar/LICENSE +21 -0
- package/plugins/bizar/README.md +448 -0
- package/plugins/bizar/dist/index.js +29901 -0
- package/plugins/bizar/index.ts +1491 -0
- package/plugins/bizar/scripts/check-forbidden-imports.sh +33 -0
- package/plugins/bizar/src/background-state.ts +551 -0
- package/plugins/bizar/src/background.ts +1250 -0
- package/plugins/bizar/src/commands-impl.ts +464 -0
- package/plugins/bizar/src/commands.ts +1168 -0
- package/plugins/bizar/src/dashboard-client.ts +233 -0
- package/plugins/bizar/src/event-stream.ts +606 -0
- package/plugins/bizar/src/fingerprint.ts +120 -0
- package/plugins/bizar/src/handoff.ts +79 -0
- package/plugins/bizar/src/http-client.ts +467 -0
- package/plugins/bizar/src/key-rotation.ts +218 -0
- package/plugins/bizar/src/logger.ts +144 -0
- package/plugins/bizar/src/loop.ts +176 -0
- package/plugins/bizar/src/opencode-runner.ts +390 -0
- package/plugins/bizar/src/options.ts +421 -0
- package/plugins/bizar/src/plan-fs.ts +323 -0
- package/plugins/bizar/src/reasoning-clean.ts +454 -0
- package/plugins/bizar/src/report.ts +178 -0
- package/plugins/bizar/src/research-prompt.ts +35 -0
- package/plugins/bizar/src/serve-info.ts +228 -0
- package/plugins/bizar/src/serve.ts +496 -0
- package/plugins/bizar/src/settings.ts +349 -0
- package/plugins/bizar/src/state.ts +298 -0
- package/plugins/bizar/src/tools/bg-collect.ts +104 -0
- package/plugins/bizar/src/tools/bg-get-comments.ts +239 -0
- package/plugins/bizar/src/tools/bg-kill.ts +87 -0
- package/plugins/bizar/src/tools/bg-spawn.ts +401 -0
- package/plugins/bizar/src/tools/bg-status.ts +99 -0
- package/plugins/bizar/src/tools/open-kb.ts +191 -0
- package/plugins/bizar/src/tools/plan-action.ts +767 -0
- package/plugins/bizar/src/tools/read-glyph-feedback.ts +170 -0
- package/plugins/bizar/src/tools/wait-for-feedback.ts +402 -0
- package/plugins/bizar/tests/attach-handler-bug.test.ts +169 -0
- package/plugins/bizar/tests/background-state.test.ts +277 -0
- package/plugins/bizar/tests/background.test.ts +402 -0
- package/plugins/bizar/tests/block.test.ts +195 -0
- package/plugins/bizar/tests/canonical-key-order.test.ts +75 -0
- package/plugins/bizar/tests/commands-impl.test.ts +442 -0
- package/plugins/bizar/tests/commands.test.ts +584 -0
- package/plugins/bizar/tests/config.test.ts +122 -0
- package/plugins/bizar/tests/dashboard-client.test.ts +159 -0
- package/plugins/bizar/tests/dispose.test.ts +336 -0
- package/plugins/bizar/tests/event-stream.test.ts +409 -0
- package/plugins/bizar/tests/event.test.ts +262 -0
- package/plugins/bizar/tests/fingerprint.test.ts +162 -0
- package/plugins/bizar/tests/http-client.test.ts +404 -0
- package/plugins/bizar/tests/init-helpers.test.ts +203 -0
- package/plugins/bizar/tests/integration/slash-command.test.ts +348 -0
- package/plugins/bizar/tests/integration/tool-routing.test.ts +314 -0
- package/plugins/bizar/tests/key-rotation.test.ts +396 -0
- package/plugins/bizar/tests/loop.test.ts +397 -0
- package/plugins/bizar/tests/options.test.ts +276 -0
- package/plugins/bizar/tests/reasoning-clean.test.ts +422 -0
- package/plugins/bizar/tests/serve.test.ts +339 -0
- package/plugins/bizar/tests/settings.test.ts +351 -0
- package/plugins/bizar/tests/stall-think.test.ts +750 -0
- package/plugins/bizar/tests/state.test.ts +276 -0
- package/plugins/bizar/tests/tools/bg-collect.test.ts +337 -0
- package/plugins/bizar/tests/tools/bg-get-comments.test.ts +485 -0
- package/plugins/bizar/tests/tools/bg-kill.test.ts +235 -0
- package/plugins/bizar/tests/tools/bg-spawn-delegation.test.ts +147 -0
- package/plugins/bizar/tests/tools/bg-spawn.test.ts +311 -0
- package/plugins/bizar/tests/tools/bg-status.test.ts +217 -0
- package/plugins/bizar/tests/tools/opencode-runner.test.ts +115 -0
- package/plugins/bizar/tests/tools/plan-action.test.ts +599 -0
- package/plugins/bizar/tests/tools/read-glyph-feedback.test.ts +253 -0
- package/plugins/bizar/tests/tools/wait-for-feedback.test.ts +390 -0
- package/plugins/bizar/tests/update-deadlock.test.ts +145 -0
- package/plugins/bizar/tsconfig.json +29 -0
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/server/bg-poller.mjs
|
|
3
|
+
*
|
|
4
|
+
* v3.5.5 — Task-completion polling bridge.
|
|
5
|
+
*
|
|
6
|
+
* The plugin writes bg state files to `~/.cache/bizar/bg/<id>.json`
|
|
7
|
+
* as each agent instance runs. When an instance reaches a terminal
|
|
8
|
+
* state (`done` or `failed`), this poller:
|
|
9
|
+
*
|
|
10
|
+
* 1. Updates the linked task's `status` to `done` / `blocked`.
|
|
11
|
+
* 2. Kills the tmux session (Task 3 integration) if one is alive.
|
|
12
|
+
* 3. For `done` instances, scans the final assistant message from
|
|
13
|
+
* the opencode session for an `html-artifact` fenced block and,
|
|
14
|
+
* when found, saves it via the artifacts store and links the
|
|
15
|
+
* artifact id onto the task's `metadata` (Task 5 + 6).
|
|
16
|
+
* 4. Broadcasts a `tasks:change` event so the UI updates in real
|
|
17
|
+
* time without waiting for a full snapshot.
|
|
18
|
+
*
|
|
19
|
+
* Polling cadence is 3s — long enough to keep idle CPU at zero, short
|
|
20
|
+
* enough that the dashboard reflects completions within a couple of
|
|
21
|
+
* seconds. The poller is started once during server boot and never
|
|
22
|
+
* stopped (it lives for the lifetime of the dashboard).
|
|
23
|
+
*
|
|
24
|
+
* Idempotency: we remember the last status we've seen per instance
|
|
25
|
+
* in a `Map` and only react to transitions, so a `done` instance that
|
|
26
|
+
* reappears in the list (the plugin rewrites the file on every
|
|
27
|
+
* progress event) won't trigger a duplicate task update.
|
|
28
|
+
*/
|
|
29
|
+
import { backgroundStore } from './background-store.mjs';
|
|
30
|
+
import { tasksStore } from './tasks-store.mjs';
|
|
31
|
+
import { projectsStore } from './projects-store.mjs';
|
|
32
|
+
import { artifactsStore, extractArtifactFromMessage } from './artifacts-store.mjs';
|
|
33
|
+
import { readServeInfo, listOpencodeMessages, extractContentFromOpencodeMessage, abortSession } from './serve-info.mjs';
|
|
34
|
+
import { execFileSync } from 'node:child_process';
|
|
35
|
+
|
|
36
|
+
const POLL_INTERVAL_MS = 3_000;
|
|
37
|
+
const ARTIFACT_SCAN_TIMEOUT_MS = 6_000;
|
|
38
|
+
|
|
39
|
+
const trackedStatuses = new Map(); // bgInstanceId -> last known status
|
|
40
|
+
const processedArtifacts = new Set(); // bgInstanceId -> "scanned once" guard
|
|
41
|
+
// v3.5.8 — Failure counter per task. Bumps on every update error and
|
|
42
|
+
// emits a WS `background:syncError` event at 3, 10, 20, 30, 40, 50, 60
|
|
43
|
+
// … so the UI can surface a real badge instead of swallowing the
|
|
44
|
+
// problem in console.error. After FAIL_GIVE_UP consecutive failures
|
|
45
|
+
// we reset the counter — the poller will keep retrying each tick, but
|
|
46
|
+
// we stop spamming the WS.
|
|
47
|
+
const taskFailures = new Map(); // taskId -> failure count
|
|
48
|
+
const FAIL_GIVE_UP = 50;
|
|
49
|
+
|
|
50
|
+
function recordPollerFailure(scope, taskId, instanceId, err) {
|
|
51
|
+
const key = String(taskId || instanceId || 'unknown');
|
|
52
|
+
const fails = (taskFailures.get(key) || 0) + 1;
|
|
53
|
+
taskFailures.set(key, fails);
|
|
54
|
+
console.error(`[bg-poller] ${scope} failed for ${key}:`, err.message);
|
|
55
|
+
if (fails === 3 || fails === 10 || fails % 10 === 0) {
|
|
56
|
+
// Lazy import — same pattern as the broadcast calls already in
|
|
57
|
+
// this file. Avoids pulling server.mjs at module load time.
|
|
58
|
+
import('./server.mjs')
|
|
59
|
+
.then(({ broadcast }) => {
|
|
60
|
+
broadcast({
|
|
61
|
+
type: 'background:syncError',
|
|
62
|
+
taskId: taskId || null,
|
|
63
|
+
instanceId: instanceId || null,
|
|
64
|
+
scope,
|
|
65
|
+
failures: fails,
|
|
66
|
+
error: err && err.message ? err.message : String(err),
|
|
67
|
+
});
|
|
68
|
+
})
|
|
69
|
+
.catch(() => {
|
|
70
|
+
/* best effort */
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
if (fails > FAIL_GIVE_UP) {
|
|
74
|
+
// Reset so the next batch of failures can notify again.
|
|
75
|
+
taskFailures.set(key, 0);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
let _interval = null;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Read the artifact for a finished bg instance from the opencode
|
|
83
|
+
* session. Returns the { html, name } pair or null when:
|
|
84
|
+
* - the plugin is offline
|
|
85
|
+
* - the opencode session has no messages
|
|
86
|
+
* - the final assistant message has no html-artifact block
|
|
87
|
+
*
|
|
88
|
+
* @returns {Promise<{html:string,name:string|null}|null>}
|
|
89
|
+
*/
|
|
90
|
+
async function scanForArtifact(bg) {
|
|
91
|
+
if (!bg.sessionId) return null;
|
|
92
|
+
const serveInfo = readServeInfo();
|
|
93
|
+
if (!serveInfo) return null;
|
|
94
|
+
// v3.5.5 — `active.path` is the project root; that's the worktree
|
|
95
|
+
// the opencode session was created in. Fall back to the plugin's
|
|
96
|
+
// recorded worktree when the active project has been removed.
|
|
97
|
+
const active = projectsStore.active();
|
|
98
|
+
const directory = bg.worktree || (active && active.path) || serveInfo.worktree || '';
|
|
99
|
+
const list = await listOpencodeMessages(serveInfo, bg.sessionId, directory, ARTIFACT_SCAN_TIMEOUT_MS);
|
|
100
|
+
if (!list.ok || !Array.isArray(list.messages) || list.messages.length === 0) {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
// Walk newest → oldest; pick the last assistant message.
|
|
104
|
+
const assistants = list.messages
|
|
105
|
+
.filter((m) => (m?.info?.role || m?.role) === 'assistant')
|
|
106
|
+
.sort((a, b) => {
|
|
107
|
+
const ta = a?.info?.time?.created || 0;
|
|
108
|
+
const tb = b?.info?.time?.created || 0;
|
|
109
|
+
return tb - ta;
|
|
110
|
+
});
|
|
111
|
+
for (const m of assistants) {
|
|
112
|
+
const text = extractContentFromOpencodeMessage(m);
|
|
113
|
+
const found = extractArtifactFromMessage(text);
|
|
114
|
+
if (found) return found;
|
|
115
|
+
}
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Kill the tmux session for a bg instance, best-effort. Idempotent —
|
|
121
|
+
* returns true when the session is absent (it was already gone).
|
|
122
|
+
*/
|
|
123
|
+
function killTmuxFor(instanceId) {
|
|
124
|
+
if (!instanceId) return false;
|
|
125
|
+
const session = `bizar-bg-${instanceId}`;
|
|
126
|
+
try {
|
|
127
|
+
execFileSync('tmux', ['kill-session', '-t', session], { stdio: 'ignore', timeout: 4_000 });
|
|
128
|
+
return true;
|
|
129
|
+
} catch {
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
async function tick() {
|
|
135
|
+
let list;
|
|
136
|
+
try {
|
|
137
|
+
list = await backgroundStore.list();
|
|
138
|
+
} catch (err) {
|
|
139
|
+
console.error('[bg-poller] list() failed:', err.message);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
const seen = new Set();
|
|
143
|
+
|
|
144
|
+
for (const bg of list) {
|
|
145
|
+
seen.add(bg.instanceId);
|
|
146
|
+
const prev = trackedStatuses.get(bg.instanceId);
|
|
147
|
+
const curr = bg.status;
|
|
148
|
+
if (prev === curr) continue;
|
|
149
|
+
trackedStatuses.set(bg.instanceId, curr);
|
|
150
|
+
|
|
151
|
+
const active = projectsStore.active();
|
|
152
|
+
const projectId = bg.projectId || active?.id || null;
|
|
153
|
+
if (!projectId) continue;
|
|
154
|
+
const taskId = bg.taskId;
|
|
155
|
+
if (!taskId) continue;
|
|
156
|
+
|
|
157
|
+
// Map bg terminal states to task statuses. `done` is a clean
|
|
158
|
+
// success, `failed` / `killed` / `timed_out` map to `blocked`
|
|
159
|
+
// so the operator has to actively move them out of the blocked
|
|
160
|
+
// pile.
|
|
161
|
+
const TERMINAL = new Set(['done', 'failed', 'killed', 'timed_out']);
|
|
162
|
+
if (TERMINAL.has(curr)) {
|
|
163
|
+
// Update the task in-place.
|
|
164
|
+
const newStatus = curr === 'done' ? 'done' : 'blocked';
|
|
165
|
+
const currentStep =
|
|
166
|
+
curr === 'done'
|
|
167
|
+
? 'Completed'
|
|
168
|
+
: curr === 'failed'
|
|
169
|
+
? `Failed: ${bg.error || '(no error)'}`
|
|
170
|
+
: curr === 'killed'
|
|
171
|
+
? 'Killed by operator'
|
|
172
|
+
: `Timed out`;
|
|
173
|
+
try {
|
|
174
|
+
const updated = await tasksStore.update(projectId, taskId, {
|
|
175
|
+
status: newStatus,
|
|
176
|
+
metadata: {
|
|
177
|
+
...(bg || {}),
|
|
178
|
+
currentStep,
|
|
179
|
+
progress: curr === 'done' ? 100 : (bg.progress ?? 0),
|
|
180
|
+
completedAt: Date.now(),
|
|
181
|
+
},
|
|
182
|
+
});
|
|
183
|
+
if (updated) {
|
|
184
|
+
try {
|
|
185
|
+
const { broadcast } = await import('./server.mjs');
|
|
186
|
+
broadcast({ type: 'tasks:change', task: updated });
|
|
187
|
+
broadcast({ type: 'background:change', id: bg.instanceId, status: curr });
|
|
188
|
+
} catch { /* best effort */ }
|
|
189
|
+
}
|
|
190
|
+
} catch (err) {
|
|
191
|
+
recordPollerFailure('task-update', taskId, bg.instanceId, err);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Best-effort: abort the opencode session. Idempotent — a
|
|
195
|
+
// already-finished session just returns 404 and we move on.
|
|
196
|
+
if (bg.sessionId) {
|
|
197
|
+
try {
|
|
198
|
+
const serveInfo = readServeInfo();
|
|
199
|
+
if (serveInfo) {
|
|
200
|
+
await abortSession(serveInfo, bg.sessionId, bg.worktree || serveInfo.worktree);
|
|
201
|
+
}
|
|
202
|
+
} catch { /* best effort */ }
|
|
203
|
+
|
|
204
|
+
// v3.5.5 — On `done`, scan for an html-artifact in the
|
|
205
|
+
// final message and save it. Guarded by `processedArtifacts`
|
|
206
|
+
// so a `done` status that lingers in the list doesn't keep
|
|
207
|
+
// re-creating the artifact.
|
|
208
|
+
if (curr === 'done' && !processedArtifacts.has(bg.instanceId)) {
|
|
209
|
+
processedArtifacts.add(bg.instanceId);
|
|
210
|
+
try {
|
|
211
|
+
const found = await scanForArtifact(bg);
|
|
212
|
+
if (found) {
|
|
213
|
+
const meta = artifactsStore.save({
|
|
214
|
+
taskId,
|
|
215
|
+
projectId,
|
|
216
|
+
name: found.name || `${projectId} artifact`,
|
|
217
|
+
contentType: 'text/html',
|
|
218
|
+
content: found.html,
|
|
219
|
+
});
|
|
220
|
+
// Link the artifact back to the task. The UI looks for
|
|
221
|
+
// `metadata.artifactId` (single) first, then falls back
|
|
222
|
+
// to listing all artifacts by task id.
|
|
223
|
+
const updated2 = await tasksStore.update(projectId, taskId, {
|
|
224
|
+
metadata: {
|
|
225
|
+
artifactId: meta.id,
|
|
226
|
+
artifactName: meta.name,
|
|
227
|
+
},
|
|
228
|
+
});
|
|
229
|
+
if (updated2) {
|
|
230
|
+
try {
|
|
231
|
+
const { broadcast } = await import('./server.mjs');
|
|
232
|
+
broadcast({ type: 'tasks:change', task: updated2 });
|
|
233
|
+
broadcast({ type: 'artifact:new', artifact: meta });
|
|
234
|
+
} catch { /* best effort */ }
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
} catch (err) {
|
|
238
|
+
recordPollerFailure('artifact-scan', taskId, bg.instanceId, err);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Kill the tmux session if one is attached. Safe to call
|
|
244
|
+
// multiple times — the second call is a no-op.
|
|
245
|
+
killTmuxFor(bg.instanceId);
|
|
246
|
+
} else if (curr === 'running' && (prev === 'pending' || !prev)) {
|
|
247
|
+
// First transition into running — push a status sync.
|
|
248
|
+
try {
|
|
249
|
+
const updated = await tasksStore.update(projectId, taskId, {
|
|
250
|
+
status: 'doing',
|
|
251
|
+
metadata: {
|
|
252
|
+
...(bg || {}),
|
|
253
|
+
currentStep: 'Agent running',
|
|
254
|
+
},
|
|
255
|
+
});
|
|
256
|
+
if (updated) {
|
|
257
|
+
try {
|
|
258
|
+
const { broadcast } = await import('./server.mjs');
|
|
259
|
+
broadcast({ type: 'tasks:change', task: updated });
|
|
260
|
+
} catch { /* best effort */ }
|
|
261
|
+
}
|
|
262
|
+
} catch { /* best effort */ }
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// Clean up tracking for instances that have been removed from disk.
|
|
267
|
+
for (const id of trackedStatuses.keys()) {
|
|
268
|
+
if (!seen.has(id)) trackedStatuses.delete(id);
|
|
269
|
+
}
|
|
270
|
+
for (const id of processedArtifacts) {
|
|
271
|
+
if (!seen.has(id)) processedArtifacts.delete(id);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
export function startBgPoller() {
|
|
276
|
+
if (_interval) return; // idempotent
|
|
277
|
+
// Tick once immediately so completions that happened while the
|
|
278
|
+
// dashboard was down are reflected on the first WS snapshot.
|
|
279
|
+
tick().catch((err) => console.error('[bg-poller] initial tick:', err.message));
|
|
280
|
+
_interval = setInterval(() => {
|
|
281
|
+
tick().catch((err) => console.error('[bg-poller] tick:', err.message));
|
|
282
|
+
}, POLL_INTERVAL_MS);
|
|
283
|
+
// Don't keep the event loop alive just for the poller — the http
|
|
284
|
+
// server already does that. `unref()` is safe because we tear down
|
|
285
|
+
// via the parent module's lifecycle.
|
|
286
|
+
if (_interval && typeof _interval.unref === 'function') {
|
|
287
|
+
_interval.unref();
|
|
288
|
+
}
|
|
289
|
+
console.log(`[bg-poller] started (interval=${POLL_INTERVAL_MS}ms)`);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
export function stopBgPoller() {
|
|
293
|
+
if (_interval) {
|
|
294
|
+
clearInterval(_interval);
|
|
295
|
+
_interval = null;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// Exposed for tests / introspection.
|
|
300
|
+
export const _pollerInternals = {
|
|
301
|
+
trackedStatuses,
|
|
302
|
+
processedArtifacts,
|
|
303
|
+
tick,
|
|
304
|
+
POLL_INTERVAL_MS,
|
|
305
|
+
};
|