zoe-agent 0.3.1

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 (267) hide show
  1. package/CHANGELOG.md +154 -0
  2. package/LICENSE +96 -0
  3. package/README.md +568 -0
  4. package/dist/adapters/cli/agent.d.ts +59 -0
  5. package/dist/adapters/cli/agent.js +232 -0
  6. package/dist/adapters/cli/bootstrap.d.ts +25 -0
  7. package/dist/adapters/cli/bootstrap.js +204 -0
  8. package/dist/adapters/cli/commands/build-registry.d.ts +14 -0
  9. package/dist/adapters/cli/commands/build-registry.js +88 -0
  10. package/dist/adapters/cli/commands/clear.d.ts +7 -0
  11. package/dist/adapters/cli/commands/clear.js +10 -0
  12. package/dist/adapters/cli/commands/compact.d.ts +13 -0
  13. package/dist/adapters/cli/commands/compact.js +96 -0
  14. package/dist/adapters/cli/commands/exit.d.ts +7 -0
  15. package/dist/adapters/cli/commands/exit.js +9 -0
  16. package/dist/adapters/cli/commands/gateway.d.ts +7 -0
  17. package/dist/adapters/cli/commands/gateway.js +152 -0
  18. package/dist/adapters/cli/commands/help.d.ts +9 -0
  19. package/dist/adapters/cli/commands/help.js +12 -0
  20. package/dist/adapters/cli/commands/models.d.ts +10 -0
  21. package/dist/adapters/cli/commands/models.js +32 -0
  22. package/dist/adapters/cli/commands/registry.d.ts +70 -0
  23. package/dist/adapters/cli/commands/registry.js +111 -0
  24. package/dist/adapters/cli/commands/settings-utils.d.ts +38 -0
  25. package/dist/adapters/cli/commands/settings-utils.js +182 -0
  26. package/dist/adapters/cli/commands/settings.d.ts +9 -0
  27. package/dist/adapters/cli/commands/settings.js +395 -0
  28. package/dist/adapters/cli/commands/skills.d.ts +7 -0
  29. package/dist/adapters/cli/commands/skills.js +21 -0
  30. package/dist/adapters/cli/config-loader.d.ts +27 -0
  31. package/dist/adapters/cli/config-loader.js +48 -0
  32. package/dist/adapters/cli/docker-utils.d.ts +37 -0
  33. package/dist/adapters/cli/docker-utils.js +90 -0
  34. package/dist/adapters/cli/index.d.ts +2 -0
  35. package/dist/adapters/cli/index.js +88 -0
  36. package/dist/adapters/cli/repl.d.ts +22 -0
  37. package/dist/adapters/cli/repl.js +256 -0
  38. package/dist/adapters/cli/setup.d.ts +19 -0
  39. package/dist/adapters/cli/setup.js +613 -0
  40. package/dist/adapters/cli/system-prompts.d.ts +56 -0
  41. package/dist/adapters/cli/system-prompts.js +131 -0
  42. package/dist/adapters/cli/tui/app.d.ts +58 -0
  43. package/dist/adapters/cli/tui/app.js +314 -0
  44. package/dist/adapters/cli/tui/components/assistant-message.d.ts +5 -0
  45. package/dist/adapters/cli/tui/components/assistant-message.js +9 -0
  46. package/dist/adapters/cli/tui/components/autocomplete.d.ts +19 -0
  47. package/dist/adapters/cli/tui/components/autocomplete.js +75 -0
  48. package/dist/adapters/cli/tui/components/command-palette.d.ts +15 -0
  49. package/dist/adapters/cli/tui/components/command-palette.js +50 -0
  50. package/dist/adapters/cli/tui/components/diff-viewer.d.ts +5 -0
  51. package/dist/adapters/cli/tui/components/diff-viewer.js +109 -0
  52. package/dist/adapters/cli/tui/components/error-message.d.ts +5 -0
  53. package/dist/adapters/cli/tui/components/error-message.js +8 -0
  54. package/dist/adapters/cli/tui/components/footer.d.ts +20 -0
  55. package/dist/adapters/cli/tui/components/footer.js +19 -0
  56. package/dist/adapters/cli/tui/components/goal-status.d.ts +12 -0
  57. package/dist/adapters/cli/tui/components/goal-status.js +22 -0
  58. package/dist/adapters/cli/tui/components/info-message.d.ts +5 -0
  59. package/dist/adapters/cli/tui/components/info-message.js +8 -0
  60. package/dist/adapters/cli/tui/components/logo-banner.d.ts +7 -0
  61. package/dist/adapters/cli/tui/components/logo-banner.js +33 -0
  62. package/dist/adapters/cli/tui/components/markdown.d.ts +9 -0
  63. package/dist/adapters/cli/tui/components/markdown.js +92 -0
  64. package/dist/adapters/cli/tui/components/message-area.d.ts +19 -0
  65. package/dist/adapters/cli/tui/components/message-area.js +55 -0
  66. package/dist/adapters/cli/tui/components/permission-prompt.d.ts +13 -0
  67. package/dist/adapters/cli/tui/components/permission-prompt.js +32 -0
  68. package/dist/adapters/cli/tui/components/prompt-area.d.ts +22 -0
  69. package/dist/adapters/cli/tui/components/prompt-area.js +68 -0
  70. package/dist/adapters/cli/tui/components/text-input.d.ts +27 -0
  71. package/dist/adapters/cli/tui/components/text-input.js +142 -0
  72. package/dist/adapters/cli/tui/components/tool-call-block.d.ts +11 -0
  73. package/dist/adapters/cli/tui/components/tool-call-block.js +68 -0
  74. package/dist/adapters/cli/tui/components/user-message.d.ts +5 -0
  75. package/dist/adapters/cli/tui/components/user-message.js +8 -0
  76. package/dist/adapters/cli/tui/diff/file-write-meta.d.ts +11 -0
  77. package/dist/adapters/cli/tui/diff/file-write-meta.js +11 -0
  78. package/dist/adapters/cli/tui/diff/line-diff.d.ts +17 -0
  79. package/dist/adapters/cli/tui/diff/line-diff.js +44 -0
  80. package/dist/adapters/cli/tui/feed-serializer.d.ts +29 -0
  81. package/dist/adapters/cli/tui/feed-serializer.js +70 -0
  82. package/dist/adapters/cli/tui/file-index.d.ts +8 -0
  83. package/dist/adapters/cli/tui/file-index.js +41 -0
  84. package/dist/adapters/cli/tui/hooks/use-agent.d.ts +54 -0
  85. package/dist/adapters/cli/tui/hooks/use-agent.js +177 -0
  86. package/dist/adapters/cli/tui/hooks/use-feed.d.ts +16 -0
  87. package/dist/adapters/cli/tui/hooks/use-feed.js +25 -0
  88. package/dist/adapters/cli/tui/hooks/use-file-watcher.d.ts +10 -0
  89. package/dist/adapters/cli/tui/hooks/use-file-watcher.js +43 -0
  90. package/dist/adapters/cli/tui/hooks/use-keybindings.d.ts +16 -0
  91. package/dist/adapters/cli/tui/hooks/use-keybindings.js +25 -0
  92. package/dist/adapters/cli/tui/hooks/use-theme.d.ts +8 -0
  93. package/dist/adapters/cli/tui/hooks/use-theme.js +12 -0
  94. package/dist/adapters/cli/tui/index.d.ts +19 -0
  95. package/dist/adapters/cli/tui/index.js +206 -0
  96. package/dist/adapters/cli/tui/ink-reset.d.ts +29 -0
  97. package/dist/adapters/cli/tui/ink-reset.js +57 -0
  98. package/dist/adapters/cli/tui/layout.d.ts +15 -0
  99. package/dist/adapters/cli/tui/layout.js +15 -0
  100. package/dist/adapters/cli/tui/logo/gradient.d.ts +11 -0
  101. package/dist/adapters/cli/tui/logo/gradient.js +31 -0
  102. package/dist/adapters/cli/tui/overlays/help-dialog.d.ts +4 -0
  103. package/dist/adapters/cli/tui/overlays/help-dialog.js +26 -0
  104. package/dist/adapters/cli/tui/overlays/model-selector.d.ts +14 -0
  105. package/dist/adapters/cli/tui/overlays/model-selector.js +43 -0
  106. package/dist/adapters/cli/tui/overlays/session-selector.d.ts +35 -0
  107. package/dist/adapters/cli/tui/overlays/session-selector.js +162 -0
  108. package/dist/adapters/cli/tui/overlays/settings-overlay.d.ts +24 -0
  109. package/dist/adapters/cli/tui/overlays/settings-overlay.js +126 -0
  110. package/dist/adapters/cli/tui/session-export.d.ts +21 -0
  111. package/dist/adapters/cli/tui/session-export.js +63 -0
  112. package/dist/adapters/cli/tui/theme.d.ts +23 -0
  113. package/dist/adapters/cli/tui/theme.js +22 -0
  114. package/dist/adapters/cli/tui/types.d.ts +52 -0
  115. package/dist/adapters/cli/tui/types.js +12 -0
  116. package/dist/adapters/sdk/agent.d.ts +20 -0
  117. package/dist/adapters/sdk/agent.js +356 -0
  118. package/dist/adapters/sdk/http.d.ts +43 -0
  119. package/dist/adapters/sdk/http.js +61 -0
  120. package/dist/adapters/sdk/index.d.ts +58 -0
  121. package/dist/adapters/sdk/index.js +209 -0
  122. package/dist/adapters/sdk/settings.d.ts +18 -0
  123. package/dist/adapters/sdk/settings.js +57 -0
  124. package/dist/adapters/sdk/tools.d.ts +7 -0
  125. package/dist/adapters/sdk/tools.js +13 -0
  126. package/dist/adapters/server/auth.d.ts +53 -0
  127. package/dist/adapters/server/auth.js +168 -0
  128. package/dist/adapters/server/index.d.ts +40 -0
  129. package/dist/adapters/server/index.js +255 -0
  130. package/dist/adapters/server/rest-gateway.d.ts +13 -0
  131. package/dist/adapters/server/rest-gateway.js +218 -0
  132. package/dist/adapters/server/rest.d.ts +37 -0
  133. package/dist/adapters/server/rest.js +341 -0
  134. package/dist/adapters/server/server-core.d.ts +55 -0
  135. package/dist/adapters/server/server-core.js +121 -0
  136. package/dist/adapters/server/session-store.d.ts +81 -0
  137. package/dist/adapters/server/session-store.js +272 -0
  138. package/dist/adapters/server/settings-handlers.d.ts +24 -0
  139. package/dist/adapters/server/settings-handlers.js +360 -0
  140. package/dist/adapters/server/standalone.d.ts +19 -0
  141. package/dist/adapters/server/standalone.js +113 -0
  142. package/dist/adapters/server/websocket.d.ts +26 -0
  143. package/dist/adapters/server/websocket.js +68 -0
  144. package/dist/adapters/server/ws-handlers.d.ts +32 -0
  145. package/dist/adapters/server/ws-handlers.js +523 -0
  146. package/dist/adapters/server/ws-types.d.ts +304 -0
  147. package/dist/adapters/server/ws-types.js +7 -0
  148. package/dist/core/agent-loop.d.ts +68 -0
  149. package/dist/core/agent-loop.js +423 -0
  150. package/dist/core/config.d.ts +115 -0
  151. package/dist/core/config.js +189 -0
  152. package/dist/core/errors.d.ts +58 -0
  153. package/dist/core/errors.js +88 -0
  154. package/dist/core/hooks.d.ts +35 -0
  155. package/dist/core/hooks.js +49 -0
  156. package/dist/core/index.d.ts +23 -0
  157. package/dist/core/index.js +29 -0
  158. package/dist/core/message-convert.d.ts +41 -0
  159. package/dist/core/message-convert.js +94 -0
  160. package/dist/core/middleware/auth.d.ts +24 -0
  161. package/dist/core/middleware/auth.js +28 -0
  162. package/dist/core/middleware/logging.d.ts +23 -0
  163. package/dist/core/middleware/logging.js +28 -0
  164. package/dist/core/middleware/rate-limit.d.ts +27 -0
  165. package/dist/core/middleware/rate-limit.js +38 -0
  166. package/dist/core/middleware/semantic-tools.d.ts +10 -0
  167. package/dist/core/middleware/semantic-tools.js +43 -0
  168. package/dist/core/middleware.d.ts +48 -0
  169. package/dist/core/middleware.js +38 -0
  170. package/dist/core/permission.d.ts +25 -0
  171. package/dist/core/permission.js +50 -0
  172. package/dist/core/provider-config.d.ts +129 -0
  173. package/dist/core/provider-config.js +273 -0
  174. package/dist/core/provider-env.d.ts +39 -0
  175. package/dist/core/provider-env.js +142 -0
  176. package/dist/core/provider-resolver.d.ts +12 -0
  177. package/dist/core/provider-resolver.js +12 -0
  178. package/dist/core/session-store.d.ts +75 -0
  179. package/dist/core/session-store.js +245 -0
  180. package/dist/core/settings-manager.d.ts +57 -0
  181. package/dist/core/settings-manager.js +359 -0
  182. package/dist/core/settings-schema.d.ts +38 -0
  183. package/dist/core/settings-schema.js +171 -0
  184. package/dist/core/skill-catalog.d.ts +6 -0
  185. package/dist/core/skill-catalog.js +17 -0
  186. package/dist/core/skill-invoker.d.ts +127 -0
  187. package/dist/core/skill-invoker.js +182 -0
  188. package/dist/core/stream-accumulator.d.ts +21 -0
  189. package/dist/core/stream-accumulator.js +51 -0
  190. package/dist/core/stream-manager.d.ts +58 -0
  191. package/dist/core/stream-manager.js +212 -0
  192. package/dist/core/tool-executor.d.ts +84 -0
  193. package/dist/core/tool-executor.js +256 -0
  194. package/dist/core/types.d.ts +259 -0
  195. package/dist/core/types.js +11 -0
  196. package/dist/gateway/gateway.d.ts +52 -0
  197. package/dist/gateway/gateway.js +537 -0
  198. package/dist/gateway/index.d.ts +21 -0
  199. package/dist/gateway/index.js +31 -0
  200. package/dist/gateway/openapi-importer.d.ts +15 -0
  201. package/dist/gateway/openapi-importer.js +66 -0
  202. package/dist/gateway/semantic-scorer.d.ts +7 -0
  203. package/dist/gateway/semantic-scorer.js +24 -0
  204. package/dist/gateway/settings-adapter.d.ts +49 -0
  205. package/dist/gateway/settings-adapter.js +137 -0
  206. package/dist/gateway/tool-factory.d.ts +9 -0
  207. package/dist/gateway/tool-factory.js +414 -0
  208. package/dist/gateway/types.d.ts +68 -0
  209. package/dist/gateway/types.js +7 -0
  210. package/dist/models-catalog.js +46 -0
  211. package/dist/providers/anthropic.d.ts +22 -0
  212. package/dist/providers/anthropic.js +148 -0
  213. package/dist/providers/factory.d.ts +10 -0
  214. package/dist/providers/factory.js +25 -0
  215. package/dist/providers/openai.d.ts +15 -0
  216. package/dist/providers/openai.js +71 -0
  217. package/dist/providers/types.d.ts +48 -0
  218. package/dist/providers/types.js +1 -0
  219. package/dist/skills/args.d.ts +37 -0
  220. package/dist/skills/args.js +99 -0
  221. package/dist/skills/index.d.ts +11 -0
  222. package/dist/skills/index.js +23 -0
  223. package/dist/skills/loader.d.ts +3 -0
  224. package/dist/skills/loader.js +59 -0
  225. package/dist/skills/parser.d.ts +7 -0
  226. package/dist/skills/parser.js +152 -0
  227. package/dist/skills/registry.d.ts +13 -0
  228. package/dist/skills/registry.js +74 -0
  229. package/dist/skills/resolver.d.ts +19 -0
  230. package/dist/skills/resolver.js +116 -0
  231. package/dist/skills/types.d.ts +74 -0
  232. package/dist/skills/types.js +50 -0
  233. package/dist/tools/browser.d.ts +2 -0
  234. package/dist/tools/browser.js +68 -0
  235. package/dist/tools/core.d.ts +20 -0
  236. package/dist/tools/core.js +244 -0
  237. package/dist/tools/email.d.ts +2 -0
  238. package/dist/tools/email.js +61 -0
  239. package/dist/tools/image.d.ts +2 -0
  240. package/dist/tools/image.js +257 -0
  241. package/dist/tools/index.d.ts +2 -0
  242. package/dist/tools/index.js +88 -0
  243. package/dist/tools/interface.d.ts +22 -0
  244. package/dist/tools/interface.js +1 -0
  245. package/dist/tools/notify.d.ts +2 -0
  246. package/dist/tools/notify.js +100 -0
  247. package/dist/tools/prompt-optimizer.d.ts +2 -0
  248. package/dist/tools/prompt-optimizer.js +65 -0
  249. package/dist/tools/screenshot.d.ts +2 -0
  250. package/dist/tools/screenshot.js +184 -0
  251. package/dist/tools/search.d.ts +2 -0
  252. package/dist/tools/search.js +78 -0
  253. package/dist/tools/todos.d.ts +10 -0
  254. package/dist/tools/todos.js +50 -0
  255. package/package.json +119 -0
  256. package/skills/docker-ops/SKILL.md +329 -0
  257. package/skills/k8s-deploy/SKILL.md +397 -0
  258. package/skills/log-analyzer/SKILL.md +331 -0
  259. package/skills/speckit-analyze/SKILL.md +260 -0
  260. package/skills/speckit-checklist/SKILL.md +374 -0
  261. package/skills/speckit-clarify/SKILL.md +286 -0
  262. package/skills/speckit-constitution/SKILL.md +157 -0
  263. package/skills/speckit-implement/SKILL.md +224 -0
  264. package/skills/speckit-plan/SKILL.md +171 -0
  265. package/skills/speckit-specify/SKILL.md +346 -0
  266. package/skills/speckit-tasks/SKILL.md +215 -0
  267. package/skills/speckit-taskstoissues/SKILL.md +107 -0
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Zoe Core — StreamManager
3
+ *
4
+ * Shared streaming queue management for text deltas, step results,
5
+ * and SSE conversion. Eliminates duplication between SDK's streamText()
6
+ * and agent's chatStream().
7
+ *
8
+ * Pattern: push-based queues with resolver-based backpressure.
9
+ * Producers call enqueueText/enqueueStep; consumers iterate via
10
+ * textStream/stepsStream async iterables.
11
+ */
12
+ import type { StepResult, Usage } from "./types.js";
13
+ export declare class StreamManager {
14
+ private textQueue;
15
+ private stepQueue;
16
+ private eventQueue;
17
+ private textDone;
18
+ private stepsDone;
19
+ private eventsDone;
20
+ private textResolver;
21
+ private stepResolver;
22
+ private eventResolver;
23
+ private textResolve;
24
+ private usageResolve;
25
+ private finishResolve;
26
+ readonly fullText: Promise<string>;
27
+ readonly usage: Promise<Usage>;
28
+ readonly finishReason: Promise<string>;
29
+ constructor();
30
+ /** Enqueue a text delta and wake any waiting consumer. */
31
+ enqueueText(delta: string): void;
32
+ /** Enqueue a step result and wake any waiting consumer. */
33
+ enqueueStep(step: StepResult): void;
34
+ /** Resolve the fullText promise. */
35
+ resolveText(text: string): void;
36
+ /** Resolve the usage promise. */
37
+ resolveUsage(usage: Usage): void;
38
+ /** Resolve the finishReason promise. */
39
+ resolveFinish(reason: string): void;
40
+ /** Signal completion: set done flags and wake any waiting consumers. */
41
+ complete(): void;
42
+ /** Async iterable of text deltas. */
43
+ get textStream(): AsyncIterable<string>;
44
+ /** Async iterable of step results. */
45
+ get stepsStream(): AsyncIterable<StepResult>;
46
+ /**
47
+ * Returns a ReadableStream that pipes text deltas and tool events as SSE.
48
+ *
49
+ * Events emitted:
50
+ * - `text` — { delta: string }
51
+ * - `tool_call` — { callId, name, args }
52
+ * - `tool_result` — { callId, output, success }
53
+ * - `done` — { usage: { totalTokens, cost }, finishReason }
54
+ */
55
+ toSSEStream(): ReadableStream;
56
+ /** Returns a Web API Response wrapping the SSE stream. */
57
+ toResponse(): Response;
58
+ }
@@ -0,0 +1,212 @@
1
+ /**
2
+ * Zoe Core — StreamManager
3
+ *
4
+ * Shared streaming queue management for text deltas, step results,
5
+ * and SSE conversion. Eliminates duplication between SDK's streamText()
6
+ * and agent's chatStream().
7
+ *
8
+ * Pattern: push-based queues with resolver-based backpressure.
9
+ * Producers call enqueueText/enqueueStep; consumers iterate via
10
+ * textStream/stepsStream async iterables.
11
+ */
12
+ // ── SSE helper ────────────────────────────────────────────────────────────
13
+ function sseLine(event, data) {
14
+ return `event: ${event}\ndata: ${JSON.stringify(data)}\n\n`;
15
+ }
16
+ // ── StreamManager ─────────────────────────────────────────────────────────
17
+ export class StreamManager {
18
+ // Queues for individual consumers
19
+ textQueue = [];
20
+ stepQueue = [];
21
+ // Unified event queue preserving interleaved insertion order for SSE
22
+ eventQueue = [];
23
+ // Done flags
24
+ textDone = false;
25
+ stepsDone = false;
26
+ eventsDone = false;
27
+ // Resolvers for backpressure
28
+ textResolver = null;
29
+ stepResolver = null;
30
+ eventResolver = null;
31
+ // Result promises
32
+ textResolve;
33
+ usageResolve;
34
+ finishResolve;
35
+ fullText;
36
+ usage;
37
+ finishReason;
38
+ constructor() {
39
+ this.fullText = new Promise((r) => { this.textResolve = r; });
40
+ this.usage = new Promise((r) => { this.usageResolve = r; });
41
+ this.finishReason = new Promise((r) => { this.finishResolve = r; });
42
+ }
43
+ // ── Producer API ──────────────────────────────────────────────────────
44
+ /** Enqueue a text delta and wake any waiting consumer. */
45
+ enqueueText(delta) {
46
+ this.textQueue.push(delta);
47
+ this.eventQueue.push({ type: "text", delta });
48
+ if (this.textResolver) {
49
+ this.textResolver();
50
+ this.textResolver = null;
51
+ }
52
+ if (this.eventResolver) {
53
+ this.eventResolver();
54
+ this.eventResolver = null;
55
+ }
56
+ }
57
+ /** Enqueue a step result and wake any waiting consumer. */
58
+ enqueueStep(step) {
59
+ this.stepQueue.push(step);
60
+ this.eventQueue.push({ type: "step", step });
61
+ if (this.stepResolver) {
62
+ this.stepResolver();
63
+ this.stepResolver = null;
64
+ }
65
+ if (this.eventResolver) {
66
+ this.eventResolver();
67
+ this.eventResolver = null;
68
+ }
69
+ }
70
+ /** Resolve the fullText promise. */
71
+ resolveText(text) {
72
+ this.textResolve(text);
73
+ }
74
+ /** Resolve the usage promise. */
75
+ resolveUsage(usage) {
76
+ this.usageResolve(usage);
77
+ }
78
+ /** Resolve the finishReason promise. */
79
+ resolveFinish(reason) {
80
+ this.finishResolve(reason);
81
+ }
82
+ /** Signal completion: set done flags and wake any waiting consumers. */
83
+ complete() {
84
+ this.textDone = true;
85
+ this.stepsDone = true;
86
+ this.eventsDone = true;
87
+ if (this.textResolver) {
88
+ this.textResolver();
89
+ this.textResolver = null;
90
+ }
91
+ if (this.stepResolver) {
92
+ this.stepResolver();
93
+ this.stepResolver = null;
94
+ }
95
+ if (this.eventResolver) {
96
+ this.eventResolver();
97
+ this.eventResolver = null;
98
+ }
99
+ }
100
+ // ── Consumer API ──────────────────────────────────────────────────────
101
+ /** Async iterable of text deltas. */
102
+ get textStream() {
103
+ const self = this;
104
+ return {
105
+ [Symbol.asyncIterator]() {
106
+ return {
107
+ async next() {
108
+ while (self.textQueue.length === 0 && !self.textDone) {
109
+ await new Promise((r) => { self.textResolver = r; });
110
+ }
111
+ if (self.textQueue.length > 0) {
112
+ return { value: self.textQueue.shift(), done: false };
113
+ }
114
+ return { value: undefined, done: true };
115
+ },
116
+ };
117
+ },
118
+ };
119
+ }
120
+ /** Async iterable of step results. */
121
+ get stepsStream() {
122
+ const self = this;
123
+ return {
124
+ [Symbol.asyncIterator]() {
125
+ return {
126
+ async next() {
127
+ while (self.stepQueue.length === 0 && !self.stepsDone) {
128
+ await new Promise((r) => { self.stepResolver = r; });
129
+ }
130
+ if (self.stepQueue.length > 0) {
131
+ return { value: self.stepQueue.shift(), done: false };
132
+ }
133
+ return { value: undefined, done: true };
134
+ },
135
+ };
136
+ },
137
+ };
138
+ }
139
+ /**
140
+ * Returns a ReadableStream that pipes text deltas and tool events as SSE.
141
+ *
142
+ * Events emitted:
143
+ * - `text` — { delta: string }
144
+ * - `tool_call` — { callId, name, args }
145
+ * - `tool_result` — { callId, output, success }
146
+ * - `done` — { usage: { totalTokens, cost }, finishReason }
147
+ */
148
+ toSSEStream() {
149
+ const encoder = new TextEncoder();
150
+ const self = this;
151
+ return new ReadableStream({
152
+ async start(controller) {
153
+ try {
154
+ // Drain unified event queue preserving interleaved order
155
+ while (true) {
156
+ while (self.eventQueue.length === 0 && !self.eventsDone) {
157
+ await new Promise((r) => { self.eventResolver = r; });
158
+ }
159
+ if (self.eventQueue.length === 0)
160
+ break;
161
+ const event = self.eventQueue.shift();
162
+ if (event.type === "text") {
163
+ controller.enqueue(encoder.encode(sseLine("text", { delta: event.delta })));
164
+ }
165
+ else if (event.type === "step" && event.step.type === "tool_call" && event.step.toolCall) {
166
+ controller.enqueue(encoder.encode(sseLine("tool_call", {
167
+ callId: event.step.toolCall.id,
168
+ name: event.step.toolCall.name,
169
+ args: event.step.toolCall.args,
170
+ })));
171
+ controller.enqueue(encoder.encode(sseLine("tool_result", {
172
+ callId: event.step.toolCall.id,
173
+ output: event.step.toolCall.result,
174
+ success: true,
175
+ })));
176
+ }
177
+ }
178
+ // Done event
179
+ const [usage, finishReason] = await Promise.all([
180
+ self.usage,
181
+ self.finishReason,
182
+ ]);
183
+ controller.enqueue(encoder.encode(sseLine("done", {
184
+ usage: {
185
+ totalTokens: usage.totalTokens,
186
+ cost: usage.cost,
187
+ },
188
+ finishReason,
189
+ })));
190
+ }
191
+ catch (err) {
192
+ if (err instanceof Error && err.name !== "AbortError") {
193
+ console.warn("[StreamManager] SSE stream error:", err);
194
+ }
195
+ }
196
+ finally {
197
+ controller.close();
198
+ }
199
+ },
200
+ });
201
+ }
202
+ /** Returns a Web API Response wrapping the SSE stream. */
203
+ toResponse() {
204
+ return new Response(this.toSSEStream(), {
205
+ headers: {
206
+ "Content-Type": "text/event-stream",
207
+ "Cache-Control": "no-cache",
208
+ Connection: "keep-alive",
209
+ },
210
+ });
211
+ }
212
+ }
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Zoe Core — Tool executor
3
+ *
4
+ * Tool registry, resolution, factory, and execution logic.
5
+ * Transport-agnostic: no chalk, no HTTP, no CLI concerns.
6
+ */
7
+ import { ToolModule, ToolDefinition, ToolExecExtra } from "../tools/interface.js";
8
+ import { UserToolDefinition, ToolResult } from "./types.js";
9
+ /**
10
+ * Return the tool definitions for all registered tools (built-in + custom).
11
+ */
12
+ export declare function getAllToolDefinitions(): ToolDefinition[];
13
+ /**
14
+ * Return all registered tool modules (built-in + custom).
15
+ */
16
+ export declare function getAllToolModules(): ToolModule[];
17
+ export declare const CORE_TOOLS: string[];
18
+ export declare const COMM_TOOLS: string[];
19
+ export declare const ADVANCED_TOOLS: string[];
20
+ export declare const ALL_TOOLS: string[];
21
+ /**
22
+ * Create a custom tool module from a Zod-like schema definition.
23
+ *
24
+ * Returns a `ToolModule` compatible with the built-in tool registry,
25
+ * so custom tools can be mixed freely with built-in ones.
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * const myTool = tool({
30
+ * description: "Greets a person",
31
+ * parameters: z.object({ name: z.string() }),
32
+ * execute: async ({ name }) => `Hello, ${name}!`,
33
+ * });
34
+ * ```
35
+ */
36
+ export declare function tool(definition: UserToolDefinition): ToolModule;
37
+ /**
38
+ * Register a tool module in the global tool registry.
39
+ *
40
+ * @param module A `ToolModule` to add to the registry
41
+ */
42
+ export declare function registerTool(module: ToolModule): void;
43
+ /**
44
+ * Coerce a tool handler's `string | ToolResult` return into a `ToolResult`.
45
+ * Plain strings (the common case) become `{ output, success: true }` with no
46
+ * metadata. Structured ToolResults pass through with `metadata` preserved.
47
+ */
48
+ export declare function normalizeToolResult(raw: string | ToolResult): ToolResult;
49
+ /**
50
+ * Execute a tool by name with the given arguments and optional config.
51
+ *
52
+ * @param name Tool function name (e.g. "execute_shell_command")
53
+ * @param args Arguments object for the tool
54
+ * @param config Optional runtime config passed to the tool handler
55
+ * @returns ToolResult — `output` (what the LLM sees) + optional `metadata`
56
+ * for adapters (e.g. write_file's FileWriteMetadata for the diff)
57
+ * @throws Error if the tool name is not found in the registry
58
+ */
59
+ export declare function executeTool(name: string, args: Record<string, unknown>, config?: Record<string, unknown>, extra?: ToolExecExtra): Promise<ToolResult>;
60
+ /**
61
+ * Return the built-in tool definitions belonging to a named group.
62
+ *
63
+ * @param group One of "core", "comm", "advanced", or "all"
64
+ * @returns Array of OpenAI function definitions for the matching tools
65
+ * @throws Error if the group name is not recognised
66
+ */
67
+ export declare function getToolGroup(group: "core" | "comm" | "advanced" | "all"): ToolDefinition[];
68
+ type ToolInput = string | UserToolDefinition;
69
+ /**
70
+ * Resolve a mixed array of tool references into concrete OpenAI function
71
+ * definitions ready to send to the LLM.
72
+ *
73
+ * Accepted input shapes:
74
+ * - `"all"` — expands to all built-in tools
75
+ * - `"core"` / `"comm"` / `"advanced"` — expands to the named group
76
+ * - A built-in tool name string — looked up from the internal registry
77
+ * - A `UserToolDefinition` object — converted via `tool()` factory
78
+ *
79
+ * @param tools Array of tool references (defaults to all built-in tools)
80
+ * @returns Deduplicated array of OpenAI function definitions
81
+ * @throws Error if a string name is not found in the built-in registry
82
+ */
83
+ export declare function resolveTools(tools?: ToolInput[]): ToolDefinition[];
84
+ export {};
@@ -0,0 +1,256 @@
1
+ /**
2
+ * Zoe Core — Tool executor
3
+ *
4
+ * Tool registry, resolution, factory, and execution logic.
5
+ * Transport-agnostic: no chalk, no HTTP, no CLI concerns.
6
+ */
7
+ import { builtInTools } from "../tools/index.js";
8
+ // ── Internal registry ───────────────────────────────────────────────
9
+ const registry = [...builtInTools];
10
+ /**
11
+ * Return the tool definitions for all registered tools (built-in + custom).
12
+ */
13
+ export function getAllToolDefinitions() {
14
+ return registry.map((t) => t.definition);
15
+ }
16
+ /**
17
+ * Return all registered tool modules (built-in + custom).
18
+ */
19
+ export function getAllToolModules() {
20
+ return registry;
21
+ }
22
+ // ── Tool groups ──────────────────────────────────────────────────────
23
+ export const CORE_TOOLS = [
24
+ "execute_shell_command",
25
+ "read_file",
26
+ "write_file",
27
+ "get_current_datetime",
28
+ ];
29
+ export const COMM_TOOLS = [
30
+ "send_email",
31
+ "web_search",
32
+ "send_notification",
33
+ ];
34
+ export const ADVANCED_TOOLS = [
35
+ "read_website",
36
+ "take_screenshot",
37
+ "generate_image",
38
+ "optimize_prompt",
39
+ "use_skill",
40
+ ];
41
+ export const ALL_TOOLS = [...CORE_TOOLS, ...COMM_TOOLS, ...ADVANCED_TOOLS];
42
+ // ── Helpers ──────────────────────────────────────────────────────────
43
+ let customToolCounter = 0;
44
+ /**
45
+ * Convert a parameter definition into JSON Schema.
46
+ *
47
+ * Accepts plain `{ type: "object", properties: {...}, required: [...] }` objects.
48
+ * Anything else is wrapped in a generic object schema.
49
+ */
50
+ function parametersToJsonSchema(parameters) {
51
+ if (parameters == null || typeof parameters !== "object") {
52
+ return { type: "object", properties: {} };
53
+ }
54
+ const rec = parameters;
55
+ // Already a valid JSON Schema object — validate basic shape
56
+ if ("type" in rec && "properties" in rec
57
+ && typeof rec.type === "string"
58
+ && typeof rec.properties === "object" && rec.properties !== null) {
59
+ return rec;
60
+ }
61
+ // Unknown shape — wrap generically
62
+ return { type: "object", properties: {} };
63
+ }
64
+ /**
65
+ * Generate a unique tool name when the user doesn't supply one.
66
+ */
67
+ function generateToolName() {
68
+ customToolCounter += 1;
69
+ return `custom_tool_${customToolCounter}`;
70
+ }
71
+ // ── tool() factory ───────────────────────────────────────────────────
72
+ /**
73
+ * Create a custom tool module from a Zod-like schema definition.
74
+ *
75
+ * Returns a `ToolModule` compatible with the built-in tool registry,
76
+ * so custom tools can be mixed freely with built-in ones.
77
+ *
78
+ * @example
79
+ * ```ts
80
+ * const myTool = tool({
81
+ * description: "Greets a person",
82
+ * parameters: z.object({ name: z.string() }),
83
+ * execute: async ({ name }) => `Hello, ${name}!`,
84
+ * });
85
+ * ```
86
+ */
87
+ export function tool(definition) {
88
+ const functionName = definition.name ?? generateToolName();
89
+ const jsonSchema = parametersToJsonSchema(definition.parameters);
90
+ const openaiDefinition = {
91
+ type: "function",
92
+ function: {
93
+ name: functionName,
94
+ description: definition.description,
95
+ parameters: {
96
+ type: jsonSchema.type ?? "object",
97
+ properties: jsonSchema.properties ?? {},
98
+ required: jsonSchema.required ?? [],
99
+ },
100
+ },
101
+ };
102
+ const handler = async (args, config, extra) => {
103
+ const context = {
104
+ config: config ?? {},
105
+ onUpdate: extra?.onUpdate,
106
+ signal: extra?.signal,
107
+ };
108
+ // Passthrough — normalization (string | ToolResult → ToolResult) happens once
109
+ // at the executeTool boundary. Direct handler callers get back exactly what
110
+ // `execute` returned (a string in the common case → backward compatible).
111
+ return definition.execute(args, context);
112
+ };
113
+ return {
114
+ name: functionName,
115
+ definition: openaiDefinition,
116
+ handler,
117
+ };
118
+ }
119
+ // ── registerTool ──────────────────────────────────────────────────────
120
+ /**
121
+ * Register a tool module in the global tool registry.
122
+ *
123
+ * @param module A `ToolModule` to add to the registry
124
+ */
125
+ export function registerTool(module) {
126
+ if (registry.some(t => t.definition.function.name === module.definition.function.name)) {
127
+ console.warn(`[tool-executor] Duplicate tool registration ignored: ${module.definition.function.name}`);
128
+ return;
129
+ }
130
+ registry.push(module);
131
+ }
132
+ // ── executeTool ───────────────────────────────────────────────────────
133
+ /**
134
+ * Coerce a tool handler's `string | ToolResult` return into a `ToolResult`.
135
+ * Plain strings (the common case) become `{ output, success: true }` with no
136
+ * metadata. Structured ToolResults pass through with `metadata` preserved.
137
+ */
138
+ export function normalizeToolResult(raw) {
139
+ if (typeof raw === "string")
140
+ return { output: raw, success: true };
141
+ if (raw && typeof raw === "object" && "output" in raw)
142
+ return raw;
143
+ return { output: String(raw), success: true };
144
+ }
145
+ /**
146
+ * Execute a tool by name with the given arguments and optional config.
147
+ *
148
+ * @param name Tool function name (e.g. "execute_shell_command")
149
+ * @param args Arguments object for the tool
150
+ * @param config Optional runtime config passed to the tool handler
151
+ * @returns ToolResult — `output` (what the LLM sees) + optional `metadata`
152
+ * for adapters (e.g. write_file's FileWriteMetadata for the diff)
153
+ * @throws Error if the tool name is not found in the registry
154
+ */
155
+ export async function executeTool(name, args, config, extra) {
156
+ const found = registry.find((t) => t.definition.function.name === name);
157
+ if (!found) {
158
+ throw new Error(`Unknown tool "${name}". Available: ${registry
159
+ .map((t) => t.definition.function.name)
160
+ .join(", ")}`);
161
+ }
162
+ const raw = await found.handler(args, config, extra);
163
+ return normalizeToolResult(raw);
164
+ }
165
+ // ── getToolGroup ─────────────────────────────────────────────────────
166
+ /**
167
+ * Return the built-in tool definitions belonging to a named group.
168
+ *
169
+ * @param group One of "core", "comm", "advanced", or "all"
170
+ * @returns Array of OpenAI function definitions for the matching tools
171
+ * @throws Error if the group name is not recognised
172
+ */
173
+ export function getToolGroup(group) {
174
+ let names;
175
+ switch (group) {
176
+ case "core":
177
+ names = CORE_TOOLS;
178
+ break;
179
+ case "comm":
180
+ names = COMM_TOOLS;
181
+ break;
182
+ case "advanced":
183
+ names = ADVANCED_TOOLS;
184
+ break;
185
+ case "all":
186
+ names = ALL_TOOLS;
187
+ break;
188
+ default:
189
+ throw new Error(`Unknown tool group "${group}". Valid groups: core, comm, advanced, all`);
190
+ }
191
+ const defs = [];
192
+ for (const name of names) {
193
+ const found = registry.find((t) => t.definition.function.name === name);
194
+ if (found) {
195
+ defs.push(found.definition);
196
+ }
197
+ }
198
+ return defs;
199
+ }
200
+ /**
201
+ * Resolve a mixed array of tool references into concrete OpenAI function
202
+ * definitions ready to send to the LLM.
203
+ *
204
+ * Accepted input shapes:
205
+ * - `"all"` — expands to all built-in tools
206
+ * - `"core"` / `"comm"` / `"advanced"` — expands to the named group
207
+ * - A built-in tool name string — looked up from the internal registry
208
+ * - A `UserToolDefinition` object — converted via `tool()` factory
209
+ *
210
+ * @param tools Array of tool references (defaults to all built-in tools)
211
+ * @returns Deduplicated array of OpenAI function definitions
212
+ * @throws Error if a string name is not found in the built-in registry
213
+ */
214
+ export function resolveTools(tools) {
215
+ const inputs = tools ?? ["all"];
216
+ const seen = new Set();
217
+ const result = [];
218
+ for (const input of inputs) {
219
+ // String reference — group name or built-in tool name
220
+ if (typeof input === "string") {
221
+ // Group expansion
222
+ if (input === "all" || input === "core" || input === "comm" || input === "advanced") {
223
+ const groupDefs = getToolGroup(input);
224
+ for (const def of groupDefs) {
225
+ const name = def.function.name;
226
+ if (!seen.has(name)) {
227
+ seen.add(name);
228
+ result.push(def);
229
+ }
230
+ }
231
+ continue;
232
+ }
233
+ // Individual built-in tool lookup
234
+ const found = registry.find((t) => t.definition.function.name === input);
235
+ if (!found) {
236
+ throw new Error(`Unknown tool "${input}". Available: ${registry
237
+ .map((t) => t.definition.function.name)
238
+ .join(", ")}`);
239
+ }
240
+ const name = found.definition.function.name;
241
+ if (!seen.has(name)) {
242
+ seen.add(name);
243
+ result.push(found.definition);
244
+ }
245
+ continue;
246
+ }
247
+ // ToolDefinition object — convert via factory
248
+ const module = tool(input);
249
+ const name = module.definition.function.name;
250
+ if (!seen.has(name)) {
251
+ seen.add(name);
252
+ result.push(module.definition);
253
+ }
254
+ }
255
+ return result;
256
+ }