@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,364 @@
1
+ /**
2
+ * src/server/projects-store.mjs
3
+ *
4
+ * v3.0.0 — Per-project state registry.
5
+ *
6
+ * Project identification: the project's path basename (e.g.,
7
+ * `/home/user/myapp` → `myapp`). If the basename collides, the full path
8
+ * becomes the id.
9
+ *
10
+ * Storage:
11
+ * ~/.config/opencode/projects.json — registry (list + active id)
12
+ * ~/.config/opencode/projects/<id>/ — per-project data dir
13
+ * tasks.json, plans.json, schedules.json, mods.json, state.json,
14
+ * sessions/ (chat sessions)
15
+ *
16
+ * The bizar core runtime (bizar package) and the dashboard both call into
17
+ * this module. All file ops are defensive — missing files / parse errors
18
+ * are silent.
19
+ */
20
+ import {
21
+ existsSync,
22
+ readFileSync,
23
+ writeFileSync,
24
+ renameSync,
25
+ readdirSync,
26
+ statSync,
27
+ mkdirSync,
28
+ } from 'node:fs';
29
+ import { readdir as readdirAsync, stat as statAsync } from 'node:fs/promises';
30
+ import { join, basename, dirname, resolve as pathResolve } from 'node:path';
31
+ import { homedir } from 'node:os';
32
+ import { randomBytes } from 'node:crypto';
33
+
34
+ const HOME = homedir();
35
+ const OPENCODE_DIR = join(HOME, '.config', 'opencode');
36
+ const PROJECTS_FILE = join(OPENCODE_DIR, 'projects.json');
37
+ const PROJECTS_DIR = join(OPENCODE_DIR, 'projects');
38
+
39
+ /**
40
+ * v3.6.0 — Markers that identify a directory as a "project root".
41
+ *
42
+ * If a directory contains any of these (or the dotdir form of them),
43
+ * the scan treats it as a project and registers it. Kept in sync with
44
+ * the documentation shown in the Add Project dialog.
45
+ */
46
+ export const PROJECT_ROOT_MARKERS = [
47
+ '.git',
48
+ '.bizar',
49
+ 'package.json',
50
+ 'Cargo.toml',
51
+ 'pyproject.toml',
52
+ 'go.mod',
53
+ 'pom.xml',
54
+ 'build.gradle',
55
+ 'build.gradle.kts',
56
+ ];
57
+
58
+ function safeReadJSON(file, fallback = null) {
59
+ try {
60
+ if (!existsSync(file)) return fallback;
61
+ const text = readFileSync(file, 'utf8');
62
+ if (!text.trim()) return fallback;
63
+ return JSON.parse(text);
64
+ } catch {
65
+ return fallback;
66
+ }
67
+ }
68
+
69
+ function ensureProjectsDir() {
70
+ mkdirSync(PROJECTS_DIR, { recursive: true });
71
+ mkdirSync(OPENCODE_DIR, { recursive: true });
72
+ }
73
+
74
+ function atomicWriteJson(filePath, data) {
75
+ const tmp = `${filePath}.tmp.${process.pid}`;
76
+ writeFileSync(tmp, JSON.stringify(data, null, 2) + '\n', 'utf8');
77
+ renameSync(tmp, filePath);
78
+ }
79
+
80
+ function loadRegistry() {
81
+ const data = safeReadJSON(PROJECTS_FILE, null);
82
+ if (!data || typeof data !== 'object') {
83
+ return { projects: [], active: null };
84
+ }
85
+ if (!Array.isArray(data.projects)) data.projects = [];
86
+ return data;
87
+ }
88
+
89
+ function saveRegistry(reg) {
90
+ ensureProjectsDir();
91
+ atomicWriteJson(PROJECTS_FILE, reg);
92
+ }
93
+
94
+ function projectIdFromPath(path) {
95
+ const b = basename(path);
96
+ return b || 'project';
97
+ }
98
+
99
+ function projectDir(id) {
100
+ return join(PROJECTS_DIR, id);
101
+ }
102
+
103
+ function readProjectFile(id, name, fallback) {
104
+ const file = join(projectDir(id), name);
105
+ return safeReadJSON(file, fallback);
106
+ }
107
+
108
+ function writeProjectFile(id, name, data) {
109
+ ensureProjectsDir();
110
+ const dir = projectDir(id);
111
+ mkdirSync(dir, { recursive: true });
112
+ atomicWriteJson(join(dir, name), data);
113
+ }
114
+
115
+ function uniqueProjectId(absPath, reg) {
116
+ const existingByPath = reg.projects.find((p) => p.path === absPath);
117
+ if (existingByPath?.id) return existingByPath.id;
118
+ const baseId = projectIdFromPath(absPath);
119
+ const same = reg.projects.find((p) => p.id === baseId);
120
+ if (!same || same.path === absPath) return baseId;
121
+ return `${baseId}-${randomBytes(3).toString('hex')}`;
122
+ }
123
+
124
+ /**
125
+ * Public API.
126
+ */
127
+ export const projectsStore = {
128
+ HOME,
129
+ OPENCODE_DIR,
130
+ PROJECTS_DIR,
131
+ PROJECTS_FILE,
132
+
133
+ /** Return the full registry. */
134
+ list() {
135
+ const reg = loadRegistry();
136
+ // Augment with disk status (active/inactive/error)
137
+ const out = (reg.projects || []).map((p) => {
138
+ let status = 'inactive';
139
+ if (p.path && existsSync(p.path)) {
140
+ status = p.id === reg.active ? 'active' : 'inactive';
141
+ } else if (p.path) {
142
+ status = 'error';
143
+ }
144
+ return { ...p, status };
145
+ });
146
+ return { projects: out, active: reg.active };
147
+ },
148
+
149
+ /** Add a project by absolute path. Returns the new project entry. */
150
+ add(path, name) {
151
+ if (!path || typeof path !== 'string') {
152
+ throw new Error('path is required');
153
+ }
154
+ const reg = loadRegistry();
155
+ const absPath = pathResolve(path);
156
+ const id = uniqueProjectId(absPath, reg);
157
+ const existing = reg.projects.find((p) => p.id === id);
158
+ const now = new Date().toISOString();
159
+ if (existing) {
160
+ existing.path = absPath;
161
+ existing.lastAccessed = now;
162
+ saveRegistry(reg);
163
+ return existing;
164
+ }
165
+ const entry = {
166
+ id,
167
+ name: name || id,
168
+ path: absPath,
169
+ lastAccessed: now,
170
+ status: 'inactive',
171
+ summary: '',
172
+ };
173
+ reg.projects.push(entry);
174
+ if (!reg.active) reg.active = id;
175
+ saveRegistry(reg);
176
+ // Make sure the per-project dir exists
177
+ ensureProjectsDir();
178
+ mkdirSync(projectDir(id), { recursive: true });
179
+ return entry;
180
+ },
181
+
182
+ /** Remove a project from the registry. Per-project data is NOT deleted. */
183
+ remove(id) {
184
+ const reg = loadRegistry();
185
+ reg.projects = reg.projects.filter((p) => p.id !== id);
186
+ if (reg.active === id) reg.active = reg.projects[0]?.id || null;
187
+ saveRegistry(reg);
188
+ return true;
189
+ },
190
+
191
+ /** Switch the active project. Returns the new active entry or null. */
192
+ activate(id) {
193
+ const reg = loadRegistry();
194
+ const found = reg.projects.find((p) => p.id === id);
195
+ if (!found) return null;
196
+ reg.active = id;
197
+ found.lastAccessed = new Date().toISOString();
198
+ saveRegistry(reg);
199
+ return found;
200
+ },
201
+
202
+ /** Get the active project entry, or null. */
203
+ active() {
204
+ const reg = loadRegistry();
205
+ return reg.projects.find((p) => p.id === reg.active) || null;
206
+ },
207
+
208
+ /** Touch the lastAccessed timestamp. */
209
+ touch(id) {
210
+ const reg = loadRegistry();
211
+ const found = reg.projects.find((p) => p.id === id);
212
+ if (found) {
213
+ found.lastAccessed = new Date().toISOString();
214
+ saveRegistry(reg);
215
+ }
216
+ },
217
+
218
+ /**
219
+ * v3.0.4 — Auto-detect the user's current working directory.
220
+ *
221
+ * If `cwd` is not already registered, add it. If no active project
222
+ * exists, set it as active. Idempotent: safe to call on every server
223
+ * startup, and safe to call multiple times.
224
+ *
225
+ * Returns the resulting active project entry, or null if `cwd` was
226
+ * not a string / could not be resolved.
227
+ */
228
+ autoDetect({ cwd } = {}) {
229
+ if (!cwd || typeof cwd !== 'string') return null;
230
+ const abs = pathResolve(cwd);
231
+ const reg = loadRegistry();
232
+ const id = uniqueProjectId(abs, reg);
233
+ const existing = reg.projects.find((p) => p.id === id);
234
+ const now = new Date().toISOString();
235
+ if (existing) {
236
+ // Keep the existing path/name in sync if the cwd moved, but
237
+ // do not stomp on a user-edited name.
238
+ existing.path = abs;
239
+ existing.lastAccessed = now;
240
+ // Don't change the active project — the user already chose one.
241
+ saveRegistry(reg);
242
+ return existing;
243
+ }
244
+ const entry = {
245
+ id,
246
+ name: basename(abs) || id,
247
+ path: abs,
248
+ lastAccessed: now,
249
+ status: 'inactive',
250
+ summary: '',
251
+ };
252
+ reg.projects.push(entry);
253
+ if (!reg.active) reg.active = id;
254
+ saveRegistry(reg);
255
+ // Make sure the per-project dir exists so the rest of the server
256
+ // can write to it without further checks.
257
+ ensureProjectsDir();
258
+ mkdirSync(projectDir(id), { recursive: true });
259
+ return entry;
260
+ },
261
+
262
+ /**
263
+ * v3.6.0 — Walk a directory and add any subdirectory that looks
264
+ * like a project root as a registered project. Idempotent: paths
265
+ * already in the registry are skipped silently.
266
+ *
267
+ * Detection: a directory is a "project root" if it contains any
268
+ * of `PROJECT_ROOT_MARKERS` (see the exported list at the top of
269
+ * this file). We do NOT recurse into a detected project — the
270
+ * scan is intentionally one level deep so a checked-out `node_modules`
271
+ * inside a project doesn't get re-registered.
272
+ *
273
+ * @param {string} rootDir
274
+ * @param {object} [opts]
275
+ * @param {number} [opts.maxDepth=1] — currently unused; reserved for future two-level scans.
276
+ * @returns {Promise<{ added: Array<{id: string, path: string, name: string}>, skipped: number, scanned: number, error?: string }>}
277
+ */
278
+ async scanDirectory(rootDir, { maxDepth = 1 } = {}) {
279
+ const result = { added: [], skipped: 0, scanned: 0 };
280
+ if (!rootDir || typeof rootDir !== 'string') {
281
+ result.error = 'rootDir must be a non-empty string';
282
+ return result;
283
+ }
284
+ void maxDepth; // Reserved for future two-level scans.
285
+ const absRoot = pathResolve(rootDir);
286
+
287
+ try {
288
+ // Confirm the root is a directory before reading its children.
289
+ const rootStat = await statAsync(absRoot);
290
+ if (!rootStat || !rootStat.isDirectory()) {
291
+ result.error = 'rootDir is not a directory';
292
+ return result;
293
+ }
294
+
295
+ const children = await readdirAsync(absRoot, { withFileTypes: true });
296
+ for (const child of children) {
297
+ // Only descend into directories. Skip symlinks so we don't
298
+ // accidentally pull in something outside the configured root.
299
+ if (!child.isDirectory() || child.isSymbolicLink()) continue;
300
+ result.scanned += 1;
301
+ const childPath = pathResolve(absRoot, child.name);
302
+
303
+ // Check for any project-root marker. Stat each one in a
304
+ // try/catch so a single permission error doesn't sink the
305
+ // entire scan.
306
+ let isProject = false;
307
+ for (const marker of PROJECT_ROOT_MARKERS) {
308
+ try {
309
+ const s = await statAsync(pathResolve(childPath, marker));
310
+ if (s && (s.isDirectory() || s.isFile())) {
311
+ isProject = true;
312
+ break;
313
+ }
314
+ } catch {
315
+ // ENOENT / EACCES / EPERM on the marker — keep looking.
316
+ }
317
+ }
318
+ if (!isProject) continue;
319
+
320
+ try {
321
+ // Snapshot the registry *before* `add()` so we can tell
322
+ // whether the entry already existed. The existing add()
323
+ // doesn't expose this distinction (it always bumps
324
+ // lastAccessed), so we have to peek.
325
+ const before = loadRegistry();
326
+ const existed = before.projects.some(
327
+ (p) => p.path === childPath || p.id === basename(childPath),
328
+ );
329
+ const entry = this.add(childPath);
330
+ if (existed) {
331
+ result.skipped += 1;
332
+ } else {
333
+ result.added.push({ id: entry.id, path: entry.path, name: entry.name });
334
+ }
335
+ } catch {
336
+ // `add()` throws only on truly invalid input. Don't fail
337
+ // the whole scan — count and continue.
338
+ result.skipped += 1;
339
+ }
340
+ }
341
+ } catch (err) {
342
+ result.error = (err && err.message) || String(err);
343
+ }
344
+ return result;
345
+ },
346
+
347
+ /** Per-project file helpers. */
348
+ readProjectFile,
349
+ writeProjectFile,
350
+ projectDir,
351
+
352
+ /** Return path to the per-project data dir; ensure it exists. */
353
+ ensureProjectDir(id) {
354
+ ensureProjectsDir();
355
+ const dir = projectDir(id);
356
+ mkdirSync(dir, { recursive: true });
357
+ return dir;
358
+ },
359
+
360
+ /** Generate a short random id with prefix. */
361
+ genId(prefix = 'id') {
362
+ return prefix + '_' + randomBytes(6).toString('hex').slice(0, 10);
363
+ },
364
+ };