@desplega.ai/agent-swarm 1.104.0 → 1.106.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.
- package/README.md +2 -0
- package/dist/{actions-2expzt47.js → actions-pk6xqa2y.js} +6 -6
- package/dist/{anthropic-messages-8q7p5vyq.js → anthropic-messages-8nc6r2dw.js} +10 -4
- package/dist/{app-dr8hwx7z.js → app-pmfvefkh.js} +3 -3
- package/dist/{assistant-9rhgsw7v.js → assistant-wcjpqxk6.js} +9 -9
- package/dist/{azure-openai-responses-0dmr2hzc.js → azure-openai-responses-6yfzw3qw.js} +10 -18
- package/dist/{boot-reembed-9kt97g1z.js → boot-reembed-atv4kcrh.js} +3 -3
- package/dist/{boot-reembed-3q1aywnz.js → boot-reembed-zanbm36c.js} +4 -4
- package/dist/{boot-scrub-logs-vskq108e.js → boot-scrub-logs-asq051ff.js} +2 -2
- package/dist/{claude-adapter-e3dhkq85.js → claude-adapter-w96mzan4.js} +2 -2
- package/dist/{claude-managed-adapter-z29hjgzz.js → claude-managed-adapter-vj9kzegz.js} +4 -4
- package/dist/{claude-managed-setup-ftbmvmvx.js → claude-managed-setup-t0wkvzgz.js} +1 -1
- package/dist/{cli-92fqyjcv.js → cli-07er7wrs.js} +1 -1
- package/dist/{cli-y9p3e94h.js → cli-08fnz4jm.js} +3 -3
- package/dist/{cli-yjt8a36k.js → cli-39jaysbv.js} +8 -6
- package/dist/{cli-5pf0b84v.js → cli-4fwzc50f.js} +2 -2
- package/dist/{cli-p03mawph.js → cli-50nss8e8.js} +928 -335
- package/dist/{cli-e7bwjntj.js → cli-6hqvenfv.js} +1 -1
- package/dist/{cli-0jw6j755.js → cli-6xn2xv4r.js} +24 -8
- package/dist/{cli-2g9jf9ek.js → cli-842gfjn1.js} +1 -1
- package/dist/{cli-v1syqkcb.js → cli-84gyjn6h.js} +146 -3
- package/dist/{cli-7b9ctyfq.js → cli-8da61htc.js} +1 -1
- package/dist/{cli-nzc0h54v.js → cli-8fhhmzbh.js} +1 -1
- package/dist/{cli-khe4x17a.js → cli-anrn8brw.js} +3 -3
- package/dist/{cli-2q1ct4en.js → cli-bsyka9ta.js} +104 -3
- package/dist/{cli-p04j6hjv.js → cli-dqhz8451.js} +1 -1
- package/dist/{cli-s42f54ja.js → cli-f7ypwjgh.js} +1 -1
- package/dist/{cli-p4cj4vhc.js → cli-hmqkes02.js} +1 -1
- package/dist/{cli-23zk7xqy.js → cli-j1172z85.js} +26 -18
- package/dist/{cli-yp2krx5r.js → cli-jk4tj5m6.js} +9 -3
- package/dist/{cli-q5tshxd6.js → cli-k7gt5r0p.js} +1 -1
- package/dist/{cli-54h5daha.js → cli-n38fcvhe.js} +6 -6
- package/dist/{cli-2hap19dv.js → cli-p7hff99g.js} +3 -3
- package/dist/cli-pscrc6tw.js +73 -0
- package/dist/{cli-yvektv79.js → cli-pxddwmyc.js} +1 -1
- package/dist/{cli-ncg70f07.js → cli-q44nxhwq.js} +1 -1
- package/dist/{cli-d4z1csms.js → cli-qtr61agf.js} +3 -3
- package/dist/{cli-zaxksbgj.js → cli-rp5kaak8.js} +5 -5
- package/dist/{cli-0fxvpa2q.js → cli-sdpnhajn.js} +150 -163
- package/dist/{cli-w1nfskkg.js → cli-sp3c9fwf.js} +2 -2
- package/dist/{cli-gj2n2ec1.js → cli-tfcrm7ds.js} +1 -1
- package/dist/{cli-0k9dc6ks.js → cli-tghre7g6.js} +1 -0
- package/dist/{cli-qvzgncd8.js → cli-v90vvqt8.js} +401 -125
- package/dist/{cli-zghef0em.js → cli-v9853xza.js} +1 -1
- package/dist/{cli-t9v14cnd.js → cli-wfhe4tgs.js} +1 -1
- package/dist/{cli-7v4y3hyd.js → cli-xgssgdqn.js} +2 -2
- package/dist/{cli-etvgz5x8.js → cli-xvs40j7w.js} +4 -4
- package/dist/{cli-jntqphs0.js → cli-ygcrdkqt.js} +15 -9
- package/dist/{cli-2957pqpj.js → cli-yv9dttkh.js} +32 -9
- package/dist/cli.js +20 -17
- package/dist/{codex-adapter-w0xharsg.js → codex-adapter-h9rj59tj.js} +5 -5
- package/dist/{codex-session-runner-kzbjcm2k.js → codex-session-runner-2ybavr0w.js} +5 -5
- package/dist/{commands-wfrkef57.js → commands-075ak6vf.js} +2 -2
- package/dist/{db-c42pxt7h.js → db-60fj8j7t.js} +2 -2
- package/dist/{google-generative-ai-mdn340ga.js → google-generative-ai-rf42vj2h.js} +9 -4
- package/dist/{google-vertex-mkdewpwe.js → google-vertex-m92pj5fb.js} +9 -4
- package/dist/{handlers-n36zkfvx.js → handlers-96j9z4gk.js} +9 -9
- package/dist/{hook-gw3vhv6s.js → hook-f58wyvmy.js} +3 -3
- package/dist/{http-59ygpn2h.js → http-naqhj1n0.js} +579 -52
- package/dist/{index-xf6fp4y1.js → index-45bqm6xc.js} +5 -5
- package/dist/{index-xz8vaa5c.js → index-f5e873a5.js} +10 -10
- package/dist/{index-jca7jdpt.js → index-jscerv2x.js} +10 -6
- package/dist/{index-881c1baf.js → index-v3r40ak0.js} +8 -8
- package/dist/{keepalive-mj4302vw.js → keepalive-8gbgeg21.js} +4 -4
- package/dist/{lead-qm0xjvkv.js → lead-hj6stakm.js} +26 -26
- package/dist/{maintenance-xppxbe4t.js → maintenance-1nvd0jva.js} +4 -4
- package/dist/{mistral-conversations-j380wd2q.js → mistral-conversations-26yrnbf1.js} +2 -2
- package/dist/{onboard-ejx6yxh8.js → onboard-8myqe0jh.js} +2 -2
- package/dist/{openai-codex-responses-v80z7kgx.js → openai-codex-responses-8h6kvfv8.js} +16 -25
- package/dist/{openai-completions-39vefwrq.js → openai-completions-x6kjnqjd.js} +11 -5
- package/dist/{openai-responses-dp5bkm3q.js → openai-responses-7jwyz3ds.js} +8 -16
- package/dist/{opencode-adapter-s8vsmzpy.js → opencode-adapter-p2w6efwc.js} +2 -2
- package/dist/{openrouter-images-54cva05t.js → openrouter-images-537nmn1r.js} +5 -1
- package/dist/{otel-impl-zs5exkpk.js → otel-impl-tddx9x81.js} +4510 -4465
- package/dist/{pi-mono-adapter-zf7dt1wg.js → pi-mono-adapter-y037wnp4.js} +596 -297
- package/dist/{pricing-refresh-nqyf8bkb.js → pricing-refresh-f6cgj5br.js} +4 -4
- package/dist/{seed-pricing-w3x550cj.js → seed-pricing-3tqmbe0p.js} +3 -3
- package/dist/{setup-7729ktfj.js → setup-tq3ept9k.js} +2 -2
- package/dist/{worker-4ttemwhw.js → worker-526psbtb.js} +26 -26
- package/openapi.json +315 -1
- package/package.json +8 -6
- package/src/be/db.ts +6 -2
- package/src/be/memory/access.ts +5 -0
- package/src/be/migrations/102_script_apis.sql +31 -0
- package/src/be/modelsdev-cache.json +22170 -7247
- package/src/be/scripts/db.ts +214 -1
- package/src/be/seed-pricing.ts +1 -1
- package/src/commands/claude-managed-setup.ts +1 -1
- package/src/hooks/tool-loop-detection.test.ts +81 -1
- package/src/hooks/tool-loop-detection.ts +53 -10
- package/src/http/index.ts +11 -1
- package/src/http/mcp.ts +49 -0
- package/src/http/memory.ts +21 -11
- package/src/http/pages-public.ts +123 -2
- package/src/http/scripts.ts +213 -0
- package/src/http/session-data.ts +16 -0
- package/src/http/x.ts +244 -0
- package/src/otel-impl.ts +73 -0
- package/src/otel.ts +12 -0
- package/src/prompts/session-templates.ts +5 -1
- package/src/providers/claude-managed-models.ts +9 -0
- package/src/server.ts +2 -0
- package/src/tests/agents-list-model-display.test.ts +5 -0
- package/src/tests/bedrock-model-groups.test.ts +3 -0
- package/src/tests/claude-managed-adapter.test.ts +14 -0
- package/src/tests/claude-managed-setup.test.ts +3 -3
- package/src/tests/context-window.test.ts +1 -0
- package/src/tests/harness-provider-resolution.test.ts +39 -0
- package/src/tests/http-api-integration.test.ts +1 -1
- package/src/tests/mcp-user-route.test.ts +70 -5
- package/src/tests/memory-get-tool.test.ts +132 -0
- package/src/tests/memory-http-recall-gating.test.ts +17 -1
- package/src/tests/migration-046-budgets.test.ts +32 -0
- package/src/tests/otel-impl-secret-scrubbing.test.ts +101 -3
- package/src/tests/otel-session-cost-metrics.test.ts +281 -0
- package/src/tests/pages-authed-mode.test.ts +50 -0
- package/src/tests/preload.ts +26 -0
- package/src/tests/register-service-security.test.ts +194 -0
- package/src/tests/script-apis-mcp.test.ts +308 -0
- package/src/tests/scripts-external-api.test.ts +449 -0
- package/src/tests/session-costs-model-key-normalize.test.ts +1 -0
- package/src/tests/update-profile-auth.test.ts +35 -1
- package/src/tools/memory-get.ts +17 -2
- package/src/tools/register-service.ts +68 -4
- package/src/tools/script-apis.ts +158 -0
- package/src/tools/script-common.ts +1 -1
- package/src/tools/tool-config.ts +2 -1
- package/src/tools/update-profile.ts +84 -1
- package/src/types.ts +27 -1
- package/src/utils/context-window.ts +1 -0
- package/src/utils/harness-provider.ts +35 -6
- package/src/utils/short-id.ts +44 -0
- package/templates/community/code-health-reports/run.sh +12 -6
- package/templates/community/dora-metrics/run.sh +10 -2
- package/templates/official/coder/start-up.sh +2 -2
- package/templates/official/content-reviewer/start-up.sh +2 -2
- package/templates/official/content-strategist/start-up.sh +2 -2
- package/templates/official/content-writer/start-up.sh +2 -2
- package/templates/official/discoverability-optimizer/start-up.sh +2 -2
- package/templates/official/ux-principles/start-up.sh +5 -5
- package/templates/skills/swarm-scripts/SKILL.md +4 -0
- package/templates/skills/swarm-scripts/content.md +4 -0
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
applyRating,
|
|
10
10
|
assertSelectOnlyQuery,
|
|
11
11
|
canClaim,
|
|
12
|
+
canReadMemory,
|
|
12
13
|
cancelTaskHandler,
|
|
13
14
|
cancelTaskInputSchema,
|
|
14
15
|
cancelTaskOutputSchema,
|
|
@@ -79,6 +80,7 @@ import {
|
|
|
79
80
|
parseQueryParams,
|
|
80
81
|
parseSkillContent,
|
|
81
82
|
recordRetrievals,
|
|
83
|
+
recordSessionCost,
|
|
82
84
|
registerJiraWebhook,
|
|
83
85
|
reloadGlobalConfigsAndIntegrations,
|
|
84
86
|
resolveHttpAuditUserId,
|
|
@@ -106,7 +108,7 @@ import {
|
|
|
106
108
|
withRemoteContext,
|
|
107
109
|
withSpanContext,
|
|
108
110
|
writeSkillsToFilesystem
|
|
109
|
-
} from "./cli-
|
|
111
|
+
} from "./cli-v90vvqt8.js";
|
|
110
112
|
import {
|
|
111
113
|
BROWSER_SDK_JS,
|
|
112
114
|
SWARM_UI_JS
|
|
@@ -129,27 +131,27 @@ import {
|
|
|
129
131
|
generateRandomState,
|
|
130
132
|
getOAuthApp,
|
|
131
133
|
getOAuthTokens
|
|
132
|
-
} from "./cli-
|
|
133
|
-
import"./cli-
|
|
134
|
+
} from "./cli-842gfjn1.js";
|
|
135
|
+
import"./cli-sp3c9fwf.js";
|
|
134
136
|
import {
|
|
135
137
|
normalizeModelKey
|
|
136
|
-
} from "./cli-
|
|
138
|
+
} from "./cli-xgssgdqn.js";
|
|
137
139
|
import {
|
|
138
140
|
SCRIPT_STDLIB_TYPES,
|
|
139
141
|
extractArgsJsonSchema,
|
|
140
142
|
extractScriptSignature,
|
|
141
143
|
scriptSdkTypesWithGeneratedApis,
|
|
142
144
|
typecheckScript
|
|
143
|
-
} from "./cli-
|
|
145
|
+
} from "./cli-wfhe4tgs.js";
|
|
144
146
|
import {
|
|
145
147
|
checkHeartbeatChecklist,
|
|
146
148
|
runHeartbeatSweep,
|
|
147
149
|
stopHeartbeat
|
|
148
|
-
} from "./cli-
|
|
150
|
+
} from "./cli-qtr61agf.js";
|
|
149
151
|
import {
|
|
150
152
|
createResumeFollowUp,
|
|
151
153
|
createWorkerTaskFollowUp
|
|
152
|
-
} from "./cli-
|
|
154
|
+
} from "./cli-f7ypwjgh.js";
|
|
153
155
|
import {
|
|
154
156
|
RawLlmConfigSchema,
|
|
155
157
|
buildScriptCredentialBindings,
|
|
@@ -160,23 +162,31 @@ import {
|
|
|
160
162
|
retryFailedRun,
|
|
161
163
|
runScript,
|
|
162
164
|
snapshotWorkflow
|
|
163
|
-
} from "./cli-
|
|
165
|
+
} from "./cli-n38fcvhe.js";
|
|
164
166
|
import {
|
|
165
167
|
getApiKey
|
|
166
168
|
} from "./cli-f14fvzag.js";
|
|
167
169
|
import {
|
|
170
|
+
createScriptApi,
|
|
168
171
|
deleteScript,
|
|
172
|
+
deleteScriptApi,
|
|
169
173
|
getScript,
|
|
174
|
+
getScriptApiById,
|
|
170
175
|
getScriptApiConnectionDescriptors,
|
|
176
|
+
getScriptApiSecret,
|
|
171
177
|
getScriptApiTypes,
|
|
172
178
|
getScriptById,
|
|
179
|
+
listScriptApisForScript,
|
|
173
180
|
listScriptVersions,
|
|
174
181
|
listScripts,
|
|
182
|
+
recordScriptApiUsage,
|
|
183
|
+
rotateScriptApiSecret,
|
|
184
|
+
updateScriptApi,
|
|
175
185
|
upsertScriptByName
|
|
176
|
-
} from "./cli-
|
|
186
|
+
} from "./cli-84gyjn6h.js";
|
|
177
187
|
import {
|
|
178
188
|
searchScripts
|
|
179
|
-
} from "./cli-
|
|
189
|
+
} from "./cli-4fwzc50f.js";
|
|
180
190
|
import {
|
|
181
191
|
CANDIDATE_SET_MULTIPLIER,
|
|
182
192
|
getEmbeddingProvider,
|
|
@@ -184,7 +194,7 @@ import {
|
|
|
184
194
|
init_constants,
|
|
185
195
|
init_reranker,
|
|
186
196
|
rerank
|
|
187
|
-
} from "./cli-
|
|
197
|
+
} from "./cli-hmqkes02.js";
|
|
188
198
|
import"./cli-3j01d33e.js";
|
|
189
199
|
import"./cli-fad8m16k.js";
|
|
190
200
|
import {
|
|
@@ -193,7 +203,7 @@ import {
|
|
|
193
203
|
ensure,
|
|
194
204
|
initialize,
|
|
195
205
|
require_dist
|
|
196
|
-
} from "./cli-
|
|
206
|
+
} from "./cli-08fnz4jm.js";
|
|
197
207
|
import {
|
|
198
208
|
TriggerSchemaError,
|
|
199
209
|
WebhookError,
|
|
@@ -205,18 +215,18 @@ import {
|
|
|
205
215
|
validateDefinition,
|
|
206
216
|
validateJsonSchema,
|
|
207
217
|
verifyHmacSignature
|
|
208
|
-
} from "./cli-
|
|
209
|
-
import"./cli-
|
|
218
|
+
} from "./cli-v9853xza.js";
|
|
219
|
+
import"./cli-8fhhmzbh.js";
|
|
210
220
|
import {
|
|
211
221
|
getSlackApp,
|
|
212
222
|
startSlackApp,
|
|
213
223
|
stopSlackApp
|
|
214
|
-
} from "./cli-
|
|
224
|
+
} from "./cli-rp5kaak8.js";
|
|
215
225
|
import"./cli-fete3y1e.js";
|
|
216
226
|
import"./cli-b0p7rfnd.js";
|
|
217
227
|
import {
|
|
218
228
|
recordUnmappedIdentity
|
|
219
|
-
} from "./cli-
|
|
229
|
+
} from "./cli-tfcrm7ds.js";
|
|
220
230
|
import {
|
|
221
231
|
findOrCreateUserByEmail,
|
|
222
232
|
findUserByExternalId,
|
|
@@ -230,7 +240,7 @@ import {
|
|
|
230
240
|
resolveUserByToken,
|
|
231
241
|
revokeToken,
|
|
232
242
|
unlinkIdentity
|
|
233
|
-
} from "./cli-
|
|
243
|
+
} from "./cli-pxddwmyc.js";
|
|
234
244
|
import"./cli-z92pkwzn.js";
|
|
235
245
|
import {
|
|
236
246
|
getAppUrl,
|
|
@@ -243,7 +253,7 @@ import {
|
|
|
243
253
|
createTaskWithSiblingAwareness,
|
|
244
254
|
gitlabContextKey,
|
|
245
255
|
pageContextKey
|
|
246
|
-
} from "./cli-
|
|
256
|
+
} from "./cli-6hqvenfv.js";
|
|
247
257
|
import {
|
|
248
258
|
AgentCredStatusSchema,
|
|
249
259
|
AgentLatestModelSchema,
|
|
@@ -280,6 +290,7 @@ import {
|
|
|
280
290
|
RepoGuidelinesSchema,
|
|
281
291
|
RepoHooksSchema,
|
|
282
292
|
ResumeReasonSchema,
|
|
293
|
+
ScriptApiAuthModeSchema,
|
|
283
294
|
ScriptFsModeSchema,
|
|
284
295
|
ScriptRunStatusSchema,
|
|
285
296
|
ScriptScopeSchema,
|
|
@@ -536,7 +547,7 @@ import {
|
|
|
536
547
|
upsertSkillFiles,
|
|
537
548
|
upsertSwarmConfig,
|
|
538
549
|
validateConfigValue
|
|
539
|
-
} from "./cli-
|
|
550
|
+
} from "./cli-6xn2xv4r.js";
|
|
540
551
|
import"./cli-z2zcxes1.js";
|
|
541
552
|
import {
|
|
542
553
|
init_zod
|
|
@@ -551,7 +562,7 @@ import {
|
|
|
551
562
|
import {
|
|
552
563
|
init_package,
|
|
553
564
|
package_default
|
|
554
|
-
} from "./cli-
|
|
565
|
+
} from "./cli-39jaysbv.js";
|
|
555
566
|
import {
|
|
556
567
|
init_secret_scrubber,
|
|
557
568
|
registerVolatileSecret,
|
|
@@ -565,17 +576,18 @@ import {
|
|
|
565
576
|
} from "./cli-9aryf9tv.js";
|
|
566
577
|
import {
|
|
567
578
|
bedrockProviderModule
|
|
568
|
-
} from "./cli-
|
|
579
|
+
} from "./cli-ygcrdkqt.js";
|
|
569
580
|
import"./cli-jvv0g8bh.js";
|
|
570
581
|
import {
|
|
571
582
|
setBedrockProviderModule
|
|
572
583
|
} from "./cli-xw7p4wkq.js";
|
|
573
584
|
import"./cli-6kqcg4zv.js";
|
|
574
585
|
import"./cli-cwy5hqbq.js";
|
|
586
|
+
import"./cli-pscrc6tw.js";
|
|
575
587
|
import"./cli-4wgngmwv.js";
|
|
576
588
|
import"./cli-vapyk8sw.js";
|
|
577
589
|
import"./cli-zyxs93y9.js";
|
|
578
|
-
import"./cli-
|
|
590
|
+
import"./cli-bsyka9ta.js";
|
|
579
591
|
import"./cli-y2apkfe2.js";
|
|
580
592
|
import"./cli-m6pzzhqr.js";
|
|
581
593
|
import"./cli-7sgrxg9a.js";
|
|
@@ -5071,6 +5083,7 @@ class StreamableHTTPServerTransport {
|
|
|
5071
5083
|
}
|
|
5072
5084
|
|
|
5073
5085
|
// src/http/mcp.ts
|
|
5086
|
+
init_db();
|
|
5074
5087
|
var DEFAULT_MCP_TRANSPORT_IDLE_TIMEOUT_MS = 2 * 60 * 60 * 1000;
|
|
5075
5088
|
function markMcpTransportActivity(sessionActivity, sessionId, now = Date.now()) {
|
|
5076
5089
|
if (sessionId) {
|
|
@@ -5102,11 +5115,45 @@ function closeIdleMcpTransports(transports, sessionActivity, options = {}) {
|
|
|
5102
5115
|
}
|
|
5103
5116
|
return closed;
|
|
5104
5117
|
}
|
|
5105
|
-
|
|
5118
|
+
function unauthorized(res, message = "Unauthorized") {
|
|
5119
|
+
res.writeHead(401, { "Content-Type": "application/json" });
|
|
5120
|
+
res.end(JSON.stringify({ error: message }));
|
|
5121
|
+
return true;
|
|
5122
|
+
}
|
|
5123
|
+
function headerValue(value) {
|
|
5124
|
+
return Array.isArray(value) ? value[0] : value;
|
|
5125
|
+
}
|
|
5126
|
+
function requireKnownAgent(req, res) {
|
|
5127
|
+
const agentId = headerValue(req.headers["x-agent-id"]);
|
|
5128
|
+
if (!agentId)
|
|
5129
|
+
return unauthorized(res, "Missing X-Agent-ID header");
|
|
5130
|
+
if (!getAgentById(agentId))
|
|
5131
|
+
return unauthorized(res, "Agent not found");
|
|
5132
|
+
return agentId;
|
|
5133
|
+
}
|
|
5134
|
+
function validateBoundAgent(req, res, sessionId, sessionAgents) {
|
|
5135
|
+
if (!sessionId)
|
|
5136
|
+
return;
|
|
5137
|
+
const boundAgentId = sessionAgents[sessionId];
|
|
5138
|
+
if (!boundAgentId)
|
|
5139
|
+
return;
|
|
5140
|
+
const agentId = headerValue(req.headers["x-agent-id"]);
|
|
5141
|
+
if (!agentId) {
|
|
5142
|
+
return unauthorized(res, "Missing X-Agent-ID header");
|
|
5143
|
+
}
|
|
5144
|
+
if (agentId !== boundAgentId) {
|
|
5145
|
+
return unauthorized(res, "X-Agent-ID does not match MCP session");
|
|
5146
|
+
}
|
|
5147
|
+
return;
|
|
5148
|
+
}
|
|
5149
|
+
async function handleMcp(req, res, transports, sessionActivity = {}, sessionAgents = {}) {
|
|
5106
5150
|
const sessionId = req.headers["mcp-session-id"];
|
|
5107
5151
|
if (req.url !== "/mcp") {
|
|
5108
5152
|
return false;
|
|
5109
5153
|
}
|
|
5154
|
+
const agentMismatch = validateBoundAgent(req, res, sessionId, sessionAgents);
|
|
5155
|
+
if (agentMismatch)
|
|
5156
|
+
return true;
|
|
5110
5157
|
if (req.method === "POST") {
|
|
5111
5158
|
const chunks = [];
|
|
5112
5159
|
for await (const chunk of req) {
|
|
@@ -5118,20 +5165,26 @@ async function handleMcp(req, res, transports, sessionActivity = {}) {
|
|
|
5118
5165
|
transport = transports[sessionId];
|
|
5119
5166
|
markMcpTransportActivity(sessionActivity, sessionId);
|
|
5120
5167
|
} else if (!sessionId && isInitializeRequest(body)) {
|
|
5168
|
+
const agentId = requireKnownAgent(req, res);
|
|
5169
|
+
if (agentId === true)
|
|
5170
|
+
return true;
|
|
5121
5171
|
transport = new StreamableHTTPServerTransport({
|
|
5122
5172
|
sessionIdGenerator: () => randomUUID(),
|
|
5123
5173
|
onsessioninitialized: (id) => {
|
|
5124
5174
|
transports[id] = transport;
|
|
5175
|
+
sessionAgents[id] = agentId;
|
|
5125
5176
|
markMcpTransportActivity(sessionActivity, id);
|
|
5126
5177
|
},
|
|
5127
5178
|
onsessionclosed: (id) => {
|
|
5128
5179
|
delete transports[id];
|
|
5180
|
+
delete sessionAgents[id];
|
|
5129
5181
|
delete sessionActivity[id];
|
|
5130
5182
|
}
|
|
5131
5183
|
});
|
|
5132
5184
|
transport.onclose = () => {
|
|
5133
5185
|
if (transport.sessionId) {
|
|
5134
5186
|
delete transports[transport.sessionId];
|
|
5187
|
+
delete sessionAgents[transport.sessionId];
|
|
5135
5188
|
delete sessionActivity[transport.sessionId];
|
|
5136
5189
|
}
|
|
5137
5190
|
};
|
|
@@ -6824,7 +6877,7 @@ function createUserServer(user) {
|
|
|
6824
6877
|
}
|
|
6825
6878
|
|
|
6826
6879
|
// src/http/mcp-user.ts
|
|
6827
|
-
function
|
|
6880
|
+
function unauthorized2(res) {
|
|
6828
6881
|
res.writeHead(401, { "Content-Type": "application/json" });
|
|
6829
6882
|
res.end(JSON.stringify({ error: "Unauthorized" }));
|
|
6830
6883
|
return true;
|
|
@@ -6852,9 +6905,9 @@ async function handleMcpUser(req, res, transports, sessionUsers, sessionActivity
|
|
|
6852
6905
|
}
|
|
6853
6906
|
const user = resolveActiveUser(req);
|
|
6854
6907
|
if (!user)
|
|
6855
|
-
return
|
|
6908
|
+
return unauthorized2(res);
|
|
6856
6909
|
if (sessionId && transports[sessionId] && sessionUsers[sessionId] !== user.id) {
|
|
6857
|
-
return
|
|
6910
|
+
return unauthorized2(res);
|
|
6858
6911
|
}
|
|
6859
6912
|
if (req.method === "POST") {
|
|
6860
6913
|
const chunks = [];
|
|
@@ -7385,6 +7438,7 @@ async function handleMemory(req, res, pathSegments, myAgentId) {
|
|
|
7385
7438
|
persistMemory,
|
|
7386
7439
|
contextKey
|
|
7387
7440
|
} = parsed.body;
|
|
7441
|
+
const memoryAgentId = agentId ?? (scope === "agent" ? myAgentId : undefined);
|
|
7388
7442
|
if (source === "session_summary" && sourceTaskId) {
|
|
7389
7443
|
const sourceTask = getTaskById(sourceTaskId);
|
|
7390
7444
|
if (sourceTask && !shouldPersistAutomaticTaskMemory(sourceTask, persistMemory)) {
|
|
@@ -7403,11 +7457,11 @@ async function handleMemory(req, res, pathSegments, myAgentId) {
|
|
|
7403
7457
|
}
|
|
7404
7458
|
const store = getMemoryStore();
|
|
7405
7459
|
const provider = getEmbeddingProvider();
|
|
7406
|
-
if (sourcePath &&
|
|
7407
|
-
const existing = store.list(
|
|
7460
|
+
if (sourcePath && memoryAgentId && contentChunks.length === 1) {
|
|
7461
|
+
const existing = store.list(memoryAgentId, {
|
|
7408
7462
|
scope,
|
|
7409
7463
|
limit: 2,
|
|
7410
|
-
ownerAgentId:
|
|
7464
|
+
ownerAgentId: memoryAgentId,
|
|
7411
7465
|
sourcePath
|
|
7412
7466
|
}).filter((memory) => memory.sourcePath === sourcePath);
|
|
7413
7467
|
if (existing.length === 1 && existing[0]?.totalChunks === 1) {
|
|
@@ -7422,7 +7476,7 @@ async function handleMemory(req, res, pathSegments, myAgentId) {
|
|
|
7422
7476
|
if (embedding)
|
|
7423
7477
|
store.updateEmbedding(result.memory.id, embedding, provider.name);
|
|
7424
7478
|
try {
|
|
7425
|
-
storeLinks(result.memory.id,
|
|
7479
|
+
storeLinks(result.memory.id, memoryAgentId, result.memory.content);
|
|
7426
7480
|
} catch (err) {
|
|
7427
7481
|
console.error(`[memory] Link resolution failed for ${result.memory.id}:`, err.message);
|
|
7428
7482
|
}
|
|
@@ -7430,13 +7484,13 @@ async function handleMemory(req, res, pathSegments, myAgentId) {
|
|
|
7430
7484
|
return true;
|
|
7431
7485
|
}
|
|
7432
7486
|
}
|
|
7433
|
-
if (sourcePath &&
|
|
7434
|
-
store.deleteBySourcePath(sourcePath,
|
|
7487
|
+
if (sourcePath && memoryAgentId) {
|
|
7488
|
+
store.deleteBySourcePath(sourcePath, memoryAgentId);
|
|
7435
7489
|
}
|
|
7436
7490
|
const headerContextKey = req.headers["x-context-key"];
|
|
7437
7491
|
const resolvedContextKey = contextKey ?? (Array.isArray(headerContextKey) ? headerContextKey[0] : headerContextKey) ?? undefined;
|
|
7438
7492
|
const memories = store.storeBatch(contentChunks.map((chunk) => ({
|
|
7439
|
-
agentId:
|
|
7493
|
+
agentId: memoryAgentId || null,
|
|
7440
7494
|
content: chunk.content,
|
|
7441
7495
|
name,
|
|
7442
7496
|
scope,
|
|
@@ -7450,10 +7504,10 @@ async function handleMemory(req, res, pathSegments, myAgentId) {
|
|
|
7450
7504
|
intent: "index memory content",
|
|
7451
7505
|
key: sourcePath || null
|
|
7452
7506
|
})));
|
|
7453
|
-
if (
|
|
7507
|
+
if (memoryAgentId) {
|
|
7454
7508
|
for (const memory of memories) {
|
|
7455
7509
|
try {
|
|
7456
|
-
storeLinks(memory.id,
|
|
7510
|
+
storeLinks(memory.id, memoryAgentId, memory.content);
|
|
7457
7511
|
} catch (err) {
|
|
7458
7512
|
console.error(`[memory] Link resolution failed for ${memory.id}:`, err.message);
|
|
7459
7513
|
}
|
|
@@ -7819,11 +7873,17 @@ async function handleMemory(req, res, pathSegments, myAgentId) {
|
|
|
7819
7873
|
const parsed = await getMemoryById.parse(req, res, pathSegments, queryParams);
|
|
7820
7874
|
if (!parsed)
|
|
7821
7875
|
return true;
|
|
7822
|
-
const
|
|
7823
|
-
|
|
7876
|
+
const store = getMemoryStore();
|
|
7877
|
+
const memoryForAuth = store.peek(parsed.params.id);
|
|
7878
|
+
if (!memoryForAuth) {
|
|
7824
7879
|
jsonError(res, "Memory not found", 404);
|
|
7825
7880
|
return true;
|
|
7826
7881
|
}
|
|
7882
|
+
if (!canReadMemory(memoryForAuth, myAgentId)) {
|
|
7883
|
+
jsonError(res, "Not authorized", 403);
|
|
7884
|
+
return true;
|
|
7885
|
+
}
|
|
7886
|
+
const memory = store.get(parsed.params.id);
|
|
7827
7887
|
const { intent } = parsed.query;
|
|
7828
7888
|
const sourceTaskIdHeader = req.headers["x-source-task-id"];
|
|
7829
7889
|
const sourceTaskId = Array.isArray(sourceTaskIdHeader) ? sourceTaskIdHeader[0] : sourceTaskIdHeader;
|
|
@@ -9076,6 +9136,86 @@ function injectBrowserSdk(html) {
|
|
|
9076
9136
|
}
|
|
9077
9137
|
return injection + html;
|
|
9078
9138
|
}
|
|
9139
|
+
var PRINT_AUTOTRIGGER_SCRIPT = `<script>
|
|
9140
|
+
(function () {
|
|
9141
|
+
function print() { setTimeout(function () { window.print(); }, 400); }
|
|
9142
|
+
window.addEventListener("load", function () {
|
|
9143
|
+
var fonts = document.fonts;
|
|
9144
|
+
if (fonts && fonts.ready && typeof fonts.ready.then === "function") {
|
|
9145
|
+
fonts.ready.then(print, print);
|
|
9146
|
+
} else {
|
|
9147
|
+
print();
|
|
9148
|
+
}
|
|
9149
|
+
});
|
|
9150
|
+
})();
|
|
9151
|
+
</script>`;
|
|
9152
|
+
function escapeHtml(value) {
|
|
9153
|
+
return value.replace(/[&<>"']/g, (char) => {
|
|
9154
|
+
switch (char) {
|
|
9155
|
+
case "&":
|
|
9156
|
+
return "&";
|
|
9157
|
+
case "<":
|
|
9158
|
+
return "<";
|
|
9159
|
+
case ">":
|
|
9160
|
+
return ">";
|
|
9161
|
+
case '"':
|
|
9162
|
+
return """;
|
|
9163
|
+
default:
|
|
9164
|
+
return "'";
|
|
9165
|
+
}
|
|
9166
|
+
});
|
|
9167
|
+
}
|
|
9168
|
+
function printableJsonPageHtml(page) {
|
|
9169
|
+
let body = page.body;
|
|
9170
|
+
try {
|
|
9171
|
+
body = JSON.stringify(JSON.parse(page.body), null, 2);
|
|
9172
|
+
} catch {}
|
|
9173
|
+
const description = page.description ? `<p class="description">${escapeHtml(page.description)}</p>` : "";
|
|
9174
|
+
return `<!doctype html>
|
|
9175
|
+
<html>
|
|
9176
|
+
<head>
|
|
9177
|
+
<meta charset="utf-8">
|
|
9178
|
+
<title>${escapeHtml(page.title)}</title>
|
|
9179
|
+
<style>
|
|
9180
|
+
body {
|
|
9181
|
+
color: #111827;
|
|
9182
|
+
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
9183
|
+
line-height: 1.5;
|
|
9184
|
+
margin: 0;
|
|
9185
|
+
padding: 24px;
|
|
9186
|
+
}
|
|
9187
|
+
h1 {
|
|
9188
|
+
font-size: 24px;
|
|
9189
|
+
line-height: 1.2;
|
|
9190
|
+
margin: 0 0 8px;
|
|
9191
|
+
}
|
|
9192
|
+
.description {
|
|
9193
|
+
color: #4b5563;
|
|
9194
|
+
margin: 0 0 20px;
|
|
9195
|
+
}
|
|
9196
|
+
pre {
|
|
9197
|
+
background: #f8fafc;
|
|
9198
|
+
border: 1px solid #e5e7eb;
|
|
9199
|
+
border-radius: 6px;
|
|
9200
|
+
color: #111827;
|
|
9201
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
9202
|
+
font-size: 11px;
|
|
9203
|
+
line-height: 1.45;
|
|
9204
|
+
margin: 0;
|
|
9205
|
+
overflow-wrap: anywhere;
|
|
9206
|
+
padding: 16px;
|
|
9207
|
+
white-space: pre-wrap;
|
|
9208
|
+
}
|
|
9209
|
+
</style>
|
|
9210
|
+
</head>
|
|
9211
|
+
<body>
|
|
9212
|
+
<h1>${escapeHtml(page.title)}</h1>
|
|
9213
|
+
${description}
|
|
9214
|
+
<pre>${escapeHtml(body)}</pre>
|
|
9215
|
+
${PRINT_AUTOTRIGGER_SCRIPT}
|
|
9216
|
+
</body>
|
|
9217
|
+
</html>`;
|
|
9218
|
+
}
|
|
9079
9219
|
function stripJsonSuffix(idSegment) {
|
|
9080
9220
|
return idSegment.endsWith(".json") ? idSegment.slice(0, -".json".length) : null;
|
|
9081
9221
|
}
|
|
@@ -9257,7 +9397,22 @@ async function handlePagesPublic(req, res, pathSegments, queryParams) {
|
|
|
9257
9397
|
bumpViewCount(page.id);
|
|
9258
9398
|
return true;
|
|
9259
9399
|
}
|
|
9400
|
+
const wantsPrint = queryParams.get("print") === "1";
|
|
9260
9401
|
if (page.contentType === "application/json") {
|
|
9402
|
+
if (wantsPrint) {
|
|
9403
|
+
const headers4 = {
|
|
9404
|
+
"Content-Type": "text/html; charset=utf-8",
|
|
9405
|
+
"Cache-Control": "no-store",
|
|
9406
|
+
"Content-Security-Policy": buildCsp(),
|
|
9407
|
+
"X-Content-Type-Options": "nosniff"
|
|
9408
|
+
};
|
|
9409
|
+
if (inlineSetCookie)
|
|
9410
|
+
headers4["Set-Cookie"] = inlineSetCookie;
|
|
9411
|
+
res.writeHead(200, headers4);
|
|
9412
|
+
res.end(printableJsonPageHtml(page));
|
|
9413
|
+
bumpViewCount(page.id);
|
|
9414
|
+
return true;
|
|
9415
|
+
}
|
|
9261
9416
|
const headers3 = { Location: `${getAppBaseUrl2()}/pages/${page.id}` };
|
|
9262
9417
|
if (inlineSetCookie)
|
|
9263
9418
|
headers3["Set-Cookie"] = inlineSetCookie;
|
|
@@ -9265,7 +9420,7 @@ async function handlePagesPublic(req, res, pathSegments, queryParams) {
|
|
|
9265
9420
|
res.end();
|
|
9266
9421
|
return true;
|
|
9267
9422
|
}
|
|
9268
|
-
const html = injectBrowserSdk(page.body);
|
|
9423
|
+
const html = injectBrowserSdk(page.body) + (wantsPrint ? PRINT_AUTOTRIGGER_SCRIPT : "");
|
|
9269
9424
|
const headers2 = {
|
|
9270
9425
|
"Content-Type": "text/html; charset=utf-8",
|
|
9271
9426
|
"Cache-Control": "no-store",
|
|
@@ -11519,6 +11674,102 @@ var listVersionsRoute = route({
|
|
|
11519
11674
|
404: { description: "Script not found" }
|
|
11520
11675
|
}
|
|
11521
11676
|
});
|
|
11677
|
+
var apiEndpointParamsSchema = exports_external.object({
|
|
11678
|
+
id: exports_external.string().uuid(),
|
|
11679
|
+
endpointId: exports_external.string()
|
|
11680
|
+
});
|
|
11681
|
+
var createScriptApiBodySchema = exports_external.object({
|
|
11682
|
+
authMode: ScriptApiAuthModeSchema.default("bearer"),
|
|
11683
|
+
label: exports_external.string().max(200).optional(),
|
|
11684
|
+
agentId: exports_external.string().optional()
|
|
11685
|
+
});
|
|
11686
|
+
var patchScriptApiBodySchema = exports_external.object({
|
|
11687
|
+
enabled: exports_external.boolean().optional(),
|
|
11688
|
+
label: exports_external.string().max(200).nullable().optional()
|
|
11689
|
+
});
|
|
11690
|
+
var createScriptApiRoute = route({
|
|
11691
|
+
method: "post",
|
|
11692
|
+
path: "/api/scripts/{id}/apis",
|
|
11693
|
+
pattern: ["api", "scripts", null, "apis"],
|
|
11694
|
+
operationId: "scripts_api_create",
|
|
11695
|
+
summary: "Expose a script as an external HTTP API endpoint",
|
|
11696
|
+
description: "Returns the endpoint plus the plaintext bearer token (when authMode is 'bearer').",
|
|
11697
|
+
tags: ["Scripts"],
|
|
11698
|
+
params: idParamsSchema2,
|
|
11699
|
+
body: createScriptApiBodySchema,
|
|
11700
|
+
responses: {
|
|
11701
|
+
201: { description: "Endpoint created" },
|
|
11702
|
+
400: { description: "Validation error or script has no owning agent" },
|
|
11703
|
+
404: { description: "Script not found" }
|
|
11704
|
+
}
|
|
11705
|
+
});
|
|
11706
|
+
var listScriptApisRoute = route({
|
|
11707
|
+
method: "get",
|
|
11708
|
+
path: "/api/scripts/{id}/apis",
|
|
11709
|
+
pattern: ["api", "scripts", null, "apis"],
|
|
11710
|
+
operationId: "scripts_api_list",
|
|
11711
|
+
summary: "List external API endpoints for a script",
|
|
11712
|
+
tags: ["Scripts"],
|
|
11713
|
+
params: idParamsSchema2,
|
|
11714
|
+
responses: {
|
|
11715
|
+
200: { description: "Endpoints (without secrets)" },
|
|
11716
|
+
404: { description: "Script not found" }
|
|
11717
|
+
}
|
|
11718
|
+
});
|
|
11719
|
+
var revealScriptApiSecretRoute = route({
|
|
11720
|
+
method: "get",
|
|
11721
|
+
path: "/api/scripts/{id}/apis/{endpointId}/secret",
|
|
11722
|
+
pattern: ["api", "scripts", null, "apis", null, "secret"],
|
|
11723
|
+
operationId: "scripts_api_reveal_secret",
|
|
11724
|
+
summary: "Reveal an endpoint's bearer token",
|
|
11725
|
+
tags: ["Scripts"],
|
|
11726
|
+
params: apiEndpointParamsSchema,
|
|
11727
|
+
responses: {
|
|
11728
|
+
200: { description: "Decrypted token (null when authMode is 'none')" },
|
|
11729
|
+
404: { description: "Endpoint not found" }
|
|
11730
|
+
}
|
|
11731
|
+
});
|
|
11732
|
+
var patchScriptApiRoute = route({
|
|
11733
|
+
method: "patch",
|
|
11734
|
+
path: "/api/scripts/{id}/apis/{endpointId}",
|
|
11735
|
+
pattern: ["api", "scripts", null, "apis", null],
|
|
11736
|
+
operationId: "scripts_api_update",
|
|
11737
|
+
summary: "Enable/disable or relabel an external API endpoint",
|
|
11738
|
+
tags: ["Scripts"],
|
|
11739
|
+
params: apiEndpointParamsSchema,
|
|
11740
|
+
body: patchScriptApiBodySchema,
|
|
11741
|
+
responses: {
|
|
11742
|
+
200: { description: "Updated endpoint" },
|
|
11743
|
+
404: { description: "Endpoint not found" }
|
|
11744
|
+
}
|
|
11745
|
+
});
|
|
11746
|
+
var rotateScriptApiRoute = route({
|
|
11747
|
+
method: "post",
|
|
11748
|
+
path: "/api/scripts/{id}/apis/{endpointId}/rotate",
|
|
11749
|
+
pattern: ["api", "scripts", null, "apis", null, "rotate"],
|
|
11750
|
+
operationId: "scripts_api_rotate",
|
|
11751
|
+
summary: "Rotate an endpoint's bearer token",
|
|
11752
|
+
tags: ["Scripts"],
|
|
11753
|
+
params: apiEndpointParamsSchema,
|
|
11754
|
+
responses: {
|
|
11755
|
+
200: { description: "Endpoint with new plaintext token" },
|
|
11756
|
+
400: { description: "Endpoint uses 'none' auth — nothing to rotate" },
|
|
11757
|
+
404: { description: "Endpoint not found" }
|
|
11758
|
+
}
|
|
11759
|
+
});
|
|
11760
|
+
var deleteScriptApiRoute = route({
|
|
11761
|
+
method: "delete",
|
|
11762
|
+
path: "/api/scripts/{id}/apis/{endpointId}",
|
|
11763
|
+
pattern: ["api", "scripts", null, "apis", null],
|
|
11764
|
+
operationId: "scripts_api_delete",
|
|
11765
|
+
summary: "Delete an external API endpoint",
|
|
11766
|
+
tags: ["Scripts"],
|
|
11767
|
+
params: apiEndpointParamsSchema,
|
|
11768
|
+
responses: {
|
|
11769
|
+
200: { description: "Deleted" },
|
|
11770
|
+
404: { description: "Endpoint not found" }
|
|
11771
|
+
}
|
|
11772
|
+
});
|
|
11522
11773
|
function requireAgent2(res, agentId) {
|
|
11523
11774
|
if (!agentId) {
|
|
11524
11775
|
jsonError(res, "X-Agent-ID required for scripts API", 400);
|
|
@@ -11834,6 +12085,99 @@ async function handleScripts(req, res, pathSegments, queryParams, agentId) {
|
|
|
11834
12085
|
json(res, { deleted });
|
|
11835
12086
|
return true;
|
|
11836
12087
|
}
|
|
12088
|
+
if (createScriptApiRoute.match(req.method, pathSegments)) {
|
|
12089
|
+
const parsed = await createScriptApiRoute.parse(req, res, pathSegments, queryParams);
|
|
12090
|
+
if (!parsed)
|
|
12091
|
+
return true;
|
|
12092
|
+
const script = getScriptById(parsed.params.id);
|
|
12093
|
+
if (!script) {
|
|
12094
|
+
jsonError(res, "Script not found", 404);
|
|
12095
|
+
return true;
|
|
12096
|
+
}
|
|
12097
|
+
const runAsAgentId = parsed.body.agentId ?? script.scopeId ?? script.createdByAgentId;
|
|
12098
|
+
if (!runAsAgentId) {
|
|
12099
|
+
jsonError(res, "agentId is required: this script has no owning agent to run as", 400);
|
|
12100
|
+
return true;
|
|
12101
|
+
}
|
|
12102
|
+
const endpoint = createScriptApi({
|
|
12103
|
+
scriptId: script.id,
|
|
12104
|
+
agentId: runAsAgentId,
|
|
12105
|
+
authMode: parsed.body.authMode,
|
|
12106
|
+
label: parsed.body.label ?? null,
|
|
12107
|
+
createdBy: resolveHttpAuditUserId(req, agentId)
|
|
12108
|
+
});
|
|
12109
|
+
json(res, endpoint, 201);
|
|
12110
|
+
return true;
|
|
12111
|
+
}
|
|
12112
|
+
if (listScriptApisRoute.match(req.method, pathSegments)) {
|
|
12113
|
+
const parsed = await listScriptApisRoute.parse(req, res, pathSegments, queryParams);
|
|
12114
|
+
if (!parsed)
|
|
12115
|
+
return true;
|
|
12116
|
+
if (!getScriptById(parsed.params.id)) {
|
|
12117
|
+
jsonError(res, "Script not found", 404);
|
|
12118
|
+
return true;
|
|
12119
|
+
}
|
|
12120
|
+
json(res, { apis: listScriptApisForScript(parsed.params.id) });
|
|
12121
|
+
return true;
|
|
12122
|
+
}
|
|
12123
|
+
if (revealScriptApiSecretRoute.match(req.method, pathSegments)) {
|
|
12124
|
+
const parsed = await revealScriptApiSecretRoute.parse(req, res, pathSegments, queryParams);
|
|
12125
|
+
if (!parsed)
|
|
12126
|
+
return true;
|
|
12127
|
+
const endpoint = getScriptApiById(parsed.params.endpointId);
|
|
12128
|
+
if (!endpoint || endpoint.scriptId !== parsed.params.id) {
|
|
12129
|
+
jsonError(res, "Endpoint not found", 404);
|
|
12130
|
+
return true;
|
|
12131
|
+
}
|
|
12132
|
+
json(res, { token: getScriptApiSecret(endpoint.id) });
|
|
12133
|
+
return true;
|
|
12134
|
+
}
|
|
12135
|
+
if (rotateScriptApiRoute.match(req.method, pathSegments)) {
|
|
12136
|
+
const parsed = await rotateScriptApiRoute.parse(req, res, pathSegments, queryParams);
|
|
12137
|
+
if (!parsed)
|
|
12138
|
+
return true;
|
|
12139
|
+
const endpoint = getScriptApiById(parsed.params.endpointId);
|
|
12140
|
+
if (!endpoint || endpoint.scriptId !== parsed.params.id) {
|
|
12141
|
+
jsonError(res, "Endpoint not found", 404);
|
|
12142
|
+
return true;
|
|
12143
|
+
}
|
|
12144
|
+
const rotated = rotateScriptApiSecret(endpoint.id, resolveHttpAuditUserId(req, agentId));
|
|
12145
|
+
if (!rotated) {
|
|
12146
|
+
jsonError(res, "Cannot rotate a token on a 'none' auth endpoint", 400);
|
|
12147
|
+
return true;
|
|
12148
|
+
}
|
|
12149
|
+
json(res, rotated);
|
|
12150
|
+
return true;
|
|
12151
|
+
}
|
|
12152
|
+
if (patchScriptApiRoute.match(req.method, pathSegments)) {
|
|
12153
|
+
const parsed = await patchScriptApiRoute.parse(req, res, pathSegments, queryParams);
|
|
12154
|
+
if (!parsed)
|
|
12155
|
+
return true;
|
|
12156
|
+
const endpoint = getScriptApiById(parsed.params.endpointId);
|
|
12157
|
+
if (!endpoint || endpoint.scriptId !== parsed.params.id) {
|
|
12158
|
+
jsonError(res, "Endpoint not found", 404);
|
|
12159
|
+
return true;
|
|
12160
|
+
}
|
|
12161
|
+
const updated = updateScriptApi(endpoint.id, {
|
|
12162
|
+
enabled: parsed.body.enabled,
|
|
12163
|
+
label: parsed.body.label,
|
|
12164
|
+
updatedBy: resolveHttpAuditUserId(req, agentId)
|
|
12165
|
+
});
|
|
12166
|
+
json(res, updated);
|
|
12167
|
+
return true;
|
|
12168
|
+
}
|
|
12169
|
+
if (deleteScriptApiRoute.match(req.method, pathSegments)) {
|
|
12170
|
+
const parsed = await deleteScriptApiRoute.parse(req, res, pathSegments, queryParams);
|
|
12171
|
+
if (!parsed)
|
|
12172
|
+
return true;
|
|
12173
|
+
const endpoint = getScriptApiById(parsed.params.endpointId);
|
|
12174
|
+
if (!endpoint || endpoint.scriptId !== parsed.params.id) {
|
|
12175
|
+
jsonError(res, "Endpoint not found", 404);
|
|
12176
|
+
return true;
|
|
12177
|
+
}
|
|
12178
|
+
json(res, { deleted: deleteScriptApi(endpoint.id) });
|
|
12179
|
+
return true;
|
|
12180
|
+
}
|
|
11837
12181
|
return false;
|
|
11838
12182
|
}
|
|
11839
12183
|
|
|
@@ -12025,6 +12369,21 @@ async function handleSessionData(req, res, pathSegments, queryParams, _myAgentId
|
|
|
12025
12369
|
isError: parsed.body.isError ?? false,
|
|
12026
12370
|
costSource
|
|
12027
12371
|
});
|
|
12372
|
+
recordSessionCost({
|
|
12373
|
+
totalCostUsd,
|
|
12374
|
+
harness: parsed.body.provider ?? "unknown",
|
|
12375
|
+
model,
|
|
12376
|
+
costSource,
|
|
12377
|
+
isError: parsed.body.isError ?? false,
|
|
12378
|
+
tokens: {
|
|
12379
|
+
input: inputTokens,
|
|
12380
|
+
output: outputTokens,
|
|
12381
|
+
cacheRead: cachedInputTokens,
|
|
12382
|
+
cacheWrite: parsed.body.cacheWriteTokens ?? 0,
|
|
12383
|
+
reasoning: parsed.body.reasoningOutputTokens ?? 0,
|
|
12384
|
+
thinking: parsed.body.thinkingTokens ?? 0
|
|
12385
|
+
}
|
|
12386
|
+
});
|
|
12028
12387
|
incrementServerSessionsProcessed();
|
|
12029
12388
|
json(res, { success: true, cost }, 201);
|
|
12030
12389
|
} catch (error) {
|
|
@@ -16918,6 +17277,167 @@ async function handleWorkflows(req, res, pathSegments, queryParams, myAgentId) {
|
|
|
16918
17277
|
return false;
|
|
16919
17278
|
}
|
|
16920
17279
|
|
|
17280
|
+
// src/http/x.ts
|
|
17281
|
+
init_zod();
|
|
17282
|
+
init_db();
|
|
17283
|
+
import { timingSafeEqual as timingSafeEqual3 } from "node:crypto";
|
|
17284
|
+
init_secret_scrubber();
|
|
17285
|
+
var DEFAULT_TIMEOUT_MS = 60000;
|
|
17286
|
+
var MIN_TIMEOUT_MS = 1000;
|
|
17287
|
+
var MAX_TIMEOUT_MS = 300000;
|
|
17288
|
+
var TIMEOUT_HEADER = "x-swarm-timeout-ms";
|
|
17289
|
+
var MAX_BODY_BYTES = 1 * 1024 * 1024;
|
|
17290
|
+
var scriptApiRoute = route({
|
|
17291
|
+
method: "post",
|
|
17292
|
+
path: "/api/x/script/{endpointId}",
|
|
17293
|
+
pattern: ["api", "x", "script", null],
|
|
17294
|
+
operationId: "x_script_run",
|
|
17295
|
+
summary: "Invoke an externally-exposed swarm script",
|
|
17296
|
+
description: "Runs the script bound to this endpoint and returns a JSON envelope " + "`{ ok, result, error, durationMs }` (HTTP 200) once execution is reached. " + "Auth/routing failures use 401 (bad/missing bearer) and 404 (unknown or " + "disabled endpoint). Optional `X-Swarm-Timeout-Ms` header (default 60000, " + "clamped 1000–300000) sets the wall-clock timeout.",
|
|
17297
|
+
tags: ["External APIs"],
|
|
17298
|
+
params: exports_external.object({ endpointId: exports_external.string() }),
|
|
17299
|
+
auth: { apiKey: false },
|
|
17300
|
+
responses: {
|
|
17301
|
+
200: { description: "Script executed — see `ok` in the envelope" },
|
|
17302
|
+
401: { description: "Missing or invalid bearer token" },
|
|
17303
|
+
404: { description: "Endpoint not found or disabled" },
|
|
17304
|
+
501: { description: "workspace-rw scripts are not supported" }
|
|
17305
|
+
}
|
|
17306
|
+
});
|
|
17307
|
+
function extractBearer3(req) {
|
|
17308
|
+
const raw = req.headers.authorization;
|
|
17309
|
+
const header = Array.isArray(raw) ? raw[0] : raw;
|
|
17310
|
+
if (!header)
|
|
17311
|
+
return null;
|
|
17312
|
+
const match = /^Bearer\s+(.+)$/i.exec(header.trim());
|
|
17313
|
+
return match?.[1] ?? null;
|
|
17314
|
+
}
|
|
17315
|
+
function timingSafeEqualStr(a, b) {
|
|
17316
|
+
const ab = Buffer.from(a);
|
|
17317
|
+
const bb = Buffer.from(b);
|
|
17318
|
+
if (ab.length !== bb.length)
|
|
17319
|
+
return false;
|
|
17320
|
+
return timingSafeEqual3(ab, bb);
|
|
17321
|
+
}
|
|
17322
|
+
function resolveTimeoutMs(req) {
|
|
17323
|
+
const raw = req.headers[TIMEOUT_HEADER];
|
|
17324
|
+
const val = Array.isArray(raw) ? raw[0] : raw;
|
|
17325
|
+
if (!val)
|
|
17326
|
+
return DEFAULT_TIMEOUT_MS;
|
|
17327
|
+
const n = Number(val);
|
|
17328
|
+
if (!Number.isFinite(n))
|
|
17329
|
+
return DEFAULT_TIMEOUT_MS;
|
|
17330
|
+
return Math.min(MAX_TIMEOUT_MS, Math.max(MIN_TIMEOUT_MS, Math.floor(n)));
|
|
17331
|
+
}
|
|
17332
|
+
function buildExecutionError(output) {
|
|
17333
|
+
if (output.runtimeError) {
|
|
17334
|
+
return {
|
|
17335
|
+
type: "runtime_error",
|
|
17336
|
+
message: `${output.runtimeError.name}: ${output.runtimeError.message}`
|
|
17337
|
+
};
|
|
17338
|
+
}
|
|
17339
|
+
switch (output.error) {
|
|
17340
|
+
case "timeout":
|
|
17341
|
+
return { type: "timeout", message: "Script timed out" };
|
|
17342
|
+
case "import_violation":
|
|
17343
|
+
return { type: "import_violation", message: output.stderr || "Disallowed import" };
|
|
17344
|
+
default:
|
|
17345
|
+
return {
|
|
17346
|
+
type: "runtime_error",
|
|
17347
|
+
message: output.error ? `Script failed: ${output.error}` : `Script exited with code ${output.exitCode}`
|
|
17348
|
+
};
|
|
17349
|
+
}
|
|
17350
|
+
}
|
|
17351
|
+
async function handleX(req, res, pathSegments) {
|
|
17352
|
+
if (!scriptApiRoute.match(req.method, pathSegments))
|
|
17353
|
+
return false;
|
|
17354
|
+
const endpointId = pathSegments[3] ?? "";
|
|
17355
|
+
const endpoint = getScriptApiById(endpointId);
|
|
17356
|
+
if (!endpoint || !endpoint.enabled) {
|
|
17357
|
+
json(res, { error: { type: "not_found", message: "Endpoint not found" } }, 404);
|
|
17358
|
+
return true;
|
|
17359
|
+
}
|
|
17360
|
+
if (endpoint.authMode === "bearer") {
|
|
17361
|
+
const provided = extractBearer3(req);
|
|
17362
|
+
const expected = getScriptApiSecret(endpointId);
|
|
17363
|
+
if (!provided || !expected || !timingSafeEqualStr(provided, expected)) {
|
|
17364
|
+
json(res, { error: { type: "unauthorized", message: "Invalid or missing bearer token" } }, 401);
|
|
17365
|
+
return true;
|
|
17366
|
+
}
|
|
17367
|
+
}
|
|
17368
|
+
if (enforceContentLengthCap(req, res, MAX_BODY_BYTES) === BODY_TOO_LARGE)
|
|
17369
|
+
return true;
|
|
17370
|
+
let args;
|
|
17371
|
+
try {
|
|
17372
|
+
args = await parseBody(req);
|
|
17373
|
+
} catch {
|
|
17374
|
+
json(res, {
|
|
17375
|
+
ok: false,
|
|
17376
|
+
result: null,
|
|
17377
|
+
error: { type: "invalid_json", message: "Request body must be valid JSON" },
|
|
17378
|
+
durationMs: 0
|
|
17379
|
+
});
|
|
17380
|
+
return true;
|
|
17381
|
+
}
|
|
17382
|
+
const script = getScriptById(endpoint.scriptId);
|
|
17383
|
+
if (!script) {
|
|
17384
|
+
json(res, { error: { type: "not_found", message: "Script not found" } }, 404);
|
|
17385
|
+
return true;
|
|
17386
|
+
}
|
|
17387
|
+
if (script.fsMode === "workspace-rw") {
|
|
17388
|
+
jsonError(res, "workspace-rw scripts are not supported", 501);
|
|
17389
|
+
return true;
|
|
17390
|
+
}
|
|
17391
|
+
if (script.argsJsonSchema) {
|
|
17392
|
+
try {
|
|
17393
|
+
const schema = JSON.parse(script.argsJsonSchema);
|
|
17394
|
+
const errors = validateJsonSchema(schema, args ?? null);
|
|
17395
|
+
if (errors.length > 0) {
|
|
17396
|
+
json(res, {
|
|
17397
|
+
ok: false,
|
|
17398
|
+
result: null,
|
|
17399
|
+
error: { type: "args_validation", message: errors.join("; "), details: errors },
|
|
17400
|
+
durationMs: 0
|
|
17401
|
+
});
|
|
17402
|
+
return true;
|
|
17403
|
+
}
|
|
17404
|
+
} catch {}
|
|
17405
|
+
}
|
|
17406
|
+
const timeoutMs = resolveTimeoutMs(req);
|
|
17407
|
+
const startedAt = new Date().toISOString();
|
|
17408
|
+
const output = await runScript({
|
|
17409
|
+
source: script.source,
|
|
17410
|
+
args: args ?? null,
|
|
17411
|
+
fsMode: "none",
|
|
17412
|
+
agentId: endpoint.agentId,
|
|
17413
|
+
timeoutMs,
|
|
17414
|
+
egressSecrets: buildScriptCredentialBindings({ agentId: endpoint.agentId }),
|
|
17415
|
+
apiConnections: getScriptApiConnectionDescriptors({ agentId: endpoint.agentId })
|
|
17416
|
+
});
|
|
17417
|
+
const ok = output.exitCode === 0 && !output.error && !output.runtimeError;
|
|
17418
|
+
const error = ok ? null : buildExecutionError(output);
|
|
17419
|
+
try {
|
|
17420
|
+
recordScriptApiUsage(endpointId);
|
|
17421
|
+
} catch {}
|
|
17422
|
+
try {
|
|
17423
|
+
recordInlineScriptRun({
|
|
17424
|
+
id: crypto.randomUUID(),
|
|
17425
|
+
agentId: endpoint.agentId,
|
|
17426
|
+
source: script.source,
|
|
17427
|
+
args: scrubObject(args ?? null),
|
|
17428
|
+
scriptName: script.name,
|
|
17429
|
+
status: ok ? "completed" : "failed",
|
|
17430
|
+
output: scrubObject(output.result),
|
|
17431
|
+
error: ok ? undefined : scrubSecrets(error?.message ?? "Script failed"),
|
|
17432
|
+
startedAt,
|
|
17433
|
+
finishedAt: new Date().toISOString(),
|
|
17434
|
+
apiEndpointId: endpointId
|
|
17435
|
+
});
|
|
17436
|
+
} catch {}
|
|
17437
|
+
json(res, scrubObject({ ok, result: ok ? output.result : null, error, durationMs: output.durationMs }));
|
|
17438
|
+
return true;
|
|
17439
|
+
}
|
|
17440
|
+
|
|
16921
17441
|
// src/http/index.ts
|
|
16922
17442
|
process.on("uncaughtException", (err) => {
|
|
16923
17443
|
console.error("[fatal] uncaughtException:", err);
|
|
@@ -16958,7 +17478,10 @@ function startApiGcInterval() {
|
|
|
16958
17478
|
const interval = setInterval(() => {
|
|
16959
17479
|
const closedOwnerTransports = closeIdleMcpTransports(transports, transportActivity, {
|
|
16960
17480
|
idleTimeoutMs: MCP_TRANSPORT_IDLE_TIMEOUT_MS,
|
|
16961
|
-
label: "MCP"
|
|
17481
|
+
label: "MCP",
|
|
17482
|
+
onClose: (id) => {
|
|
17483
|
+
delete mcpSessionAgents[id];
|
|
17484
|
+
}
|
|
16962
17485
|
});
|
|
16963
17486
|
const closedUserTransports = closeIdleMcpUserTransports(transportsUser, sessionUsers, transportActivityUser, { idleTimeoutMs: MCP_TRANSPORT_IDLE_TIMEOUT_MS });
|
|
16964
17487
|
if (closedOwnerTransports > 0 || closedUserTransports > 0) {
|
|
@@ -16974,6 +17497,7 @@ if (globalState.__httpServer) {
|
|
|
16974
17497
|
globalState.__httpServer.close();
|
|
16975
17498
|
}
|
|
16976
17499
|
var transports = globalState.__transports ?? {};
|
|
17500
|
+
var mcpSessionAgents = globalState.__mcpSessionAgents ?? {};
|
|
16977
17501
|
var transportsUser = globalState.__transportsUser ?? {};
|
|
16978
17502
|
var sessionUsers = globalState.__sessionUsers ?? {};
|
|
16979
17503
|
var transportActivity = globalState.__transportActivity ?? {};
|
|
@@ -17071,6 +17595,7 @@ var httpServer = createHttpServer(async (req, res) => {
|
|
|
17071
17595
|
() => handleSkills(req, res, pathSegments, queryParams, myAgentId),
|
|
17072
17596
|
() => handleScriptRuns(req, res, pathSegments, queryParams, myAgentId),
|
|
17073
17597
|
() => handleScripts(req, res, pathSegments, queryParams, myAgentId),
|
|
17598
|
+
() => handleX(req, res, pathSegments),
|
|
17074
17599
|
() => handleMcpBridge(req, res, pathSegments, queryParams, myAgentId),
|
|
17075
17600
|
() => handleMcpServers(req, res, pathSegments, queryParams),
|
|
17076
17601
|
() => handleMcpOAuth(req, res, pathSegments, queryParams),
|
|
@@ -17085,7 +17610,7 @@ var httpServer = createHttpServer(async (req, res) => {
|
|
|
17085
17610
|
() => handleSessions(req, res, pathSegments, queryParams),
|
|
17086
17611
|
() => handleInboxState(req, res, pathSegments, queryParams),
|
|
17087
17612
|
() => handleTaskTemplates(req, res, pathSegments, queryParams),
|
|
17088
|
-
() => handleMcp(req, res, transports, transportActivity),
|
|
17613
|
+
() => handleMcp(req, res, transports, transportActivity, mcpSessionAgents),
|
|
17089
17614
|
() => handleMcpUser(req, res, transportsUser, sessionUsers, transportActivityUser)
|
|
17090
17615
|
];
|
|
17091
17616
|
try {
|
|
@@ -17120,6 +17645,7 @@ var httpServer = createHttpServer(async (req, res) => {
|
|
|
17120
17645
|
globalState.__httpServer = httpServer;
|
|
17121
17646
|
globalState.__transports = transports;
|
|
17122
17647
|
globalState.__transportsUser = transportsUser;
|
|
17648
|
+
globalState.__mcpSessionAgents = mcpSessionAgents;
|
|
17123
17649
|
globalState.__sessionUsers = sessionUsers;
|
|
17124
17650
|
globalState.__transportActivity = transportActivity;
|
|
17125
17651
|
globalState.__transportActivityUser = transportActivityUser;
|
|
@@ -17131,14 +17657,14 @@ async function shutdown() {
|
|
|
17131
17657
|
sessionsProcessed: getServerSessionsProcessed()
|
|
17132
17658
|
});
|
|
17133
17659
|
if (hasCapability("scheduling")) {
|
|
17134
|
-
const { stopScheduler } = await import("./index-
|
|
17660
|
+
const { stopScheduler } = await import("./index-45bqm6xc.js");
|
|
17135
17661
|
stopScheduler();
|
|
17136
17662
|
}
|
|
17137
17663
|
stopHeartbeat();
|
|
17138
17664
|
stopScriptRunSupervisor();
|
|
17139
17665
|
await stopSlackApp();
|
|
17140
17666
|
if (process.env.OAUTH_KEEPALIVE_DISABLE !== "true") {
|
|
17141
|
-
const { stopOAuthKeepalive } = await import("./keepalive-
|
|
17667
|
+
const { stopOAuthKeepalive } = await import("./keepalive-8gbgeg21.js");
|
|
17142
17668
|
await stopOAuthKeepalive();
|
|
17143
17669
|
}
|
|
17144
17670
|
stopMcpOAuthPendingGc();
|
|
@@ -17151,6 +17677,7 @@ async function shutdown() {
|
|
|
17151
17677
|
console.log(`[HTTP] Closing transport ${id}`);
|
|
17152
17678
|
transport.close();
|
|
17153
17679
|
delete transports[id];
|
|
17680
|
+
delete mcpSessionAgents[id];
|
|
17154
17681
|
delete transportActivity[id];
|
|
17155
17682
|
}
|
|
17156
17683
|
for (const [id, transport] of Object.entries(transportsUser)) {
|
|
@@ -17190,15 +17717,15 @@ try {
|
|
|
17190
17717
|
throw err;
|
|
17191
17718
|
}
|
|
17192
17719
|
try {
|
|
17193
|
-
const { seedPricingFromModelsDev } = await import("./seed-pricing-
|
|
17720
|
+
const { seedPricingFromModelsDev } = await import("./seed-pricing-3tqmbe0p.js");
|
|
17194
17721
|
seedPricingFromModelsDev();
|
|
17195
|
-
const { startPricingRefreshLoop } = await import("./pricing-refresh-
|
|
17722
|
+
const { startPricingRefreshLoop } = await import("./pricing-refresh-f6cgj5br.js");
|
|
17196
17723
|
startPricingRefreshLoop();
|
|
17197
17724
|
} catch (err) {
|
|
17198
17725
|
console.error("[startup] Failed to seed pricing rows:", err);
|
|
17199
17726
|
}
|
|
17200
17727
|
try {
|
|
17201
|
-
const { runAllSeeders } = await import("./index-
|
|
17728
|
+
const { runAllSeeders } = await import("./index-jscerv2x.js");
|
|
17202
17729
|
await runAllSeeders({ scriptEmbeddingMode: "skip" });
|
|
17203
17730
|
} catch (err) {
|
|
17204
17731
|
console.error("[startup] Failed to seed built-in entities:", err);
|
|
@@ -17231,31 +17758,31 @@ httpServer.listen(port, async () => {
|
|
|
17231
17758
|
initWorkflows();
|
|
17232
17759
|
startScriptRunSupervisor(getMcpBaseUrl());
|
|
17233
17760
|
if (hasCapability("scheduling")) {
|
|
17234
|
-
const { startScheduler } = await import("./index-
|
|
17235
|
-
const { getExecutorRegistry: getExecutorRegistry2 } = await import("./index-
|
|
17761
|
+
const { startScheduler } = await import("./index-45bqm6xc.js");
|
|
17762
|
+
const { getExecutorRegistry: getExecutorRegistry2 } = await import("./index-v3r40ak0.js");
|
|
17236
17763
|
const intervalMs = Number(process.env.SCHEDULER_INTERVAL_MS) || 1e4;
|
|
17237
17764
|
startScheduler(getExecutorRegistry2(), intervalMs, {
|
|
17238
17765
|
runId: globalState.__runId
|
|
17239
17766
|
});
|
|
17240
17767
|
}
|
|
17241
17768
|
if (process.env.HEARTBEAT_DISABLE !== "true") {
|
|
17242
|
-
const { startHeartbeat } = await import("./index-
|
|
17769
|
+
const { startHeartbeat } = await import("./index-f5e873a5.js");
|
|
17243
17770
|
const heartbeatMs = Number(process.env.HEARTBEAT_INTERVAL_MS) || 90000;
|
|
17244
17771
|
startHeartbeat(heartbeatMs);
|
|
17245
17772
|
}
|
|
17246
17773
|
if (process.env.OAUTH_KEEPALIVE_DISABLE !== "true") {
|
|
17247
|
-
const { startOAuthKeepalive } = await import("./keepalive-
|
|
17774
|
+
const { startOAuthKeepalive } = await import("./keepalive-8gbgeg21.js");
|
|
17248
17775
|
startOAuthKeepalive();
|
|
17249
17776
|
}
|
|
17250
17777
|
startMcpOAuthPendingGc();
|
|
17251
17778
|
startMemoryGc();
|
|
17252
|
-
import("./boot-reembed-
|
|
17779
|
+
import("./boot-reembed-atv4kcrh.js").then(({ runBootReembed }) => runBootReembed()).catch((err) => {
|
|
17253
17780
|
console.error("[boot-reembed] startup backfill failed (non-fatal):", err);
|
|
17254
17781
|
});
|
|
17255
|
-
import("./boot-reembed-
|
|
17782
|
+
import("./boot-reembed-zanbm36c.js").then(({ runBootReembedScripts }) => runBootReembedScripts()).catch((err) => {
|
|
17256
17783
|
console.error("[boot-reembed-scripts] startup backfill failed (non-fatal):", err);
|
|
17257
17784
|
});
|
|
17258
|
-
import("./boot-scrub-logs-
|
|
17785
|
+
import("./boot-scrub-logs-asq051ff.js").then(({ runBootScrubLogs }) => runBootScrubLogs()).catch((err) => {
|
|
17259
17786
|
console.error("[boot-scrub-logs] startup scrub failed (non-fatal):", err);
|
|
17260
17787
|
});
|
|
17261
17788
|
}).on("error", (err) => {
|