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,273 @@
1
+ /**
2
+ * Zoe Core — Provider Configuration Types & Mutation
3
+ *
4
+ * Types, singleton management, config mutation functions, and file-based resolution.
5
+ * Extracted from provider-resolver.ts for single-responsibility.
6
+ */
7
+ import { createProvider } from "../providers/factory.js";
8
+ import { DEFAULT_MODELS, PROVIDER_ENV_KEYS, resolveApiKey, resolveBaseUrl, resolveDefaultType, resolveDefaultModel, } from "./provider-env.js";
9
+ import { applyEnvOverrides, loadMergedConfig, resolveActiveProviderType, } from "./config.js";
10
+ /**
11
+ * Module-level singleton that holds multi-provider configuration.
12
+ */
13
+ let providerConfig = null;
14
+ // ── Public API ───────────────────────────────────────────────────────
15
+ /**
16
+ * Creates a single provider configuration object.
17
+ * Useful for building `MultiProviderConfig` declaratively.
18
+ */
19
+ export function provider(type, apiKey, options) {
20
+ return {
21
+ type,
22
+ apiKey,
23
+ ...options,
24
+ };
25
+ }
26
+ /**
27
+ * Stores multi-provider configuration globally.
28
+ * Can be called once at application startup.
29
+ */
30
+ export function configureProviders(config) {
31
+ providerConfig = config;
32
+ }
33
+ /**
34
+ * Returns the raw configuration for a given provider type.
35
+ * Falls back to environment variables when no explicit config is set.
36
+ *
37
+ * @param type - Provider type. If omitted, uses the default provider.
38
+ * @returns Resolved provider configuration with apiKey, model, and optional baseUrl.
39
+ * @throws Error if the provider is not configured and no env var is available.
40
+ */
41
+ export function getProviderConfig(type) {
42
+ const resolvedType = type ?? getDefaultProviderType();
43
+ // 1. Check explicit config first
44
+ if (providerConfig) {
45
+ const entry = providerConfig[resolvedType];
46
+ if (entry && "apiKey" in entry) {
47
+ const cfg = entry;
48
+ return {
49
+ type: resolvedType,
50
+ apiKey: cfg.apiKey,
51
+ model: cfg.model ?? resolveDefaultModel(resolvedType),
52
+ baseUrl: cfg.baseUrl,
53
+ };
54
+ }
55
+ }
56
+ // 2. Fall back to environment variables
57
+ const apiKey = resolveApiKey(resolvedType);
58
+ if (!apiKey) {
59
+ const envHint = PROVIDER_ENV_KEYS[resolvedType].apiKey;
60
+ throw new Error(`No provider is configured. Pass \`provider\` to generateText/createAgent/streamText, ` +
61
+ `call \`configureProviders(loadProviderConfig())\` at startup, or set the ${envHint} env var.`);
62
+ }
63
+ return {
64
+ type: resolvedType,
65
+ apiKey,
66
+ model: resolveDefaultModel(resolvedType),
67
+ baseUrl: resolveBaseUrl(resolvedType),
68
+ };
69
+ }
70
+ /**
71
+ * Resolves which provider type is the default.
72
+ * Checks explicit config, then LLM_PROVIDER env var, then falls back to "openai".
73
+ */
74
+ export function getDefaultProviderType() {
75
+ if (providerConfig?.default) {
76
+ return providerConfig.default;
77
+ }
78
+ return resolveDefaultType();
79
+ }
80
+ /**
81
+ * Returns the default configured provider type (alias for getDefaultProviderType).
82
+ */
83
+ export function getDefaultProvider() {
84
+ return getDefaultProviderType();
85
+ }
86
+ /**
87
+ * Creates and returns an LLMProvider instance using the existing factory.
88
+ * If type is omitted, uses the default provider.
89
+ *
90
+ * @param type - Provider type. If omitted, uses the default provider.
91
+ * @param modelOverride - When set, overrides the resolved model before creating the provider.
92
+ * @returns The initialized LLMProvider and the resolved model name.
93
+ */
94
+ export async function getProvider(type, modelOverride) {
95
+ const config = getProviderConfig(type);
96
+ const factoryConfig = {
97
+ type: config.type,
98
+ apiKey: config.apiKey,
99
+ model: modelOverride ?? config.model,
100
+ ...(config.baseUrl ? { baseUrl: config.baseUrl } : {}),
101
+ };
102
+ const llmProvider = await createProvider(factoryConfig);
103
+ return {
104
+ provider: llmProvider,
105
+ model: modelOverride ?? config.model,
106
+ };
107
+ }
108
+ // ── CLI-specific functions ───────────────────────────────────────────
109
+ /**
110
+ * Resolves provider configuration from legacy AppConfig (CLI format).
111
+ * This handles both old-style top-level config and new models map format.
112
+ */
113
+ export function resolveProviderConfigFromApp(config, providerType) {
114
+ const modelConfig = config.models?.[providerType];
115
+ if (!modelConfig)
116
+ return null;
117
+ const apiKey = ("apiKey" in modelConfig) ? modelConfig.apiKey : config.apiKey;
118
+ if (!apiKey)
119
+ return null;
120
+ const model = "model" in modelConfig ? modelConfig.model : config.model || DEFAULT_MODELS[providerType];
121
+ const baseUrl = "baseUrl" in modelConfig ? modelConfig.baseUrl : config.baseUrl;
122
+ return { type: providerType, apiKey, model, baseUrl };
123
+ }
124
+ // ── CLI-config bridge ────────────────────────────────────────────────
125
+ /**
126
+ * Load CLI-style config (~/.zoe/setting.json + .zoe/setting.json + env
127
+ * overrides) and translate it to a MultiProviderConfig suitable for
128
+ * `configureProviders()`.
129
+ *
130
+ * When `app` is provided, uses that config directly (callers that have already
131
+ * loaded and mutated their AppConfig should pass it here). Otherwise reads
132
+ * fresh from disk via `loadMergedConfig()` + `applyEnvOverrides()`.
133
+ *
134
+ * @returns MultiProviderConfig if any provider has a configured apiKey, null otherwise.
135
+ * Callers should check for null before passing to configureProviders().
136
+ */
137
+ export function loadProviderConfig(app, cliProvider) {
138
+ const appConfig = app ?? applyEnvOverrides(loadMergedConfig());
139
+ const multi = {};
140
+ const types = [
141
+ "openai",
142
+ "anthropic",
143
+ "glm",
144
+ "openai-compatible",
145
+ ];
146
+ for (const t of types) {
147
+ const entry = appConfig.models?.[t];
148
+ if (entry && "apiKey" in entry && entry.apiKey) {
149
+ multi[t] = entry;
150
+ }
151
+ }
152
+ const collected = Object.keys(multi);
153
+ if (collected.length === 0)
154
+ return null;
155
+ // Derive `default`: CLI flag → config.provider → resolveActiveProviderType(),
156
+ // but only if that provider was actually collected above. Otherwise fall back
157
+ // to the first collected entry so `default` always points at a real provider.
158
+ const candidate = cliProvider ??
159
+ appConfig.provider ??
160
+ resolveActiveProviderType(appConfig);
161
+ multi.default = collected.includes(candidate) ? candidate : collected[0];
162
+ return multi;
163
+ }
164
+ // ── Config-file resolution ───────────────────────────────────────────
165
+ /**
166
+ * Resolves provider configuration from a config file object.
167
+ * Supports both legacy AppConfig format and new MultiProviderConfig format.
168
+ */
169
+ export function resolveFromConfigFile(config, type) {
170
+ // First, try to treat it as MultiProviderConfig (new format)
171
+ if (config.models || config.default) {
172
+ const multiConfig = config;
173
+ const resolvedType = type ?? multiConfig.default ?? "openai";
174
+ const entry = multiConfig[resolvedType];
175
+ if (entry && "apiKey" in entry) {
176
+ return {
177
+ type: resolvedType,
178
+ apiKey: entry.apiKey,
179
+ model: entry.model ?? DEFAULT_MODELS[resolvedType],
180
+ baseUrl: "baseUrl" in entry ? entry.baseUrl : undefined,
181
+ };
182
+ }
183
+ }
184
+ // Fall back to legacy AppConfig format
185
+ if (config.apiKey || config.models) {
186
+ const appConfig = migrateLegacyConfig(config);
187
+ return resolveFromConfigFile(appConfig, type);
188
+ }
189
+ return null;
190
+ }
191
+ /**
192
+ * Migrates legacy top-level config to the new models map format.
193
+ */
194
+ export function migrateLegacyConfig(config) {
195
+ const result = {};
196
+ // If config already has models map, it's not legacy
197
+ if (config.models) {
198
+ return config;
199
+ }
200
+ // Migrate top-level provider config
201
+ const providerType = config.provider || "openai";
202
+ if (config.apiKey) {
203
+ result[providerType] = {
204
+ apiKey: config.apiKey,
205
+ ...(config.model ? { model: config.model } : {}),
206
+ ...(config.baseUrl ? { baseUrl: config.baseUrl } : {}),
207
+ };
208
+ }
209
+ result.default = providerType;
210
+ return result;
211
+ }
212
+ // ── Provider mutation functions ──────────────────────────────────────
213
+ /**
214
+ * Adds or updates a provider configuration.
215
+ * Modifies the global providerConfig singleton.
216
+ */
217
+ export function addProvider(type, config) {
218
+ if (!providerConfig) {
219
+ providerConfig = { default: type };
220
+ }
221
+ // For openai-compatible, baseUrl is required
222
+ if (type === "openai-compatible" && !config.baseUrl) {
223
+ throw new Error('Provider "openai-compatible" requires a baseUrl.');
224
+ }
225
+ providerConfig[type] = config;
226
+ }
227
+ /**
228
+ * Updates an existing provider configuration.
229
+ * Only updates the specified fields, preserving others.
230
+ */
231
+ export function updateProviderConfig(type, updates) {
232
+ if (!providerConfig?.[type]) {
233
+ throw new Error(`Provider "${type}" is not configured. Use addProvider() first.`);
234
+ }
235
+ const existing = providerConfig[type];
236
+ providerConfig[type] = {
237
+ ...existing,
238
+ ...updates,
239
+ };
240
+ }
241
+ /**
242
+ * Removes a provider configuration.
243
+ */
244
+ export function removeProvider(type) {
245
+ if (!providerConfig) {
246
+ return;
247
+ }
248
+ delete providerConfig[type];
249
+ // If we removed the default, switch to another available provider
250
+ if (providerConfig.default === type) {
251
+ const remaining = Object.keys(providerConfig).filter(k => k !== "default");
252
+ if (remaining.length > 0) {
253
+ providerConfig.default = remaining[0];
254
+ }
255
+ }
256
+ }
257
+ /**
258
+ * Saves the current provider configuration to a file.
259
+ */
260
+ export async function saveConfig(configPath) {
261
+ if (!providerConfig) {
262
+ throw new Error("No provider configuration to save. Call configureProviders() first.");
263
+ }
264
+ const fs = await import("fs");
265
+ const path = await import("path");
266
+ const os = await import("os");
267
+ const targetPath = configPath ?? path.join(os.homedir(), ".zoerc.json");
268
+ const dir = path.dirname(targetPath);
269
+ // Ensure directory exists
270
+ await fs.promises.mkdir(dir, { recursive: true });
271
+ // Write config file
272
+ await fs.promises.writeFile(targetPath, JSON.stringify(providerConfig, null, 2), "utf-8");
273
+ }
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Zoe Core — Provider Environment Resolution
3
+ *
4
+ * Environment variable helpers, default models, and env-based resolution.
5
+ * Extracted from provider-resolver.ts for single-responsibility.
6
+ */
7
+ import { DEFAULT_MODELS } from "../models-catalog.js";
8
+ import type { MultiProviderConfig, ProviderType } from "./types.js";
9
+ export { DEFAULT_MODELS };
10
+ export declare const PROVIDER_ENV_KEYS: Record<ProviderType, {
11
+ apiKey: string;
12
+ baseUrl?: string;
13
+ }>;
14
+ export declare function env(name: string): string | undefined;
15
+ export declare function resolveApiKey(type: ProviderType): string | undefined;
16
+ export declare function resolveBaseUrl(type: ProviderType): string | undefined;
17
+ export declare function resolveDefaultType(): ProviderType;
18
+ export declare function resolveDefaultModel(type: ProviderType): string;
19
+ /**
20
+ * Resolve a GLM model alias or model name to the actual model identifier.
21
+ *
22
+ * Looks up the model in the GLM_MODEL_MAP (e.g. "haiku" -> "glm-4.5-air",
23
+ * "sonnet" -> "glm-4.7", "opus" -> "glm-5.1"). If the model is not found in
24
+ * the map, it is returned unchanged.
25
+ *
26
+ * @param model - Model name or alias to resolve.
27
+ * @returns The resolved model identifier.
28
+ */
29
+ export declare function resolveGLMModel(model: string): string;
30
+ /**
31
+ * Scans environment variables and builds a MultiProviderConfig from them.
32
+ * This replaces the server's `initializeProvidersFromEnv()` function.
33
+ *
34
+ * Note: This function only RETURNS the config. To actually configure providers,
35
+ * call `configureProviders(resolveFromEnv())`.
36
+ *
37
+ * @returns MultiProviderConfig if any env vars are set, null otherwise.
38
+ */
39
+ export declare function resolveFromEnv(): MultiProviderConfig | null;
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Zoe Core — Provider Environment Resolution
3
+ *
4
+ * Environment variable helpers, default models, and env-based resolution.
5
+ * Extracted from provider-resolver.ts for single-responsibility.
6
+ */
7
+ import { GLM_MODEL_MAP } from "../providers/factory.js";
8
+ import { DEFAULT_MODELS } from "../models-catalog.js";
9
+ // ── Default models per provider ──────────────────────────────────────
10
+ export { DEFAULT_MODELS };
11
+ // ── Env var keys per provider ────────────────────────────────────────
12
+ export const PROVIDER_ENV_KEYS = {
13
+ openai: { apiKey: "OPENAI_API_KEY" },
14
+ anthropic: { apiKey: "ANTHROPIC_API_KEY" },
15
+ glm: { apiKey: "GLM_API_KEY" },
16
+ "openai-compatible": {
17
+ apiKey: "OPENAI_COMPAT_API_KEY",
18
+ baseUrl: "OPENAI_COMPAT_BASE_URL",
19
+ },
20
+ };
21
+ // ── Internal helpers ─────────────────────────────────────────────────
22
+ export function env(name) {
23
+ return process.env[name];
24
+ }
25
+ export function resolveApiKey(type) {
26
+ // Per-provider env var takes priority
27
+ const envKeys = PROVIDER_ENV_KEYS[type];
28
+ if (envKeys.apiKey) {
29
+ const key = env(envKeys.apiKey);
30
+ if (key)
31
+ return key;
32
+ }
33
+ // Backward compat: check deprecated env vars
34
+ if (type === "openai-compatible") {
35
+ const legacy = env("ZOE_API_KEY");
36
+ if (legacy) {
37
+ console.warn("[zoe] ZOE_API_KEY is deprecated. Use OPENAI_COMPAT_API_KEY instead.");
38
+ return legacy;
39
+ }
40
+ }
41
+ return undefined;
42
+ }
43
+ export function resolveBaseUrl(type) {
44
+ const envKeys = PROVIDER_ENV_KEYS[type];
45
+ if (envKeys.baseUrl) {
46
+ const url = env(envKeys.baseUrl);
47
+ if (url)
48
+ return url;
49
+ }
50
+ // Backward compat: check deprecated env var for openai-compatible
51
+ if (type === "openai-compatible") {
52
+ const legacy = env("OPENAI_BASE_URL");
53
+ if (legacy) {
54
+ console.warn("[zoe] OPENAI_BASE_URL is deprecated. Use OPENAI_COMPAT_BASE_URL instead.");
55
+ return legacy;
56
+ }
57
+ }
58
+ return undefined;
59
+ }
60
+ export function resolveDefaultType() {
61
+ const fromEnv = env("LLM_PROVIDER") ?? env("ZOE_PROVIDER");
62
+ if (fromEnv &&
63
+ (fromEnv === "openai" ||
64
+ fromEnv === "anthropic" ||
65
+ fromEnv === "glm" ||
66
+ fromEnv === "openai-compatible")) {
67
+ return fromEnv;
68
+ }
69
+ return "openai";
70
+ }
71
+ export function resolveDefaultModel(type) {
72
+ return env("LLM_MODEL") ?? env("ZOE_MODEL") ?? DEFAULT_MODELS[type];
73
+ }
74
+ // ── GLM model alias resolution ───────────────────────────────────────
75
+ /**
76
+ * Resolve a GLM model alias or model name to the actual model identifier.
77
+ *
78
+ * Looks up the model in the GLM_MODEL_MAP (e.g. "haiku" -> "glm-4.5-air",
79
+ * "sonnet" -> "glm-4.7", "opus" -> "glm-5.1"). If the model is not found in
80
+ * the map, it is returned unchanged.
81
+ *
82
+ * @param model - Model name or alias to resolve.
83
+ * @returns The resolved model identifier.
84
+ */
85
+ export function resolveGLMModel(model) {
86
+ return GLM_MODEL_MAP[model] ?? model;
87
+ }
88
+ // ── Full env-based resolution ────────────────────────────────────────
89
+ /**
90
+ * Scans environment variables and builds a MultiProviderConfig from them.
91
+ * This replaces the server's `initializeProvidersFromEnv()` function.
92
+ *
93
+ * Note: This function only RETURNS the config. To actually configure providers,
94
+ * call `configureProviders(resolveFromEnv())`.
95
+ *
96
+ * @returns MultiProviderConfig if any env vars are set, null otherwise.
97
+ */
98
+ export function resolveFromEnv() {
99
+ const config = {};
100
+ if (process.env.OPENAI_API_KEY) {
101
+ config.openai = {
102
+ apiKey: process.env.OPENAI_API_KEY,
103
+ model: process.env.OPENAI_MODEL ?? DEFAULT_MODELS.openai,
104
+ };
105
+ }
106
+ if (process.env.ANTHROPIC_API_KEY) {
107
+ config.anthropic = {
108
+ apiKey: process.env.ANTHROPIC_API_KEY,
109
+ model: process.env.ANTHROPIC_MODEL ?? DEFAULT_MODELS.anthropic,
110
+ };
111
+ }
112
+ if (process.env.GLM_API_KEY) {
113
+ config.glm = {
114
+ apiKey: process.env.GLM_API_KEY,
115
+ model: process.env.GLM_MODEL ?? DEFAULT_MODELS.glm,
116
+ };
117
+ }
118
+ const compatApiKey = process.env.OPENAI_COMPAT_API_KEY || process.env.ZOE_API_KEY;
119
+ const compatBaseUrl = process.env.OPENAI_COMPAT_BASE_URL || process.env.OPENAI_BASE_URL;
120
+ if (compatApiKey && compatBaseUrl) {
121
+ if (process.env.ZOE_API_KEY && !process.env.OPENAI_COMPAT_API_KEY) {
122
+ console.warn("[zoe] ZOE_API_KEY is deprecated. Use OPENAI_COMPAT_API_KEY instead.");
123
+ }
124
+ if (process.env.OPENAI_BASE_URL && !process.env.OPENAI_COMPAT_BASE_URL) {
125
+ console.warn("[zoe] OPENAI_BASE_URL is deprecated. Use OPENAI_COMPAT_BASE_URL instead.");
126
+ }
127
+ config["openai-compatible"] = {
128
+ apiKey: compatApiKey,
129
+ baseUrl: compatBaseUrl,
130
+ model: process.env.OPENAI_COMPAT_MODEL ?? process.env.LLM_MODEL ?? process.env.ZOE_MODEL ?? DEFAULT_MODELS['openai-compatible'],
131
+ };
132
+ }
133
+ if (Object.keys(config).length > 0) {
134
+ const defaultProvider = (process.env.LLM_PROVIDER ?? process.env.ZOE_PROVIDER) ??
135
+ (config.openai ? "openai" : Object.keys(config)[0]);
136
+ return {
137
+ ...config,
138
+ default: defaultProvider,
139
+ };
140
+ }
141
+ return null;
142
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Zoe Core — Unified Provider Resolver
3
+ *
4
+ * Re-export hub. All logic has been split into:
5
+ * - provider-env.ts — env var helpers, defaults, resolveFromEnv(), resolveGLMModel()
6
+ * - provider-config.ts — types, singleton, mutation, getProvider(), resolveFromConfigFile()
7
+ *
8
+ * This file preserves all existing import paths. No consumer changes needed.
9
+ */
10
+ export { DEFAULT_MODELS, PROVIDER_ENV_KEYS, resolveFromEnv, resolveGLMModel, } from "./provider-env.js";
11
+ export type { ResolvedProviderConfig, AppConfig } from "./provider-config.js";
12
+ export { provider, configureProviders, loadProviderConfig, getProviderConfig, getDefaultProviderType, getDefaultProvider, getProvider, resolveProviderConfigFromApp, resolveFromConfigFile, migrateLegacyConfig, addProvider, updateProviderConfig, removeProvider, saveConfig, } from "./provider-config.js";
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Zoe Core — Unified Provider Resolver
3
+ *
4
+ * Re-export hub. All logic has been split into:
5
+ * - provider-env.ts — env var helpers, defaults, resolveFromEnv(), resolveGLMModel()
6
+ * - provider-config.ts — types, singleton, mutation, getProvider(), resolveFromConfigFile()
7
+ *
8
+ * This file preserves all existing import paths. No consumer changes needed.
9
+ */
10
+ // ── From provider-env.ts ─────────────────────────────────────────────
11
+ export { DEFAULT_MODELS, PROVIDER_ENV_KEYS, resolveFromEnv, resolveGLMModel, } from "./provider-env.js";
12
+ export { provider, configureProviders, loadProviderConfig, getProviderConfig, getDefaultProviderType, getDefaultProvider, getProvider, resolveProviderConfigFromApp, resolveFromConfigFile, migrateLegacyConfig, addProvider, updateProviderConfig, removeProvider, saveConfig, } from "./provider-config.js";
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Zoe SDK — Session persistence
3
+ *
4
+ * Provides composable persistence backends for storing conversation history.
5
+ * Built-in "file" and "memory" backends are registered by default. Custom
6
+ * backends (Redis, SQLite, etc.) can be registered via `registerBackend()`.
7
+ *
8
+ * Legacy `SessionStore`-based API is preserved for backward compatibility.
9
+ */
10
+ import type { Message, PersistenceBackend, PersistenceConfig, ProviderType, SessionData, SessionStore } from "./types.js";
11
+ /**
12
+ * File-backed persistence backend. Each session is stored as a JSON file
13
+ * at `{basePath}/{sessionId}.json`.
14
+ */
15
+ export declare class FilePersistenceBackend implements PersistenceBackend {
16
+ readonly __persistenceBackend: true;
17
+ private basePath;
18
+ constructor(basePath: string);
19
+ private filePath;
20
+ private ensureDir;
21
+ save(id: string, data: SessionData): Promise<void>;
22
+ load(id: string): Promise<SessionData | null>;
23
+ delete(id: string): Promise<void>;
24
+ list(): Promise<string[]>;
25
+ private loadFromDisk;
26
+ }
27
+ /**
28
+ * In-memory persistence backend backed by a Map. Useful for testing.
29
+ */
30
+ export declare class MemoryPersistenceBackend implements PersistenceBackend {
31
+ readonly __persistenceBackend: true;
32
+ private store;
33
+ save(id: string, data: SessionData): Promise<void>;
34
+ load(id: string): Promise<SessionData | null>;
35
+ delete(id: string): Promise<void>;
36
+ list(): Promise<string[]>;
37
+ }
38
+ export type BackendFactory = (config: PersistenceConfig) => PersistenceBackend;
39
+ /**
40
+ * Register a custom persistence backend factory.
41
+ *
42
+ * @param type Unique backend identifier (e.g., "redis", "sqlite")
43
+ * @param factory Factory function that creates a `PersistenceBackend` from config
44
+ */
45
+ export declare function registerBackend(type: string, factory: BackendFactory): void;
46
+ /**
47
+ * Create a persistence backend from a config object.
48
+ * Uses the `type` field to look up the registered factory.
49
+ *
50
+ * @throws Error if `type` is not registered
51
+ */
52
+ export declare function createPersistenceBackend(config: PersistenceConfig): PersistenceBackend;
53
+ /**
54
+ * Persist a session's messages to the backend.
55
+ *
56
+ * Single source of truth for the save step shared by all adapters (SDK, CLI,
57
+ * Server). The backend owns `createdAt` (assigns it on first save, preserves
58
+ * it on overwrite — see FilePersistenceBackend / MemoryPersistenceBackend) and
59
+ * merges optional `provider`/`model`/`metadata` fields, so callers only pass
60
+ * what they know. Adapters that don't track provider/model (the SDK) omit them
61
+ * and the persisted values are left untouched.
62
+ */
63
+ export declare function persistSession(backend: PersistenceBackend, sessionId: string, messages: Message[], opts?: {
64
+ provider?: ProviderType;
65
+ model?: string;
66
+ metadata?: Record<string, unknown>;
67
+ }): Promise<void>;
68
+ /**
69
+ * @deprecated Use `createPersistenceBackend({ type: "file", path })` instead.
70
+ */
71
+ export declare function createSessionStore(path?: string): SessionStore;
72
+ /**
73
+ * @deprecated Use `createPersistenceBackend({ type: "memory" })` instead.
74
+ */
75
+ export declare function createMemoryStore(): SessionStore;