@desplega.ai/agent-swarm 1.130.0 → 1.131.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/{actions-73ee723n.js → actions-jgcy477k.js} +7 -7
- package/dist/{anthropic-messages-3xgme8my.js → anthropic-messages-rjmd2e7n.js} +5 -5
- package/dist/{app-hz5c2xay.js → app-5da78bd4.js} +4 -4
- package/dist/{assistant-08mr16yp.js → assistant-f2vkk1hj.js} +9 -9
- package/dist/{azure-openai-responses-xa4sh9f6.js → azure-openai-responses-c0yjmbfd.js} +8 -5
- package/dist/{boot-reembed-5bgan3cd.js → boot-reembed-q7mp8hcr.js} +4 -4
- package/dist/{boot-reembed-z7ykyeq8.js → boot-reembed-xmw8wcx6.js} +5 -5
- package/dist/{boot-scrub-logs-b2rjk8mv.js → boot-scrub-logs-dsqrv79n.js} +3 -3
- package/dist/{claude-adapter-qr0k17km.js → claude-adapter-q6x7yspx.js} +6 -6
- package/dist/{claude-managed-adapter-gv19tdew.js → claude-managed-adapter-wsg37bt8.js} +1 -1
- package/dist/{cli-vr2f46zj.js → cli-114fvtmj.js} +1 -1
- package/dist/{cli-mhr8tq3v.js → cli-2f07m0xr.js} +1 -1
- package/dist/{cli-mgerp0vs.js → cli-2rk0cx7s.js} +2 -2
- package/dist/{cli-tfw3c0y1.js → cli-3ty0t082.js} +2 -2
- package/dist/{cli-fs153s3x.js → cli-4rkfg1wx.js} +3 -3
- package/dist/{cli-s18zzkfp.js → cli-50vbt00w.js} +44 -7
- package/dist/{cli-vgexpfsr.js → cli-57khth04.js} +6 -3
- package/dist/{cli-n9yxcnvk.js → cli-5n6e5yfn.js} +29 -7
- package/dist/{cli-q8zwffx0.js → cli-6dp3ydxa.js} +158 -39
- package/dist/{cli-r62me33w.js → cli-6dpytdr2.js} +2 -2
- package/dist/{cli-ch7t5v7n.js → cli-6map995v.js} +9 -4
- package/dist/{cli-326083vb.js → cli-6pcz9h15.js} +14 -14
- package/dist/{cli-h3e66g5b.js → cli-793jvbsh.js} +1 -1
- package/dist/{cli-yj7z99vp.js → cli-7dm2zqy2.js} +2 -2
- package/dist/{cli-t5tsq67k.js → cli-9dr5qzc0.js} +39 -4
- package/dist/{cli-m8fs5ttq.js → cli-aca5pz9f.js} +1 -1
- package/dist/{cli-w10fkrf1.js → cli-akdvwc9v.js} +354 -115
- package/dist/{cli-hntzdchd.js → cli-bqw0mt1n.js} +1 -1
- package/dist/{cli-7v5dhmc8.js → cli-ccf9vy7q.js} +6 -6
- package/dist/{cli-6nh2qxvh.js → cli-darcwax3.js} +1 -1
- package/dist/{cli-xg2eezyv.js → cli-f1am9szv.js} +1 -1
- package/dist/{cli-1px8pn1s.js → cli-g1re8r05.js} +2 -2
- package/dist/{cli-z9q7pb38.js → cli-g74vpjp2.js} +4 -4
- package/dist/{cli-brebbsen.js → cli-gecy3z2s.js} +20 -8
- package/dist/{cli-epsvdckx.js → cli-gm9cbhbq.js} +20 -10
- package/dist/{cli-xdrmxvd4.js → cli-jbcva0xj.js} +55 -11
- package/dist/{cli-haanc4qd.js → cli-jevgrb4w.js} +22 -22
- package/dist/{cli-e5p3es48.js → cli-kd1ck4rx.js} +1 -1
- package/dist/{cli-1mj7yz1r.js → cli-nrkkknat.js} +1 -1
- package/dist/{cli-2pa5w9b6.js → cli-pxfxkx5m.js} +1 -1
- package/dist/{cli-qcsjdppx.js → cli-rgrfzg8z.js} +7 -7
- package/dist/{cli-mf009e0j.js → cli-se2p6rkb.js} +1 -1
- package/dist/{cli-tp519bjz.js → cli-sy7jk3tx.js} +2 -2
- package/dist/{cli-qbb2ten8.js → cli-t8d349cy.js} +2 -2
- package/dist/{cli-s21zzx4b.js → cli-w2wxd56v.js} +448 -184
- package/dist/{cli-qmdnhpej.js → cli-wz9115x0.js} +17 -7
- package/dist/{cli-4n4mdv21.js → cli-xpxde7rm.js} +7 -3
- package/dist/{cli-dakxgk70.js → cli-ycrnynpw.js} +4 -4
- package/dist/{cli-73bvdyxr.js → cli-ygrbmjja.js} +6 -6
- package/dist/cli.js +22 -22
- package/dist/{codex-adapter-6pc50x9q.js → codex-adapter-htjkn22b.js} +4 -4
- package/dist/{codex-hook-amndawyb.js → codex-hook-hq54t9ft.js} +2 -2
- package/dist/{codex-session-runner-tpg8hyj7.js → codex-session-runner-wjfc7smz.js} +4 -4
- package/dist/{commands-yfpwt11g.js → commands-xhrfwqsk.js} +3 -3
- package/dist/{db-jn499nmp.js → db-anvwb22f.js} +3 -3
- package/dist/{google-generative-ai-txgg2q58.js → google-generative-ai-hysrd8qx.js} +7 -5
- package/dist/{google-vertex-t663s1c3.js → google-vertex-p5arrga0.js} +7 -5
- package/dist/{handlers-eev4nng0.js → handlers-b9kbc621.js} +9 -9
- package/dist/{hook-9fkwkf3m.js → hook-cgk4wxmx.js} +5 -5
- package/dist/{hook-sn7pj75w.js → hook-xkvn6c5h.js} +4 -4
- package/dist/{http-xdbbtmhx.js → http-9xh6ta4r.js} +324 -82
- package/dist/{index-9vnkprkh.js → index-25wjsdv2.js} +10 -10
- package/dist/{index-5fdsemf0.js → index-eaxyqcmj.js} +155 -37
- package/dist/{index-fnack5vh.js → index-vg4snay4.js} +11 -11
- package/dist/{index-c0qedjh6.js → index-ywds4812.js} +9 -9
- package/dist/{keepalive-fc7a2hw9.js → keepalive-vc7s2aa6.js} +5 -5
- package/dist/{lead-1fva34y9.js → lead-r2yqfmx7.js} +29 -29
- package/dist/{maintenance-0rdb12vf.js → maintenance-mw70k468.js} +5 -5
- package/dist/{mistral-conversations-4swenhmf.js → mistral-conversations-81fwav0j.js} +2 -2
- package/dist/{oauth-refresh-sweep-f9rptqbt.js → oauth-refresh-sweep-yecgjpk4.js} +4 -4
- package/dist/{onboard-9zn0fx2m.js → onboard-xj0f73f9.js} +2 -2
- package/dist/{openai-codex-responses-xetseqvt.js → openai-codex-responses-5g27pd6f.js} +43 -23
- package/dist/{openai-completions-5r2g5axa.js → openai-completions-3vkmfz2a.js} +55 -11
- package/dist/{openai-responses-ce67hd23.js → openai-responses-dg4t7j7a.js} +8 -5
- package/dist/{openrouter-images-pzfp22jb.js → openrouter-images-g3gm8931.js} +1 -1
- package/dist/{otel-impl-thnttmbn.js → otel-impl-nxg0n0b3.js} +1 -1
- package/dist/{pi-mono-adapter-bpfrn6d7.js → pi-mono-adapter-4g5kby31.js} +17114 -7514
- package/dist/{pricing-refresh-n0ve0kh6.js → pricing-refresh-2cn6effr.js} +5 -5
- package/dist/{rbac-roles-w45bhahg.js → rbac-roles-1hcxdtg7.js} +4 -4
- package/dist/{rbac-roles-bbwb4wrm.js → rbac-roles-vynday5g.js} +5 -5
- package/dist/{render-v2-d675cp9r.js → render-v2-tc0bh8kk.js} +4 -4
- package/dist/{seed-pricing-47q77nw4.js → seed-pricing-8kceb43f.js} +4 -4
- package/dist/{setup-3vnv2m43.js → setup-46xtgq3c.js} +2 -2
- package/dist/{worker-7shsr8hk.js → worker-qrbz6hmv.js} +29 -29
- package/openapi.json +342 -10
- package/package.json +6 -6
- package/src/apps/store.ts +13 -4
- package/src/assets/key.ts +8 -1
- package/src/be/asset-key-audit.ts +3 -1
- package/src/be/db-queries/mcp-oauth.ts +26 -0
- package/src/be/db.ts +42 -1
- package/src/be/migrations/129_asset_keys_apps_scripts.sql +161 -0
- package/src/be/migrations/130_scratch_script_retention_grace.sql +6 -0
- package/src/be/scripts/db.ts +48 -3
- package/src/be/scripts/retention.ts +164 -0
- package/src/be/scripts/run-saved.ts +16 -1
- package/src/be/seed-skills/index.ts +7 -0
- package/src/http/assets.ts +120 -29
- package/src/http/index.ts +5 -0
- package/src/http/mcp-oauth.ts +69 -1
- package/src/http/scripts.ts +21 -3
- package/src/http/users.ts +45 -0
- package/src/http/x.ts +14 -0
- package/src/oauth/ensure-mcp-token.ts +7 -1
- package/src/oauth/mcp-wrapper.ts +247 -24
- package/src/providers/claude-managed-models.ts +34 -10
- package/src/providers/pi-mono-adapter.ts +1 -1
- package/src/tests/asset-key-api.test.ts +48 -2
- package/src/tests/asset-key-invariants.test.ts +92 -0
- package/src/tests/asset-key-migration.test.ts +174 -8
- package/src/tests/asset-key-normalization.test.ts +2 -0
- package/src/tests/claude-managed-adapter.test.ts +38 -7
- package/src/tests/mcp-oauth-dcr-reuse.test.ts +95 -0
- package/src/tests/mcp-oauth-ensure-token.test.ts +23 -0
- package/src/tests/mcp-oauth-manual-client.test.ts +135 -2
- package/src/tests/mcp-oauth-wrapper.test.ts +380 -0
- package/src/tests/rbac-admission-e2e.test.ts +68 -0
- package/src/tests/sandboxed-process.test.ts +45 -0
- package/src/tests/script-connections.test.ts +4 -0
- package/src/tests/scripts-external-api.test.ts +8 -3
- package/src/tests/scripts-http.test.ts +12 -0
- package/src/tests/scripts-retention.test.ts +384 -0
- package/src/tests/whoami-route.test.ts +127 -0
- package/src/tests/workflow-engine-v2.test.ts +80 -7
- package/src/tests/workflow-swarm-script.test.ts +118 -5
- package/src/tools/workflows/create-workflow.ts +4 -1
- package/src/types.ts +18 -5
- package/src/utils/sandboxed-process.ts +40 -14
- package/src/utils/template.ts +8 -1
- package/src/workflows/engine.ts +27 -4
- package/src/workflows/executors/swarm-script.ts +52 -1
- package/src/workflows/retry-poller.ts +19 -2
- package/templates/schedules/daily-compounding-reflection/content.md +12 -3
- package/templates/skills/asset-namespaces/content.md +2 -2
- package/templates/skills/scheduled-task-resilience/SKILL.md +102 -0
- package/templates/skills/scheduled-task-resilience/config.json +14 -0
- package/templates/skills/scheduled-task-resilience/content.md +97 -0
|
@@ -152,7 +152,7 @@ import {
|
|
|
152
152
|
withRemoteContext,
|
|
153
153
|
withSpanContext,
|
|
154
154
|
writeSkillsToFilesystem
|
|
155
|
-
} from "./cli-
|
|
155
|
+
} from "./cli-jevgrb4w.js";
|
|
156
156
|
import"./cli-1z7048dy.js";
|
|
157
157
|
import {
|
|
158
158
|
Anthropic
|
|
@@ -173,34 +173,34 @@ import {
|
|
|
173
173
|
checkHeartbeatChecklist,
|
|
174
174
|
runHeartbeatSweep,
|
|
175
175
|
stopHeartbeat
|
|
176
|
-
} from "./cli-
|
|
176
|
+
} from "./cli-g74vpjp2.js";
|
|
177
177
|
import {
|
|
178
178
|
createResumeFollowUp,
|
|
179
179
|
createWorkerTaskFollowUp
|
|
180
|
-
} from "./cli-
|
|
180
|
+
} from "./cli-3ty0t082.js";
|
|
181
181
|
import {
|
|
182
182
|
calculateNextRun,
|
|
183
183
|
dispatchScheduleTarget,
|
|
184
184
|
ensure,
|
|
185
185
|
initialize,
|
|
186
186
|
require_dist
|
|
187
|
-
} from "./cli-
|
|
187
|
+
} from "./cli-ycrnynpw.js";
|
|
188
188
|
import {
|
|
189
189
|
getModelsCatalog
|
|
190
|
-
} from "./cli-
|
|
190
|
+
} from "./cli-t8d349cy.js";
|
|
191
191
|
import {
|
|
192
192
|
normalizeModelKey
|
|
193
|
-
} from "./cli-
|
|
193
|
+
} from "./cli-114fvtmj.js";
|
|
194
194
|
import {
|
|
195
195
|
getUserGrant
|
|
196
|
-
} from "./cli-
|
|
196
|
+
} from "./cli-sy7jk3tx.js";
|
|
197
197
|
import {
|
|
198
198
|
can,
|
|
199
199
|
clearAuditSink,
|
|
200
200
|
decideToolAdmission,
|
|
201
201
|
isRbacEnabled,
|
|
202
202
|
setAuditSink
|
|
203
|
-
} from "./cli-
|
|
203
|
+
} from "./cli-bqw0mt1n.js";
|
|
204
204
|
import {
|
|
205
205
|
ensureAgentFsCredentialsForAgent,
|
|
206
206
|
extractArgsJsonSchema,
|
|
@@ -210,11 +210,12 @@ import {
|
|
|
210
210
|
scriptSdkTypesWithGeneratedApis,
|
|
211
211
|
scriptStdlibTypesWithGeneratedApis,
|
|
212
212
|
typecheckScript
|
|
213
|
-
} from "./cli-
|
|
213
|
+
} from "./cli-4rkfg1wx.js";
|
|
214
214
|
import {
|
|
215
215
|
collectScriptReferences,
|
|
216
|
+
getApp,
|
|
216
217
|
listAppRecords
|
|
217
|
-
} from "./cli-
|
|
218
|
+
} from "./cli-gecy3z2s.js";
|
|
218
219
|
import {
|
|
219
220
|
RawLlmConfigSchema,
|
|
220
221
|
RawLlmOutputSchema,
|
|
@@ -234,7 +235,7 @@ import {
|
|
|
234
235
|
validateDefinition,
|
|
235
236
|
validateJsonSchema,
|
|
236
237
|
verifyHmacSignature
|
|
237
|
-
} from "./cli-
|
|
238
|
+
} from "./cli-jbcva0xj.js";
|
|
238
239
|
import"./cli-3dpj7atn.js";
|
|
239
240
|
import {
|
|
240
241
|
ConnectionAuthInputSchema,
|
|
@@ -242,6 +243,7 @@ import {
|
|
|
242
243
|
MIN_SCRIPT_WALL_CLOCK_MS,
|
|
243
244
|
applyMcpOAuthRefresh,
|
|
244
245
|
assertUrlSafe,
|
|
246
|
+
authMethodForStoredClient,
|
|
245
247
|
buildAuthorizeUrl,
|
|
246
248
|
buildSandboxedCommand,
|
|
247
249
|
buildScriptCredentialBindingsWithFailures,
|
|
@@ -281,6 +283,7 @@ import {
|
|
|
281
283
|
listScripts,
|
|
282
284
|
listVendoredOpenapiEntries,
|
|
283
285
|
markMcpOAuthTokenStatus,
|
|
286
|
+
normalizeTokenEndpointAuthMethod,
|
|
284
287
|
oauthAppToProviderConfig,
|
|
285
288
|
publicEndpointSsrfOptions,
|
|
286
289
|
readStreamCapped,
|
|
@@ -289,25 +292,29 @@ import {
|
|
|
289
292
|
refreshScriptConnection,
|
|
290
293
|
registerClient,
|
|
291
294
|
require_typescript,
|
|
295
|
+
resolveAdvertisedTokenEndpointAuthMethod,
|
|
296
|
+
restoreScratchScriptLastUsedIfUnchanged,
|
|
292
297
|
revokeMcpToken,
|
|
293
298
|
rotateScriptApiSecret,
|
|
294
299
|
runScript,
|
|
295
300
|
sandboxSpawnEnv,
|
|
301
|
+
selectDcrTokenEndpointAuthMethod,
|
|
296
302
|
setMcpServerAuthMethod,
|
|
297
303
|
setScriptConnectionEnabled,
|
|
304
|
+
touchScratchScriptLastUsed,
|
|
298
305
|
updateScriptApi,
|
|
299
306
|
upsertCredentialBinding,
|
|
300
307
|
upsertMcpOAuthToken,
|
|
301
308
|
upsertScriptByName,
|
|
302
309
|
upsertScriptConnection
|
|
303
|
-
} from "./cli-
|
|
310
|
+
} from "./cli-6dp3ydxa.js";
|
|
304
311
|
import"./cli-epan13p1.js";
|
|
305
312
|
import {
|
|
306
313
|
getApiKey
|
|
307
314
|
} from "./cli-f14fvzag.js";
|
|
308
315
|
import {
|
|
309
316
|
searchScripts
|
|
310
|
-
} from "./cli-
|
|
317
|
+
} from "./cli-g1re8r05.js";
|
|
311
318
|
import {
|
|
312
319
|
CANDIDATE_SET_MULTIPLIER,
|
|
313
320
|
getEmbeddingProvider,
|
|
@@ -315,7 +322,7 @@ import {
|
|
|
315
322
|
init_constants as init_constants2,
|
|
316
323
|
init_reranker,
|
|
317
324
|
rerank
|
|
318
|
-
} from "./cli-
|
|
325
|
+
} from "./cli-se2p6rkb.js";
|
|
319
326
|
import"./cli-0258203w.js";
|
|
320
327
|
import {
|
|
321
328
|
acquireOAuthRefreshLock,
|
|
@@ -340,14 +347,14 @@ import {
|
|
|
340
347
|
updateAuthorizationIdentity,
|
|
341
348
|
updateOAuthAppById,
|
|
342
349
|
upsertAuthorization
|
|
343
|
-
} from "./cli-
|
|
350
|
+
} from "./cli-nrkkknat.js";
|
|
344
351
|
import"./cli-fad8m16k.js";
|
|
345
352
|
import {
|
|
346
353
|
FilesError,
|
|
347
354
|
getFileStorageProvider,
|
|
348
355
|
normalizeFilesError
|
|
349
356
|
} from "./cli-bnx54kxv.js";
|
|
350
|
-
import"./cli-
|
|
357
|
+
import"./cli-6dpytdr2.js";
|
|
351
358
|
import {
|
|
352
359
|
findUserById,
|
|
353
360
|
fingerprintApiKey,
|
|
@@ -363,15 +370,15 @@ import {
|
|
|
363
370
|
resolveUserByToken,
|
|
364
371
|
revokeToken,
|
|
365
372
|
unlinkIdentity
|
|
366
|
-
} from "./cli-
|
|
373
|
+
} from "./cli-aca5pz9f.js";
|
|
367
374
|
import {
|
|
368
375
|
createTaskWithSiblingAwareness
|
|
369
|
-
} from "./cli-
|
|
376
|
+
} from "./cli-2f07m0xr.js";
|
|
370
377
|
import {
|
|
371
378
|
getSlackApp,
|
|
372
379
|
startSlackApp,
|
|
373
380
|
stopSlackApp
|
|
374
|
-
} from "./cli-
|
|
381
|
+
} from "./cli-rgrfzg8z.js";
|
|
375
382
|
import"./cli-k9qkf1hw.js";
|
|
376
383
|
import"./cli-b0p7rfnd.js";
|
|
377
384
|
import"./cli-t930g0xh.js";
|
|
@@ -749,7 +756,7 @@ import {
|
|
|
749
756
|
upsertSwarmConfig,
|
|
750
757
|
validateConfigValue,
|
|
751
758
|
withFavoriteFlags
|
|
752
|
-
} from "./cli-
|
|
759
|
+
} from "./cli-50vbt00w.js";
|
|
753
760
|
import {
|
|
754
761
|
getAllTemplateDefinitions,
|
|
755
762
|
getTemplateDefinition,
|
|
@@ -762,7 +769,7 @@ import {
|
|
|
762
769
|
isEnvFlagEnabled,
|
|
763
770
|
isSteeringEnabled,
|
|
764
771
|
resolveTemplate
|
|
765
|
-
} from "./cli-
|
|
772
|
+
} from "./cli-xpxde7rm.js";
|
|
766
773
|
import {
|
|
767
774
|
MAX_PROFILE_FILE_LENGTH,
|
|
768
775
|
getAppUrl,
|
|
@@ -784,7 +791,7 @@ import {
|
|
|
784
791
|
import {
|
|
785
792
|
init_package,
|
|
786
793
|
package_default
|
|
787
|
-
} from "./cli-
|
|
794
|
+
} from "./cli-ccf9vy7q.js";
|
|
788
795
|
import {
|
|
789
796
|
array,
|
|
790
797
|
exports_external,
|
|
@@ -799,20 +806,20 @@ import {
|
|
|
799
806
|
} from "./cli-9aryf9tv.js";
|
|
800
807
|
import {
|
|
801
808
|
bedrockProviderModule
|
|
802
|
-
} from "./cli-
|
|
809
|
+
} from "./cli-9dr5qzc0.js";
|
|
803
810
|
import"./cli-cwy5hqbq.js";
|
|
804
811
|
import {
|
|
805
812
|
setBedrockProviderModule
|
|
806
|
-
} from "./cli-
|
|
813
|
+
} from "./cli-darcwax3.js";
|
|
807
814
|
import"./cli-jvv0g8bh.js";
|
|
808
815
|
import"./cli-r6kqqbj0.js";
|
|
809
|
-
import"./cli-
|
|
816
|
+
import"./cli-6map995v.js";
|
|
810
817
|
import"./cli-4wgngmwv.js";
|
|
811
818
|
import"./cli-vapyk8sw.js";
|
|
812
819
|
import"./cli-zyxs93y9.js";
|
|
813
|
-
import"./cli-
|
|
820
|
+
import"./cli-57khth04.js";
|
|
814
821
|
import"./cli-y2apkfe2.js";
|
|
815
|
-
import"./cli-
|
|
822
|
+
import"./cli-akdvwc9v.js";
|
|
816
823
|
import"./cli-8wrympd7.js";
|
|
817
824
|
import"./cli-7sgrxg9a.js";
|
|
818
825
|
import"./cli-3fj60etf.js";
|
|
@@ -836,6 +843,107 @@ import {
|
|
|
836
843
|
} from "node:http";
|
|
837
844
|
init_db();
|
|
838
845
|
|
|
846
|
+
// src/be/scripts/retention.ts
|
|
847
|
+
init_db();
|
|
848
|
+
var SCRATCH_RETENTION_DAYS = 14;
|
|
849
|
+
var SCRATCH_GC_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
850
|
+
var scratchGcTimer = null;
|
|
851
|
+
function appReferencedScriptIds(candidateIds) {
|
|
852
|
+
const ids = new Set;
|
|
853
|
+
for (const app of listAppRecords()) {
|
|
854
|
+
for (const scriptId of collectScriptReferences(app.definition).keys()) {
|
|
855
|
+
ids.add(scriptId);
|
|
856
|
+
}
|
|
857
|
+
if (app.definitionError === undefined)
|
|
858
|
+
continue;
|
|
859
|
+
const serialized = JSON.stringify(app.definition ?? null);
|
|
860
|
+
for (const id of candidateIds) {
|
|
861
|
+
if (!ids.has(id) && serialized.includes(id))
|
|
862
|
+
ids.add(id);
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
return ids;
|
|
866
|
+
}
|
|
867
|
+
function scriptApiReferencedScriptIds() {
|
|
868
|
+
const rows = getDb().prepare("SELECT DISTINCT scriptId FROM script_apis").all();
|
|
869
|
+
return new Set(rows.map((row) => row.scriptId));
|
|
870
|
+
}
|
|
871
|
+
function workflowReferencedAgentScriptKeys() {
|
|
872
|
+
const keys = new Set;
|
|
873
|
+
for (const workflow of listWorkflows()) {
|
|
874
|
+
if (!workflow.createdByAgentId)
|
|
875
|
+
continue;
|
|
876
|
+
for (const node of workflow.definition.nodes) {
|
|
877
|
+
if (node.type !== "swarm-script")
|
|
878
|
+
continue;
|
|
879
|
+
const scriptName = node.config.scriptName;
|
|
880
|
+
const scope = node.config.scope;
|
|
881
|
+
if (typeof scriptName !== "string" || scope === "global")
|
|
882
|
+
continue;
|
|
883
|
+
keys.add(`${scriptName}::${workflow.createdByAgentId}`);
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
return keys;
|
|
887
|
+
}
|
|
888
|
+
function workflowReferencedScratchNamesForOwnerlessWorkflows() {
|
|
889
|
+
const names = new Set;
|
|
890
|
+
for (const workflow of listWorkflows()) {
|
|
891
|
+
if (workflow.createdByAgentId)
|
|
892
|
+
continue;
|
|
893
|
+
for (const node of workflow.definition.nodes) {
|
|
894
|
+
if (node.type !== "swarm-script")
|
|
895
|
+
continue;
|
|
896
|
+
const scriptName = node.config.scriptName;
|
|
897
|
+
const scope = node.config.scope;
|
|
898
|
+
if (typeof scriptName !== "string" || scope === "global")
|
|
899
|
+
continue;
|
|
900
|
+
names.add(scriptName);
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
return names;
|
|
904
|
+
}
|
|
905
|
+
function purgeExpiredScratchScripts(now = new Date) {
|
|
906
|
+
const cutoff = new Date(now.getTime() - SCRATCH_RETENTION_DAYS * 24 * 60 * 60 * 1000).toISOString();
|
|
907
|
+
const candidates = getDb().prepare(`SELECT id, name, scopeId FROM scripts
|
|
908
|
+
WHERE scope = 'agent'
|
|
909
|
+
AND isScratch = 1
|
|
910
|
+
AND name GLOB 'scratch-*'
|
|
911
|
+
AND updatedAt < ?`).all(cutoff);
|
|
912
|
+
if (candidates.length === 0)
|
|
913
|
+
return 0;
|
|
914
|
+
const referenced = appReferencedScriptIds(candidates.map((row) => row.id));
|
|
915
|
+
const apiReferenced = scriptApiReferencedScriptIds();
|
|
916
|
+
const workflowReferenced = workflowReferencedAgentScriptKeys();
|
|
917
|
+
const ownerlessWorkflowReferencedNames = workflowReferencedScratchNamesForOwnerlessWorkflows();
|
|
918
|
+
const idsToDelete = candidates.filter((row) => !referenced.has(row.id)).filter((row) => !apiReferenced.has(row.id)).filter((row) => !(row.scopeId && workflowReferenced.has(`${row.name}::${row.scopeId}`))).filter((row) => !ownerlessWorkflowReferencedNames.has(row.name)).map((row) => row.id);
|
|
919
|
+
if (idsToDelete.length === 0)
|
|
920
|
+
return 0;
|
|
921
|
+
const placeholders = idsToDelete.map(() => "?").join(",");
|
|
922
|
+
return getDb().prepare(`DELETE FROM scripts WHERE id IN (${placeholders}) RETURNING id`).all(...idsToDelete).length;
|
|
923
|
+
}
|
|
924
|
+
function runScratchScriptGc(label) {
|
|
925
|
+
try {
|
|
926
|
+
const purged = purgeExpiredScratchScripts();
|
|
927
|
+
console.log(`[scratch-script-gc] ${label} purge removed ${purged} scratch script row(s)`);
|
|
928
|
+
} catch (err) {
|
|
929
|
+
console.error(`[scratch-script-gc] ${label} purge failed:`, err.message);
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
function startScratchScriptGc(intervalMs = SCRATCH_GC_INTERVAL_MS) {
|
|
933
|
+
if (scratchGcTimer)
|
|
934
|
+
return;
|
|
935
|
+
runScratchScriptGc("Initial");
|
|
936
|
+
scratchGcTimer = setInterval(() => runScratchScriptGc("Periodic"), intervalMs);
|
|
937
|
+
if (typeof scratchGcTimer.unref === "function")
|
|
938
|
+
scratchGcTimer.unref();
|
|
939
|
+
}
|
|
940
|
+
function stopScratchScriptGc() {
|
|
941
|
+
if (!scratchGcTimer)
|
|
942
|
+
return;
|
|
943
|
+
clearInterval(scratchGcTimer);
|
|
944
|
+
scratchGcTimer = null;
|
|
945
|
+
}
|
|
946
|
+
|
|
839
947
|
// src/be/seed-capabilities.ts
|
|
840
948
|
init_db();
|
|
841
949
|
var LEGACY_ALWAYS_ON_DEFAULTS = [
|
|
@@ -2619,7 +2727,7 @@ var listAssetsRoute = route({
|
|
|
2619
2727
|
tags: ["Assets"],
|
|
2620
2728
|
query: exports_external.object({
|
|
2621
2729
|
keyPrefix: AssetKeySchema.optional(),
|
|
2622
|
-
types: exports_external.string().optional().describe("Comma-separated task,workflow,schedule,page,file list"),
|
|
2730
|
+
types: exports_external.string().optional().describe("Comma-separated task,workflow,schedule,page,app,script,file list"),
|
|
2623
2731
|
limit: exports_external.coerce.number().int().min(1).max(1000).optional()
|
|
2624
2732
|
}),
|
|
2625
2733
|
responses: {
|
|
@@ -2659,6 +2767,41 @@ function ensureOperator(req, res) {
|
|
|
2659
2767
|
jsonError(res, "Operator access required", 403);
|
|
2660
2768
|
return false;
|
|
2661
2769
|
}
|
|
2770
|
+
var moveAssetBodySchema = exports_external.object({ key: AssetKeySchema });
|
|
2771
|
+
var moveAssetSuccessSchema = exports_external.object({
|
|
2772
|
+
entityType: AssetEntityTypeSchema,
|
|
2773
|
+
id: exports_external.string(),
|
|
2774
|
+
key: AssetKeySchema
|
|
2775
|
+
});
|
|
2776
|
+
var moveAssetResponses = {
|
|
2777
|
+
200: { description: "Asset namespace updated", schema: moveAssetSuccessSchema },
|
|
2778
|
+
400: { description: "Invalid namespace" },
|
|
2779
|
+
403: { description: "Move not authorized" },
|
|
2780
|
+
404: { description: "Asset not found" },
|
|
2781
|
+
409: { description: "Moves blocked until audit warnings are repaired" }
|
|
2782
|
+
};
|
|
2783
|
+
var moveAppAssetRoute = route({
|
|
2784
|
+
method: "patch",
|
|
2785
|
+
path: "/api/assets/app/{id}/key",
|
|
2786
|
+
pattern: ["api", "assets", "app", null, "key"],
|
|
2787
|
+
summary: "Move an app to another logical namespace",
|
|
2788
|
+
tags: ["Assets"],
|
|
2789
|
+
params: exports_external.object({ id: exports_external.string().min(1) }),
|
|
2790
|
+
body: moveAssetBodySchema,
|
|
2791
|
+
responses: moveAssetResponses,
|
|
2792
|
+
rbac: { permission: "app.manage" }
|
|
2793
|
+
});
|
|
2794
|
+
var moveScriptAssetRoute = route({
|
|
2795
|
+
method: "patch",
|
|
2796
|
+
path: "/api/assets/script/{id}/key",
|
|
2797
|
+
pattern: ["api", "assets", "script", null, "key"],
|
|
2798
|
+
summary: "Move a script to another logical namespace",
|
|
2799
|
+
tags: ["Assets"],
|
|
2800
|
+
params: exports_external.object({ id: exports_external.string().min(1) }),
|
|
2801
|
+
body: moveAssetBodySchema,
|
|
2802
|
+
responses: moveAssetResponses,
|
|
2803
|
+
rbac: { permission: "script.global.write" }
|
|
2804
|
+
});
|
|
2662
2805
|
var moveAssetRoute = route({
|
|
2663
2806
|
method: "patch",
|
|
2664
2807
|
path: "/api/assets/{entityType}/{id}/key",
|
|
@@ -2667,25 +2810,23 @@ var moveAssetRoute = route({
|
|
|
2667
2810
|
description: "Updates namespace metadata only. Provider-backed files keep the same provider key, org, and drive; no remote move occurs. Personal keys are labels, not a privacy guarantee.",
|
|
2668
2811
|
tags: ["Assets"],
|
|
2669
2812
|
params: exports_external.object({ entityType: AssetEntityTypeSchema, id: exports_external.string().min(1) }),
|
|
2670
|
-
body:
|
|
2671
|
-
responses:
|
|
2672
|
-
200: {
|
|
2673
|
-
description: "Asset namespace updated",
|
|
2674
|
-
schema: exports_external.object({
|
|
2675
|
-
entityType: AssetEntityTypeSchema,
|
|
2676
|
-
id: exports_external.string(),
|
|
2677
|
-
key: AssetKeySchema
|
|
2678
|
-
})
|
|
2679
|
-
},
|
|
2680
|
-
400: { description: "Invalid namespace" },
|
|
2681
|
-
403: { description: "Move not authorized" },
|
|
2682
|
-
404: { description: "Asset not found" },
|
|
2683
|
-
409: { description: "Moves blocked until audit warnings are repaired" }
|
|
2684
|
-
},
|
|
2813
|
+
body: moveAssetBodySchema,
|
|
2814
|
+
responses: moveAssetResponses,
|
|
2685
2815
|
rbac: {
|
|
2686
|
-
ungated: "preserves each entity's current mutation posture; task moves
|
|
2816
|
+
ungated: "preserves each entity's current mutation posture; task moves use task.fs.mutate, app moves use app.manage, scripts preserve agent ownership/global-lead rules, file moves require operator authentication, and personal destinations require a matching trusted user"
|
|
2687
2817
|
}
|
|
2688
2818
|
});
|
|
2819
|
+
function assetMovePrincipal(req, myAgentId) {
|
|
2820
|
+
const auth = getRequestAuth(req);
|
|
2821
|
+
if (auth?.kind === "operator")
|
|
2822
|
+
return { kind: "operator" };
|
|
2823
|
+
if (auth?.kind === "user")
|
|
2824
|
+
return { kind: "user", userId: auth.userId };
|
|
2825
|
+
if (!myAgentId)
|
|
2826
|
+
return null;
|
|
2827
|
+
const agent = getAgentById(myAgentId);
|
|
2828
|
+
return { kind: "agent", agentId: myAgentId, isLead: agent?.isLead ?? false };
|
|
2829
|
+
}
|
|
2689
2830
|
function canMutateTaskNamespace(task, myAgentId, req) {
|
|
2690
2831
|
const resource = {
|
|
2691
2832
|
kind: "task",
|
|
@@ -2693,20 +2834,32 @@ function canMutateTaskNamespace(task, myAgentId, req) {
|
|
|
2693
2834
|
agentId: task.agentId,
|
|
2694
2835
|
creatorAgentId: task.creatorAgentId
|
|
2695
2836
|
};
|
|
2696
|
-
const
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
principal = { kind: "operator" };
|
|
2700
|
-
} else if (auth?.kind === "user") {
|
|
2701
|
-
principal = { kind: "user", userId: auth.userId };
|
|
2702
|
-
} else {
|
|
2703
|
-
if (!myAgentId)
|
|
2704
|
-
return false;
|
|
2705
|
-
const agent = getAgentById(myAgentId);
|
|
2706
|
-
principal = { kind: "agent", agentId: myAgentId, isLead: agent?.isLead ?? false };
|
|
2707
|
-
}
|
|
2837
|
+
const principal = assetMovePrincipal(req, myAgentId);
|
|
2838
|
+
if (!principal)
|
|
2839
|
+
return false;
|
|
2708
2840
|
return can({ principal, verb: "task.fs.mutate", resource, source: "http" }).allow;
|
|
2709
2841
|
}
|
|
2842
|
+
function canManageAppNamespace(id, req, myAgentId) {
|
|
2843
|
+
const principal = assetMovePrincipal(req, myAgentId);
|
|
2844
|
+
return !!principal && can({ principal, verb: "app.manage", resource: { kind: "app", appId: id }, source: "http" }).allow;
|
|
2845
|
+
}
|
|
2846
|
+
function canManageScriptNamespace(script, req, myAgentId) {
|
|
2847
|
+
const principal = assetMovePrincipal(req, myAgentId);
|
|
2848
|
+
if (!principal)
|
|
2849
|
+
return false;
|
|
2850
|
+
if (principal.kind === "operator")
|
|
2851
|
+
return true;
|
|
2852
|
+
if (principal.kind !== "agent")
|
|
2853
|
+
return false;
|
|
2854
|
+
if (script.scope === "agent")
|
|
2855
|
+
return script.scopeId === principal.agentId;
|
|
2856
|
+
return can({
|
|
2857
|
+
principal,
|
|
2858
|
+
verb: "script.global.write",
|
|
2859
|
+
resource: { kind: "owned", scope: "global" },
|
|
2860
|
+
source: "http"
|
|
2861
|
+
}).allow;
|
|
2862
|
+
}
|
|
2710
2863
|
async function handleAssets(req, res, pathSegments, queryParams, myAgentId) {
|
|
2711
2864
|
if (keyAuditRoute.match(req.method, pathSegments)) {
|
|
2712
2865
|
const parsed = await keyAuditRoute.parse(req, res, pathSegments, queryParams);
|
|
@@ -2768,7 +2921,7 @@ async function handleAssets(req, res, pathSegments, queryParams, myAgentId) {
|
|
|
2768
2921
|
}
|
|
2769
2922
|
return true;
|
|
2770
2923
|
}
|
|
2771
|
-
if (moveAssetRoute.match(req.method, pathSegments)) {
|
|
2924
|
+
if (moveAppAssetRoute.match(req.method, pathSegments) || moveScriptAssetRoute.match(req.method, pathSegments) || moveAssetRoute.match(req.method, pathSegments)) {
|
|
2772
2925
|
const parsed = await moveAssetRoute.parse(req, res, pathSegments, queryParams);
|
|
2773
2926
|
if (!parsed)
|
|
2774
2927
|
return true;
|
|
@@ -2785,6 +2938,27 @@ async function handleAssets(req, res, pathSegments, queryParams, myAgentId) {
|
|
|
2785
2938
|
return true;
|
|
2786
2939
|
}
|
|
2787
2940
|
}
|
|
2941
|
+
if (parsed.params.entityType === "app") {
|
|
2942
|
+
if (!getApp(parsed.params.id)) {
|
|
2943
|
+
jsonError(res, "Asset not found", 404);
|
|
2944
|
+
return true;
|
|
2945
|
+
}
|
|
2946
|
+
if (!canManageAppNamespace(parsed.params.id, req, myAgentId)) {
|
|
2947
|
+
jsonError(res, "Not authorized to move this app namespace", 403);
|
|
2948
|
+
return true;
|
|
2949
|
+
}
|
|
2950
|
+
}
|
|
2951
|
+
if (parsed.params.entityType === "script") {
|
|
2952
|
+
const script = getScriptById(parsed.params.id);
|
|
2953
|
+
if (!script) {
|
|
2954
|
+
jsonError(res, "Asset not found", 404);
|
|
2955
|
+
return true;
|
|
2956
|
+
}
|
|
2957
|
+
if (!canManageScriptNamespace(script, req, myAgentId)) {
|
|
2958
|
+
jsonError(res, "Not authorized to move this script namespace", 403);
|
|
2959
|
+
return true;
|
|
2960
|
+
}
|
|
2961
|
+
}
|
|
2788
2962
|
try {
|
|
2789
2963
|
const actor = resolveHttpAuditUserId(req, myAgentId);
|
|
2790
2964
|
const key = authorizeAssetKeyWrite(parsed.body.key, actor);
|
|
@@ -6589,7 +6763,8 @@ var DiscoveryResultSchema = exports_external.object({
|
|
|
6589
6763
|
scopes: exports_external.array(exports_external.string()),
|
|
6590
6764
|
requiresOAuth: exports_external.literal(true),
|
|
6591
6765
|
dcrSupported: exports_external.boolean(),
|
|
6592
|
-
bearerMethodsSupported: exports_external.array(exports_external.string()).nullable()
|
|
6766
|
+
bearerMethodsSupported: exports_external.array(exports_external.string()).nullable(),
|
|
6767
|
+
tokenEndpointAuthMethodsSupported: exports_external.array(exports_external.string()).nullable()
|
|
6593
6768
|
});
|
|
6594
6769
|
var MetadataResponseSchema = exports_external.union([
|
|
6595
6770
|
exports_external.object({ requiresOAuth: exports_external.literal(false) }),
|
|
@@ -6645,7 +6820,8 @@ function manualClientFromToken(token) {
|
|
|
6645
6820
|
authorizeUrl: token.authorizeUrl,
|
|
6646
6821
|
tokenUrl: token.tokenUrl,
|
|
6647
6822
|
revocationUrl: token.revocationUrl,
|
|
6648
|
-
scopes: splitScopes(token.scope)
|
|
6823
|
+
scopes: splitScopes(token.scope),
|
|
6824
|
+
tokenEndpointAuthMethod: authMethodForStoredClient(token.tokenEndpointAuthMethod)
|
|
6649
6825
|
};
|
|
6650
6826
|
}
|
|
6651
6827
|
async function discoverForMcp(resourceUrl) {
|
|
@@ -6667,7 +6843,8 @@ async function discoverForMcp(resourceUrl) {
|
|
|
6667
6843
|
scopes: prmd.scopes_supported ?? as.scopes_supported ?? [],
|
|
6668
6844
|
requiresOAuth: true,
|
|
6669
6845
|
dcrSupported: !!as.registration_endpoint,
|
|
6670
|
-
bearerMethodsSupported: prmd.bearer_methods_supported ?? null
|
|
6846
|
+
bearerMethodsSupported: prmd.bearer_methods_supported ?? null,
|
|
6847
|
+
tokenEndpointAuthMethodsSupported: as.token_endpoint_auth_methods_supported ?? null
|
|
6671
6848
|
};
|
|
6672
6849
|
}
|
|
6673
6850
|
function getMcpOrError(res, mcpServerId) {
|
|
@@ -6824,7 +7001,8 @@ var manualClientRoute = route({
|
|
|
6824
7001
|
authorizeUrl: exports_external.string().url().optional(),
|
|
6825
7002
|
tokenUrl: exports_external.string().url().optional(),
|
|
6826
7003
|
revocationUrl: exports_external.string().url().optional(),
|
|
6827
|
-
scopes: exports_external.array(exports_external.string()).optional()
|
|
7004
|
+
scopes: exports_external.array(exports_external.string()).optional(),
|
|
7005
|
+
tokenEndpointAuthMethod: exports_external.enum(["client_secret_basic", "client_secret_post", "none"]).optional()
|
|
6828
7006
|
}),
|
|
6829
7007
|
responses: {
|
|
6830
7008
|
200: {
|
|
@@ -6886,7 +7064,8 @@ async function runAuthorizeFlow(res, mcpServerId, server, q, userId) {
|
|
|
6886
7064
|
authorizeUrl: discovery.authorizeUrl,
|
|
6887
7065
|
tokenUrl: discovery.tokenUrl,
|
|
6888
7066
|
revocationUrl: discovery.revocationUrl,
|
|
6889
|
-
scopes: reusable.scopes.length > 0 ? reusable.scopes : discovery.scopes
|
|
7067
|
+
scopes: reusable.scopes.length > 0 ? reusable.scopes : discovery.scopes,
|
|
7068
|
+
tokenEndpointAuthMethod: authMethodForStoredClient(reusable.tokenEndpointAuthMethod)
|
|
6890
7069
|
};
|
|
6891
7070
|
}
|
|
6892
7071
|
}
|
|
@@ -6900,15 +7079,17 @@ async function runAuthorizeFlow(res, mcpServerId, server, q, userId) {
|
|
|
6900
7079
|
return null;
|
|
6901
7080
|
}
|
|
6902
7081
|
const scopes2 = q.scopes ? splitScopes(q.scopes) : discovery.scopes;
|
|
7082
|
+
const requestedAuthMethod = selectDcrTokenEndpointAuthMethod(discovery.tokenEndpointAuthMethodsSupported ?? undefined);
|
|
6903
7083
|
const dcr = await registerClient(discovery.registrationEndpoint, {
|
|
6904
7084
|
client_name: `agent-swarm (${server.name})`,
|
|
6905
7085
|
redirect_uris: [callbackRedirectUri()],
|
|
6906
7086
|
grant_types: ["authorization_code", "refresh_token"],
|
|
6907
7087
|
response_types: ["code"],
|
|
6908
|
-
token_endpoint_auth_method:
|
|
7088
|
+
token_endpoint_auth_method: requestedAuthMethod,
|
|
6909
7089
|
application_type: "web",
|
|
6910
7090
|
scope: scopes2.join(" ") || undefined
|
|
6911
7091
|
});
|
|
7092
|
+
const registeredAuthMethod = dcr.token_endpoint_auth_method ? resolveAdvertisedTokenEndpointAuthMethod(dcr.token_endpoint_auth_method, "returned") : requestedAuthMethod;
|
|
6912
7093
|
registeredScopes = scopes2;
|
|
6913
7094
|
client = {
|
|
6914
7095
|
clientId: dcr.client_id,
|
|
@@ -6918,7 +7099,8 @@ async function runAuthorizeFlow(res, mcpServerId, server, q, userId) {
|
|
|
6918
7099
|
authorizeUrl: discovery.authorizeUrl,
|
|
6919
7100
|
tokenUrl: discovery.tokenUrl,
|
|
6920
7101
|
revocationUrl: discovery.revocationUrl,
|
|
6921
|
-
scopes: scopes2
|
|
7102
|
+
scopes: scopes2,
|
|
7103
|
+
tokenEndpointAuthMethod: registeredAuthMethod
|
|
6922
7104
|
};
|
|
6923
7105
|
}
|
|
6924
7106
|
const scopes = q.scopes ? splitScopes(q.scopes) : client.scopes;
|
|
@@ -6957,6 +7139,7 @@ async function runAuthorizeFlow(res, mcpServerId, server, q, userId) {
|
|
|
6957
7139
|
registeredScopes,
|
|
6958
7140
|
dcrClientId: client.clientId,
|
|
6959
7141
|
dcrClientSecret: client.clientSecret,
|
|
7142
|
+
tokenEndpointAuthMethod: client.tokenEndpointAuthMethod,
|
|
6960
7143
|
redirectUri: callbackRedirectUri(),
|
|
6961
7144
|
finalRedirect: q.redirect ?? null
|
|
6962
7145
|
});
|
|
@@ -6996,6 +7179,7 @@ async function completeMcpOAuthCallback(res, query) {
|
|
|
6996
7179
|
tokenUrl: pending.tokenUrl,
|
|
6997
7180
|
clientId: pending.dcrClientId ?? "",
|
|
6998
7181
|
clientSecret: pending.dcrClientSecret ?? undefined,
|
|
7182
|
+
tokenEndpointAuthMethod: authMethodForStoredClient(pending.tokenEndpointAuthMethod),
|
|
6999
7183
|
redirectUri: pending.redirectUri,
|
|
7000
7184
|
code: query.code,
|
|
7001
7185
|
codeVerifier: pending.codeVerifier,
|
|
@@ -7021,6 +7205,7 @@ async function completeMcpOAuthCallback(res, query) {
|
|
|
7021
7205
|
registeredScopes: pending.registeredScopes ?? undefined,
|
|
7022
7206
|
dcrClientId: pending.dcrClientId,
|
|
7023
7207
|
dcrClientSecret: pending.dcrClientSecret,
|
|
7208
|
+
tokenEndpointAuthMethod: authMethodForStoredClient(pending.tokenEndpointAuthMethod),
|
|
7024
7209
|
clientSource,
|
|
7025
7210
|
lastRefreshedAt: new Date().toISOString()
|
|
7026
7211
|
});
|
|
@@ -7166,6 +7351,7 @@ async function handleMcpOAuth(req, res, pathSegments, queryParams) {
|
|
|
7166
7351
|
tokenUrl: existing.tokenUrl,
|
|
7167
7352
|
clientId: existing.dcrClientId ?? "",
|
|
7168
7353
|
clientSecret: existing.dcrClientSecret ?? undefined,
|
|
7354
|
+
tokenEndpointAuthMethod: authMethodForStoredClient(existing.tokenEndpointAuthMethod),
|
|
7169
7355
|
refreshToken: existing.refreshToken,
|
|
7170
7356
|
resource: existing.resourceUrl
|
|
7171
7357
|
});
|
|
@@ -7208,7 +7394,8 @@ async function handleMcpOAuth(req, res, pathSegments, queryParams) {
|
|
|
7208
7394
|
token: token.accessToken,
|
|
7209
7395
|
tokenTypeHint: "access_token",
|
|
7210
7396
|
clientId: token.dcrClientId ?? "",
|
|
7211
|
-
clientSecret: token.dcrClientSecret ?? undefined
|
|
7397
|
+
clientSecret: token.dcrClientSecret ?? undefined,
|
|
7398
|
+
tokenEndpointAuthMethod: authMethodForStoredClient(token.tokenEndpointAuthMethod)
|
|
7212
7399
|
});
|
|
7213
7400
|
} catch (err) {
|
|
7214
7401
|
console.warn("[mcp-oauth] revocation call failed (continuing with local delete):", err instanceof Error ? err.message : err);
|
|
@@ -7234,6 +7421,8 @@ async function handleMcpOAuth(req, res, pathSegments, queryParams) {
|
|
|
7234
7421
|
let authorizationServerIssuer = overrides.authorizationServerIssuer ?? null;
|
|
7235
7422
|
let resourceUrl = server.url;
|
|
7236
7423
|
let scopes = overrides.scopes ?? [];
|
|
7424
|
+
let tokenEndpointAuthMethod = overrides.tokenEndpointAuthMethod ? normalizeTokenEndpointAuthMethod(overrides.tokenEndpointAuthMethod) : undefined;
|
|
7425
|
+
let advertisedAuthMethods = null;
|
|
7237
7426
|
if (!authorizeUrl || !tokenUrl) {
|
|
7238
7427
|
const discovery = await discoverForMcp(server.url);
|
|
7239
7428
|
if (!discovery) {
|
|
@@ -7247,6 +7436,11 @@ async function handleMcpOAuth(req, res, pathSegments, queryParams) {
|
|
|
7247
7436
|
resourceUrl = discovery.resourceUrl;
|
|
7248
7437
|
if (scopes.length === 0)
|
|
7249
7438
|
scopes = discovery.scopes;
|
|
7439
|
+
advertisedAuthMethods = discovery.tokenEndpointAuthMethodsSupported;
|
|
7440
|
+
}
|
|
7441
|
+
if (!tokenEndpointAuthMethod) {
|
|
7442
|
+
const postUnsupported = advertisedAuthMethods !== null && advertisedAuthMethods.length > 0 && !advertisedAuthMethods.includes("client_secret_post");
|
|
7443
|
+
tokenEndpointAuthMethod = postUnsupported ? selectDcrTokenEndpointAuthMethod(advertisedAuthMethods ?? undefined) : authMethodForStoredClient(undefined);
|
|
7250
7444
|
}
|
|
7251
7445
|
if (!authorizationServerIssuer) {
|
|
7252
7446
|
jsonError(res, "authorizationServerIssuer is required when endpoints are provided manually.", 400);
|
|
@@ -7265,6 +7459,7 @@ async function handleMcpOAuth(req, res, pathSegments, queryParams) {
|
|
|
7265
7459
|
revocationUrl,
|
|
7266
7460
|
dcrClientId: overrides.clientId,
|
|
7267
7461
|
dcrClientSecret: overrides.clientSecret ?? null,
|
|
7462
|
+
tokenEndpointAuthMethod,
|
|
7268
7463
|
clientSource: "manual",
|
|
7269
7464
|
status: "error",
|
|
7270
7465
|
lastErrorMessage: "Manual client pre-registered; awaiting authorize flow."
|
|
@@ -16464,12 +16659,14 @@ async function handleScripts(req, res, pathSegments, queryParams, agentId) {
|
|
|
16464
16659
|
return true;
|
|
16465
16660
|
let source = parsed.body.source;
|
|
16466
16661
|
let fsMode = parsed.body.fsMode;
|
|
16662
|
+
let namedScript = null;
|
|
16467
16663
|
if (parsed.body.name) {
|
|
16468
16664
|
const script = resolveScript(parsed.body.name, agent.id, parsed.body.scope);
|
|
16469
16665
|
if (!script) {
|
|
16470
16666
|
jsonError(res, "Script not found", 404);
|
|
16471
16667
|
return true;
|
|
16472
16668
|
}
|
|
16669
|
+
namedScript = script;
|
|
16473
16670
|
source = script.source;
|
|
16474
16671
|
fsMode = script.fsMode;
|
|
16475
16672
|
}
|
|
@@ -16478,6 +16675,7 @@ async function handleScripts(req, res, pathSegments, queryParams, agentId) {
|
|
|
16478
16675
|
return true;
|
|
16479
16676
|
}
|
|
16480
16677
|
const startedAt = new Date().toISOString();
|
|
16678
|
+
const runStartTouch = namedScript?.isScratch ? touchScratchScriptLastUsed(namedScript.id) : null;
|
|
16481
16679
|
const credentials = await buildScriptCredentialBindingsWithFailures({ agentId: agent.id });
|
|
16482
16680
|
const output = await runScript({
|
|
16483
16681
|
source,
|
|
@@ -16489,8 +16687,14 @@ async function handleScripts(req, res, pathSegments, queryParams, agentId) {
|
|
|
16489
16687
|
apiConnections: getScriptApiConnectionDescriptors({ agentId: agent.id }),
|
|
16490
16688
|
mcpConnections: getScriptMcpConnectionDescriptors({ agentId: agent.id })
|
|
16491
16689
|
});
|
|
16690
|
+
const ok = output.exitCode === 0 && !output.error && !output.runtimeError;
|
|
16691
|
+
if (namedScript?.isScratch && ok) {
|
|
16692
|
+
touchScratchScriptLastUsed(namedScript.id);
|
|
16693
|
+
} else if (namedScript?.isScratch && runStartTouch) {
|
|
16694
|
+
restoreScratchScriptLastUsedIfUnchanged(namedScript.id, namedScript.updatedAt, runStartTouch);
|
|
16695
|
+
}
|
|
16492
16696
|
let kvSaved;
|
|
16493
|
-
if (parsed.body.idempotencyKey &&
|
|
16697
|
+
if (parsed.body.idempotencyKey && ok) {
|
|
16494
16698
|
const kvNamespace = `script:executions`;
|
|
16495
16699
|
const kvKey = parsed.body.idempotencyKey;
|
|
16496
16700
|
const kvValue = {
|
|
@@ -16509,7 +16713,7 @@ async function handleScripts(req, res, pathSegments, queryParams, agentId) {
|
|
|
16509
16713
|
kvSaved = { namespace: kvNamespace, key: kvKey };
|
|
16510
16714
|
}
|
|
16511
16715
|
let autoSaved;
|
|
16512
|
-
if (parsed.body.source &&
|
|
16716
|
+
if (parsed.body.source && ok) {
|
|
16513
16717
|
const slug = scratchSlug(parsed.body.intent, parsed.body.source);
|
|
16514
16718
|
await upsertScriptByName({
|
|
16515
16719
|
name: slug,
|
|
@@ -16527,7 +16731,6 @@ async function handleScripts(req, res, pathSegments, queryParams, agentId) {
|
|
|
16527
16731
|
});
|
|
16528
16732
|
autoSaved = { slug, reason: "successful_inline_run" };
|
|
16529
16733
|
}
|
|
16530
|
-
const ok = output.exitCode === 0 && !output.error && !output.runtimeError;
|
|
16531
16734
|
const runError = ok ? undefined : scrubSecrets([
|
|
16532
16735
|
output.error,
|
|
16533
16736
|
output.runtimeError ? `${output.runtimeError.name}: ${output.runtimeError.message}` : undefined
|
|
@@ -20766,6 +20969,7 @@ async function handleTrackers(req, res, pathSegments) {
|
|
|
20766
20969
|
init_zod();
|
|
20767
20970
|
init_db();
|
|
20768
20971
|
init_types();
|
|
20972
|
+
init_request_auth_context();
|
|
20769
20973
|
|
|
20770
20974
|
// src/http/operator-actor.ts
|
|
20771
20975
|
init_request_auth_context();
|
|
@@ -20852,6 +21056,24 @@ var UnmappedIdentitySchema = exports_external.object({
|
|
|
20852
21056
|
sampleEventType: exports_external.string().nullable(),
|
|
20853
21057
|
sampleContext: exports_external.unknown().nullable()
|
|
20854
21058
|
});
|
|
21059
|
+
var whoamiRoute = route({
|
|
21060
|
+
method: "get",
|
|
21061
|
+
path: "/api/whoami",
|
|
21062
|
+
pattern: ["api", "whoami"],
|
|
21063
|
+
summary: "Resolve the authenticated principal behind the presented bearer",
|
|
21064
|
+
tags: ["Users"],
|
|
21065
|
+
responses: {
|
|
21066
|
+
200: {
|
|
21067
|
+
description: "Authenticated principal",
|
|
21068
|
+
schema: exports_external.object({
|
|
21069
|
+
kind: exports_external.enum(["operator", "user"]),
|
|
21070
|
+
user: exports_external.union([UserSchema, exports_external.null()])
|
|
21071
|
+
})
|
|
21072
|
+
},
|
|
21073
|
+
401: { description: "Unauthorized" }
|
|
21074
|
+
},
|
|
21075
|
+
auth: { apiKey: true }
|
|
21076
|
+
});
|
|
20855
21077
|
var listUsers = route({
|
|
20856
21078
|
method: "get",
|
|
20857
21079
|
path: "/api/users",
|
|
@@ -21165,6 +21387,18 @@ function collectUnmappedForKind(kind, limit) {
|
|
|
21165
21387
|
return Array.from(byId.values());
|
|
21166
21388
|
}
|
|
21167
21389
|
async function handleUsers(req, res, pathSegments, queryParams) {
|
|
21390
|
+
if (whoamiRoute.match(req.method, pathSegments)) {
|
|
21391
|
+
const parsed = await whoamiRoute.parse(req, res, pathSegments, queryParams);
|
|
21392
|
+
if (!parsed)
|
|
21393
|
+
return true;
|
|
21394
|
+
const auth = getRequestAuth(req);
|
|
21395
|
+
if (auth?.kind === "user") {
|
|
21396
|
+
whoamiRoute.respond(res, 200, { kind: "user", user: auth.user });
|
|
21397
|
+
} else {
|
|
21398
|
+
whoamiRoute.respond(res, 200, { kind: "operator", user: null });
|
|
21399
|
+
}
|
|
21400
|
+
return true;
|
|
21401
|
+
}
|
|
21168
21402
|
if (listUsers.match(req.method, pathSegments)) {
|
|
21169
21403
|
const parsed = await listUsers.parse(req, res, pathSegments, queryParams);
|
|
21170
21404
|
if (!parsed)
|
|
@@ -23077,6 +23311,7 @@ async function handleX(req, res, pathSegments) {
|
|
|
23077
23311
|
}
|
|
23078
23312
|
const timeoutMs = resolveTimeoutMs(req);
|
|
23079
23313
|
const startedAt = new Date().toISOString();
|
|
23314
|
+
const runStartTouch = script.isScratch ? touchScratchScriptLastUsed(script.id) : null;
|
|
23080
23315
|
const credentials = await buildScriptCredentialBindingsWithFailures({
|
|
23081
23316
|
agentId: endpoint.agentId
|
|
23082
23317
|
});
|
|
@@ -23093,6 +23328,11 @@ async function handleX(req, res, pathSegments) {
|
|
|
23093
23328
|
});
|
|
23094
23329
|
const ok = output.exitCode === 0 && !output.error && !output.runtimeError;
|
|
23095
23330
|
const error = ok ? null : buildExecutionError(output);
|
|
23331
|
+
if (ok) {
|
|
23332
|
+
touchScratchScriptLastUsed(script.id);
|
|
23333
|
+
} else if (script.isScratch && runStartTouch) {
|
|
23334
|
+
restoreScratchScriptLastUsedIfUnchanged(script.id, script.updatedAt, runStartTouch);
|
|
23335
|
+
}
|
|
23096
23336
|
try {
|
|
23097
23337
|
recordScriptApiUsage(endpointId);
|
|
23098
23338
|
} catch {}
|
|
@@ -23345,18 +23585,19 @@ async function shutdown() {
|
|
|
23345
23585
|
sessionsProcessed: getServerSessionsProcessed()
|
|
23346
23586
|
});
|
|
23347
23587
|
if (hasCapability("scheduling")) {
|
|
23348
|
-
const { stopScheduler } = await import("./index-
|
|
23588
|
+
const { stopScheduler } = await import("./index-25wjsdv2.js");
|
|
23349
23589
|
stopScheduler();
|
|
23350
23590
|
}
|
|
23351
23591
|
stopHeartbeat();
|
|
23352
23592
|
stopScriptRunSupervisor();
|
|
23353
23593
|
await stopSlackApp();
|
|
23354
23594
|
if (process.env.OAUTH_KEEPALIVE_DISABLE !== "true") {
|
|
23355
|
-
const { stopOAuthKeepalive } = await import("./keepalive-
|
|
23595
|
+
const { stopOAuthKeepalive } = await import("./keepalive-vc7s2aa6.js");
|
|
23356
23596
|
await stopOAuthKeepalive();
|
|
23357
23597
|
}
|
|
23358
23598
|
stopOAuthPendingGc();
|
|
23359
23599
|
stopMemoryGc();
|
|
23600
|
+
stopScratchScriptGc();
|
|
23360
23601
|
stopAuditGc();
|
|
23361
23602
|
stopAuditWriter();
|
|
23362
23603
|
flushAuditBuffer();
|
|
@@ -23414,15 +23655,15 @@ try {
|
|
|
23414
23655
|
console.warn("[startup] CAPABILITIES upgrade seed failed (non-fatal):", err);
|
|
23415
23656
|
}
|
|
23416
23657
|
try {
|
|
23417
|
-
const { seedPricingFromModelsDev } = await import("./seed-pricing-
|
|
23658
|
+
const { seedPricingFromModelsDev } = await import("./seed-pricing-8kceb43f.js");
|
|
23418
23659
|
seedPricingFromModelsDev();
|
|
23419
|
-
const { startPricingRefreshLoop } = await import("./pricing-refresh-
|
|
23660
|
+
const { startPricingRefreshLoop } = await import("./pricing-refresh-2cn6effr.js");
|
|
23420
23661
|
startPricingRefreshLoop();
|
|
23421
23662
|
} catch (err) {
|
|
23422
23663
|
console.error("[startup] Failed to seed pricing rows:", err);
|
|
23423
23664
|
}
|
|
23424
23665
|
try {
|
|
23425
|
-
const { ensureRbacSeedsSynced } = await import("./rbac-roles-
|
|
23666
|
+
const { ensureRbacSeedsSynced } = await import("./rbac-roles-vynday5g.js");
|
|
23426
23667
|
ensureRbacSeedsSynced();
|
|
23427
23668
|
} catch (err) {
|
|
23428
23669
|
console.error("[startup] Failed to sync RBAC seed rows:", err);
|
|
@@ -23430,7 +23671,7 @@ try {
|
|
|
23430
23671
|
throw err;
|
|
23431
23672
|
}
|
|
23432
23673
|
try {
|
|
23433
|
-
const { runAllSeeders } = await import("./index-
|
|
23674
|
+
const { runAllSeeders } = await import("./index-eaxyqcmj.js");
|
|
23434
23675
|
await runAllSeeders({ scriptEmbeddingMode: "skip" });
|
|
23435
23676
|
} catch (err) {
|
|
23436
23677
|
console.error("[startup] Failed to seed built-in entities:", err);
|
|
@@ -23438,6 +23679,7 @@ try {
|
|
|
23438
23679
|
setAuditSink(enqueueAuditRow);
|
|
23439
23680
|
startAuditWriter();
|
|
23440
23681
|
startAuditGc();
|
|
23682
|
+
startScratchScriptGc();
|
|
23441
23683
|
initialize();
|
|
23442
23684
|
await initOtel("api");
|
|
23443
23685
|
httpServer.listen(port, async () => {
|
|
@@ -23466,35 +23708,35 @@ httpServer.listen(port, async () => {
|
|
|
23466
23708
|
initWorkflows();
|
|
23467
23709
|
startScriptRunSupervisor(getMcpBaseUrl());
|
|
23468
23710
|
if (hasCapability("scheduling")) {
|
|
23469
|
-
const { startScheduler } = await import("./index-
|
|
23470
|
-
const { getExecutorRegistry: getExecutorRegistry2 } = await import("./index-
|
|
23711
|
+
const { startScheduler } = await import("./index-25wjsdv2.js");
|
|
23712
|
+
const { getExecutorRegistry: getExecutorRegistry2 } = await import("./index-ywds4812.js");
|
|
23471
23713
|
const intervalMs = Number(process.env.SCHEDULER_INTERVAL_MS) || 1e4;
|
|
23472
23714
|
startScheduler(getExecutorRegistry2(), intervalMs, {
|
|
23473
23715
|
runId: globalState.__runId
|
|
23474
23716
|
});
|
|
23475
23717
|
}
|
|
23476
23718
|
if (!isEnvFlagEnabled("HEARTBEAT_DISABLE", false)) {
|
|
23477
|
-
const { startHeartbeat } = await import("./index-
|
|
23719
|
+
const { startHeartbeat } = await import("./index-vg4snay4.js");
|
|
23478
23720
|
const heartbeatMs = Number(process.env.HEARTBEAT_INTERVAL_MS) || 90000;
|
|
23479
23721
|
startHeartbeat(heartbeatMs);
|
|
23480
23722
|
}
|
|
23481
23723
|
if (process.env.OAUTH_KEEPALIVE_DISABLE !== "true") {
|
|
23482
|
-
const { startOAuthKeepalive } = await import("./keepalive-
|
|
23724
|
+
const { startOAuthKeepalive } = await import("./keepalive-vc7s2aa6.js");
|
|
23483
23725
|
startOAuthKeepalive();
|
|
23484
23726
|
}
|
|
23485
23727
|
if (process.env.OAUTH_REFRESH_SWEEP_DISABLE !== "true") {
|
|
23486
|
-
const { startOAuthRefreshSweep } = await import("./oauth-refresh-sweep-
|
|
23728
|
+
const { startOAuthRefreshSweep } = await import("./oauth-refresh-sweep-yecgjpk4.js");
|
|
23487
23729
|
startOAuthRefreshSweep();
|
|
23488
23730
|
}
|
|
23489
23731
|
startOAuthPendingGc();
|
|
23490
23732
|
startMemoryGc();
|
|
23491
|
-
import("./boot-reembed-
|
|
23733
|
+
import("./boot-reembed-q7mp8hcr.js").then(({ runBootReembed }) => runBootReembed()).catch((err) => {
|
|
23492
23734
|
console.error("[boot-reembed] startup backfill failed (non-fatal):", err);
|
|
23493
23735
|
});
|
|
23494
|
-
import("./boot-reembed-
|
|
23736
|
+
import("./boot-reembed-xmw8wcx6.js").then(({ runBootReembedScripts }) => runBootReembedScripts()).catch((err) => {
|
|
23495
23737
|
console.error("[boot-reembed-scripts] startup backfill failed (non-fatal):", err);
|
|
23496
23738
|
});
|
|
23497
|
-
import("./boot-scrub-logs-
|
|
23739
|
+
import("./boot-scrub-logs-dsqrv79n.js").then(({ runBootScrubLogs }) => runBootScrubLogs()).catch((err) => {
|
|
23498
23740
|
console.error("[boot-scrub-logs] startup scrub failed (non-fatal):", err);
|
|
23499
23741
|
});
|
|
23500
23742
|
}).on("error", (err) => {
|