@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.
Files changed (361) hide show
  1. package/README.md +83 -16
  2. package/bizar-dash/.bizar/activity.log +3 -0
  3. package/bizar-dash/.bizar/graph/.graphify_analysis.json +1540 -0
  4. package/bizar-dash/.bizar/graph/.graphify_labels.json +1 -0
  5. package/bizar-dash/.bizar/graph/GRAPH_REPORT.md +404 -0
  6. package/bizar-dash/.bizar/graph/cache/ast/v0.8.46/0661b816358db84dfdb7f10443db8a61152fd20b3fee950caf8fbf32920a1790.json +1 -0
  7. package/bizar-dash/.bizar/graph/cache/ast/v0.8.46/16da06d774142a6e5d74829ad982531286a6193ef798de8f593db029e123ec32.json +1 -0
  8. package/bizar-dash/.bizar/graph/cache/ast/v0.8.46/27e5697c01254c69c64c5a33896669073b40afb5ba88375102ae77fa5404136d.json +1 -0
  9. package/bizar-dash/.bizar/graph/cache/ast/v0.8.46/532997898027254aa4c0932243dc71d2f55888181232b65974961934997dc85b.json +1 -0
  10. package/bizar-dash/.bizar/graph/cache/ast/v0.8.46/84e3451a64c7f99f0cd6a88b0748d7426780486f53ab4935b7476b28c08f8293.json +1 -0
  11. package/bizar-dash/.bizar/graph/cache/ast/v0.8.46/88e5ea5f3e78fa69353fe9e6a8d1a05391d54605e25600cb125531eb5a6432ff.json +1 -0
  12. package/bizar-dash/.bizar/graph/cache/stat-index.json +1 -0
  13. package/bizar-dash/.bizar/graph/graph.html +307 -0
  14. package/bizar-dash/.bizar/graph/graph.json +40267 -0
  15. package/bizar-dash/.bizar/graph/manifest.json +762 -0
  16. package/bizar-dash/.graphifyignore +40 -0
  17. package/bizar-dash/.obsidian/README.md +14 -0
  18. package/bizar-dash/.obsidian/daily/2026-06-25.md +9 -0
  19. package/bizar-dash/.obsidian/vault.json +7 -0
  20. package/bizar-dash/.od-skills/web-prototype-e1429c1737/SKILL.md +103 -0
  21. package/bizar-dash/.od-skills/web-prototype-e1429c1737/assets/template.html +338 -0
  22. package/bizar-dash/.od-skills/web-prototype-e1429c1737/example.html +81 -0
  23. package/bizar-dash/.od-skills/web-prototype-e1429c1737/open-design.json +172 -0
  24. package/bizar-dash/.od-skills/web-prototype-e1429c1737/references/checklist.md +44 -0
  25. package/bizar-dash/.od-skills/web-prototype-e1429c1737/references/layouts.md +247 -0
  26. package/bizar-dash/CHANGELOG.md +474 -0
  27. package/bizar-dash/DESIGN.md +136 -0
  28. package/bizar-dash/dist/assets/main-B3RgW6FS.js +331 -0
  29. package/bizar-dash/dist/assets/main-B3RgW6FS.js.map +1 -0
  30. package/bizar-dash/dist/assets/main-DlJ8wgLR.css +1 -0
  31. package/bizar-dash/dist/assets/mobile-CsZQAswA.css +1 -0
  32. package/bizar-dash/dist/assets/mobile-DbxIw8BG.js +2 -0
  33. package/bizar-dash/dist/assets/mobile-DbxIw8BG.js.map +1 -0
  34. package/bizar-dash/dist/assets/mobile-Dvq2d53Y.js +354 -0
  35. package/bizar-dash/dist/assets/mobile-Dvq2d53Y.js.map +1 -0
  36. package/bizar-dash/dist/index.html +40 -0
  37. package/bizar-dash/dist/mobile.html +22 -0
  38. package/bizar-dash/plans/debug-plan/comments.json +1 -0
  39. package/bizar-dash/plans/debug-plan/meta.json +10 -0
  40. package/bizar-dash/plans/debug-plan/plan.json +174 -0
  41. package/bizar-dash/scripts/smoke-bg-retry.mjs +246 -0
  42. package/bizar-dash/src/cli/dashboard-ports.mjs +488 -0
  43. package/bizar-dash/src/cli.mjs +522 -0
  44. package/bizar-dash/src/server/activity-log.mjs +174 -0
  45. package/bizar-dash/src/server/agents-store.mjs +465 -0
  46. package/bizar-dash/src/server/api.mjs +138 -0
  47. package/bizar-dash/src/server/artifact-template.html +810 -0
  48. package/bizar-dash/src/server/artifacts-store.mjs +733 -0
  49. package/bizar-dash/src/server/auth.mjs +381 -0
  50. package/bizar-dash/src/server/background-store.mjs +447 -0
  51. package/bizar-dash/src/server/bg-poller.mjs +305 -0
  52. package/bizar-dash/src/server/bg-retry.mjs +574 -0
  53. package/bizar-dash/src/server/browser.mjs +40 -0
  54. package/bizar-dash/src/server/diagnostics-store.mjs +148 -0
  55. package/bizar-dash/src/server/dialog-poller.mjs +105 -0
  56. package/bizar-dash/src/server/dialog-store.mjs +177 -0
  57. package/bizar-dash/src/server/glyphs/mdx-compiler.mjs +583 -0
  58. package/bizar-dash/src/server/lib/path-safe.mjs +283 -0
  59. package/bizar-dash/src/server/memory-git.mjs +329 -0
  60. package/bizar-dash/src/server/memory-lightrag.mjs +767 -0
  61. package/bizar-dash/src/server/memory-schema.mjs +145 -0
  62. package/bizar-dash/src/server/memory-secrets.mjs +84 -0
  63. package/bizar-dash/src/server/memory-store.mjs +471 -0
  64. package/bizar-dash/src/server/mod-security.mjs +398 -0
  65. package/bizar-dash/src/server/mods-loader.mjs +1067 -0
  66. package/bizar-dash/src/server/notifications-store.mjs +243 -0
  67. package/bizar-dash/src/server/obsidian-store.mjs +318 -0
  68. package/bizar-dash/src/server/opencode-runner.mjs +279 -0
  69. package/bizar-dash/src/server/pair-store.mjs +138 -0
  70. package/bizar-dash/src/server/projects-store.mjs +364 -0
  71. package/bizar-dash/src/server/providers-store.mjs +789 -0
  72. package/bizar-dash/src/server/routes/_shared.mjs +415 -0
  73. package/bizar-dash/src/server/routes/activity.mjs +110 -0
  74. package/bizar-dash/src/server/routes/agents.mjs +134 -0
  75. package/bizar-dash/src/server/routes/artifacts.mjs +279 -0
  76. package/bizar-dash/src/server/routes/auth.mjs +69 -0
  77. package/bizar-dash/src/server/routes/background.mjs +165 -0
  78. package/bizar-dash/src/server/routes/chat.mjs +485 -0
  79. package/bizar-dash/src/server/routes/config.mjs +129 -0
  80. package/bizar-dash/src/server/routes/diagnostics.mjs +50 -0
  81. package/bizar-dash/src/server/routes/dialogs.mjs +86 -0
  82. package/bizar-dash/src/server/routes/fs.mjs +429 -0
  83. package/bizar-dash/src/server/routes/history.mjs +78 -0
  84. package/bizar-dash/src/server/routes/memory.mjs +658 -0
  85. package/bizar-dash/src/server/routes/misc.mjs +89 -0
  86. package/bizar-dash/src/server/routes/mods.mjs +359 -0
  87. package/bizar-dash/src/server/routes/notifications.mjs +54 -0
  88. package/bizar-dash/src/server/routes/obsidian.mjs +239 -0
  89. package/bizar-dash/src/server/routes/opencode-sessions.mjs +55 -0
  90. package/bizar-dash/src/server/routes/overview.mjs +91 -0
  91. package/bizar-dash/src/server/routes/pair.mjs +67 -0
  92. package/bizar-dash/src/server/routes/projects.mjs +175 -0
  93. package/bizar-dash/src/server/routes/providers.mjs +47 -0
  94. package/bizar-dash/src/server/routes/schedules.mjs +104 -0
  95. package/bizar-dash/src/server/routes/settings.mjs +51 -0
  96. package/bizar-dash/src/server/routes/skills.mjs +76 -0
  97. package/bizar-dash/src/server/routes/tasks.mjs +468 -0
  98. package/bizar-dash/src/server/routes/themes.mjs +51 -0
  99. package/bizar-dash/src/server/routes-v2/auth.mjs +59 -0
  100. package/bizar-dash/src/server/routes-v2/events.mjs +107 -0
  101. package/bizar-dash/src/server/routes-v2/health.mjs +21 -0
  102. package/bizar-dash/src/server/routes-v2/index.mjs +90 -0
  103. package/bizar-dash/src/server/routes-v2/sessions.mjs +111 -0
  104. package/bizar-dash/src/server/schedules-runner.mjs +369 -0
  105. package/bizar-dash/src/server/schedules-store.mjs +268 -0
  106. package/bizar-dash/src/server/search-store.mjs +220 -0
  107. package/bizar-dash/src/server/serve-info.mjs +684 -0
  108. package/bizar-dash/src/server/server.mjs +796 -0
  109. package/bizar-dash/src/server/settings-store.mjs +45 -0
  110. package/bizar-dash/src/server/skills-store.mjs +300 -0
  111. package/bizar-dash/src/server/state.mjs +437 -0
  112. package/bizar-dash/src/server/tailscale-store.mjs +113 -0
  113. package/bizar-dash/src/server/task-delegator.mjs +824 -0
  114. package/bizar-dash/src/server/tasks-store.mjs +508 -0
  115. package/bizar-dash/src/server/tui.mjs +923 -0
  116. package/bizar-dash/src/server/update-store.mjs +168 -0
  117. package/bizar-dash/src/server/v2-auth-file.mjs +99 -0
  118. package/bizar-dash/src/server/v2-event-bus.mjs +128 -0
  119. package/bizar-dash/src/server/watcher.mjs +81 -0
  120. package/bizar-dash/src/server/yaml.mjs +238 -0
  121. package/bizar-dash/src/web/App.tsx +718 -0
  122. package/bizar-dash/src/web/MobileApp.tsx +408 -0
  123. package/bizar-dash/src/web/components/ArtifactCreateDialog.tsx +95 -0
  124. package/bizar-dash/src/web/components/ArtifactListDialog.tsx +55 -0
  125. package/bizar-dash/src/web/components/ArtifactViewer.tsx +143 -0
  126. package/bizar-dash/src/web/components/AuditDialog.tsx +79 -0
  127. package/bizar-dash/src/web/components/BgStatusBadge.tsx +32 -0
  128. package/bizar-dash/src/web/components/Button.tsx +56 -0
  129. package/bizar-dash/src/web/components/CanvasContextMenu.tsx +68 -0
  130. package/bizar-dash/src/web/components/Card.tsx +40 -0
  131. package/bizar-dash/src/web/components/CollapsibleSection.tsx +72 -0
  132. package/bizar-dash/src/web/components/CommandDialog.tsx +66 -0
  133. package/bizar-dash/src/web/components/EmptyState.tsx +30 -0
  134. package/bizar-dash/src/web/components/FileBrowser.tsx +633 -0
  135. package/bizar-dash/src/web/components/HelpDialog.tsx +55 -0
  136. package/bizar-dash/src/web/components/KillConfirmDialog.tsx +88 -0
  137. package/bizar-dash/src/web/components/Modal.tsx +215 -0
  138. package/bizar-dash/src/web/components/Notifications.tsx +241 -0
  139. package/bizar-dash/src/web/components/SearchModal.tsx +224 -0
  140. package/bizar-dash/src/web/components/Sidebar.tsx +66 -0
  141. package/bizar-dash/src/web/components/Spinner.tsx +19 -0
  142. package/bizar-dash/src/web/components/StatusBadge.tsx +25 -0
  143. package/bizar-dash/src/web/components/Tag.tsx +28 -0
  144. package/bizar-dash/src/web/components/Toast.tsx +150 -0
  145. package/bizar-dash/src/web/components/Topbar.tsx +368 -0
  146. package/bizar-dash/src/web/components/VisualPlanDialog.tsx +58 -0
  147. package/bizar-dash/src/web/components/chat/AgentChip.tsx +68 -0
  148. package/bizar-dash/src/web/components/chat/ChatBubble.tsx +60 -0
  149. package/bizar-dash/src/web/components/chat/ChatThread.tsx +88 -0
  150. package/bizar-dash/src/web/components/chat/ChatTopBar.tsx +50 -0
  151. package/bizar-dash/src/web/components/chat/Composer.tsx +164 -0
  152. package/bizar-dash/src/web/components/chat/ConfirmModal.tsx +54 -0
  153. package/bizar-dash/src/web/components/chat/EmptyState.tsx +21 -0
  154. package/bizar-dash/src/web/components/chat/FirstRunGreeting.tsx +18 -0
  155. package/bizar-dash/src/web/components/chat/FloatingComposer.tsx +32 -0
  156. package/bizar-dash/src/web/components/chat/InfoPanel.tsx +119 -0
  157. package/bizar-dash/src/web/components/chat/LoadingSkeleton.tsx +19 -0
  158. package/bizar-dash/src/web/components/chat/MessageBubble.tsx +60 -0
  159. package/bizar-dash/src/web/components/chat/SessionList.tsx +153 -0
  160. package/bizar-dash/src/web/components/chat/StreamingIndicator.tsx +9 -0
  161. package/bizar-dash/src/web/components/chat/SuggestionCards.tsx +55 -0
  162. package/bizar-dash/src/web/components/chat/WelcomeScreen.tsx +36 -0
  163. package/bizar-dash/src/web/components/chat/index.ts +20 -0
  164. package/bizar-dash/src/web/components/chat/useAutoGrowTextarea.ts +18 -0
  165. package/bizar-dash/src/web/components/chat/useChat.ts +219 -0
  166. package/bizar-dash/src/web/components/chat/useSlashCommands.ts +47 -0
  167. package/bizar-dash/src/web/index.html +37 -0
  168. package/bizar-dash/src/web/lib/api.ts +193 -0
  169. package/bizar-dash/src/web/lib/markdown.tsx +59 -0
  170. package/bizar-dash/src/web/lib/types.ts +668 -0
  171. package/bizar-dash/src/web/lib/utils.ts +114 -0
  172. package/bizar-dash/src/web/lib/ws.ts +176 -0
  173. package/bizar-dash/src/web/main.tsx +34 -0
  174. package/bizar-dash/src/web/mobile/MobileApp.tsx +278 -0
  175. package/bizar-dash/src/web/mobile/MobileBottomNav.tsx +38 -0
  176. package/bizar-dash/src/web/mobile/MobileTopbar.tsx +115 -0
  177. package/bizar-dash/src/web/mobile/components/MobileBottomSheet.tsx +182 -0
  178. package/bizar-dash/src/web/mobile/components/MobileListItem.tsx +64 -0
  179. package/bizar-dash/src/web/mobile/components/MobileModal.tsx +123 -0
  180. package/bizar-dash/src/web/mobile/views/MobileActivity.tsx +273 -0
  181. package/bizar-dash/src/web/mobile/views/MobileAgents.tsx +374 -0
  182. package/bizar-dash/src/web/mobile/views/MobileArtifactCanvas.tsx +439 -0
  183. package/bizar-dash/src/web/mobile/views/MobileArtifacts.tsx +143 -0
  184. package/bizar-dash/src/web/mobile/views/MobileChat.tsx +180 -0
  185. package/bizar-dash/src/web/mobile/views/MobileConfig.tsx +175 -0
  186. package/bizar-dash/src/web/mobile/views/MobileHistory.tsx +191 -0
  187. package/bizar-dash/src/web/mobile/views/MobileMods.tsx +149 -0
  188. package/bizar-dash/src/web/mobile/views/MobileMore.tsx +121 -0
  189. package/bizar-dash/src/web/mobile/views/MobileNotifications.tsx +137 -0
  190. package/bizar-dash/src/web/mobile/views/MobilePlans.tsx +26 -0
  191. package/bizar-dash/src/web/mobile/views/MobileSchedules.tsx +685 -0
  192. package/bizar-dash/src/web/mobile/views/MobileSearchModal.tsx +172 -0
  193. package/bizar-dash/src/web/mobile/views/MobileSettings.tsx +388 -0
  194. package/bizar-dash/src/web/mobile/views/MobileSkills.tsx +153 -0
  195. package/bizar-dash/src/web/mobile/views/MobileTasks.tsx +564 -0
  196. package/bizar-dash/src/web/mobile.html +20 -0
  197. package/bizar-dash/src/web/mobile.tsx +13 -0
  198. package/bizar-dash/src/web/styles/chat.css +198 -0
  199. package/bizar-dash/src/web/styles/glyphs.css +960 -0
  200. package/bizar-dash/src/web/styles/main.css +8855 -0
  201. package/bizar-dash/src/web/styles/mobile-chat.css +5 -0
  202. package/bizar-dash/src/web/styles/mobile.css +1960 -0
  203. package/bizar-dash/src/web/views/Activity.tsx +1203 -0
  204. package/bizar-dash/src/web/views/Agents.tsx +701 -0
  205. package/bizar-dash/src/web/views/Artifacts.tsx +1480 -0
  206. package/bizar-dash/src/web/views/BackgroundAgents.tsx +450 -0
  207. package/bizar-dash/src/web/views/Chat.tsx +190 -0
  208. package/bizar-dash/src/web/views/Config.tsx +2063 -0
  209. package/bizar-dash/src/web/views/History.tsx +335 -0
  210. package/bizar-dash/src/web/views/ModView.tsx +207 -0
  211. package/bizar-dash/src/web/views/Mods.tsx +693 -0
  212. package/bizar-dash/src/web/views/Overview.tsx +812 -0
  213. package/bizar-dash/src/web/views/Providers.tsx +302 -0
  214. package/bizar-dash/src/web/views/Schedules.tsx +802 -0
  215. package/bizar-dash/src/web/views/Settings.tsx +1787 -0
  216. package/bizar-dash/src/web/views/Skills.tsx +431 -0
  217. package/bizar-dash/src/web/views/Tasks.tsx +1523 -0
  218. package/bizar-dash/src/web/views/glyphs/GlyphRenderer.tsx +613 -0
  219. package/bizar-dash/src/web/views/glyphs/components.tsx +1098 -0
  220. package/bizar-dash/templates/mod/FORMAT.md +76 -0
  221. package/bizar-dash/templates/mod/hello-mod/README.md +19 -0
  222. package/bizar-dash/templates/mod/hello-mod/agents/greeter.md +8 -0
  223. package/bizar-dash/templates/mod/hello-mod/commands/hello.md +6 -0
  224. package/bizar-dash/templates/mod/hello-mod/mod.json +20 -0
  225. package/bizar-dash/templates/mod/hello-mod/routes/ping.mjs +9 -0
  226. package/bizar-dash/templates/mod/hello-mod/views/HelloView.tsx +10 -0
  227. package/bizar-dash/tests/dashboard-ports.test.mjs +138 -0
  228. package/bizar-dash/tests/graphify-mod-spawn.node.test.mjs +90 -0
  229. package/bizar-dash/tests/memory-cli.test.mjs +542 -0
  230. package/bizar-dash/tests/memory-config.test.mjs +422 -0
  231. package/bizar-dash/tests/memory-git.test.mjs +246 -0
  232. package/bizar-dash/tests/memory-lightrag.test.mjs +153 -0
  233. package/bizar-dash/tests/memory-protocol-drift.test.mjs +45 -0
  234. package/bizar-dash/tests/memory-schema.test.mjs +198 -0
  235. package/bizar-dash/tests/memory-secrets.test.mjs +121 -0
  236. package/bizar-dash/tests/memory-store.test.mjs +390 -0
  237. package/bizar-dash/tests/memory-sync.test.mjs +141 -0
  238. package/bizar-dash/tests/mod-instructions.node.test.mjs +188 -0
  239. package/bizar-dash/tests/mod-security.test.mjs +273 -0
  240. package/bizar-dash/tests/mod-upgrade.node.test.mjs +357 -0
  241. package/bizar-dash/tests/no-agent-browser.node.test.mjs +98 -0
  242. package/bizar-dash/tests/obsidian-back-compat.test.mjs +199 -0
  243. package/bizar-dash/tests/opencode-runner.test.mjs +172 -0
  244. package/bizar-dash/tests/path-safe.test.mjs +108 -0
  245. package/bizar-dash/tests/providers-store-backup-keys.node.test.mjs +333 -0
  246. package/bizar-dash/tests/smoke-v2.mjs +212 -0
  247. package/bizar-dash/tests/strip-thinking.test.mjs +175 -0
  248. package/bizar-dash/tests/submit-feedback.test.mjs +353 -0
  249. package/bizar-dash/tests/tmux-wrap.test.mjs +145 -0
  250. package/bizar-dash/tests/yaml.test.mjs +128 -0
  251. package/bizar-dash/tsconfig.json +23 -0
  252. package/bizar-dash/vite.config.ts +27 -0
  253. package/cli/atomic.mjs +73 -0
  254. package/cli/banner.mjs +1 -1
  255. package/cli/bin.mjs +44 -47
  256. package/cli/bootstrap.mjs +1 -1
  257. package/cli/copy.mjs +25 -16
  258. package/cli/dev-link.mjs +17 -1
  259. package/cli/doctor.mjs +4 -4
  260. package/cli/doctor.test.mjs +2 -2
  261. package/cli/init.mjs +135 -1
  262. package/cli/install.mjs +31 -39
  263. package/cli/memory-constants.mjs +59 -0
  264. package/cli/memory.mjs +1436 -0
  265. package/cli/service.mjs +5 -6
  266. package/cli/utils.mjs +6 -3
  267. package/config/AGENTS.md +7 -7
  268. package/config/agents/_shared/AGENT_BASELINE.md +59 -61
  269. package/config/opencode.json +13 -38
  270. package/config/skills/memory-protocol/SKILL.md +105 -0
  271. package/config/skills/obsidian/SKILL.md +270 -65
  272. package/install.sh +59 -19
  273. package/package.json +49 -14
  274. package/packages/sdk/LICENSE +21 -0
  275. package/packages/sdk/README.md +80 -0
  276. package/packages/sdk/src/client.ts +183 -0
  277. package/packages/sdk/src/errors.ts +120 -0
  278. package/packages/sdk/src/events.ts +153 -0
  279. package/packages/sdk/src/index.ts +63 -0
  280. package/packages/sdk/src/types.ts +176 -0
  281. package/packages/sdk/src/version.ts +4 -0
  282. package/packages/sdk/tests/client.test.ts +217 -0
  283. package/packages/sdk/tests/errors.test.ts +108 -0
  284. package/packages/sdk/tests/events.test.ts +139 -0
  285. package/packages/sdk/tests/fixtures/fetch-mock.ts +152 -0
  286. package/packages/sdk/tests/fixtures/sse-mock.ts +30 -0
  287. package/packages/sdk/tsconfig.json +25 -0
  288. package/packages/sdk/vitest.config.ts +9 -0
  289. package/plugins/bizar/LICENSE +21 -0
  290. package/plugins/bizar/README.md +448 -0
  291. package/plugins/bizar/dist/index.js +29901 -0
  292. package/plugins/bizar/index.ts +1491 -0
  293. package/plugins/bizar/scripts/check-forbidden-imports.sh +33 -0
  294. package/plugins/bizar/src/background-state.ts +551 -0
  295. package/plugins/bizar/src/background.ts +1250 -0
  296. package/plugins/bizar/src/commands-impl.ts +464 -0
  297. package/plugins/bizar/src/commands.ts +1168 -0
  298. package/plugins/bizar/src/dashboard-client.ts +233 -0
  299. package/plugins/bizar/src/event-stream.ts +606 -0
  300. package/plugins/bizar/src/fingerprint.ts +120 -0
  301. package/plugins/bizar/src/handoff.ts +79 -0
  302. package/plugins/bizar/src/http-client.ts +467 -0
  303. package/plugins/bizar/src/key-rotation.ts +218 -0
  304. package/plugins/bizar/src/logger.ts +144 -0
  305. package/plugins/bizar/src/loop.ts +176 -0
  306. package/plugins/bizar/src/opencode-runner.ts +390 -0
  307. package/plugins/bizar/src/options.ts +421 -0
  308. package/plugins/bizar/src/plan-fs.ts +323 -0
  309. package/plugins/bizar/src/reasoning-clean.ts +454 -0
  310. package/plugins/bizar/src/report.ts +178 -0
  311. package/plugins/bizar/src/research-prompt.ts +35 -0
  312. package/plugins/bizar/src/serve-info.ts +228 -0
  313. package/plugins/bizar/src/serve.ts +496 -0
  314. package/plugins/bizar/src/settings.ts +349 -0
  315. package/plugins/bizar/src/state.ts +298 -0
  316. package/plugins/bizar/src/tools/bg-collect.ts +104 -0
  317. package/plugins/bizar/src/tools/bg-get-comments.ts +239 -0
  318. package/plugins/bizar/src/tools/bg-kill.ts +87 -0
  319. package/plugins/bizar/src/tools/bg-spawn.ts +401 -0
  320. package/plugins/bizar/src/tools/bg-status.ts +99 -0
  321. package/plugins/bizar/src/tools/open-kb.ts +191 -0
  322. package/plugins/bizar/src/tools/plan-action.ts +767 -0
  323. package/plugins/bizar/src/tools/read-glyph-feedback.ts +170 -0
  324. package/plugins/bizar/src/tools/wait-for-feedback.ts +402 -0
  325. package/plugins/bizar/tests/attach-handler-bug.test.ts +169 -0
  326. package/plugins/bizar/tests/background-state.test.ts +277 -0
  327. package/plugins/bizar/tests/background.test.ts +402 -0
  328. package/plugins/bizar/tests/block.test.ts +195 -0
  329. package/plugins/bizar/tests/canonical-key-order.test.ts +75 -0
  330. package/plugins/bizar/tests/commands-impl.test.ts +442 -0
  331. package/plugins/bizar/tests/commands.test.ts +584 -0
  332. package/plugins/bizar/tests/config.test.ts +122 -0
  333. package/plugins/bizar/tests/dashboard-client.test.ts +159 -0
  334. package/plugins/bizar/tests/dispose.test.ts +336 -0
  335. package/plugins/bizar/tests/event-stream.test.ts +409 -0
  336. package/plugins/bizar/tests/event.test.ts +262 -0
  337. package/plugins/bizar/tests/fingerprint.test.ts +162 -0
  338. package/plugins/bizar/tests/http-client.test.ts +404 -0
  339. package/plugins/bizar/tests/init-helpers.test.ts +203 -0
  340. package/plugins/bizar/tests/integration/slash-command.test.ts +348 -0
  341. package/plugins/bizar/tests/integration/tool-routing.test.ts +314 -0
  342. package/plugins/bizar/tests/key-rotation.test.ts +396 -0
  343. package/plugins/bizar/tests/loop.test.ts +397 -0
  344. package/plugins/bizar/tests/options.test.ts +276 -0
  345. package/plugins/bizar/tests/reasoning-clean.test.ts +422 -0
  346. package/plugins/bizar/tests/serve.test.ts +339 -0
  347. package/plugins/bizar/tests/settings.test.ts +351 -0
  348. package/plugins/bizar/tests/stall-think.test.ts +750 -0
  349. package/plugins/bizar/tests/state.test.ts +276 -0
  350. package/plugins/bizar/tests/tools/bg-collect.test.ts +337 -0
  351. package/plugins/bizar/tests/tools/bg-get-comments.test.ts +485 -0
  352. package/plugins/bizar/tests/tools/bg-kill.test.ts +235 -0
  353. package/plugins/bizar/tests/tools/bg-spawn-delegation.test.ts +147 -0
  354. package/plugins/bizar/tests/tools/bg-spawn.test.ts +311 -0
  355. package/plugins/bizar/tests/tools/bg-status.test.ts +217 -0
  356. package/plugins/bizar/tests/tools/opencode-runner.test.ts +115 -0
  357. package/plugins/bizar/tests/tools/plan-action.test.ts +599 -0
  358. package/plugins/bizar/tests/tools/read-glyph-feedback.test.ts +253 -0
  359. package/plugins/bizar/tests/tools/wait-for-feedback.test.ts +390 -0
  360. package/plugins/bizar/tests/update-deadlock.test.ts +145 -0
  361. package/plugins/bizar/tsconfig.json +29 -0
@@ -0,0 +1,148 @@
1
+ /**
2
+ * src/server/diagnostics-store.mjs
3
+ *
4
+ * v3.0.0 — Health check, version info, and last-N errors.
5
+ *
6
+ * Returns a single snapshot for the diagnostics card in the dashboard.
7
+ */
8
+ import { existsSync, readFileSync, statSync, readdirSync } from 'node:fs';
9
+ import { join, dirname } from 'node:path';
10
+ import { homedir } from 'node:os';
11
+ import { fileURLToPath } from 'node:url';
12
+ import { projectsStore } from './projects-store.mjs';
13
+ import { modsLoader } from './mods-loader.mjs';
14
+ import { agentsStore } from './agents-store.mjs';
15
+ import { providersStore, mcpsStore } from './providers-store.mjs';
16
+ import { tasksStore } from './tasks-store.mjs';
17
+ import { schedulesStore } from './schedules-store.mjs';
18
+
19
+ const HOME = homedir();
20
+ const SERVICE_LOG = join(HOME, '.config', 'bizar', 'service.log');
21
+ const SERVICE_PID = join(HOME, '.config', 'bizar', 'service.pid');
22
+ const DASH_PACKAGE_JSON = join(dirname(fileURLToPath(import.meta.url)), '..', '..', 'package.json');
23
+
24
+ const startedAt = Date.now();
25
+
26
+ function dashboardVersion() {
27
+ try {
28
+ return JSON.parse(readFileSync(DASH_PACKAGE_JSON, 'utf8'))?.version || '0.0.0';
29
+ } catch {
30
+ return '0.0.0';
31
+ }
32
+ }
33
+
34
+ function readRecentErrors() {
35
+ if (!existsSync(SERVICE_LOG)) return [];
36
+ try {
37
+ const text = readFileSync(SERVICE_LOG, 'utf8');
38
+ const lines = text.split(/\r?\n/);
39
+ const errors = [];
40
+ for (let i = lines.length - 1; i >= 0 && errors.length < 10; i--) {
41
+ const line = lines[i];
42
+ if (!line.trim()) continue;
43
+ if (/\b(failed|error|err)\b/i.test(line)) {
44
+ errors.push({ line, ts: parseLogTs(line) });
45
+ }
46
+ }
47
+ return errors;
48
+ } catch {
49
+ return [];
50
+ }
51
+ }
52
+
53
+ function parseLogTs(line) {
54
+ const m = /^\[([^\]]+)\]/.exec(line);
55
+ return m ? m[1] : null;
56
+ }
57
+
58
+ function checkPidAlive(pid) {
59
+ if (!pid) return false;
60
+ try {
61
+ process.kill(pid, 0);
62
+ return true;
63
+ } catch {
64
+ return false;
65
+ }
66
+ }
67
+
68
+ function serviceStatus() {
69
+ if (!existsSync(SERVICE_PID)) return { running: false };
70
+ try {
71
+ const pid = parseInt(readFileSync(SERVICE_PID, 'utf8').trim(), 10);
72
+ if (!Number.isFinite(pid)) return { running: false, error: 'bad PID file' };
73
+ const alive = checkPidAlive(pid);
74
+ return { running: alive, pid, pidFile: SERVICE_PID };
75
+ } catch (err) {
76
+ return { running: false, error: err.message };
77
+ }
78
+ }
79
+
80
+ export const diagnosticsStore = {
81
+ /** Build the full diagnostics snapshot. */
82
+ snapshot(extra = {}) {
83
+ const projects = projectsStore.list();
84
+ const active = projectsStore.active();
85
+ const tasks = active ? tasksStore.loadTasks(active.id) : [];
86
+ const schedules = active ? schedulesStore.list(active.id) : [];
87
+ return {
88
+ version: dashboardVersion(),
89
+ uptimeMs: Date.now() - startedAt,
90
+ uptime: Math.floor((Date.now() - startedAt) / 1000),
91
+ nodeVersion: process.version,
92
+ platform: process.platform,
93
+ memory: {
94
+ rss: process.memoryUsage().rss,
95
+ heapUsed: process.memoryUsage().heapUsed,
96
+ heapTotal: process.memoryUsage().heapTotal,
97
+ },
98
+ counts: {
99
+ agents: agentsStore.list().length,
100
+ plans: 0, // plans are not in our scope yet; leave at 0
101
+ tasks: tasks.length,
102
+ projects: projects.projects.length,
103
+ activeProject: active?.id || null,
104
+ mods: modsLoader.list().length,
105
+ schedules: schedules.length,
106
+ providers: providersStore.list().length,
107
+ mcps: mcpsStore.list().length,
108
+ },
109
+ errors: readRecentErrors(),
110
+ service: serviceStatus(),
111
+ ...extra,
112
+ };
113
+ },
114
+
115
+ /** Run a set of health checks and return per-subsystem status. */
116
+ health() {
117
+ const checks = [];
118
+ const projectsFile = projectsStore.PROJECTS_FILE;
119
+ checks.push({
120
+ name: 'projects-registry',
121
+ ok: existsSync(dirname(projectsFile)),
122
+ detail: dirname(projectsFile),
123
+ });
124
+ checks.push({
125
+ name: 'opencode-agents',
126
+ ok: existsSync(agentsStore.AGENTS_DIR),
127
+ detail: agentsStore.AGENTS_DIR,
128
+ });
129
+ checks.push({
130
+ name: 'opencode-config',
131
+ ok: existsSync(providersStore.OPENCODE_JSON),
132
+ detail: providersStore.OPENCODE_JSON,
133
+ });
134
+ const modsDir = modsLoader.MOD_DIR || modsLoader.MOD_DIR;
135
+ checks.push({
136
+ name: 'mods-dir',
137
+ ok: true, // the dir is auto-created; this is informational
138
+ detail: modsLoader.MOD_DIR || modsLoader.MOD_DIR,
139
+ });
140
+ return {
141
+ ts: new Date().toISOString(),
142
+ checks,
143
+ };
144
+ },
145
+ };
146
+
147
+ // Add MOD_DIR alias for older access
148
+ modsLoader.MOD_DIR = modsLoader.MOD_DIR || modsLoader.MODS_DIR;
@@ -0,0 +1,105 @@
1
+ /**
2
+ * src/server/dialog-poller.mjs
3
+ *
4
+ * v3.9.0 — Dialog-request poller.
5
+ *
6
+ * Mirrors the bg-poller pattern: the plugin writes dialog requests to
7
+ * `~/.cache/bizar/dialogs/*.json`; this poller scans every second,
8
+ * broadcasts each one as a `dialog:show` WS message, and removes the
9
+ * file once the broadcast is dispatched.
10
+ *
11
+ * The dashboard's Chat view (sibling scope — Thor) listens for
12
+ * `dialog:show` messages and mounts the dialog component keyed by
13
+ * `dialog.component`.
14
+ *
15
+ * Idempotency: a dialog is a one-shot event. As soon as the broadcast
16
+ * succeeds the file is deleted. If the WS layer is down (no clients
17
+ * connected), the dialog stays on disk and will be delivered on the
18
+ * next tick — at-least-once delivery is acceptable because the
19
+ * dashboard de-duplicates by `dialog.id`.
20
+ *
21
+ * WIRING: this module is loaded by the dashboard's `server.mjs` (sibling
22
+ * scope — Thor). It expects `server.mjs` to call
23
+ * `startDialogPoller()` once at startup. The `broadcast()` function
24
+ * is exported from `server.mjs`; we lazy-import it the same way
25
+ * `bg-poller.mjs` does to avoid a circular dep.
26
+ *
27
+ * v3.x service-mode gap: `cli/service.mjs` does NOT currently start
28
+ * the dialog poller. Service-only deployments will need to add
29
+ * `startDialogPoller()` to `cli/service.mjs` if they want slash-
30
+ * command dialogs to flow without a running dashboard.
31
+ */
32
+ import { dialogStore } from './dialog-store.mjs';
33
+
34
+ const POLL_INTERVAL_MS = 1_000;
35
+
36
+ let _interval = null;
37
+
38
+ async function broadcastDialog(dialog) {
39
+ try {
40
+ const { broadcast } = await import('./server.mjs');
41
+ broadcast({
42
+ type: 'dialog:show',
43
+ dialog: {
44
+ id: dialog.id,
45
+ title: dialog.title,
46
+ command: dialog.command,
47
+ component: dialog.component,
48
+ data: dialog.data,
49
+ },
50
+ });
51
+ } catch (err) {
52
+ console.error('[dialog-poller] broadcast failed:', err.message);
53
+ return false;
54
+ }
55
+ return true;
56
+ }
57
+
58
+ async function tick() {
59
+ let queue;
60
+ try {
61
+ queue = dialogStore.list();
62
+ } catch (err) {
63
+ console.error('[dialog-poller] list() failed:', err.message);
64
+ return;
65
+ }
66
+ if (!queue || queue.length === 0) return;
67
+ for (const dialog of queue) {
68
+ const ok = await broadcastDialog(dialog);
69
+ if (!ok) continue;
70
+ // We remove AFTER broadcast — never before. That way a crash in
71
+ // the WS layer doesn't permanently lose a dialog.
72
+ try {
73
+ dialogStore.remove(dialog.id);
74
+ } catch (err) {
75
+ console.error('[dialog-poller] remove failed:', err.message);
76
+ }
77
+ }
78
+ }
79
+
80
+ export function startDialogPoller() {
81
+ if (_interval) return; // idempotent
82
+ // Tick once immediately so any dialog queued before startup is
83
+ // delivered to the first WS client without waiting a full interval.
84
+ tick().catch((err) => console.error('[dialog-poller] initial tick:', err.message));
85
+ _interval = setInterval(() => {
86
+ tick().catch((err) => console.error('[dialog-poller] tick:', err.message));
87
+ }, POLL_INTERVAL_MS);
88
+ if (_interval && typeof _interval.unref === 'function') {
89
+ _interval.unref();
90
+ }
91
+ console.log(`[dialog-poller] started (interval=${POLL_INTERVAL_MS}ms)`);
92
+ }
93
+
94
+ export function stopDialogPoller() {
95
+ if (_interval) {
96
+ clearInterval(_interval);
97
+ _interval = null;
98
+ }
99
+ }
100
+
101
+ // Exposed for tests / introspection.
102
+ export const _pollerInternals = {
103
+ tick,
104
+ POLL_INTERVAL_MS,
105
+ };
@@ -0,0 +1,177 @@
1
+ /**
2
+ * src/server/dialog-store.mjs
3
+ *
4
+ * v3.9.0 — Persisted dialog-request store for the slash-command plugin
5
+ * bridge. Thor's sibling plugin writes dialog requests to disk here; the
6
+ * dialog poller picks them up and broadcasts each as a
7
+ * `{ type: 'dialog:show', dialog }` WS message.
8
+ *
9
+ * Storage:
10
+ * ~/.cache/bizar/dialogs/<iso-ts>-<rand>.json
11
+ *
12
+ * Each entry:
13
+ * { id, ts, title, command, component, data? }
14
+ *
15
+ * Each entry is a single one-shot event: the poller removes the file
16
+ * after the broadcast succeeds. There is no ack/retry — if the WS is
17
+ * offline, the dialog is still on disk and will be delivered on the
18
+ * next tick. Operators who care about delivery can poll
19
+ * GET /api/dialogs for recent history.
20
+ *
21
+ * WIRING: this module is intentionally READ-ONLY from the perspective
22
+ * of `server.mjs` — the file that mounts routes and starts the poller
23
+ * is owned by the slash-command sibling. See the header comment at the
24
+ * top of `routes/dialogs.mjs` for the exact wiring contract.
25
+ *
26
+ * v3.x service-mode gap: `cli/service.mjs` runs the schedule tick but
27
+ * does NOT currently start the dialog poller. The dialog poller lives
28
+ * in the dashboard server. Service-only deployments (no dashboard
29
+ * running) will silently drop dialog requests until a future PR wires
30
+ * the poller into `cli/service.mjs`.
31
+ */
32
+ import {
33
+ existsSync,
34
+ readFileSync,
35
+ writeFileSync,
36
+ renameSync,
37
+ mkdirSync,
38
+ readdirSync,
39
+ unlinkSync,
40
+ } from 'node:fs';
41
+ import { join } from 'node:path';
42
+ import { homedir } from 'node:os';
43
+ import { randomBytes } from 'node:crypto';
44
+
45
+ const HOME = homedir();
46
+ const DIALOG_DIR = join(HOME, '.cache', 'bizar', 'dialogs');
47
+
48
+ function ensureDir() {
49
+ try {
50
+ mkdirSync(DIALOG_DIR, { recursive: true });
51
+ } catch {
52
+ /* ignore — best-effort */
53
+ }
54
+ }
55
+
56
+ function safeReadJSON(file) {
57
+ try {
58
+ if (!existsSync(file)) return null;
59
+ const text = readFileSync(file, 'utf8');
60
+ if (!text.trim()) return null;
61
+ return JSON.parse(text);
62
+ } catch {
63
+ return null;
64
+ }
65
+ }
66
+
67
+ function genId() {
68
+ return `dlg_${Date.now().toString(36)}${randomBytes(3).toString('hex')}`;
69
+ }
70
+
71
+ /** Allow-list of dialog `component` keys. The dashboard mounts each key
72
+ * in the Chat view; unknown keys are accepted but logged. */
73
+ // NOTE: if you add a new DialogComponent to lib/types.ts or
74
+ // plugins/bizar/src/commands.ts, mirror it here so dialog-store
75
+ // doesn't warn on every dialog of that type.
76
+ const KNOWN_COMPONENTS = new Set([
77
+ 'visual-plan',
78
+ 'plan-create',
79
+ 'plan-list',
80
+ 'help',
81
+ 'audit',
82
+ 'generic',
83
+ ]);
84
+
85
+ export const dialogStore = {
86
+ DIALOG_DIR,
87
+
88
+ /**
89
+ * Append a dialog request. Returns the persisted descriptor.
90
+ * Caller is expected to provide at minimum `{ id, title, command,
91
+ * component }`. `id` is auto-generated when missing.
92
+ *
93
+ * @param {{ id?: string, title: string, command: string, component: string, data?: Record<string, unknown> }} input
94
+ */
95
+ add(input) {
96
+ ensureDir();
97
+ if (!input || typeof input !== 'object') {
98
+ throw new Error('dialog payload required');
99
+ }
100
+ const id = input.id || genId();
101
+ const component = String(input.component || '');
102
+ if (!KNOWN_COMPONENTS.has(component)) {
103
+ // Don't reject — the desktop UI may grow new dialog components
104
+ // before this list does. Log instead so the operator can spot it.
105
+ console.warn(`[dialog-store] unknown dialog component: ${component}`);
106
+ }
107
+ const dialog = {
108
+ id,
109
+ ts: new Date().toISOString(),
110
+ title: String(input.title || ''),
111
+ command: String(input.command || ''),
112
+ component,
113
+ data: input.data && typeof input.data === 'object' ? input.data : undefined,
114
+ };
115
+ const safeTs = dialog.ts.replace(/[:.]/g, '-');
116
+ const file = join(DIALOG_DIR, `${safeTs}-${randomBytes(3).toString('hex')}.json`);
117
+ const tmp = `${file}.tmp.${process.pid}`;
118
+ writeFileSync(tmp, JSON.stringify(dialog, null, 2) + '\n', 'utf8');
119
+ renameSync(tmp, file);
120
+ return dialog;
121
+ },
122
+
123
+ /** Read every queued dialog. Cheap on a phone — expected N is 0–5. */
124
+ list() {
125
+ ensureDir();
126
+ let files;
127
+ try {
128
+ files = readdirSync(DIALOG_DIR).filter((f) => f.endsWith('.json'));
129
+ } catch {
130
+ return [];
131
+ }
132
+ const out = [];
133
+ for (const f of files) {
134
+ const full = join(DIALOG_DIR, f);
135
+ const data = safeReadJSON(full);
136
+ if (data) {
137
+ out.push({ ...data, _file: full });
138
+ }
139
+ }
140
+ // Oldest first — the poller processes in order so the user sees
141
+ // dialogs in the same sequence the plugin emitted them.
142
+ out.sort((a, b) => (a.ts || '').localeCompare(b.ts || ''));
143
+ return out;
144
+ },
145
+
146
+ /**
147
+ * Remove a dialog by id. Returns true when a file was actually
148
+ * deleted (used by the poller after a successful broadcast).
149
+ *
150
+ * @param {string} id
151
+ */
152
+ remove(id) {
153
+ if (!id) return false;
154
+ ensureDir();
155
+ let files;
156
+ try {
157
+ files = readdirSync(DIALOG_DIR).filter((f) => f.endsWith('.json'));
158
+ } catch {
159
+ return false;
160
+ }
161
+ let removed = false;
162
+ for (const f of files) {
163
+ const full = join(DIALOG_DIR, f);
164
+ const data = safeReadJSON(full);
165
+ if (data && data.id === id) {
166
+ try {
167
+ unlinkSync(full);
168
+ removed = true;
169
+ } catch {
170
+ /* best-effort */
171
+ }
172
+ break;
173
+ }
174
+ }
175
+ return removed;
176
+ },
177
+ };