@desplega.ai/agent-swarm 1.129.0 → 1.131.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (226) hide show
  1. package/README.md +2 -2
  2. package/dist/{actions-kfv2dawe.js → actions-w53mbns9.js} +11 -11
  3. package/dist/{anthropic-messages-3xgme8my.js → anthropic-messages-rjmd2e7n.js} +5 -5
  4. package/dist/{app-q8vjk6e8.js → app-m9gwqsqv.js} +8 -8
  5. package/dist/{artifact-hg4t1nx7.js → artifact-jysj3wrg.js} +2 -2
  6. package/dist/{assistant-g037r345.js → assistant-bp65m6f3.js} +13 -13
  7. package/dist/{azure-openai-responses-xa4sh9f6.js → azure-openai-responses-c0yjmbfd.js} +8 -5
  8. package/dist/{boot-reembed-18pzsrxa.js → boot-reembed-62p0at2k.js} +6 -6
  9. package/dist/{boot-reembed-wpks2cj8.js → boot-reembed-xmfp6wdh.js} +7 -7
  10. package/dist/{boot-scrub-logs-n7szd57r.js → boot-scrub-logs-rr8q2dms.js} +5 -5
  11. package/dist/{claude-adapter-qz4r0ajt.js → claude-adapter-2y47mrkd.js} +9 -9
  12. package/dist/{cli-mhjnbgb6.js → cli-0rcyq6d9.js} +450 -186
  13. package/dist/{cli-ttkmehy0.js → cli-2q72qz2s.js} +274 -25
  14. package/dist/{cli-gztgc3hz.js → cli-2wadx7p2.js} +2 -2
  15. package/dist/cli-3fj60etf.js +153 -0
  16. package/dist/{cli-7ecgm5v0.js → cli-3kf51j15.js} +1 -1
  17. package/dist/{cli-vgexpfsr.js → cli-57khth04.js} +6 -3
  18. package/dist/{cli-2mbe7vk0.js → cli-5dsbcjjw.js} +1 -1
  19. package/dist/{cli-etr62zy6.js → cli-5kx36evn.js} +2 -2
  20. package/dist/{cli-v2tr6amf.js → cli-5n6e5yfn.js} +30 -8
  21. package/dist/{cli-hx02s9zq.js → cli-5v4rw6yd.js} +2 -2
  22. package/dist/{cli-v37yr6mf.js → cli-5ze9rv97.js} +4 -4
  23. package/dist/{cli-ch7t5v7n.js → cli-6map995v.js} +9 -4
  24. package/dist/{cli-h0457a67.js → cli-70xqj0z3.js} +3 -3
  25. package/dist/{cli-kk4f9r17.js → cli-72q8m8gk.js} +8 -6
  26. package/dist/{cli-7padk69a.js → cli-78xwvkhj.js} +2 -2
  27. package/dist/{cli-dxtxacy7.js → cli-9dr5qzc0.js} +45 -8
  28. package/dist/{cli-17zxdgsq.js → cli-a40rnf71.js} +6 -6
  29. package/dist/{cli-t53vnnxz.js → cli-a4jzdpa3.js} +2514 -1055
  30. package/dist/{cli-w10fkrf1.js → cli-akdvwc9v.js} +354 -115
  31. package/dist/{cli-1qkk5er0.js → cli-bmze986d.js} +1 -1
  32. package/dist/{cli-ga12dc1d.js → cli-bqw0mt1n.js} +3 -3
  33. package/dist/{cli-0sf92efp.js → cli-cdeg08wx.js} +1 -1
  34. package/dist/{cli-a8ynhkyj.js → cli-cvgjwnh1.js} +17 -15
  35. package/dist/{cli-9fxg3v5m.js → cli-d2tfkcga.js} +4 -4
  36. package/dist/{cli-nhcd7x43.js → cli-d3x3x1c9.js} +2 -2
  37. package/dist/{cli-6nh2qxvh.js → cli-darcwax3.js} +1 -1
  38. package/dist/{cli-yjbgmysx.js → cli-e7ckcg4v.js} +12 -12
  39. package/dist/{cli-4n2gcjpd.js → cli-efxfnq6q.js} +4 -3
  40. package/dist/{cli-z9xqqhfk.js → cli-er3a4bb0.js} +1 -1
  41. package/dist/{cli-xg2eezyv.js → cli-f1am9szv.js} +1 -1
  42. package/dist/{cli-xy4cwsm9.js → cli-fywms69x.js} +1 -1
  43. package/dist/{cli-33jj76y8.js → cli-g6b8x1h8.js} +1 -1
  44. package/dist/{cli-epsvdckx.js → cli-gm9cbhbq.js} +20 -10
  45. package/dist/{cli-rkndnn90.js → cli-k9qkf1hw.js} +6 -4
  46. package/dist/{cli-zejvt395.js → cli-kh3ba2zf.js} +1 -1
  47. package/dist/{cli-gb25p1h2.js → cli-nm5gtp1x.js} +2 -2
  48. package/dist/{cli-akxnpx17.js → cli-pm6xbh84.js} +1829 -1629
  49. package/dist/{cli-2k0ztbfp.js → cli-psh3c4va.js} +1 -1
  50. package/dist/{cli-39vgrsep.js → cli-qv61hp37.js} +2 -2
  51. package/dist/{cli-hv2fndhm.js → cli-r6kqqbj0.js} +6 -4
  52. package/dist/{cli-1y1cm570.js → cli-rzbpmxdr.js} +1 -1
  53. package/dist/{cli-mmrk00vp.js → cli-t1xze5qh.js} +1 -1
  54. package/dist/{cli-g252a9ky.js → cli-t55yw3a1.js} +2 -2
  55. package/dist/{cli-7bz8dzqa.js → cli-t76vw5db.js} +1184 -1522
  56. package/dist/{cli-4n4mdv21.js → cli-xpxde7rm.js} +7 -3
  57. package/dist/{cli-fpaa5k2q.js → cli-yw8vghx2.js} +54 -18
  58. package/dist/cli-zsspvvm2.js +490 -0
  59. package/dist/cli.js +27 -25
  60. package/dist/{codex-adapter-7v6t7ff6.js → codex-adapter-d24q75wk.js} +7 -7
  61. package/dist/{codex-hook-amndawyb.js → codex-hook-hq54t9ft.js} +2 -2
  62. package/dist/{codex-session-runner-e7j4khe2.js → codex-session-runner-g50vcsex.js} +7 -7
  63. package/dist/{commands-ex0k5tbf.js → commands-c3nrc5hg.js} +5 -5
  64. package/dist/{db-df7jatfc.js → db-nt7fg3tw.js} +5 -5
  65. package/dist/{google-generative-ai-y42hnw9p.js → google-generative-ai-hysrd8qx.js} +7 -5
  66. package/dist/{google-vertex-4sg66gb6.js → google-vertex-p5arrga0.js} +7 -5
  67. package/dist/{handlers-1j2cfqt2.js → handlers-fkr6swat.js} +13 -13
  68. package/dist/{hook-nx9a0mj3.js → hook-77wpvnjc.js} +7 -7
  69. package/dist/{hook-w6yaf6sy.js → hook-g019yehy.js} +8 -8
  70. package/dist/{http-4tz5h8wg.js → http-jewj0syk.js} +2993 -716
  71. package/dist/{index-0bpkzb09.js → index-070v4eyb.js} +3 -3
  72. package/dist/{index-0s67qv7h.js → index-6gm5he8h.js} +11 -11
  73. package/dist/{index-35gtv6gj.js → index-7n2xpbd4.js} +310 -40
  74. package/dist/{index-ker3gccb.js → index-9znhar3x.js} +4 -4
  75. package/dist/{index-5n2c8yay.js → index-hase6zbe.js} +2 -2
  76. package/dist/{index-kcf3tm9h.js → index-hfvggd0z.js} +12 -12
  77. package/dist/{index-7c0jqna0.js → index-hp1kdbjj.js} +13 -13
  78. package/dist/{keepalive-3j4a9168.js → keepalive-j0fjvqfd.js} +7 -7
  79. package/dist/{lead-6kpevymb.js → lead-1n8x30xe.js} +33 -33
  80. package/dist/{maintenance-m1k82ean.js → maintenance-gvev11sa.js} +7 -7
  81. package/dist/{mistral-conversations-bjkdfb6z.js → mistral-conversations-81fwav0j.js} +6 -6
  82. package/dist/{oauth-refresh-sweep-881k8e4q.js → oauth-refresh-sweep-s9ecsvh0.js} +6 -6
  83. package/dist/{onboard-c0ykffjn.js → onboard-pvm5b38w.js} +2 -2
  84. package/dist/{openai-codex-responses-xetseqvt.js → openai-codex-responses-5g27pd6f.js} +43 -23
  85. package/dist/{openai-completions-5r2g5axa.js → openai-completions-3vkmfz2a.js} +55 -11
  86. package/dist/{openai-responses-ce67hd23.js → openai-responses-dg4t7j7a.js} +8 -5
  87. package/dist/{openrouter-images-pzfp22jb.js → openrouter-images-g3gm8931.js} +1 -1
  88. package/dist/{otel-impl-sqagjerv.js → otel-impl-p6jvgd9c.js} +6 -4
  89. package/dist/{otel-3mp81ppd.js → otel-nqa12wf3.js} +2 -2
  90. package/dist/{pi-mono-adapter-k584k16g.js → pi-mono-adapter-t091s27g.js} +17117 -7517
  91. package/dist/{pricing-refresh-y82whbf9.js → pricing-refresh-k49rcyed.js} +7 -7
  92. package/dist/{rbac-roles-nvkqmzyd.js → rbac-roles-30pspvy7.js} +7 -7
  93. package/dist/{rbac-roles-4ht8gegc.js → rbac-roles-cr80g96t.js} +6 -6
  94. package/dist/{render-v2-wvqdgvvp.js → render-v2-xm457ng1.js} +8 -8
  95. package/dist/{seed-pricing-fy3rxhde.js → seed-pricing-yhpv35fr.js} +6 -6
  96. package/dist/{setup-ak5cnc6f.js → setup-nytnmwwr.js} +2 -2
  97. package/dist/{worker-d8769q8a.js → worker-msytr2cw.js} +33 -33
  98. package/openapi.json +34039 -11036
  99. package/package.json +8 -6
  100. package/src/apps/definition.ts +368 -26
  101. package/src/apps/row-store.ts +66 -10
  102. package/src/apps/schema-migrate.ts +95 -1
  103. package/src/apps/store.ts +13 -4
  104. package/src/apps/sync-run-as.ts +18 -0
  105. package/src/apps/sync.ts +934 -0
  106. package/src/apps/version.ts +16 -2
  107. package/src/assets/key.ts +8 -1
  108. package/src/be/asset-key-audit.ts +3 -1
  109. package/src/be/db-queries/mcp-oauth.ts +297 -24
  110. package/src/be/db.ts +42 -1
  111. package/src/be/migrations/129_asset_keys_apps_scripts.sql +161 -0
  112. package/src/be/scripts/db.ts +5 -2
  113. package/src/be/scripts/typecheck.ts +1 -0
  114. package/src/be/seed-scripts/catalog/app-sync-run.ts +32 -0
  115. package/src/be/seed-scripts/catalog/github-issues-pull.ts +102 -0
  116. package/src/be/seed-scripts/index.ts +18 -0
  117. package/src/be/seed-skills/index.ts +7 -0
  118. package/src/http/active-sessions.ts +26 -18
  119. package/src/http/agents.ts +94 -27
  120. package/src/http/api-keys.ts +91 -17
  121. package/src/http/approval-requests.ts +87 -10
  122. package/src/http/apps.ts +361 -53
  123. package/src/http/assets.ts +165 -31
  124. package/src/http/budgets.ts +7 -5
  125. package/src/http/codex-oauth-keep-warm.ts +21 -3
  126. package/src/http/config.ts +46 -16
  127. package/src/http/context.ts +33 -6
  128. package/src/http/ecosystem.ts +20 -6
  129. package/src/http/events.ts +24 -9
  130. package/src/http/favorites.ts +20 -6
  131. package/src/http/fs.ts +60 -17
  132. package/src/http/heartbeat.ts +18 -4
  133. package/src/http/inbox-state.ts +12 -6
  134. package/src/http/integrations.ts +25 -5
  135. package/src/http/kv.ts +36 -15
  136. package/src/http/mcp-bridge.ts +5 -1
  137. package/src/http/mcp-oauth.ts +332 -17
  138. package/src/http/mcp-servers.ts +56 -18
  139. package/src/http/memory.ts +282 -29
  140. package/src/http/metrics.ts +80 -17
  141. package/src/http/oauth-callback.ts +10 -4
  142. package/src/http/oauth-generic.ts +5 -1
  143. package/src/http/oauth-locks.ts +6 -3
  144. package/src/http/openapi.ts +57 -9
  145. package/src/http/page-proxy.ts +25 -5
  146. package/src/http/pages-public.ts +37 -20
  147. package/src/http/pages.ts +93 -28
  148. package/src/http/poll.ts +89 -5
  149. package/src/http/pricing.ts +9 -6
  150. package/src/http/prompt-templates.ts +85 -21
  151. package/src/http/route-def.ts +67 -4
  152. package/src/http/schedules.ts +63 -14
  153. package/src/http/script-connection-proxy.ts +30 -4
  154. package/src/http/script-connections.ts +393 -43
  155. package/src/http/script-runs.ts +73 -19
  156. package/src/http/scripts.ts +257 -39
  157. package/src/http/session-data.ts +87 -14
  158. package/src/http/sessions.ts +80 -5
  159. package/src/http/skills.ts +115 -35
  160. package/src/http/stats.ts +94 -13
  161. package/src/http/task-templates.ts +6 -4
  162. package/src/http/tasks.ts +230 -61
  163. package/src/http/trackers/jira.ts +90 -30
  164. package/src/http/trackers/linear.ts +46 -12
  165. package/src/http/users.ts +162 -25
  166. package/src/http/utils.ts +12 -2
  167. package/src/http/webhooks.ts +30 -16
  168. package/src/http/workflow-events.ts +18 -5
  169. package/src/http/workflows.ts +128 -39
  170. package/src/http/x.ts +37 -6
  171. package/src/oauth/ensure-mcp-token.ts +16 -1
  172. package/src/oauth/mcp-wrapper.ts +281 -26
  173. package/src/providers/pi-mono-adapter.ts +1 -1
  174. package/src/scripts-runtime/credential-broker/README.md +1 -1
  175. package/src/scripts-runtime/credential-broker/fetch-patch.ts +12 -2
  176. package/src/scripts-runtime/sdk-allowlist.ts +1 -0
  177. package/src/scripts-runtime/stdlib/fetch.ts +6 -0
  178. package/src/scripts-runtime/types/stdlib.d.ts +1 -0
  179. package/src/scripts-runtime/types/swarm-sdk.d.ts +1 -0
  180. package/src/server.ts +2 -0
  181. package/src/tests/apps-rbac.test.ts +110 -0
  182. package/src/tests/apps-spike2.test.ts +4 -1
  183. package/src/tests/apps-sync-engine.test.ts +2540 -0
  184. package/src/tests/apps-sync.test.ts +1627 -0
  185. package/src/tests/asset-key-api.test.ts +48 -2
  186. package/src/tests/asset-key-invariants.test.ts +92 -0
  187. package/src/tests/asset-key-migration.test.ts +174 -8
  188. package/src/tests/asset-key-normalization.test.ts +2 -0
  189. package/src/tests/credential-broker.test.ts +27 -2
  190. package/src/tests/mcp-oauth-dcr-reuse.test.ts +743 -0
  191. package/src/tests/mcp-oauth-ensure-token.test.ts +45 -0
  192. package/src/tests/mcp-oauth-manual-client.test.ts +135 -2
  193. package/src/tests/mcp-oauth-queries.test.ts +153 -0
  194. package/src/tests/mcp-oauth-wrapper.test.ts +432 -0
  195. package/src/tests/memory-http-recall-gating.test.ts +2 -0
  196. package/src/tests/openapi-response-contract.test.ts +138 -0
  197. package/src/tests/rbac-admission-e2e.test.ts +68 -0
  198. package/src/tests/script-connections.test.ts +3 -0
  199. package/src/tests/scripts-runtime-fetch.test.ts +121 -0
  200. package/src/tests/scripts-runtime-secret-egress.test.ts +4 -2
  201. package/src/tests/seed-scripts.test.ts +2 -2
  202. package/src/tests/swarm-tool-result-gate.test.ts +32 -0
  203. package/src/tests/task-working-dir.test.ts +8 -4
  204. package/src/tests/whoami-route.test.ts +127 -0
  205. package/src/tests/workflow-engine-v2.test.ts +80 -7
  206. package/src/tests/workflow-swarm-script.test.ts +104 -0
  207. package/src/tools/app-get.ts +10 -2
  208. package/src/tools/app-rollback.ts +1 -0
  209. package/src/tools/app-sync.ts +112 -0
  210. package/src/tools/script-common.ts +20 -0
  211. package/src/tools/tool-config.ts +2 -1
  212. package/src/tools/utils.ts +11 -0
  213. package/src/tools/workflows/create-workflow.ts +4 -1
  214. package/src/types.ts +1394 -1206
  215. package/src/utils/template.ts +8 -1
  216. package/src/utils/zod-openapi.ts +11 -0
  217. package/src/workflows/engine.ts +27 -4
  218. package/src/workflows/executors/swarm-script.ts +28 -0
  219. package/src/workflows/retry-poller.ts +19 -2
  220. package/templates/skills/apps/content.md +94 -5
  221. package/templates/skills/asset-namespaces/content.md +2 -2
  222. package/templates/skills/scheduled-task-resilience/SKILL.md +102 -0
  223. package/templates/skills/scheduled-task-resilience/config.json +14 -0
  224. package/templates/skills/scheduled-task-resilience/content.md +97 -0
  225. package/dist/cli-7wmybrt5.js +0 -115
  226. package/dist/cli-d91pvmq1.js +0 -14
@@ -7,7 +7,7 @@ import {
7
7
  LlmRater,
8
8
  REFERENCES_SOURCE_MAX_LENGTH,
9
9
  sanitizeReferencesSource
10
- } from "./cli-gztgc3hz.js";
10
+ } from "./cli-2wadx7p2.js";
11
11
  import {
12
12
  createTrackerAgentMapping,
13
13
  createTrackerSync,
@@ -22,32 +22,34 @@ import {
22
22
  repointTrackerSyncBySwarmId,
23
23
  updateTrackerSync,
24
24
  updateTrackerSyncSwarmId
25
- } from "./cli-gb25p1h2.js";
25
+ } from "./cli-nm5gtp1x.js";
26
26
  import {
27
27
  calculateNextRun,
28
28
  ensure,
29
29
  require_dist,
30
30
  runScheduleNow
31
- } from "./cli-v37yr6mf.js";
31
+ } from "./cli-5ze9rv97.js";
32
32
  import {
33
33
  startPricingRefreshLoop
34
- } from "./cli-g252a9ky.js";
34
+ } from "./cli-t55yw3a1.js";
35
35
  import {
36
36
  seedPricingFromModelsDev
37
- } from "./cli-mmrk00vp.js";
37
+ } from "./cli-t1xze5qh.js";
38
38
  import {
39
39
  ensureRbacSeedsSynced,
40
40
  getUserGrant
41
- } from "./cli-hx02s9zq.js";
41
+ } from "./cli-5v4rw6yd.js";
42
42
  import {
43
43
  can,
44
44
  decideAdmission,
45
45
  isRbacEnabled
46
- } from "./cli-ga12dc1d.js";
46
+ } from "./cli-bqw0mt1n.js";
47
47
  import {
48
48
  AppDefinitionSchema,
49
49
  AppElementsSchema,
50
50
  AppNameSchema,
51
+ ColumnKindSchema,
52
+ SORTABLE_SYSTEM_DATE_COLUMNS,
51
53
  SYSTEM_COLUMN_KINDS,
52
54
  appDefinitionNeedsRepair,
53
55
  applyAppDefinitionPatch,
@@ -59,10 +61,11 @@ import {
59
61
  isIso8601Date,
60
62
  listApps,
61
63
  parseAppDefinition,
64
+ resolveSyncRunAs,
62
65
  runSavedScriptAsAgent,
63
66
  updateApp,
64
67
  upgradeAppDefinition
65
- } from "./cli-ttkmehy0.js";
68
+ } from "./cli-2q72qz2s.js";
66
69
  import {
67
70
  TriggerSchemaError,
68
71
  applyDefinitionPatch,
@@ -75,7 +78,7 @@ import {
75
78
  startWorkflowExecution,
76
79
  validateDefinition,
77
80
  validateJsonSchema
78
- } from "./cli-fpaa5k2q.js";
81
+ } from "./cli-yw8vghx2.js";
79
82
  import {
80
83
  ConnectionAuthInputSchema,
81
84
  SCRIPT_LONG_TIMEOUT_HINT_MS,
@@ -94,7 +97,7 @@ import {
94
97
  setScriptConnectionEnabled,
95
98
  upsertCredentialBinding,
96
99
  upsertScriptConnection
97
- } from "./cli-akxnpx17.js";
100
+ } from "./cli-pm6xbh84.js";
98
101
  import {
99
102
  getApiKey
100
103
  } from "./cli-f14fvzag.js";
@@ -109,7 +112,7 @@ import {
109
112
  isGraphExpansionEnabled,
110
113
  rerank,
111
114
  rowToCandidate
112
- } from "./cli-1y1cm570.js";
115
+ } from "./cli-rzbpmxdr.js";
113
116
  import {
114
117
  buildAuthorizationUrl,
115
118
  createOAuthApp,
@@ -124,7 +127,7 @@ import {
124
127
  listAuthorizationsForApp,
125
128
  onAuthorizationRefreshed,
126
129
  upsertOAuthApp
127
- } from "./cli-33jj76y8.js";
130
+ } from "./cli-g6b8x1h8.js";
128
131
  import {
129
132
  ZodFirstPartyTypeKind,
130
133
  objectType
@@ -133,7 +136,7 @@ import {
133
136
  createAdditiveBuffer,
134
137
  extractSlackMessageText,
135
138
  parseSlackTs
136
- } from "./cli-nhcd7x43.js";
139
+ } from "./cli-d3x3x1c9.js";
137
140
  import {
138
141
  findOrCreateUserByEmail,
139
142
  findUserByExternalId,
@@ -149,10 +152,10 @@ import {
149
152
  resolveIdentityByEmail,
150
153
  resolveUserByToken,
151
154
  unlinkIdentity
152
- } from "./cli-2k0ztbfp.js";
155
+ } from "./cli-psh3c4va.js";
153
156
  import {
154
157
  createTaskWithSiblingAwareness
155
- } from "./cli-0sf92efp.js";
158
+ } from "./cli-cdeg08wx.js";
156
159
  import {
157
160
  getAgentDisplayName,
158
161
  getAgentEmoji,
@@ -161,8 +164,10 @@ import {
161
164
  markdownToSlack,
162
165
  startSlackApp,
163
166
  stopSlackApp
164
- } from "./cli-a8ynhkyj.js";
167
+ } from "./cli-cvgjwnh1.js";
165
168
  import {
169
+ $OpenAPIRegistry,
170
+ $OpenApiGeneratorV31,
166
171
  AgentAvatarSchema,
167
172
  AgentMemoryScopeSchema,
168
173
  AgentMemorySourceSchema,
@@ -332,6 +337,7 @@ import {
332
337
  init_credential_broker,
333
338
  init_db,
334
339
  init_defaults,
340
+ init_dist,
335
341
  init_key,
336
342
  init_request_auth_context,
337
343
  init_slack_routing,
@@ -339,6 +345,7 @@ import {
339
345
  init_swarm_config_guard,
340
346
  init_task_lifecycle_events,
341
347
  init_types,
348
+ init_zod_openapi,
342
349
  insertTaskAttachment,
343
350
  installMcpServer,
344
351
  installSkill,
@@ -403,7 +410,7 @@ import {
403
410
  upsertService,
404
411
  upsertSwarmConfig,
405
412
  validateConfigValue
406
- } from "./cli-t53vnnxz.js";
413
+ } from "./cli-a4jzdpa3.js";
407
414
  import {
408
415
  getTemplateDefinition,
409
416
  init_env_flag,
@@ -415,7 +422,7 @@ import {
415
422
  parseEnvFlag,
416
423
  registerTemplate,
417
424
  resolveTemplate
418
- } from "./cli-4n4mdv21.js";
425
+ } from "./cli-xpxde7rm.js";
419
426
  import {
420
427
  MAX_PROFILE_FILE_LENGTH,
421
428
  getAppUrl,
@@ -424,8 +431,9 @@ import {
424
431
  init_constants
425
432
  } from "./cli-x23me2mg.js";
426
433
  import {
434
+ exports_zod,
427
435
  init_zod
428
- } from "./cli-d91pvmq1.js";
436
+ } from "./cli-zsspvvm2.js";
429
437
  import {
430
438
  init_secret_scrubber,
431
439
  refreshSecretScrubberCache,
@@ -436,7 +444,7 @@ import {
436
444
  import {
437
445
  init_package,
438
446
  package_default
439
- } from "./cli-kk4f9r17.js";
447
+ } from "./cli-72q8m8gk.js";
440
448
  import {
441
449
  $ZodObject,
442
450
  $ZodType,
@@ -475,7 +483,7 @@ import {
475
483
  union,
476
484
  unknown,
477
485
  uuid
478
- } from "./cli-2mbe7vk0.js";
486
+ } from "./cli-5dsbcjjw.js";
479
487
  import {
480
488
  init_event_bus,
481
489
  workflowEventBus
@@ -22893,7 +22901,7 @@ async function notifySlack(text) {
22893
22901
  return;
22894
22902
  }
22895
22903
  try {
22896
- const { getSlackApp: getSlackApp2 } = await import("./app-q8vjk6e8.js");
22904
+ const { getSlackApp: getSlackApp2 } = await import("./app-m9gwqsqv.js");
22897
22905
  const app = getSlackApp2();
22898
22906
  if (!app) {
22899
22907
  console.warn("[Jira webhook keepalive] Slack not available, cannot send notification");
@@ -22964,7 +22972,7 @@ async function deleteJiraWebhook(webhookId) {
22964
22972
  console.log(`[Jira webhook keepalive] Deleted webhook id=${webhookId}`);
22965
22973
  }
22966
22974
  async function overwriteWebhookIds(next) {
22967
- const { getDb: getDb2 } = await import("./db-df7jatfc.js");
22975
+ const { getDb: getDb2 } = await import("./db-nt7fg3tw.js");
22968
22976
  const db = getDb2();
22969
22977
  const txn = db.transaction(() => {
22970
22978
  const row = db.query("SELECT metadata FROM oauth_apps WHERE provider = 'jira'").get();
@@ -95816,1431 +95824,10 @@ function isActiveUser(user) {
95816
95824
  return !!user && user.status === "active";
95817
95825
  }
95818
95826
 
95819
- // node_modules/@asteasolutions/zod-to-openapi/dist/index.cjs
95820
- function __rest(s, e) {
95821
- var t = {};
95822
- for (var p in s)
95823
- if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
95824
- t[p] = s[p];
95825
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
95826
- for (var i = 0, p = Object.getOwnPropertySymbols(s);i < p.length; i++) {
95827
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
95828
- t[p[i]] = s[p[i]];
95829
- }
95830
- return t;
95831
- }
95832
- var ZodTypeKeys = {
95833
- ZodAny: "any",
95834
- ZodArray: "array",
95835
- ZodBigInt: "bigint",
95836
- ZodBoolean: "boolean",
95837
- ZodDefault: "default",
95838
- ZodPrefault: "prefault",
95839
- ZodTransform: "transform",
95840
- ZodEnum: "enum",
95841
- ZodIntersection: "intersection",
95842
- ZodLazy: "lazy",
95843
- ZodLiteral: "literal",
95844
- ZodNever: "never",
95845
- ZodNull: "null",
95846
- ZodNullable: "nullable",
95847
- ZodNumber: "number",
95848
- ZodNonOptional: "nonoptional",
95849
- ZodObject: "object",
95850
- ZodOptional: "optional",
95851
- ZodPipe: "pipe",
95852
- ZodReadonly: "readonly",
95853
- ZodRecord: "record",
95854
- ZodString: "string",
95855
- ZodTuple: "tuple",
95856
- ZodType: "type",
95857
- ZodUnion: "union",
95858
- ZodDiscriminatedUnion: "union",
95859
- ZodUnknown: "unknown",
95860
- ZodVoid: "void",
95861
- ZodDate: "date",
95862
- ZodTemplateLiteral: "template_literal"
95863
- };
95864
- function isZodType(schema, typeNames) {
95865
- const typeNamesArray = Array.isArray(typeNames) ? typeNames : [typeNames];
95866
- return typeNamesArray.some((typeName) => {
95867
- var _a;
95868
- const typeNameMatch = ((_a = schema === null || schema === undefined ? undefined : schema.def) === null || _a === undefined ? undefined : _a.type) === ZodTypeKeys[typeName];
95869
- if (typeName === "ZodDiscriminatedUnion") {
95870
- return typeNameMatch && "discriminator" in schema.def;
95871
- }
95872
- return typeNameMatch;
95873
- });
95874
- }
95875
- function isAnyZodType(schema) {
95876
- return schema && "def" in schema;
95877
- }
95878
- function isNullableSchema(schema) {
95879
- return schema.safeParse(null).success;
95880
- }
95881
- function isOptionalSchema(schema) {
95882
- return schema.safeParse(undefined).success;
95883
- }
95884
-
95885
- class $ZodRegistry {
95886
- constructor() {
95887
- this._map = new Map;
95888
- this._idmap = new Map;
95889
- }
95890
- add(schema, ..._meta) {
95891
- const meta2 = _meta[0];
95892
- this._map.set(schema, meta2);
95893
- if (meta2 && typeof meta2 === "object" && "id" in meta2) {
95894
- if (this._idmap.has(meta2.id)) {
95895
- throw new Error(`ID ${meta2.id} already exists in the registry`);
95896
- }
95897
- this._idmap.set(meta2.id, schema);
95898
- }
95899
- return this;
95900
- }
95901
- clear() {
95902
- this._map = new Map;
95903
- this._idmap = new Map;
95904
- return this;
95905
- }
95906
- remove(schema) {
95907
- const meta2 = this._map.get(schema);
95908
- if (meta2 && typeof meta2 === "object" && "id" in meta2) {
95909
- this._idmap.delete(meta2.id);
95910
- }
95911
- this._map.delete(schema);
95912
- return this;
95913
- }
95914
- get(schema) {
95915
- const p = schema._zod.parent;
95916
- if (p) {
95917
- const pm = { ...this.get(p) ?? {} };
95918
- delete pm.id;
95919
- return { ...pm, ...this._map.get(schema) };
95920
- }
95921
- return this._map.get(schema);
95922
- }
95923
- has(schema) {
95924
- return this._map.has(schema);
95925
- }
95926
- }
95927
- function registry() {
95928
- return new $ZodRegistry;
95929
- }
95930
- function isEqual(x, y) {
95931
- if (x === null || x === undefined || y === null || y === undefined) {
95932
- return x === y;
95933
- }
95934
- if (x === y || x.valueOf() === y.valueOf()) {
95935
- return true;
95936
- }
95937
- if (Array.isArray(x)) {
95938
- if (!Array.isArray(y)) {
95939
- return false;
95940
- }
95941
- if (x.length !== y.length) {
95942
- return false;
95943
- }
95944
- }
95945
- if (!(x instanceof Object) || !(y instanceof Object)) {
95946
- return false;
95947
- }
95948
- const keysX = Object.keys(x);
95949
- return Object.keys(y).every((keyY) => keysX.indexOf(keyY) !== -1) && keysX.every((key) => isEqual(x[key], y[key]));
95950
- }
95951
-
95952
- class ObjectSet {
95953
- constructor() {
95954
- this.buckets = new Map;
95955
- }
95956
- put(value) {
95957
- const hashCode = this.hashCodeOf(value);
95958
- const itemsByCode = this.buckets.get(hashCode);
95959
- if (!itemsByCode) {
95960
- this.buckets.set(hashCode, [value]);
95961
- return;
95962
- }
95963
- const alreadyHasItem = itemsByCode.some((_) => isEqual(_, value));
95964
- if (!alreadyHasItem) {
95965
- itemsByCode.push(value);
95966
- }
95967
- }
95968
- contains(value) {
95969
- const hashCode = this.hashCodeOf(value);
95970
- const itemsByCode = this.buckets.get(hashCode);
95971
- if (!itemsByCode) {
95972
- return false;
95973
- }
95974
- return itemsByCode.some((_) => isEqual(_, value));
95975
- }
95976
- values() {
95977
- return [...this.buckets.values()].flat();
95978
- }
95979
- stats() {
95980
- let totalBuckets = 0;
95981
- let totalValues = 0;
95982
- let collisions = 0;
95983
- for (const bucket of this.buckets.values()) {
95984
- totalBuckets += 1;
95985
- totalValues += bucket.length;
95986
- if (bucket.length > 1) {
95987
- collisions += 1;
95988
- }
95989
- }
95990
- const hashEffectiveness = totalBuckets / totalValues;
95991
- return { totalBuckets, collisions, totalValues, hashEffectiveness };
95992
- }
95993
- hashCodeOf(object4) {
95994
- let hashCode = 0;
95995
- if (Array.isArray(object4)) {
95996
- for (let i = 0;i < object4.length; i++) {
95997
- hashCode ^= this.hashCodeOf(object4[i]) * i;
95998
- }
95999
- return hashCode;
96000
- }
96001
- if (typeof object4 === "string") {
96002
- for (let i = 0;i < object4.length; i++) {
96003
- hashCode ^= object4.charCodeAt(i) * i;
96004
- }
96005
- return hashCode;
96006
- }
96007
- if (typeof object4 === "number") {
96008
- return object4;
96009
- }
96010
- if (typeof object4 === "object") {
96011
- for (const [key, value] of Object.entries(object4)) {
96012
- hashCode ^= this.hashCodeOf(key) + this.hashCodeOf(value !== null && value !== undefined ? value : "");
96013
- }
96014
- }
96015
- return hashCode;
96016
- }
96017
- }
96018
- function isUndefined(value) {
96019
- return value === undefined;
96020
- }
96021
- function mapValues(object4, mapper) {
96022
- const result = {};
96023
- Object.entries(object4).forEach(([key, value]) => {
96024
- result[key] = mapper(value);
96025
- });
96026
- return result;
96027
- }
96028
- function omit(object4, keys) {
96029
- const result = {};
96030
- Object.entries(object4).forEach(([key, value]) => {
96031
- if (!keys.some((keyToOmit) => keyToOmit === key)) {
96032
- result[key] = value;
96033
- }
96034
- });
96035
- return result;
96036
- }
96037
- function omitBy(object4, predicate) {
96038
- const result = {};
96039
- Object.entries(object4).forEach(([key, value]) => {
96040
- if (!predicate(value, key)) {
96041
- result[key] = value;
96042
- }
96043
- });
96044
- return result;
96045
- }
96046
- function compact(arr) {
96047
- return arr.filter((elem) => !isUndefined(elem));
96048
- }
96049
- var objectEquals = isEqual;
96050
- function uniq(values) {
96051
- const set2 = new ObjectSet;
96052
- values.forEach((value) => set2.put(value));
96053
- return [...set2.values()];
96054
- }
96055
- function isString(val) {
96056
- return typeof val === "string";
96057
- }
96058
- function sortObjectByKeys(obj) {
96059
- return Object.fromEntries(Object.entries(obj).sort(([leftKey], [rightKey]) => leftKey.localeCompare(rightKey)));
96060
- }
96061
- var zodToOpenAPIRegistry = registry();
96062
-
96063
- class Metadata {
96064
- static collectMetadata(schema, metadata) {
96065
- const currentMetadata = this.getMetadataFromRegistry(schema);
96066
- const _internal = Object.assign(Object.assign({}, currentMetadata === null || currentMetadata === undefined ? undefined : currentMetadata._internal), metadata === null || metadata === undefined ? undefined : metadata._internal);
96067
- const param = Object.assign(Object.assign({}, currentMetadata === null || currentMetadata === undefined ? undefined : currentMetadata.param), metadata === null || metadata === undefined ? undefined : metadata.param);
96068
- const totalMetadata = Object.assign(Object.assign(Object.assign(Object.assign({}, Object.keys(_internal).length > 0 ? { _internal } : {}), currentMetadata), metadata), Object.keys(param).length > 0 ? { param } : {});
96069
- if (isZodType(schema, [
96070
- "ZodOptional",
96071
- "ZodNullable",
96072
- "ZodDefault",
96073
- "ZodPrefault",
96074
- "ZodReadonly",
96075
- "ZodNonOptional"
96076
- ]) && isAnyZodType(schema._zod.def.innerType)) {
96077
- return this.collectMetadata(schema._zod.def.innerType, totalMetadata);
96078
- }
96079
- if (isZodType(schema, "ZodPipe")) {
96080
- const inSchema = schema._zod.def.in;
96081
- const outSchema = schema._zod.def.out;
96082
- if (isZodType(inSchema, "ZodTransform") && isAnyZodType(outSchema)) {
96083
- return this.collectMetadata(outSchema, totalMetadata);
96084
- }
96085
- if (isAnyZodType(inSchema)) {
96086
- return this.collectMetadata(inSchema, totalMetadata);
96087
- }
96088
- }
96089
- return totalMetadata;
96090
- }
96091
- static getMetadata(zodSchema) {
96092
- return this.collectMetadata(zodSchema);
96093
- }
96094
- static getOpenApiMetadata(zodSchema) {
96095
- const metadata = this.collectMetadata(zodSchema);
96096
- const _a = metadata !== null && metadata !== undefined ? metadata : {}, { _internal } = _a, rest = __rest(_a, ["_internal"]);
96097
- return rest;
96098
- }
96099
- static getInternalMetadata(zodSchema) {
96100
- var _a;
96101
- return (_a = this.collectMetadata(zodSchema)) === null || _a === undefined ? undefined : _a._internal;
96102
- }
96103
- static getParamMetadata(zodSchema) {
96104
- const metadata = this.collectMetadata(zodSchema);
96105
- return Object.assign(Object.assign({}, metadata), {
96106
- param: Object.assign(Object.assign({}, (metadata === null || metadata === undefined ? undefined : metadata.description) ? { description: metadata.description } : {}), metadata === null || metadata === undefined ? undefined : metadata.param)
96107
- });
96108
- }
96109
- static buildSchemaMetadata(metadata) {
96110
- return omitBy(omit(metadata, ["param", "_internal"]), isUndefined);
96111
- }
96112
- static buildParameterMetadata(metadata) {
96113
- return omitBy(metadata, isUndefined);
96114
- }
96115
- static applySchemaMetadata(initialData, metadata) {
96116
- return omitBy(Object.assign(Object.assign({}, initialData), this.buildSchemaMetadata(metadata)), isUndefined);
96117
- }
96118
- static getRefId(zodSchema) {
96119
- var _a;
96120
- return (_a = this.getInternalMetadata(zodSchema)) === null || _a === undefined ? undefined : _a.refId;
96121
- }
96122
- static unwrapChained(schema) {
96123
- return this.unwrapUntil(schema);
96124
- }
96125
- static getDefaultValue(zodSchema) {
96126
- var _a;
96127
- const unwrapped = (_a = this.unwrapUntil(zodSchema, "ZodDefault")) !== null && _a !== undefined ? _a : this.unwrapUntil(zodSchema, "ZodPrefault");
96128
- return unwrapped === null || unwrapped === undefined ? undefined : unwrapped._zod.def.defaultValue;
96129
- }
96130
- static unwrapUntil(schema, typeName) {
96131
- if (typeName && isZodType(schema, typeName)) {
96132
- return schema;
96133
- }
96134
- if (isZodType(schema, [
96135
- "ZodOptional",
96136
- "ZodNullable",
96137
- "ZodDefault",
96138
- "ZodPrefault",
96139
- "ZodReadonly",
96140
- "ZodNonOptional"
96141
- ]) && isAnyZodType(schema._zod.def.innerType)) {
96142
- return this.unwrapUntil(schema._zod.def.innerType, typeName);
96143
- }
96144
- if (isZodType(schema, "ZodPipe")) {
96145
- const inSchema = schema._zod.def.in;
96146
- const outSchema = schema._zod.def.out;
96147
- if (isZodType(inSchema, "ZodTransform") && isAnyZodType(outSchema)) {
96148
- return this.unwrapUntil(outSchema, typeName);
96149
- }
96150
- if (isAnyZodType(inSchema)) {
96151
- return this.unwrapUntil(inSchema, typeName);
96152
- }
96153
- }
96154
- return typeName ? undefined : schema;
96155
- }
96156
- static getMetadataFromInternalRegistry(zodSchema) {
96157
- return zodToOpenAPIRegistry.get(zodSchema);
96158
- }
96159
- static getMetadataFromRegistry(zodSchema) {
96160
- const internal = this.getMetadataFromInternalRegistry(zodSchema);
96161
- const general = zodSchema.meta();
96162
- if (!internal) {
96163
- return general;
96164
- }
96165
- const { _internal } = internal, rest = __rest(internal, ["_internal"]);
96166
- const _a = general !== null && general !== undefined ? general : {}, { id, title } = _a, restGeneral = __rest(_a, ["id", "title"]);
96167
- return Object.assign(Object.assign(Object.assign({ _internal: Object.assign(Object.assign({}, id ? { refId: id } : {}), _internal) }, rest), title ? { description: title } : {}), restGeneral);
96168
- }
96169
- static setMetadataInRegistry(zodSchema, metadata) {
96170
- zodToOpenAPIRegistry.add(zodSchema, metadata);
96171
- }
96172
- }
96173
- function preserveMetadataFromModifier(zodSchema, modifier) {
96174
- const zodModifier = zodSchema[modifier];
96175
- if (typeof zodModifier !== "function") {
96176
- return;
96177
- }
96178
- zodSchema[modifier] = function(...args) {
96179
- const result = zodModifier.apply(this, args);
96180
- const meta2 = Metadata.getMetadataFromRegistry(this);
96181
- if (meta2) {
96182
- Metadata.setMetadataInRegistry(result, meta2);
96183
- }
96184
- return result;
96185
- };
96186
- }
96187
- function extendZodWithOpenApi(zod) {
96188
- if (typeof zod.ZodType.prototype.openapi !== "undefined") {
96189
- return;
96190
- }
96191
- zod.ZodType.prototype.openapi = function(...args) {
96192
- const { refId, metadata, options } = getOpenApiConfiguration(...args);
96193
- const _a = metadata !== null && metadata !== undefined ? metadata : {}, { param } = _a, restOfOpenApi = __rest(_a, ["param"]);
96194
- const allMetadata = Metadata.getMetadataFromRegistry(this);
96195
- const _b = allMetadata !== null && allMetadata !== undefined ? allMetadata : {}, { _internal: internalMetadata } = _b, currentMetadata = __rest(_b, ["_internal"]);
96196
- const _internal = Object.assign(Object.assign(Object.assign({}, internalMetadata), options), refId ? { refId } : undefined);
96197
- const resultMetadata = Object.assign(Object.assign(Object.assign({}, currentMetadata), restOfOpenApi), (currentMetadata === null || currentMetadata === undefined ? undefined : currentMetadata.param) || param ? {
96198
- param: Object.assign(Object.assign({}, currentMetadata === null || currentMetadata === undefined ? undefined : currentMetadata.param), param)
96199
- } : undefined);
96200
- const result = new this.constructor(this._def);
96201
- function setMetadata(schema) {
96202
- Metadata.setMetadataInRegistry(schema, Object.assign(Object.assign({}, Object.keys(_internal).length > 0 ? { _internal } : undefined), resultMetadata));
96203
- }
96204
- setMetadata(result);
96205
- if (isZodType(result, "ZodLazy")) {
96206
- setMetadata(this);
96207
- }
96208
- if (isZodType(result, "ZodObject")) {
96209
- const currentMetadata2 = Metadata.getMetadataFromRegistry(result);
96210
- const originalExtend = result.extend;
96211
- result.extend = function(...args2) {
96212
- const extendedResult = originalExtend.apply(result, args2);
96213
- const _a2 = currentMetadata2 !== null && currentMetadata2 !== undefined ? currentMetadata2 : {}, { _internal: _internal2 } = _a2, rest = __rest(_a2, ["_internal"]);
96214
- Metadata.setMetadataInRegistry(extendedResult, {
96215
- _internal: {
96216
- extendedFrom: (_internal2 === null || _internal2 === undefined ? undefined : _internal2.refId) ? { refId: _internal2.refId, schema: result } : _internal2 === null || _internal2 === undefined ? undefined : _internal2.extendedFrom
96217
- }
96218
- });
96219
- return extendedResult.openapi(rest);
96220
- };
96221
- preserveMetadataFromModifier(result, "catchall");
96222
- }
96223
- preserveMetadataFromModifier(result, "optional");
96224
- preserveMetadataFromModifier(result, "nullable");
96225
- preserveMetadataFromModifier(result, "default");
96226
- preserveMetadataFromModifier(result, "transform");
96227
- preserveMetadataFromModifier(result, "refine");
96228
- preserveMetadataFromModifier(result, "length");
96229
- preserveMetadataFromModifier(result, "min");
96230
- preserveMetadataFromModifier(result, "max");
96231
- const originalMeta = result.meta;
96232
- result.meta = function(...args2) {
96233
- const result2 = originalMeta.apply(this, args2);
96234
- if (args2[0]) {
96235
- const meta2 = Metadata.getMetadataFromInternalRegistry(this);
96236
- if (meta2) {
96237
- Metadata.setMetadataInRegistry(result2, Object.assign(Object.assign({}, meta2), args2[0]));
96238
- }
96239
- }
96240
- return result2;
96241
- };
96242
- return result;
96243
- };
96244
- }
96245
- function getOpenApiConfiguration(refOrOpenapi, metadataOrOptions, options) {
96246
- if (typeof refOrOpenapi === "string") {
96247
- return {
96248
- refId: refOrOpenapi,
96249
- metadata: metadataOrOptions,
96250
- options
96251
- };
96252
- }
96253
- return {
96254
- refId: undefined,
96255
- metadata: refOrOpenapi,
96256
- options: metadataOrOptions
96257
- };
96258
- }
96259
- class OpenAPIRegistry {
96260
- constructor(parents) {
96261
- this.parents = parents;
96262
- this._definitions = [];
96263
- }
96264
- get definitions() {
96265
- var _a, _b;
96266
- const parentDefinitions = (_b = (_a = this.parents) === null || _a === undefined ? undefined : _a.flatMap((par) => par._definitions)) !== null && _b !== undefined ? _b : [];
96267
- return [...parentDefinitions, ...this._definitions];
96268
- }
96269
- register(refId, zodSchema) {
96270
- const schemaWithRefId = this.schemaWithRefId(refId, zodSchema);
96271
- this._definitions.push({ type: "schema", schema: schemaWithRefId });
96272
- return schemaWithRefId;
96273
- }
96274
- registerParameter(refId, zodSchema) {
96275
- var _a, _b, _c;
96276
- const schemaWithRefId = this.schemaWithRefId(refId, zodSchema);
96277
- const currentMetadata = (_a = Metadata.getOpenApiMetadata(schemaWithRefId)) !== null && _a !== undefined ? _a : {};
96278
- const schemaWithMetadata = schemaWithRefId.openapi(Object.assign(Object.assign({}, currentMetadata), { param: Object.assign(Object.assign({}, currentMetadata === null || currentMetadata === undefined ? undefined : currentMetadata.param), { name: (_c = (_b = currentMetadata === null || currentMetadata === undefined ? undefined : currentMetadata.param) === null || _b === undefined ? undefined : _b.name) !== null && _c !== undefined ? _c : refId }) }));
96279
- this._definitions.push({
96280
- type: "parameter",
96281
- schema: schemaWithMetadata
96282
- });
96283
- return schemaWithMetadata;
96284
- }
96285
- registerPath(route) {
96286
- this._definitions.push({
96287
- type: "route",
96288
- route
96289
- });
96290
- }
96291
- registerWebhook(webhook) {
96292
- this._definitions.push({
96293
- type: "webhook",
96294
- webhook
96295
- });
96296
- }
96297
- registerComponent(type, name, component) {
96298
- this._definitions.push({
96299
- type: "component",
96300
- componentType: type,
96301
- name,
96302
- component
96303
- });
96304
- return {
96305
- name,
96306
- ref: { $ref: `#/components/${type}/${name}` }
96307
- };
96308
- }
96309
- schemaWithRefId(refId, zodSchema) {
96310
- return zodSchema.openapi(refId);
96311
- }
96312
- }
96313
-
96314
- class ZodToOpenAPIError {
96315
- constructor(message) {
96316
- this.message = message;
96317
- }
96318
- }
96319
-
96320
- class ConflictError extends ZodToOpenAPIError {
96321
- constructor(message, data) {
96322
- super(message);
96323
- this.data = data;
96324
- }
96325
- }
96326
-
96327
- class MissingParameterDataError extends ZodToOpenAPIError {
96328
- constructor(data) {
96329
- super(`Missing parameter data, please specify \`${data.missingField}\` and other OpenAPI parameter props using the \`param\` field of \`schema.openapi\``);
96330
- this.data = data;
96331
- }
96332
- }
96333
- function enhanceMissingParametersError(action, paramsToAdd) {
96334
- try {
96335
- return action();
96336
- } catch (error) {
96337
- if (error instanceof MissingParameterDataError) {
96338
- throw new MissingParameterDataError(Object.assign(Object.assign({}, error.data), paramsToAdd));
96339
- }
96340
- throw error;
96341
- }
96342
- }
96343
-
96344
- class UnknownZodTypeError extends ZodToOpenAPIError {
96345
- constructor(data) {
96346
- super(`Unknown zod object type, please specify \`type\` and other OpenAPI props using \`schema.openapi\`.`);
96347
- this.data = data;
96348
- }
96349
- }
96350
-
96351
- class ArrayTransformer {
96352
- transform(zodSchema, mapNullableType, mapItems) {
96353
- var _a, _b, _c, _d;
96354
- const itemType = zodSchema.def.element;
96355
- const minItems = (_b = (_a = zodSchema.def.checks) === null || _a === undefined ? undefined : _a.find((check) => check._zod.def.check === "min_length")) === null || _b === undefined ? undefined : _b._zod.def.minimum;
96356
- const maxItems = (_d = (_c = zodSchema.def.checks) === null || _c === undefined ? undefined : _c.find((check) => check._zod.def.check === "max_length")) === null || _d === undefined ? undefined : _d._zod.def.maximum;
96357
- return Object.assign(Object.assign({}, mapNullableType("array")), {
96358
- items: isAnyZodType(itemType) ? mapItems(itemType) : {},
96359
- minItems,
96360
- maxItems
96361
- });
96362
- }
96363
- }
96364
-
96365
- class BigIntTransformer {
96366
- transform(mapNullableType) {
96367
- return Object.assign(Object.assign({}, mapNullableType("string")), { pattern: `^d+$` });
96368
- }
96369
- }
96370
-
96371
- class DiscriminatedUnionTransformer {
96372
- transform(zodSchema, isNullable, mapNullableOfArray, mapItem, generateSchemaRef) {
96373
- const options = [...zodSchema.def.options];
96374
- const optionSchema = options.map(mapItem);
96375
- if (isNullable) {
96376
- return {
96377
- oneOf: mapNullableOfArray(optionSchema, isNullable)
96378
- };
96379
- }
96380
- const discriminator = zodSchema._zod.def.discriminator;
96381
- if (!discriminator) {
96382
- console.error("No discriminator found for discriminated union", zodSchema);
96383
- return {
96384
- oneOf: optionSchema
96385
- };
96386
- }
96387
- return {
96388
- oneOf: optionSchema,
96389
- discriminator: this.mapDiscriminator(options, discriminator, generateSchemaRef)
96390
- };
96391
- }
96392
- mapDiscriminator(zodObjects, discriminator, generateSchemaRef) {
96393
- if (zodObjects.some((obj) => Metadata.getRefId(obj) === undefined)) {
96394
- return;
96395
- }
96396
- const mapping = {};
96397
- zodObjects.forEach((obj) => {
96398
- var _a;
96399
- const refId = Metadata.getRefId(obj);
96400
- const value = (_a = obj.def.shape) === null || _a === undefined ? undefined : _a[discriminator];
96401
- if (isZodType(value, "ZodEnum")) {
96402
- const keys = Object.values(value._zod.def.entries).filter(isString);
96403
- keys.forEach((enumValue) => {
96404
- mapping[enumValue] = generateSchemaRef(refId);
96405
- });
96406
- return;
96407
- }
96408
- const literalValue = value === null || value === undefined ? undefined : value.def.values[0];
96409
- if (typeof literalValue !== "string") {
96410
- throw new Error(`Discriminator ${discriminator} could not be found in one of the values of a discriminated union`);
96411
- }
96412
- mapping[literalValue] = generateSchemaRef(refId);
96413
- });
96414
- return {
96415
- propertyName: discriminator,
96416
- mapping
96417
- };
96418
- }
96419
- }
96420
- function enumInfo(enumObject) {
96421
- const keysExceptReverseMappings = Object.keys(enumObject).filter((key) => typeof enumObject[enumObject[key]] !== "number");
96422
- const values = keysExceptReverseMappings.map((key) => enumObject[key]);
96423
- const numericCount = values.filter((_) => typeof _ === "number").length;
96424
- const type = numericCount === 0 ? "string" : numericCount === values.length ? "numeric" : "mixed";
96425
- return { values, type };
96426
- }
96427
-
96428
- class EnumTransformer {
96429
- transform(zodSchema, isNullable, mapNullableType) {
96430
- const { type, values } = enumInfo(zodSchema._zod.def.entries);
96431
- if (type === "mixed") {
96432
- throw new ZodToOpenAPIError("Enum has mixed string and number values, please specify the OpenAPI type manually");
96433
- }
96434
- return Object.assign(Object.assign({}, mapNullableType(type === "numeric" ? "integer" : "string")), { enum: isNullable ? [...values, null] : values });
96435
- }
96436
- }
96437
-
96438
- class IntersectionTransformer {
96439
- transform(zodSchema, isNullable, mapNullableOfArray, mapItem) {
96440
- const subtypes = this.flattenIntersectionTypes(zodSchema);
96441
- const allOfSchema = {
96442
- allOf: subtypes.map(mapItem)
96443
- };
96444
- if (isNullable) {
96445
- return {
96446
- anyOf: mapNullableOfArray([allOfSchema], isNullable)
96447
- };
96448
- }
96449
- return allOfSchema;
96450
- }
96451
- flattenIntersectionTypes(schema) {
96452
- if (!isZodType(schema, "ZodIntersection")) {
96453
- return [schema];
96454
- }
96455
- const leftSubTypes = isAnyZodType(schema._zod.def.left) ? this.flattenIntersectionTypes(schema._zod.def.left) : [];
96456
- const rightSubTypes = isAnyZodType(schema._zod.def.right) ? this.flattenIntersectionTypes(schema._zod.def.right) : [];
96457
- return [...leftSubTypes, ...rightSubTypes];
96458
- }
96459
- }
96460
-
96461
- class LiteralTransformer {
96462
- constructor() {
96463
- this.bigIntTransformer = new BigIntTransformer;
96464
- }
96465
- transform(zodSchema, mapNullableType) {
96466
- const type = typeof zodSchema.def.values[0];
96467
- if (type === "boolean" || type === "number" || type === "string" || type === "object") {
96468
- return Object.assign(Object.assign({}, mapNullableType(type)), { enum: [zodSchema.def.values[0]] });
96469
- }
96470
- if (type === "bigint") {
96471
- return this.bigIntTransformer.transform(mapNullableType);
96472
- }
96473
- return mapNullableType("null");
96474
- }
96475
- }
96476
-
96477
- class NumberTransformer {
96478
- transform(zodSchema, mapNullableType, getNumberChecks) {
96479
- var _a;
96480
- return Object.assign(Object.assign(Object.assign({}, mapNullableType("number")), mapNullableType(zodSchema.format === "safeint" ? "integer" : "number")), getNumberChecks((_a = zodSchema.def.checks) !== null && _a !== undefined ? _a : []));
96481
- }
96482
- }
96483
-
96484
- class ObjectTransformer {
96485
- transform(zodSchema, defaultValue, mapNullableType, mapItem) {
96486
- var _a;
96487
- const extendedFrom = (_a = Metadata.getInternalMetadata(zodSchema)) === null || _a === undefined ? undefined : _a.extendedFrom;
96488
- const required = this.requiredKeysOf(zodSchema);
96489
- const properties = mapValues(zodSchema.def.shape, mapItem);
96490
- if (!extendedFrom) {
96491
- return Object.assign(Object.assign(Object.assign(Object.assign({}, mapNullableType("object")), { properties, default: defaultValue }), required.length > 0 ? { required } : {}), this.generateAdditionalProperties(zodSchema, mapItem));
96492
- }
96493
- const parent = extendedFrom.schema;
96494
- mapItem(parent);
96495
- const keysRequiredByParent = this.requiredKeysOf(parent);
96496
- const propsOfParent = mapValues(parent === null || parent === undefined ? undefined : parent.def.shape, mapItem);
96497
- const propertiesToAdd = Object.fromEntries(Object.entries(properties).filter(([key, type]) => {
96498
- return !objectEquals(propsOfParent[key], type);
96499
- }));
96500
- const additionallyRequired = required.filter((prop) => !keysRequiredByParent.includes(prop));
96501
- const objectData = Object.assign(Object.assign(Object.assign(Object.assign({}, mapNullableType("object")), { default: defaultValue, properties: propertiesToAdd }), additionallyRequired.length > 0 ? { required: additionallyRequired } : {}), this.generateAdditionalProperties(zodSchema, mapItem));
96502
- return {
96503
- allOf: [
96504
- { $ref: `#/components/schemas/${extendedFrom.refId}` },
96505
- objectData
96506
- ]
96507
- };
96508
- }
96509
- generateAdditionalProperties(zodSchema, mapItem) {
96510
- const catchallSchema = zodSchema.def.catchall;
96511
- if (!catchallSchema) {
96512
- return {};
96513
- }
96514
- if (isZodType(catchallSchema, "ZodNever")) {
96515
- return { additionalProperties: false };
96516
- }
96517
- if (isAnyZodType(catchallSchema)) {
96518
- return { additionalProperties: mapItem(catchallSchema) };
96519
- }
96520
- return {};
96521
- }
96522
- requiredKeysOf(objectSchema) {
96523
- return Object.entries(objectSchema.def.shape).filter(([_key, type]) => !isOptionalSchema(type)).map(([key, _type]) => key);
96524
- }
96525
- }
96526
-
96527
- class RecordTransformer {
96528
- transform(zodSchema, mapNullableType, mapItem) {
96529
- const propertiesType = zodSchema.valueType;
96530
- const keyType = zodSchema.keyType;
96531
- const propertiesSchema = isAnyZodType(propertiesType) ? mapItem(propertiesType) : {};
96532
- if (isZodType(keyType, "ZodEnum")) {
96533
- const keys = Object.values(keyType._zod.def.entries).filter(isString);
96534
- const properties = keys.reduce((acc, curr) => Object.assign(Object.assign({}, acc), { [curr]: propertiesSchema }), {});
96535
- return Object.assign(Object.assign({}, mapNullableType("object")), { properties });
96536
- }
96537
- return Object.assign(Object.assign({}, mapNullableType("object")), { additionalProperties: propertiesSchema });
96538
- }
96539
- }
96540
- function isZodCheckLengthEquals(check) {
96541
- return check._zod.def.check === "length_equals";
96542
- }
96543
- function isZodCheckRegex(check) {
96544
- return check._zod.def.check === "string_format" && check._zod.def.format === "regex";
96545
- }
96546
-
96547
- class StringTransformer {
96548
- transform(zodSchema, mapNullableType) {
96549
- var _a, _b, _c, _d;
96550
- const regexCheck = (_a = zodSchema.def.checks) === null || _a === undefined ? undefined : _a.find(isZodCheckRegex);
96551
- const pattern = regexCheck === null || regexCheck === undefined ? undefined : regexCheck._zod.def.pattern.toString().replace(/^\/|\/$/g, "");
96552
- const check = (_b = zodSchema.def.checks) === null || _b === undefined ? undefined : _b.find(isZodCheckLengthEquals);
96553
- const length = check === null || check === undefined ? undefined : check._zod.def.length;
96554
- const maxLength = Number.isFinite(zodSchema.minLength) ? (_c = zodSchema.minLength) !== null && _c !== undefined ? _c : undefined : undefined;
96555
- const minLength = Number.isFinite(zodSchema.maxLength) ? (_d = zodSchema.maxLength) !== null && _d !== undefined ? _d : undefined : undefined;
96556
- return Object.assign(Object.assign({}, mapNullableType("string")), {
96557
- minLength: length !== null && length !== undefined ? length : maxLength,
96558
- maxLength: length !== null && length !== undefined ? length : minLength,
96559
- format: this.mapStringFormat(zodSchema),
96560
- pattern
96561
- });
96562
- }
96563
- mapStringFormat(zodString) {
96564
- if (zodString.format === "uuid")
96565
- return "uuid";
96566
- if (zodString.format === "email")
96567
- return "email";
96568
- if (zodString.format === "url")
96569
- return "uri";
96570
- if (zodString.format === "date")
96571
- return "date";
96572
- if (zodString.format === "datetime")
96573
- return "date-time";
96574
- if (zodString.format === "cuid")
96575
- return "cuid";
96576
- if (zodString.format === "cuid2")
96577
- return "cuid2";
96578
- if (zodString.format === "ulid")
96579
- return "ulid";
96580
- if (zodString.format === "ipv4")
96581
- return "ip";
96582
- if (zodString.format === "ipv6")
96583
- return "ip";
96584
- if (zodString.format === "emoji")
96585
- return "emoji";
96586
- return;
96587
- }
96588
- }
96589
-
96590
- class TupleTransformer {
96591
- constructor(versionSpecifics) {
96592
- this.versionSpecifics = versionSpecifics;
96593
- }
96594
- transform(zodSchema, mapNullableType, mapItem) {
96595
- const items = zodSchema._zod.def.items;
96596
- const schemas2 = items.map((item) => isAnyZodType(item) ? mapItem(item) : {});
96597
- return Object.assign(Object.assign({}, mapNullableType("array")), this.versionSpecifics.mapTupleItems(schemas2));
96598
- }
96599
- }
96600
-
96601
- class UnionTransformer {
96602
- constructor(options) {
96603
- this.options = options;
96604
- }
96605
- transform(zodSchema, mapNullableOfArray, mapItem) {
96606
- var _a, _b, _c;
96607
- const internalMetadata = Metadata.getInternalMetadata(zodSchema);
96608
- const preferredType = (_c = (_a = internalMetadata === null || internalMetadata === undefined ? undefined : internalMetadata.unionPreferredType) !== null && _a !== undefined ? _a : (_b = this.options) === null || _b === undefined ? undefined : _b.unionPreferredType) !== null && _c !== undefined ? _c : "anyOf";
96609
- const options = this.flattenUnionTypes(zodSchema);
96610
- const schemas2 = options.map((schema) => {
96611
- const optionToGenerate = this.unwrapNullable(schema);
96612
- return mapItem(optionToGenerate);
96613
- });
96614
- return {
96615
- [preferredType]: mapNullableOfArray(schemas2)
96616
- };
96617
- }
96618
- flattenUnionTypes(schema) {
96619
- if (!isZodType(schema, "ZodUnion")) {
96620
- return [schema];
96621
- }
96622
- const options = schema.def.options;
96623
- return options.flatMap((option) => isAnyZodType(option) ? this.flattenUnionTypes(option) : []);
96624
- }
96625
- unwrapNullable(schema) {
96626
- if (isZodType(schema, "ZodNullable")) {
96627
- const unwrapped = schema.unwrap();
96628
- if (isAnyZodType(unwrapped)) {
96629
- return this.unwrapNullable(unwrapped);
96630
- }
96631
- }
96632
- return schema;
96633
- }
96634
- }
96635
-
96636
- class DateTransformer {
96637
- transform(mapNullableType) {
96638
- return Object.assign(Object.assign({}, mapNullableType("string")), { format: "date-time" });
96639
- }
96640
- }
96641
-
96642
- class LazyTransformer {
96643
- transform(zodSchema, mapItem, mapNullableType, mapNullableRef) {
96644
- const result = mapItem(zodSchema._zod.def.getter());
96645
- return LazyTransformer.mapRecursive(result, mapNullableType, mapNullableRef);
96646
- }
96647
- static mapRecursive(schema, mapNullableType, mapNullableRef) {
96648
- if ("$ref" in schema) {
96649
- return mapNullableRef(schema);
96650
- }
96651
- if (schema.type) {
96652
- return Object.assign(Object.assign({}, schema), mapNullableType(schema.type));
96653
- }
96654
- return schema;
96655
- }
96656
- }
96657
-
96658
- class TemplateLiteralTransformer {
96659
- transform(zodSchema, mapNullableType) {
96660
- const parts = zodSchema.def.parts;
96661
- const contentPattern = parts.map((part) => this.generatePattern(part)).join("");
96662
- return Object.assign(Object.assign({}, mapNullableType("string")), { pattern: `^${contentPattern}$` });
96663
- }
96664
- generatePattern(part) {
96665
- if (typeof part === "string" || typeof part === "number" || typeof part === "boolean" || typeof part === "bigint" || part === null || part === undefined) {
96666
- return this.escapeRegex(String(part));
96667
- }
96668
- if (isZodType(part, "ZodLiteral")) {
96669
- const value = part.def.values[0];
96670
- return this.escapeRegex(String(value));
96671
- }
96672
- if (isZodType(part, "ZodNumber")) {
96673
- return "[+-]?\\d+(\\.\\d+)?";
96674
- }
96675
- if (isZodType(part, "ZodBoolean")) {
96676
- return "(true|false)";
96677
- }
96678
- if (isZodType(part, "ZodEnum")) {
96679
- const { values } = enumInfo(part.def.entries);
96680
- return `(${values.map((v) => this.escapeRegex(String(v))).join("|")})`;
96681
- }
96682
- return ".*";
96683
- }
96684
- escapeRegex(str) {
96685
- return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
96686
- }
96687
- }
96688
-
96689
- class OpenApiTransformer {
96690
- constructor(versionSpecifics, options) {
96691
- this.versionSpecifics = versionSpecifics;
96692
- this.objectTransformer = new ObjectTransformer;
96693
- this.stringTransformer = new StringTransformer;
96694
- this.numberTransformer = new NumberTransformer;
96695
- this.bigIntTransformer = new BigIntTransformer;
96696
- this.dateTransformer = new DateTransformer;
96697
- this.lazyTransformer = new LazyTransformer;
96698
- this.literalTransformer = new LiteralTransformer;
96699
- this.templateLiteralTransformer = new TemplateLiteralTransformer;
96700
- this.enumTransformer = new EnumTransformer;
96701
- this.arrayTransformer = new ArrayTransformer;
96702
- this.discriminatedUnionTransformer = new DiscriminatedUnionTransformer;
96703
- this.intersectionTransformer = new IntersectionTransformer;
96704
- this.recordTransformer = new RecordTransformer;
96705
- this.tupleTransformer = new TupleTransformer(versionSpecifics);
96706
- this.unionTransformer = new UnionTransformer(options);
96707
- }
96708
- transform(zodSchema, isNullable, mapItem, generateSchemaRef, defaultValue) {
96709
- if (isZodType(zodSchema, "ZodNull")) {
96710
- return this.versionSpecifics.nullType;
96711
- }
96712
- if (isZodType(zodSchema, "ZodUnknown") || isZodType(zodSchema, "ZodAny")) {
96713
- return this.versionSpecifics.mapNullableType(undefined, isNullable);
96714
- }
96715
- if (isZodType(zodSchema, "ZodObject")) {
96716
- return this.objectTransformer.transform(zodSchema, defaultValue, (_) => this.versionSpecifics.mapNullableType(_, isNullable), mapItem);
96717
- }
96718
- const schema = this.transformSchemaWithoutDefault(zodSchema, isNullable, mapItem, generateSchemaRef);
96719
- return Object.assign(Object.assign({}, schema), { default: defaultValue });
96720
- }
96721
- transformSchemaWithoutDefault(zodSchema, isNullable, mapItem, generateSchemaRef) {
96722
- if (isZodType(zodSchema, "ZodUnknown") || isZodType(zodSchema, "ZodAny")) {
96723
- return this.versionSpecifics.mapNullableType(undefined, isNullable);
96724
- }
96725
- if (isZodType(zodSchema, "ZodString")) {
96726
- return this.stringTransformer.transform(zodSchema, (schema) => this.versionSpecifics.mapNullableType(schema, isNullable));
96727
- }
96728
- if (isZodType(zodSchema, "ZodNumber")) {
96729
- return this.numberTransformer.transform(zodSchema, (schema) => this.versionSpecifics.mapNullableType(schema, isNullable), (_) => this.versionSpecifics.getNumberChecks(_));
96730
- }
96731
- if (isZodType(zodSchema, "ZodBigInt")) {
96732
- return this.bigIntTransformer.transform((schema) => this.versionSpecifics.mapNullableType(schema, isNullable));
96733
- }
96734
- if (isZodType(zodSchema, "ZodBoolean")) {
96735
- return this.versionSpecifics.mapNullableType("boolean", isNullable);
96736
- }
96737
- if (isZodType(zodSchema, "ZodLazy")) {
96738
- return this.lazyTransformer.transform(zodSchema, mapItem, (schema) => this.versionSpecifics.mapNullableType(schema, isNullable), (schema) => this.versionSpecifics.mapNullableOfRef(schema, isNullable));
96739
- }
96740
- if (isZodType(zodSchema, "ZodLiteral")) {
96741
- return this.literalTransformer.transform(zodSchema, (schema) => this.versionSpecifics.mapNullableType(schema, isNullable));
96742
- }
96743
- if (isZodType(zodSchema, "ZodTemplateLiteral")) {
96744
- return this.templateLiteralTransformer.transform(zodSchema, (schema) => this.versionSpecifics.mapNullableType(schema, isNullable));
96745
- }
96746
- if (isZodType(zodSchema, "ZodEnum")) {
96747
- return this.enumTransformer.transform(zodSchema, isNullable, (schema) => this.versionSpecifics.mapNullableType(schema, isNullable));
96748
- }
96749
- if (isZodType(zodSchema, "ZodArray")) {
96750
- return this.arrayTransformer.transform(zodSchema, (_) => this.versionSpecifics.mapNullableType(_, isNullable), mapItem);
96751
- }
96752
- if (isZodType(zodSchema, "ZodTuple")) {
96753
- return this.tupleTransformer.transform(zodSchema, (_) => this.versionSpecifics.mapNullableType(_, isNullable), mapItem);
96754
- }
96755
- if (isZodType(zodSchema, "ZodDiscriminatedUnion")) {
96756
- return this.discriminatedUnionTransformer.transform(zodSchema, isNullable, (_) => this.versionSpecifics.mapNullableOfArray(_, isNullable), mapItem, generateSchemaRef);
96757
- }
96758
- if (isZodType(zodSchema, "ZodUnion")) {
96759
- return this.unionTransformer.transform(zodSchema, (_) => this.versionSpecifics.mapNullableOfArray(_, isNullable), mapItem);
96760
- }
96761
- if (isZodType(zodSchema, "ZodIntersection")) {
96762
- return this.intersectionTransformer.transform(zodSchema, isNullable, (_) => this.versionSpecifics.mapNullableOfArray(_, isNullable), mapItem);
96763
- }
96764
- if (isZodType(zodSchema, "ZodRecord")) {
96765
- return this.recordTransformer.transform(zodSchema, (_) => this.versionSpecifics.mapNullableType(_, isNullable), mapItem);
96766
- }
96767
- if (isZodType(zodSchema, "ZodDate")) {
96768
- return this.dateTransformer.transform((_) => this.versionSpecifics.mapNullableType(_, isNullable));
96769
- }
96770
- const refId = Metadata.getRefId(zodSchema);
96771
- throw new UnknownZodTypeError({
96772
- currentSchema: zodSchema.def,
96773
- schemaName: refId
96774
- });
96775
- }
96776
- }
96777
-
96778
- class OpenAPIGenerator {
96779
- constructor(definitions, versionSpecifics, options) {
96780
- this.definitions = definitions;
96781
- this.versionSpecifics = versionSpecifics;
96782
- this.options = options;
96783
- this.schemaRefs = {};
96784
- this.paramRefs = {};
96785
- this.pathRefs = {};
96786
- this.rawComponents = [];
96787
- this.openApiTransformer = new OpenApiTransformer(versionSpecifics, options);
96788
- this.sortDefinitions();
96789
- }
96790
- generateDocumentData() {
96791
- this.definitions.forEach((definition) => this.generateSingle(definition));
96792
- return {
96793
- components: this.buildComponents(),
96794
- paths: this.pathRefs
96795
- };
96796
- }
96797
- generateComponents() {
96798
- this.definitions.forEach((definition) => this.generateSingle(definition));
96799
- return {
96800
- components: this.buildComponents()
96801
- };
96802
- }
96803
- buildComponents() {
96804
- var _a, _b, _c, _d;
96805
- const rawComponents = {};
96806
- this.rawComponents.forEach(({ componentType, name, component }) => {
96807
- var _a2;
96808
- (_a2 = rawComponents[componentType]) !== null && _a2 !== undefined || (rawComponents[componentType] = {});
96809
- rawComponents[componentType][name] = component;
96810
- });
96811
- const allSchemas = Object.assign(Object.assign({}, (_a = rawComponents.schemas) !== null && _a !== undefined ? _a : {}), this.filteredSchemaRefs);
96812
- const schemas2 = ((_b = this.options) === null || _b === undefined ? undefined : _b.sortComponents) === "alphabetically" ? sortObjectByKeys(allSchemas) : allSchemas;
96813
- const allParameters = Object.assign(Object.assign({}, (_c = rawComponents.parameters) !== null && _c !== undefined ? _c : {}), this.paramRefs);
96814
- const parameters = ((_d = this.options) === null || _d === undefined ? undefined : _d.sortComponents) === "alphabetically" ? sortObjectByKeys(allParameters) : allParameters;
96815
- return Object.assign(Object.assign({}, rawComponents), { schemas: schemas2, parameters });
96816
- }
96817
- isNotPendingRefEntry(entry) {
96818
- return entry[1] !== "pending";
96819
- }
96820
- get filteredSchemaRefs() {
96821
- const filtered = Object.entries(this.schemaRefs).filter(this.isNotPendingRefEntry);
96822
- return Object.fromEntries(filtered);
96823
- }
96824
- sortDefinitions() {
96825
- const generationOrder = [
96826
- "schema",
96827
- "parameter",
96828
- "component",
96829
- "route"
96830
- ];
96831
- this.definitions.sort((left, right) => {
96832
- if (!("type" in left)) {
96833
- if (!("type" in right)) {
96834
- return 0;
96835
- }
96836
- return -1;
96837
- }
96838
- if (!("type" in right)) {
96839
- return 1;
96840
- }
96841
- const leftIndex = generationOrder.findIndex((type) => type === left.type);
96842
- const rightIndex = generationOrder.findIndex((type) => type === right.type);
96843
- return leftIndex - rightIndex;
96844
- });
96845
- }
96846
- generateSingle(definition) {
96847
- if (!("type" in definition)) {
96848
- this.generateSchemaWithRef(definition);
96849
- return;
96850
- }
96851
- switch (definition.type) {
96852
- case "parameter":
96853
- this.generateParameterDefinition(definition.schema);
96854
- return;
96855
- case "schema":
96856
- this.generateSchemaWithRef(definition.schema);
96857
- return;
96858
- case "route":
96859
- this.generateSingleRoute(definition.route);
96860
- return;
96861
- case "component":
96862
- this.rawComponents.push(definition);
96863
- return;
96864
- }
96865
- }
96866
- generateParameterDefinition(zodSchema) {
96867
- const refId = Metadata.getRefId(zodSchema);
96868
- const result = this.generateParameter(zodSchema);
96869
- if (refId) {
96870
- this.paramRefs[refId] = result;
96871
- }
96872
- return result;
96873
- }
96874
- getParameterRef(schema, external) {
96875
- const metadata = Metadata.getOpenApiMetadata(schema);
96876
- const internalMetadata = Metadata.getInternalMetadata(schema);
96877
- const parameterMetadata = metadata === null || metadata === undefined ? undefined : metadata.param;
96878
- const existingRef = (internalMetadata === null || internalMetadata === undefined ? undefined : internalMetadata.refId) ? this.paramRefs[internalMetadata.refId] : undefined;
96879
- if (!(internalMetadata === null || internalMetadata === undefined ? undefined : internalMetadata.refId) || !existingRef) {
96880
- return;
96881
- }
96882
- if (parameterMetadata && existingRef.in !== parameterMetadata.in || (external === null || external === undefined ? undefined : external.in) && existingRef.in !== external.in) {
96883
- throw new ConflictError(`Conflicting location for parameter ${existingRef.name}`, {
96884
- key: "in",
96885
- values: compact([
96886
- existingRef.in,
96887
- external === null || external === undefined ? undefined : external.in,
96888
- parameterMetadata === null || parameterMetadata === undefined ? undefined : parameterMetadata.in
96889
- ])
96890
- });
96891
- }
96892
- if (parameterMetadata && existingRef.name !== parameterMetadata.name || (external === null || external === undefined ? undefined : external.name) && existingRef.name !== (external === null || external === undefined ? undefined : external.name)) {
96893
- throw new ConflictError(`Conflicting names for parameter`, {
96894
- key: "name",
96895
- values: compact([
96896
- existingRef.name,
96897
- external === null || external === undefined ? undefined : external.name,
96898
- parameterMetadata === null || parameterMetadata === undefined ? undefined : parameterMetadata.name
96899
- ])
96900
- });
96901
- }
96902
- return {
96903
- $ref: `#/components/parameters/${internalMetadata.refId}`
96904
- };
96905
- }
96906
- generateInlineParameters(zodSchema, location) {
96907
- const metadata = Metadata.getOpenApiMetadata(zodSchema);
96908
- const parameterMetadata = metadata === null || metadata === undefined ? undefined : metadata.param;
96909
- const referencedSchema = this.getParameterRef(zodSchema, { in: location });
96910
- if (referencedSchema) {
96911
- return [referencedSchema];
96912
- }
96913
- if (isZodType(zodSchema, "ZodObject")) {
96914
- const propTypes = zodSchema.def.shape;
96915
- const parameters = Object.entries(propTypes).map(([key, schema]) => {
96916
- var _a;
96917
- const innerMetadata = Metadata.getOpenApiMetadata(schema);
96918
- const referencedSchema2 = this.getParameterRef(schema, {
96919
- in: location,
96920
- name: key
96921
- });
96922
- if (referencedSchema2) {
96923
- return referencedSchema2;
96924
- }
96925
- const innerParameterMetadata = innerMetadata === null || innerMetadata === undefined ? undefined : innerMetadata.param;
96926
- if ((innerParameterMetadata === null || innerParameterMetadata === undefined ? undefined : innerParameterMetadata.name) && innerParameterMetadata.name !== key) {
96927
- throw new ConflictError(`Conflicting names for parameter`, {
96928
- key: "name",
96929
- values: [key, innerParameterMetadata.name]
96930
- });
96931
- }
96932
- if ((innerParameterMetadata === null || innerParameterMetadata === undefined ? undefined : innerParameterMetadata.in) && innerParameterMetadata.in !== location) {
96933
- throw new ConflictError(`Conflicting location for parameter ${(_a = innerParameterMetadata.name) !== null && _a !== undefined ? _a : key}`, {
96934
- key: "in",
96935
- values: [location, innerParameterMetadata.in]
96936
- });
96937
- }
96938
- return this.generateParameter(schema, { name: key, in: location });
96939
- });
96940
- return parameters;
96941
- }
96942
- if ((parameterMetadata === null || parameterMetadata === undefined ? undefined : parameterMetadata.in) && parameterMetadata.in !== location) {
96943
- throw new ConflictError(`Conflicting location for parameter ${parameterMetadata.name}`, {
96944
- key: "in",
96945
- values: [location, parameterMetadata.in]
96946
- });
96947
- }
96948
- return [this.generateParameter(zodSchema, { in: location })];
96949
- }
96950
- generateSimpleParameter(zodSchema, externalParamMetadata) {
96951
- const metadata = Metadata.getParamMetadata(zodSchema);
96952
- const paramMetadata = metadata === null || metadata === undefined ? undefined : metadata.param;
96953
- const mergedParamMetadata = Object.assign(Object.assign({}, paramMetadata), externalParamMetadata);
96954
- const required = !isOptionalSchema(zodSchema) && !isNullableSchema(zodSchema);
96955
- const schema = this.generateSchemaWithRef(zodSchema);
96956
- return Object.assign({
96957
- schema,
96958
- required
96959
- }, Object.keys(mergedParamMetadata).length > 0 ? Metadata.buildParameterMetadata(mergedParamMetadata) : {});
96960
- }
96961
- generateParameter(zodSchema, externalParamMetadata) {
96962
- var _a, _b;
96963
- const metadata = Metadata.getOpenApiMetadata(zodSchema);
96964
- const paramMetadata = metadata === null || metadata === undefined ? undefined : metadata.param;
96965
- const paramName = (_a = externalParamMetadata === null || externalParamMetadata === undefined ? undefined : externalParamMetadata.name) !== null && _a !== undefined ? _a : paramMetadata === null || paramMetadata === undefined ? undefined : paramMetadata.name;
96966
- const paramLocation = (_b = externalParamMetadata === null || externalParamMetadata === undefined ? undefined : externalParamMetadata.in) !== null && _b !== undefined ? _b : paramMetadata === null || paramMetadata === undefined ? undefined : paramMetadata.in;
96967
- if (!paramName) {
96968
- throw new MissingParameterDataError({ missingField: "name" });
96969
- }
96970
- if (!paramLocation) {
96971
- throw new MissingParameterDataError({
96972
- missingField: "in",
96973
- paramName
96974
- });
96975
- }
96976
- const baseParameter = this.generateSimpleParameter(zodSchema, externalParamMetadata);
96977
- return Object.assign(Object.assign({}, baseParameter), { in: paramLocation, name: paramName });
96978
- }
96979
- generateSchemaWithMetadata(zodSchema) {
96980
- const innerSchema = Metadata.unwrapChained(zodSchema);
96981
- const metadata = Metadata.getOpenApiMetadata(zodSchema);
96982
- const defaultValue = Metadata.getDefaultValue(zodSchema);
96983
- const refId = Metadata.getRefId(zodSchema);
96984
- if (refId && typeof this.schemaRefs[refId] === "object") {
96985
- return this.schemaRefs[refId];
96986
- }
96987
- if (refId && this.schemaRefs[refId] === "pending") {
96988
- const refSchema = { $ref: this.generateSchemaRef(refId) };
96989
- return this.versionSpecifics.mapNullableOfRef(refSchema, isNullableSchema(zodSchema));
96990
- }
96991
- if (refId && !this.schemaRefs[refId]) {
96992
- this.schemaRefs[refId] = "pending";
96993
- }
96994
- const result = (metadata === null || metadata === undefined ? undefined : metadata.type) ? { type: metadata.type } : this.toOpenAPISchema(innerSchema, isNullableSchema(zodSchema), defaultValue);
96995
- return metadata ? Metadata.applySchemaMetadata(result, metadata) : omitBy(result, isUndefined);
96996
- }
96997
- constructReferencedOpenAPISchema(zodSchema) {
96998
- const metadata = Metadata.getOpenApiMetadata(zodSchema);
96999
- const innerSchema = Metadata.unwrapChained(zodSchema);
97000
- const defaultValue = Metadata.getDefaultValue(zodSchema);
97001
- const isNullable = isNullableSchema(zodSchema);
97002
- if (metadata === null || metadata === undefined ? undefined : metadata.type) {
97003
- return this.versionSpecifics.mapNullableType(metadata.type, isNullable);
97004
- }
97005
- const refId = Metadata.getRefId(zodSchema);
97006
- if (refId && typeof this.schemaRefs[refId] === "object") {
97007
- return LazyTransformer.mapRecursive(this.schemaRefs[refId], (schema) => this.versionSpecifics.mapNullableType(schema, isNullable), (schema) => this.versionSpecifics.mapNullableOfRef(schema, isNullable));
97008
- }
97009
- if (refId && this.schemaRefs[refId] === "pending") {
97010
- const refSchema = { $ref: this.generateSchemaRef(refId) };
97011
- return this.versionSpecifics.mapNullableOfRef(refSchema, isNullable);
97012
- }
97013
- if (refId && !this.schemaRefs[refId]) {
97014
- this.schemaRefs[refId] = "pending";
97015
- }
97016
- return this.toOpenAPISchema(innerSchema, isNullable, defaultValue);
97017
- }
97018
- generateSimpleSchema(zodSchema) {
97019
- const metadata = Metadata.getOpenApiMetadata(zodSchema);
97020
- const refId = Metadata.getRefId(zodSchema);
97021
- if (!refId || !this.schemaRefs[refId]) {
97022
- return this.generateSchemaWithMetadata(zodSchema);
97023
- }
97024
- const schemaRef = this.schemaRefs[refId];
97025
- const referenceObject = {
97026
- $ref: this.generateSchemaRef(refId)
97027
- };
97028
- if (this.schemaRefs[refId] === "pending") {
97029
- return this.versionSpecifics.mapNullableOfRef(referenceObject, isNullableSchema(zodSchema));
97030
- }
97031
- const newMetadata = omitBy(Metadata.buildSchemaMetadata(metadata !== null && metadata !== undefined ? metadata : {}), (value, key) => value === undefined || objectEquals(value, schemaRef[key]));
97032
- if (newMetadata.type) {
97033
- return {
97034
- allOf: [referenceObject, newMetadata]
97035
- };
97036
- }
97037
- const newSchemaMetadata = omitBy(this.constructReferencedOpenAPISchema(zodSchema), (value, key) => value === undefined || objectEquals(value, schemaRef[key]));
97038
- const appliedMetadata = Metadata.applySchemaMetadata(newSchemaMetadata, newMetadata);
97039
- if (Object.keys(appliedMetadata).length > 0) {
97040
- return {
97041
- allOf: [referenceObject, appliedMetadata]
97042
- };
97043
- }
97044
- return referenceObject;
97045
- }
97046
- generateSchemaWithRef(zodSchema) {
97047
- const refId = Metadata.getRefId(zodSchema);
97048
- if (refId && !this.schemaRefs[refId]) {
97049
- this.schemaRefs[refId] = this.generateSimpleSchema(zodSchema);
97050
- return { $ref: this.generateSchemaRef(refId) };
97051
- }
97052
- return this.generateSimpleSchema(zodSchema);
97053
- }
97054
- generateSchemaRef(refId) {
97055
- return `#/components/schemas/${refId}`;
97056
- }
97057
- getRequestBody(requestBody) {
97058
- if (!requestBody) {
97059
- return;
97060
- }
97061
- const { content } = requestBody, rest = __rest(requestBody, ["content"]);
97062
- const requestBodyContent = this.getBodyContent(content);
97063
- return Object.assign(Object.assign({}, rest), { content: requestBodyContent });
97064
- }
97065
- getParameters(request) {
97066
- if (!request) {
97067
- return [];
97068
- }
97069
- const { headers: headers2 } = request;
97070
- const query = this.cleanParameter(request.query);
97071
- const params = this.cleanParameter(request.params);
97072
- const cookies = this.cleanParameter(request.cookies);
97073
- const queryParameters = enhanceMissingParametersError(() => query ? this.generateInlineParameters(query, "query") : [], { location: "query" });
97074
- const pathParameters = enhanceMissingParametersError(() => params ? this.generateInlineParameters(params, "path") : [], { location: "path" });
97075
- const cookieParameters = enhanceMissingParametersError(() => cookies ? this.generateInlineParameters(cookies, "cookie") : [], { location: "cookie" });
97076
- const headerParameters = enhanceMissingParametersError(() => {
97077
- if (Array.isArray(headers2)) {
97078
- return headers2.flatMap((header) => this.generateInlineParameters(header, "header"));
97079
- }
97080
- const cleanHeaders = this.cleanParameter(headers2);
97081
- return cleanHeaders ? this.generateInlineParameters(cleanHeaders, "header") : [];
97082
- }, { location: "header" });
97083
- return [
97084
- ...pathParameters,
97085
- ...queryParameters,
97086
- ...headerParameters,
97087
- ...cookieParameters
97088
- ];
97089
- }
97090
- cleanParameter(schema) {
97091
- if (!schema) {
97092
- return;
97093
- }
97094
- if (isZodType(schema, "ZodPipe")) {
97095
- const inSchema = schema._zod.def.in;
97096
- const outSchema = schema._zod.def.out;
97097
- if (isZodType(inSchema, "ZodObject")) {
97098
- return this.cleanParameter(inSchema);
97099
- }
97100
- if (isZodType(outSchema, "ZodObject")) {
97101
- return this.cleanParameter(outSchema);
97102
- }
97103
- return;
97104
- }
97105
- return schema;
97106
- }
97107
- generatePath(route) {
97108
- const { method, path, request, responses } = route, pathItemConfig = __rest(route, ["method", "path", "request", "responses"]);
97109
- const generatedResponses = mapValues(responses, (response) => {
97110
- return this.getResponse(response);
97111
- });
97112
- const parameters = enhanceMissingParametersError(() => this.getParameters(request), { route: `${method} ${path}` });
97113
- const requestBody = this.getRequestBody(request === null || request === undefined ? undefined : request.body);
97114
- const routeDoc = {
97115
- [method]: Object.assign(Object.assign(Object.assign(Object.assign({}, pathItemConfig), parameters.length > 0 ? {
97116
- parameters: [...pathItemConfig.parameters || [], ...parameters]
97117
- } : {}), requestBody ? { requestBody } : {}), { responses: generatedResponses })
97118
- };
97119
- return routeDoc;
97120
- }
97121
- generateSingleRoute(route) {
97122
- const routeDoc = this.generatePath(route);
97123
- this.pathRefs[route.path] = Object.assign(Object.assign({}, this.pathRefs[route.path]), routeDoc);
97124
- return routeDoc;
97125
- }
97126
- getResponse(response) {
97127
- if (this.isReferenceObject(response)) {
97128
- return response;
97129
- }
97130
- const { content, headers: headers2 } = response, rest = __rest(response, ["content", "headers"]);
97131
- const responseContent = content ? { content: this.getBodyContent(content) } : {};
97132
- if (!headers2) {
97133
- return Object.assign(Object.assign({}, rest), responseContent);
97134
- }
97135
- const responseHeaders = isZodType(headers2, "ZodObject") ? this.getResponseHeaders(headers2) : headers2;
97136
- return Object.assign(Object.assign(Object.assign({}, rest), { headers: responseHeaders }), responseContent);
97137
- }
97138
- isReferenceObject(schema) {
97139
- return "$ref" in schema;
97140
- }
97141
- getResponseHeaders(headers2) {
97142
- const schemaShape = headers2.def.shape;
97143
- const responseHeaders = mapValues(schemaShape, (_) => this.generateSimpleParameter(_));
97144
- return responseHeaders;
97145
- }
97146
- getBodyContent(content) {
97147
- return mapValues(content, (config) => {
97148
- if (!config || !isAnyZodType(config.schema)) {
97149
- return config;
97150
- }
97151
- const { schema: configSchema } = config, rest = __rest(config, ["schema"]);
97152
- const schema = this.generateSchemaWithRef(configSchema);
97153
- return Object.assign({ schema }, rest);
97154
- });
97155
- }
97156
- toOpenAPISchema(zodSchema, isNullable, defaultValue) {
97157
- const result = this.openApiTransformer.transform(zodSchema, isNullable, (_) => this.generateSchemaWithRef(_), (_) => this.generateSchemaRef(_), defaultValue);
97158
- return result;
97159
- }
97160
- }
97161
- class OpenApiGeneratorV31Specifics {
97162
- get nullType() {
97163
- return { type: "null" };
97164
- }
97165
- mapNullableOfArray(objects, isNullable) {
97166
- if (isNullable && !objects.some((object4) => objectEquals(object4, this.nullType))) {
97167
- return [...objects, this.nullType];
97168
- }
97169
- return objects;
97170
- }
97171
- mapNullableType(type, isNullable) {
97172
- if (!type) {
97173
- return {};
97174
- }
97175
- if (isNullable) {
97176
- const typeArray = Array.isArray(type) ? type : [type];
97177
- const nullableType = uniq([...typeArray, "null"]);
97178
- return { type: nullableType };
97179
- }
97180
- return { type };
97181
- }
97182
- mapNullableOfRef(ref, isNullable) {
97183
- if (isNullable) {
97184
- return {
97185
- oneOf: [ref, this.nullType]
97186
- };
97187
- }
97188
- return ref;
97189
- }
97190
- mapTupleItems(schemas2) {
97191
- return {
97192
- prefixItems: schemas2
97193
- };
97194
- }
97195
- getNumberChecks(checks2) {
97196
- return Object.assign({}, ...checks2.map((check) => {
97197
- switch (check._zod.def.check) {
97198
- case "greater_than": {
97199
- const greaterThanCheck = check;
97200
- return greaterThanCheck._zod.def.inclusive ? { minimum: Number(greaterThanCheck._zod.def.value) } : { exclusiveMinimum: Number(greaterThanCheck._zod.def.value) };
97201
- }
97202
- case "less_than": {
97203
- const lessThanCheck = check;
97204
- return lessThanCheck._zod.def.inclusive ? { maximum: Number(lessThanCheck._zod.def.value) } : { exclusiveMaximum: Number(lessThanCheck._zod.def.value) };
97205
- }
97206
- default:
97207
- return {};
97208
- }
97209
- }));
97210
- }
97211
- }
97212
- function isWebhookDefinition(definition) {
97213
- return "type" in definition && definition.type === "webhook";
97214
- }
97215
-
97216
- class OpenApiGeneratorV31 {
97217
- constructor(definitions, options) {
97218
- this.definitions = definitions;
97219
- this.webhookRefs = {};
97220
- const specifics = new OpenApiGeneratorV31Specifics;
97221
- this.generator = new OpenAPIGenerator(this.definitions, specifics, options);
97222
- }
97223
- generateDocument(config) {
97224
- const baseDocument = this.generator.generateDocumentData();
97225
- this.definitions.filter(isWebhookDefinition).forEach((definition) => this.generateSingleWebhook(definition.webhook));
97226
- return Object.assign(Object.assign(Object.assign({}, config), baseDocument), { webhooks: this.webhookRefs });
97227
- }
97228
- generateComponents() {
97229
- return this.generator.generateComponents();
97230
- }
97231
- generateSingleWebhook(route) {
97232
- const routeDoc = this.generator.generatePath(route);
97233
- this.webhookRefs[route.path] = Object.assign(Object.assign({}, this.webhookRefs[route.path]), routeDoc);
97234
- return routeDoc;
97235
- }
97236
- }
97237
- var $OpenAPIRegistry = OpenAPIRegistry;
97238
- var $OpenApiGeneratorV31 = OpenApiGeneratorV31;
97239
- var $extendZodWithOpenApi = extendZodWithOpenApi;
97240
-
97241
95827
  // src/http/openapi.ts
97242
- init_zod();
95828
+ init_dist();
97243
95829
  init_constants();
95830
+ init_zod_openapi();
97244
95831
 
97245
95832
  // src/http/route-def.ts
97246
95833
  init_zod();
@@ -97310,7 +95897,10 @@ async function parseBody(req) {
97310
95897
  for await (const chunk of req) {
97311
95898
  chunks.push(chunk);
97312
95899
  }
97313
- return JSON.parse(Buffer.concat(chunks).toString());
95900
+ const raw = Buffer.concat(chunks).toString();
95901
+ if (raw.trim() === "")
95902
+ return {};
95903
+ return JSON.parse(raw);
97314
95904
  }
97315
95905
  var BODY_TOO_LARGE = Symbol("body-too-large");
97316
95906
  function enforceContentLengthCap(req, res, maxBytes) {
@@ -97415,10 +96005,24 @@ function describeRequestRoute(method, pathSegments) {
97415
96005
  const first = pathSegments[0];
97416
96006
  return { spanName: first ? `${m} /${first}` : m };
97417
96007
  }
96008
+ var VALIDATE_RESPONSES = true;
97418
96009
  function route(def) {
97419
96010
  routeRegistry.push(def);
97420
96011
  return {
97421
96012
  def,
96013
+ respond(res, code, data) {
96014
+ if (VALIDATE_RESPONSES) {
96015
+ const schema = def.responses[code]?.schema;
96016
+ if (schema) {
96017
+ const result = schema.safeParse(data);
96018
+ if (!result.success) {
96019
+ throw new Error(`Response schema violation: ${def.method.toUpperCase()} ${def.path} ${code} — ` + result.error.issues.map((i) => `${i.path.join(".") || "<root>"}: ${i.message}`).join("; "));
96020
+ }
96021
+ }
96022
+ }
96023
+ res.writeHead(code, { "Content-Type": "application/json" });
96024
+ res.end(JSON.stringify(data));
96025
+ },
97422
96026
  match(method, pathSegments) {
97423
96027
  return matchRoute(method, pathSegments, def.method.toUpperCase(), def.pattern, def.exact ?? true);
97424
96028
  },
@@ -97449,18 +96053,18 @@ function route(def) {
97449
96053
  }
97450
96054
 
97451
96055
  // src/http/openapi.ts
97452
- $extendZodWithOpenApi(exports_external);
96056
+ var ErrorResponseSchema = exports_zod.looseObject({ error: exports_zod.string() }).openapi("ErrorResponse", { description: "Standard error envelope" });
97453
96057
  var cachedSpec = null;
97454
96058
  function generateOpenApiSpec(opts) {
97455
96059
  if (cachedSpec)
97456
96060
  return cachedSpec;
97457
- const registry2 = new $OpenAPIRegistry;
97458
- registry2.registerComponent("securitySchemes", "bearerAuth", {
96061
+ const registry = new $OpenAPIRegistry;
96062
+ registry.registerComponent("securitySchemes", "bearerAuth", {
97459
96063
  type: "http",
97460
96064
  scheme: "bearer",
97461
96065
  description: "API key via Authorization: Bearer <API_KEY>"
97462
96066
  });
97463
- registry2.registerComponent("securitySchemes", "agentId", {
96067
+ registry.registerComponent("securitySchemes", "agentId", {
97464
96068
  type: "apiKey",
97465
96069
  in: "header",
97466
96070
  name: "X-Agent-ID",
@@ -97469,11 +96073,12 @@ function generateOpenApiSpec(opts) {
97469
96073
  for (const routeDef of routeRegistry) {
97470
96074
  const responses = {};
97471
96075
  for (const [code, resDef] of Object.entries(routeDef.responses)) {
96076
+ const schema = resDef.schema ?? (Number(code) >= 400 && !resDef.unstructured ? ErrorResponseSchema : undefined);
97472
96077
  responses[code] = {
97473
96078
  description: resDef.description,
97474
- ...resDef.schema && {
96079
+ ...schema && {
97475
96080
  content: {
97476
- "application/json": { schema: resDef.schema }
96081
+ "application/json": { schema }
97477
96082
  }
97478
96083
  }
97479
96084
  };
@@ -97488,7 +96093,7 @@ function generateOpenApiSpec(opts) {
97488
96093
  content: { "application/json": { schema: routeDef.body } }
97489
96094
  };
97490
96095
  }
97491
- registry2.registerPath({
96096
+ registry.registerPath({
97492
96097
  method: routeDef.method,
97493
96098
  path: routeDef.path,
97494
96099
  operationId: routeDef.operationId,
@@ -97501,7 +96106,36 @@ function generateOpenApiSpec(opts) {
97501
96106
  });
97502
96107
  }
97503
96108
  const serverUrl = opts.serverUrl || getPublicMcpBaseUrl();
97504
- const generator = new $OpenApiGeneratorV31(registry2.definitions);
96109
+ function fixNullableAllOf(node) {
96110
+ if (!node || typeof node !== "object")
96111
+ return;
96112
+ if (Array.isArray(node)) {
96113
+ for (const item of node)
96114
+ fixNullableAllOf(item);
96115
+ return;
96116
+ }
96117
+ const obj = node;
96118
+ const allOf = obj.allOf;
96119
+ if (Array.isArray(allOf)) {
96120
+ let hadNull = false;
96121
+ for (const member of allOf) {
96122
+ if (member && Array.isArray(member.type) && member.type.includes("null")) {
96123
+ hadNull = true;
96124
+ const rest = member.type.filter((t) => t !== "null");
96125
+ member.type = rest.length === 1 ? rest[0] : rest;
96126
+ }
96127
+ }
96128
+ if (hadNull) {
96129
+ const members = allOf.filter((m) => !(Object.keys(m).length === 1 && m.type === "object"));
96130
+ const intersection3 = members.length === 1 ? members[0] : { allOf: members };
96131
+ delete obj.allOf;
96132
+ obj.anyOf = [intersection3, { type: "null" }];
96133
+ }
96134
+ }
96135
+ for (const value of Object.values(obj))
96136
+ fixNullableAllOf(value);
96137
+ }
96138
+ const generator = new $OpenApiGeneratorV31(registry.definitions);
97505
96139
  const doc = generator.generateDocument({
97506
96140
  openapi: "3.1.0",
97507
96141
  info: {
@@ -97518,6 +96152,8 @@ function generateOpenApiSpec(opts) {
97518
96152
  }
97519
96153
  ]
97520
96154
  });
96155
+ fixNullableAllOf(doc.paths);
96156
+ fixNullableAllOf(doc.components);
97521
96157
  cachedSpec = JSON.stringify(doc, null, 2);
97522
96158
  return cachedSpec;
97523
96159
  }
@@ -97880,7 +96516,7 @@ async function initOtel(serviceRole = process.env.AGENT_ROLE || "api") {
97880
96516
  return;
97881
96517
  initialized6 = true;
97882
96518
  try {
97883
- const impl = await import("./otel-impl-sqagjerv.js");
96519
+ const impl = await import("./otel-impl-p6jvgd9c.js");
97884
96520
  await impl.boot(serviceRole);
97885
96521
  realWithSpan = impl.withSpan;
97886
96522
  realStartSpan = impl.startSpan;
@@ -98069,6 +96705,14 @@ var NUDGES = {
98069
96705
  const results = r.data?.results;
98070
96706
  return Array.isArray(results) && results.some((entry) => Boolean(entry?.rateHint)) ? "Rate memories that help or mislead you with memory_rate." : undefined;
98071
96707
  },
96708
+ "app-get": (r) => {
96709
+ if (!r.ok)
96710
+ return;
96711
+ const definition = r.data?.app?.definition;
96712
+ const hasQueries = Object.keys(definition?.queries ?? {}).length > 0;
96713
+ const hasActions = Object.keys(definition?.actions ?? {}).length > 0;
96714
+ return hasQueries || hasActions ? "This app's callable surface is `definition.queries` (run with `app-query`, passing any `$param` values) and `definition.actions` (invoke with `POST /api/apps/<id>/actions/<name>`; `sync` actions refresh sources)." : undefined;
96715
+ },
98072
96716
  "kv-get": (r) => {
98073
96717
  if (!r.ok)
98074
96718
  return;
@@ -98560,13 +97204,41 @@ function validValue(column, value) {
98560
97204
  return typeof value === "string" && isIso8601Date(value);
98561
97205
  return typeof value === "string" && Boolean(column.enum?.includes(value));
98562
97206
  }
98563
- function prepareValues(definition, values, mode) {
97207
+ function joinKeyColumnNames(definition) {
97208
+ const names = new Set;
97209
+ for (const source of Object.values(definition.sources ?? {}))
97210
+ names.add(source.joinKey);
97211
+ return names;
97212
+ }
97213
+ function sourceEnvelope(options) {
97214
+ return options.allowSourceManaged === true ? options.envelope : undefined;
97215
+ }
97216
+ function prepareValues(definition, values, mode, options = {}) {
98564
97217
  const issues = [];
98565
97218
  const prepared = { ...values };
97219
+ const sourceManaged = options.allowSourceManaged === true;
97220
+ if (sourceManaged && !options.envelope) {
97221
+ throw new Error("allowSourceManaged writes must carry an envelope");
97222
+ }
97223
+ const joinKeys = sourceManaged ? new Set : joinKeyColumnNames(definition);
98566
97224
  for (const name of Object.keys(values)) {
98567
97225
  const column = Object.hasOwn(definition.columns, name) ? definition.columns[name] : undefined;
98568
97226
  if (!column || column.hidden === true) {
98569
97227
  issues.push({ path: `values.${name}`, message: `unknown or hidden column "${name}"` });
97228
+ continue;
97229
+ }
97230
+ if (sourceManaged)
97231
+ continue;
97232
+ if (column.source) {
97233
+ issues.push({
97234
+ path: `values.${name}`,
97235
+ message: `column is a read-only projection from source "${column.source.of}"; mutate it via the source or a sync refresh`
97236
+ });
97237
+ } else if (joinKeys.has(name)) {
97238
+ issues.push({
97239
+ path: `values.${name}`,
97240
+ message: "column is the sync join key and is managed by the sync engine"
97241
+ });
98570
97242
  }
98571
97243
  }
98572
97244
  if (mode === "create") {
@@ -98575,6 +97247,8 @@ function prepareValues(definition, values, mode) {
98575
97247
  continue;
98576
97248
  if (!Object.hasOwn(prepared, name) && column.default !== undefined)
98577
97249
  prepared[name] = column.default;
97250
+ if (sourceManaged && column.source)
97251
+ continue;
98578
97252
  if (column.required === true && (!Object.hasOwn(prepared, name) || prepared[name] === undefined || prepared[name] === null)) {
98579
97253
  issues.push({ path: `values.${name}`, message: "required column is missing" });
98580
97254
  }
@@ -98626,25 +97300,33 @@ function currentModelDefinition(appId2, model) {
98626
97300
  return null;
98627
97301
  }
98628
97302
  }
98629
- function createRowUnlocked(appId2, model, definition, prepared, actor) {
97303
+ function createRowUnlocked(appId2, model, definition, prepared, options) {
98630
97304
  const issuedMs = Math.max(Date.now(), lastCreatedAtMs + 1);
98631
97305
  lastCreatedAtMs = issuedMs;
98632
97306
  const now = new Date(issuedMs).toISOString();
97307
+ const actor = options.actor;
98633
97308
  return writeRow(appId2, model, definition, {
98634
97309
  id: crypto.randomUUID(),
98635
97310
  createdAt: now,
98636
97311
  updatedAt: now,
98637
97312
  ...actor !== undefined ? { createdBy: actor, updatedBy: actor } : {},
98638
- ...prepared
97313
+ ...prepared,
97314
+ ...sourceEnvelope(options)
98639
97315
  });
98640
97316
  }
97317
+ function createAppRowUnlocked(appId2, model, definition, values, options = {}) {
97318
+ const prepared = prepareValues(definition, values, "create", options);
97319
+ if (!appExists(appId2))
97320
+ throw new AppRowAppNotFoundError(appId2);
97321
+ return createRowUnlocked(appId2, model, definition, prepared, options);
97322
+ }
98641
97323
  function createAppRow(appId2, model, _definition, values, options = {}) {
98642
97324
  return withMutationLock(appId2, model, () => {
98643
97325
  const currentDefinition = currentModelDefinition(appId2, model);
98644
97326
  if (!currentDefinition)
98645
97327
  throw new AppRowAppNotFoundError(appId2);
98646
- const prepared = prepareValues(currentDefinition, values, "create");
98647
- return createRowUnlocked(appId2, model, currentDefinition, prepared, options.actor);
97328
+ const prepared = prepareValues(currentDefinition, values, "create", options);
97329
+ return createRowUnlocked(appId2, model, currentDefinition, prepared, options);
98648
97330
  });
98649
97331
  }
98650
97332
  function createAppRows(appId2, model, _definition, rows, options = {}) {
@@ -98652,8 +97334,8 @@ function createAppRows(appId2, model, _definition, rows, options = {}) {
98652
97334
  const currentDefinition = currentModelDefinition(appId2, model);
98653
97335
  if (!currentDefinition)
98654
97336
  throw new AppRowAppNotFoundError(appId2);
98655
- const prepared = rows.map((values) => prepareValues(currentDefinition, values, "create"));
98656
- return prepared.map((values) => createRowUnlocked(appId2, model, currentDefinition, values, options.actor));
97337
+ const prepared = rows.map((values) => prepareValues(currentDefinition, values, "create", options));
97338
+ return prepared.map((values) => createRowUnlocked(appId2, model, currentDefinition, values, options));
98657
97339
  });
98658
97340
  }
98659
97341
  function getAppRow(appId2, model, rowId) {
@@ -98690,7 +97372,7 @@ function patchAppRow(appId2, model, _definition, rowId, values, options = {}) {
98690
97372
  const currentDefinition = currentModelDefinition(appId2, model);
98691
97373
  if (!currentDefinition)
98692
97374
  throw new AppRowAppNotFoundError(appId2);
98693
- const prepared = prepareValues(currentDefinition, values, "patch");
97375
+ const prepared = prepareValues(currentDefinition, values, "patch", options);
98694
97376
  return patchPreparedRowUnlocked(appId2, model, currentDefinition, rowId, prepared, options);
98695
97377
  });
98696
97378
  }
@@ -98714,6 +97396,7 @@ function patchPreparedRowUnlocked(appId2, model, definition, rowId, prepared, op
98714
97396
  updated[name] = value;
98715
97397
  }
98716
97398
  }
97399
+ Object.assign(updated, sourceEnvelope(options));
98717
97400
  const newKeys = new Set(indexKeys(model, definition, updated));
98718
97401
  const namespace = appsNamespace(appId2);
98719
97402
  for (const key of oldKeys)
@@ -98726,6 +97409,10 @@ function patchPreparedRowUnlocked(appId2, model, definition, rowId, prepared, op
98726
97409
  }
98727
97410
  return updated;
98728
97411
  }
97412
+ function patchAppRowUnlocked(appId2, model, definition, rowId, values, options = {}) {
97413
+ const prepared = prepareValues(definition, values, "patch", options);
97414
+ return patchPreparedRowUnlocked(appId2, model, definition, rowId, prepared, options);
97415
+ }
98729
97416
  function writeAppRowForMigrationUnlocked(appId2, model, row) {
98730
97417
  upsertKv({
98731
97418
  namespace: appsNamespace(appId2),
@@ -98802,6 +97489,572 @@ function purgeAppRows(appId2, models, afterPurge) {
98802
97489
  return acquire(0);
98803
97490
  }
98804
97491
 
97492
+ // src/apps/sync.ts
97493
+ init_zod();
97494
+ init_db();
97495
+ init_types();
97496
+ init_secret_scrubber();
97497
+ var MAX_PULL_RECORDS = 500;
97498
+ var MAX_PASS_WARNINGS = 20;
97499
+ var MAX_TASK_LIMIT = 200;
97500
+ var DEFAULT_TASK_LIMIT = 100;
97501
+ var MAX_TASK_PROMPT_CHARS = 1000;
97502
+ var MAX_ERROR_DETAIL_CHARS = 500;
97503
+
97504
+ class SyncPassError extends Error {
97505
+ constructor(message) {
97506
+ super(message);
97507
+ this.name = "SyncPassError";
97508
+ }
97509
+ }
97510
+
97511
+ class TransformError extends Error {
97512
+ }
97513
+ function warn(warnings, message) {
97514
+ if (warnings.length < MAX_PASS_WARNINGS)
97515
+ warnings.push(message);
97516
+ }
97517
+ function syncStatusKey(model, source) {
97518
+ return `sync-status:${model}:${source}`;
97519
+ }
97520
+ function writeSyncStatus(appId2, pass, lastStartedAt) {
97521
+ if (!getApp(appId2))
97522
+ return;
97523
+ const status = {
97524
+ lastStartedAt,
97525
+ lastFinishedAt: new Date().toISOString(),
97526
+ ok: pass.error === undefined,
97527
+ created: pass.created,
97528
+ updated: pass.updated,
97529
+ refreshed: pass.refreshed,
97530
+ markedStale: pass.markedStale,
97531
+ ...pass.error === undefined ? {} : { error: pass.error }
97532
+ };
97533
+ upsertKv({
97534
+ namespace: appsNamespace(appId2),
97535
+ key: syncStatusKey(pass.model, pass.source),
97536
+ value: status,
97537
+ valueType: "json"
97538
+ });
97539
+ }
97540
+ function getAppSyncStatus(appId2, model, source) {
97541
+ const entry = getKv(appsNamespace(appId2), syncStatusKey(model, source));
97542
+ const value = entry?.value;
97543
+ if (typeof value !== "object" || value === null || Array.isArray(value))
97544
+ return null;
97545
+ return value;
97546
+ }
97547
+ function collectAppSyncStatus(appId2) {
97548
+ const statuses = {};
97549
+ const app = getApp(appId2);
97550
+ if (!app || appDefinitionNeedsRepair(app))
97551
+ return statuses;
97552
+ for (const [modelName, model] of Object.entries(app.definition.models)) {
97553
+ for (const sourceName of Object.keys(model.sources ?? {})) {
97554
+ const status = getAppSyncStatus(appId2, modelName, sourceName);
97555
+ if (status)
97556
+ statuses[`${modelName}:${sourceName}`] = status;
97557
+ }
97558
+ }
97559
+ return statuses;
97560
+ }
97561
+ function invalidateChangedSyncStatus(appId2, previous, next) {
97562
+ if (!previous)
97563
+ return;
97564
+ for (const [modelName, oldModel] of Object.entries(previous.models)) {
97565
+ for (const [sourceName, oldSource] of Object.entries(oldModel.sources ?? {})) {
97566
+ const nextModel = next.models[modelName];
97567
+ const nextSource = nextModel?.sources?.[sourceName];
97568
+ const unchanged = nextModel !== undefined && nextSource !== undefined && pairFingerprint(nextModel, sourceName, nextSource) === pairFingerprint(oldModel, sourceName, oldSource);
97569
+ if (!unchanged)
97570
+ deleteKv(appsNamespace(appId2), syncStatusKey(modelName, sourceName));
97571
+ }
97572
+ }
97573
+ }
97574
+ var SourceRecordSchema = object({
97575
+ key: union([string().min(1), number()]).transform(String),
97576
+ fields: record(string(), unknown())
97577
+ });
97578
+ var PullPayloadSchema = union([
97579
+ array(SourceRecordSchema),
97580
+ object({ records: array(SourceRecordSchema), complete: boolean().optional() })
97581
+ ]);
97582
+ function scriptFailure(output) {
97583
+ if (output.exitCode === 0 && !output.error && !output.runtimeError)
97584
+ return;
97585
+ const base = output.runtimeError ? `${output.runtimeError.name}: ${output.runtimeError.message}` : output.error ?? `script exited with code ${output.exitCode}`;
97586
+ const stderr = scrubSecrets(output.stderr).trim().slice(0, MAX_ERROR_DETAIL_CHARS);
97587
+ return stderr.length > 0 ? `${base} — ${stderr}` : base;
97588
+ }
97589
+ function parsePullPayload(payload, warnings) {
97590
+ const parsed = PullPayloadSchema.safeParse(payload);
97591
+ if (!parsed.success) {
97592
+ const detail = parsed.error.issues.slice(0, 3).map((issue) => `${issue.path.join(".") || "<root>"}: ${issue.message}`).join("; ");
97593
+ throw new SyncPassError(`source script returned an invalid payload — expected Array<{key, fields}> or {records, complete?} (${detail})`);
97594
+ }
97595
+ let records = Array.isArray(parsed.data) ? parsed.data : parsed.data.records;
97596
+ let complete = Array.isArray(parsed.data) ? true : parsed.data.complete ?? true;
97597
+ if (records.length > MAX_PULL_RECORDS) {
97598
+ warn(warnings, `source returned ${records.length} records; truncated to the ${MAX_PULL_RECORDS}-record cap and the stale sweep is skipped`);
97599
+ records = records.slice(0, MAX_PULL_RECORDS);
97600
+ complete = false;
97601
+ }
97602
+ return { records, complete, warnings };
97603
+ }
97604
+ async function pullFromScript(args) {
97605
+ const warnings = [];
97606
+ const { source } = args;
97607
+ const script = getScriptById(source.scriptId);
97608
+ if (!script)
97609
+ throw new SyncPassError(`script "${source.scriptId}" not found`);
97610
+ const agentId = resolveSyncRunAs(script);
97611
+ if (source.connection !== undefined) {
97612
+ const reachable = listScriptConnections({ agentId });
97613
+ if (!reachable.some((connection) => connection.slug === source.connection)) {
97614
+ throw new SyncPassError(`connection "${source.connection}" not found or disabled for the sync run-as identity`);
97615
+ }
97616
+ }
97617
+ const output = await runSavedScriptAsAgent({
97618
+ script,
97619
+ agentId,
97620
+ input: {
97621
+ ...source.args,
97622
+ app: { id: args.appId },
97623
+ model: args.model,
97624
+ source: args.sourceName,
97625
+ ...source.connection ? { connection: source.connection } : {}
97626
+ }
97627
+ });
97628
+ const failure = scriptFailure(output);
97629
+ if (failure)
97630
+ throw new SyncPassError(failure);
97631
+ return parsePullPayload(output.result, warnings);
97632
+ }
97633
+ var TASK_CONFIG_KEYS = new Set([
97634
+ "status",
97635
+ "agentId",
97636
+ "tags",
97637
+ "assetKey",
97638
+ "limit",
97639
+ "includeHeartbeat"
97640
+ ]);
97641
+ function commaList(value) {
97642
+ return String(value).split(",").map((entry) => entry.trim()).filter((entry) => entry.length > 0);
97643
+ }
97644
+ function taskLimit(raw, warnings) {
97645
+ if (raw === undefined)
97646
+ return DEFAULT_TASK_LIMIT;
97647
+ const parsed = Math.trunc(Number(raw));
97648
+ if (!Number.isFinite(parsed) || parsed < 1) {
97649
+ warn(warnings, `config.limit "${String(raw)}" is not a positive integer; using ${DEFAULT_TASK_LIMIT}`);
97650
+ return DEFAULT_TASK_LIMIT;
97651
+ }
97652
+ if (parsed > MAX_TASK_LIMIT) {
97653
+ warn(warnings, `config.limit ${parsed} exceeds the ${MAX_TASK_LIMIT} cap; using ${MAX_TASK_LIMIT}`);
97654
+ return MAX_TASK_LIMIT;
97655
+ }
97656
+ return parsed;
97657
+ }
97658
+ function taskRecord(task) {
97659
+ return {
97660
+ key: task.id,
97661
+ fields: {
97662
+ id: task.id,
97663
+ status: task.status,
97664
+ prompt: scrubSecrets(task.task).slice(0, MAX_TASK_PROMPT_CHARS),
97665
+ source: task.source,
97666
+ agentId: task.agentId,
97667
+ tags: task.tags,
97668
+ priority: task.priority,
97669
+ createdAt: task.createdAt,
97670
+ updatedAt: task.lastUpdatedAt,
97671
+ vcsProvider: task.vcsProvider,
97672
+ vcsNumber: task.vcsNumber,
97673
+ vcsUrl: task.vcsUrl,
97674
+ vcsAuthor: task.vcsAuthor
97675
+ }
97676
+ };
97677
+ }
97678
+ function pullFromSwarmTasks(source, invokedBy) {
97679
+ const warnings = [];
97680
+ const config = source.config ?? {};
97681
+ for (const key of Object.keys(config)) {
97682
+ if (!TASK_CONFIG_KEYS.has(key)) {
97683
+ warn(warnings, `config key "${key}" is not supported by the swarm-tasks connector and was ignored`);
97684
+ }
97685
+ }
97686
+ const limit = taskLimit(config.limit, warnings);
97687
+ const filters = {
97688
+ limit,
97689
+ includeHeartbeat: config.includeHeartbeat === true || config.includeHeartbeat === "true"
97690
+ };
97691
+ if (config.status !== undefined) {
97692
+ const statuses = commaList(config.status).map((token) => {
97693
+ const parsed = AgentTaskStatusSchema.safeParse(token);
97694
+ if (!parsed.success)
97695
+ throw new SyncPassError(`config.status: unknown task status "${token}"`);
97696
+ return parsed.data;
97697
+ });
97698
+ if (statuses.length === 0) {
97699
+ throw new SyncPassError(`config.status must name at least one task status, got ${JSON.stringify(config.status)}`);
97700
+ }
97701
+ filters.status = statuses;
97702
+ }
97703
+ if (config.agentId !== undefined) {
97704
+ if (typeof config.agentId !== "string" || config.agentId.trim().length === 0) {
97705
+ throw new SyncPassError(`config.agentId must be a non-empty string, got ${JSON.stringify(config.agentId)}`);
97706
+ }
97707
+ filters.agentId = config.agentId.trim();
97708
+ }
97709
+ if (config.tags !== undefined) {
97710
+ const tags = commaList(config.tags);
97711
+ if (tags.length === 0) {
97712
+ throw new SyncPassError(`config.tags must name at least one tag, got ${JSON.stringify(config.tags)}`);
97713
+ }
97714
+ filters.tags = tags;
97715
+ }
97716
+ if (config.assetKey !== undefined) {
97717
+ if (typeof config.assetKey !== "string" || config.assetKey.trim().length === 0) {
97718
+ throw new SyncPassError(`config.assetKey must be a non-empty string, got ${JSON.stringify(config.assetKey)}`);
97719
+ }
97720
+ filters.keyPrefix = config.assetKey.trim();
97721
+ }
97722
+ const scopedUserId = invokedBy?.startsWith("user:") ? invokedBy.slice("user:".length) : undefined;
97723
+ if (scopedUserId !== undefined) {
97724
+ filters.requestedByUserId = scopedUserId;
97725
+ warn(warnings, "pull scoped to tasks requested by the invoking user");
97726
+ }
97727
+ const records = getAllTasks(filters).map(taskRecord);
97728
+ return { records, complete: scopedUserId === undefined && records.length < limit, warnings };
97729
+ }
97730
+ function getByDottedPath(fields, path) {
97731
+ let value = fields;
97732
+ for (const segment of path.split(".")) {
97733
+ if (value === null || typeof value !== "object")
97734
+ return;
97735
+ value = value[segment];
97736
+ }
97737
+ return value;
97738
+ }
97739
+ function slugify(value) {
97740
+ return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
97741
+ }
97742
+ function applyTransform(value, transform) {
97743
+ if (value === undefined || value === null)
97744
+ return null;
97745
+ switch (transform) {
97746
+ case undefined:
97747
+ return value;
97748
+ case "lower":
97749
+ return String(value).toLowerCase();
97750
+ case "upper":
97751
+ return String(value).toUpperCase();
97752
+ case "slug":
97753
+ return slugify(String(value));
97754
+ case "cents": {
97755
+ const numeric = Number(value);
97756
+ if (!Number.isFinite(numeric))
97757
+ throw new TransformError(`"${String(value)}" is not a number`);
97758
+ return Math.round(numeric * 100);
97759
+ }
97760
+ case "date-parse": {
97761
+ const date2 = new Date(typeof value === "number" ? value : String(value));
97762
+ if (Number.isNaN(date2.getTime()))
97763
+ throw new TransformError(`"${String(value)}" is not a date`);
97764
+ return date2.toISOString();
97765
+ }
97766
+ }
97767
+ }
97768
+ function validForKind(column, value) {
97769
+ if (column.kind === "string")
97770
+ return typeof value === "string";
97771
+ if (column.kind === "number")
97772
+ return typeof value === "number" && Number.isFinite(value);
97773
+ if (column.kind === "boolean")
97774
+ return typeof value === "boolean";
97775
+ if (column.kind === "date")
97776
+ return typeof value === "string" && isIso8601Date(value);
97777
+ return typeof value === "string" && Boolean(column.enum?.includes(value));
97778
+ }
97779
+ function projectRecord(args) {
97780
+ const values = { [args.joinKey]: args.record.key };
97781
+ for (const [name, column] of args.bindings) {
97782
+ const binding = column.source;
97783
+ if (!binding)
97784
+ continue;
97785
+ const raw = getByDottedPath(args.record.fields, binding.field);
97786
+ let value;
97787
+ try {
97788
+ value = applyTransform(raw, binding.transform);
97789
+ } catch (error) {
97790
+ warn(args.warnings, `column "${name}": transform "${binding.transform}" failed — ${error instanceof Error ? error.message : String(error)}`);
97791
+ value = null;
97792
+ }
97793
+ if (value !== null && !validForKind(column, value)) {
97794
+ warn(args.warnings, `column "${name}": field "${binding.field}" produced a value that is not a valid ${column.kind}`);
97795
+ value = null;
97796
+ }
97797
+ values[name] = value;
97798
+ }
97799
+ return values;
97800
+ }
97801
+ function sameValue(existing, projected) {
97802
+ return Object.is(existing ?? null, projected ?? null);
97803
+ }
97804
+ function resolvePair(appId2, model, source) {
97805
+ const app = getApp(appId2);
97806
+ if (!app || appDefinitionNeedsRepair(app))
97807
+ return null;
97808
+ const modelDef = app.definition.models[model];
97809
+ const sourceDef = modelDef?.sources?.[source];
97810
+ return modelDef && sourceDef ? { model: modelDef, source: sourceDef } : null;
97811
+ }
97812
+ function pairFingerprint(model, sourceName, source) {
97813
+ const bindings = Object.entries(model.columns).filter(([, column]) => column.source?.of === sourceName).map(([name, column]) => ({
97814
+ name,
97815
+ kind: column.kind,
97816
+ enum: column.enum ?? null,
97817
+ required: column.required === true,
97818
+ hidden: column.hidden === true,
97819
+ field: column.source?.field,
97820
+ transform: column.source?.transform ?? null
97821
+ }));
97822
+ return JSON.stringify({ source, bindings });
97823
+ }
97824
+ function reconcile(args) {
97825
+ const { appId: appId2, model, sourceName, joinKey, pull, warnings, counts } = args;
97826
+ return withMutationLock(appId2, model, () => {
97827
+ const fresh = resolvePair(appId2, model, sourceName);
97828
+ if (!fresh) {
97829
+ throw new SyncPassError(`model "${model}" no longer declares source "${sourceName}"; pass aborted with no writes`);
97830
+ }
97831
+ if (pairFingerprint(fresh.model, sourceName, fresh.source) !== args.fingerprint) {
97832
+ throw new SyncPassError(`source "${sourceName}" changed while the pull was running; pass aborted with no writes`);
97833
+ }
97834
+ const modelDef = fresh.model;
97835
+ const bindings = Object.entries(modelDef.columns).filter(([, column]) => column.source?.of === sourceName && column.hidden !== true);
97836
+ const mine = new Map;
97837
+ const unkeyed = [];
97838
+ for (const row of listAllAppRowsForMigrationUnlocked(appId2, model)) {
97839
+ if (row.source !== sourceName)
97840
+ continue;
97841
+ const key = row[joinKey];
97842
+ if (typeof key === "string")
97843
+ mine.set(key, row);
97844
+ else
97845
+ unkeyed.push(row);
97846
+ }
97847
+ const now = new Date().toISOString();
97848
+ const actor = `sync:${sourceName}`;
97849
+ const seen = new Set;
97850
+ for (const record3 of pull.records) {
97851
+ if (seen.has(record3.key)) {
97852
+ warn(warnings, `source returned duplicate key "${record3.key}"; the last record wins`);
97853
+ }
97854
+ seen.add(record3.key);
97855
+ const values = projectRecord({ record: record3, bindings, joinKey, warnings });
97856
+ const envelope = { source: sourceName, syncedAt: now, stale: false };
97857
+ const existing = mine.get(record3.key);
97858
+ if (!existing) {
97859
+ const created = createAppRowUnlocked(appId2, model, modelDef, values, {
97860
+ allowSourceManaged: true,
97861
+ envelope,
97862
+ actor
97863
+ });
97864
+ mine.set(record3.key, created);
97865
+ counts.created += 1;
97866
+ continue;
97867
+ }
97868
+ const differs = Object.entries(values).some(([name, value]) => !sameValue(existing[name], value));
97869
+ const updated = patchAppRowUnlocked(appId2, model, modelDef, existing.id, values, {
97870
+ allowSourceManaged: true,
97871
+ envelope,
97872
+ actor,
97873
+ ...differs ? {} : { skipUpdatedAt: true }
97874
+ });
97875
+ if (!updated) {
97876
+ warn(warnings, `row "${existing.id}" vanished before it could be updated`);
97877
+ continue;
97878
+ }
97879
+ mine.set(record3.key, updated);
97880
+ if (differs)
97881
+ counts.updated += 1;
97882
+ else
97883
+ counts.refreshed += 1;
97884
+ }
97885
+ const unseen = [...mine.entries()].filter(([key]) => !seen.has(key)).map(([, row]) => row).concat(unkeyed);
97886
+ if (!pull.complete) {
97887
+ counts.staleSweepSkipped = true;
97888
+ counts.unchanged += unseen.length;
97889
+ warn(warnings, "pull reported an incomplete window; stale sweep skipped");
97890
+ return;
97891
+ }
97892
+ for (const row of unseen) {
97893
+ if (row.stale === true) {
97894
+ counts.unchanged += 1;
97895
+ continue;
97896
+ }
97897
+ patchAppRowUnlocked(appId2, model, modelDef, row.id, {}, {
97898
+ allowSourceManaged: true,
97899
+ skipUpdatedAt: true,
97900
+ envelope: {
97901
+ source: sourceName,
97902
+ syncedAt: typeof row.syncedAt === "string" ? row.syncedAt : now,
97903
+ stale: true
97904
+ }
97905
+ });
97906
+ counts.markedStale += 1;
97907
+ }
97908
+ });
97909
+ }
97910
+ var inFlight = new Map;
97911
+ function passBase(args) {
97912
+ return {
97913
+ model: args.model,
97914
+ source: args.source,
97915
+ connector: args.connector,
97916
+ pulled: 0,
97917
+ created: 0,
97918
+ updated: 0,
97919
+ refreshed: 0,
97920
+ unchanged: 0,
97921
+ markedStale: 0,
97922
+ warnings: [],
97923
+ durationMs: 0,
97924
+ ...args.invokedBy === undefined ? {} : { invokedBy: args.invokedBy }
97925
+ };
97926
+ }
97927
+ async function executePass(args) {
97928
+ const startedMs = Date.now();
97929
+ const lastStartedAt = new Date(startedMs).toISOString();
97930
+ const warnings = [];
97931
+ const base = passBase({
97932
+ model: args.model,
97933
+ source: args.sourceName,
97934
+ connector: args.source.connector,
97935
+ invokedBy: args.invokedBy
97936
+ });
97937
+ let plannedFingerprint = null;
97938
+ const finish = (result) => {
97939
+ const scrubbed = scrubObject({ ...result, warnings, durationMs: Date.now() - startedMs });
97940
+ const current = resolvePair(args.appId, args.model, args.sourceName);
97941
+ const stillCurrent = plannedFingerprint !== null && current !== null && pairFingerprint(current.model, args.sourceName, current.source) === plannedFingerprint;
97942
+ if (stillCurrent)
97943
+ writeSyncStatus(args.appId, scrubbed, lastStartedAt);
97944
+ return scrubbed;
97945
+ };
97946
+ const counts = {
97947
+ created: 0,
97948
+ updated: 0,
97949
+ refreshed: 0,
97950
+ unchanged: 0,
97951
+ markedStale: 0
97952
+ };
97953
+ let pulled = 0;
97954
+ try {
97955
+ const planned = resolvePair(args.appId, args.model, args.sourceName);
97956
+ if (!planned) {
97957
+ throw new SyncPassError(`model "${args.model}" no longer declares source "${args.sourceName}"; pass aborted with no writes`);
97958
+ }
97959
+ const source = planned.source;
97960
+ const fingerprint = pairFingerprint(planned.model, args.sourceName, source);
97961
+ plannedFingerprint = fingerprint;
97962
+ const pull = scrubObject(source.connector === "script" ? await pullFromScript({
97963
+ appId: args.appId,
97964
+ model: args.model,
97965
+ sourceName: args.sourceName,
97966
+ source
97967
+ }) : pullFromSwarmTasks(source, args.invokedBy));
97968
+ pulled = pull.records.length;
97969
+ for (const warning of pull.warnings)
97970
+ warn(warnings, warning);
97971
+ await reconcile({
97972
+ appId: args.appId,
97973
+ model: args.model,
97974
+ sourceName: args.sourceName,
97975
+ fingerprint,
97976
+ joinKey: source.joinKey,
97977
+ pull,
97978
+ warnings,
97979
+ counts
97980
+ });
97981
+ return finish({ ...base, ...counts, pulled });
97982
+ } catch (error) {
97983
+ const message = error instanceof SyncPassError ? error.message : error instanceof Error ? `${error.name}: ${error.message}` : String(error);
97984
+ return finish({ ...base, ...counts, pulled, error: message });
97985
+ }
97986
+ }
97987
+ async function runPass(args) {
97988
+ const key = `${args.appId}:${args.model}:${args.sourceName}`;
97989
+ if (inFlight.has(key)) {
97990
+ return scrubObject({
97991
+ ...passBase({
97992
+ model: args.model,
97993
+ source: args.sourceName,
97994
+ connector: args.source.connector,
97995
+ invokedBy: args.invokedBy
97996
+ }),
97997
+ warnings: ["a sync pass for this pair is already running; this trigger did not pull"],
97998
+ skipped: true,
97999
+ alreadyRunning: true
98000
+ });
98001
+ }
98002
+ const pass = executePass(args);
98003
+ inFlight.set(key, pass);
98004
+ try {
98005
+ return await pass;
98006
+ } finally {
98007
+ if (inFlight.get(key) === pass)
98008
+ inFlight.delete(key);
98009
+ }
98010
+ }
98011
+ function noPairIssue(input) {
98012
+ if (input.source !== undefined) {
98013
+ return {
98014
+ path: "source",
98015
+ message: input.model !== undefined ? `unknown source "${input.source}" on model "${input.model}"` : `unknown source "${input.source}" — no model declares it`
98016
+ };
98017
+ }
98018
+ if (input.model !== undefined) {
98019
+ return { path: "model", message: `model "${input.model}" declares no sources` };
98020
+ }
98021
+ return { path: "appId", message: "no model declares a source to sync" };
98022
+ }
98023
+ async function runAppSync(input) {
98024
+ const app = getApp(input.appId);
98025
+ if (!app) {
98026
+ return {
98027
+ ok: false,
98028
+ passes: [],
98029
+ issues: [{ path: "appId", message: `app "${input.appId}" not found` }]
98030
+ };
98031
+ }
98032
+ if (appDefinitionNeedsRepair(app)) {
98033
+ return {
98034
+ ok: false,
98035
+ passes: [],
98036
+ issues: [{ path: "definition", message: "app definition needs repair before it can sync" }]
98037
+ };
98038
+ }
98039
+ const models = app.definition.models;
98040
+ if (input.model !== undefined && !Object.hasOwn(models, input.model)) {
98041
+ return {
98042
+ ok: false,
98043
+ passes: [],
98044
+ issues: [{ path: "model", message: `unknown model "${input.model}"` }]
98045
+ };
98046
+ }
98047
+ const pairs = (input.model !== undefined ? [input.model] : Object.keys(models)).flatMap((model) => Object.entries(models[model]?.sources ?? {}).filter(([sourceName]) => input.source === undefined || sourceName === input.source).map(([sourceName, source]) => ({ model, sourceName, source })));
98048
+ if (pairs.length === 0) {
98049
+ return { ok: false, passes: [], issues: [noPairIssue(input)] };
98050
+ }
98051
+ const passes = [];
98052
+ for (const pair of pairs) {
98053
+ passes.push(await runPass({ appId: app.id, ...pair, invokedBy: input.invokedBy }));
98054
+ }
98055
+ return { ok: passes.every((pass) => pass.error === undefined), passes };
98056
+ }
98057
+
98805
98058
  // src/apps/schema-migrate.ts
98806
98059
  var MigrationValueSchema = union([string(), number(), boolean()]);
98807
98060
  var AppMigrationDirectiveSchema = union([
@@ -98824,6 +98077,7 @@ var AppMigrationReportSchema = object({
98824
98077
  elsed: number().int().nonnegative(),
98825
98078
  purgedValues: number().int().nonnegative(),
98826
98079
  idxRebuilt: number().int().nonnegative(),
98080
+ detachedRows: number().int().nonnegative(),
98827
98081
  orphanFields: array(string()),
98828
98082
  userConfigChanged: array(string())
98829
98083
  });
@@ -98835,6 +98089,7 @@ var AppMigrationReportOutputSchema = looseObject({
98835
98089
  elsed: number().optional(),
98836
98090
  purgedValues: number().optional(),
98837
98091
  idxRebuilt: number().optional(),
98092
+ detachedRows: number().optional(),
98838
98093
  orphanFields: array(string()).optional(),
98839
98094
  userConfigChanged: array(string()).optional()
98840
98095
  });
@@ -98862,6 +98117,7 @@ var EMPTY_REPORT = {
98862
98117
  elsed: 0,
98863
98118
  purgedValues: 0,
98864
98119
  idxRebuilt: 0,
98120
+ detachedRows: 0,
98865
98121
  orphanFields: [],
98866
98122
  userConfigChanged: []
98867
98123
  };
@@ -99243,6 +98499,45 @@ function applyDirective(rows, modelName, columnName, directive, oldColumn, nextC
99243
98499
  });
99244
98500
  }
99245
98501
  }
98502
+ function ownSource(model, sourceName) {
98503
+ const sources = model?.sources;
98504
+ return sources && Object.hasOwn(sources, sourceName) ? sources[sourceName] : undefined;
98505
+ }
98506
+ function planSources(modelName, oldModel, nextModel, rows, report, issues) {
98507
+ const sourceNames = new Set([
98508
+ ...Object.keys(oldModel?.sources ?? {}),
98509
+ ...Object.keys(nextModel?.sources ?? {})
98510
+ ]);
98511
+ for (const sourceName of [...sourceNames].sort()) {
98512
+ const oldSource = ownSource(oldModel, sourceName);
98513
+ if (!oldSource)
98514
+ continue;
98515
+ const nextSource = ownSource(nextModel, sourceName);
98516
+ const path = `models.${modelName}.sources.${sourceName}`;
98517
+ const owned = rows.filter((row) => row.source === sourceName);
98518
+ if (!nextSource) {
98519
+ for (const row of owned) {
98520
+ delete row.source;
98521
+ delete row.syncedAt;
98522
+ delete row.stale;
98523
+ report.detachedRows += 1;
98524
+ }
98525
+ continue;
98526
+ }
98527
+ if (nextSource.joinKey !== oldSource.joinKey) {
98528
+ issues.push({
98529
+ path: `${path}.joinKey`,
98530
+ message: "join key is immutable; remove the source and add it again"
98531
+ });
98532
+ }
98533
+ if (nextSource.connector !== oldSource.connector && owned.length > 0) {
98534
+ issues.push({
98535
+ path: `${path}.connector`,
98536
+ message: `connector change would orphan ${owned.length} row(s) this source owns; remove the source and add it again`
98537
+ });
98538
+ }
98539
+ }
98540
+ }
99246
98541
  function planModel(appId2, modelName, oldModel, nextModel, migration, oldSideUnparseable, report, orphanFields, appliedDirectives) {
99247
98542
  const persistedRows = listAllAppRowsForMigrationUnlocked(appId2, modelName);
99248
98543
  const rows = persistedRows.map((row) => structuredClone(row));
@@ -99256,6 +98551,7 @@ function planModel(appId2, modelName, oldModel, nextModel, migration, oldSideUnp
99256
98551
  message: `model holds ${rows.length} ${rows.length === 1 ? "row" : "rows"} — delete its rows before removing the model`
99257
98552
  });
99258
98553
  }
98554
+ planSources(modelName, oldModel, nextModel, rows, report, issues);
99259
98555
  for (const columnName of changedColumns) {
99260
98556
  const oldColumn = ownColumn(oldModel, columnName);
99261
98557
  const nextColumn = ownColumn(nextModel, columnName);
@@ -99279,6 +98575,16 @@ function planModel(appId2, modelName, oldModel, nextModel, migration, oldSideUnp
99279
98575
  }
99280
98576
  continue;
99281
98577
  }
98578
+ if (nextColumn.source !== undefined && (oldColumn?.source === undefined || oldColumn.source.of !== nextColumn.source.of)) {
98579
+ const populated = rows.filter((row) => Object.hasOwn(row, columnName) && row[columnName] !== null).length;
98580
+ if (populated > 0) {
98581
+ issues.push({
98582
+ path: `${path}.source`,
98583
+ message: `binding an existing column would let the next pass overwrite ${populated} row(s) of existing data; hide or purge the column and add it bound instead`
98584
+ });
98585
+ continue;
98586
+ }
98587
+ }
99282
98588
  if (exactUnhide && nextColumn.required === true && (!directive || !("set" in directive))) {
99283
98589
  const missing = rows.filter((row) => !Object.hasOwn(row, columnName) || row[columnName] === null).length;
99284
98590
  if (missing > 0) {
@@ -99434,7 +98740,9 @@ async function migrateAppSchema(input) {
99434
98740
  rebuildAppColumnIndexUnlocked(input.appId, modelPlan.modelName, columnName, ownColumn(nextModel, columnName), modelPlan.rows);
99435
98741
  }
99436
98742
  }
99437
- return input.writeDefinition();
98743
+ const written = input.writeDefinition();
98744
+ invalidateChangedSyncStatus(input.appId, input.previousDefinition, input.nextDefinition);
98745
+ return written;
99438
98746
  });
99439
98747
  return { result: transaction(), migration: plan.report };
99440
98748
  });
@@ -99500,7 +98808,7 @@ function decodeAppVersion(appVersion) {
99500
98808
  }
99501
98809
  };
99502
98810
  }
99503
- function rollbackSnapshot(version) {
98811
+ function rollbackSnapshot(version, writer, existingDefinition) {
99504
98812
  if (typeof version.snapshot !== "object" || version.snapshot === null || Array.isArray(version.snapshot)) {
99505
98813
  throw new AppRollbackDefinitionError(version.version, [
99506
98814
  { path: "snapshot", message: "app version snapshot must be an object" }
@@ -99519,7 +98827,10 @@ function rollbackSnapshot(version) {
99519
98827
  }
99520
98828
  const parsed = parseAppDefinition(upgradeAppDefinition(snapshot.definition), {
99521
98829
  currentAppId: version.appId,
99522
- resolveApp: getApp
98830
+ resolveApp: getApp,
98831
+ writerAgentId: writer.writerAgentId ?? null,
98832
+ ...writer.writerIsUser === undefined ? {} : { writerIsUser: writer.writerIsUser },
98833
+ existingDefinition
99523
98834
  });
99524
98835
  if (!parsed.success)
99525
98836
  throw new AppRollbackDefinitionError(version.version, parsed.issues);
@@ -99537,7 +98848,7 @@ async function rollbackApp(input) {
99537
98848
  const version = getAppVersions(input.appId).find((candidate) => candidate.version === input.version);
99538
98849
  if (!version)
99539
98850
  throw new AppRollbackVersionNotFoundError(input.version);
99540
- const snapshot = rollbackSnapshot(version);
98851
+ const snapshot = rollbackSnapshot(version, input, existing.definition);
99541
98852
  const migrated = await migrateAppSchema({
99542
98853
  appId: input.appId,
99543
98854
  previousDefinition: appDefinitionNeedsRepair(existing) ? undefined : existing.definition,
@@ -99822,8 +99133,10 @@ function upsertAppUserConfigValues(appId2, scope, values) {
99822
99133
  }
99823
99134
 
99824
99135
  // src/http/apps.ts
99136
+ init_key();
99825
99137
  init_db();
99826
99138
  init_resolver();
99139
+ init_types();
99827
99140
  init_request_auth_context();
99828
99141
  init_secret_scrubber();
99829
99142
 
@@ -99901,8 +99214,84 @@ var rowParamsSchema = object({
99901
99214
  rowId: string().min(1)
99902
99215
  });
99903
99216
  var valuesSchema = record(string(), unknown());
99217
+ var AppValidationIssueSchema = object({ path: string(), message: string() });
99218
+ var JsonValueSchema = union([
99219
+ record(string(), unknown()),
99220
+ array(unknown()),
99221
+ string(),
99222
+ number(),
99223
+ boolean(),
99224
+ _null()
99225
+ ]);
99226
+ var AppRecordSchema = object({
99227
+ id: string(),
99228
+ name: string(),
99229
+ description: string().optional(),
99230
+ definition: JsonValueSchema,
99231
+ definitionError: array(AppValidationIssueSchema).optional(),
99232
+ createdAt: string(),
99233
+ updatedAt: string()
99234
+ });
99235
+ var AppSummarySchema = object({
99236
+ id: string(),
99237
+ name: string(),
99238
+ description: string().optional(),
99239
+ createdAt: string(),
99240
+ updatedAt: string()
99241
+ });
99242
+ var AppVersionSchema = object({
99243
+ id: string(),
99244
+ appId: string(),
99245
+ version: number(),
99246
+ snapshot: unknown(),
99247
+ changedByAgentId: string().optional(),
99248
+ createdAt: string()
99249
+ });
99250
+ var AppRowSchema = looseObject({
99251
+ id: string(),
99252
+ createdAt: string(),
99253
+ updatedAt: string(),
99254
+ createdBy: string().optional(),
99255
+ updatedBy: string().optional()
99256
+ });
99257
+ var SyncPassResultSchema = object({
99258
+ model: string(),
99259
+ source: string(),
99260
+ connector: _enum(["script", "swarm-tasks"]),
99261
+ pulled: number(),
99262
+ created: number(),
99263
+ updated: number(),
99264
+ refreshed: number(),
99265
+ unchanged: number(),
99266
+ markedStale: number(),
99267
+ staleSweepSkipped: boolean().optional(),
99268
+ warnings: array(string()),
99269
+ durationMs: number(),
99270
+ invokedBy: string().optional(),
99271
+ error: string().optional(),
99272
+ skipped: literal(true).optional(),
99273
+ alreadyRunning: literal(true).optional()
99274
+ });
99275
+ var AppSyncStatusSchema = object({
99276
+ lastStartedAt: string(),
99277
+ lastFinishedAt: string(),
99278
+ ok: boolean(),
99279
+ created: number(),
99280
+ updated: number(),
99281
+ refreshed: number(),
99282
+ markedStale: number(),
99283
+ error: string().optional()
99284
+ });
99285
+ var UserConfigValuesSchema = record(string(), union([string(), number(), boolean(), _null()]));
99286
+ var AppUserConfigFieldSchema = object({
99287
+ kind: ColumnKindSchema,
99288
+ default: union([string(), number(), boolean()]).optional(),
99289
+ enum: array(string()).optional(),
99290
+ label: string().optional()
99291
+ });
99292
+ var AppUserConfigSchema = record(AppNameSchema, AppUserConfigFieldSchema);
99904
99293
  var appWriteResponseSchema = object({
99905
- app: unknown(),
99294
+ app: AppRecordSchema,
99906
99295
  migration: AppMigrationReportSchema
99907
99296
  });
99908
99297
  var userConfigBodySchema = object({ values: record(string(), unknown()) }).strict();
@@ -99915,7 +99304,10 @@ var getUserConfigRoute = route({
99915
99304
  tags: ["Apps"],
99916
99305
  params: appParamsSchema,
99917
99306
  responses: {
99918
- 200: { description: "Merged user configuration" },
99307
+ 200: {
99308
+ description: "Merged user configuration",
99309
+ schema: object({ values: UserConfigValuesSchema, schema: AppUserConfigSchema })
99310
+ },
99919
99311
  403: { description: "Permission denied" },
99920
99312
  404: { description: "App not found" },
99921
99313
  409: { description: "App definition needs repair" }
@@ -99932,7 +99324,10 @@ var putUserConfigRoute = route({
99932
99324
  params: appParamsSchema,
99933
99325
  body: userConfigBodySchema,
99934
99326
  responses: {
99935
- 200: { description: "Stored user configuration" },
99327
+ 200: {
99328
+ description: "Stored user configuration",
99329
+ schema: object({ values: UserConfigValuesSchema, schema: AppUserConfigSchema })
99330
+ },
99936
99331
  400: { description: "Invalid user configuration" },
99937
99332
  403: { description: "Permission denied" },
99938
99333
  413: { description: "Request exceeds 64 KB or serialized values exceed 16 KB" },
@@ -99947,7 +99342,12 @@ var listAppsRoute = route({
99947
99342
  pattern: ["api", "apps"],
99948
99343
  summary: "List apps",
99949
99344
  tags: ["Apps"],
99950
- responses: { 200: { description: "App summaries without definitions" } },
99345
+ responses: {
99346
+ 200: {
99347
+ description: "App summaries without definitions",
99348
+ schema: object({ apps: array(AppSummarySchema) })
99349
+ }
99350
+ },
99951
99351
  rbac: { ungated: "app summaries are list-level; per-app filtering is future work" }
99952
99352
  });
99953
99353
  var createAppRoute = route({
@@ -99963,7 +99363,7 @@ var createAppRoute = route({
99963
99363
  forceElementBreak: ForceElementBreakSchema.optional()
99964
99364
  }),
99965
99365
  responses: {
99966
- 201: { description: "Created app" },
99366
+ 201: { description: "Created app", schema: object({ app: AppRecordSchema }) },
99967
99367
  400: { description: "Invalid app definition" },
99968
99368
  403: { description: "Permission denied" }
99969
99369
  },
@@ -99977,7 +99377,10 @@ var listAppVersionsRoute = route({
99977
99377
  tags: ["Apps"],
99978
99378
  params: appParamsSchema,
99979
99379
  responses: {
99980
- 200: { description: "App definition versions" },
99380
+ 200: {
99381
+ description: "App definition versions",
99382
+ schema: object({ versions: array(AppVersionSchema) })
99383
+ },
99981
99384
  404: { description: "App not found" }
99982
99385
  },
99983
99386
  rbac: { permission: "app.manage" }
@@ -99990,7 +99393,7 @@ var getAppVersionRoute = route({
99990
99393
  tags: ["Apps"],
99991
99394
  params: appVersionParamsSchema,
99992
99395
  responses: {
99993
- 200: { description: "App definition version" },
99396
+ 200: { description: "App definition version", schema: object({ version: AppVersionSchema }) },
99994
99397
  404: { description: "App or version not found" }
99995
99398
  },
99996
99399
  rbac: { permission: "app.manage" }
@@ -100024,7 +99427,13 @@ var getAppRoute = route({
100024
99427
  tags: ["Apps"],
100025
99428
  params: appParamsSchema,
100026
99429
  responses: {
100027
- 200: { description: "App including its definition" },
99430
+ 200: {
99431
+ description: "App including its definition",
99432
+ schema: object({
99433
+ app: AppRecordSchema,
99434
+ syncStatus: record(string(), AppSyncStatusSchema).optional()
99435
+ })
99436
+ },
100028
99437
  403: { description: "Permission denied" },
100029
99438
  404: { description: "App not found" }
100030
99439
  },
@@ -100083,7 +99492,7 @@ var deleteAppRoute = route({
100083
99492
  tags: ["Apps"],
100084
99493
  params: appParamsSchema,
100085
99494
  responses: {
100086
- 200: { description: "App deleted" },
99495
+ 200: { description: "App deleted", schema: object({ ok: literal(true) }) },
100087
99496
  403: { description: "Permission denied" },
100088
99497
  404: { description: "App not found" }
100089
99498
  },
@@ -100098,7 +99507,7 @@ var createRowRoute = route({
100098
99507
  params: modelParamsSchema,
100099
99508
  body: object({ values: valuesSchema }),
100100
99509
  responses: {
100101
- 201: { description: "Created row" },
99510
+ 201: { description: "Created row", schema: object({ row: AppRowSchema }) },
100102
99511
  400: { description: "Invalid row values" },
100103
99512
  403: { description: "Permission denied" },
100104
99513
  404: { description: "App or model not found" }
@@ -100114,7 +99523,7 @@ var bulkCreateRowsRoute = route({
100114
99523
  params: modelParamsSchema,
100115
99524
  body: object({ rows: array(object({ values: valuesSchema })).max(500) }),
100116
99525
  responses: {
100117
- 200: { description: "Created rows" },
99526
+ 200: { description: "Created rows", schema: object({ rows: array(AppRowSchema) }) },
100118
99527
  400: { description: "Invalid row values" },
100119
99528
  403: { description: "Permission denied" },
100120
99529
  404: { description: "App or model not found" }
@@ -100133,7 +99542,10 @@ var listRowsRoute = route({
100133
99542
  limit: exports_coerce.number().int().positive().max(1000).optional()
100134
99543
  }),
100135
99544
  responses: {
100136
- 200: { description: "Filtered app model rows" },
99545
+ 200: {
99546
+ description: "Filtered app model rows",
99547
+ schema: object({ rows: array(AppRowSchema), total: number() })
99548
+ },
100137
99549
  400: { description: "Invalid filter or sort" },
100138
99550
  403: { description: "Permission denied" },
100139
99551
  404: { description: "App or model not found" }
@@ -100148,7 +99560,7 @@ var getRowRoute = route({
100148
99560
  tags: ["Apps"],
100149
99561
  params: rowParamsSchema,
100150
99562
  responses: {
100151
- 200: { description: "App model row" },
99563
+ 200: { description: "App model row", schema: object({ row: AppRowSchema }) },
100152
99564
  403: { description: "Permission denied" },
100153
99565
  404: { description: "App, model, or row not found" }
100154
99566
  },
@@ -100163,7 +99575,7 @@ var patchRowRoute = route({
100163
99575
  params: rowParamsSchema,
100164
99576
  body: object({ values: valuesSchema }),
100165
99577
  responses: {
100166
- 200: { description: "Updated row" },
99578
+ 200: { description: "Updated row", schema: object({ row: AppRowSchema }) },
100167
99579
  400: { description: "Invalid row values" },
100168
99580
  403: { description: "Permission denied" },
100169
99581
  404: { description: "App, model, or row not found" }
@@ -100178,7 +99590,7 @@ var deleteRowRoute = route({
100178
99590
  tags: ["Apps"],
100179
99591
  params: rowParamsSchema,
100180
99592
  responses: {
100181
- 200: { description: "Row deleted" },
99593
+ 200: { description: "Row deleted", schema: object({ ok: literal(true) }) },
100182
99594
  403: { description: "Permission denied" },
100183
99595
  404: { description: "App, model, or row not found" }
100184
99596
  },
@@ -100192,7 +99604,7 @@ var runNamedQueryRoute = route({
100192
99604
  tags: ["Apps"],
100193
99605
  params: object({ id: string().min(1), name: AppNameSchema }),
100194
99606
  responses: {
100195
- 200: { description: "Named query rows" },
99607
+ 200: { description: "Named query rows", schema: object({ rows: array(AppRowSchema) }) },
100196
99608
  400: { description: "Missing or invalid named query parameters" },
100197
99609
  403: { description: "Permission denied" },
100198
99610
  409: { description: "App definition needs repair" },
@@ -100200,6 +99612,29 @@ var runNamedQueryRoute = route({
100200
99612
  },
100201
99613
  rbac: { permission: "app.use" }
100202
99614
  });
99615
+ var runActionScriptResultSchema = object({
99616
+ ok: boolean(),
99617
+ result: unknown(),
99618
+ stdout: string(),
99619
+ error: string().optional(),
99620
+ durationMs: number()
99621
+ });
99622
+ var runActionTaskResultSchema = object({
99623
+ ok: literal(true),
99624
+ taskId: string(),
99625
+ status: AgentTaskStatusSchema
99626
+ });
99627
+ var runActionSyncResultSchema = object({
99628
+ ok: boolean(),
99629
+ result: object({ passes: array(SyncPassResultSchema) }),
99630
+ error: string().optional(),
99631
+ durationMs: number()
99632
+ });
99633
+ var runActionResultSchema = union([
99634
+ runActionScriptResultSchema,
99635
+ runActionTaskResultSchema,
99636
+ runActionSyncResultSchema
99637
+ ]);
100203
99638
  var runActionRoute = route({
100204
99639
  method: "post",
100205
99640
  path: "/api/apps/{id}/actions/{name}",
@@ -100210,7 +99645,7 @@ var runActionRoute = route({
100210
99645
  params: object({ id: string().min(1), name: AppNameSchema }),
100211
99646
  body: object({ input: record(string(), unknown()).optional() }),
100212
99647
  responses: {
100213
- 200: { description: "Action invoked" },
99648
+ 200: { description: "Action invoked", schema: runActionResultSchema },
100214
99649
  400: { description: "Invalid action input or stale script reference" },
100215
99650
  403: { description: "Permission denied" },
100216
99651
  409: { description: "App definition needs repair" },
@@ -100218,6 +99653,27 @@ var runActionRoute = route({
100218
99653
  },
100219
99654
  rbac: { permission: "app.use" }
100220
99655
  });
99656
+ var syncAppRoute = route({
99657
+ method: "post",
99658
+ path: "/api/apps/{id}/sync",
99659
+ pattern: ["api", "apps", null, "sync"],
99660
+ summary: "Sync an app's declared sources",
99661
+ description: "Runs every (model x source) pair the body selects. Each pass pulls outside the row mutation lock and reconciles inside it.",
99662
+ tags: ["Apps"],
99663
+ params: appParamsSchema,
99664
+ body: object({ model: AppNameSchema.optional(), source: AppNameSchema.optional() }),
99665
+ responses: {
99666
+ 200: {
99667
+ description: "Sync passes",
99668
+ schema: object({ ok: boolean(), passes: array(SyncPassResultSchema) })
99669
+ },
99670
+ 400: { description: "Unknown model or source, or no model declares a source" },
99671
+ 403: { description: "Permission denied" },
99672
+ 409: { description: "App definition needs repair" },
99673
+ 404: { description: "App not found" }
99674
+ },
99675
+ rbac: { permission: "app.use" }
99676
+ });
100221
99677
  function authorizeApp(req, res, myAgentId, verb, resource) {
100222
99678
  const auth = getRequestAuth(req);
100223
99679
  let principal;
@@ -100259,6 +99715,12 @@ function definitionNeedsRepair(res, app) {
100259
99715
  json(res, { error: "definition needs repair", issues: app.definitionError }, 409);
100260
99716
  return true;
100261
99717
  }
99718
+ function syncPassError(sync) {
99719
+ const failed = sync.passes.filter((pass) => pass.error !== undefined);
99720
+ if (failed.length === 0)
99721
+ return;
99722
+ return failed.map((pass) => `${pass.model}.${pass.source}: ${pass.error}`).join("; ");
99723
+ }
100262
99724
  function snapshotFailure(res) {
100263
99725
  jsonError(res, "failed to snapshot app", 500);
100264
99726
  }
@@ -100435,7 +99897,7 @@ function applyQuery(rows, query, model, params = {}, queryName = "<unnamed>") {
100435
99897
  const sort = query.sort;
100436
99898
  if (sort) {
100437
99899
  selected = [...selected].sort((a, b) => {
100438
- const result = compareValues(rowValue(a, sort.column), rowValue(b, sort.column), sort.dir, sort.column === "createdAt" || sort.column === "updatedAt" || Object.hasOwn(model.columns, sort.column) && model.columns[sort.column].kind === "date");
99900
+ const result = compareValues(rowValue(a, sort.column), rowValue(b, sort.column), sort.dir, SORTABLE_SYSTEM_DATE_COLUMNS.has(sort.column) || Object.hasOwn(model.columns, sort.column) && model.columns[sort.column].kind === "date");
100439
99901
  return result;
100440
99902
  });
100441
99903
  }
@@ -100456,23 +99918,24 @@ async function handleApps(req, res, pathSegments, queryParams, myAgentId) {
100456
99918
  }
100457
99919
  const definition = parseAppDefinition(parsed.body.definition, {
100458
99920
  resolveApp: getApp,
100459
- writerAgentId: myAgentId ?? null
99921
+ writerAgentId: myAgentId ?? null,
99922
+ writerIsUser: getRequestAuth(req)?.kind === "user"
100460
99923
  });
100461
99924
  if (!definition.success) {
100462
99925
  invalidDefinition(res, definition.issues);
100463
99926
  return true;
100464
99927
  }
100465
- json(res, {
99928
+ createAppRoute.respond(res, 201, {
100466
99929
  app: createApp({
100467
99930
  name: parsed.body.name,
100468
99931
  description: parsed.body.description,
100469
99932
  definition: definition.definition
100470
99933
  })
100471
- }, 201);
99934
+ });
100472
99935
  return true;
100473
99936
  }
100474
99937
  if (listAppsRoute.match(req.method, pathSegments)) {
100475
- json(res, { apps: listApps() });
99938
+ listAppsRoute.respond(res, 200, { apps: listApps() });
100476
99939
  return true;
100477
99940
  }
100478
99941
  if (listAppVersionsRoute.match(req.method, pathSegments)) {
@@ -100485,7 +99948,9 @@ async function handleApps(req, res, pathSegments, queryParams, myAgentId) {
100485
99948
  jsonError(res, "app not found", 404);
100486
99949
  return true;
100487
99950
  }
100488
- json(res, { versions: getAppVersions(parsed.params.id).map(decodeAppVersion) });
99951
+ listAppVersionsRoute.respond(res, 200, {
99952
+ versions: getAppVersions(parsed.params.id).map(decodeAppVersion)
99953
+ });
100489
99954
  return true;
100490
99955
  }
100491
99956
  if (getAppVersionRoute.match(req.method, pathSegments)) {
@@ -100503,7 +99968,7 @@ async function handleApps(req, res, pathSegments, queryParams, myAgentId) {
100503
99968
  jsonError(res, "app version not found", 404);
100504
99969
  return true;
100505
99970
  }
100506
- json(res, { version: decodeAppVersion(version) });
99971
+ getAppVersionRoute.respond(res, 200, { version: decodeAppVersion(version) });
100507
99972
  return true;
100508
99973
  }
100509
99974
  if (rollbackAppRoute.match(req.method, pathSegments)) {
@@ -100520,9 +99985,11 @@ async function handleApps(req, res, pathSegments, queryParams, myAgentId) {
100520
99985
  version: parsed.body.version,
100521
99986
  migration: parsed.body.migration,
100522
99987
  forceElementBreak: parsed.body.forceElementBreak,
100523
- changedByAgentId: myAgentId
99988
+ changedByAgentId: myAgentId,
99989
+ writerAgentId: myAgentId ?? null,
99990
+ writerIsUser: getRequestAuth(req)?.kind === "user"
100524
99991
  });
100525
- json(res, { app: rolledBack.app, migration: rolledBack.migration });
99992
+ rollbackAppRoute.respond(res, 200, { app: rolledBack.app, migration: rolledBack.migration });
100526
99993
  } catch (error) {
100527
99994
  if (error instanceof AppRollbackAppNotFoundError) {
100528
99995
  jsonError(res, "app not found", 404);
@@ -100554,7 +100021,7 @@ async function handleApps(req, res, pathSegments, queryParams, myAgentId) {
100554
100021
  return true;
100555
100022
  try {
100556
100023
  const rows = await createAppRows(parsed.params.id, parsed.params.model, resolved.model, parsed.body.rows.map((row) => row.values), { actor });
100557
- json(res, { rows });
100024
+ bulkCreateRowsRoute.respond(res, 200, { rows });
100558
100025
  } catch (error) {
100559
100026
  if (!invalidRows(res, error))
100560
100027
  throw error;
@@ -100575,7 +100042,7 @@ async function handleApps(req, res, pathSegments, queryParams, myAgentId) {
100575
100042
  return true;
100576
100043
  try {
100577
100044
  const row = await createAppRow(parsed.params.id, parsed.params.model, resolved.model, parsed.body.values, { actor });
100578
- json(res, { row }, 201);
100045
+ createRowRoute.respond(res, 201, { row });
100579
100046
  } catch (error) {
100580
100047
  if (!invalidRows(res, error))
100581
100048
  throw error;
@@ -100600,7 +100067,7 @@ async function handleApps(req, res, pathSegments, queryParams, myAgentId) {
100600
100067
  const sortRaw = parsed.query.sort;
100601
100068
  if (sortRaw) {
100602
100069
  const [column, dir, extra] = sortRaw.split(":");
100603
- if (extra !== undefined || !column || dir !== "asc" && dir !== "desc" || column !== "createdAt" && column !== "updatedAt" && (!Object.hasOwn(resolved.model.columns, column) || resolved.model.columns[column].hidden === true)) {
100070
+ if (extra !== undefined || !column || dir !== "asc" && dir !== "desc" || !SORTABLE_SYSTEM_DATE_COLUMNS.has(column) && (!Object.hasOwn(resolved.model.columns, column) || resolved.model.columns[column].hidden === true)) {
100604
100071
  json(res, {
100605
100072
  error: "invalid sort",
100606
100073
  issues: [{ path: "sort", message: "must be <column>:<asc|desc> for a known column" }]
@@ -100608,12 +100075,12 @@ async function handleApps(req, res, pathSegments, queryParams, myAgentId) {
100608
100075
  return true;
100609
100076
  }
100610
100077
  rows.sort((a, b) => {
100611
- const result = compareValues(rowValue(a, column), rowValue(b, column), dir, column === "createdAt" || column === "updatedAt" || Object.hasOwn(resolved.model.columns, column) && resolved.model.columns[column].kind === "date");
100078
+ const result = compareValues(rowValue(a, column), rowValue(b, column), dir, SORTABLE_SYSTEM_DATE_COLUMNS.has(column) || Object.hasOwn(resolved.model.columns, column) && resolved.model.columns[column].kind === "date");
100612
100079
  return result;
100613
100080
  });
100614
100081
  }
100615
100082
  const total = rows.length;
100616
- json(res, { rows: rows.slice(0, parsed.query.limit ?? 200), total });
100083
+ listRowsRoute.respond(res, 200, { rows: rows.slice(0, parsed.query.limit ?? 200), total });
100617
100084
  return true;
100618
100085
  }
100619
100086
  if (getRowRoute.match(req.method, pathSegments)) {
@@ -100629,7 +100096,7 @@ async function handleApps(req, res, pathSegments, queryParams, myAgentId) {
100629
100096
  jsonError(res, "row not found", 404);
100630
100097
  return true;
100631
100098
  }
100632
- json(res, { row });
100099
+ getRowRoute.respond(res, 200, { row });
100633
100100
  return true;
100634
100101
  }
100635
100102
  if (patchRowRoute.match(req.method, pathSegments)) {
@@ -100650,7 +100117,7 @@ async function handleApps(req, res, pathSegments, queryParams, myAgentId) {
100650
100117
  jsonError(res, "row not found", 404);
100651
100118
  return true;
100652
100119
  }
100653
- json(res, { row });
100120
+ patchRowRoute.respond(res, 200, { row });
100654
100121
  } catch (error) {
100655
100122
  if (!invalidRows(res, error))
100656
100123
  throw error;
@@ -100670,7 +100137,7 @@ async function handleApps(req, res, pathSegments, queryParams, myAgentId) {
100670
100137
  jsonError(res, "row not found", 404);
100671
100138
  return true;
100672
100139
  }
100673
- json(res, { ok: true });
100140
+ deleteRowRoute.respond(res, 200, { ok: true });
100674
100141
  return true;
100675
100142
  }
100676
100143
  if (runNamedQueryRoute.match(req.method, pathSegments)) {
@@ -100694,7 +100161,7 @@ async function handleApps(req, res, pathSegments, queryParams, myAgentId) {
100694
100161
  }
100695
100162
  const model = app.definition.models[query.model];
100696
100163
  try {
100697
- json(res, {
100164
+ runNamedQueryRoute.respond(res, 200, {
100698
100165
  rows: applyQuery(listAppRows(app.id, query.model), query, model, appQueryParamsFromRequest(queryParams), parsed.params.name)
100699
100166
  });
100700
100167
  } catch (error) {
@@ -100753,7 +100220,7 @@ async function handleApps(req, res, pathSegments, queryParams, myAgentId) {
100753
100220
  });
100754
100221
  const ok = output.exitCode === 0 && !output.error && !output.runtimeError;
100755
100222
  const error = ok ? undefined : output.runtimeError ? `${output.runtimeError.name}: ${output.runtimeError.message}` : output.error ?? `Script exited with code ${output.exitCode}`;
100756
- json(res, scrubObject({
100223
+ runActionRoute.respond(res, 200, scrubObject({
100757
100224
  ok,
100758
100225
  result: output.result,
100759
100226
  stdout: output.stdout,
@@ -100762,6 +100229,28 @@ async function handleApps(req, res, pathSegments, queryParams, myAgentId) {
100762
100229
  }));
100763
100230
  return true;
100764
100231
  }
100232
+ if (action.kind === "sync") {
100233
+ const startedAt = Date.now();
100234
+ const sync = await runAppSync({
100235
+ appId: app.id,
100236
+ ...action.model === undefined ? {} : { model: action.model },
100237
+ ...action.source === undefined ? {} : { source: action.source },
100238
+ invokedBy: actor
100239
+ });
100240
+ const durationMs = Date.now() - startedAt;
100241
+ if (sync.issues && sync.issues.length > 0) {
100242
+ json(res, { error: "invalid sync action", issues: sync.issues }, 400);
100243
+ return true;
100244
+ }
100245
+ const error = syncPassError(sync);
100246
+ runActionRoute.respond(res, 200, scrubObject({
100247
+ ok: sync.ok,
100248
+ result: { passes: sync.passes },
100249
+ ...error === undefined ? {} : { error },
100250
+ durationMs
100251
+ }));
100252
+ return true;
100253
+ }
100765
100254
  const lead = action.agentId ? null : getLeadAgent();
100766
100255
  const taskPrompt = resolveTemplate("task.app.action", {
100767
100256
  prompt: action.prompt,
@@ -100772,9 +100261,39 @@ async function handleApps(req, res, pathSegments, queryParams, myAgentId) {
100772
100261
  const task = createTaskWithSiblingAwareness(taskPrompt.text, {
100773
100262
  source: "api",
100774
100263
  agentId: action.agentId ?? lead?.id,
100264
+ key: normalizeAssetKey(`shared/app:${app.id}/action:${parsed.params.name}/`),
100775
100265
  ...actor.startsWith("user:") ? { requestedByUserId: actor.slice("user:".length) } : {}
100776
100266
  });
100777
- json(res, { ok: true, taskId: task.id, status: task.status });
100267
+ runActionRoute.respond(res, 200, { ok: true, taskId: task.id, status: task.status });
100268
+ return true;
100269
+ }
100270
+ if (syncAppRoute.match(req.method, pathSegments)) {
100271
+ if (enforceContentLengthCap(req, res, MAX_APP_ROW_BODY_BYTES) === BODY_TOO_LARGE)
100272
+ return true;
100273
+ const parsed = await syncAppRoute.parse(req, res, pathSegments, queryParams);
100274
+ if (!parsed)
100275
+ return true;
100276
+ const actor = authorizeAppUse(req, res, myAgentId, parsed.params.id);
100277
+ if (!actor)
100278
+ return true;
100279
+ const app = getApp(parsed.params.id);
100280
+ if (!app) {
100281
+ jsonError(res, "app not found", 404);
100282
+ return true;
100283
+ }
100284
+ if (definitionNeedsRepair(res, app))
100285
+ return true;
100286
+ const sync = await runAppSync({
100287
+ appId: app.id,
100288
+ ...parsed.body.model === undefined ? {} : { model: parsed.body.model },
100289
+ ...parsed.body.source === undefined ? {} : { source: parsed.body.source },
100290
+ invokedBy: actor
100291
+ });
100292
+ if (sync.issues && sync.issues.length > 0) {
100293
+ json(res, { error: "nothing to sync", issues: sync.issues }, 400);
100294
+ return true;
100295
+ }
100296
+ syncAppRoute.respond(res, 200, scrubObject({ ok: sync.ok, passes: sync.passes }));
100778
100297
  return true;
100779
100298
  }
100780
100299
  if (patchAppRoute.match(req.method, pathSegments)) {
@@ -100814,6 +100333,7 @@ async function handleApps(req, res, pathSegments, queryParams, myAgentId) {
100814
100333
  currentAppId: parsed.params.id,
100815
100334
  resolveApp: getApp,
100816
100335
  writerAgentId: myAgentId ?? null,
100336
+ writerIsUser: getRequestAuth(req)?.kind === "user",
100817
100337
  existingDefinition: existing.definition
100818
100338
  });
100819
100339
  if (!definition.success) {
@@ -100861,7 +100381,7 @@ async function handleApps(req, res, pathSegments, queryParams, myAgentId) {
100861
100381
  jsonError(res, "app not found", 404);
100862
100382
  return true;
100863
100383
  }
100864
- json(res, { app, migration });
100384
+ patchAppRoute.respond(res, 200, { app, migration });
100865
100385
  return true;
100866
100386
  }
100867
100387
  if (updateAppRoute.match(req.method, pathSegments)) {
@@ -100893,6 +100413,7 @@ async function handleApps(req, res, pathSegments, queryParams, myAgentId) {
100893
100413
  currentAppId: parsed.params.id,
100894
100414
  resolveApp: getApp,
100895
100415
  writerAgentId: myAgentId ?? null,
100416
+ writerIsUser: getRequestAuth(req)?.kind === "user",
100896
100417
  existingDefinition: existing.definition
100897
100418
  });
100898
100419
  if (!parsedDefinition.success) {
@@ -100946,7 +100467,7 @@ async function handleApps(req, res, pathSegments, queryParams, myAgentId) {
100946
100467
  jsonError(res, "app not found", 404);
100947
100468
  return true;
100948
100469
  }
100949
- json(res, { app, migration });
100470
+ updateAppRoute.respond(res, 200, { app, migration });
100950
100471
  return true;
100951
100472
  }
100952
100473
  if (deleteAppRoute.match(req.method, pathSegments)) {
@@ -100969,7 +100490,7 @@ async function handleApps(req, res, pathSegments, queryParams, myAgentId) {
100969
100490
  jsonError(res, "app not found", 404);
100970
100491
  return true;
100971
100492
  }
100972
- json(res, { ok: true });
100493
+ deleteAppRoute.respond(res, 200, { ok: true });
100973
100494
  return true;
100974
100495
  }
100975
100496
  if (getAppRoute.match(req.method, pathSegments)) {
@@ -100983,7 +100504,11 @@ async function handleApps(req, res, pathSegments, queryParams, myAgentId) {
100983
100504
  jsonError(res, "app not found", 404);
100984
100505
  return true;
100985
100506
  }
100986
- json(res, { app });
100507
+ const syncStatus = collectAppSyncStatus(app.id);
100508
+ getAppRoute.respond(res, 200, {
100509
+ app,
100510
+ ...Object.keys(syncStatus).length > 0 ? { syncStatus } : {}
100511
+ });
100987
100512
  return true;
100988
100513
  }
100989
100514
  if (getUserConfigRoute.match(req.method, pathSegments)) {
@@ -101002,7 +100527,7 @@ async function handleApps(req, res, pathSegments, queryParams, myAgentId) {
101002
100527
  const schema = app.definition.userConfig ?? {};
101003
100528
  const owner = resolveHttpFavoriteOwner(req, myAgentId);
101004
100529
  const stored = owner ? getAppUserConfigValues(app.id, owner.scope) : {};
101005
- json(res, { values: mergeUserConfigValues(schema, stored), schema });
100530
+ getUserConfigRoute.respond(res, 200, { values: mergeUserConfigValues(schema, stored), schema });
101006
100531
  return true;
101007
100532
  }
101008
100533
  if (putUserConfigRoute.match(req.method, pathSegments)) {
@@ -101042,7 +100567,10 @@ async function handleApps(req, res, pathSegments, queryParams, myAgentId) {
101042
100567
  return true;
101043
100568
  }
101044
100569
  upsertAppUserConfigValues(app.id, owner.scope, parsed.body.values);
101045
- json(res, { values: mergeUserConfigValues(schema, parsed.body.values), schema });
100570
+ putUserConfigRoute.respond(res, 200, {
100571
+ values: mergeUserConfigValues(schema, parsed.body.values),
100572
+ schema
100573
+ });
101046
100574
  return true;
101047
100575
  }
101048
100576
  return false;
@@ -101090,9 +100618,15 @@ var registerAppGetTool = (server) => {
101090
100618
  const app = getApp(appId2);
101091
100619
  if (!app)
101092
100620
  return toolErr(`App ${appId2} not found.`);
100621
+ const syncStatus = collectAppSyncStatus(app.id);
100622
+ const hasSyncStatus = Object.keys(syncStatus).length > 0;
100623
+ const details = hasSyncStatus ? `${JSON.stringify(app, null, 2)}
100624
+
100625
+ Sync status (model:source):
100626
+ ${JSON.stringify(syncStatus, null, 2)}` : JSON.stringify(app, null, 2);
101093
100627
  return toolOk(`App "${app.name}" (${app.id}).`, {
101094
- details: JSON.stringify(app, null, 2),
101095
- data: { app }
100628
+ details,
100629
+ data: { app, ...hasSyncStatus ? { syncStatus } : {} }
101096
100630
  });
101097
100631
  });
101098
100632
  };
@@ -101415,7 +100949,8 @@ var registerAppRollbackTool = (server) => {
101415
100949
  version,
101416
100950
  migration,
101417
100951
  forceElementBreak,
101418
- changedByAgentId: requestInfo.agentId
100952
+ changedByAgentId: requestInfo.agentId,
100953
+ writerAgentId: requestInfo.agentId
101419
100954
  });
101420
100955
  const url = `/apps/${rolledBack.app.id}`;
101421
100956
  return toolOk(`App "${rolledBack.app.name}" rolled back to v${version}.`, {
@@ -101453,6 +100988,92 @@ var registerAppRollbackTool = (server) => {
101453
100988
  });
101454
100989
  };
101455
100990
 
100991
+ // src/tools/app-sync.ts
100992
+ init_zod();
100993
+ init_db();
100994
+ function cell(value) {
100995
+ return String(value ?? "—").replaceAll("\\", "\\\\").replaceAll("|", "\\|").replace(/\r\n|\r|\n/g, "<br>");
100996
+ }
100997
+ function renderPasses(passes) {
100998
+ if (passes.length === 0)
100999
+ return "No sync passes ran.";
101000
+ const header = "| model | source | created | updated | refreshed | stale | error |";
101001
+ const separator = "| --- | --- | --- | --- | --- | --- | --- |";
101002
+ const body = passes.map((pass) => [
101003
+ cell(pass.model),
101004
+ cell(pass.source),
101005
+ cell(pass.created),
101006
+ cell(pass.updated),
101007
+ cell(pass.refreshed),
101008
+ cell(pass.markedStale),
101009
+ cell(pass.error ?? (pass.skipped ? "skipped: already running" : undefined))
101010
+ ].map((value) => ` ${value} `).join("|"));
101011
+ const warnings = passes.flatMap((pass) => pass.warnings.map((warning) => `- ${pass.model}.${pass.source}: ${warning}`));
101012
+ return [header, separator, ...body.map((row) => `|${row}|`), ...warnings].join(`
101013
+ `);
101014
+ }
101015
+ var registerAppSyncTool = (server) => {
101016
+ createToolRegistrar(server)("app-sync", {
101017
+ title: "Sync an app's sources",
101018
+ description: "Refresh an app's declared sources: pull each selected (model x source) pair and reconcile its rows.",
101019
+ annotations: { destructiveHint: false },
101020
+ rbac: { permission: "app.use" },
101021
+ inputSchema: object({
101022
+ appId: string().min(1).describe("App ID whose sources should sync."),
101023
+ model: AppNameSchema.optional().describe("Limit the sync to one model."),
101024
+ source: AppNameSchema.optional().describe("Limit the sync to one declared source name.")
101025
+ }),
101026
+ outputSchema: swarmToolOutputSchema({
101027
+ passes: array(looseObject({})).optional(),
101028
+ ok: boolean().optional()
101029
+ })
101030
+ }, async ({ appId: appId2, model, source }, requestInfo) => {
101031
+ if (!requestInfo.agentId)
101032
+ return toolErr('Agent ID not found. Set the "X-Agent-ID" header.');
101033
+ const agent = getAgentById(requestInfo.agentId);
101034
+ const decision = can({
101035
+ principal: { kind: "agent", agentId: requestInfo.agentId, isLead: agent?.isLead ?? false },
101036
+ verb: "app.use",
101037
+ resource: { kind: "app", appId: appId2 },
101038
+ source: "mcp"
101039
+ });
101040
+ if (!decision.allow)
101041
+ return toolErr(decision.reason);
101042
+ const app = getApp(appId2);
101043
+ if (!app)
101044
+ return toolErr(`App ${appId2} not found.`);
101045
+ const result = await runAppSync({
101046
+ appId: appId2,
101047
+ ...model === undefined ? {} : { model },
101048
+ ...source === undefined ? {} : { source },
101049
+ invokedBy: `agent:${requestInfo.agentId}`
101050
+ });
101051
+ if (result.issues && result.issues.length > 0) {
101052
+ return toolErr(`Cannot sync app "${app.name}" (${app.id}).`, {
101053
+ details: result.issues.map((issue) => `${issue.path}: ${issue.message}`).join(`
101054
+ `),
101055
+ data: { ok: false }
101056
+ });
101057
+ }
101058
+ const totals = result.passes.reduce((sum, pass) => ({
101059
+ created: sum.created + pass.created,
101060
+ updated: sum.updated + pass.updated,
101061
+ refreshed: sum.refreshed + pass.refreshed,
101062
+ markedStale: sum.markedStale + pass.markedStale
101063
+ }), { created: 0, updated: 0, refreshed: 0, markedStale: 0 });
101064
+ const summary = `${result.passes.length} pass(es): ${totals.created} created, ${totals.updated} updated, ` + `${totals.refreshed} refreshed, ${totals.markedStale} marked stale.`;
101065
+ const details = renderPasses(result.passes);
101066
+ const data = { ok: result.ok, passes: result.passes };
101067
+ if (!result.ok) {
101068
+ return toolErr(`Sync failed for app "${app.name}" (${app.id}) — ${summary}`, {
101069
+ details,
101070
+ data
101071
+ });
101072
+ }
101073
+ return toolOk(`Synced app "${app.name}" (${app.id}) — ${summary}`, { details, data });
101074
+ });
101075
+ };
101076
+
101456
101077
  // src/tools/app-upsert.ts
101457
101078
  init_zod();
101458
101079
  init_db();
@@ -102122,7 +101743,7 @@ function snapshotMetric(metricId, changedByAgentId) {
102122
101743
  // src/tools/create-metric.ts
102123
101744
  init_types();
102124
101745
  init_constants();
102125
- function slugify(input) {
101746
+ function slugify2(input) {
102126
101747
  const slug = input.toLowerCase().normalize("NFKD").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
102127
101748
  return slug || "metric";
102128
101749
  }
@@ -102165,7 +101786,7 @@ var registerCreateMetricTool = (server) => {
102165
101786
  data: { yourAgentId: requestInfo.agentId, id: "" }
102166
101787
  });
102167
101788
  }
102168
- const slug = input.slug ?? slugify(input.title);
101789
+ const slug = input.slug ?? slugify2(input.title);
102169
101790
  const existing = getMetricBySlug(requestInfo.agentId, slug);
102170
101791
  let id;
102171
101792
  if (existing) {
@@ -102279,7 +101900,7 @@ function snapshotPage(pageId, changedByAgentId) {
102279
101900
  // src/tools/create-page.ts
102280
101901
  init_types();
102281
101902
  init_constants();
102282
- function slugify2(input) {
101903
+ function slugify3(input) {
102283
101904
  const slug = input.toLowerCase().normalize("NFKD").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
102284
101905
  return slug;
102285
101906
  }
@@ -102322,7 +101943,7 @@ var registerCreatePageTool = (server) => {
102322
101943
  const msg = "Agent ID required. Set the X-Agent-ID header on the MCP request.";
102323
101944
  return toolErr(msg);
102324
101945
  }
102325
- const slug = input.slug ?? slugify2(input.title);
101946
+ const slug = input.slug ?? slugify3(input.title);
102326
101947
  const finalSlug = slug || "page";
102327
101948
  let passwordHash;
102328
101949
  if (input.password) {
@@ -103263,8 +102884,8 @@ var getTasksOutputSchema = swarmToolOutputSchema({
103263
102884
  var TASK_DETAILS_CELL_CAP = 180;
103264
102885
  function escapeMarkdownCell(value) {
103265
102886
  const text = String(value ?? "—");
103266
- const compact2 = text.length > TASK_DETAILS_CELL_CAP ? `${text.slice(0, TASK_DETAILS_CELL_CAP - 1)}…` : text;
103267
- return compact2.replaceAll("\\", "\\\\").replaceAll("|", "\\|").replace(/\r\n|\r|\n/g, "<br>");
102887
+ const compact = text.length > TASK_DETAILS_CELL_CAP ? `${text.slice(0, TASK_DETAILS_CELL_CAP - 1)}…` : text;
102888
+ return compact.replaceAll("\\", "\\\\").replaceAll("|", "\\|").replace(/\r\n|\r|\n/g, "<br>");
103268
102889
  }
103269
102890
  function renderTaskSummaries(tasks) {
103270
102891
  if (tasks.length === 0)
@@ -108194,6 +107815,14 @@ function isRecord(value) {
108194
107815
  function apiBaseUrl() {
108195
107816
  return getMcpBaseUrl();
108196
107817
  }
107818
+ function renderIssue(issue) {
107819
+ if (typeof issue === "string")
107820
+ return issue;
107821
+ if (isRecord(issue) && typeof issue.message === "string") {
107822
+ return typeof issue.path === "string" ? `${issue.path}: ${issue.message}` : issue.message;
107823
+ }
107824
+ return JSON.stringify(issue);
107825
+ }
108197
107826
  function describeScriptFailure(resOk, status, data) {
108198
107827
  const body = isRecord(data) ? data : undefined;
108199
107828
  if (!resOk) {
@@ -108215,6 +107844,14 @@ function describeScriptFailure(resOk, status, data) {
108215
107844
  return {
108216
107845
  message: `${error ?? `Scripts API request failed with ${status}`} — ${violations.length} violation(s)`,
108217
107846
  details: capDetails(violations.map((v) => typeof v === "string" ? v : JSON.stringify(v)).join(`
107847
+ `))
107848
+ };
107849
+ }
107850
+ const issues = body && Array.isArray(body.issues) ? body.issues : undefined;
107851
+ if (issues && issues.length > 0) {
107852
+ return {
107853
+ message: `${error ?? `Scripts API request failed with ${status}`} — ${issues.length} issue(s)`,
107854
+ details: capDetails(issues.map(renderIssue).join(`
108218
107855
  `))
108219
107856
  };
108220
107857
  }
@@ -113594,7 +113231,7 @@ var registerCreateWorkflowTool = (server) => {
113594
113231
  annotations: { destructiveHint: false },
113595
113232
  description: `Create a new automation workflow. Key concepts:
113596
113233
  ` + `- Nodes are linked via 'next' (string or port-based record).
113597
- ` + "- CROSS-NODE DATA: To use output from an upstream node, you MUST declare an 'inputs' mapping on the downstream node. " + 'Example: inputs: { "cityData": "generate-city" } → then use {{cityData.taskOutput.field}} in config templates. ' + `Without 'inputs', only 'trigger' and workflow-level 'input' are available for interpolation.
113234
+ ` + "- CROSS-NODE DATA: To use output from an upstream node, you MUST declare an 'inputs' mapping on the downstream node. " + 'Example: inputs: { "cityData": "generate-city" } → then use {{cityData.taskOutput.field}} in config templates. ' + "Without 'inputs', built-in trigger/input/workflow/swarm/run context remains available, but upstream outputs do not. " + "Agent-task templates may interpolate trigger and declared upstream aliases. SECURITY: executable source for script/swarm-script nodes does not: " + "inline script source allows only input/workflow/swarm/run values, while named swarm-script source is not workflow-interpolated. " + `Pass dynamic trigger or upstream values through config.args (argv for inline scripts; the args object for swarm-script).
113598
113235
  ` + "- STRUCTURED OUTPUT: For agent-task nodes, put outputSchema inside 'config' to validate the agent's raw JSON output. " + `Node-level outputSchema validates the executor's return ({taskId, taskOutput}), which is different.
113599
113236
  ` + `- Agent-task config: { template, outputSchema?, agentId?, tags?, priority?, dir?, vcsRepo?, model? }.
113600
113237
  ` + "- FOREACH NODE: type 'foreach' fans out one agent-task per item. Config: " + "{ over: <array or exact {{input}} token>, itemKey: <property name>, body: { type: 'agent-task', config: {...} } }. " + "The body config is interpolated once per item with {{item.*}} and {{index}}. Child steps use synthetic IDs " + "'<foreachNodeId>#<itemKey>'; the parent waits for every child and exposes one aggregate result to successors. " + `concurrency is not supported in v1; use definition-level onNodeFailure: 'continue' to aggregate failed children.
@@ -114240,6 +113877,30 @@ function resolveScriptsOnlyMode(opts) {
114240
113877
  }
114241
113878
 
114242
113879
  // src/server.ts
113880
+ var ALL_CAPABILITIES = [
113881
+ "core",
113882
+ "task-pool",
113883
+ "scripts",
113884
+ "config",
113885
+ "prompt-templates",
113886
+ "mcp",
113887
+ "profiles",
113888
+ "services",
113889
+ "scheduling",
113890
+ "memory",
113891
+ "workflows",
113892
+ "pages",
113893
+ "metrics",
113894
+ "kv",
113895
+ "slack",
113896
+ "tracker",
113897
+ "skills",
113898
+ "messaging",
113899
+ "repo",
113900
+ "agentmail",
113901
+ "kapso",
113902
+ "swarm-x"
113903
+ ];
114243
113904
  var DEFAULT_CAPABILITIES = [
114244
113905
  "core",
114245
113906
  "task-pool",
@@ -114418,6 +114079,7 @@ function createServer(opts = {}) {
114418
114079
  registerAppPatchTool(server);
114419
114080
  registerAppQueryTool(server);
114420
114081
  registerAppRollbackTool(server);
114082
+ registerAppSyncTool(server);
114421
114083
  registerAppUpsertTool(server);
114422
114084
  registerCreatePageTool(server);
114423
114085
  registerDeletePageTool(server);
@@ -114617,4 +114279,4 @@ function writeSkillsToFilesystem(entries, harnessType = "all", home) {
114617
114279
  return { synced, removed, errors };
114618
114280
  }
114619
114281
 
114620
- export { DEFAULT_NEGOTIATED_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS, isJSONRPCRequest, isJSONRPCResultResponse, isJSONRPCErrorResponse, JSONRPCMessageSchema, isInitializeRequest, McpServer, isGitHubEnabled, initGitHub, verifyWebhookSignature, isAgentMailEnabled, initAgentMail, verifyAgentMailWebhook, isInboxAllowed, isSenderAllowed, handleMessageReceived, enqueueAuditRow, enqueueAdmissionRow, flushAuditBuffer, startAuditWriter, stopAuditWriter, startAuditGc, stopAuditGc, handlePullRequest, handleIssue, handleComment, handlePullRequestReview, handleCheckRun, handleCheckSuite, handleWorkflowRun, isGitLabEnabled, initGitLab, verifyGitLabWebhook, handleMergeRequest, handleIssue2 as handleIssue1, handleNote, handlePipeline, getJiraMetadata, updateJiraMetadata, clearJiraMetadata, registerJiraWebhook, deleteJiraWebhook, isJiraEnabled, initJira, handleJiraWebhook, handleAgentSessionEvent, handleIssueUpdate, handleIssueDelete, handleAgentSessionPrompted, isLinearEnabled, initLinear, setCorsHeaders, parseQueryParams, getPathSegments, safeRequestUrlForLog, agentWithCapacity, parseBody, BODY_TOO_LARGE, enforceContentLengthCap, json, jsonError, triggerSchemaErrorResponse, deriveApiBaseUrl, httpServerSemconvAttributes, describeRequestRoute, route, loadGlobalConfigsIntoEnv, reloadGlobalConfigsAndIntegrations, scheduleIntegrationsReload, handleCore, mcpOverflowAuthError, isPollTracingEnabled, initOtel, withSpan, startSpan, withSpanContext, withRemoteContext, injectTraceContext, recordSessionCost, markScriptSdkRequestOrigin, toolErr, createToolRegistrar, userCtx, resolveTaskAuditUserId, resolveHttpAuditUserId, resolveHttpFavoriteOwner, handleApps, getTaskDetailsInputSchema, getTaskDetailsOutputSchema, getTaskDetailsHandler, cancelTaskInputSchema, cancelTaskOutputSchema, cancelTaskHandler, assertSelectOnlyQuery, executeReadOnlyQuery, handleDbQuery, snapshotMetric, AssetKeyAuthorizationError, authorizeAssetKeyWrite, snapshotPage, assertOAuthAppUrlsSafe, assertOAuthEgressUrlSafe, listOAuthPresets, listOAuthPresetIds, getOAuthPreset, hydrateOAuthAppFromPreset, scopedResourceScopeIdSchema, resolveScopedResourceId, getTasksInputSchema, getTasksOutputSchema, getTasksHandler, reservedNamespaceError, storeLinks, refreshLinks, canReadMemory, getLinksForMemory, recordRetrievals, expandCandidatesWithGraph, markKapsoMessageRead, sendKapsoReaction, getKapsoConfig, getKapsoNumberMapping, markKapsoMessageSeen, createEvent, createEventsBatch, getEventCountsFiltered, getEventsFiltered, mergeScheduleTiming, validateRecurringTiming, sendTaskOutputSchema, sendTaskHandler, parseSkillContent, steerTaskUserInputSchema, steerTaskOutputSchema, steerTaskHandler, ExplicitSelfDuplicateError, applyRating, shouldPersistAutomaticTaskMemory, guardTerminalTaskResultWrite, canClaim, emitBudgetRefusalSideEffects, taskActionInputSchema, taskActionOutputSchema, taskActionHandler, resolveScriptsOnlyMode, hasCapability, getEnabledCapabilities, createServer, writeSkillsToFilesystem };
114282
+ export { DEFAULT_NEGOTIATED_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS, isJSONRPCRequest, isJSONRPCResultResponse, isJSONRPCErrorResponse, JSONRPCMessageSchema, isInitializeRequest, McpServer, isGitHubEnabled, initGitHub, verifyWebhookSignature, isAgentMailEnabled, initAgentMail, verifyAgentMailWebhook, isInboxAllowed, isSenderAllowed, handleMessageReceived, enqueueAuditRow, enqueueAdmissionRow, flushAuditBuffer, startAuditWriter, stopAuditWriter, startAuditGc, stopAuditGc, handlePullRequest, handleIssue, handleComment, handlePullRequestReview, handleCheckRun, handleCheckSuite, handleWorkflowRun, isGitLabEnabled, initGitLab, verifyGitLabWebhook, handleMergeRequest, handleIssue2 as handleIssue1, handleNote, handlePipeline, getJiraMetadata, updateJiraMetadata, clearJiraMetadata, registerJiraWebhook, deleteJiraWebhook, isJiraEnabled, initJira, handleJiraWebhook, handleAgentSessionEvent, handleIssueUpdate, handleIssueDelete, handleAgentSessionPrompted, isLinearEnabled, initLinear, setCorsHeaders, parseQueryParams, getPathSegments, safeRequestUrlForLog, agentWithCapacity, parseBody, BODY_TOO_LARGE, enforceContentLengthCap, json, jsonError, triggerSchemaErrorResponse, deriveApiBaseUrl, httpServerSemconvAttributes, describeRequestRoute, route, loadGlobalConfigsIntoEnv, reloadGlobalConfigsAndIntegrations, scheduleIntegrationsReload, handleCore, mcpOverflowAuthError, isPollTracingEnabled, initOtel, withSpan, startSpan, withSpanContext, withRemoteContext, injectTraceContext, recordSessionCost, markScriptSdkRequestOrigin, toolErr, createToolRegistrar, userCtx, resolveTaskAuditUserId, resolveHttpAuditUserId, resolveHttpFavoriteOwner, handleApps, getTaskDetailsInputSchema, getTaskDetailsOutputSchema, getTaskDetailsHandler, cancelTaskInputSchema, cancelTaskOutputSchema, cancelTaskHandler, assertSelectOnlyQuery, executeReadOnlyQuery, handleDbQuery, snapshotMetric, AssetKeyAuthorizationError, authorizeAssetKeyWrite, snapshotPage, assertOAuthAppUrlsSafe, assertOAuthEgressUrlSafe, listOAuthPresets, listOAuthPresetIds, getOAuthPreset, hydrateOAuthAppFromPreset, scopedResourceScopeIdSchema, resolveScopedResourceId, getTasksInputSchema, getTasksOutputSchema, getTasksHandler, reservedNamespaceError, storeLinks, refreshLinks, canReadMemory, getLinksForMemory, recordRetrievals, expandCandidatesWithGraph, markKapsoMessageRead, sendKapsoReaction, getKapsoConfig, getKapsoNumberMapping, markKapsoMessageSeen, createEvent, createEventsBatch, getEventCountsFiltered, getEventsFiltered, mergeScheduleTiming, validateRecurringTiming, sendTaskOutputSchema, sendTaskHandler, parseSkillContent, steerTaskUserInputSchema, steerTaskOutputSchema, steerTaskHandler, ExplicitSelfDuplicateError, applyRating, shouldPersistAutomaticTaskMemory, guardTerminalTaskResultWrite, canClaim, emitBudgetRefusalSideEffects, taskActionInputSchema, taskActionOutputSchema, taskActionHandler, resolveScriptsOnlyMode, ALL_CAPABILITIES, hasCapability, getEnabledCapabilities, createServer, writeSkillsToFilesystem };