@studio-foundation/api 0.3.0-beta.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 (188) hide show
  1. package/ARCHITECTURE.md +52 -0
  2. package/LICENSE +663 -0
  3. package/README.md +161 -0
  4. package/dist/api.d.ts +8 -0
  5. package/dist/api.d.ts.map +1 -0
  6. package/dist/api.js +6 -0
  7. package/dist/api.js.map +1 -0
  8. package/dist/bootstrap.d.ts +66 -0
  9. package/dist/bootstrap.d.ts.map +1 -0
  10. package/dist/bootstrap.js +193 -0
  11. package/dist/bootstrap.js.map +1 -0
  12. package/dist/event-bus.d.ts +16 -0
  13. package/dist/event-bus.d.ts.map +1 -0
  14. package/dist/event-bus.js +37 -0
  15. package/dist/event-bus.js.map +1 -0
  16. package/dist/index.d.ts +3 -0
  17. package/dist/index.d.ts.map +1 -0
  18. package/dist/index.js +52 -0
  19. package/dist/index.js.map +1 -0
  20. package/dist/integration-runtime.d.ts +22 -0
  21. package/dist/integration-runtime.d.ts.map +1 -0
  22. package/dist/integration-runtime.js +150 -0
  23. package/dist/integration-runtime.js.map +1 -0
  24. package/dist/integration-store.d.ts +26 -0
  25. package/dist/integration-store.d.ts.map +1 -0
  26. package/dist/integration-store.js +80 -0
  27. package/dist/integration-store.js.map +1 -0
  28. package/dist/integrations/linear/failure-handler.d.ts +5 -0
  29. package/dist/integrations/linear/failure-handler.d.ts.map +1 -0
  30. package/dist/integrations/linear/failure-handler.js +73 -0
  31. package/dist/integrations/linear/failure-handler.js.map +1 -0
  32. package/dist/integrations/linear/webhook-handler.d.ts +6 -0
  33. package/dist/integrations/linear/webhook-handler.d.ts.map +1 -0
  34. package/dist/integrations/linear/webhook-handler.js +131 -0
  35. package/dist/integrations/linear/webhook-handler.js.map +1 -0
  36. package/dist/integrations/registry.d.ts +4 -0
  37. package/dist/integrations/registry.d.ts.map +1 -0
  38. package/dist/integrations/registry.js +9 -0
  39. package/dist/integrations/registry.js.map +1 -0
  40. package/dist/integrations/types.d.ts +33 -0
  41. package/dist/integrations/types.d.ts.map +1 -0
  42. package/dist/integrations/types.js +2 -0
  43. package/dist/integrations/types.js.map +1 -0
  44. package/dist/launcher.d.ts +45 -0
  45. package/dist/launcher.d.ts.map +1 -0
  46. package/dist/launcher.js +149 -0
  47. package/dist/launcher.js.map +1 -0
  48. package/dist/logger.d.ts +7 -0
  49. package/dist/logger.d.ts.map +1 -0
  50. package/dist/logger.js +37 -0
  51. package/dist/logger.js.map +1 -0
  52. package/dist/plans.d.ts +13 -0
  53. package/dist/plans.d.ts.map +1 -0
  54. package/dist/plans.js +33 -0
  55. package/dist/plans.js.map +1 -0
  56. package/dist/routes/agents.d.ts +6 -0
  57. package/dist/routes/agents.d.ts.map +1 -0
  58. package/dist/routes/agents.js +118 -0
  59. package/dist/routes/agents.js.map +1 -0
  60. package/dist/routes/config.d.ts +6 -0
  61. package/dist/routes/config.d.ts.map +1 -0
  62. package/dist/routes/config.js +129 -0
  63. package/dist/routes/config.js.map +1 -0
  64. package/dist/routes/contracts.d.ts +6 -0
  65. package/dist/routes/contracts.d.ts.map +1 -0
  66. package/dist/routes/contracts.js +188 -0
  67. package/dist/routes/contracts.js.map +1 -0
  68. package/dist/routes/pipelines.d.ts +6 -0
  69. package/dist/routes/pipelines.d.ts.map +1 -0
  70. package/dist/routes/pipelines.js +133 -0
  71. package/dist/routes/pipelines.js.map +1 -0
  72. package/dist/routes/projects.d.ts +6 -0
  73. package/dist/routes/projects.d.ts.map +1 -0
  74. package/dist/routes/projects.js +220 -0
  75. package/dist/routes/projects.js.map +1 -0
  76. package/dist/routes/runs.d.ts +6 -0
  77. package/dist/routes/runs.d.ts.map +1 -0
  78. package/dist/routes/runs.js +427 -0
  79. package/dist/routes/runs.js.map +1 -0
  80. package/dist/routes/skills.d.ts +6 -0
  81. package/dist/routes/skills.d.ts.map +1 -0
  82. package/dist/routes/skills.js +123 -0
  83. package/dist/routes/skills.js.map +1 -0
  84. package/dist/routes/tools.d.ts +6 -0
  85. package/dist/routes/tools.d.ts.map +1 -0
  86. package/dist/routes/tools.js +193 -0
  87. package/dist/routes/tools.js.map +1 -0
  88. package/dist/routes/users.d.ts +6 -0
  89. package/dist/routes/users.d.ts.map +1 -0
  90. package/dist/routes/users.js +152 -0
  91. package/dist/routes/users.js.map +1 -0
  92. package/dist/routes/validate.d.ts +6 -0
  93. package/dist/routes/validate.d.ts.map +1 -0
  94. package/dist/routes/validate.js +171 -0
  95. package/dist/routes/validate.js.map +1 -0
  96. package/dist/routes/webhooks.d.ts +8 -0
  97. package/dist/routes/webhooks.d.ts.map +1 -0
  98. package/dist/routes/webhooks.js +102 -0
  99. package/dist/routes/webhooks.js.map +1 -0
  100. package/dist/server.d.ts +46 -0
  101. package/dist/server.d.ts.map +1 -0
  102. package/dist/server.js +101 -0
  103. package/dist/server.js.map +1 -0
  104. package/dist/spawners/http-api-spawner.d.ts +10 -0
  105. package/dist/spawners/http-api-spawner.d.ts.map +1 -0
  106. package/dist/spawners/http-api-spawner.js +88 -0
  107. package/dist/spawners/http-api-spawner.js.map +1 -0
  108. package/dist/user-store-pg.d.ts +21 -0
  109. package/dist/user-store-pg.d.ts.map +1 -0
  110. package/dist/user-store-pg.js +97 -0
  111. package/dist/user-store-pg.js.map +1 -0
  112. package/dist/user-store.d.ts +29 -0
  113. package/dist/user-store.d.ts.map +1 -0
  114. package/dist/user-store.js +97 -0
  115. package/dist/user-store.js.map +1 -0
  116. package/dist/utils/repo-resolver.d.ts +3 -0
  117. package/dist/utils/repo-resolver.d.ts.map +1 -0
  118. package/dist/utils/repo-resolver.js +3 -0
  119. package/dist/utils/repo-resolver.js.map +1 -0
  120. package/dist/webhook-dispatcher.d.ts +13 -0
  121. package/dist/webhook-dispatcher.d.ts.map +1 -0
  122. package/dist/webhook-dispatcher.js +108 -0
  123. package/dist/webhook-dispatcher.js.map +1 -0
  124. package/dist/webhook-store.d.ts +31 -0
  125. package/dist/webhook-store.d.ts.map +1 -0
  126. package/dist/webhook-store.js +91 -0
  127. package/dist/webhook-store.js.map +1 -0
  128. package/package.json +59 -0
  129. package/src/.gitkeep +0 -0
  130. package/src/api.ts +8 -0
  131. package/src/bootstrap.ts +259 -0
  132. package/src/event-bus.ts +64 -0
  133. package/src/index.ts +58 -0
  134. package/src/integration-runtime.ts +180 -0
  135. package/src/integration-store.ts +125 -0
  136. package/src/integrations/linear/failure-handler.ts +93 -0
  137. package/src/integrations/linear/webhook-handler.ts +156 -0
  138. package/src/integrations/registry.ts +12 -0
  139. package/src/integrations/types.ts +37 -0
  140. package/src/launcher.ts +214 -0
  141. package/src/logger.ts +50 -0
  142. package/src/plans.ts +43 -0
  143. package/src/routes/agents.ts +131 -0
  144. package/src/routes/config.ts +154 -0
  145. package/src/routes/contracts.ts +205 -0
  146. package/src/routes/pipelines.ts +146 -0
  147. package/src/routes/projects.ts +237 -0
  148. package/src/routes/runs.ts +468 -0
  149. package/src/routes/skills.ts +136 -0
  150. package/src/routes/tools.ts +222 -0
  151. package/src/routes/users.ts +169 -0
  152. package/src/routes/validate.ts +196 -0
  153. package/src/routes/webhooks.ts +120 -0
  154. package/src/server.ts +155 -0
  155. package/src/spawners/http-api-spawner.ts +96 -0
  156. package/src/user-store-pg.ts +138 -0
  157. package/src/user-store.ts +125 -0
  158. package/src/utils/repo-resolver.ts +3 -0
  159. package/src/webhook-dispatcher.ts +142 -0
  160. package/src/webhook-store.ts +141 -0
  161. package/tests/agents.test.ts +164 -0
  162. package/tests/cancel.test.ts +120 -0
  163. package/tests/config.test.ts +196 -0
  164. package/tests/contracts.test.ts +302 -0
  165. package/tests/event-bus.test.ts +53 -0
  166. package/tests/http-api-spawner.test.ts +158 -0
  167. package/tests/integration-runtime.test.ts +199 -0
  168. package/tests/integration-store.test.ts +66 -0
  169. package/tests/integrations/linear/failure-handler.test.ts +113 -0
  170. package/tests/integrations/linear/webhook-handler.test.ts +191 -0
  171. package/tests/launcher.test.ts +380 -0
  172. package/tests/linear-webhook.test.ts +390 -0
  173. package/tests/pipelines.test.ts +166 -0
  174. package/tests/projects.test.ts +283 -0
  175. package/tests/runs.test.ts +379 -0
  176. package/tests/server.test.ts +208 -0
  177. package/tests/skills.test.ts +149 -0
  178. package/tests/sse.test.ts +129 -0
  179. package/tests/tools.test.ts +233 -0
  180. package/tests/user-store.test.ts +93 -0
  181. package/tests/users.test.ts +189 -0
  182. package/tests/utils/repo-resolver.test.ts +105 -0
  183. package/tests/validate.test.ts +233 -0
  184. package/tests/webhook-dispatcher.test.ts +214 -0
  185. package/tests/webhook-store.test.ts +98 -0
  186. package/tests/webhooks.test.ts +176 -0
  187. package/tsconfig.json +24 -0
  188. package/vitest.config.ts +7 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"launcher.d.ts","sourceRoot":"","sources":["../src/launcher.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,YAAY,EACZ,YAAY,EACZ,WAAW,EAcZ,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAI3D,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAgB,MAAM,gBAAgB,CAAC;AAC7E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAgC,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAE5E,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,8FAA8F;IAC9F,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,aAAa,GAAG,CAC1B,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,YAAY,KACjB,IAAI,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;AAEjC,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC1D,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,GAAG,MAAM,IAAI,CAAC;CAC7D;AAED,qBAAa,iBAAkB,YAAW,WAAW;IAKjD,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,SAAS,CAAC;IAClB,OAAO,CAAC,KAAK;IAVf,OAAO,CAAC,MAAM,CAAsC;IACpD,OAAO,CAAC,aAAa,CAAkC;gBAG7C,YAAY,EAAE,YAAY,EAC1B,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,WAAW,EAChB,aAAa,GAAE,aAA4D,EAC3E,SAAS,CAAC,EAAE,YAAY,YAAA,EACxB,KAAK,GAAE,WAA2B;IAG5C,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,GAAG,MAAM,IAAI;IAIrD,MAAM,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAsIzD,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAG5C;AAED,OAAO,EAAE,UAAU,IAAI,aAAa,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,149 @@
1
+ // Run launcher — interface + InProcessLauncher implementation
2
+ // InProcessLauncher creates a new PipelineEngine per run for event isolation.
3
+ // Future: BullMQLauncher, etc.
4
+ import { PipelineEngine } from '@studio-foundation/engine';
5
+ import { loadProjectTools } from '@studio-foundation/runner';
6
+ import { join } from 'node:path';
7
+ import { createApiLogger } from './logger.js';
8
+ import { getPlanLimits, DEFAULT_PLANS } from './plans.js';
9
+ export class InProcessLauncher {
10
+ engineConfig;
11
+ store;
12
+ runsDir;
13
+ bus;
14
+ engineFactory;
15
+ userStore;
16
+ plans;
17
+ active = new Map();
18
+ activePerUser = new Map(); // userId → Set<runId>
19
+ constructor(engineConfig, store, runsDir, bus, engineFactory = (cfg, evts) => new PipelineEngine(cfg, evts), userStore, plans = DEFAULT_PLANS) {
20
+ this.engineConfig = engineConfig;
21
+ this.store = store;
22
+ this.runsDir = runsDir;
23
+ this.bus = bus;
24
+ this.engineFactory = engineFactory;
25
+ this.userStore = userStore;
26
+ this.plans = plans;
27
+ }
28
+ subscribe(runId, listener) {
29
+ return this.bus.subscribe(runId, listener);
30
+ }
31
+ async launch(config) {
32
+ const { runId, pipeline, input, meta, parentRunId, userId } = config;
33
+ // Quota enforcement (only if userId provided and userStore available)
34
+ if (userId && this.userStore) {
35
+ const user = await this.userStore.getUserById(userId);
36
+ if (user) {
37
+ const today = new Date().toISOString().slice(0, 10);
38
+ const limits = getPlanLimits(this.plans, user.plan);
39
+ // Check runs_per_day
40
+ if (limits.runs_per_day !== -1) {
41
+ const usage = await this.userStore.getDailyUsage(userId, today);
42
+ if (usage.runs_count >= limits.runs_per_day) {
43
+ throw Object.assign(new Error('Daily run limit exceeded'), { code: 'QUOTA_EXCEEDED', limit: limits.runs_per_day, used: usage.runs_count });
44
+ }
45
+ }
46
+ // Check max_concurrent
47
+ const activeForUser = this.activePerUser.get(userId)?.size ?? 0;
48
+ if (activeForUser >= limits.max_concurrent) {
49
+ throw Object.assign(new Error('Concurrent run limit exceeded'), { code: 'QUOTA_EXCEEDED', limit: limits.max_concurrent, used: activeForUser });
50
+ }
51
+ // Increment runs_count
52
+ await this.userStore.incrementRuns(userId, today);
53
+ }
54
+ }
55
+ // Track active run for user (before creating the controller)
56
+ if (userId) {
57
+ if (!this.activePerUser.has(userId))
58
+ this.activePerUser.set(userId, new Set());
59
+ this.activePerUser.get(userId).add(runId);
60
+ }
61
+ const controller = new AbortController();
62
+ this.active.set(runId, controller);
63
+ const logger = createApiLogger(this.runsDir, runId, pipeline);
64
+ // Pre-create the run in the store so GET /api/runs/:id/stream can find it immediately
65
+ // after launch() returns. The engine will upsert it again at onPipelineStart with the
66
+ // same id (savePipelineRun is ON CONFLICT DO UPDATE in all store implementations).
67
+ const stubRun = {
68
+ id: runId,
69
+ pipeline_name: pipeline,
70
+ status: 'running',
71
+ started_at: new Date().toISOString(),
72
+ stages: [],
73
+ ...(input && typeof input === 'object' ? { input: input } : {}),
74
+ ...(parentRunId ? { parent_run_id: parentRunId } : {}),
75
+ };
76
+ await this.store.savePipelineRun(stubRun);
77
+ // Save log path immediately so callers can locate the log file right after launch().
78
+ // For InMemoryRunStore this is a simple Map.set() and works regardless of row existence.
79
+ // For SQLiteRunStore/PgRunStore the row now exists, so the UPDATE will take effect.
80
+ void this.store.saveLogPath(runId, logger.logPath);
81
+ const emit = (type, data) => {
82
+ this.bus.emit(runId, type, data);
83
+ logger.log({ event: type, ...data });
84
+ };
85
+ // Track last group feedback for inclusion in the pipeline_complete bus event
86
+ let lastGroupFeedback;
87
+ const perRunEvents = {
88
+ onPipelineStart: (e) => {
89
+ // Row exists now — persist log_path for SQLiteRunStore (the call in launch() was a no-op there).
90
+ void this.store.saveLogPath(runId, logger.logPath);
91
+ emit('pipeline_start', e);
92
+ },
93
+ onStageStart: (e) => emit('stage_start', e),
94
+ onStageComplete: (e) => emit('stage_complete', e),
95
+ onTaskRetry: (e) => emit('stage_retry', e),
96
+ onGroupStart: (e) => emit('group_start', e),
97
+ onGroupIteration: (e) => emit('group_iteration', e),
98
+ onGroupFeedback: (e) => {
99
+ lastGroupFeedback = e;
100
+ emit('group_feedback', e);
101
+ },
102
+ onGroupComplete: (e) => emit('group_complete', e),
103
+ onStageContext: (e) => emit('stage_context', e),
104
+ onToolCallStart: (e) => emit('tool_call_start', e),
105
+ onToolCallComplete: (e) => emit('tool_call_complete', e),
106
+ onPipelineComplete: (e) => {
107
+ emit('pipeline_complete', { ...e, meta: meta ?? {}, last_group_feedback: lastGroupFeedback });
108
+ this.bus.close(runId);
109
+ },
110
+ onPipelineCancelled: (e) => {
111
+ emit('pipeline_cancelled', e);
112
+ },
113
+ };
114
+ let runEngineConfig = this.engineConfig;
115
+ if (config.repoPath !== undefined) {
116
+ const toolsDir = join(this.engineConfig.configsDir, 'tools');
117
+ const freshPlugins = await loadProjectTools(toolsDir, config.repoPath);
118
+ // toolRegistry is always provided when using the API launcher
119
+ const freshRegistry = this.engineConfig.toolRegistry.clone();
120
+ for (const plugin of freshPlugins) {
121
+ freshRegistry.registerPlugin(plugin.name, plugin.tools, plugin.promptSnippet);
122
+ }
123
+ runEngineConfig = { ...this.engineConfig, repoPath: config.repoPath, toolRegistry: freshRegistry };
124
+ }
125
+ const engine = this.engineFactory(runEngineConfig, perRunEvents);
126
+ void engine
127
+ .run({ pipeline, input, meta, signal: controller.signal, id: runId, depth: config.depth, parentRunId })
128
+ .then(async () => {
129
+ await logger.close();
130
+ })
131
+ .catch(async (err) => {
132
+ logger.log({ event: 'pipeline_error', error: String(err) });
133
+ this.bus.close(runId);
134
+ await logger.close();
135
+ })
136
+ .finally(() => {
137
+ this.active.delete(runId);
138
+ if (userId) {
139
+ this.activePerUser.get(userId)?.delete(runId);
140
+ }
141
+ });
142
+ return { run_id: runId };
143
+ }
144
+ async cancel(run_id) {
145
+ this.active.get(run_id)?.abort();
146
+ }
147
+ }
148
+ export { randomUUID as generateRunId } from 'node:crypto';
149
+ //# sourceMappingURL=launcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"launcher.js","sourceRoot":"","sources":["../src/launcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export interface ApiRunLogger {
2
+ logPath: string;
3
+ log(payload: Record<string, unknown>): void;
4
+ close(): Promise<void>;
5
+ }
6
+ export declare function createApiLogger(runsDir: string, runId: string, pipeline: string): ApiRunLogger;
7
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC5C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,YAAY,CA4B9F"}
package/dist/logger.js ADDED
@@ -0,0 +1,37 @@
1
+ // JSONL logger for API runs
2
+ // Writes to <runsDir>/<date>-<pipeline>-<runId>.jsonl
3
+ import { createWriteStream, mkdirSync } from 'node:fs';
4
+ import { resolve } from 'node:path';
5
+ function runIdShort(runId) {
6
+ return runId.slice(0, 8);
7
+ }
8
+ function dateForFilename() {
9
+ const iso = new Date().toISOString();
10
+ return iso.slice(0, 16).replace(/(\d{2}):(\d{2})$/, '$1h$2m');
11
+ }
12
+ export function createApiLogger(runsDir, runId, pipeline) {
13
+ const shortId = runIdShort(runId);
14
+ const date = dateForFilename();
15
+ const logPath = resolve(runsDir, `${date}-${pipeline}-${shortId}.jsonl`);
16
+ mkdirSync(runsDir, { recursive: true });
17
+ const stream = createWriteStream(logPath, { flags: 'a' });
18
+ return {
19
+ logPath,
20
+ log(payload) {
21
+ const line = {
22
+ ts: new Date().toISOString(),
23
+ run_id: shortId,
24
+ ...payload,
25
+ };
26
+ if (stream.writable) {
27
+ stream.write(JSON.stringify(line) + '\n');
28
+ }
29
+ },
30
+ close() {
31
+ return new Promise((resolve) => {
32
+ stream.end(() => resolve());
33
+ });
34
+ },
35
+ };
36
+ }
37
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,4BAA4B;AAC5B,sDAAsD;AAEtD,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,SAAS,UAAU,CAAC,KAAa;IAC/B,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAC3B,CAAC;AAED,SAAS,eAAe;IACtB,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACrC,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAC;AAChE,CAAC;AAQD,MAAM,UAAU,eAAe,CAAC,OAAe,EAAE,KAAa,EAAE,QAAgB;IAC9E,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IAClC,MAAM,IAAI,GAAG,eAAe,EAAE,CAAC;IAC/B,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,EAAE,GAAG,IAAI,IAAI,QAAQ,IAAI,OAAO,QAAQ,CAAC,CAAC;IAEzE,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;IAE1D,OAAO;QACL,OAAO;QAEP,GAAG,CAAC,OAAgC;YAClC,MAAM,IAAI,GAAG;gBACX,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBAC5B,MAAM,EAAE,OAAO;gBACf,GAAG,OAAO;aACX,CAAC;YACF,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;gBACpB,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC;QAED,KAAK;YACH,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;gBAC7B,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;YAC9B,CAAC,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,13 @@
1
+ export interface PlanLimits {
2
+ runs_per_day: number;
3
+ max_concurrent: number;
4
+ max_tokens_per_run: number;
5
+ rate_limit_per_minute: number;
6
+ }
7
+ export type PlansConfig = Record<string, PlanLimits>;
8
+ export declare const DEFAULT_PLANS: PlansConfig;
9
+ /** Merge user-supplied partial plans with defaults. Unknown plans fall back to 'free'. */
10
+ export declare function resolvePlans(configPlans?: Record<string, PlanLimits>): PlansConfig;
11
+ /** Get plan limits for a user, defaulting to 'free' if plan is unknown. */
12
+ export declare function getPlanLimits(plans: PlansConfig, planName: string): PlanLimits;
13
+ //# sourceMappingURL=plans.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plans.d.ts","sourceRoot":"","sources":["../src/plans.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,UAAU;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,qBAAqB,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AAErD,eAAO,MAAM,aAAa,EAAE,WAmB3B,CAAC;AAEF,0FAA0F;AAC1F,wBAAgB,YAAY,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,WAAW,CAGlF;AAED,2EAA2E;AAC3E,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,GAAG,UAAU,CAE9E"}
package/dist/plans.js ADDED
@@ -0,0 +1,33 @@
1
+ // api/src/plans.ts
2
+ // Plan configuration types and default plans
3
+ export const DEFAULT_PLANS = {
4
+ free: {
5
+ runs_per_day: 5,
6
+ max_concurrent: 1,
7
+ max_tokens_per_run: 50_000,
8
+ rate_limit_per_minute: 10,
9
+ },
10
+ pro: {
11
+ runs_per_day: 100,
12
+ max_concurrent: 5,
13
+ max_tokens_per_run: 500_000,
14
+ rate_limit_per_minute: 60,
15
+ },
16
+ unlimited: {
17
+ runs_per_day: -1,
18
+ max_concurrent: 20,
19
+ max_tokens_per_run: -1,
20
+ rate_limit_per_minute: 300,
21
+ },
22
+ };
23
+ /** Merge user-supplied partial plans with defaults. Unknown plans fall back to 'free'. */
24
+ export function resolvePlans(configPlans) {
25
+ if (!configPlans)
26
+ return DEFAULT_PLANS;
27
+ return { ...DEFAULT_PLANS, ...configPlans };
28
+ }
29
+ /** Get plan limits for a user, defaulting to 'free' if plan is unknown. */
30
+ export function getPlanLimits(plans, planName) {
31
+ return plans[planName] ?? plans.free ?? DEFAULT_PLANS.free;
32
+ }
33
+ //# sourceMappingURL=plans.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plans.js","sourceRoot":"","sources":["../src/plans.ts"],"names":[],"mappings":"AAAA,mBAAmB;AACnB,6CAA6C;AAW7C,MAAM,CAAC,MAAM,aAAa,GAAgB;IACxC,IAAI,EAAE;QACJ,YAAY,EAAE,CAAC;QACf,cAAc,EAAE,CAAC;QACjB,kBAAkB,EAAE,MAAM;QAC1B,qBAAqB,EAAE,EAAE;KAC1B;IACD,GAAG,EAAE;QACH,YAAY,EAAE,GAAG;QACjB,cAAc,EAAE,CAAC;QACjB,kBAAkB,EAAE,OAAO;QAC3B,qBAAqB,EAAE,EAAE;KAC1B;IACD,SAAS,EAAE;QACT,YAAY,EAAE,CAAC,CAAC;QAChB,cAAc,EAAE,EAAE;QAClB,kBAAkB,EAAE,CAAC,CAAC;QACtB,qBAAqB,EAAE,GAAG;KAC3B;CACF,CAAC;AAEF,0FAA0F;AAC1F,MAAM,UAAU,YAAY,CAAC,WAAwC;IACnE,IAAI,CAAC,WAAW;QAAE,OAAO,aAAa,CAAC;IACvC,OAAO,EAAE,GAAG,aAAa,EAAE,GAAG,WAAW,EAAE,CAAC;AAC9C,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,aAAa,CAAC,KAAkB,EAAE,QAAgB;IAChE,OAAO,KAAK,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC,IAAI,IAAI,aAAa,CAAC,IAAI,CAAC;AAC7D,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { FastifyInstance } from 'fastify';
2
+ import type { ServerDeps } from '../server.js';
3
+ export declare function agentsRoutes(fastify: FastifyInstance, options: {
4
+ deps: ServerDeps;
5
+ }): Promise<void>;
6
+ //# sourceMappingURL=agents.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/routes/agents.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C,wBAAsB,YAAY,CAChC,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,GAC5B,OAAO,CAAC,IAAI,CAAC,CAyHf"}
@@ -0,0 +1,118 @@
1
+ import { readdir, readFile, writeFile, unlink, mkdir } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ import * as yaml from 'js-yaml';
4
+ export async function agentsRoutes(fastify, options) {
5
+ const agentsDir = join(options.deps.configsDir, 'agents');
6
+ const errorSchema = { type: 'object', properties: { error: { type: 'string' } } };
7
+ // GET /api/agents
8
+ fastify.get('/agents', {
9
+ schema: {
10
+ tags: ['agents'],
11
+ summary: 'List all agent names',
12
+ response: {
13
+ 200: {
14
+ type: 'object',
15
+ properties: {
16
+ agents: { type: 'array', items: { type: 'string' } },
17
+ },
18
+ },
19
+ },
20
+ },
21
+ }, async (_request, reply) => {
22
+ let entries;
23
+ try {
24
+ entries = await readdir(agentsDir);
25
+ }
26
+ catch {
27
+ return reply.send({ agents: [] });
28
+ }
29
+ const agents = entries
30
+ .filter(f => f.endsWith('.agent.yaml'))
31
+ .map(f => f.slice(0, -'.agent.yaml'.length));
32
+ return reply.send({ agents });
33
+ });
34
+ // GET /api/agents/:name
35
+ fastify.get('/agents/:name', {
36
+ schema: {
37
+ tags: ['agents'],
38
+ summary: 'Get an agent by name',
39
+ params: {
40
+ type: 'object',
41
+ properties: { name: { type: 'string' } },
42
+ required: ['name'],
43
+ },
44
+ response: {
45
+ 200: { type: 'object', additionalProperties: true },
46
+ 404: errorSchema,
47
+ },
48
+ },
49
+ }, async (request, reply) => {
50
+ const filePath = join(agentsDir, `${request.params.name}.agent.yaml`);
51
+ let content;
52
+ try {
53
+ content = await readFile(filePath, 'utf-8');
54
+ }
55
+ catch {
56
+ return reply.status(404).send({ error: 'Agent not found' });
57
+ }
58
+ return reply.send(yaml.load(content));
59
+ });
60
+ // PUT /api/agents/:name
61
+ fastify.put('/agents/:name', {
62
+ schema: {
63
+ tags: ['agents'],
64
+ summary: 'Create or update an agent',
65
+ params: {
66
+ type: 'object',
67
+ properties: { name: { type: 'string' } },
68
+ required: ['name'],
69
+ },
70
+ body: { type: 'object' },
71
+ response: {
72
+ 200: {
73
+ type: 'object',
74
+ properties: {
75
+ name: { type: 'string' },
76
+ content: { type: 'object', additionalProperties: true },
77
+ },
78
+ },
79
+ 400: errorSchema,
80
+ },
81
+ },
82
+ }, async (request, reply) => {
83
+ const body = request.body;
84
+ if (!body['name'] || typeof body['name'] !== 'string') {
85
+ return reply.status(400).send({ error: "Agent must have a 'name' field (string)" });
86
+ }
87
+ await mkdir(agentsDir, { recursive: true });
88
+ const filePath = join(agentsDir, `${request.params.name}.agent.yaml`);
89
+ await writeFile(filePath, yaml.dump(body), 'utf-8');
90
+ return reply.send({ name: request.params.name, content: body });
91
+ });
92
+ // DELETE /api/agents/:name
93
+ fastify.delete('/agents/:name', {
94
+ schema: {
95
+ tags: ['agents'],
96
+ summary: 'Delete an agent',
97
+ params: {
98
+ type: 'object',
99
+ properties: { name: { type: 'string' } },
100
+ required: ['name'],
101
+ },
102
+ response: {
103
+ 204: { type: 'null', description: 'No content' },
104
+ 404: errorSchema,
105
+ },
106
+ },
107
+ }, async (request, reply) => {
108
+ const filePath = join(agentsDir, `${request.params.name}.agent.yaml`);
109
+ try {
110
+ await unlink(filePath);
111
+ }
112
+ catch {
113
+ return reply.status(404).send({ error: 'Agent not found' });
114
+ }
115
+ return reply.status(204).send();
116
+ });
117
+ }
118
+ //# sourceMappingURL=agents.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agents.js","sourceRoot":"","sources":["../../src/routes/agents.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC/E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,KAAK,IAAI,MAAM,SAAS,CAAC;AAIhC,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,OAAwB,EACxB,OAA6B;IAE7B,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IAE1D,MAAM,WAAW,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAElF,kBAAkB;IAClB,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE;QACrB,MAAM,EAAE;YACN,IAAI,EAAE,CAAC,QAAQ,CAAC;YAChB,OAAO,EAAE,sBAAsB;YAC/B,QAAQ,EAAE;gBACR,GAAG,EAAE;oBACH,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,MAAM,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;qBACrD;iBACF;aACF;SACF;KACF,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE;QAC3B,IAAI,OAAiB,CAAC;QACtB,IAAI,CAAC;YACH,OAAO,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,CAAC;QACrC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC;QACpC,CAAC;QACD,MAAM,MAAM,GAAG,OAAO;aACnB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;aACtC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC;QAC/C,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,wBAAwB;IACxB,OAAO,CAAC,GAAG,CAA+B,eAAe,EAAE;QACzD,MAAM,EAAE;YACN,IAAI,EAAE,CAAC,QAAQ,CAAC;YAChB,OAAO,EAAE,sBAAsB;YAC/B,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;gBACxC,QAAQ,EAAE,CAAC,MAAM,CAAC;aACnB;YACD,QAAQ,EAAE;gBACR,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,oBAAoB,EAAE,IAAI,EAAE;gBACnD,GAAG,EAAE,WAAW;aACjB;SACF;KACF,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QAC1B,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,aAAa,CAAC,CAAC;QACtE,IAAI,OAAe,CAAC;QACpB,IAAI,CAAC;YACH,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC9C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC,CAAC;QAC9D,CAAC;QACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,wBAAwB;IACxB,OAAO,CAAC,GAAG,CAGR,eAAe,EAAE;QAClB,MAAM,EAAE;YACN,IAAI,EAAE,CAAC,QAAQ,CAAC;YAChB,OAAO,EAAE,2BAA2B;YACpC,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;gBACxC,QAAQ,EAAE,CAAC,MAAM,CAAC;aACnB;YACD,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;YACxB,QAAQ,EAAE;gBACR,GAAG,EAAE;oBACH,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;wBACxB,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,oBAAoB,EAAE,IAAI,EAAE;qBACxD;iBACF;gBACD,GAAG,EAAE,WAAW;aACjB;SACF;KACF,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QAC1B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QAE1B,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,QAAQ,EAAE,CAAC;YACtD,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,yCAAyC,EAAE,CAAC,CAAC;QACtF,CAAC;QAED,MAAM,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5C,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,aAAa,CAAC,CAAC;QACtE,MAAM,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;QAEpD,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;IAEH,2BAA2B;IAC3B,OAAO,CAAC,MAAM,CAA+B,eAAe,EAAE;QAC5D,MAAM,EAAE;YACN,IAAI,EAAE,CAAC,QAAQ,CAAC;YAChB,OAAO,EAAE,iBAAiB;YAC1B,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;gBACxC,QAAQ,EAAE,CAAC,MAAM,CAAC;aACnB;YACD,QAAQ,EAAE;gBACR,GAAG,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE;gBAChD,GAAG,EAAE,WAAW;aACjB;SACF;KACF,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QAC1B,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,aAAa,CAAC,CAAC;QACtE,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;QACzB,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC,CAAC;QAC9D,CAAC;QACD,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAClC,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { FastifyInstance } from 'fastify';
2
+ import type { ServerDeps } from '../server.js';
3
+ export declare function configRoutes(fastify: FastifyInstance, options: {
4
+ deps: ServerDeps;
5
+ }): Promise<void>;
6
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/routes/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAgC/C,wBAAsB,YAAY,CAChC,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,GAC5B,OAAO,CAAC,IAAI,CAAC,CAkHf"}
@@ -0,0 +1,129 @@
1
+ import { readFile, writeFile, mkdir } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ import * as yaml from 'js-yaml';
4
+ const KNOWN_PROVIDERS = new Set(['anthropic', 'openai', 'ollama']);
5
+ async function readConfig(configsDir) {
6
+ try {
7
+ const content = await readFile(join(configsDir, 'config.yaml'), 'utf-8');
8
+ return yaml.load(content) ?? {};
9
+ }
10
+ catch {
11
+ return {};
12
+ }
13
+ }
14
+ async function writeConfig(configsDir, config) {
15
+ await mkdir(configsDir, { recursive: true });
16
+ await writeFile(join(configsDir, 'config.yaml'), yaml.dump(config), 'utf-8');
17
+ }
18
+ function maskConfig(config) {
19
+ if (!config.providers)
20
+ return config;
21
+ const maskedProviders = {};
22
+ for (const [name, provider] of Object.entries(config.providers)) {
23
+ maskedProviders[name] = { apiKey: provider.apiKey ? '***' : '' };
24
+ }
25
+ return { ...config, providers: maskedProviders };
26
+ }
27
+ export async function configRoutes(fastify, options) {
28
+ const { configsDir } = options.deps;
29
+ const configResponseSchema = {
30
+ type: 'object',
31
+ properties: {
32
+ providers: {
33
+ type: 'object',
34
+ additionalProperties: {
35
+ type: 'object',
36
+ properties: { apiKey: { type: 'string' } },
37
+ },
38
+ },
39
+ defaults: {
40
+ type: 'object',
41
+ properties: {
42
+ provider: { type: 'string' },
43
+ model: { type: 'string' },
44
+ },
45
+ },
46
+ },
47
+ };
48
+ // GET /api/config
49
+ fastify.get('/config', {
50
+ schema: {
51
+ tags: ['config'],
52
+ summary: 'Get current config',
53
+ response: {
54
+ 200: configResponseSchema,
55
+ },
56
+ },
57
+ }, async (_request, reply) => {
58
+ const config = await readConfig(configsDir);
59
+ return reply.send({
60
+ providers: {},
61
+ ...maskConfig(config),
62
+ });
63
+ });
64
+ // PATCH /api/config
65
+ fastify.patch('/config', {
66
+ schema: {
67
+ tags: ['config'],
68
+ summary: 'Patch config (merge defaults and providers)',
69
+ body: { type: 'object' },
70
+ response: {
71
+ 200: configResponseSchema,
72
+ },
73
+ },
74
+ }, async (request, reply) => {
75
+ const config = await readConfig(configsDir);
76
+ const patch = request.body;
77
+ if (patch.defaults) {
78
+ config.defaults = { ...config.defaults, ...patch.defaults };
79
+ }
80
+ if (patch.providers) {
81
+ config.providers = { ...config.providers, ...patch.providers };
82
+ }
83
+ await writeConfig(configsDir, config);
84
+ return reply.send({
85
+ providers: {},
86
+ ...maskConfig(config),
87
+ });
88
+ });
89
+ // POST /api/config/providers
90
+ fastify.post('/config/providers', {
91
+ schema: {
92
+ tags: ['config'],
93
+ summary: 'Add or update a provider',
94
+ body: {
95
+ type: 'object',
96
+ required: ['provider', 'apiKeyEnvVar'],
97
+ properties: {
98
+ provider: { type: 'string' },
99
+ apiKeyEnvVar: { type: 'string' },
100
+ },
101
+ },
102
+ response: {
103
+ 200: configResponseSchema,
104
+ 400: {
105
+ type: 'object',
106
+ properties: { error: { type: 'string' } },
107
+ },
108
+ },
109
+ },
110
+ }, async (request, reply) => {
111
+ const { provider, apiKeyEnvVar } = request.body;
112
+ if (!KNOWN_PROVIDERS.has(provider)) {
113
+ return reply.status(400).send({
114
+ error: `Unknown provider: '${provider}'. Supported: ${[...KNOWN_PROVIDERS].join(', ')}`,
115
+ });
116
+ }
117
+ const config = await readConfig(configsDir);
118
+ config.providers = {
119
+ ...config.providers,
120
+ [provider]: { apiKey: `\${${apiKeyEnvVar}}` },
121
+ };
122
+ await writeConfig(configsDir, config);
123
+ return reply.send({
124
+ providers: {},
125
+ ...maskConfig(config),
126
+ });
127
+ });
128
+ }
129
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/routes/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { FastifyInstance } from 'fastify';
2
+ import type { ServerDeps } from '../server.js';
3
+ export declare function contractsRoutes(fastify: FastifyInstance, options: {
4
+ deps: ServerDeps;
5
+ }): Promise<void>;
6
+ //# sourceMappingURL=contracts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../../src/routes/contracts.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAI/C,wBAAsB,eAAe,CACnC,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,GAC5B,OAAO,CAAC,IAAI,CAAC,CAiMf"}