@voybio/ace-swarm 0.1.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 (334) hide show
  1. package/CHANGELOG.md +109 -0
  2. package/LICENSE +186 -0
  3. package/README.md +229 -0
  4. package/assets/.agents/ACE/ACE-Init/AGENTS.md +210 -0
  5. package/assets/.agents/ACE/ACE-Init/instructions.md +118 -0
  6. package/assets/.agents/ACE/ACE_coders/AGENTS.md +154 -0
  7. package/assets/.agents/ACE/ACE_coders/INSTRUCTIONS.md +216 -0
  8. package/assets/.agents/ACE/AGENT_REGISTRY.md +70 -0
  9. package/assets/.agents/ACE/AGENT_REGISTRY_7.md +9 -0
  10. package/assets/.agents/ACE/DIRECTIVE_KERNEL.md +234 -0
  11. package/assets/.agents/ACE/UI/AGENTS.md +115 -0
  12. package/assets/.agents/ACE/UI/instructions.md +178 -0
  13. package/assets/.agents/ACE/VOS/ACE_VOS_MISSING_INFO_MATRIX.md +42 -0
  14. package/assets/.agents/ACE/VOS/AGENTS.md +72 -0
  15. package/assets/.agents/ACE/VOS/instructions.md +211 -0
  16. package/assets/.agents/ACE/agent-astgrep/AGENTS.md +123 -0
  17. package/assets/.agents/ACE/agent-astgrep/instructions.md +91 -0
  18. package/assets/.agents/ACE/agent-builder/AGENTS.md +172 -0
  19. package/assets/.agents/ACE/agent-builder/instructions.md +137 -0
  20. package/assets/.agents/ACE/agent-docs/AGENTS.md +159 -0
  21. package/assets/.agents/ACE/agent-docs/instructions.md +133 -0
  22. package/assets/.agents/ACE/agent-eval/AGENTS.md +46 -0
  23. package/assets/.agents/ACE/agent-eval/instructions.md +56 -0
  24. package/assets/.agents/ACE/agent-memory/AGENTS.md +49 -0
  25. package/assets/.agents/ACE/agent-memory/instructions.md +50 -0
  26. package/assets/.agents/ACE/agent-observability/AGENTS.md +46 -0
  27. package/assets/.agents/ACE/agent-observability/instructions.md +50 -0
  28. package/assets/.agents/ACE/agent-ops/AGENTS.md +201 -0
  29. package/assets/.agents/ACE/agent-ops/instructions.md +136 -0
  30. package/assets/.agents/ACE/agent-qa/AGENTS.md +189 -0
  31. package/assets/.agents/ACE/agent-qa/instructions.md +121 -0
  32. package/assets/.agents/ACE/agent-release/AGENTS.md +48 -0
  33. package/assets/.agents/ACE/agent-release/instructions.md +49 -0
  34. package/assets/.agents/ACE/agent-research/AGENTS.md +160 -0
  35. package/assets/.agents/ACE/agent-research/instructions.md +118 -0
  36. package/assets/.agents/ACE/agent-security/AGENTS.md +48 -0
  37. package/assets/.agents/ACE/agent-security/instructions.md +50 -0
  38. package/assets/.agents/ACE/agent-skeptic/AGENTS.md +178 -0
  39. package/assets/.agents/ACE/agent-skeptic/instructions.md +196 -0
  40. package/assets/.agents/ACE/agent-spec/AGENTS.md +169 -0
  41. package/assets/.agents/ACE/agent-spec/instructions.md +116 -0
  42. package/assets/.agents/ACE/orchestrator/AGENTS.md +365 -0
  43. package/assets/.agents/ACE/orchestrator/instructions.md +231 -0
  44. package/assets/.agents/skills/ace-orchestrator/SKILL.md +63 -0
  45. package/assets/.agents/skills/ace-orchestrator/references/engineering-bootstrap-playbook.md +360 -0
  46. package/assets/.agents/skills/astgrep-index/SKILL.md +58 -0
  47. package/assets/.agents/skills/codemunch/SKILL.md +65 -0
  48. package/assets/.agents/skills/codemunch/references/ast-driven-protocol.md +543 -0
  49. package/assets/.agents/skills/codesnipe/SKILL.md +64 -0
  50. package/assets/.agents/skills/codesnipe/references/dual-codebase-playbook.md +671 -0
  51. package/assets/.agents/skills/eval-harness/SKILL.md +203 -0
  52. package/assets/.agents/skills/handoff-lint/SKILL.md +164 -0
  53. package/assets/.agents/skills/incident-commander/SKILL.md +174 -0
  54. package/assets/.agents/skills/landing-review-watcher/SKILL.md +68 -0
  55. package/assets/.agents/skills/memory-curator/SKILL.md +179 -0
  56. package/assets/.agents/skills/problem-triage/SKILL.md +57 -0
  57. package/assets/.agents/skills/problem-triage/agents/openai.yaml +3 -0
  58. package/assets/.agents/skills/release-sentry/SKILL.md +189 -0
  59. package/assets/.agents/skills/risk-quant/SKILL.md +190 -0
  60. package/assets/.agents/skills/schema-forge/SKILL.md +174 -0
  61. package/assets/.agents/skills/skill-auditor/SKILL.md +52 -0
  62. package/assets/.agents/skills/state-auditor/SKILL.md +182 -0
  63. package/assets/.github/hooks/ace-copilot.json +68 -0
  64. package/assets/agent-state/ACE_WORKFLOW.md +131 -0
  65. package/assets/agent-state/ARTIFACT_MANIFEST.json +5 -0
  66. package/assets/agent-state/AST_GREP_COMMANDS.md +121 -0
  67. package/assets/agent-state/AST_GREP_INDEX.json +13 -0
  68. package/assets/agent-state/AST_GREP_INDEX.md +15 -0
  69. package/assets/agent-state/DECISIONS.md +7 -0
  70. package/assets/agent-state/EVIDENCE_LOG.md +7 -0
  71. package/assets/agent-state/HANDOFF.json +24 -0
  72. package/assets/agent-state/INTERFACE_REGISTRY.md +75 -0
  73. package/assets/agent-state/MODULES/gates/gate-autonomy.json +7 -0
  74. package/assets/agent-state/MODULES/gates/gate-completeness.json +7 -0
  75. package/assets/agent-state/MODULES/gates/gate-correctness.json +7 -0
  76. package/assets/agent-state/MODULES/gates/gate-evaluation.json +7 -0
  77. package/assets/agent-state/MODULES/gates/gate-operability.json +7 -0
  78. package/assets/agent-state/MODULES/gates/gate-security.json +7 -0
  79. package/assets/agent-state/MODULES/gates/gate-typescript-public-surface.json +7 -0
  80. package/assets/agent-state/MODULES/registry.json +41 -0
  81. package/assets/agent-state/MODULES/roles/capability-astgrep.json +49 -0
  82. package/assets/agent-state/MODULES/roles/capability-build.json +39 -0
  83. package/assets/agent-state/MODULES/roles/capability-docs.json +38 -0
  84. package/assets/agent-state/MODULES/roles/capability-eval.json +20 -0
  85. package/assets/agent-state/MODULES/roles/capability-memory.json +20 -0
  86. package/assets/agent-state/MODULES/roles/capability-observability.json +20 -0
  87. package/assets/agent-state/MODULES/roles/capability-ops.json +45 -0
  88. package/assets/agent-state/MODULES/roles/capability-qa.json +40 -0
  89. package/assets/agent-state/MODULES/roles/capability-release.json +21 -0
  90. package/assets/agent-state/MODULES/roles/capability-research.json +44 -0
  91. package/assets/agent-state/MODULES/roles/capability-security.json +21 -0
  92. package/assets/agent-state/MODULES/roles/capability-skeptic.json +48 -0
  93. package/assets/agent-state/MODULES/roles/capability-spec.json +42 -0
  94. package/assets/agent-state/MODULES/schemas/ACE_RUNTIME_PROFILE.schema.json +289 -0
  95. package/assets/agent-state/MODULES/schemas/ARTIFACT_MANIFEST.schema.json +185 -0
  96. package/assets/agent-state/MODULES/schemas/HANDOFF.agent-state.schema.json +124 -0
  97. package/assets/agent-state/MODULES/schemas/HANDOFF.schema.json +55 -0
  98. package/assets/agent-state/MODULES/schemas/RUNTIME_EXECUTOR_SESSION_REGISTRY.schema.json +290 -0
  99. package/assets/agent-state/MODULES/schemas/RUNTIME_TOOL_SPEC_REGISTRY.schema.json +144 -0
  100. package/assets/agent-state/MODULES/schemas/STATUS_EVENT.schema.json +84 -0
  101. package/assets/agent-state/MODULES/schemas/SWARM_HANDOFF.schema.json +138 -0
  102. package/assets/agent-state/MODULES/schemas/TRACKER_SNAPSHOT.schema.json +134 -0
  103. package/assets/agent-state/MODULES/schemas/VERICIFY_BRIDGE_SNAPSHOT.schema.json +157 -0
  104. package/assets/agent-state/MODULES/schemas/VERICIFY_PROCESS_POST_LOG.schema.json +93 -0
  105. package/assets/agent-state/MODULES/schemas/WORKSPACE_SESSION_REGISTRY.schema.json +133 -0
  106. package/assets/agent-state/PROVENANCE_LOG.md +28 -0
  107. package/assets/agent-state/QUALITY_GATES.md +15 -0
  108. package/assets/agent-state/RISKS.md +8 -0
  109. package/assets/agent-state/SCOPE.md +20 -0
  110. package/assets/agent-state/SKILL_CATALOG.md +48 -0
  111. package/assets/agent-state/STATUS.md +8 -0
  112. package/assets/agent-state/STATUS_EVENTS.ndjson +1 -0
  113. package/assets/agent-state/TASK.md +18 -0
  114. package/assets/agent-state/TEAL_CONFIG.md +117 -0
  115. package/assets/agent-state/handoff-registry.json +5 -0
  116. package/assets/agent-state/index-fingerprints.json +7 -0
  117. package/assets/agent-state/index.json +32 -0
  118. package/assets/agent-state/run-ledger.json +5 -0
  119. package/assets/agent-state/runtime-executor-sessions.json +5 -0
  120. package/assets/agent-state/runtime-tool-specs.json +5 -0
  121. package/assets/agent-state/runtime-workspaces.json +5 -0
  122. package/assets/agent-state/todo-state.json +7 -0
  123. package/assets/agent-state/tracker-snapshot.json +7 -0
  124. package/assets/agent-state/vericify/ace-bridge.json +60 -0
  125. package/assets/agent-state/vericify/process-posts.json +5 -0
  126. package/assets/instructions/ACE.instructions.md +187 -0
  127. package/assets/instructions/ACE_Coder.instructions.md +146 -0
  128. package/assets/instructions/ACE_UI.instructions.md +178 -0
  129. package/assets/instructions/ACE_VOS.instructions.md +211 -0
  130. package/assets/scripts/ace-hook-dispatch.mjs +538 -0
  131. package/assets/scripts/bootstrap-workspace.sh +27 -0
  132. package/assets/scripts/copilot-hook-dispatch.mjs +3 -0
  133. package/assets/scripts/eval-harness.sh +68 -0
  134. package/assets/scripts/render-mcp-configs.sh +396 -0
  135. package/assets/tasks/README.md +48 -0
  136. package/assets/tasks/SWARM_HANDOFF.example.json +53 -0
  137. package/assets/tasks/SWARM_HANDOFF.example_ui_to_coders.json +55 -0
  138. package/assets/tasks/SWARM_HANDOFF.example_vos_to_ui.json +55 -0
  139. package/assets/tasks/SWARM_HANDOFF.template.json +52 -0
  140. package/assets/tasks/cli_work_split.md +22 -0
  141. package/assets/tasks/lessons.md +17 -0
  142. package/assets/tasks/role_tasks.md +206 -0
  143. package/assets/tasks/todo.md +23 -0
  144. package/dist/ace-autonomy.d.ts +137 -0
  145. package/dist/ace-autonomy.js +472 -0
  146. package/dist/ace-context.d.ts +29 -0
  147. package/dist/ace-context.js +240 -0
  148. package/dist/ace-internal-tools.d.ts +8 -0
  149. package/dist/ace-internal-tools.js +76 -0
  150. package/dist/ace-server-instructions.d.ts +12 -0
  151. package/dist/ace-server-instructions.js +324 -0
  152. package/dist/agent-runtime/role-adapters.d.ts +29 -0
  153. package/dist/agent-runtime/role-adapters.js +573 -0
  154. package/dist/astgrep-index.d.ts +24 -0
  155. package/dist/astgrep-index.js +476 -0
  156. package/dist/cli.d.ts +3 -0
  157. package/dist/cli.js +591 -0
  158. package/dist/git-ops.d.ts +53 -0
  159. package/dist/git-ops.js +238 -0
  160. package/dist/handoff-registry.d.ts +71 -0
  161. package/dist/handoff-registry.js +422 -0
  162. package/dist/helpers.d.ts +126 -0
  163. package/dist/helpers.js +1687 -0
  164. package/dist/index-store.d.ts +51 -0
  165. package/dist/index-store.js +328 -0
  166. package/dist/index.d.ts +3 -0
  167. package/dist/index.js +7 -0
  168. package/dist/internal-tool-runtime.d.ts +21 -0
  169. package/dist/internal-tool-runtime.js +136 -0
  170. package/dist/job-scheduler.d.ts +175 -0
  171. package/dist/job-scheduler.js +1217 -0
  172. package/dist/kanban.d.ts +27 -0
  173. package/dist/kanban.js +339 -0
  174. package/dist/local-model-runtime.d.ts +40 -0
  175. package/dist/local-model-runtime.js +174 -0
  176. package/dist/model-bridge.d.ts +54 -0
  177. package/dist/model-bridge.js +587 -0
  178. package/dist/orchestrator-supervisor.d.ts +100 -0
  179. package/dist/orchestrator-supervisor.js +399 -0
  180. package/dist/problem-triage.d.ts +23 -0
  181. package/dist/problem-triage.js +448 -0
  182. package/dist/prompts.d.ts +7 -0
  183. package/dist/prompts.js +628 -0
  184. package/dist/public-surface.d.ts +30 -0
  185. package/dist/public-surface.js +316 -0
  186. package/dist/resources.d.ts +7 -0
  187. package/dist/resources.js +545 -0
  188. package/dist/run-ledger.d.ts +36 -0
  189. package/dist/run-ledger.js +257 -0
  190. package/dist/runtime-command.d.ts +18 -0
  191. package/dist/runtime-command.js +76 -0
  192. package/dist/runtime-executor.d.ts +104 -0
  193. package/dist/runtime-executor.js +985 -0
  194. package/dist/runtime-profile.d.ts +116 -0
  195. package/dist/runtime-profile.js +532 -0
  196. package/dist/runtime-tool-specs.d.ts +68 -0
  197. package/dist/runtime-tool-specs.js +527 -0
  198. package/dist/safe-edit.d.ts +52 -0
  199. package/dist/safe-edit.js +255 -0
  200. package/dist/schemas.d.ts +44 -0
  201. package/dist/schemas.js +830 -0
  202. package/dist/semantic-cache.d.ts +147 -0
  203. package/dist/semantic-cache.js +552 -0
  204. package/dist/semantic-hash.d.ts +83 -0
  205. package/dist/semantic-hash.js +346 -0
  206. package/dist/server.d.ts +10 -0
  207. package/dist/server.js +46 -0
  208. package/dist/shared.d.ts +136 -0
  209. package/dist/shared.js +269 -0
  210. package/dist/skill-auditor.d.ts +26 -0
  211. package/dist/skill-auditor.js +184 -0
  212. package/dist/skill-catalog.d.ts +60 -0
  213. package/dist/skill-catalog.js +305 -0
  214. package/dist/status-events.d.ts +40 -0
  215. package/dist/status-events.js +269 -0
  216. package/dist/store/ace-packed-store.d.ts +69 -0
  217. package/dist/store/ace-packed-store.js +434 -0
  218. package/dist/store/bootstrap-store.d.ts +46 -0
  219. package/dist/store/bootstrap-store.js +242 -0
  220. package/dist/store/catalog-builder.d.ts +21 -0
  221. package/dist/store/catalog-builder.js +68 -0
  222. package/dist/store/importer.d.ts +19 -0
  223. package/dist/store/importer.js +157 -0
  224. package/dist/store/knowledge-bake.d.ts +59 -0
  225. package/dist/store/knowledge-bake.js +339 -0
  226. package/dist/store/materializers/hook-context-materializer.d.ts +25 -0
  227. package/dist/store/materializers/hook-context-materializer.js +100 -0
  228. package/dist/store/materializers/host-file-materializer.d.ts +37 -0
  229. package/dist/store/materializers/host-file-materializer.js +271 -0
  230. package/dist/store/materializers/todo-syncer.d.ts +30 -0
  231. package/dist/store/materializers/todo-syncer.js +140 -0
  232. package/dist/store/materializers/vericify-projector.d.ts +38 -0
  233. package/dist/store/materializers/vericify-projector.js +239 -0
  234. package/dist/store/repositories/discovery-repository.d.ts +24 -0
  235. package/dist/store/repositories/discovery-repository.js +58 -0
  236. package/dist/store/repositories/handoff-repository.d.ts +31 -0
  237. package/dist/store/repositories/handoff-repository.js +67 -0
  238. package/dist/store/repositories/ledger-repository.d.ts +26 -0
  239. package/dist/store/repositories/ledger-repository.js +49 -0
  240. package/dist/store/repositories/runtime-kv-repository.d.ts +16 -0
  241. package/dist/store/repositories/runtime-kv-repository.js +36 -0
  242. package/dist/store/repositories/scheduler-repository.d.ts +50 -0
  243. package/dist/store/repositories/scheduler-repository.js +123 -0
  244. package/dist/store/repositories/session-repository.d.ts +33 -0
  245. package/dist/store/repositories/session-repository.js +82 -0
  246. package/dist/store/repositories/todo-repository.d.ts +31 -0
  247. package/dist/store/repositories/todo-repository.js +77 -0
  248. package/dist/store/repositories/tracker-repository.d.ts +25 -0
  249. package/dist/store/repositories/tracker-repository.js +43 -0
  250. package/dist/store/repositories/vericify-repository.d.ts +32 -0
  251. package/dist/store/repositories/vericify-repository.js +58 -0
  252. package/dist/store/skills-install.d.ts +28 -0
  253. package/dist/store/skills-install.js +86 -0
  254. package/dist/store/state-reader.d.ts +49 -0
  255. package/dist/store/state-reader.js +111 -0
  256. package/dist/store/store-artifacts.d.ts +12 -0
  257. package/dist/store/store-artifacts.js +138 -0
  258. package/dist/store/store-snapshot.d.ts +19 -0
  259. package/dist/store/store-snapshot.js +140 -0
  260. package/dist/store/topology-bake.d.ts +15 -0
  261. package/dist/store/topology-bake.js +215 -0
  262. package/dist/store/types.d.ts +155 -0
  263. package/dist/store/types.js +35 -0
  264. package/dist/store/workspace-snapshot.d.ts +26 -0
  265. package/dist/store/workspace-snapshot.js +107 -0
  266. package/dist/store/write-queue.d.ts +7 -0
  267. package/dist/store/write-queue.js +26 -0
  268. package/dist/todo-state.d.ts +41 -0
  269. package/dist/todo-state.js +399 -0
  270. package/dist/tools-agent.d.ts +7 -0
  271. package/dist/tools-agent.js +1542 -0
  272. package/dist/tools-discovery.d.ts +6 -0
  273. package/dist/tools-discovery.js +178 -0
  274. package/dist/tools-drift.d.ts +13 -0
  275. package/dist/tools-drift.js +357 -0
  276. package/dist/tools-files.d.ts +6 -0
  277. package/dist/tools-files.js +679 -0
  278. package/dist/tools-framework.d.ts +7 -0
  279. package/dist/tools-framework.js +1414 -0
  280. package/dist/tools-git.d.ts +6 -0
  281. package/dist/tools-git.js +183 -0
  282. package/dist/tools-handoff.d.ts +32 -0
  283. package/dist/tools-handoff.js +489 -0
  284. package/dist/tools-lifecycle.d.ts +6 -0
  285. package/dist/tools-lifecycle.js +205 -0
  286. package/dist/tools-memory.d.ts +6 -0
  287. package/dist/tools-memory.js +260 -0
  288. package/dist/tools-scheduler.d.ts +6 -0
  289. package/dist/tools-scheduler.js +228 -0
  290. package/dist/tools-skills.d.ts +3 -0
  291. package/dist/tools-skills.js +104 -0
  292. package/dist/tools-todo.d.ts +6 -0
  293. package/dist/tools-todo.js +154 -0
  294. package/dist/tools.d.ts +9 -0
  295. package/dist/tools.js +33 -0
  296. package/dist/tracker-adapters.d.ts +74 -0
  297. package/dist/tracker-adapters.js +776 -0
  298. package/dist/tracker-sync.d.ts +10 -0
  299. package/dist/tracker-sync.js +84 -0
  300. package/dist/tui/agent-runner.d.ts +137 -0
  301. package/dist/tui/agent-runner.js +466 -0
  302. package/dist/tui/agent-worker.d.ts +10 -0
  303. package/dist/tui/agent-worker.js +347 -0
  304. package/dist/tui/chat.d.ts +84 -0
  305. package/dist/tui/chat.js +368 -0
  306. package/dist/tui/commands.d.ts +57 -0
  307. package/dist/tui/commands.js +432 -0
  308. package/dist/tui/dashboard.d.ts +24 -0
  309. package/dist/tui/dashboard.js +110 -0
  310. package/dist/tui/index.d.ts +114 -0
  311. package/dist/tui/index.js +1059 -0
  312. package/dist/tui/input.d.ts +49 -0
  313. package/dist/tui/input.js +336 -0
  314. package/dist/tui/layout.d.ts +116 -0
  315. package/dist/tui/layout.js +367 -0
  316. package/dist/tui/ollama.d.ts +116 -0
  317. package/dist/tui/ollama.js +192 -0
  318. package/dist/tui/openai-compatible.d.ts +63 -0
  319. package/dist/tui/openai-compatible.js +370 -0
  320. package/dist/tui/provider-discovery.d.ts +59 -0
  321. package/dist/tui/provider-discovery.js +530 -0
  322. package/dist/tui/renderer.d.ts +166 -0
  323. package/dist/tui/renderer.js +304 -0
  324. package/dist/tui/tabs.d.ts +70 -0
  325. package/dist/tui/tabs.js +208 -0
  326. package/dist/tui/telemetry.d.ts +56 -0
  327. package/dist/tui/telemetry.js +106 -0
  328. package/dist/vericify-bridge.d.ts +146 -0
  329. package/dist/vericify-bridge.js +571 -0
  330. package/dist/vericify-context.d.ts +10 -0
  331. package/dist/vericify-context.js +72 -0
  332. package/dist/workspace-manager.d.ts +107 -0
  333. package/dist/workspace-manager.js +636 -0
  334. package/package.json +83 -0
@@ -0,0 +1,367 @@
1
+ /**
2
+ * ACE-TUI Layout Manager
3
+ *
4
+ * Screen zone management with dynamic resize handling.
5
+ * Arttime-inspired: defined zones for each UI element.
6
+ */
7
+ import { getTermSize, write, writeAt, drawBox, clearRegion, cursor, screen, style, fg, bg, padRight, truncate, visibleWidth, box, symbols, formatTime, formatElapsed, formatNumber, hline, } from "./renderer.js";
8
+ // ── Layout manager ───────────────────────────────────────────────────
9
+ export class LayoutManager {
10
+ zones;
11
+ cols;
12
+ rows;
13
+ colorLevel;
14
+ tabs = [];
15
+ activeTab = 0;
16
+ constructor(colorLevel = "256") {
17
+ const size = getTermSize();
18
+ this.cols = size.cols;
19
+ this.rows = size.rows;
20
+ this.colorLevel = colorLevel;
21
+ this.computeZones();
22
+ }
23
+ /** Recalculate zones on terminal resize */
24
+ handleResize() {
25
+ const size = getTermSize();
26
+ this.cols = size.cols;
27
+ this.rows = size.rows;
28
+ this.computeZones();
29
+ }
30
+ computeZones() {
31
+ const inputHeight = 5;
32
+ const statusHeight = 1;
33
+ const mainHeight = Math.max(3, this.rows - 1 - statusHeight - inputHeight);
34
+ const statusY = 1 + mainHeight;
35
+ this.zones = {
36
+ tabBar: { x: 0, y: 0, width: this.cols, height: 1 },
37
+ main: { x: 0, y: 1, width: this.cols, height: mainHeight },
38
+ statusBar: { x: 0, y: statusY, width: this.cols, height: statusHeight },
39
+ inputLine: { x: 0, y: statusY + statusHeight, width: this.cols, height: inputHeight },
40
+ };
41
+ }
42
+ getZones() {
43
+ return this.zones;
44
+ }
45
+ getMainZone() {
46
+ return this.zones.main;
47
+ }
48
+ getCols() {
49
+ return this.cols;
50
+ }
51
+ getRows() {
52
+ return this.rows;
53
+ }
54
+ // ── Tab bar rendering ────────────────────────────────────────────
55
+ setTabs(tabs) {
56
+ this.tabs = tabs;
57
+ }
58
+ setActiveTab(index) {
59
+ this.activeTab = index;
60
+ }
61
+ getActiveTab() {
62
+ return this.activeTab;
63
+ }
64
+ renderTabBar() {
65
+ const { tabBar } = this.zones;
66
+ writeAt(tabBar.x, tabBar.y, bg.gray + " ".repeat(tabBar.width) + style.reset);
67
+ let x = 1;
68
+ for (let i = 0; i < this.tabs.length; i++) {
69
+ const tab = this.tabs[i];
70
+ const isActive = i === this.activeTab;
71
+ const label = ` ${tab.label} `;
72
+ const tabWidth = visibleWidth(label);
73
+ if (x + tabWidth >= tabBar.width - 2)
74
+ break;
75
+ if (isActive) {
76
+ writeAt(tabBar.x + x, tabBar.y, `${bg.black}${fg.brightWhite}${style.bold}${symbols.activeTab}${label}${style.reset}${bg.gray}`);
77
+ }
78
+ else {
79
+ const actColor = tab.hasActivity ? fg.brightYellow : fg.white;
80
+ writeAt(tabBar.x + x, tabBar.y, `${bg.gray}${actColor}${symbols.tab}${label}${style.reset}${bg.gray}`);
81
+ }
82
+ x += tabWidth + 2;
83
+ }
84
+ // [+] new tab indicator
85
+ if (x + 3 < tabBar.width) {
86
+ writeAt(tabBar.x + x, tabBar.y, `${bg.gray}${fg.gray} [+]${style.reset}`);
87
+ }
88
+ // Title on right
89
+ const title = "ACE Swarm TUI";
90
+ if (x + visibleWidth(title) + 2 < tabBar.width) {
91
+ writeAt(tabBar.x + tabBar.width - title.length - 2, tabBar.y, `${bg.gray}${fg.brightCyan}${title} ${style.reset}`);
92
+ }
93
+ }
94
+ // ── Status bar rendering (arttime contextual time bar pattern) ───
95
+ renderStatusBar(state) {
96
+ const { statusBar } = this.zones;
97
+ const y = statusBar.y;
98
+ // Separator line
99
+ writeAt(0, y - 1, `${fg.gray}${box.horizontal.repeat(this.cols)}${style.reset}`);
100
+ // Build status segments
101
+ const elapsed = formatElapsed(Date.now() - state.startTime);
102
+ const time = formatTime();
103
+ // State indicator with color
104
+ let stateIndicator;
105
+ switch (state.taskState) {
106
+ case "idle":
107
+ stateIndicator = `${fg.gray}${symbols.hollowBullet} idle${style.reset}`;
108
+ break;
109
+ case "running":
110
+ stateIndicator = `${fg.green}${symbols.bullet} running${style.reset}`;
111
+ break;
112
+ case "blocked":
113
+ stateIndicator = `${fg.yellow}${symbols.bullet} blocked${style.reset}`;
114
+ break;
115
+ case "overdue":
116
+ stateIndicator = `${fg.red}${style.bold}${symbols.bullet} OVERDUE${style.reset}`;
117
+ break;
118
+ }
119
+ const providerSeg = `${fg.cyan}provider: ${fg.brightCyan}${state.provider}${style.reset}`;
120
+ const modelSeg = `${fg.cyan}model: ${fg.brightCyan}${state.model}${style.reset}`;
121
+ const tokenSeg = `${fg.gray}tokens: ${fg.white}${formatNumber(state.tokensIn)}/${formatNumber(state.tokensOut)}${style.reset}`;
122
+ const timeSeg = `${fg.gray}${elapsed}${style.reset}`;
123
+ const clockSeg = `${fg.gray}${style.underline}${time}${style.reset}`;
124
+ const segments = [stateIndicator, providerSeg, modelSeg, tokenSeg, timeSeg, clockSeg];
125
+ const sep = ` ${fg.gray}│${style.reset} `;
126
+ const line = ` ${segments.join(sep)} `;
127
+ // Clear and write
128
+ writeAt(statusBar.x, y, bg.black + " ".repeat(this.cols) + style.reset);
129
+ writeAt(statusBar.x, y, line);
130
+ }
131
+ // ── Input line rendering ─────────────────────────────────────────
132
+ renderInputLine(buffer, cursorPos, mode, prompt) {
133
+ const { inputLine } = this.zones;
134
+ const y = inputLine.y;
135
+ const width = Math.max(1, this.cols - 1);
136
+ const textRows = Math.max(1, inputLine.height - 1);
137
+ // Separator
138
+ writeAt(0, y, `${fg.gray}${box.horizontal.repeat(this.cols)}${style.reset}`);
139
+ // Prompt and multi-line wrapped input.
140
+ const promptText = prompt ?? (mode === "command" ? "" : mode === "chat" ? "> " : "> ");
141
+ const content = `${promptText}${buffer}`;
142
+ const wrapped = this.wrapInputText(content, width);
143
+ const start = Math.max(0, wrapped.length - textRows);
144
+ const visible = wrapped.slice(start);
145
+ for (let row = 0; row < textRows; row++) {
146
+ const line = visible[row] ?? "";
147
+ const lineY = y + 1 + row;
148
+ writeAt(inputLine.x, lineY, " ".repeat(this.cols));
149
+ if (row === 0 && start === 0 && promptText.length > 0) {
150
+ const plain = line.startsWith(promptText) ? line.slice(promptText.length) : line;
151
+ writeAt(inputLine.x, lineY, `${fg.gray}${promptText}${style.reset}${plain}`);
152
+ }
153
+ else {
154
+ writeAt(inputLine.x, lineY, line);
155
+ }
156
+ }
157
+ // Position cursor
158
+ const absoluteCursor = Math.max(0, Math.min(content.length, promptText.length + cursorPos));
159
+ const cursorLine = Math.floor(absoluteCursor / width);
160
+ const cursorCol = absoluteCursor % width;
161
+ const visibleCursorLine = Math.max(0, Math.min(textRows - 1, cursorLine - start));
162
+ const cx = inputLine.x + cursorCol;
163
+ const cy = y + 1 + visibleCursorLine;
164
+ write(cursor.to(cx, cy) + cursor.show);
165
+ }
166
+ // ── Dashboard panels ─────────────────────────────────────────────
167
+ renderDashboard(data, controls) {
168
+ const main = this.zones.main;
169
+ // Clear main area
170
+ clearRegion(main.x, main.y, main.width, main.height);
171
+ // Control strip at top of dashboard.
172
+ writeAt(main.x, main.y, `${bg.black}${" ".repeat(main.width)}${style.reset}`);
173
+ if (controls) {
174
+ this.renderControlStrip(main.x + 1, main.y, main.width - 2, controls);
175
+ }
176
+ const content = {
177
+ x: main.x,
178
+ y: main.y + 1,
179
+ width: main.width,
180
+ height: Math.max(4, main.height - 1),
181
+ };
182
+ const midX = Math.floor(content.width / 2);
183
+ // Status panel (top-left)
184
+ const statusH = Math.max(2, Math.min(8, content.height - 3));
185
+ const statusW = midX - 1;
186
+ drawBox(content.x, content.y, statusW, statusH, { title: "Status", titleColor: fg.brightCyan, borderColor: fg.gray, rounded: true });
187
+ this.renderStatusPanel(content.x + 2, content.y + 1, statusW - 4, statusH - 2, data);
188
+ // Tasks panel (top-right)
189
+ const tasksW = content.width - midX - 1;
190
+ drawBox(content.x + midX + 1, content.y, tasksW, statusH, { title: "Tasks", titleColor: fg.brightYellow, borderColor: fg.gray, rounded: true });
191
+ this.renderTasksPanel(content.x + midX + 3, content.y + 1, tasksW - 4, statusH - 2, data.tasks);
192
+ // Activity log (bottom)
193
+ const actY = content.y + statusH + 1;
194
+ const actH = Math.max(2, content.height - statusH - 1);
195
+ drawBox(content.x, actY, content.width, actH, { title: "Agent Activity", titleColor: fg.brightGreen, borderColor: fg.gray, rounded: true });
196
+ this.renderActivityLog(content.x + 2, actY + 1, content.width - 4, actH - 2, data.events);
197
+ }
198
+ renderStatusPanel(x, y, w, h, data) {
199
+ const lines = [
200
+ `${fg.gray}Phase: ${fg.brightWhite}${data.phase}`,
201
+ `${fg.gray}Provider:${fg.brightCyan} ${padRight(data.provider, 8)}`,
202
+ `${fg.gray}Model: ${fg.brightCyan}${data.model}`,
203
+ `${fg.gray}Agents: ${fg.brightGreen}${data.activeAgents}${fg.gray}/${data.totalAgents} active`,
204
+ `${fg.gray}Uptime: ${fg.white}${formatElapsed(Date.now() - data.startTime)}`,
205
+ `${fg.gray}Tokens: ${fg.white}${formatNumber(data.tokensIn)} in / ${formatNumber(data.tokensOut)} out`,
206
+ `${fg.gray}Speed: ${fg.white}${data.tokensPerSec.toFixed(0)} tok/s`,
207
+ ];
208
+ for (let i = 0; i < Math.min(lines.length, h); i++) {
209
+ writeAt(x, y + i, truncate(lines[i] + style.reset, w));
210
+ }
211
+ }
212
+ renderControlStrip(x, y, w, controls) {
213
+ let cursorX = x;
214
+ for (let i = 0; i < controls.items.length; i++) {
215
+ const item = controls.items[i];
216
+ const active = controls.focused && i === controls.selectedIndex;
217
+ const seg = `${item.label}: ${item.value}`;
218
+ const styled = active
219
+ ? `${bg.brightBlue}${fg.brightWhite}${style.bold} ${seg} ${style.reset}`
220
+ : `${bg.black}${fg.gray} ${seg} ${style.reset}`;
221
+ const segW = visibleWidth(seg) + 2;
222
+ if (cursorX + segW > x + w)
223
+ break;
224
+ writeAt(cursorX, y, styled);
225
+ cursorX += segW + 1;
226
+ }
227
+ }
228
+ renderTasksPanel(x, y, w, h, tasks) {
229
+ for (let i = 0; i < Math.min(tasks.length, h); i++) {
230
+ const t = tasks[i];
231
+ const icon = t.done ? `${fg.green}${symbols.check}` : `${fg.gray}${symbols.hollowBullet}`;
232
+ const priority = t.priority ? `${fg.gray}[${t.priority}]` : "";
233
+ const line = `${icon} ${fg.white}${t.title} ${priority}${style.reset}`;
234
+ writeAt(x, y + i, truncate(line, w));
235
+ }
236
+ if (tasks.length === 0) {
237
+ writeAt(x, y, `${fg.gray}No tasks${style.reset}`);
238
+ }
239
+ }
240
+ renderActivityLog(x, y, w, h, events) {
241
+ const visible = events.slice(-h);
242
+ for (let i = 0; i < visible.length; i++) {
243
+ const e = visible[i];
244
+ const timeStr = formatTime(new Date(e.timestamp));
245
+ const roleColor = this.agentColor(e.agent);
246
+ const line = `${fg.gray}${timeStr} ${roleColor}[${e.agent}]${style.reset} ${e.message}`;
247
+ writeAt(x, y + i, truncate(line, w));
248
+ }
249
+ if (events.length === 0) {
250
+ writeAt(x, y, `${fg.gray}No activity yet${style.reset}`);
251
+ }
252
+ }
253
+ // ── Chat view rendering ──────────────────────────────────────────
254
+ renderChatView(messages) {
255
+ const main = this.zones.main;
256
+ clearRegion(main.x, main.y, main.width, main.height);
257
+ const maxVisible = main.height - 1;
258
+ const visible = messages.slice(-maxVisible);
259
+ for (let i = 0; i < visible.length; i++) {
260
+ const msg = visible[i];
261
+ const y = main.y + i;
262
+ if (msg.role === "user") {
263
+ const prefix = `${fg.brightCyan}${style.bold}You: ${style.reset}`;
264
+ writeAt(main.x + 1, y, truncate(`${prefix}${msg.content}`, main.width - 2));
265
+ }
266
+ else if (msg.role === "assistant") {
267
+ const prefix = `${fg.brightGreen}${style.bold}AI: ${style.reset}`;
268
+ // Wrap long assistant messages
269
+ const lines = this.wrapText(msg.content, main.width - 7);
270
+ for (let j = 0; j < lines.length && (i + j) < maxVisible; j++) {
271
+ const p = j === 0 ? prefix : " ";
272
+ writeAt(main.x + 1, y + j, truncate(`${p}${lines[j]}`, main.width - 2));
273
+ if (j > 0)
274
+ i++;
275
+ }
276
+ }
277
+ else if (msg.role === "system") {
278
+ writeAt(main.x + 1, y, truncate(`${fg.gray}${style.italic}${msg.content}${style.reset}`, main.width - 2));
279
+ }
280
+ }
281
+ }
282
+ /** Render streaming text at the bottom of chat */
283
+ renderStreamChunk(text, line) {
284
+ const main = this.zones.main;
285
+ const y = main.y + Math.min(line, main.height - 2);
286
+ writeAt(main.x + 6, y, truncate(text, main.width - 8));
287
+ }
288
+ // ── Agent tab view ───────────────────────────────────────────────
289
+ renderAgentView(agentName, output, thinking) {
290
+ const main = this.zones.main;
291
+ clearRegion(main.x, main.y, main.width, main.height);
292
+ // Agent header
293
+ const headerColor = this.agentColor(agentName);
294
+ writeAt(main.x + 1, main.y, `${headerColor}${style.bold}Agent: ${agentName}${style.reset}`);
295
+ hline(main.x, main.y + 1, main.width, box.horizontal);
296
+ // Output area
297
+ const outputStart = main.y + 2;
298
+ const thinkingHeight = thinking ? 4 : 0;
299
+ const outputHeight = main.height - 3 - thinkingHeight;
300
+ const visible = output.slice(-outputHeight);
301
+ for (let i = 0; i < visible.length; i++) {
302
+ writeAt(main.x + 1, outputStart + i, truncate(visible[i], main.width - 2));
303
+ }
304
+ // Thinking panel (if active)
305
+ if (thinking) {
306
+ const thinkY = main.y + main.height - thinkingHeight;
307
+ drawBox(main.x, thinkY, main.width, thinkingHeight, { title: "Thinking", titleColor: fg.brightMagenta, borderColor: fg.gray, rounded: true });
308
+ const thinkLines = this.wrapText(thinking, main.width - 4);
309
+ for (let i = 0; i < Math.min(thinkLines.length, thinkingHeight - 2); i++) {
310
+ writeAt(main.x + 2, thinkY + 1 + i, `${fg.gray}${style.italic}${truncate(thinkLines[i], main.width - 4)}${style.reset}`);
311
+ }
312
+ }
313
+ }
314
+ // ── Utilities ────────────────────────────────────────────────────
315
+ agentColor(name) {
316
+ const colors = [fg.brightCyan, fg.brightGreen, fg.brightYellow, fg.brightMagenta, fg.brightBlue, fg.brightRed];
317
+ let hash = 0;
318
+ for (const ch of name)
319
+ hash = (hash * 31 + ch.charCodeAt(0)) | 0;
320
+ return colors[Math.abs(hash) % colors.length];
321
+ }
322
+ wrapText(text, width) {
323
+ const lines = [];
324
+ const words = text.split(" ");
325
+ let current = "";
326
+ for (const word of words) {
327
+ if (current.length + word.length + 1 > width) {
328
+ if (current)
329
+ lines.push(current);
330
+ current = word;
331
+ }
332
+ else {
333
+ current = current ? current + " " + word : word;
334
+ }
335
+ }
336
+ if (current)
337
+ lines.push(current);
338
+ return lines.length ? lines : [""];
339
+ }
340
+ wrapInputText(text, width) {
341
+ if (!text)
342
+ return [""];
343
+ const chunks = [];
344
+ for (let i = 0; i < text.length; i += width) {
345
+ chunks.push(text.slice(i, i + width));
346
+ }
347
+ return chunks.length > 0 ? chunks : [""];
348
+ }
349
+ /** Full screen initialization */
350
+ initScreen() {
351
+ write(screen.altBuffer);
352
+ write(cursor.hide);
353
+ write(screen.clear);
354
+ write(cursor.home);
355
+ }
356
+ /** Full screen teardown */
357
+ destroyScreen() {
358
+ write(cursor.show);
359
+ write(screen.mainBuffer);
360
+ }
361
+ /** Full redraw (arttime: called on resume from suspend) */
362
+ fullRedraw() {
363
+ write(screen.clear);
364
+ this.handleResize();
365
+ }
366
+ }
367
+ //# sourceMappingURL=layout.js.map
@@ -0,0 +1,116 @@
1
+ /**
2
+ * ACE-TUI Ollama Client
3
+ *
4
+ * Direct HTTP communication with Ollama API.
5
+ * Zero dependencies — uses Node.js built-in fetch/http.
6
+ * Supports model listing, pulling, chat streaming, and health checks.
7
+ */
8
+ export interface OllamaModel {
9
+ name: string;
10
+ size: number;
11
+ digest: string;
12
+ modified_at: string;
13
+ details?: {
14
+ format?: string;
15
+ family?: string;
16
+ parameter_size?: string;
17
+ quantization_level?: string;
18
+ };
19
+ }
20
+ export interface OllamaModelInfo {
21
+ modelfile: string;
22
+ parameters: string;
23
+ template: string;
24
+ details: {
25
+ format: string;
26
+ family: string;
27
+ parameter_size: string;
28
+ quantization_level: string;
29
+ };
30
+ }
31
+ export interface ChatMessage {
32
+ role: "system" | "user" | "assistant";
33
+ content: string;
34
+ }
35
+ export interface ChatRequest {
36
+ model: string;
37
+ messages: ChatMessage[];
38
+ stream?: boolean;
39
+ options?: {
40
+ temperature?: number;
41
+ top_p?: number;
42
+ num_ctx?: number;
43
+ num_predict?: number;
44
+ stop?: string[];
45
+ };
46
+ }
47
+ export interface ChatChunk {
48
+ model: string;
49
+ message: {
50
+ role: string;
51
+ content: string;
52
+ };
53
+ done: boolean;
54
+ total_duration?: number;
55
+ load_duration?: number;
56
+ prompt_eval_count?: number;
57
+ eval_count?: number;
58
+ eval_duration?: number;
59
+ }
60
+ export interface GenerateRequest {
61
+ model: string;
62
+ prompt: string;
63
+ system?: string;
64
+ stream?: boolean;
65
+ options?: {
66
+ temperature?: number;
67
+ top_p?: number;
68
+ num_ctx?: number;
69
+ num_predict?: number;
70
+ };
71
+ }
72
+ export interface GenerateChunk {
73
+ model: string;
74
+ response: string;
75
+ done: boolean;
76
+ total_duration?: number;
77
+ prompt_eval_count?: number;
78
+ eval_count?: number;
79
+ eval_duration?: number;
80
+ }
81
+ export interface PullProgress {
82
+ status: string;
83
+ digest?: string;
84
+ total?: number;
85
+ completed?: number;
86
+ }
87
+ export declare class OllamaClient {
88
+ private baseUrl;
89
+ private abortControllers;
90
+ constructor(baseUrl?: string);
91
+ getBaseUrl(): string;
92
+ setBaseUrl(url: string): void;
93
+ /** Check if Ollama is reachable */
94
+ isReachable(): Promise<boolean>;
95
+ /** List available models */
96
+ listModels(): Promise<OllamaModel[]>;
97
+ /** Get model info */
98
+ showModel(name: string): Promise<OllamaModelInfo>;
99
+ /** Pull a model with progress streaming */
100
+ pullModel(name: string): AsyncGenerator<PullProgress>;
101
+ /** Chat with streaming response */
102
+ chat(request: ChatRequest): AsyncGenerator<ChatChunk>;
103
+ /** Generate (completion) with streaming */
104
+ generate(request: GenerateRequest): AsyncGenerator<GenerateChunk>;
105
+ /** Abort a running operation */
106
+ abort(key?: string): void;
107
+ private fetch;
108
+ /** Stream newline-delimited JSON from a ReadableStream */
109
+ private streamJsonLines;
110
+ }
111
+ export declare class OllamaError extends Error {
112
+ statusCode: number;
113
+ responseBody: string;
114
+ constructor(message: string, statusCode: number, responseBody: string);
115
+ }
116
+ //# sourceMappingURL=ollama.d.ts.map
@@ -0,0 +1,192 @@
1
+ /**
2
+ * ACE-TUI Ollama Client
3
+ *
4
+ * Direct HTTP communication with Ollama API.
5
+ * Zero dependencies — uses Node.js built-in fetch/http.
6
+ * Supports model listing, pulling, chat streaming, and health checks.
7
+ */
8
+ // ── Client ───────────────────────────────────────────────────────────
9
+ export class OllamaClient {
10
+ baseUrl;
11
+ abortControllers = new Map();
12
+ constructor(baseUrl) {
13
+ this.baseUrl = (baseUrl ?? "").replace(/\/$/, "");
14
+ }
15
+ getBaseUrl() {
16
+ return this.baseUrl;
17
+ }
18
+ setBaseUrl(url) {
19
+ this.baseUrl = url.replace(/\/$/, "");
20
+ }
21
+ /** Check if Ollama is reachable */
22
+ async isReachable() {
23
+ try {
24
+ const controller = new AbortController();
25
+ const timeout = setTimeout(() => controller.abort(), 3000);
26
+ const res = await fetch(`${this.baseUrl}/api/tags`, {
27
+ signal: controller.signal,
28
+ });
29
+ clearTimeout(timeout);
30
+ return res.ok;
31
+ }
32
+ catch {
33
+ return false;
34
+ }
35
+ }
36
+ /** List available models */
37
+ async listModels() {
38
+ const res = await this.fetch("/api/tags");
39
+ const data = (await res.json());
40
+ return data.models ?? [];
41
+ }
42
+ /** Get model info */
43
+ async showModel(name) {
44
+ const res = await this.fetch("/api/show", {
45
+ method: "POST",
46
+ body: JSON.stringify({ name }),
47
+ });
48
+ return (await res.json());
49
+ }
50
+ /** Pull a model with progress streaming */
51
+ async *pullModel(name) {
52
+ const key = `pull:${name}`;
53
+ const controller = new AbortController();
54
+ this.abortControllers.set(key, controller);
55
+ try {
56
+ const res = await this.fetch("/api/pull", {
57
+ method: "POST",
58
+ body: JSON.stringify({ name, stream: true }),
59
+ signal: controller.signal,
60
+ });
61
+ if (!res.body)
62
+ throw new Error("No response body");
63
+ yield* this.streamJsonLines(res.body);
64
+ }
65
+ finally {
66
+ this.abortControllers.delete(key);
67
+ }
68
+ }
69
+ /** Chat with streaming response */
70
+ async *chat(request) {
71
+ const key = `chat:${Date.now()}`;
72
+ const controller = new AbortController();
73
+ this.abortControllers.set(key, controller);
74
+ try {
75
+ const res = await this.fetch("/api/chat", {
76
+ method: "POST",
77
+ body: JSON.stringify({ ...request, stream: true }),
78
+ signal: controller.signal,
79
+ });
80
+ if (!res.body)
81
+ throw new Error("No response body");
82
+ yield* this.streamJsonLines(res.body);
83
+ }
84
+ finally {
85
+ this.abortControllers.delete(key);
86
+ }
87
+ }
88
+ /** Generate (completion) with streaming */
89
+ async *generate(request) {
90
+ const key = `gen:${Date.now()}`;
91
+ const controller = new AbortController();
92
+ this.abortControllers.set(key, controller);
93
+ try {
94
+ const res = await this.fetch("/api/generate", {
95
+ method: "POST",
96
+ body: JSON.stringify({ ...request, stream: true }),
97
+ signal: controller.signal,
98
+ });
99
+ if (!res.body)
100
+ throw new Error("No response body");
101
+ yield* this.streamJsonLines(res.body);
102
+ }
103
+ finally {
104
+ this.abortControllers.delete(key);
105
+ }
106
+ }
107
+ /** Abort a running operation */
108
+ abort(key) {
109
+ if (key) {
110
+ this.abortControllers.get(key)?.abort();
111
+ this.abortControllers.delete(key);
112
+ }
113
+ else {
114
+ // Abort all
115
+ for (const [k, c] of this.abortControllers) {
116
+ c.abort();
117
+ this.abortControllers.delete(k);
118
+ }
119
+ }
120
+ }
121
+ // ── Internal helpers ─────────────────────────────────────────────
122
+ async fetch(path, options) {
123
+ if (!this.baseUrl) {
124
+ throw new OllamaError("Ollama base URL is not configured. Set one explicitly or run `ace doctor --scan`.", 0, "");
125
+ }
126
+ const url = `${this.baseUrl}${path}`;
127
+ const res = await fetch(url, {
128
+ ...options,
129
+ headers: {
130
+ "Content-Type": "application/json",
131
+ Accept: "application/json",
132
+ ...(options?.headers ?? {}),
133
+ },
134
+ });
135
+ if (!res.ok) {
136
+ const text = await res.text().catch(() => "");
137
+ throw new OllamaError(`Ollama API error: ${res.status} ${res.statusText}`, res.status, text);
138
+ }
139
+ return res;
140
+ }
141
+ /** Stream newline-delimited JSON from a ReadableStream */
142
+ async *streamJsonLines(body) {
143
+ const reader = body.getReader();
144
+ const decoder = new TextDecoder();
145
+ let buffer = "";
146
+ try {
147
+ while (true) {
148
+ const { done, value } = await reader.read();
149
+ if (done)
150
+ break;
151
+ buffer += decoder.decode(value, { stream: true });
152
+ const lines = buffer.split("\n");
153
+ buffer = lines.pop() ?? "";
154
+ for (const line of lines) {
155
+ const trimmed = line.trim();
156
+ if (!trimmed)
157
+ continue;
158
+ try {
159
+ yield JSON.parse(trimmed);
160
+ }
161
+ catch {
162
+ // Skip malformed JSON lines
163
+ }
164
+ }
165
+ }
166
+ // Process remaining buffer
167
+ if (buffer.trim()) {
168
+ try {
169
+ yield JSON.parse(buffer.trim());
170
+ }
171
+ catch {
172
+ // Skip
173
+ }
174
+ }
175
+ }
176
+ finally {
177
+ reader.releaseLock();
178
+ }
179
+ }
180
+ }
181
+ // ── Error class ──────────────────────────────────────────────────────
182
+ export class OllamaError extends Error {
183
+ statusCode;
184
+ responseBody;
185
+ constructor(message, statusCode, responseBody) {
186
+ super(message);
187
+ this.statusCode = statusCode;
188
+ this.responseBody = responseBody;
189
+ this.name = "OllamaError";
190
+ }
191
+ }
192
+ //# sourceMappingURL=ollama.js.map