@desplega.ai/agent-swarm 2.4.3 → 2.4.5
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/dist/{acp-adapter-1885dpr7.js → acp-adapter-2wdkktv6.js} +1 -2
- package/dist/{actions-pn76n32q.js → actions-c40ebcm4.js} +18 -18
- package/dist/{amp-adapter-af84rx1d.js → amp-adapter-wb67m95z.js} +2 -2
- package/dist/{app-6sv8mhzm.js → app-353vre8g.js} +3 -3
- package/dist/{assistant-sc2tf825.js → assistant-sj1njh23.js} +21 -21
- package/dist/{boot-reembed-y3m0ydzj.js → boot-reembed-b9c3az3c.js} +1 -1
- package/dist/{boot-reembed-gvxjs2py.js → boot-reembed-qdkvxeem.js} +1 -1
- package/dist/{boot-scrub-sweep-1j9mk05f.js → boot-scrub-sweep-m3wh8eks.js} +2 -2
- package/dist/{boot-seeds-37sp626b.js → boot-seeds-j2273s54.js} +4 -4
- package/dist/{claude-adapter-rp0jtnwr.js → claude-adapter-m7q0a085.js} +2 -2
- package/dist/{claude-managed-adapter-h2y889ge.js → claude-managed-adapter-5ptb6tzs.js} +2 -2
- package/dist/{claude-managed-setup-rdt248k7.js → claude-managed-setup-smrqk5j5.js} +3 -3
- package/dist/{claude-sdk-session-53rcw5we.js → claude-sdk-session-38xnz21e.js} +8284 -8267
- package/dist/{cli-6eyncg0y.js → cli-018r4jq6.js} +34 -6
- package/dist/{cli-sds5zzs8.js → cli-1f3qzw6y.js} +78 -12
- package/dist/{cli-f0p0f6ja.js → cli-1sp861s4.js} +7 -7
- package/dist/{cli-dm8p2dpf.js → cli-1syn2xy1.js} +10 -10
- package/dist/{cli-tkf4x6ha.js → cli-37j04k05.js} +11 -11
- package/dist/{cli-v87dr6e3.js → cli-3a45zcgm.js} +1 -1
- package/dist/{cli-1n9gdg56.js → cli-43x64hv3.js} +4 -4
- package/dist/{cli-p0qerd2r.js → cli-4zfqgjc5.js} +2 -2
- package/dist/{cli-aa3tb29r.js → cli-7c9qs530.js} +1 -1
- package/dist/{cli-9qtjfd60.js → cli-848hxdwj.js} +1 -1
- package/dist/{cli-1xsraagq.js → cli-94gwyg7m.js} +8 -8
- package/dist/{cli-0dxxwfkt.js → cli-9hstj09h.js} +17 -14
- package/dist/{cli-1012xb7j.js → cli-9yqgm9nd.js} +22 -22
- package/dist/{cli-pygdsgh8.js → cli-a92r1127.js} +1 -1
- package/dist/{cli-8vverzf7.js → cli-ba8ne1es.js} +5 -0
- package/dist/{cli-bxrqvpg5.js → cli-be2161h1.js} +7 -7
- package/dist/{cli-npfe9t1s.js → cli-bnes4z6b.js} +2 -2
- package/dist/{cli-aypbg9r2.js → cli-cxxe61f6.js} +1 -1
- package/dist/{cli-vq9gqarq.js → cli-dk44dxec.js} +1 -1
- package/dist/{cli-836ehxmt.js → cli-eww120g8.js} +3 -2
- package/dist/{cli-a0kcty51.js → cli-f01h25yt.js} +1 -1
- package/dist/{cli-mzkwkbdy.js → cli-f0g3pgvf.js} +1 -1
- package/dist/{cli-1ma335fz.js → cli-ftc1g5tj.js} +2 -2
- package/dist/{cli-4yef8ghv.js → cli-fv5hepyy.js} +3 -3
- package/dist/{cli-58vwn100.js → cli-g35m2xwm.js} +4 -4
- package/dist/{cli-qje9k2nh.js → cli-g9ypd5en.js} +12 -2
- package/dist/{cli-gx0j2khs.js → cli-j99azg3g.js} +3 -3
- package/dist/{cli-er83cjbn.js → cli-k8g16gz3.js} +416 -116
- package/dist/{cli-qp2m4btv.js → cli-kpw04va0.js} +2 -2
- package/dist/{cli-8y99kfey.js → cli-ms85309d.js} +33 -15
- package/dist/{cli-kgnkyabk.js → cli-n72rg53p.js} +1555 -645
- package/dist/{cli-e4d78xsv.js → cli-p14m2cnp.js} +1 -1
- package/dist/{cli-1eszr343.js → cli-qfxc84gh.js} +1 -1
- package/dist/{cli-wk28hzqn.js → cli-qwhy2qma.js} +1 -1
- package/dist/{cli-73ezfhha.js → cli-st8aw1m6.js} +228 -11
- package/dist/{cli-zvbb4n0e.js → cli-tw4p90jb.js} +92 -192
- package/dist/{cli-038fga5k.js → cli-v0yrfmdh.js} +148 -183
- package/dist/{cli-6aen3ezb.js → cli-v8fjakwf.js} +1 -1
- package/dist/{cli-99jez72r.js → cli-w9etnnxk.js} +6 -1
- package/dist/{cli-vcgscaan.js → cli-wt0jf9hm.js} +217 -80
- package/dist/{cli-s9rr4gr2.js → cli-xpa64rek.js} +1065 -305
- package/dist/{cli-h0mgxann.js → cli-z7d29rw9.js} +2 -2
- package/dist/cli.js +45 -20
- package/dist/{codex-adapter-2zrmab9b.js → codex-adapter-tn6k5mkg.js} +1 -1
- package/dist/{codex-session-runner-kbkz62vc.js → codex-session-runner-7vjt7jbw.js} +1 -1
- package/dist/{commands-hd574th6.js → commands-t7rz9146.js} +2 -2
- package/dist/{controller-pz5mcfg4.js → controller-m2jasma5.js} +2 -2
- package/dist/{controllers-connect-5rgq2hfk.js → controllers-connect-9ftpex99.js} +19 -19
- package/dist/{cursor-adapter-mgaprq0j.js → cursor-adapter-mjv79e4z.js} +1 -1
- package/dist/{db-6nf1207q.js → db-6sfrn9g3.js} +1 -1
- package/dist/{db-h06dxp05.js → db-rn673r06.js} +3 -3
- package/dist/{dispatcher-zthpy4m1.js → dispatcher-c155xz0p.js} +17 -17
- package/dist/{dsh-adapter-64dhw0j7.js → dsh-adapter-3mmszc1x.js} +1 -1
- package/dist/{external-channel-x01t7ke6.js → external-channel-35k6tkv8.js} +2 -2
- package/dist/{grok-adapter-h21jv594.js → grok-adapter-tfrq7tg1.js} +2 -3
- package/dist/handlers-7gw64dxw.js +39 -0
- package/dist/{heartbeat-zzfksckz.js → heartbeat-dyg4npkp.js} +20 -20
- package/dist/{hook-z4zhzj1f.js → hook-drspbwpe.js} +1 -1
- package/dist/{hook-3xfqhh2s.js → hook-x26b31bg.js} +1 -1
- package/dist/{http-q813tmya.js → http-pk972xyw.js} +571 -294
- package/dist/{index-va3y63es.js → index-6srwvd5b.js} +1 -2
- package/dist/{index-x8xbyn1t.js → index-arytgj5q.js} +1 -1
- package/dist/{index-wbbs14c5.js → index-bgdyvcnv.js} +17 -17
- package/dist/{index-s98037v0.js → index-cbxkmfc5.js} +1 -2
- package/dist/{index-c4ykd0f1.js → index-dr94zbnh.js} +13348 -11611
- package/dist/{index-m0a4ydqj.js → index-gabbcdn2.js} +17 -17
- package/dist/{index-220tk9bw.js → index-jwxkkex2.js} +139 -76
- package/dist/index-tfb26zhy.js +41 -0
- package/dist/{keepalive-y5t1my7m.js → keepalive-7yrng7px.js} +3 -3
- package/dist/{lead-2xwtq66b.js → lead-7e02z839.js} +29 -30
- package/dist/{maintenance-ybfsaedv.js → maintenance-e6cemdqt.js} +1 -1
- package/dist/{node-3v3f08f7.js → node-de6akczr.js} +10 -9
- package/dist/{oauth-refresh-sweep-909jmn12.js → oauth-refresh-sweep-yw3xdbcj.js} +2 -2
- package/dist/{onboard-xn6fkkys.js → onboard-0a9y5yrc.js} +2 -2
- package/dist/{otel-impl-e6mn0z13.js → otel-impl-trjpkfb7.js} +1 -1
- package/dist/{pricing-refresh-ygd362ep.js → pricing-refresh-d2b5my0y.js} +3 -3
- package/dist/{rbac-roles-mb470p4e.js → rbac-roles-hey3yv9d.js} +2 -2
- package/dist/{rbac-roles-c9axvfnz.js → rbac-roles-nxh5ahwk.js} +2 -2
- package/dist/{registry-rxw10xzg.js → registry-ajhexe44.js} +1 -1
- package/dist/{render-v2-g0306nh1.js → render-v2-rr3p2atg.js} +3 -3
- package/dist/{resume-v315hnq6.js → resume-2efkf1s1.js} +5 -5
- package/dist/{session-access-2zg285a1.js → session-access-s2mttxpw.js} +6 -4
- package/dist/{setup-a4mtf02k.js → setup-vypma5yt.js} +1 -1
- package/dist/{work-objects-9fr0fgtn.js → work-objects-rvhckdkp.js} +20 -20
- package/dist/{worker-qae22jeb.js → worker-5snytpbd.js} +29 -30
- package/dist/worker-token-xf11yyds.js +136 -0
- package/openapi.json +303 -13
- package/package.json +8 -8
- package/src/apps/action-runner.ts +4 -0
- package/src/apps/catalog.generated.json +209 -4
- package/src/apps/page-validator.ts +21 -3
- package/src/be/chunking.ts +42 -9
- package/src/be/db/tasks/draft-text.ts +15 -0
- package/src/be/db/tasks/read.ts +14 -1
- package/src/be/db.ts +5 -1
- package/src/be/memory/index-content.ts +36 -17
- package/src/be/memory/providers/openai-embedding.ts +115 -61
- package/src/be/memory/providers/sqlite-store.ts +69 -23
- package/src/be/memory/reranker.ts +31 -1
- package/src/be/memory/search-candidates.ts +47 -0
- package/src/be/memory/types.ts +14 -0
- package/src/be/migrations/232_agent_session_tokens.sql +41 -0
- package/src/be/scripts/typecheck.ts +2 -0
- package/src/be/seed-scripts/catalog/heartbeat-jev-gate.ts +116 -55
- package/src/be/seed-scripts/index.ts +2 -2
- package/src/be/swarm-config-guard.ts +40 -1
- package/src/be/task-attachment-store.ts +30 -0
- package/src/be/users.ts +169 -12
- package/src/cli.tsx +24 -0
- package/src/commands/worker-token.ts +164 -0
- package/src/extensions/catalog.generated.json +4 -4
- package/src/extensions/contract-types.generated.ts +1 -1
- package/src/extensions/contract.ts +7 -0
- package/src/fs/provider.ts +13 -1
- package/src/heartbeat/heartbeat.ts +31 -11
- package/src/http/apps.ts +43 -5
- package/src/http/codex-oauth-keep-warm.ts +27 -9
- package/src/http/config.ts +5 -3
- package/src/http/core.ts +2 -0
- package/src/http/fs.ts +54 -34
- package/src/http/mcp-body.ts +37 -0
- package/src/http/mcp-user.ts +3 -5
- package/src/http/mcp.ts +6 -7
- package/src/http/memory.ts +26 -15
- package/src/http/page-proxy.ts +61 -5
- package/src/http/pages-public.ts +27 -44
- package/src/http/pages.ts +4 -4
- package/src/http/script-runs.ts +2 -0
- package/src/http/session-access.ts +51 -2
- package/src/http/sessions.ts +249 -10
- package/src/http/tasks.ts +4 -32
- package/src/http/users.ts +12 -1
- package/src/integrations/chat-sdk/adapters.ts +7 -3
- package/src/integrations/chat-sdk/attachments.ts +90 -12
- package/src/integrations/chat-sdk/facts.ts +120 -0
- package/src/integrations/chat-sdk/inbound.ts +156 -8
- package/src/integrations/chat-sdk/limits.ts +24 -0
- package/src/integrations/chat-sdk/outbound-files.ts +186 -0
- package/src/integrations/chat-sdk/outbound.ts +234 -4
- package/src/integrations/chat-sdk/relay.ts +4 -1
- package/src/integrations/chat-sdk/router.ts +28 -2
- package/src/integrations/chat-sdk/steering.ts +9 -0
- package/src/integrations/chat-sdk/templates.ts +14 -0
- package/src/integrations/chat-sdk/thread-buffer.ts +4 -0
- package/src/mcp-limits.ts +20 -0
- package/src/pages/browser-sdk.ts +8 -3
- package/src/pages/feedback-overlay.ts +1 -1
- package/src/providers/acp-adapter.ts +33 -13
- package/src/providers/acp-swarm-events.ts +1 -1
- package/src/providers/amp-adapter.ts +1 -1
- package/src/providers/codex-adapter.ts +106 -119
- package/src/providers/codex-agents-md.ts +35 -229
- package/src/providers/codex-oauth/storage.ts +1 -1
- package/src/providers/cursor-adapter.ts +1 -1
- package/src/rbac/legacy-policy.ts +3 -1
- package/src/rbac/permissions.ts +4 -0
- package/src/realtime/transport.ts +1 -2
- package/src/script-workflows/workflow-ctx.ts +1 -0
- package/src/scripts-runtime/types/stdlib.d.ts +2 -0
- package/src/scripts-runtime/types/swarm-extension.d.ts +8 -0
- package/src/scripts-runtime/types/swarm-sdk.d.ts +2 -0
- package/src/server-user.ts +2 -0
- package/src/server.ts +2 -0
- package/src/slack/assistant.ts +2 -2
- package/src/slack/files.ts +2 -0
- package/src/slack/handlers.ts +4 -4
- package/src/slack/inbound-files.ts +39 -6
- package/src/slack/thread-buffer.ts +2 -1
- package/src/tasks/task-terminal-effects.ts +21 -17
- package/src/tests/acp-adapter.test.ts +10 -23
- package/src/tests/acp-fake-agent.ts +36 -0
- package/src/tests/acp-swarm-events.test.ts +1 -1
- package/src/tests/agent-session-tokens.test.ts +452 -0
- package/src/tests/apps-action-parent-task.test.ts +295 -0
- package/src/tests/apps-card-grid.test.ts +197 -0
- package/src/tests/apps-catalog-additions.test.ts +120 -0
- package/src/tests/apps-tree.test.ts +129 -0
- package/src/tests/chat-sdk-attachments-reply.test.ts +52 -0
- package/src/tests/chat-sdk-config.test.ts +11 -0
- package/src/tests/chat-sdk-facts.test.ts +23 -0
- package/src/tests/chat-sdk-inbound.test.ts +558 -4
- package/src/tests/chat-sdk-outbound-files.test.ts +652 -0
- package/src/tests/codex-adapter.test.ts +167 -242
- package/src/tests/codex-oauth-keep-warm.test.ts +85 -1
- package/src/tests/config-api-only-keys.test.ts +9 -0
- package/src/tests/config-session-auth.test.ts +14 -0
- package/src/tests/cors-allowlist.test.ts +1 -1
- package/src/tests/docs-index-footprint.test.js +2 -2
- package/src/tests/extensions-example-slack-reply-gate.test.ts +262 -91
- package/src/tests/grok-adapter.test.ts +3 -3
- package/src/tests/heartbeat-checklist.test.ts +33 -0
- package/src/tests/heartbeat-jev-gate-credentials.test.ts +44 -0
- package/src/tests/heartbeat-jev-gate.test.ts +265 -1
- package/src/tests/kv-page-proxy.test.ts +91 -5
- package/src/tests/launch-password-rejection.test.ts +2 -2
- package/src/tests/mcp-input-caps.test.ts +294 -0
- package/src/tests/memory-chunked-search-starvation.test.ts +200 -0
- package/src/tests/memory-embedding-input-cap.test.ts +114 -0
- package/src/tests/memory.test.ts +14 -0
- package/src/tests/migration-232-agent-session-tokens.test.ts +67 -0
- package/src/tests/page-guest-session.test.ts +19 -8
- package/src/tests/page-proxy-authed.test.ts +1 -1
- package/src/tests/page-proxy.test.ts +17 -10
- package/src/tests/page-session.test.ts +102 -1
- package/src/tests/pages-authed-mode.test.ts +82 -12
- package/src/tests/pages-password-mode.test.ts +5 -5
- package/src/tests/rbac-engine.test.ts +1 -0
- package/src/tests/realtime-transport.test.ts +13 -7
- package/src/tests/runtime-child-token-cleanup.test.ts +3 -3
- package/src/tests/script-connections.test.ts +2 -0
- package/src/tests/script-runs-http.test.ts +84 -0
- package/src/tests/scripts-http.test.ts +10 -1
- package/src/tests/session-route-posture.test.ts +2 -0
- package/src/tests/swarm-config-export-to-env.test.ts +22 -3
- package/src/tests/task-audio-transcription.test.ts +299 -0
- package/src/tests/task-completion-memory-chunking.test.ts +434 -0
- package/src/tests/task-terminal-secret-scrub.test.ts +6 -1
- package/src/tests/transcription.test.ts +299 -0
- package/src/tests/worker-token-cli.test.ts +76 -0
- package/src/tests/workflow-executors.test.ts +4 -2
- package/src/tests/workflow-system-one-decision-providers.test.ts +98 -1
- package/src/tests/workflow-system-one-decision.test.ts +2 -1
- package/src/tests/workflow-system-one-extraction.test.ts +805 -0
- package/src/tools/chat-access.ts +10 -0
- package/src/tools/chat-post.ts +31 -11
- package/src/tools/chat-reply.ts +32 -10
- package/src/tools/memory-search.ts +3 -1
- package/src/tools/system-one-decide.ts +17 -4
- package/src/types.ts +8 -1
- package/src/utils/config-env-export.ts +3 -1
- package/src/utils/page-session.ts +133 -20
- package/src/utils/request-auth-context.ts +2 -1
- package/src/utils/transcription.ts +246 -0
- package/src/workflows/definition.ts +7 -1
- package/src/workflows/engine.ts +18 -12
- package/src/workflows/executors/index.ts +1 -0
- package/src/workflows/executors/registry.ts +2 -0
- package/src/workflows/executors/system-one-decision.ts +84 -262
- package/src/workflows/executors/system-one-extract-wire.ts +57 -0
- package/src/workflows/executors/system-one-extraction.ts +830 -0
- package/src/workflows/executors/system-one-providers.ts +316 -114
- package/src/workflows/executors/system-one-transport.ts +264 -0
- package/templates/extensions/slack-reply-gate/README.md +24 -22
- package/templates/extensions/slack-reply-gate/hooks.ts +146 -95
- package/templates/extensions/slack-reply-gate/manifest.json +2 -2
- package/templates/official/lead/HEARTBEAT.md +1 -1
- package/templates/skills/apps/SKILL.md +31 -7
- package/templates/skills/apps/content.md +31 -7
- package/templates/skills/chat-sdk/content.md +6 -2
- package/templates/skills/code-quality/content.md +2 -1
- package/templates/skills/heartbeat-runbook/content.md +8 -8
- package/templates/skills/pages/content.md +6 -4
- package/templates/skills/swarm-scripts/SKILL.md +2 -2
- package/templates/skills/swarm-scripts/content.md +2 -2
- package/dist/cli-v1sjhn52.js +0 -7
- package/dist/handlers-2qjw434w.js +0 -39
- package/dist/index-d0g18bax.js +0 -41
|
@@ -155,6 +155,8 @@ import {
|
|
|
155
155
|
computeScore,
|
|
156
156
|
rerank,
|
|
157
157
|
init_reranker,
|
|
158
|
+
searchMemoryCandidates,
|
|
159
|
+
init_search_candidates,
|
|
158
160
|
rowToCandidate,
|
|
159
161
|
init_sqlite_store,
|
|
160
162
|
getEmbeddingProvider2,
|
|
@@ -332,19 +334,19 @@ import {
|
|
|
332
334
|
recordInlineScriptRun2,
|
|
333
335
|
exports_db,
|
|
334
336
|
init_db3
|
|
335
|
-
} from "./cli-
|
|
337
|
+
} from "./cli-wt0jf9hm.js";
|
|
336
338
|
import {
|
|
337
339
|
getUserGrant2,
|
|
338
340
|
init_rbac_roles
|
|
339
|
-
} from "./cli-
|
|
341
|
+
} from "./cli-kpw04va0.js";
|
|
340
342
|
import {
|
|
341
343
|
ensurePricingSeeded2,
|
|
342
344
|
ensureRbacSeeded2,
|
|
343
345
|
ensureModelProfilesSeeded2
|
|
344
|
-
} from "./cli-
|
|
346
|
+
} from "./cli-43x64hv3.js";
|
|
345
347
|
import {
|
|
346
348
|
loadModelsDevCache
|
|
347
|
-
} from "./cli-
|
|
349
|
+
} from "./cli-dk44dxec.js";
|
|
348
350
|
import {
|
|
349
351
|
buildCatalogEntries,
|
|
350
352
|
listModelCatalog,
|
|
@@ -354,12 +356,12 @@ import {
|
|
|
354
356
|
loadModelsCatalog,
|
|
355
357
|
requestModelCatalogRefresh2,
|
|
356
358
|
startPricingRefreshLoop2
|
|
357
|
-
} from "./cli-
|
|
359
|
+
} from "./cli-bnes4z6b.js";
|
|
358
360
|
import {
|
|
359
361
|
ampPinProviderError,
|
|
360
362
|
ampPinCatalogError,
|
|
361
363
|
ampModelError
|
|
362
|
-
} from "./cli-
|
|
364
|
+
} from "./cli-qfxc84gh.js";
|
|
363
365
|
import {
|
|
364
366
|
notifyAutomationPreflightFailure,
|
|
365
367
|
isNeedsSetupFailure,
|
|
@@ -411,7 +413,7 @@ import {
|
|
|
411
413
|
buildNodeInterpolationCtx,
|
|
412
414
|
interpolateNodeConfig,
|
|
413
415
|
scriptBodyInterpolationError
|
|
414
|
-
} from "./cli-
|
|
416
|
+
} from "./cli-9hstj09h.js";
|
|
415
417
|
import {
|
|
416
418
|
require_dist2,
|
|
417
419
|
publicEndpointSsrfOptions,
|
|
@@ -471,14 +473,14 @@ import {
|
|
|
471
473
|
deleteApp,
|
|
472
474
|
typecheckScript,
|
|
473
475
|
parseSkillContent
|
|
474
|
-
} from "./cli-
|
|
476
|
+
} from "./cli-st8aw1m6.js";
|
|
475
477
|
import {
|
|
476
478
|
buildAuthorizationUrl,
|
|
477
479
|
onAuthorizationRefreshed,
|
|
478
480
|
ensureAuthorizationTokenOrThrow,
|
|
479
481
|
ensureToken,
|
|
480
482
|
ensureTokenOrThrow
|
|
481
|
-
} from "./cli-
|
|
483
|
+
} from "./cli-a92r1127.js";
|
|
482
484
|
import {
|
|
483
485
|
detachedProcessGroup,
|
|
484
486
|
registerProcessGroup,
|
|
@@ -508,14 +510,14 @@ import {
|
|
|
508
510
|
getSlackApp2,
|
|
509
511
|
startSlackApp2,
|
|
510
512
|
stopSlackApp2
|
|
511
|
-
} from "./cli-
|
|
513
|
+
} from "./cli-37j04k05.js";
|
|
512
514
|
import {
|
|
513
515
|
slackCode,
|
|
514
516
|
slackMissingScopeMessage,
|
|
515
517
|
withAutoJoin,
|
|
516
518
|
externalChannelToolError2,
|
|
517
519
|
getChannelBlockReason2
|
|
518
|
-
} from "./cli-
|
|
520
|
+
} from "./cli-3a45zcgm.js";
|
|
519
521
|
import {
|
|
520
522
|
BaseExecutor,
|
|
521
523
|
postApprovalCancellationUpdates,
|
|
@@ -523,6 +525,7 @@ import {
|
|
|
523
525
|
HumanInTheLoopExecutor,
|
|
524
526
|
resolveWorkflowLlmConfig,
|
|
525
527
|
SYSTEM_ONE_PROVIDER_IDS,
|
|
528
|
+
SystemOneExtractionExecutor,
|
|
526
529
|
SYSTEM_ONE_DECISION_NODE_TYPE,
|
|
527
530
|
SystemOneDecisionConfigSchema,
|
|
528
531
|
SystemOneDecisionExecutor,
|
|
@@ -532,7 +535,7 @@ import {
|
|
|
532
535
|
definitionNodeIds,
|
|
533
536
|
validateDefinition,
|
|
534
537
|
applyDefinitionPatch
|
|
535
|
-
} from "./cli-
|
|
538
|
+
} from "./cli-xpa64rek.js";
|
|
536
539
|
import {
|
|
537
540
|
workflowEventBus2,
|
|
538
541
|
init_event_bus
|
|
@@ -554,26 +557,30 @@ import {
|
|
|
554
557
|
SESSION_READ_DENIED2,
|
|
555
558
|
canReadSession2,
|
|
556
559
|
readableByFor2,
|
|
560
|
+
denyParentAttach2,
|
|
557
561
|
pathSessionDenial2,
|
|
558
562
|
userAgentIdentityDenial2,
|
|
559
563
|
runtimeInstanceHeader,
|
|
564
|
+
bodyTask,
|
|
560
565
|
routeRegistry,
|
|
561
566
|
isPublicRoute,
|
|
562
567
|
findRoute,
|
|
563
568
|
route
|
|
564
|
-
} from "./cli-
|
|
569
|
+
} from "./cli-018r4jq6.js";
|
|
565
570
|
import {
|
|
566
571
|
isMultiRuntimeEnabled
|
|
567
572
|
} from "./cli-e8xyjvfc.js";
|
|
568
573
|
import {
|
|
574
|
+
FilesError,
|
|
569
575
|
providerPath,
|
|
576
|
+
normalizeStoredKey,
|
|
570
577
|
AgentFsProvider,
|
|
571
578
|
getFileStorageProvider2
|
|
572
|
-
} from "./cli-
|
|
579
|
+
} from "./cli-g9ypd5en.js";
|
|
573
580
|
import {
|
|
574
581
|
getRuntimePool2,
|
|
575
582
|
init_db
|
|
576
|
-
} from "./cli-
|
|
583
|
+
} from "./cli-j99azg3g.js";
|
|
577
584
|
import {
|
|
578
585
|
getMemoryRaterNames,
|
|
579
586
|
REFERENCES_SOURCE_MAX_LENGTH,
|
|
@@ -614,7 +621,7 @@ import {
|
|
|
614
621
|
resolveSessionToken,
|
|
615
622
|
fingerprintApiKey,
|
|
616
623
|
init_users
|
|
617
|
-
} from "./cli-
|
|
624
|
+
} from "./cli-1f3qzw6y.js";
|
|
618
625
|
import {
|
|
619
626
|
isRbacEnabled,
|
|
620
627
|
decideAdmission,
|
|
@@ -623,7 +630,7 @@ import {
|
|
|
623
630
|
init_elevated_agents,
|
|
624
631
|
can,
|
|
625
632
|
init_rbac
|
|
626
|
-
} from "./cli-
|
|
633
|
+
} from "./cli-ba8ne1es.js";
|
|
627
634
|
import {
|
|
628
635
|
normalizeAssetKey,
|
|
629
636
|
parseAssetKey,
|
|
@@ -683,7 +690,7 @@ import {
|
|
|
683
690
|
KvNamespaceSchema,
|
|
684
691
|
KvKeySchema,
|
|
685
692
|
init_types
|
|
686
|
-
} from "./cli-
|
|
693
|
+
} from "./cli-eww120g8.js";
|
|
687
694
|
import {
|
|
688
695
|
generateDefaultClaudeMd2,
|
|
689
696
|
generateDefaultSoulMd2,
|
|
@@ -754,7 +761,7 @@ import {
|
|
|
754
761
|
import {
|
|
755
762
|
init_package,
|
|
756
763
|
package_default
|
|
757
|
-
} from "./cli-
|
|
764
|
+
} from "./cli-94gwyg7m.js";
|
|
758
765
|
import {
|
|
759
766
|
realtimeBus,
|
|
760
767
|
init_bus
|
|
@@ -783,6 +790,7 @@ import {
|
|
|
783
790
|
import {
|
|
784
791
|
scrubSecrets,
|
|
785
792
|
scrubObject,
|
|
793
|
+
createValueScrubber,
|
|
786
794
|
refreshSecretScrubberCache,
|
|
787
795
|
registerVolatileSecret,
|
|
788
796
|
registerSensitiveKeyName,
|
|
@@ -16806,6 +16814,9 @@ class Protocol {
|
|
|
16806
16814
|
this.setRequestHandler(GetTaskPayloadRequestSchema, async (request, extra) => {
|
|
16807
16815
|
const handleTaskResult = async () => {
|
|
16808
16816
|
const taskId = request.params.taskId;
|
|
16817
|
+
if (!await this._taskStore.getTask(taskId, extra.sessionId)) {
|
|
16818
|
+
throw new McpError(ErrorCode.InvalidParams, `Task not found: ${taskId}`);
|
|
16819
|
+
}
|
|
16809
16820
|
if (this._taskMessageQueue) {
|
|
16810
16821
|
let queuedMessage;
|
|
16811
16822
|
while (queuedMessage = await this._taskMessageQueue.dequeue(taskId, extra.sessionId)) {
|
|
@@ -16836,12 +16847,12 @@ class Protocol {
|
|
|
16836
16847
|
throw new McpError(ErrorCode.InvalidParams, `Task not found: ${taskId}`);
|
|
16837
16848
|
}
|
|
16838
16849
|
if (!isTerminal(task.status)) {
|
|
16839
|
-
await this._waitForTaskUpdate(taskId, extra.signal);
|
|
16850
|
+
await this._waitForTaskUpdate(taskId, extra.signal, extra.sessionId);
|
|
16840
16851
|
return await handleTaskResult();
|
|
16841
16852
|
}
|
|
16842
16853
|
if (isTerminal(task.status)) {
|
|
16843
16854
|
const result = await this._taskStore.getTaskResult(taskId, extra.sessionId);
|
|
16844
|
-
this._clearTaskQueue(taskId);
|
|
16855
|
+
this._clearTaskQueue(taskId, extra.sessionId);
|
|
16845
16856
|
return {
|
|
16846
16857
|
...result,
|
|
16847
16858
|
_meta: {
|
|
@@ -16878,7 +16889,7 @@ class Protocol {
|
|
|
16878
16889
|
throw new McpError(ErrorCode.InvalidParams, `Cannot cancel task in terminal status: ${task.status}`);
|
|
16879
16890
|
}
|
|
16880
16891
|
await this._taskStore.updateTaskStatus(request.params.taskId, "cancelled", "Client cancelled task execution.", extra.sessionId);
|
|
16881
|
-
this._clearTaskQueue(request.params.taskId);
|
|
16892
|
+
this._clearTaskQueue(request.params.taskId, extra.sessionId);
|
|
16882
16893
|
const cancelledTask = await this._taskStore.getTask(request.params.taskId, extra.sessionId);
|
|
16883
16894
|
if (!cancelledTask) {
|
|
16884
16895
|
throw new McpError(ErrorCode.InvalidParams, `Task not found after cancellation: ${request.params.taskId}`);
|
|
@@ -17001,6 +17012,19 @@ class Protocol {
|
|
|
17001
17012
|
const handler = this._requestHandlers.get(request.method) ?? this.fallbackRequestHandler;
|
|
17002
17013
|
const capturedTransport = this._transport;
|
|
17003
17014
|
const relatedTaskId = request.params?._meta?.[RELATED_TASK_META_KEY]?.taskId;
|
|
17015
|
+
const sessionId = capturedTransport?.sessionId;
|
|
17016
|
+
const store = this._taskStore;
|
|
17017
|
+
let relatedTaskFound = true;
|
|
17018
|
+
let relatedTaskLookup;
|
|
17019
|
+
if (relatedTaskId && store && this._taskMessageQueue && sessionId !== undefined) {
|
|
17020
|
+
relatedTaskFound = false;
|
|
17021
|
+
relatedTaskLookup = (async () => {
|
|
17022
|
+
if (!await store.getTask(relatedTaskId, sessionId)) {
|
|
17023
|
+
throw new McpError(ErrorCode.InvalidParams, `Task not found: ${relatedTaskId}`);
|
|
17024
|
+
}
|
|
17025
|
+
relatedTaskFound = true;
|
|
17026
|
+
})();
|
|
17027
|
+
}
|
|
17004
17028
|
if (handler === undefined) {
|
|
17005
17029
|
const errorResponse = {
|
|
17006
17030
|
jsonrpc: "2.0",
|
|
@@ -17010,7 +17034,10 @@ class Protocol {
|
|
|
17010
17034
|
message: "Method not found"
|
|
17011
17035
|
}
|
|
17012
17036
|
};
|
|
17013
|
-
if (relatedTaskId &&
|
|
17037
|
+
if (relatedTaskId && relatedTaskLookup) {
|
|
17038
|
+
const queuedError = { type: "error", message: errorResponse, timestamp: Date.now() };
|
|
17039
|
+
relatedTaskLookup.then(() => this._enqueueTaskMessage(relatedTaskId, queuedError, sessionId), () => capturedTransport?.send(errorResponse)).catch((error) => this._onerror(new Error(`Failed to send an error response: ${error}`)));
|
|
17040
|
+
} else if (relatedTaskId && this._taskMessageQueue) {
|
|
17014
17041
|
this._enqueueTaskMessage(relatedTaskId, {
|
|
17015
17042
|
type: "error",
|
|
17016
17043
|
message: errorResponse,
|
|
@@ -17061,7 +17088,10 @@ class Protocol {
|
|
|
17061
17088
|
closeSSEStream: extra?.closeSSEStream,
|
|
17062
17089
|
closeStandaloneSSEStream: extra?.closeStandaloneSSEStream
|
|
17063
17090
|
};
|
|
17064
|
-
Promise.resolve().then(() => {
|
|
17091
|
+
(relatedTaskLookup ?? Promise.resolve()).then(() => {
|
|
17092
|
+
if (relatedTaskLookup && abortController.signal.aborted) {
|
|
17093
|
+
throw new McpError(ErrorCode.ConnectionClosed, "Request was cancelled");
|
|
17094
|
+
}
|
|
17065
17095
|
if (taskCreationParams) {
|
|
17066
17096
|
this.assertTaskHandlerCapability(request.method);
|
|
17067
17097
|
}
|
|
@@ -17096,7 +17126,7 @@ class Protocol {
|
|
|
17096
17126
|
...error["data"] !== undefined && { data: error["data"] }
|
|
17097
17127
|
}
|
|
17098
17128
|
};
|
|
17099
|
-
if (relatedTaskId && this._taskMessageQueue) {
|
|
17129
|
+
if (relatedTaskId && this._taskMessageQueue && relatedTaskFound) {
|
|
17100
17130
|
await this._enqueueTaskMessage(relatedTaskId, {
|
|
17101
17131
|
type: "error",
|
|
17102
17132
|
message: errorResponse,
|
|
@@ -17484,7 +17514,7 @@ class Protocol {
|
|
|
17484
17514
|
throw new Error("Cannot enqueue task message: taskStore and taskMessageQueue are not configured");
|
|
17485
17515
|
}
|
|
17486
17516
|
const maxQueueSize = this._options?.maxTaskQueueSize;
|
|
17487
|
-
await this._taskMessageQueue.enqueue(taskId, message, sessionId, maxQueueSize);
|
|
17517
|
+
await this._taskMessageQueue.enqueue(taskId, message, sessionId ?? this._transport?.sessionId, maxQueueSize);
|
|
17488
17518
|
}
|
|
17489
17519
|
async _clearTaskQueue(taskId, sessionId) {
|
|
17490
17520
|
if (this._taskMessageQueue) {
|
|
@@ -17503,10 +17533,10 @@ class Protocol {
|
|
|
17503
17533
|
}
|
|
17504
17534
|
}
|
|
17505
17535
|
}
|
|
17506
|
-
async _waitForTaskUpdate(taskId, signal) {
|
|
17536
|
+
async _waitForTaskUpdate(taskId, signal, sessionId) {
|
|
17507
17537
|
let interval = this._options?.defaultTaskPollInterval ?? 1000;
|
|
17508
17538
|
try {
|
|
17509
|
-
const task = await this._taskStore?.getTask(taskId);
|
|
17539
|
+
const task = await this._taskStore?.getTask(taskId, sessionId);
|
|
17510
17540
|
if (task?.pollInterval) {
|
|
17511
17541
|
interval = task.pollInterval;
|
|
17512
17542
|
}
|
|
@@ -18175,6 +18205,42 @@ class ExperimentalMcpServerTasks {
|
|
|
18175
18205
|
|
|
18176
18206
|
// node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js
|
|
18177
18207
|
init_zod();
|
|
18208
|
+
function toolInputElementCount(value, max) {
|
|
18209
|
+
let count = 0;
|
|
18210
|
+
const stack = [value];
|
|
18211
|
+
while (stack.length > 0) {
|
|
18212
|
+
const node = stack.pop();
|
|
18213
|
+
if (node === null || typeof node !== "object")
|
|
18214
|
+
continue;
|
|
18215
|
+
if (Array.isArray(node)) {
|
|
18216
|
+
for (const child of node) {
|
|
18217
|
+
if (++count > max)
|
|
18218
|
+
return count;
|
|
18219
|
+
if (child !== null && typeof child === "object")
|
|
18220
|
+
stack.push(child);
|
|
18221
|
+
}
|
|
18222
|
+
} else {
|
|
18223
|
+
for (const key in node) {
|
|
18224
|
+
if (!Object.prototype.hasOwnProperty.call(node, key))
|
|
18225
|
+
continue;
|
|
18226
|
+
if (++count > max)
|
|
18227
|
+
return count;
|
|
18228
|
+
const child = node[key];
|
|
18229
|
+
if (child !== null && typeof child === "object")
|
|
18230
|
+
stack.push(child);
|
|
18231
|
+
}
|
|
18232
|
+
}
|
|
18233
|
+
}
|
|
18234
|
+
return count;
|
|
18235
|
+
}
|
|
18236
|
+
function resolveMaxToolInputElements(value) {
|
|
18237
|
+
if (value === undefined || value === Infinity)
|
|
18238
|
+
return;
|
|
18239
|
+
if (typeof value !== "number" || Number.isNaN(value) || value < 1) {
|
|
18240
|
+
throw new RangeError(`maxToolInputElements must be a number of at least 1, or Infinity, got ${String(value)}`);
|
|
18241
|
+
}
|
|
18242
|
+
return value;
|
|
18243
|
+
}
|
|
18178
18244
|
|
|
18179
18245
|
class McpServer {
|
|
18180
18246
|
constructor(serverInfo, options) {
|
|
@@ -18187,6 +18253,7 @@ class McpServer {
|
|
|
18187
18253
|
this._resourceHandlersInitialized = false;
|
|
18188
18254
|
this._promptHandlersInitialized = false;
|
|
18189
18255
|
this.server = new Server(serverInfo, options);
|
|
18256
|
+
this._maxToolInputElements = resolveMaxToolInputElements(options?.maxToolInputElements);
|
|
18190
18257
|
}
|
|
18191
18258
|
get experimental() {
|
|
18192
18259
|
if (!this._experimental) {
|
|
@@ -18293,12 +18360,15 @@ class McpServer {
|
|
|
18293
18360
|
};
|
|
18294
18361
|
}
|
|
18295
18362
|
async validateToolInput(tool, args, toolName) {
|
|
18363
|
+
if (this._maxToolInputElements !== undefined && toolInputElementCount(args, this._maxToolInputElements) > this._maxToolInputElements) {
|
|
18364
|
+
throw new McpError(ErrorCode.InvalidParams, `Invalid arguments for tool ${toolName}: arguments contain more than the maximum of ${this._maxToolInputElements} elements`);
|
|
18365
|
+
}
|
|
18296
18366
|
if (!tool.inputSchema) {
|
|
18297
18367
|
return;
|
|
18298
18368
|
}
|
|
18299
18369
|
const inputObj = normalizeObjectSchema(tool.inputSchema);
|
|
18300
18370
|
const schemaToParse = inputObj ?? tool.inputSchema;
|
|
18301
|
-
const parseResult = await safeParseAsync2(schemaToParse, args);
|
|
18371
|
+
const parseResult = await safeParseAsync2(schemaToParse, args ?? {});
|
|
18302
18372
|
if (!parseResult.success) {
|
|
18303
18373
|
const error = "error" in parseResult ? parseResult.error : "Unknown error";
|
|
18304
18374
|
const errorMessage = getParseErrorMessage(error);
|
|
@@ -18523,7 +18593,7 @@ class McpServer {
|
|
|
18523
18593
|
}
|
|
18524
18594
|
if (prompt.argsSchema) {
|
|
18525
18595
|
const argsObj = normalizeObjectSchema(prompt.argsSchema);
|
|
18526
|
-
const parseResult = await safeParseAsync2(argsObj, request.params.arguments);
|
|
18596
|
+
const parseResult = await safeParseAsync2(argsObj, request.params.arguments ?? {});
|
|
18527
18597
|
if (!parseResult.success) {
|
|
18528
18598
|
const error = "error" in parseResult ? parseResult.error : "Unknown error";
|
|
18529
18599
|
const errorMessage = getParseErrorMessage(error);
|
|
@@ -21146,7 +21216,7 @@ class NotifyExecutor extends BaseExecutor {
|
|
|
21146
21216
|
}
|
|
21147
21217
|
}
|
|
21148
21218
|
case "slack": {
|
|
21149
|
-
const { getSlackApp } = await import("./app-
|
|
21219
|
+
const { getSlackApp } = await import("./app-353vre8g.js");
|
|
21150
21220
|
const app = getSlackApp();
|
|
21151
21221
|
if (!app) {
|
|
21152
21222
|
return {
|
|
@@ -21272,7 +21342,7 @@ var RawLlmOutputSchema = object2({
|
|
|
21272
21342
|
async function executeRawLlm(config) {
|
|
21273
21343
|
let modelName = config.model ?? "google/gemini-3-flash-preview";
|
|
21274
21344
|
try {
|
|
21275
|
-
const { createOpenAI } = await import("./index-
|
|
21345
|
+
const { createOpenAI } = await import("./index-6srwvd5b.js");
|
|
21276
21346
|
const llmConfig = await resolveWorkflowLlmConfig(config.model);
|
|
21277
21347
|
modelName = llmConfig.model;
|
|
21278
21348
|
const provider = createOpenAI({
|
|
@@ -21282,7 +21352,7 @@ async function executeRawLlm(config) {
|
|
|
21282
21352
|
});
|
|
21283
21353
|
const model = provider(llmConfig.model);
|
|
21284
21354
|
if (config.schema) {
|
|
21285
|
-
const { generateObject, jsonSchema } = await import("./index-
|
|
21355
|
+
const { generateObject, jsonSchema } = await import("./index-cbxkmfc5.js");
|
|
21286
21356
|
const { object } = await generateObject({
|
|
21287
21357
|
model,
|
|
21288
21358
|
schema: jsonSchema(config.schema),
|
|
@@ -21296,7 +21366,7 @@ async function executeRawLlm(config) {
|
|
|
21296
21366
|
output: { result: object, model: modelName }
|
|
21297
21367
|
};
|
|
21298
21368
|
}
|
|
21299
|
-
const { generateText } = await import("./index-
|
|
21369
|
+
const { generateText } = await import("./index-cbxkmfc5.js");
|
|
21300
21370
|
const { text } = await generateText({
|
|
21301
21371
|
model,
|
|
21302
21372
|
prompt: config.prompt
|
|
@@ -21736,8 +21806,8 @@ class ValidateExecutor extends BaseExecutor {
|
|
|
21736
21806
|
const interpolatedPrompt = this.deps.interpolate(prompt, context);
|
|
21737
21807
|
const outputStr = typeof targetOutput === "string" ? targetOutput : JSON.stringify(targetOutput);
|
|
21738
21808
|
try {
|
|
21739
|
-
const { createOpenAI } = await import("./index-
|
|
21740
|
-
const { generateObject, jsonSchema } = await import("./index-
|
|
21809
|
+
const { createOpenAI } = await import("./index-6srwvd5b.js");
|
|
21810
|
+
const { generateObject, jsonSchema } = await import("./index-cbxkmfc5.js");
|
|
21741
21811
|
const llmConfig = await resolveWorkflowLlmConfig();
|
|
21742
21812
|
const provider = createOpenAI({
|
|
21743
21813
|
baseURL: llmConfig.baseURL,
|
|
@@ -21909,6 +21979,7 @@ function createExecutorRegistry(deps) {
|
|
|
21909
21979
|
registry.register(new NotifyExecutor(deps));
|
|
21910
21980
|
registry.register(new RawLlmExecutor(deps));
|
|
21911
21981
|
registry.register(new SystemOneDecisionExecutor(deps));
|
|
21982
|
+
registry.register(new SystemOneExtractionExecutor(deps));
|
|
21912
21983
|
registry.register(new ScriptExecutor(deps));
|
|
21913
21984
|
registry.register(new SwarmScriptExecutor(deps));
|
|
21914
21985
|
registry.register(new VcsExecutor(deps));
|
|
@@ -24508,7 +24579,7 @@ function setPreloadedTools(server, names) {
|
|
|
24508
24579
|
async function applyPreToolCall(name, args, requestInfo, inputSchema) {
|
|
24509
24580
|
if (requestInfo.callOrigin !== "mcp")
|
|
24510
24581
|
return { args };
|
|
24511
|
-
const dispatcher = await import("./dispatcher-
|
|
24582
|
+
const dispatcher = await import("./dispatcher-c155xz0p.js");
|
|
24512
24583
|
const result = await dispatcher.dispatchPre("pre.tool.call", { tool: name, args, requestInfo }, inputSchema ? {
|
|
24513
24584
|
validateModify: async (data) => {
|
|
24514
24585
|
const schema = normalizeObjectSchema(inputSchema) ?? inputSchema;
|
|
@@ -31264,7 +31335,11 @@ async function loadAdapter(name, config, logger) {
|
|
|
31264
31335
|
switch (name) {
|
|
31265
31336
|
case "telegram": {
|
|
31266
31337
|
const { createTelegramAdapter } = await import("./index-g216q6jr.js");
|
|
31267
|
-
return createTelegramAdapter({
|
|
31338
|
+
return createTelegramAdapter({
|
|
31339
|
+
...base,
|
|
31340
|
+
allowUnverifiedWebhooks: false,
|
|
31341
|
+
mentionOnReply: true
|
|
31342
|
+
});
|
|
31268
31343
|
}
|
|
31269
31344
|
case "slack": {
|
|
31270
31345
|
const { createSlackAdapter } = await import("./index-zgvqzjsw.js");
|
|
@@ -31866,6 +31941,43 @@ function resetDiscordGatewayHealth() {
|
|
|
31866
31941
|
// src/integrations/chat-sdk/inbound.ts
|
|
31867
31942
|
init_zod();
|
|
31868
31943
|
init_db3();
|
|
31944
|
+
|
|
31945
|
+
// src/be/unmapped-identities.ts
|
|
31946
|
+
init_db3();
|
|
31947
|
+
var TTL_MS = 30 * 24 * 60 * 60 * 1000;
|
|
31948
|
+
function namespace(kind) {
|
|
31949
|
+
return `integration:unmapped:${kind}`;
|
|
31950
|
+
}
|
|
31951
|
+
async function recordUnmappedIdentity(kind, externalId, meta) {
|
|
31952
|
+
const ns = namespace(kind);
|
|
31953
|
+
const now = new Date().toISOString();
|
|
31954
|
+
const expiresAt = Date.now() + TTL_MS;
|
|
31955
|
+
const countKey = `${externalId}:count`;
|
|
31956
|
+
const countBefore = await getKv2(ns, countKey);
|
|
31957
|
+
await upsertKv2({
|
|
31958
|
+
namespace: ns,
|
|
31959
|
+
key: `${externalId}:meta`,
|
|
31960
|
+
value: {
|
|
31961
|
+
lastSeenAt: now,
|
|
31962
|
+
sampleEventType: meta.sampleEventType,
|
|
31963
|
+
sampleContext: meta.sampleContext.slice(0, 100)
|
|
31964
|
+
},
|
|
31965
|
+
valueType: "json",
|
|
31966
|
+
expiresAt
|
|
31967
|
+
});
|
|
31968
|
+
const incremented = await incrKv2(ns, countKey, 1);
|
|
31969
|
+
if (countBefore === null) {
|
|
31970
|
+
await upsertKv2({
|
|
31971
|
+
namespace: ns,
|
|
31972
|
+
key: countKey,
|
|
31973
|
+
value: Number(incremented.value),
|
|
31974
|
+
valueType: "integer",
|
|
31975
|
+
expiresAt
|
|
31976
|
+
});
|
|
31977
|
+
}
|
|
31978
|
+
}
|
|
31979
|
+
|
|
31980
|
+
// src/integrations/chat-sdk/inbound.ts
|
|
31869
31981
|
init_resolver();
|
|
31870
31982
|
init_context_key();
|
|
31871
31983
|
init_secret_scrubber();
|
|
@@ -31914,10 +32026,191 @@ async function recordTaskAttachmentUpload(input) {
|
|
|
31914
32026
|
throw error;
|
|
31915
32027
|
}
|
|
31916
32028
|
}
|
|
32029
|
+
function scopeFromAttachment(attachment) {
|
|
32030
|
+
const storedKey = attachment.providerKey ?? attachment.path ?? "";
|
|
32031
|
+
return {
|
|
32032
|
+
taskId: attachment.taskId,
|
|
32033
|
+
name: attachment.name,
|
|
32034
|
+
key: storedKey.trim() ? storedKey : undefined,
|
|
32035
|
+
orgId: attachment.orgId,
|
|
32036
|
+
driveId: attachment.driveId
|
|
32037
|
+
};
|
|
32038
|
+
}
|
|
32039
|
+
function backingProviderId(attachment) {
|
|
32040
|
+
if (attachment.kind === "agent-fs")
|
|
32041
|
+
return attachment.providerId ?? "agent-fs";
|
|
32042
|
+
if (attachment.providerId === "local-fs")
|
|
32043
|
+
return "local-fs";
|
|
32044
|
+
return null;
|
|
32045
|
+
}
|
|
32046
|
+
|
|
32047
|
+
// src/utils/transcription.ts
|
|
32048
|
+
init_secret_scrubber();
|
|
32049
|
+
var TRANSCRIPTION_TIMEOUT_MS = 60000;
|
|
32050
|
+
var TRANSCRIPTION_API_KEY_ENV = "TRANSCRIPTION_API_KEY";
|
|
32051
|
+
var openAIShape = {
|
|
32052
|
+
path: "/audio/transcriptions",
|
|
32053
|
+
modelField: "model",
|
|
32054
|
+
authHeaders: (apiKey) => ({ authorization: `Bearer ${apiKey}` })
|
|
32055
|
+
};
|
|
32056
|
+
var PROVIDERS = {
|
|
32057
|
+
openai: {
|
|
32058
|
+
keyEnv: "OPENAI_API_KEY",
|
|
32059
|
+
defaultBaseUrl: "https://api.openai.com/v1",
|
|
32060
|
+
defaultModel: "whisper-1",
|
|
32061
|
+
...openAIShape
|
|
32062
|
+
},
|
|
32063
|
+
groq: {
|
|
32064
|
+
keyEnv: "GROQ_API_KEY",
|
|
32065
|
+
defaultBaseUrl: "https://api.groq.com/openai/v1",
|
|
32066
|
+
defaultModel: "whisper-large-v3-turbo",
|
|
32067
|
+
...openAIShape
|
|
32068
|
+
},
|
|
32069
|
+
elevenlabs: {
|
|
32070
|
+
keyEnv: "ELEVENLABS_API_KEY",
|
|
32071
|
+
defaultBaseUrl: "https://api.elevenlabs.io/v1",
|
|
32072
|
+
defaultModel: "scribe_v2",
|
|
32073
|
+
path: "/speech-to-text",
|
|
32074
|
+
modelField: "model_id",
|
|
32075
|
+
authHeaders: (apiKey) => ({ "xi-api-key": apiKey })
|
|
32076
|
+
}
|
|
32077
|
+
};
|
|
32078
|
+
var AUTO_DETECT_ORDER = ["elevenlabs", "openai", "groq"];
|
|
32079
|
+
var TRANSCRIPTION_ENV_KEYS = [
|
|
32080
|
+
TRANSCRIPTION_API_KEY_ENV,
|
|
32081
|
+
"TRANSCRIPTION_PROVIDER",
|
|
32082
|
+
"TRANSCRIPTION_BASE_URL",
|
|
32083
|
+
"TRANSCRIPTION_MODEL",
|
|
32084
|
+
...AUTO_DETECT_ORDER.map((name) => PROVIDERS[name].keyEnv)
|
|
32085
|
+
];
|
|
32086
|
+
|
|
32087
|
+
class TranscriptionError extends Error {
|
|
32088
|
+
constructor(message) {
|
|
32089
|
+
super(message);
|
|
32090
|
+
this.name = "TranscriptionError";
|
|
32091
|
+
}
|
|
32092
|
+
}
|
|
32093
|
+
function envValue(key) {
|
|
32094
|
+
return process.env[key]?.trim() || undefined;
|
|
32095
|
+
}
|
|
32096
|
+
function resolveTranscriptionConfig() {
|
|
32097
|
+
const pinned = envValue("TRANSCRIPTION_PROVIDER")?.toLowerCase();
|
|
32098
|
+
const explicitKey = envValue(TRANSCRIPTION_API_KEY_ENV);
|
|
32099
|
+
if (explicitKey) {
|
|
32100
|
+
return {
|
|
32101
|
+
provider: pinned ?? "openai",
|
|
32102
|
+
apiKey: explicitKey,
|
|
32103
|
+
keyEnv: TRANSCRIPTION_API_KEY_ENV,
|
|
32104
|
+
source: "explicit"
|
|
32105
|
+
};
|
|
32106
|
+
}
|
|
32107
|
+
const candidates = pinned ? AUTO_DETECT_ORDER.filter((name) => name === pinned) : AUTO_DETECT_ORDER;
|
|
32108
|
+
for (const name of candidates) {
|
|
32109
|
+
const { keyEnv } = PROVIDERS[name];
|
|
32110
|
+
const apiKey = envValue(keyEnv);
|
|
32111
|
+
if (apiKey)
|
|
32112
|
+
return { provider: name, apiKey, keyEnv, source: "auto" };
|
|
32113
|
+
}
|
|
32114
|
+
return null;
|
|
32115
|
+
}
|
|
32116
|
+
function isTranscriptionConfigured() {
|
|
32117
|
+
return resolveTranscriptionConfig() !== null;
|
|
32118
|
+
}
|
|
32119
|
+
function providerSpec(name) {
|
|
32120
|
+
if (!Object.hasOwn(PROVIDERS, name)) {
|
|
32121
|
+
throw new TranscriptionError(`TRANSCRIPTION_PROVIDER "${name}" is not supported (use ${Object.keys(PROVIDERS).join(", ")})`);
|
|
32122
|
+
}
|
|
32123
|
+
return PROVIDERS[name];
|
|
32124
|
+
}
|
|
32125
|
+
function errorDetail(payload, status) {
|
|
32126
|
+
const error = payload?.error;
|
|
32127
|
+
if (typeof error?.message === "string")
|
|
32128
|
+
return error.message;
|
|
32129
|
+
const detail = payload?.detail;
|
|
32130
|
+
if (typeof detail === "string")
|
|
32131
|
+
return detail;
|
|
32132
|
+
if (typeof detail?.message === "string")
|
|
32133
|
+
return detail.message;
|
|
32134
|
+
return `HTTP ${status}`;
|
|
32135
|
+
}
|
|
32136
|
+
async function transcribeAudio(input) {
|
|
32137
|
+
const config = resolveTranscriptionConfig();
|
|
32138
|
+
if (!config)
|
|
32139
|
+
throw new TranscriptionError("no transcription provider key is set");
|
|
32140
|
+
const { apiKey } = config;
|
|
32141
|
+
const provider = providerSpec(config.provider);
|
|
32142
|
+
const baseUrlOverride = config.source === "explicit" ? process.env.TRANSCRIPTION_BASE_URL?.trim() : undefined;
|
|
32143
|
+
const baseUrl = (baseUrlOverride || provider.defaultBaseUrl).replace(/\/+$/, "");
|
|
32144
|
+
const keyScrubber = createValueScrubber([{ value: apiKey, name: config.keyEnv }]);
|
|
32145
|
+
const scrub = (text) => scrubSecrets(keyScrubber.text(text));
|
|
32146
|
+
const form = new FormData;
|
|
32147
|
+
const type = input.mimeType ?? input.data.type;
|
|
32148
|
+
form.append("file", type ? new Blob([input.data], { type }) : input.data, input.filename);
|
|
32149
|
+
form.append(provider.modelField, process.env.TRANSCRIPTION_MODEL?.trim() || provider.defaultModel);
|
|
32150
|
+
let response;
|
|
32151
|
+
try {
|
|
32152
|
+
response = await fetch(`${baseUrl}${provider.path}`, {
|
|
32153
|
+
method: "POST",
|
|
32154
|
+
headers: provider.authHeaders(apiKey),
|
|
32155
|
+
body: form,
|
|
32156
|
+
signal: AbortSignal.timeout(TRANSCRIPTION_TIMEOUT_MS)
|
|
32157
|
+
});
|
|
32158
|
+
} catch (error) {
|
|
32159
|
+
if (error instanceof Error && error.name === "TimeoutError") {
|
|
32160
|
+
throw new TranscriptionError(`no answer within ${TRANSCRIPTION_TIMEOUT_MS / 1000} s`);
|
|
32161
|
+
}
|
|
32162
|
+
throw new TranscriptionError(scrub(error instanceof Error ? error.message : String(error)));
|
|
32163
|
+
}
|
|
32164
|
+
const payload = await response.json().catch(() => null);
|
|
32165
|
+
if (!response.ok || typeof payload?.text !== "string") {
|
|
32166
|
+
throw new TranscriptionError(scrub(errorDetail(payload, response.status)));
|
|
32167
|
+
}
|
|
32168
|
+
return payload.text.trim();
|
|
32169
|
+
}
|
|
32170
|
+
var NOT_TRANSCRIBED_NOTE = `(not transcribed: no transcription provider configured, set ${TRANSCRIPTION_API_KEY_ENV} or one of ${AUTO_DETECT_ORDER.map((name) => PROVIDERS[name].keyEnv).join(", ")})`;
|
|
32171
|
+
var AUDIO_EXTENSIONS = {
|
|
32172
|
+
"audio/ogg": "ogg",
|
|
32173
|
+
"audio/opus": "ogg",
|
|
32174
|
+
"audio/mpeg": "mp3",
|
|
32175
|
+
"audio/mp4": "m4a",
|
|
32176
|
+
"audio/x-m4a": "m4a",
|
|
32177
|
+
"audio/wav": "wav",
|
|
32178
|
+
"audio/x-wav": "wav",
|
|
32179
|
+
"audio/webm": "webm"
|
|
32180
|
+
};
|
|
32181
|
+
async function transcribeAudioNotes(files, logPrefix) {
|
|
32182
|
+
const notes = new Map;
|
|
32183
|
+
if (files.length === 0)
|
|
32184
|
+
return notes;
|
|
32185
|
+
if (!isTranscriptionConfigured()) {
|
|
32186
|
+
for (const file of files)
|
|
32187
|
+
notes.set(file.key, NOT_TRANSCRIBED_NOTE);
|
|
32188
|
+
return notes;
|
|
32189
|
+
}
|
|
32190
|
+
for (const file of files) {
|
|
32191
|
+
const extension = AUDIO_EXTENSIONS[file.mimeType ?? ""] ?? "ogg";
|
|
32192
|
+
const filename = /\.\w+$/.test(file.name) ? file.name : `${file.name}.${extension}`;
|
|
32193
|
+
try {
|
|
32194
|
+
const text = await transcribeAudio({ data: file.data, filename, mimeType: file.mimeType });
|
|
32195
|
+
notes.set(file.key, `[Transcript of ${file.name}]
|
|
32196
|
+
${text || "(no speech recognized)"}`);
|
|
32197
|
+
} catch (error) {
|
|
32198
|
+
const reason = scrubSecrets(error instanceof Error ? error.message : String(error));
|
|
32199
|
+
console.warn(`${logPrefix} could not transcribe file ${file.key}: ${reason}`);
|
|
32200
|
+
notes.set(file.key, `(transcription failed: ${reason})`);
|
|
32201
|
+
}
|
|
32202
|
+
}
|
|
32203
|
+
return notes;
|
|
32204
|
+
}
|
|
31917
32205
|
|
|
31918
32206
|
// src/integrations/chat-sdk/attachments.ts
|
|
31919
32207
|
var DRAFT_LEASE_REFRESH_MS = 60000;
|
|
31920
32208
|
var SHARED_FILE_INTENT = "user-upload";
|
|
32209
|
+
var MB = 1024 * 1024;
|
|
32210
|
+
var CHAT_INBOUND_FILE_LIMITS = { telegram: 20 * MB };
|
|
32211
|
+
function chatInboundFileLimit(adapter) {
|
|
32212
|
+
return Math.min(CHAT_INBOUND_FILE_LIMITS[adapter] ?? MAX_TASK_ATTACHMENT_BYTES, MAX_TASK_ATTACHMENT_BYTES);
|
|
32213
|
+
}
|
|
31921
32214
|
function formatFileSize(bytes) {
|
|
31922
32215
|
if (bytes < 1024)
|
|
31923
32216
|
return `${bytes} B`;
|
|
@@ -31938,16 +32231,42 @@ function toChatFiles(adapter, messageId, attachments) {
|
|
|
31938
32231
|
attachment
|
|
31939
32232
|
}));
|
|
31940
32233
|
}
|
|
31941
|
-
function buildChatAttachmentText(files, failed = []) {
|
|
32234
|
+
function buildChatAttachmentText(files, failed = [], notes = new Map) {
|
|
31942
32235
|
const reasons = new Map(failed.map((f) => [f.file.id, f.reason]));
|
|
31943
32236
|
return files.map((f) => {
|
|
31944
32237
|
const size = typeof f.size === "number" ? formatFileSize(f.size) : "unknown size";
|
|
31945
32238
|
const line = `[File: ${f.name} (${f.mimeType ?? "unknown type"}, ${size}) id=${f.id}]`;
|
|
31946
32239
|
const reason = reasons.get(f.id);
|
|
31947
|
-
|
|
32240
|
+
const note = notes.get(f.id);
|
|
32241
|
+
return [reason ? `${line} (not attached: ${reason})` : line, note].filter(Boolean).join(`
|
|
32242
|
+
`);
|
|
31948
32243
|
}).join(`
|
|
31949
32244
|
`);
|
|
31950
32245
|
}
|
|
32246
|
+
function markdownLiteral(value) {
|
|
32247
|
+
const text = value.replace(/[\r\n]+/g, " ");
|
|
32248
|
+
const longestRun = Math.max(0, ...(text.match(/`+/g) ?? []).map((run) => run.length));
|
|
32249
|
+
const fence = "`".repeat(longestRun + 1);
|
|
32250
|
+
const pad = /^[` ]|[` ]$/.test(text) ? " " : "";
|
|
32251
|
+
return `${fence}${pad}${text}${pad}${fence}`;
|
|
32252
|
+
}
|
|
32253
|
+
function formatTooLargeReply(failed) {
|
|
32254
|
+
const lines = failed.map((f) => `- ${markdownLiteral(f.file.name)}: ${f.reason}`);
|
|
32255
|
+
return [
|
|
32256
|
+
`Too large to read, so the swarm did not get ${failed.length === 1 ? "this file" : "these files"}:`,
|
|
32257
|
+
...lines,
|
|
32258
|
+
"Send a smaller file or a link."
|
|
32259
|
+
].join(`
|
|
32260
|
+
`);
|
|
32261
|
+
}
|
|
32262
|
+
async function transcribeChatAudio(fetched) {
|
|
32263
|
+
return transcribeAudioNotes(fetched.filter(({ file }) => file.attachment.type === "audio").map(({ file, path }) => ({
|
|
32264
|
+
key: file.id,
|
|
32265
|
+
name: file.name,
|
|
32266
|
+
data: Bun.file(path),
|
|
32267
|
+
mimeType: file.mimeType
|
|
32268
|
+
})), "[chat-sdk]");
|
|
32269
|
+
}
|
|
31951
32270
|
async function readAttachment(attachment) {
|
|
31952
32271
|
if (attachment.data instanceof Blob)
|
|
31953
32272
|
return new Uint8Array(await attachment.data.arrayBuffer());
|
|
@@ -31971,17 +32290,25 @@ async function fetchChatFiles(files) {
|
|
|
31971
32290
|
};
|
|
31972
32291
|
if (files.length === 0)
|
|
31973
32292
|
return result;
|
|
31974
|
-
const
|
|
32293
|
+
const tooLarge = (file, size) => {
|
|
32294
|
+
const limit = chatInboundFileLimit(file.adapter);
|
|
32295
|
+
const platform = file.adapter.charAt(0).toUpperCase() + file.adapter.slice(1);
|
|
32296
|
+
return {
|
|
32297
|
+
file,
|
|
32298
|
+
reason: `too large (${formatFileSize(size)}, the limit for files sent to the ${platform} bot is ${formatFileSize(limit)})`,
|
|
32299
|
+
tooLarge: true
|
|
32300
|
+
};
|
|
32301
|
+
};
|
|
31975
32302
|
dir = await mkdtemp(join(tmpdir2(), "chat-files-"));
|
|
31976
32303
|
for (const [index, file] of files.entries()) {
|
|
31977
|
-
if (typeof file.size === "number" && file.size >
|
|
31978
|
-
result.failed.push(
|
|
32304
|
+
if (typeof file.size === "number" && file.size > chatInboundFileLimit(file.adapter)) {
|
|
32305
|
+
result.failed.push(tooLarge(file, file.size));
|
|
31979
32306
|
continue;
|
|
31980
32307
|
}
|
|
31981
32308
|
try {
|
|
31982
32309
|
const bytes = await readAttachment(file.attachment);
|
|
31983
|
-
if (bytes.byteLength >
|
|
31984
|
-
result.failed.push(
|
|
32310
|
+
if (bytes.byteLength > chatInboundFileLimit(file.adapter)) {
|
|
32311
|
+
result.failed.push(tooLarge(file, bytes.byteLength));
|
|
31985
32312
|
continue;
|
|
31986
32313
|
}
|
|
31987
32314
|
const path = join(dir, String(index));
|
|
@@ -32056,6 +32383,63 @@ async function attachChatFilesToTask(taskId, fetched) {
|
|
|
32056
32383
|
return unattached;
|
|
32057
32384
|
}
|
|
32058
32385
|
|
|
32386
|
+
// src/integrations/chat-sdk/facts.ts
|
|
32387
|
+
var SNIPPET_MAX = 80;
|
|
32388
|
+
function snippet2(text) {
|
|
32389
|
+
const flat = text?.replace(/\s+/g, " ").trim();
|
|
32390
|
+
if (!flat)
|
|
32391
|
+
return;
|
|
32392
|
+
return flat.length > SNIPPET_MAX ? `${flat.slice(0, SNIPPET_MAX)}...` : flat;
|
|
32393
|
+
}
|
|
32394
|
+
function personLabel(name, username, fallback) {
|
|
32395
|
+
if (name && username && name !== username)
|
|
32396
|
+
return `${name} (@${username})`;
|
|
32397
|
+
if (username)
|
|
32398
|
+
return `@${username}`;
|
|
32399
|
+
return name || fallback;
|
|
32400
|
+
}
|
|
32401
|
+
function telegramFacts(raw, message, botUserId) {
|
|
32402
|
+
const reply = raw.reply_to_message;
|
|
32403
|
+
const replyIsTopicRoot = reply !== undefined && (reply.forum_topic_created !== undefined || raw.is_topic_message === true && reply.message_id === raw.message_thread_id);
|
|
32404
|
+
const realReply = reply && !replyIsTopicRoot ? reply : undefined;
|
|
32405
|
+
const topicName = replyIsTopicRoot ? reply?.forum_topic_created?.name : undefined;
|
|
32406
|
+
const name = [raw.from?.first_name, raw.from?.last_name].filter(Boolean).join(" ").trim();
|
|
32407
|
+
return {
|
|
32408
|
+
chatType: raw.chat?.type,
|
|
32409
|
+
isForum: raw.chat?.is_forum === true ? true : undefined,
|
|
32410
|
+
title: raw.chat?.title,
|
|
32411
|
+
topic: raw.is_topic_message === true && raw.message_thread_id !== undefined ? topicName ? `"${topicName}"` : `#${raw.message_thread_id}` : undefined,
|
|
32412
|
+
from: personLabel(name || undefined, raw.from?.username, message.author.userId),
|
|
32413
|
+
replyToBot: realReply?.from?.id !== undefined && botUserId !== undefined && String(realReply.from.id) === botUserId,
|
|
32414
|
+
replyToSnippet: snippet2(realReply?.text ?? realReply?.caption)
|
|
32415
|
+
};
|
|
32416
|
+
}
|
|
32417
|
+
function readChatMessageFacts(thread, message) {
|
|
32418
|
+
const raw = message.raw;
|
|
32419
|
+
if (thread.adapter.name === "telegram" && raw && typeof raw === "object") {
|
|
32420
|
+
return telegramFacts(raw, message, thread.adapter.botUserId);
|
|
32421
|
+
}
|
|
32422
|
+
const { fullName, userName, userId } = message.author;
|
|
32423
|
+
return {
|
|
32424
|
+
chatType: thread.isDM ? "dm" : undefined,
|
|
32425
|
+
from: personLabel(fullName || undefined, userName || undefined, userId),
|
|
32426
|
+
replyToBot: message.replyTo?.author.isMe === true,
|
|
32427
|
+
replyToSnippet: snippet2(message.replyTo?.text)
|
|
32428
|
+
};
|
|
32429
|
+
}
|
|
32430
|
+
function formatChatHeaderFacts(adapter, facts, addressed) {
|
|
32431
|
+
const oneLine = (text) => text.replace(/\s+/g, " ").trim();
|
|
32432
|
+
const parts = [adapter];
|
|
32433
|
+
if (facts.chatType)
|
|
32434
|
+
parts.push(facts.title ? `${facts.chatType} "${oneLine(facts.title)}"` : facts.chatType);
|
|
32435
|
+
if (facts.isForum)
|
|
32436
|
+
parts.push(facts.topic ? `forum topic ${oneLine(facts.topic)}` : "forum");
|
|
32437
|
+
parts.push(`from: ${oneLine(facts.from)}`, `addressed: ${addressed}`);
|
|
32438
|
+
if (facts.replyToSnippet)
|
|
32439
|
+
parts.push(`reply-to: "${facts.replyToSnippet}"`);
|
|
32440
|
+
return parts.join(" · ");
|
|
32441
|
+
}
|
|
32442
|
+
|
|
32059
32443
|
// src/integrations/chat-sdk/outbound.ts
|
|
32060
32444
|
init_secret_scrubber();
|
|
32061
32445
|
init_event_bus();
|
|
@@ -32071,6 +32455,17 @@ var FALLBACK_LIMIT = 2000;
|
|
|
32071
32455
|
function chatMessageLimit(adapter) {
|
|
32072
32456
|
return CHAT_MESSAGE_LIMITS[adapter] ?? FALLBACK_LIMIT;
|
|
32073
32457
|
}
|
|
32458
|
+
var MB2 = 1024 * 1024;
|
|
32459
|
+
var CHAT_UPLOAD_LIMITS = {
|
|
32460
|
+
telegram: 50 * MB2,
|
|
32461
|
+
discord: 10 * MB2
|
|
32462
|
+
};
|
|
32463
|
+
var FALLBACK_UPLOAD_LIMIT = 50 * MB2;
|
|
32464
|
+
var TELEGRAM_PHOTO_LIMIT = 10 * MB2;
|
|
32465
|
+
function chatUploadLimit(adapter) {
|
|
32466
|
+
return CHAT_UPLOAD_LIMITS[adapter] ?? FALLBACK_UPLOAD_LIMIT;
|
|
32467
|
+
}
|
|
32468
|
+
var CHAT_FILES_PER_MESSAGE = 10;
|
|
32074
32469
|
function splitChatMessage(text, limit) {
|
|
32075
32470
|
if (limit <= 0)
|
|
32076
32471
|
throw new Error("splitChatMessage: limit must be positive");
|
|
@@ -32111,6 +32506,15 @@ function adapterOfChatId(id) {
|
|
|
32111
32506
|
const index = id.indexOf(":");
|
|
32112
32507
|
return index === -1 ? id : id.slice(0, index);
|
|
32113
32508
|
}
|
|
32509
|
+
|
|
32510
|
+
class ChatFileTooLargeError extends Error {
|
|
32511
|
+
sizeBytes;
|
|
32512
|
+
constructor(sizeBytes) {
|
|
32513
|
+
super(`file is ${formatFileSize(sizeBytes)}`);
|
|
32514
|
+
this.sizeBytes = sizeBytes;
|
|
32515
|
+
this.name = "ChatFileTooLargeError";
|
|
32516
|
+
}
|
|
32517
|
+
}
|
|
32114
32518
|
async function postChunks(adapter, target, text) {
|
|
32115
32519
|
const messageIds = [];
|
|
32116
32520
|
let threadId;
|
|
@@ -32121,6 +32525,125 @@ async function postChunks(adapter, target, text) {
|
|
|
32121
32525
|
}
|
|
32122
32526
|
return { messageIds, threadId };
|
|
32123
32527
|
}
|
|
32528
|
+
function resolveMimeType(name, ...candidates) {
|
|
32529
|
+
for (const candidate of candidates) {
|
|
32530
|
+
const type = candidate?.split(";")[0]?.trim().toLowerCase();
|
|
32531
|
+
if (type && type !== "application/octet-stream")
|
|
32532
|
+
return type;
|
|
32533
|
+
}
|
|
32534
|
+
return Bun.file(name).type.split(";")[0] ?? "application/octet-stream";
|
|
32535
|
+
}
|
|
32536
|
+
function telegramAttachmentType(mimeType, sizeBytes) {
|
|
32537
|
+
if ((mimeType === "image/jpeg" || mimeType === "image/png") && sizeBytes <= TELEGRAM_PHOTO_LIMIT) {
|
|
32538
|
+
return "image";
|
|
32539
|
+
}
|
|
32540
|
+
if (mimeType === "video/mp4")
|
|
32541
|
+
return "video";
|
|
32542
|
+
if (mimeType === "audio/mpeg" || mimeType === "audio/mp4" || mimeType === "audio/x-m4a") {
|
|
32543
|
+
return "audio";
|
|
32544
|
+
}
|
|
32545
|
+
return "file";
|
|
32546
|
+
}
|
|
32547
|
+
function fileGroupKey(adapter, file) {
|
|
32548
|
+
if (adapter !== "telegram")
|
|
32549
|
+
return "files";
|
|
32550
|
+
const type = telegramAttachmentType(file.mimeType, file.data.byteLength);
|
|
32551
|
+
return type === "image" || type === "video" ? "visual" : type;
|
|
32552
|
+
}
|
|
32553
|
+
function fileMessage(adapter, files) {
|
|
32554
|
+
if (adapter === "telegram") {
|
|
32555
|
+
return {
|
|
32556
|
+
markdown: "",
|
|
32557
|
+
attachments: files.map((file) => ({
|
|
32558
|
+
type: telegramAttachmentType(file.mimeType, file.data.byteLength),
|
|
32559
|
+
name: file.name,
|
|
32560
|
+
mimeType: file.mimeType,
|
|
32561
|
+
size: file.data.byteLength,
|
|
32562
|
+
data: file.data
|
|
32563
|
+
}))
|
|
32564
|
+
};
|
|
32565
|
+
}
|
|
32566
|
+
return {
|
|
32567
|
+
markdown: "",
|
|
32568
|
+
files: files.map((file) => ({ data: file.data, filename: file.name, mimeType: file.mimeType }))
|
|
32569
|
+
};
|
|
32570
|
+
}
|
|
32571
|
+
function platformName(adapter) {
|
|
32572
|
+
return adapter.charAt(0).toUpperCase() + adapter.slice(1);
|
|
32573
|
+
}
|
|
32574
|
+
async function postFiles(adapter, target, files) {
|
|
32575
|
+
const limit = chatUploadLimit(adapter);
|
|
32576
|
+
const tooLarge = (size) => `${formatFileSize(size)}, over the ${formatFileSize(limit)} upload limit of ${platformName(adapter)}`;
|
|
32577
|
+
const messageIds = [];
|
|
32578
|
+
const unsent = [];
|
|
32579
|
+
const groups = new Map;
|
|
32580
|
+
const send = async (group) => {
|
|
32581
|
+
try {
|
|
32582
|
+
const sent = await target.post(fileMessage(adapter, group));
|
|
32583
|
+
messageIds.push(sent.id);
|
|
32584
|
+
} catch (error) {
|
|
32585
|
+
const reason = `refused by ${platformName(adapter)} (${scrubSecrets(errorMessage(error))})`;
|
|
32586
|
+
for (const file of group)
|
|
32587
|
+
unsent.push({ name: file.name, reason });
|
|
32588
|
+
}
|
|
32589
|
+
};
|
|
32590
|
+
for (const file of files) {
|
|
32591
|
+
if (file.sizeBytes !== undefined && file.sizeBytes > limit) {
|
|
32592
|
+
unsent.push({ name: file.name, reason: tooLarge(file.sizeBytes) });
|
|
32593
|
+
continue;
|
|
32594
|
+
}
|
|
32595
|
+
let loaded;
|
|
32596
|
+
try {
|
|
32597
|
+
const { data, mimeType } = await file.load(limit);
|
|
32598
|
+
if (data.byteLength > limit)
|
|
32599
|
+
throw new ChatFileTooLargeError(data.byteLength);
|
|
32600
|
+
loaded = {
|
|
32601
|
+
name: file.name,
|
|
32602
|
+
mimeType: resolveMimeType(file.name, file.mimeType, mimeType),
|
|
32603
|
+
data: Buffer.from(data.buffer, data.byteOffset, data.byteLength)
|
|
32604
|
+
};
|
|
32605
|
+
} catch (error) {
|
|
32606
|
+
unsent.push({
|
|
32607
|
+
name: file.name,
|
|
32608
|
+
reason: error instanceof ChatFileTooLargeError ? tooLarge(error.sizeBytes) : `could not be read (${scrubSecrets(errorMessage(error))})`
|
|
32609
|
+
});
|
|
32610
|
+
continue;
|
|
32611
|
+
}
|
|
32612
|
+
const key = fileGroupKey(adapter, loaded);
|
|
32613
|
+
const group = [...groups.get(key) ?? [], loaded];
|
|
32614
|
+
if (group.length === CHAT_FILES_PER_MESSAGE) {
|
|
32615
|
+
groups.delete(key);
|
|
32616
|
+
await send(group);
|
|
32617
|
+
} else {
|
|
32618
|
+
groups.set(key, group);
|
|
32619
|
+
}
|
|
32620
|
+
}
|
|
32621
|
+
for (const group of groups.values())
|
|
32622
|
+
await send(group);
|
|
32623
|
+
return { messageIds, unsent };
|
|
32624
|
+
}
|
|
32625
|
+
function unsentFilesSummary(unsent) {
|
|
32626
|
+
return unsent.length === 0 ? "" : ` ${formatUnsentFilesNote(unsent)}`;
|
|
32627
|
+
}
|
|
32628
|
+
function singleLine(text) {
|
|
32629
|
+
return text.replace(/[\u0000-\u001f\u007f\u2028\u2029]+/g, " ").trim();
|
|
32630
|
+
}
|
|
32631
|
+
function breakMentions(text) {
|
|
32632
|
+
return text.replace(/@/g, "@").replace(/<!/g, "<!");
|
|
32633
|
+
}
|
|
32634
|
+
function codeSpan(text) {
|
|
32635
|
+
const value = breakMentions(singleLine(text)) || "(unnamed)";
|
|
32636
|
+
const longestRun = Math.max(0, ...(value.match(/`+/g) ?? []).map((run) => run.length));
|
|
32637
|
+
const fence = "`".repeat(longestRun + 1);
|
|
32638
|
+
const pad = value.startsWith("`") || value.endsWith("`") ? " " : "";
|
|
32639
|
+
return `${fence}${pad}${value}${pad}${fence}`;
|
|
32640
|
+
}
|
|
32641
|
+
function formatUnsentFilesNote(unsent) {
|
|
32642
|
+
const lines = unsent.map((file) => `- ${codeSpan(file.name)}: ${breakMentions(singleLine(file.reason))}`);
|
|
32643
|
+
const count = unsent.length === 1 ? "1 file" : `${unsent.length} files`;
|
|
32644
|
+
return [`Could not send ${count}:`, ...lines].join(`
|
|
32645
|
+
`);
|
|
32646
|
+
}
|
|
32124
32647
|
async function postChatMessage(args) {
|
|
32125
32648
|
assertTrustedChatTarget(args.threadId ?? args.channelId ?? "");
|
|
32126
32649
|
const chat = getChatInstance(args.adapter);
|
|
@@ -32128,27 +32651,42 @@ async function postChatMessage(args) {
|
|
|
32128
32651
|
throw new ChatAdapterUnavailableError(args.adapter);
|
|
32129
32652
|
const text = scrubSecrets(args.text);
|
|
32130
32653
|
let result;
|
|
32654
|
+
let target;
|
|
32131
32655
|
if (args.threadId) {
|
|
32132
32656
|
const thread = chat.thread(args.threadId);
|
|
32657
|
+
target = thread;
|
|
32133
32658
|
const sent = await postChunks(args.adapter, thread, text);
|
|
32134
32659
|
result = {
|
|
32135
32660
|
adapter: args.adapter,
|
|
32136
32661
|
threadId: thread.id,
|
|
32137
32662
|
channelId: thread.channelId,
|
|
32138
|
-
messageIds: sent.messageIds
|
|
32663
|
+
messageIds: sent.messageIds,
|
|
32664
|
+
unsentFiles: []
|
|
32139
32665
|
};
|
|
32140
32666
|
} else if (args.channelId) {
|
|
32141
32667
|
const channel = chat.channel(args.channelId);
|
|
32668
|
+
target = channel;
|
|
32142
32669
|
const sent = await postChunks(args.adapter, channel, text);
|
|
32143
32670
|
result = {
|
|
32144
32671
|
adapter: args.adapter,
|
|
32145
32672
|
threadId: sent.threadId ?? channel.id,
|
|
32146
32673
|
channelId: channel.id,
|
|
32147
|
-
messageIds: sent.messageIds
|
|
32674
|
+
messageIds: sent.messageIds,
|
|
32675
|
+
unsentFiles: []
|
|
32148
32676
|
};
|
|
32149
32677
|
} else {
|
|
32150
32678
|
throw new Error("postChatMessage needs a threadId or a channelId");
|
|
32151
32679
|
}
|
|
32680
|
+
if (args.files?.length) {
|
|
32681
|
+
const sent = await postFiles(args.adapter, target, args.files);
|
|
32682
|
+
result.messageIds.push(...sent.messageIds);
|
|
32683
|
+
result.unsentFiles = sent.unsent;
|
|
32684
|
+
if (sent.unsent.length > 0) {
|
|
32685
|
+
const note = formatUnsentFilesNote(sent.unsent);
|
|
32686
|
+
const noted = await postChunks(args.adapter, target, scrubSecrets(note));
|
|
32687
|
+
result.messageIds.push(...noted.messageIds);
|
|
32688
|
+
}
|
|
32689
|
+
}
|
|
32152
32690
|
emitChatMessageSent({
|
|
32153
32691
|
adapter: result.adapter,
|
|
32154
32692
|
channelId: result.channelId,
|
|
@@ -32214,9 +32752,19 @@ async function putChatChannelMapping(adapter, channelId, mapping) {
|
|
|
32214
32752
|
async function deleteChatChannelMapping(adapter, channelId) {
|
|
32215
32753
|
return deleteKv2(CHAT_CHANNELS_NAMESPACE, chatChannelKey(adapter, channelId));
|
|
32216
32754
|
}
|
|
32755
|
+
function hasRoutingToken(text) {
|
|
32756
|
+
return /swarm#(?:[a-f0-9-]{36}|all)/i.test(text);
|
|
32757
|
+
}
|
|
32217
32758
|
function stripRoutingTokens(text) {
|
|
32218
32759
|
return text.replace(/swarm#[a-f0-9-]{36}/gi, "").replace(/swarm#all/gi, "").trim();
|
|
32219
32760
|
}
|
|
32761
|
+
var DEFAULT_OWNER_WINDOW_MINUTES = 15;
|
|
32762
|
+
function chatOwnerWindowStart(now = Date.now()) {
|
|
32763
|
+
const raw = process.env.CHAT_SDK_OWNER_WINDOW_MIN?.trim();
|
|
32764
|
+
const value = raw ? Number(raw) : Number.NaN;
|
|
32765
|
+
const minutes = Number.isFinite(value) && value >= 0 ? value : DEFAULT_OWNER_WINDOW_MINUTES;
|
|
32766
|
+
return new Date(now - minutes * 60000).toISOString();
|
|
32767
|
+
}
|
|
32220
32768
|
async function leadMatch(reachable, matchedText) {
|
|
32221
32769
|
const lead = reachable.find((agent) => agent.isLead) ?? await getLeadAgent2();
|
|
32222
32770
|
return { agent: lead, reason: "skill", matchedText };
|
|
@@ -32258,7 +32806,7 @@ async function routeChatMessage(text, ctx) {
|
|
|
32258
32806
|
}
|
|
32259
32807
|
console.warn(scrubSecrets(`[chat-sdk] Channel mapping for ${ctx.channelId} names unknown agent ${mapping.agentId}; using the default route`));
|
|
32260
32808
|
}
|
|
32261
|
-
const owner = await getAgentWorkingOnContextKey2(chatSdkContextKey(ctx.threadId), "chat");
|
|
32809
|
+
const owner = await getAgentWorkingOnContextKey2(chatSdkContextKey(ctx.threadId), "chat", ctx.adapter === "telegram" && !ctx.isDirectMessage ? chatOwnerWindowStart() : undefined);
|
|
32262
32810
|
if (owner && await isAgentReachable(owner)) {
|
|
32263
32811
|
return {
|
|
32264
32812
|
kind: "agents",
|
|
@@ -32288,6 +32836,9 @@ async function requestChatThreadSteering(args) {
|
|
|
32288
32836
|
const task = await getLatestLeadTaskByContextKey2(args.contextKey, "chat");
|
|
32289
32837
|
if (!task || task.status !== "in_progress")
|
|
32290
32838
|
return null;
|
|
32839
|
+
const senderUserId = await args.resolveSender();
|
|
32840
|
+
if (senderUserId !== task.requestedByUserId)
|
|
32841
|
+
return null;
|
|
32291
32842
|
try {
|
|
32292
32843
|
const result = await requestSteering({
|
|
32293
32844
|
taskId: task.id,
|
|
@@ -32295,7 +32846,8 @@ async function requestChatThreadSteering(args) {
|
|
|
32295
32846
|
mode: "queue",
|
|
32296
32847
|
onUnsupported: "degrade",
|
|
32297
32848
|
source: "chat",
|
|
32298
|
-
createdByKind: "user"
|
|
32849
|
+
createdByKind: "user",
|
|
32850
|
+
createdByUserId: senderUserId
|
|
32299
32851
|
});
|
|
32300
32852
|
return { task, result };
|
|
32301
32853
|
} catch (error) {
|
|
@@ -32389,6 +32941,18 @@ registerTemplate({
|
|
|
32389
32941
|
],
|
|
32390
32942
|
category: "system"
|
|
32391
32943
|
});
|
|
32944
|
+
registerTemplate({
|
|
32945
|
+
eventType: "chat.message.header",
|
|
32946
|
+
header: "",
|
|
32947
|
+
defaultBody: "[chat] {{chat_facts}}",
|
|
32948
|
+
variables: [
|
|
32949
|
+
{
|
|
32950
|
+
name: "chat_facts",
|
|
32951
|
+
description: "Adapter, chat type and title, forum topic, sender, why the message was taken (addressed) and the replied-to snippet, joined with ' · '"
|
|
32952
|
+
}
|
|
32953
|
+
],
|
|
32954
|
+
category: "system"
|
|
32955
|
+
});
|
|
32392
32956
|
|
|
32393
32957
|
// src/integrations/chat-sdk/inbound.ts
|
|
32394
32958
|
var ChatRouteModifySchema = object2({
|
|
@@ -32433,10 +32997,24 @@ async function handleChatInbound(thread, message, kind) {
|
|
|
32433
32997
|
if (immediate)
|
|
32434
32998
|
text = text.replace(/^!now\s*/i, "").trim();
|
|
32435
32999
|
const attachments = message.attachments ?? [];
|
|
33000
|
+
const facts = readChatMessageFacts(thread, message);
|
|
33001
|
+
const isDirectMessage = kind === "dm" || thread.isDM;
|
|
33002
|
+
const mentioned = kind === "mention" || message.isMention === true;
|
|
33003
|
+
let addressed = isDirectMessage ? "dm" : facts.replyToBot ? "reply-to-bot" : mentioned ? "mention" : "none";
|
|
33004
|
+
if (addressed === "none" && (facts.chatType === "group" || facts.chatType === "supergroup")) {
|
|
33005
|
+
const unaddressed = await classifyUnaddressedGroupMessage(thread, message.author.userId, text);
|
|
33006
|
+
if (unaddressed === "chatter") {
|
|
33007
|
+
console.log(`[chat-sdk] ${thread.id}: unaddressed group message from a non-requester, ignored`);
|
|
33008
|
+
return;
|
|
33009
|
+
}
|
|
33010
|
+
if (unaddressed === "requester-follow-up")
|
|
33011
|
+
addressed = unaddressed;
|
|
33012
|
+
}
|
|
32436
33013
|
if (!immediate && attachments.length === 0 && text && !isChatThreadBuffered(thread.id)) {
|
|
32437
33014
|
const steering = await requestChatThreadSteering({
|
|
32438
33015
|
contextKey: chatSdkContextKey(thread.id),
|
|
32439
|
-
message: text
|
|
33016
|
+
message: text,
|
|
33017
|
+
resolveSender: () => resolveChatSender(adapter, message.author.userId)
|
|
32440
33018
|
});
|
|
32441
33019
|
if (steering) {
|
|
32442
33020
|
console.log(`[chat-sdk] ${adapter} message steered task ${steering.task.id} (${steering.result.outcome})`);
|
|
@@ -32465,8 +33043,10 @@ async function handleChatInbound(thread, message, kind) {
|
|
|
32465
33043
|
text,
|
|
32466
33044
|
userId: message.author.userId,
|
|
32467
33045
|
userName: message.author.userName || undefined,
|
|
32468
|
-
botMentioned:
|
|
32469
|
-
isDirectMessage
|
|
33046
|
+
botMentioned: mentioned || facts.replyToBot,
|
|
33047
|
+
isDirectMessage,
|
|
33048
|
+
addressed,
|
|
33049
|
+
facts,
|
|
32470
33050
|
attachments
|
|
32471
33051
|
});
|
|
32472
33052
|
if (kind !== "subscribed")
|
|
@@ -32475,6 +33055,47 @@ async function handleChatInbound(thread, message, kind) {
|
|
|
32475
33055
|
if (immediate)
|
|
32476
33056
|
await instantFlushChat(thread.id);
|
|
32477
33057
|
}
|
|
33058
|
+
var REQUESTER_KEY_PREFIX = "swarm:requester:";
|
|
33059
|
+
var REQUESTER_TTL_MS = 30 * 24 * 60 * 60 * 1000;
|
|
33060
|
+
async function rememberChatThreadRequester(threadId, userId) {
|
|
33061
|
+
try {
|
|
33062
|
+
await new SqliteChatState().set(`${REQUESTER_KEY_PREFIX}${threadId}`, userId, REQUESTER_TTL_MS);
|
|
33063
|
+
} catch (error) {
|
|
33064
|
+
console.warn(`[chat-sdk] Could not store the thread requester: ${errorMessage(error)}`);
|
|
33065
|
+
}
|
|
33066
|
+
}
|
|
33067
|
+
async function classifyUnaddressedGroupMessage(thread, senderId, text) {
|
|
33068
|
+
if (hasRoutingToken(text))
|
|
33069
|
+
return "routable";
|
|
33070
|
+
if ((await getChatChannelMapping(thread.adapter.name, thread.channelId))?.agentId) {
|
|
33071
|
+
return "routable";
|
|
33072
|
+
}
|
|
33073
|
+
const owner = await getAgentWorkingOnContextKey2(chatSdkContextKey(thread.id), "chat", chatOwnerWindowStart());
|
|
33074
|
+
if (!owner)
|
|
33075
|
+
return "chatter";
|
|
33076
|
+
const requester = await new SqliteChatState().get(`${REQUESTER_KEY_PREFIX}${thread.id}`);
|
|
33077
|
+
return requester === senderId ? "requester-follow-up" : "chatter";
|
|
33078
|
+
}
|
|
33079
|
+
async function resolveChatRequester(adapter, item) {
|
|
33080
|
+
return resolveChatSender(adapter, item.userId, {
|
|
33081
|
+
sampleEventType: "chat.message",
|
|
33082
|
+
sampleContext: `${item.facts.from}: ${item.text}`
|
|
33083
|
+
});
|
|
33084
|
+
}
|
|
33085
|
+
async function resolveChatSender(adapter, userId, sample) {
|
|
33086
|
+
if (!userId || userId.startsWith("chat:"))
|
|
33087
|
+
return;
|
|
33088
|
+
try {
|
|
33089
|
+
const resolution = await resolveIdentity(adapter, userId);
|
|
33090
|
+
if (resolution.status === "resolved")
|
|
33091
|
+
return resolution.userId;
|
|
33092
|
+
if (sample)
|
|
33093
|
+
await recordUnmappedIdentity(adapter, userId, sample);
|
|
33094
|
+
} catch (error) {
|
|
33095
|
+
console.warn(`[chat-sdk] Could not resolve the requester: ${errorMessage(error)}`);
|
|
33096
|
+
}
|
|
33097
|
+
return;
|
|
33098
|
+
}
|
|
32478
33099
|
async function getChatThreadContext(thread, exclude, since) {
|
|
32479
33100
|
try {
|
|
32480
33101
|
await thread.refresh();
|
|
@@ -32545,6 +33166,8 @@ async function flushChatThread(threadId, items, immediate) {
|
|
|
32545
33166
|
`);
|
|
32546
33167
|
const botMentioned = items.some((item) => item.botMentioned);
|
|
32547
33168
|
const isDirectMessage = items.some((item) => item.isDirectMessage);
|
|
33169
|
+
const requester = items.find((item) => item.addressed !== "none") ?? first;
|
|
33170
|
+
const otherSenders = new Set(items.map((item) => item.userId)).size - 1;
|
|
32548
33171
|
const resetAt = await getChatThreadResetAt(threadId);
|
|
32549
33172
|
const previousTask = await getLatestTaskByContextKey2(contextKey);
|
|
32550
33173
|
const mostRecentTask = previousTask && resetAt && new Date(previousTask.createdAt).getTime() <= resetAt.getTime() ? null : previousTask;
|
|
@@ -32557,6 +33180,9 @@ async function flushChatThread(threadId, items, immediate) {
|
|
|
32557
33180
|
text: rawText,
|
|
32558
33181
|
botMentioned,
|
|
32559
33182
|
isDirectMessage,
|
|
33183
|
+
...first.facts.chatType ? { chatType: first.facts.chatType } : {},
|
|
33184
|
+
...first.facts.isForum ? { isForum: true } : {},
|
|
33185
|
+
replyToBot: items.some((item) => item.facts.replyToBot),
|
|
32560
33186
|
...mostRecentTask ? { threadContext: { adapter, threadId } } : {}
|
|
32561
33187
|
}, {
|
|
32562
33188
|
validateModify: (data) => {
|
|
@@ -32607,7 +33233,16 @@ async function flushChatThread(threadId, items, immediate) {
|
|
|
32607
33233
|
const body = stripRoutingTokens(rawText);
|
|
32608
33234
|
const files = items.flatMap((item) => toChatFiles(adapter, item.messageId, item.attachments));
|
|
32609
33235
|
const inbound = __using(__stack, await fetchChatFiles(files), 1);
|
|
32610
|
-
const
|
|
33236
|
+
const tooLarge = inbound.failed.filter((failure) => failure.tooLarge);
|
|
33237
|
+
if (tooLarge.length > 0) {
|
|
33238
|
+
try {
|
|
33239
|
+
await postChatMessage({ adapter, threadId, text: formatTooLargeReply(tooLarge) });
|
|
33240
|
+
} catch (error) {
|
|
33241
|
+
console.warn(`[chat-sdk] ${threadId}: could not post the too-large reply: ${errorMessage(error)}`);
|
|
33242
|
+
}
|
|
33243
|
+
}
|
|
33244
|
+
const notes = await transcribeChatAudio(inbound.fetched);
|
|
33245
|
+
const fileText = buildChatAttachmentText(inbound.files, inbound.failed, notes);
|
|
32611
33246
|
const combined = [body, fileText].filter(Boolean).join(`
|
|
32612
33247
|
|
|
32613
33248
|
`);
|
|
@@ -32615,9 +33250,17 @@ async function flushChatThread(threadId, items, immediate) {
|
|
|
32615
33250
|
|
|
32616
33251
|
${combined}` : combined;
|
|
32617
33252
|
const threadContext = mostRecentTask && thread ? await getChatThreadContext(thread, new Set(items.map((item) => item.messageId)), resetAt) : "";
|
|
32618
|
-
const
|
|
33253
|
+
const header = resolveTemplate("chat.message.header", {
|
|
33254
|
+
chat_facts: formatChatHeaderFacts(adapter, otherSenders > 0 ? { ...requester.facts, from: `${requester.facts.from} +${otherSenders} more` } : requester.facts, requester.addressed)
|
|
33255
|
+
}).text;
|
|
33256
|
+
const description = [
|
|
33257
|
+
header,
|
|
33258
|
+
threadContext ? resolveTemplate("chat.message.thread_context", { thread_messages: threadContext }).text : "",
|
|
33259
|
+
marked
|
|
33260
|
+
].filter(Boolean).join(`
|
|
32619
33261
|
|
|
32620
|
-
|
|
33262
|
+
`);
|
|
33263
|
+
const requestedByUserId = otherSenders > 0 ? undefined : await resolveChatRequester(adapter, requester);
|
|
32621
33264
|
const latestActive = await getLatestActiveTaskByContextKey2(contextKey, "chat");
|
|
32622
33265
|
const dependsOn = !immediate && latestActive ? [latestActive.id] : undefined;
|
|
32623
33266
|
let created = 0;
|
|
@@ -32632,7 +33275,9 @@ ${marked}` : marked;
|
|
|
32632
33275
|
priority: 70,
|
|
32633
33276
|
contextKey,
|
|
32634
33277
|
dependsOn,
|
|
33278
|
+
requestedByUserId,
|
|
32635
33279
|
parentTaskId: mostRecentTask?.id,
|
|
33280
|
+
inheritParentRequester: false,
|
|
32636
33281
|
inheritParentOutputSchema: false
|
|
32637
33282
|
};
|
|
32638
33283
|
try {
|
|
@@ -32648,6 +33293,7 @@ ${marked}` : marked;
|
|
|
32648
33293
|
}
|
|
32649
33294
|
}
|
|
32650
33295
|
if (created > 0) {
|
|
33296
|
+
await rememberChatThreadRequester(threadId, requester.userId);
|
|
32651
33297
|
await subscribe(thread);
|
|
32652
33298
|
startTypingKeepalive(adapter, threadId);
|
|
32653
33299
|
} else {
|
|
@@ -32693,6 +33339,127 @@ init_db3();
|
|
|
32693
33339
|
init_context_key();
|
|
32694
33340
|
init_secret_scrubber();
|
|
32695
33341
|
init_event_bus();
|
|
33342
|
+
|
|
33343
|
+
// src/integrations/chat-sdk/outbound-files.ts
|
|
33344
|
+
init_db3();
|
|
33345
|
+
init_secret_scrubber();
|
|
33346
|
+
var UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
33347
|
+
async function download(scope, maxBytes, provider = getFileStorageProvider2()) {
|
|
33348
|
+
const response = await provider.download(scope);
|
|
33349
|
+
const length = Number(response.headers.get("content-length"));
|
|
33350
|
+
if (Number.isFinite(length) && length > maxBytes) {
|
|
33351
|
+
await response.body?.cancel();
|
|
33352
|
+
throw new ChatFileTooLargeError(length);
|
|
33353
|
+
}
|
|
33354
|
+
const data = new Uint8Array(await response.arrayBuffer());
|
|
33355
|
+
if (data.byteLength > maxBytes)
|
|
33356
|
+
throw new ChatFileTooLargeError(data.byteLength);
|
|
33357
|
+
return { data, mimeType: response.headers.get("content-type") ?? undefined };
|
|
33358
|
+
}
|
|
33359
|
+
function chatFileOfTaskAttachment(attachment) {
|
|
33360
|
+
if (backingProviderId(attachment) !== getFileStorageProvider2().id)
|
|
33361
|
+
return;
|
|
33362
|
+
return {
|
|
33363
|
+
name: attachment.name,
|
|
33364
|
+
mimeType: attachment.mimeType,
|
|
33365
|
+
sizeBytes: attachment.sizeBytes,
|
|
33366
|
+
load: (maxBytes) => download(scopeFromAttachment(attachment), maxBytes)
|
|
33367
|
+
};
|
|
33368
|
+
}
|
|
33369
|
+
function pathSegments(path) {
|
|
33370
|
+
return normalizeStoredKey(path).split("/").map((segment) => {
|
|
33371
|
+
let decoded = segment;
|
|
33372
|
+
try {
|
|
33373
|
+
decoded = decodeURIComponent(segment);
|
|
33374
|
+
} catch {}
|
|
33375
|
+
if (!decoded || decoded === "." || decoded === ".." || /[/\\\0]/.test(decoded)) {
|
|
33376
|
+
throw new FilesError("Provider", "Path must not contain empty, `.` or `..` segments, or encoded separators");
|
|
33377
|
+
}
|
|
33378
|
+
return decoded;
|
|
33379
|
+
});
|
|
33380
|
+
}
|
|
33381
|
+
async function callerAgentFs(agentId) {
|
|
33382
|
+
if (!agentId)
|
|
33383
|
+
return;
|
|
33384
|
+
const configs = await getResolvedConfig2(agentId);
|
|
33385
|
+
const value = (key) => configs.find((c) => c.key === key)?.value?.trim();
|
|
33386
|
+
const apiUrl = value("AGENT_FS_API_URL") || process.env.AGENT_FS_API_URL?.trim();
|
|
33387
|
+
const apiKey = value("AGENT_FS_API_KEY");
|
|
33388
|
+
const orgId = value("AGENT_FS_DEFAULT_ORG_ID");
|
|
33389
|
+
const driveId = value("AGENT_FS_DEFAULT_DRIVE_ID");
|
|
33390
|
+
return apiUrl && apiKey && orgId && driveId ? { apiUrl, apiKey, orgId, driveId } : undefined;
|
|
33391
|
+
}
|
|
33392
|
+
function chatFileOfPath(path, access) {
|
|
33393
|
+
const segments = pathSegments(path);
|
|
33394
|
+
const name = segments.at(-1);
|
|
33395
|
+
const key = segments.map(encodeURIComponent).join("/");
|
|
33396
|
+
const keyScrubber = createValueScrubber([{ value: access.apiKey, name: "AGENT_FS_API_KEY" }]);
|
|
33397
|
+
return {
|
|
33398
|
+
name,
|
|
33399
|
+
load: async (maxBytes) => {
|
|
33400
|
+
try {
|
|
33401
|
+
return await download({ taskId: "chat", name, key, orgId: access.orgId, driveId: access.driveId }, maxBytes, new AgentFsProvider(access));
|
|
33402
|
+
} catch (error) {
|
|
33403
|
+
if (error instanceof ChatFileTooLargeError)
|
|
33404
|
+
throw error;
|
|
33405
|
+
if (error instanceof FilesError && error.code === "Unauthorized") {
|
|
33406
|
+
throw new Error("your agent-fs credential cannot read this path");
|
|
33407
|
+
}
|
|
33408
|
+
throw new Error(keyScrubber.text(error instanceof Error ? error.message : String(error)));
|
|
33409
|
+
}
|
|
33410
|
+
}
|
|
33411
|
+
};
|
|
33412
|
+
}
|
|
33413
|
+
async function resolveChatAttachmentRefs(refs, taskId, agentId) {
|
|
33414
|
+
let taskAttachments;
|
|
33415
|
+
let access = null;
|
|
33416
|
+
const files = [];
|
|
33417
|
+
for (const ref of refs) {
|
|
33418
|
+
if (UUID_PATTERN.test(ref)) {
|
|
33419
|
+
if (!taskId)
|
|
33420
|
+
return { error: `Attachment ${ref}: no current task to look it up in.` };
|
|
33421
|
+
taskAttachments ??= await getTaskAttachments2(taskId);
|
|
33422
|
+
const attachment = taskAttachments.find((a) => a.id === ref);
|
|
33423
|
+
if (!attachment)
|
|
33424
|
+
return { error: `Attachment ${ref} is not an attachment of task ${taskId}.` };
|
|
33425
|
+
const file = chatFileOfTaskAttachment(attachment);
|
|
33426
|
+
if (!file) {
|
|
33427
|
+
return {
|
|
33428
|
+
error: `Attachment ${ref} (${attachment.kind}) is not stored in the swarm file provider, so it cannot be sent as a file. Post its link instead.`
|
|
33429
|
+
};
|
|
33430
|
+
}
|
|
33431
|
+
files.push(file);
|
|
33432
|
+
continue;
|
|
33433
|
+
}
|
|
33434
|
+
if (access === null)
|
|
33435
|
+
access = await callerAgentFs(agentId);
|
|
33436
|
+
if (!access) {
|
|
33437
|
+
return {
|
|
33438
|
+
error: `Path ${ref}: you have no agent-fs credential and drive to read it with. Attach the file to your task and send its attachment id.`
|
|
33439
|
+
};
|
|
33440
|
+
}
|
|
33441
|
+
try {
|
|
33442
|
+
files.push(chatFileOfPath(ref, access));
|
|
33443
|
+
} catch (error) {
|
|
33444
|
+
return { error: `Path ${ref}: ${errorMessage(error)}` };
|
|
33445
|
+
}
|
|
33446
|
+
}
|
|
33447
|
+
return { files };
|
|
33448
|
+
}
|
|
33449
|
+
var FETCHED_SLACK_FILE_INTENT = "slack-file";
|
|
33450
|
+
async function taskOutputChatFiles(taskId) {
|
|
33451
|
+
return (await getTaskAttachments2(taskId)).flatMap((attachment) => {
|
|
33452
|
+
if (attachment.agentId === null)
|
|
33453
|
+
return [];
|
|
33454
|
+
if (attachment.intent === SHARED_FILE_INTENT || attachment.intent === FETCHED_SLACK_FILE_INTENT) {
|
|
33455
|
+
return [];
|
|
33456
|
+
}
|
|
33457
|
+
const file = chatFileOfTaskAttachment(attachment);
|
|
33458
|
+
return file ? [file] : [];
|
|
33459
|
+
});
|
|
33460
|
+
}
|
|
33461
|
+
|
|
33462
|
+
// src/integrations/chat-sdk/relay.ts
|
|
32696
33463
|
var RELAY_GIVE_UP_AFTER_MS = 24 * 60 * 60 * 1000;
|
|
32697
33464
|
var SWEEP_EVERY_N_TICKS = 20;
|
|
32698
33465
|
var EARLY_TICK_DEBOUNCE_MS = 250;
|
|
@@ -32742,7 +33509,8 @@ async function processPendingChatRelays(now = Date.now(), signal) {
|
|
|
32742
33509
|
adapter: target.adapter,
|
|
32743
33510
|
threadId: target.threadId,
|
|
32744
33511
|
text: formatChatRelayText(task),
|
|
32745
|
-
taskId: task.id
|
|
33512
|
+
taskId: task.id,
|
|
33513
|
+
files: await taskOutputChatFiles(task.id)
|
|
32746
33514
|
});
|
|
32747
33515
|
stopTypingKeepalive(target.threadId);
|
|
32748
33516
|
await markChatRelayDelivered2(task.id, now);
|
|
@@ -33400,43 +34168,6 @@ Original issue: {{issue_key}} — {{issue_summary}}`,
|
|
|
33400
34168
|
// src/jira/sync.ts
|
|
33401
34169
|
init_db3();
|
|
33402
34170
|
init_oauth();
|
|
33403
|
-
|
|
33404
|
-
// src/be/unmapped-identities.ts
|
|
33405
|
-
init_db3();
|
|
33406
|
-
var TTL_MS = 30 * 24 * 60 * 60 * 1000;
|
|
33407
|
-
function namespace(kind) {
|
|
33408
|
-
return `integration:unmapped:${kind}`;
|
|
33409
|
-
}
|
|
33410
|
-
async function recordUnmappedIdentity(kind, externalId, meta) {
|
|
33411
|
-
const ns = namespace(kind);
|
|
33412
|
-
const now = new Date().toISOString();
|
|
33413
|
-
const expiresAt = Date.now() + TTL_MS;
|
|
33414
|
-
const countKey = `${externalId}:count`;
|
|
33415
|
-
const countBefore = await getKv2(ns, countKey);
|
|
33416
|
-
await upsertKv2({
|
|
33417
|
-
namespace: ns,
|
|
33418
|
-
key: `${externalId}:meta`,
|
|
33419
|
-
value: {
|
|
33420
|
-
lastSeenAt: now,
|
|
33421
|
-
sampleEventType: meta.sampleEventType,
|
|
33422
|
-
sampleContext: meta.sampleContext.slice(0, 100)
|
|
33423
|
-
},
|
|
33424
|
-
valueType: "json",
|
|
33425
|
-
expiresAt
|
|
33426
|
-
});
|
|
33427
|
-
const incremented = await incrKv2(ns, countKey, 1);
|
|
33428
|
-
if (countBefore === null) {
|
|
33429
|
-
await upsertKv2({
|
|
33430
|
-
namespace: ns,
|
|
33431
|
-
key: countKey,
|
|
33432
|
-
value: Number(incremented.value),
|
|
33433
|
-
valueType: "integer",
|
|
33434
|
-
expiresAt
|
|
33435
|
-
});
|
|
33436
|
-
}
|
|
33437
|
-
}
|
|
33438
|
-
|
|
33439
|
-
// src/jira/sync.ts
|
|
33440
34171
|
init_users();
|
|
33441
34172
|
init_resolver();
|
|
33442
34173
|
init_context_key();
|
|
@@ -33822,7 +34553,7 @@ async function notifySlack(text) {
|
|
|
33822
34553
|
return;
|
|
33823
34554
|
}
|
|
33824
34555
|
try {
|
|
33825
|
-
const { getSlackApp } = await import("./app-
|
|
34556
|
+
const { getSlackApp } = await import("./app-353vre8g.js");
|
|
33826
34557
|
const app = getSlackApp();
|
|
33827
34558
|
if (!app) {
|
|
33828
34559
|
console.warn("[Jira webhook keepalive] Slack not available, cannot send notification");
|
|
@@ -33893,7 +34624,7 @@ async function deleteJiraWebhook(webhookId) {
|
|
|
33893
34624
|
console.log(`[Jira webhook keepalive] Deleted webhook id=${webhookId}`);
|
|
33894
34625
|
}
|
|
33895
34626
|
async function overwriteWebhookIds(next) {
|
|
33896
|
-
const { getDbClient } = await import("./db-
|
|
34627
|
+
const { getDbClient } = await import("./db-6sfrn9g3.js");
|
|
33897
34628
|
await getDbClient().transaction(async (tx) => {
|
|
33898
34629
|
const row = await tx.get("SELECT metadata FROM oauth_apps WHERE provider = 'jira'");
|
|
33899
34630
|
if (!row) {
|
|
@@ -106993,11 +107724,34 @@ function parseCookieHeader(cookieHeader, name) {
|
|
|
106993
107724
|
const match = header.match(re);
|
|
106994
107725
|
return match ? match[1] : undefined;
|
|
106995
107726
|
}
|
|
106996
|
-
|
|
106997
|
-
|
|
106998
|
-
|
|
107727
|
+
var LEGACY_PAGE_SESSION_COOKIE = "page_session";
|
|
107728
|
+
var COOKIE_SAFE_PAGE_ID = /^[A-Za-z0-9_-]{1,64}$/;
|
|
107729
|
+
function isCookieSafePageId(pageId) {
|
|
107730
|
+
return COOKIE_SAFE_PAGE_ID.test(pageId);
|
|
107731
|
+
}
|
|
107732
|
+
function pageSessionCookieName(pageId) {
|
|
107733
|
+
return `${LEGACY_PAGE_SESSION_COOKIE}_${pageId}`;
|
|
107734
|
+
}
|
|
107735
|
+
async function verifyNamedCookie(req, name) {
|
|
107736
|
+
const token = parseCookieHeader(req.headers.cookie, name);
|
|
107737
|
+
const payload = await verifyPageSession(token);
|
|
107738
|
+
return payload && token ? { token, payload } : null;
|
|
107739
|
+
}
|
|
107740
|
+
async function extractPageSession(req, pageId) {
|
|
107741
|
+
if (!isCookieSafePageId(pageId))
|
|
106999
107742
|
return null;
|
|
107000
|
-
|
|
107743
|
+
for (const name of [pageSessionCookieName(pageId), LEGACY_PAGE_SESSION_COOKIE]) {
|
|
107744
|
+
const session = await verifyNamedCookie(req, name);
|
|
107745
|
+
if (session?.payload.pageId === pageId)
|
|
107746
|
+
return session;
|
|
107747
|
+
}
|
|
107748
|
+
return null;
|
|
107749
|
+
}
|
|
107750
|
+
async function extractLegacyPageSession(req) {
|
|
107751
|
+
return verifyNamedCookie(req, LEGACY_PAGE_SESSION_COOKIE);
|
|
107752
|
+
}
|
|
107753
|
+
async function extractAndVerifyCookie(req, pageId) {
|
|
107754
|
+
return (await extractPageSession(req, pageId))?.payload ?? null;
|
|
107001
107755
|
}
|
|
107002
107756
|
var PAGE_SESSION_TTL_SECONDS = 3600;
|
|
107003
107757
|
async function issuePageSessionCookie(pageId, opts) {
|
|
@@ -107009,13 +107763,11 @@ async function issuePageSessionCookie(pageId, opts) {
|
|
|
107009
107763
|
...opts.name ? { name: opts.name } : {},
|
|
107010
107764
|
...opts.op ? { op: true } : {}
|
|
107011
107765
|
});
|
|
107012
|
-
|
|
107013
|
-
|
|
107014
|
-
|
|
107015
|
-
|
|
107016
|
-
|
|
107017
|
-
];
|
|
107018
|
-
if (opts.dev) {
|
|
107766
|
+
return buildCookie(pageSessionCookieName(pageId), token, PAGE_SESSION_TTL_SECONDS, opts.dev);
|
|
107767
|
+
}
|
|
107768
|
+
function buildCookie(name, value, maxAge, dev) {
|
|
107769
|
+
const attrs = [`${name}=${value}`, "HttpOnly", "Path=/", `Max-Age=${maxAge}`];
|
|
107770
|
+
if (dev) {
|
|
107019
107771
|
attrs.push("SameSite=Lax");
|
|
107020
107772
|
} else {
|
|
107021
107773
|
attrs.push("SameSite=None");
|
|
@@ -107023,6 +107775,30 @@ async function issuePageSessionCookie(pageId, opts) {
|
|
|
107023
107775
|
}
|
|
107024
107776
|
return attrs.join("; ");
|
|
107025
107777
|
}
|
|
107778
|
+
var MAX_PAGE_SESSION_COOKIES = 20;
|
|
107779
|
+
var PAGE_SESSION_COOKIE_RE = new RegExp(`(?:^|;\\s*)(${LEGACY_PAGE_SESSION_COOKIE}_[A-Za-z0-9_-]{1,64})=([^;]*)`, "g");
|
|
107780
|
+
async function pageSessionSetCookies(req, pageId, opts) {
|
|
107781
|
+
const issued = await issuePageSessionCookie(pageId, opts);
|
|
107782
|
+
const header = Array.isArray(req.headers.cookie) ? req.headers.cookie.join("; ") : req.headers.cookie ?? "";
|
|
107783
|
+
const keep = [];
|
|
107784
|
+
const evict = new Set;
|
|
107785
|
+
const seen = new Set([pageSessionCookieName(pageId)]);
|
|
107786
|
+
for (const [, name, token] of header.matchAll(PAGE_SESSION_COOKIE_RE)) {
|
|
107787
|
+
if (!name || seen.has(name))
|
|
107788
|
+
continue;
|
|
107789
|
+
seen.add(name);
|
|
107790
|
+
const payload = await verifyPageSession(token);
|
|
107791
|
+
if (payload && name === pageSessionCookieName(payload.pageId)) {
|
|
107792
|
+
keep.push({ name, exp: payload.exp, order: keep.length });
|
|
107793
|
+
} else {
|
|
107794
|
+
evict.add(name);
|
|
107795
|
+
}
|
|
107796
|
+
}
|
|
107797
|
+
keep.sort((a, b) => b.exp - a.exp || b.order - a.order);
|
|
107798
|
+
for (const { name } of keep.slice(MAX_PAGE_SESSION_COOKIES - 1))
|
|
107799
|
+
evict.add(name);
|
|
107800
|
+
return [issued, ...[...evict].map((name) => buildCookie(name, "", 0, opts.dev))];
|
|
107801
|
+
}
|
|
107026
107802
|
|
|
107027
107803
|
// src/http/auth.ts
|
|
107028
107804
|
function extractBearer(req) {
|
|
@@ -107243,14 +108019,14 @@ async function reloadGlobalConfigsAndIntegrations() {
|
|
|
107243
108019
|
return runWithoutRequestAuth(() => reloadGlobalConfigsAndIntegrationsInner());
|
|
107244
108020
|
}
|
|
107245
108021
|
async function reloadGlobalConfigsAndIntegrationsInner() {
|
|
107246
|
-
const { getEmbeddingProvider, resetEmbeddingProvider } = await import("./index-
|
|
108022
|
+
const { getEmbeddingProvider, resetEmbeddingProvider } = await import("./index-arytgj5q.js");
|
|
107247
108023
|
const wasEmbeddingsConfigured = getEmbeddingProvider().isConfigured();
|
|
107248
108024
|
const updated = await loadGlobalConfigsIntoEnv(true);
|
|
107249
108025
|
await syncTelemetryEnabled("settings").catch((err) => {
|
|
107250
108026
|
console.error("[config-reload] telemetry re-init failed (non-fatal):", err);
|
|
107251
108027
|
});
|
|
107252
108028
|
await stopSlackApp2();
|
|
107253
|
-
const { resetFileStorageProvider } = await import("./registry-
|
|
108029
|
+
const { resetFileStorageProvider } = await import("./registry-ajhexe44.js");
|
|
107254
108030
|
resetFileStorageProvider();
|
|
107255
108031
|
resetEmbeddingProvider();
|
|
107256
108032
|
const isEmbeddingsConfigured = getEmbeddingProvider().isConfigured();
|
|
@@ -107259,10 +108035,10 @@ async function reloadGlobalConfigsAndIntegrationsInner() {
|
|
|
107259
108035
|
integrations.push("embeddings");
|
|
107260
108036
|
}
|
|
107261
108037
|
if (!wasEmbeddingsConfigured && isEmbeddingsConfigured) {
|
|
107262
|
-
import("./boot-reembed-
|
|
108038
|
+
import("./boot-reembed-b9c3az3c.js").then(({ runBootReembed }) => runBootReembed()).catch((err) => {
|
|
107263
108039
|
console.error("[config-reload] memory backfill failed (non-fatal):", err);
|
|
107264
108040
|
});
|
|
107265
|
-
import("./boot-reembed-
|
|
108041
|
+
import("./boot-reembed-qdkvxeem.js").then(({ runBootReembedScripts }) => runBootReembedScripts()).catch((err) => {
|
|
107266
108042
|
console.error("[config-reload] script backfill failed (non-fatal):", err);
|
|
107267
108043
|
});
|
|
107268
108044
|
}
|
|
@@ -107453,6 +108229,8 @@ async function handleCore(req, res, myAgentId, apiKey) {
|
|
|
107453
108229
|
return true;
|
|
107454
108230
|
}
|
|
107455
108231
|
req.headers["x-runtime-instance-id"] = auth.runtimeId;
|
|
108232
|
+
}
|
|
108233
|
+
if (auth.tokenKind !== "task") {
|
|
107456
108234
|
const sourceHeader = req.headers["x-source-task-id"];
|
|
107457
108235
|
const taskId = Array.isArray(sourceHeader) ? sourceHeader[0] : sourceHeader;
|
|
107458
108236
|
if (taskId !== undefined && (await getTaskById2(taskId))?.agentId !== auth.agentId) {
|
|
@@ -107672,6 +108450,10 @@ async function handleCore(req, res, myAgentId, apiKey) {
|
|
|
107672
108450
|
return false;
|
|
107673
108451
|
}
|
|
107674
108452
|
|
|
108453
|
+
// src/mcp-limits.ts
|
|
108454
|
+
var MCP_MAX_TOOL_INPUT_ELEMENTS = 25000;
|
|
108455
|
+
var MCP_MAX_REQUEST_BODY_BYTES = 4 * 1024 * 1024;
|
|
108456
|
+
|
|
107675
108457
|
// src/server.ts
|
|
107676
108458
|
init_resolver();
|
|
107677
108459
|
init_rbac();
|
|
@@ -108788,6 +109570,7 @@ async function runAppAction({
|
|
|
108788
109570
|
app,
|
|
108789
109571
|
name,
|
|
108790
109572
|
input = {},
|
|
109573
|
+
parentTaskId,
|
|
108791
109574
|
caller,
|
|
108792
109575
|
actor
|
|
108793
109576
|
}) {
|
|
@@ -108874,7 +109657,8 @@ async function runAppAction({
|
|
|
108874
109657
|
routingReason: action.agentId ? "human_pinned" : lead ? "skill" : undefined,
|
|
108875
109658
|
routingSource: action.agentId || lead ? "engine_default" : undefined,
|
|
108876
109659
|
key: normalizeAssetKey(`shared/app:${app.id}/action:${name}/`),
|
|
108877
|
-
...actor.startsWith("user:") ? { requestedByUserId: actor.slice("user:".length) } : {}
|
|
109660
|
+
...actor.startsWith("user:") ? { requestedByUserId: actor.slice("user:".length) } : {},
|
|
109661
|
+
...parentTaskId ? { parentTaskId } : {}
|
|
108878
109662
|
}, { origin: "app" });
|
|
108879
109663
|
return {
|
|
108880
109664
|
status: 200,
|
|
@@ -110045,6 +110829,47 @@ init_rbac();
|
|
|
110045
110829
|
init_types();
|
|
110046
110830
|
init_request_auth_context();
|
|
110047
110831
|
init_secret_scrubber();
|
|
110832
|
+
|
|
110833
|
+
// src/http/request-principal.ts
|
|
110834
|
+
init_db3();
|
|
110835
|
+
init_request_auth_context();
|
|
110836
|
+
async function requestPrincipal(req, myAgentId) {
|
|
110837
|
+
const auth = getRequestAuth(req);
|
|
110838
|
+
if (auth?.kind === "controller")
|
|
110839
|
+
return { kind: "guest" };
|
|
110840
|
+
if (auth?.kind === "operator")
|
|
110841
|
+
return { kind: "operator" };
|
|
110842
|
+
if (auth?.kind === "user")
|
|
110843
|
+
return { kind: "user", userId: auth.userId };
|
|
110844
|
+
if (auth?.kind === "guest")
|
|
110845
|
+
return { kind: "guest" };
|
|
110846
|
+
if (!myAgentId)
|
|
110847
|
+
return null;
|
|
110848
|
+
const agent = await getAgentById2(myAgentId);
|
|
110849
|
+
return { kind: "agent", agentId: myAgentId, isLead: agent?.isLead ?? false };
|
|
110850
|
+
}
|
|
110851
|
+
async function agentFirstPrincipal(req, myAgentId) {
|
|
110852
|
+
const auth = getRequestAuth(req);
|
|
110853
|
+
if (auth?.kind === "controller")
|
|
110854
|
+
return { kind: "guest" };
|
|
110855
|
+
if (auth?.kind === "user")
|
|
110856
|
+
return { kind: "user", userId: auth.userId };
|
|
110857
|
+
if (auth?.kind === "guest")
|
|
110858
|
+
return { kind: "guest" };
|
|
110859
|
+
const agentId = auth?.kind === "agent" ? auth.agentId : myAgentId;
|
|
110860
|
+
if (!agentId)
|
|
110861
|
+
return { kind: "operator" };
|
|
110862
|
+
const agent = await getAgentById2(agentId);
|
|
110863
|
+
return { kind: "agent", agentId, isLead: agent?.isLead === true };
|
|
110864
|
+
}
|
|
110865
|
+
function rejectGuest(req, res) {
|
|
110866
|
+
if (getRequestAuth(req)?.kind !== "guest")
|
|
110867
|
+
return false;
|
|
110868
|
+
jsonError(res, "Forbidden", 403);
|
|
110869
|
+
return true;
|
|
110870
|
+
}
|
|
110871
|
+
|
|
110872
|
+
// src/http/apps.ts
|
|
110048
110873
|
var MAX_APP_BODY_BYTES = 5 * 1024 * 1024;
|
|
110049
110874
|
var MAX_APP_ROW_BODY_BYTES = 1 * 1024 * 1024;
|
|
110050
110875
|
var MAX_APP_BULK_ROWS_BODY_BYTES = 10 * 1024 * 1024;
|
|
@@ -110493,17 +111318,23 @@ var runActionRoute = route({
|
|
|
110493
111318
|
method: "post",
|
|
110494
111319
|
path: "/api/apps/{id}/actions/{name}",
|
|
110495
111320
|
pattern: ["api", "apps", null, "actions", null],
|
|
111321
|
+
session: bodyTask("parentTaskId"),
|
|
110496
111322
|
summary: "Run a custom app action",
|
|
110497
111323
|
description: "Runs the saved script, or creates the agent task, named by the app definition.",
|
|
110498
111324
|
tags: ["Apps"],
|
|
110499
111325
|
params: object2({ id: string2().min(1), name: AppNameSchema }),
|
|
110500
|
-
body: object2({
|
|
111326
|
+
body: object2({
|
|
111327
|
+
input: record2(string2(), unknown()).optional(),
|
|
111328
|
+
parentTaskId: string2().min(1).optional()
|
|
111329
|
+
}),
|
|
110501
111330
|
responses: {
|
|
110502
111331
|
200: { description: "Action invoked", schema: runActionResultSchema },
|
|
110503
|
-
400: {
|
|
111332
|
+
400: {
|
|
111333
|
+
description: "Invalid action input, stale script reference, or parentTaskId on a non-task action"
|
|
111334
|
+
},
|
|
110504
111335
|
403: { description: "Permission denied" },
|
|
110505
111336
|
409: { description: "App definition needs repair" },
|
|
110506
|
-
404: { description: "App or
|
|
111337
|
+
404: { description: "App, action, or parent task not found" }
|
|
110507
111338
|
},
|
|
110508
111339
|
rbac: { permission: "app.use" }
|
|
110509
111340
|
});
|
|
@@ -111072,10 +111903,29 @@ async function handleApps(req, res, pathSegments, queryParams, myAgentId) {
|
|
|
111072
111903
|
}
|
|
111073
111904
|
if (definitionNeedsRepair(res, app))
|
|
111074
111905
|
return true;
|
|
111906
|
+
if (parsed.body.parentTaskId) {
|
|
111907
|
+
const actions = app.definition.actions;
|
|
111908
|
+
const action = actions && Object.hasOwn(actions, parsed.params.name) ? actions[parsed.params.name] : undefined;
|
|
111909
|
+
if (action && action.kind !== "task") {
|
|
111910
|
+
jsonError(res, "parentTaskId is only supported for task-kind actions", 400);
|
|
111911
|
+
return true;
|
|
111912
|
+
}
|
|
111913
|
+
if (action) {
|
|
111914
|
+
const parentTask = await getTaskById2(parsed.body.parentTaskId);
|
|
111915
|
+
if (!parentTask) {
|
|
111916
|
+
jsonError(res, "parent task not found", 404);
|
|
111917
|
+
return true;
|
|
111918
|
+
}
|
|
111919
|
+
const principal = await agentFirstPrincipal(req, myAgentId);
|
|
111920
|
+
if (await denyParentAttach2(req, res, myAgentId, parentTask, principal))
|
|
111921
|
+
return true;
|
|
111922
|
+
}
|
|
111923
|
+
}
|
|
111075
111924
|
const output = await runAppAction({
|
|
111076
111925
|
app,
|
|
111077
111926
|
name: parsed.params.name,
|
|
111078
111927
|
input: parsed.body.input,
|
|
111928
|
+
parentTaskId: parsed.body.parentTaskId,
|
|
111079
111929
|
caller,
|
|
111080
111930
|
actor
|
|
111081
111931
|
});
|
|
@@ -112652,9 +113502,11 @@ var registerCancelTaskTool = (server) => {
|
|
|
112652
113502
|
init_zod();
|
|
112653
113503
|
|
|
112654
113504
|
// src/tools/chat-access.ts
|
|
113505
|
+
init_zod();
|
|
112655
113506
|
init_db3();
|
|
112656
113507
|
init_rbac();
|
|
112657
113508
|
init_context_key();
|
|
113509
|
+
var chatAttachmentsSchema = array2(string2().min(1)).max(10).optional().describe("Files to send after the text, up to 10: attachment ids of your current task (from get-task-details) or file paths in your agent-fs drive, such as thoughts/<agent-id>/report.pdf, read with your own agent-fs credential. Telegram shows JPEG and PNG as photos, MP4 as video, MP3 and M4A as audio, and anything else as a document. A file over the platform upload limit (Telegram 50 MB, Discord 10 MB) is not sent, and the thread gets a note naming it.");
|
|
112658
113510
|
async function callerChatThread(requestInfo) {
|
|
112659
113511
|
if (!requestInfo.agentId)
|
|
112660
113512
|
return null;
|
|
@@ -112735,16 +113587,18 @@ var registerChatPostTool = (server) => {
|
|
|
112735
113587
|
adapter: _enum2(CHAT_SDK_ADAPTER_NAMES).describe("Chat SDK adapter name."),
|
|
112736
113588
|
threadId: string2().min(1).optional().describe("Full SDK thread id, such as telegram:12345 or slack:C123:1700000000.000100."),
|
|
112737
113589
|
channelId: string2().min(1).optional().describe("Full SDK channel id, such as slack:C123. Ignored when threadId is set."),
|
|
112738
|
-
text: string2().min(1).max(20000).describe("Markdown text to post.")
|
|
113590
|
+
text: string2().min(1).max(20000).describe("Markdown text to post."),
|
|
113591
|
+
attachments: chatAttachmentsSchema
|
|
112739
113592
|
}),
|
|
112740
113593
|
outputSchema: swarmToolOutputSchema({
|
|
112741
113594
|
yourAgentId: string2().optional(),
|
|
112742
113595
|
messageId: string2().optional(),
|
|
112743
113596
|
adapter: string2().optional(),
|
|
112744
113597
|
threadId: string2().optional(),
|
|
112745
|
-
channelId: string2().optional()
|
|
113598
|
+
channelId: string2().optional(),
|
|
113599
|
+
unsentFiles: array2(looseObject({ name: string2().optional(), reason: string2().optional() })).optional()
|
|
112746
113600
|
})
|
|
112747
|
-
}, async ({ adapter, threadId, channelId, text }, requestInfo) => {
|
|
113601
|
+
}, async ({ adapter, threadId, channelId, text, attachments }, requestInfo) => {
|
|
112748
113602
|
const data = { yourAgentId: requestInfo.agentId };
|
|
112749
113603
|
const target = threadId ?? channelId;
|
|
112750
113604
|
if (!target)
|
|
@@ -112755,20 +113609,25 @@ var registerChatPostTool = (server) => {
|
|
|
112755
113609
|
if (!await canUseChatVerb(requestInfo, "integration.chat.post")) {
|
|
112756
113610
|
return toolErr("Permission denied. Only the lead can post outside the thread of its task. Use chat-reply for the thread of your current task.", { data });
|
|
112757
113611
|
}
|
|
113612
|
+
const resolved = await resolveChatAttachmentRefs(attachments ?? [], requestInfo.sourceTaskId, requestInfo.agentId);
|
|
113613
|
+
if ("error" in resolved)
|
|
113614
|
+
return toolErr(resolved.error, { data });
|
|
112758
113615
|
try {
|
|
112759
113616
|
const sent = await postChatMessage({
|
|
112760
113617
|
adapter,
|
|
112761
113618
|
...threadId ? { threadId } : { channelId },
|
|
112762
113619
|
text,
|
|
112763
|
-
taskId: requestInfo.sourceTaskId
|
|
113620
|
+
taskId: requestInfo.sourceTaskId,
|
|
113621
|
+
files: resolved.files
|
|
112764
113622
|
});
|
|
112765
|
-
return toolOk(`Posted to ${adapter} ${threadId ? "thread" : "channel"} ${target}
|
|
113623
|
+
return toolOk(`Posted to ${adapter} ${threadId ? "thread" : "channel"} ${target}.${unsentFilesSummary(sent.unsentFiles)}`, {
|
|
112766
113624
|
data: {
|
|
112767
113625
|
...data,
|
|
112768
113626
|
messageId: sent.messageIds.at(-1),
|
|
112769
113627
|
adapter: sent.adapter,
|
|
112770
113628
|
threadId: sent.threadId,
|
|
112771
|
-
channelId: sent.channelId
|
|
113629
|
+
channelId: sent.channelId,
|
|
113630
|
+
unsentFiles: sent.unsentFiles
|
|
112772
113631
|
}
|
|
112773
113632
|
});
|
|
112774
113633
|
} catch (error) {
|
|
@@ -112849,18 +113708,20 @@ init_context_key();
|
|
|
112849
113708
|
var registerChatReplyTool = (server) => {
|
|
112850
113709
|
createToolRegistrar(server)("chat-reply", {
|
|
112851
113710
|
title: "Reply in the chat thread of this task",
|
|
112852
|
-
description: "Post a message to the Telegram, Slack, Discord or Teams thread your current task came from. Works only on a task whose contextKey starts with task:chat-sdk:. The task's final output is posted to the thread automatically when the task ends, so use this only for a question to the user
|
|
113711
|
+
description: "Post a message to the Telegram, Slack, Discord or Teams thread your current task came from. Works only on a task whose contextKey starts with task:chat-sdk:. The task's final output is posted to the thread automatically when the task ends, so use this only for a question to the user, a short progress note on long work, or to send files (attachments). Markdown is supported; long text is split into several messages. When the final output of a task is posted, the files attached to that task go with it.",
|
|
112853
113712
|
annotations: { openWorldHint: true },
|
|
112854
113713
|
inputSchema: object2({
|
|
112855
|
-
text: string2().min(1).max(20000).describe("Markdown text to post to the thread.")
|
|
113714
|
+
text: string2().min(1).max(20000).describe("Markdown text to post to the thread."),
|
|
113715
|
+
attachments: chatAttachmentsSchema
|
|
112856
113716
|
}),
|
|
112857
113717
|
outputSchema: swarmToolOutputSchema({
|
|
112858
113718
|
yourAgentId: string2().optional(),
|
|
112859
113719
|
messageId: string2().optional(),
|
|
112860
113720
|
adapter: string2().optional(),
|
|
112861
|
-
threadId: string2().optional()
|
|
113721
|
+
threadId: string2().optional(),
|
|
113722
|
+
unsentFiles: array2(looseObject({ name: string2().optional(), reason: string2().optional() })).optional()
|
|
112862
113723
|
})
|
|
112863
|
-
}, async ({ text }, requestInfo) => {
|
|
113724
|
+
}, async ({ text, attachments }, requestInfo) => {
|
|
112864
113725
|
if (!requestInfo.agentId)
|
|
112865
113726
|
return toolErr("Agent ID not found.");
|
|
112866
113727
|
const data = { yourAgentId: requestInfo.agentId };
|
|
@@ -112874,19 +113735,24 @@ var registerChatReplyTool = (server) => {
|
|
|
112874
113735
|
if (!thread) {
|
|
112875
113736
|
return toolErr(`Task ${task.id} did not come from a chat thread (no task:chat-sdk contextKey). Use the tool of the channel the task came from.`, { data });
|
|
112876
113737
|
}
|
|
113738
|
+
const resolved = await resolveChatAttachmentRefs(attachments ?? [], task.id, requestInfo.agentId);
|
|
113739
|
+
if ("error" in resolved)
|
|
113740
|
+
return toolErr(resolved.error, { data });
|
|
112877
113741
|
try {
|
|
112878
113742
|
const sent = await postChatMessage({
|
|
112879
113743
|
adapter: thread.adapter,
|
|
112880
113744
|
threadId: thread.threadId,
|
|
112881
113745
|
text,
|
|
112882
|
-
taskId: task.id
|
|
113746
|
+
taskId: task.id,
|
|
113747
|
+
files: resolved.files
|
|
112883
113748
|
});
|
|
112884
|
-
return toolOk(`Posted to ${thread.adapter} thread ${sent.threadId}
|
|
113749
|
+
return toolOk(`Posted to ${thread.adapter} thread ${sent.threadId}.${unsentFilesSummary(sent.unsentFiles)}`, {
|
|
112885
113750
|
data: {
|
|
112886
113751
|
...data,
|
|
112887
113752
|
messageId: sent.messageIds.at(-1),
|
|
112888
113753
|
adapter: sent.adapter,
|
|
112889
|
-
threadId: sent.threadId
|
|
113754
|
+
threadId: sent.threadId,
|
|
113755
|
+
unsentFiles: sent.unsentFiles
|
|
112890
113756
|
}
|
|
112891
113757
|
});
|
|
112892
113758
|
} catch (error) {
|
|
@@ -114374,8 +115240,523 @@ init_db3();
|
|
|
114374
115240
|
|
|
114375
115241
|
// src/tasks/task-terminal-effects.ts
|
|
114376
115242
|
init_db3();
|
|
115243
|
+
|
|
115244
|
+
// src/be/chunking.ts
|
|
115245
|
+
var MAX_CHUNK_SIZE = 2000;
|
|
115246
|
+
var CHUNK_OVERLAP = 100;
|
|
115247
|
+
var MIN_CHUNK_SIZE = 50;
|
|
115248
|
+
function chunkContent(text) {
|
|
115249
|
+
const trimmed = text.trim();
|
|
115250
|
+
if (!trimmed || trimmed.length < MIN_CHUNK_SIZE) {
|
|
115251
|
+
return [];
|
|
115252
|
+
}
|
|
115253
|
+
if (trimmed.length <= MAX_CHUNK_SIZE) {
|
|
115254
|
+
return [{ content: trimmed, chunkIndex: 0, totalChunks: 1, headings: [] }];
|
|
115255
|
+
}
|
|
115256
|
+
const sections = splitByHeaders(trimmed);
|
|
115257
|
+
const rawChunks = [];
|
|
115258
|
+
for (const section of sections) {
|
|
115259
|
+
if (section.content.length <= MAX_CHUNK_SIZE) {
|
|
115260
|
+
rawChunks.push(section);
|
|
115261
|
+
} else {
|
|
115262
|
+
const subChunks = recursiveSplit(section.content);
|
|
115263
|
+
for (const sub of subChunks) {
|
|
115264
|
+
rawChunks.push({ content: sub, headings: section.headings });
|
|
115265
|
+
}
|
|
115266
|
+
}
|
|
115267
|
+
}
|
|
115268
|
+
const packed = packSmallSections(rawChunks);
|
|
115269
|
+
return packed.map((c, i) => ({
|
|
115270
|
+
content: c.content,
|
|
115271
|
+
chunkIndex: i,
|
|
115272
|
+
totalChunks: packed.length,
|
|
115273
|
+
headings: c.headings
|
|
115274
|
+
}));
|
|
115275
|
+
}
|
|
115276
|
+
function renderSection(section) {
|
|
115277
|
+
return section.headings.length > 0 ? `${section.headings.join(" > ")}
|
|
115278
|
+
|
|
115279
|
+
${section.content}` : section.content;
|
|
115280
|
+
}
|
|
115281
|
+
function packSmallSections(sections) {
|
|
115282
|
+
const out = [];
|
|
115283
|
+
let pending = null;
|
|
115284
|
+
const flush = () => {
|
|
115285
|
+
if (pending)
|
|
115286
|
+
out.push({ content: pending.parts.join(`
|
|
115287
|
+
|
|
115288
|
+
`), headings: pending.headings });
|
|
115289
|
+
pending = null;
|
|
115290
|
+
};
|
|
115291
|
+
for (const section of sections) {
|
|
115292
|
+
const rendered = renderSection(section);
|
|
115293
|
+
if (section.content.trim().length >= MIN_CHUNK_SIZE) {
|
|
115294
|
+
flush();
|
|
115295
|
+
out.push({ content: rendered, headings: section.headings });
|
|
115296
|
+
continue;
|
|
115297
|
+
}
|
|
115298
|
+
if (pending && pending.length + 2 + rendered.length > MAX_CHUNK_SIZE)
|
|
115299
|
+
flush();
|
|
115300
|
+
if (pending) {
|
|
115301
|
+
pending.parts.push(rendered);
|
|
115302
|
+
pending.length += 2 + rendered.length;
|
|
115303
|
+
} else {
|
|
115304
|
+
pending = { parts: [rendered], length: rendered.length, headings: section.headings };
|
|
115305
|
+
}
|
|
115306
|
+
}
|
|
115307
|
+
flush();
|
|
115308
|
+
return out;
|
|
115309
|
+
}
|
|
115310
|
+
function splitByHeaders(text) {
|
|
115311
|
+
const lines = text.split(`
|
|
115312
|
+
`);
|
|
115313
|
+
const sections = [];
|
|
115314
|
+
let currentContent = [];
|
|
115315
|
+
const headingStack = [];
|
|
115316
|
+
for (const line of lines) {
|
|
115317
|
+
const headingMatch = line.match(/^(#{1,3})\s+(.+)$/);
|
|
115318
|
+
if (headingMatch) {
|
|
115319
|
+
if (currentContent.length > 0) {
|
|
115320
|
+
const content = currentContent.join(`
|
|
115321
|
+
`).trim();
|
|
115322
|
+
if (content) {
|
|
115323
|
+
sections.push({ content, headings: [...headingStack] });
|
|
115324
|
+
}
|
|
115325
|
+
currentContent = [];
|
|
115326
|
+
}
|
|
115327
|
+
const level = headingMatch[1].length;
|
|
115328
|
+
const title = headingMatch[2].trim();
|
|
115329
|
+
while (headingStack.length >= level) {
|
|
115330
|
+
headingStack.pop();
|
|
115331
|
+
}
|
|
115332
|
+
headingStack.push(`${"#".repeat(level)} ${title}`);
|
|
115333
|
+
} else {
|
|
115334
|
+
currentContent.push(line);
|
|
115335
|
+
}
|
|
115336
|
+
}
|
|
115337
|
+
if (currentContent.length > 0) {
|
|
115338
|
+
const content = currentContent.join(`
|
|
115339
|
+
`).trim();
|
|
115340
|
+
if (content) {
|
|
115341
|
+
sections.push({ content, headings: [...headingStack] });
|
|
115342
|
+
}
|
|
115343
|
+
}
|
|
115344
|
+
if (sections.length === 0) {
|
|
115345
|
+
return [{ content: text, headings: [] }];
|
|
115346
|
+
}
|
|
115347
|
+
return sections;
|
|
115348
|
+
}
|
|
115349
|
+
var SEPARATORS = [`
|
|
115350
|
+
|
|
115351
|
+
`, `
|
|
115352
|
+
`, ". ", " "];
|
|
115353
|
+
function recursiveSplit(text) {
|
|
115354
|
+
return recursiveSplitWithSeparators(text, 0);
|
|
115355
|
+
}
|
|
115356
|
+
function recursiveSplitWithSeparators(text, separatorIndex) {
|
|
115357
|
+
if (text.length <= MAX_CHUNK_SIZE) {
|
|
115358
|
+
return [text.trim()].filter((s) => s.length > 0);
|
|
115359
|
+
}
|
|
115360
|
+
if (separatorIndex >= SEPARATORS.length) {
|
|
115361
|
+
return hardSplit(text);
|
|
115362
|
+
}
|
|
115363
|
+
const separator = SEPARATORS[separatorIndex];
|
|
115364
|
+
const parts = text.split(separator);
|
|
115365
|
+
if (parts.length <= 1) {
|
|
115366
|
+
return recursiveSplitWithSeparators(text, separatorIndex + 1);
|
|
115367
|
+
}
|
|
115368
|
+
const chunks = [];
|
|
115369
|
+
let current = "";
|
|
115370
|
+
for (const part of parts) {
|
|
115371
|
+
const candidate = current ? current + separator + part : part;
|
|
115372
|
+
if (candidate.length <= MAX_CHUNK_SIZE) {
|
|
115373
|
+
current = candidate;
|
|
115374
|
+
} else {
|
|
115375
|
+
if (current) {
|
|
115376
|
+
chunks.push(current.trim());
|
|
115377
|
+
}
|
|
115378
|
+
if (part.length > MAX_CHUNK_SIZE) {
|
|
115379
|
+
chunks.push(...recursiveSplitWithSeparators(part, separatorIndex + 1));
|
|
115380
|
+
current = "";
|
|
115381
|
+
} else {
|
|
115382
|
+
current = part;
|
|
115383
|
+
}
|
|
115384
|
+
}
|
|
115385
|
+
}
|
|
115386
|
+
if (current.trim()) {
|
|
115387
|
+
chunks.push(current.trim());
|
|
115388
|
+
}
|
|
115389
|
+
return addOverlap(chunks, text);
|
|
115390
|
+
}
|
|
115391
|
+
function hardSplit(text) {
|
|
115392
|
+
const chunks = [];
|
|
115393
|
+
let start = 0;
|
|
115394
|
+
while (start < text.length) {
|
|
115395
|
+
const end = Math.min(start + MAX_CHUNK_SIZE, text.length);
|
|
115396
|
+
chunks.push(text.slice(start, end).trim());
|
|
115397
|
+
if (end === text.length)
|
|
115398
|
+
break;
|
|
115399
|
+
start = end - CHUNK_OVERLAP;
|
|
115400
|
+
}
|
|
115401
|
+
return chunks.filter((c) => c.length > 0);
|
|
115402
|
+
}
|
|
115403
|
+
function addOverlap(chunks, _originalText) {
|
|
115404
|
+
if (chunks.length <= 1)
|
|
115405
|
+
return chunks;
|
|
115406
|
+
const result = [chunks[0]];
|
|
115407
|
+
for (let i = 1;i < chunks.length; i++) {
|
|
115408
|
+
const prevChunk = chunks[i - 1];
|
|
115409
|
+
const chunk = chunks[i];
|
|
115410
|
+
const overlapText = prevChunk.slice(-CHUNK_OVERLAP);
|
|
115411
|
+
if (overlapText.length + chunk.length <= MAX_CHUNK_SIZE + CHUNK_OVERLAP) {
|
|
115412
|
+
result.push(overlapText + chunk);
|
|
115413
|
+
} else {
|
|
115414
|
+
result.push(chunk);
|
|
115415
|
+
}
|
|
115416
|
+
}
|
|
115417
|
+
return result;
|
|
115418
|
+
}
|
|
115419
|
+
|
|
115420
|
+
// src/be/memory/index-content.ts
|
|
114377
115421
|
init_memory();
|
|
114378
115422
|
|
|
115423
|
+
// src/be/memory/key-guard.ts
|
|
115424
|
+
init_rbac();
|
|
115425
|
+
init_key_paths();
|
|
115426
|
+
|
|
115427
|
+
class MemoryKeyError extends Error {
|
|
115428
|
+
reason;
|
|
115429
|
+
constructor(message, reason) {
|
|
115430
|
+
super(message);
|
|
115431
|
+
this.reason = reason;
|
|
115432
|
+
this.name = "MemoryKeyError";
|
|
115433
|
+
}
|
|
115434
|
+
}
|
|
115435
|
+
var NO_AUTHORITY = {
|
|
115436
|
+
principal: { kind: "agent", agentId: "", isLead: false },
|
|
115437
|
+
source: "http"
|
|
115438
|
+
};
|
|
115439
|
+
function shapeError(key, origin) {
|
|
115440
|
+
if (key.length <= MEMORY_KEY_MAX_LENGTH && MEMORY_KEY_PATTERN.test(key))
|
|
115441
|
+
return null;
|
|
115442
|
+
const subject = origin === "sourcePath" ? `sourcePath "${key}" starts with ${LONGTERM_ROOT}, so it is used as the key, but it is not a valid key.` : `Key "${key}" is not a valid key.`;
|
|
115443
|
+
return `${subject} ${MEMORY_KEY_PATTERN_MESSAGE}`;
|
|
115444
|
+
}
|
|
115445
|
+
function assertKeyWritable(key, origin, writer) {
|
|
115446
|
+
if (origin === "sourcePath" && !isLongtermKey(key))
|
|
115447
|
+
return;
|
|
115448
|
+
const shape = shapeError(key, origin);
|
|
115449
|
+
if (shape)
|
|
115450
|
+
throw new MemoryKeyError(shape, "invalid");
|
|
115451
|
+
const pathError = longtermKeyError(key);
|
|
115452
|
+
if (pathError)
|
|
115453
|
+
throw new MemoryKeyError(pathError, "invalid");
|
|
115454
|
+
if (!isConsolidatedKey(key))
|
|
115455
|
+
return;
|
|
115456
|
+
const { principal, source } = writer ?? NO_AUTHORITY;
|
|
115457
|
+
const decision = can({
|
|
115458
|
+
principal,
|
|
115459
|
+
verb: "memory.write.consolidated",
|
|
115460
|
+
resource: { kind: "none" },
|
|
115461
|
+
source
|
|
115462
|
+
});
|
|
115463
|
+
if (!decision.allow)
|
|
115464
|
+
throw new MemoryKeyError(consolidatedKeyMessage(key), "forbidden");
|
|
115465
|
+
}
|
|
115466
|
+
|
|
115467
|
+
// src/be/memory/link-resolver.ts
|
|
115468
|
+
init_db3();
|
|
115469
|
+
init_constants2();
|
|
115470
|
+
var WIKILINK_RE = /\[\[([^\]]+)\]\]/g;
|
|
115471
|
+
var PR_HASH_RE = /(?:^|[\s(])#(\d{1,5})(?=[\s,.)!?]|$)/gm;
|
|
115472
|
+
var PR_PREFIX_RE = /\bPR\s*#(\d{1,5})\b/gi;
|
|
115473
|
+
var GITHUB_PR_URL_RE = /https?:\/\/github\.com\/([\w.-]+)\/([\w.-]+)\/pull\/(\d+)/g;
|
|
115474
|
+
var AGENT_FS_LIVE_HOSTS = String.raw`agent-fs|live\.agent-fs\.dev`;
|
|
115475
|
+
var AGENT_FS_FILE_ROUTE = String.raw`\/file\/~\/([a-f0-9-]+)\/([a-f0-9-]+)\/([\w/.%-]+)`;
|
|
115476
|
+
var AGENT_UI_PAGE_RE = /(?:app\.[^/]+|localhost:\d+)\/pages\/([a-f0-9-]+)/g;
|
|
115477
|
+
var AGENT_UI_TASK_RE = /(?:app\.[^/]+|localhost:\d+)\/tasks\/([a-f0-9-]+)/g;
|
|
115478
|
+
var wikilinkMatcher = (content) => {
|
|
115479
|
+
const results = [];
|
|
115480
|
+
for (const match of content.matchAll(WIKILINK_RE)) {
|
|
115481
|
+
const name = match[1].trim();
|
|
115482
|
+
if (!name)
|
|
115483
|
+
continue;
|
|
115484
|
+
results.push({
|
|
115485
|
+
linkType: "wikilink",
|
|
115486
|
+
targetKind: "memory",
|
|
115487
|
+
targetId: name,
|
|
115488
|
+
sourceText: match[0],
|
|
115489
|
+
resolver: "wikilink"
|
|
115490
|
+
});
|
|
115491
|
+
}
|
|
115492
|
+
return results;
|
|
115493
|
+
};
|
|
115494
|
+
var prMatcher = (content) => {
|
|
115495
|
+
const results = [];
|
|
115496
|
+
const seen = new Set;
|
|
115497
|
+
for (const match of content.matchAll(GITHUB_PR_URL_RE)) {
|
|
115498
|
+
const id = `github:${match[1]}/${match[2]}#${match[3]}`;
|
|
115499
|
+
if (seen.has(id))
|
|
115500
|
+
continue;
|
|
115501
|
+
seen.add(id);
|
|
115502
|
+
results.push({
|
|
115503
|
+
linkType: "pr",
|
|
115504
|
+
targetKind: "pr",
|
|
115505
|
+
targetId: id,
|
|
115506
|
+
sourceText: match[0],
|
|
115507
|
+
resolver: "pr-url",
|
|
115508
|
+
metadata: { owner: match[1], repo: match[2], number: Number(match[3]) }
|
|
115509
|
+
});
|
|
115510
|
+
}
|
|
115511
|
+
for (const match of content.matchAll(PR_PREFIX_RE)) {
|
|
115512
|
+
const id = `pr:${match[1]}`;
|
|
115513
|
+
if (seen.has(id))
|
|
115514
|
+
continue;
|
|
115515
|
+
seen.add(id);
|
|
115516
|
+
results.push({
|
|
115517
|
+
linkType: "pr",
|
|
115518
|
+
targetKind: "pr",
|
|
115519
|
+
targetId: id,
|
|
115520
|
+
sourceText: match[0].trim(),
|
|
115521
|
+
resolver: "pr-prefix",
|
|
115522
|
+
metadata: { number: Number(match[1]) }
|
|
115523
|
+
});
|
|
115524
|
+
}
|
|
115525
|
+
for (const match of content.matchAll(PR_HASH_RE)) {
|
|
115526
|
+
const id = `pr:${match[1]}`;
|
|
115527
|
+
if (seen.has(id))
|
|
115528
|
+
continue;
|
|
115529
|
+
seen.add(id);
|
|
115530
|
+
results.push({
|
|
115531
|
+
linkType: "pr",
|
|
115532
|
+
targetKind: "pr",
|
|
115533
|
+
targetId: id,
|
|
115534
|
+
sourceText: `#${match[1]}`,
|
|
115535
|
+
resolver: "pr-hash",
|
|
115536
|
+
metadata: { number: Number(match[1]) }
|
|
115537
|
+
});
|
|
115538
|
+
}
|
|
115539
|
+
return results;
|
|
115540
|
+
};
|
|
115541
|
+
function escapeRegExp2(value) {
|
|
115542
|
+
return value.replace(/[.*+?^${}()|[\]\\/]/g, "\\$&");
|
|
115543
|
+
}
|
|
115544
|
+
function agentFsPathRegex() {
|
|
115545
|
+
const appHosts = getConfiguredAppUrls().flatMap((value) => {
|
|
115546
|
+
try {
|
|
115547
|
+
const url = new URL(value);
|
|
115548
|
+
return [escapeRegExp2(`${url.host}${url.pathname.replace(/\/+$/, "")}`)];
|
|
115549
|
+
} catch {
|
|
115550
|
+
return [];
|
|
115551
|
+
}
|
|
115552
|
+
});
|
|
115553
|
+
const hosts = [AGENT_FS_LIVE_HOSTS, ...appHosts, String.raw`localhost:\d+`].join("|");
|
|
115554
|
+
return new RegExp(`(?<![\\w.-])(?:${hosts})${AGENT_FS_FILE_ROUTE}`, "gi");
|
|
115555
|
+
}
|
|
115556
|
+
var agentFsMatcher = (content) => {
|
|
115557
|
+
const results = [];
|
|
115558
|
+
for (const match of content.matchAll(agentFsPathRegex())) {
|
|
115559
|
+
const orgId = match[1];
|
|
115560
|
+
const driveId = match[2];
|
|
115561
|
+
const path = match[3];
|
|
115562
|
+
results.push({
|
|
115563
|
+
linkType: "agent-fs-file",
|
|
115564
|
+
targetKind: "agent-fs-file",
|
|
115565
|
+
targetId: `${orgId}/${driveId}/${path}`,
|
|
115566
|
+
sourceText: match[0],
|
|
115567
|
+
resolver: "agent-fs-path",
|
|
115568
|
+
metadata: { orgId, driveId, path }
|
|
115569
|
+
});
|
|
115570
|
+
}
|
|
115571
|
+
return results;
|
|
115572
|
+
};
|
|
115573
|
+
var agentUiMatcher = (content) => {
|
|
115574
|
+
const results = [];
|
|
115575
|
+
for (const match of content.matchAll(AGENT_UI_PAGE_RE)) {
|
|
115576
|
+
results.push({
|
|
115577
|
+
linkType: "agent-ui",
|
|
115578
|
+
targetKind: "agent-ui",
|
|
115579
|
+
targetId: `page:${match[1]}`,
|
|
115580
|
+
sourceText: match[0],
|
|
115581
|
+
resolver: "agent-ui-page"
|
|
115582
|
+
});
|
|
115583
|
+
}
|
|
115584
|
+
for (const match of content.matchAll(AGENT_UI_TASK_RE)) {
|
|
115585
|
+
results.push({
|
|
115586
|
+
linkType: "agent-ui",
|
|
115587
|
+
targetKind: "agent-ui",
|
|
115588
|
+
targetId: `task:${match[1]}`,
|
|
115589
|
+
sourceText: match[0],
|
|
115590
|
+
resolver: "agent-ui-task"
|
|
115591
|
+
});
|
|
115592
|
+
}
|
|
115593
|
+
return results;
|
|
115594
|
+
};
|
|
115595
|
+
var MATCHERS = [wikilinkMatcher, prMatcher, agentFsMatcher, agentUiMatcher];
|
|
115596
|
+
function resolveLinks(content) {
|
|
115597
|
+
const results = [];
|
|
115598
|
+
for (const matcher of MATCHERS) {
|
|
115599
|
+
for (const link of matcher(content)) {
|
|
115600
|
+
results.push({ ...link, strength: 1 });
|
|
115601
|
+
}
|
|
115602
|
+
}
|
|
115603
|
+
return results;
|
|
115604
|
+
}
|
|
115605
|
+
async function resolveWikilinksToMemoryIds(agentId, links) {
|
|
115606
|
+
const db = getDbClient2();
|
|
115607
|
+
const resolved = [];
|
|
115608
|
+
for (const link of links) {
|
|
115609
|
+
if (link.linkType !== "wikilink") {
|
|
115610
|
+
resolved.push(link);
|
|
115611
|
+
continue;
|
|
115612
|
+
}
|
|
115613
|
+
const row = await db.get("SELECT id FROM agent_memory WHERE name = ? AND (agentId = ? OR scope = 'swarm') LIMIT 1", [link.targetId, agentId]);
|
|
115614
|
+
resolved.push(row ? { ...link, targetId: row.id } : link);
|
|
115615
|
+
}
|
|
115616
|
+
return resolved;
|
|
115617
|
+
}
|
|
115618
|
+
var INSERT_LINK_SQL = `INSERT OR IGNORE INTO memory_link
|
|
115619
|
+
(id, from_memory_id, linkType, targetKind, targetId, strength, resolver, sourceText, metadata, createdAt, updatedAt)
|
|
115620
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`;
|
|
115621
|
+
function insertLinkArgs(memoryId, link, now) {
|
|
115622
|
+
return [
|
|
115623
|
+
crypto.randomUUID(),
|
|
115624
|
+
memoryId,
|
|
115625
|
+
link.linkType,
|
|
115626
|
+
link.targetKind,
|
|
115627
|
+
link.targetId,
|
|
115628
|
+
link.strength,
|
|
115629
|
+
link.resolver,
|
|
115630
|
+
link.sourceText,
|
|
115631
|
+
link.metadata ? JSON.stringify(link.metadata) : null,
|
|
115632
|
+
now,
|
|
115633
|
+
now
|
|
115634
|
+
];
|
|
115635
|
+
}
|
|
115636
|
+
async function storeLinks(memoryId, agentId, content) {
|
|
115637
|
+
const links = resolveLinks(content);
|
|
115638
|
+
if (links.length === 0)
|
|
115639
|
+
return;
|
|
115640
|
+
const resolved = await resolveWikilinksToMemoryIds(agentId, links);
|
|
115641
|
+
const now = new Date().toISOString();
|
|
115642
|
+
await getDbClient2().transaction(async (tx) => {
|
|
115643
|
+
for (const link of resolved) {
|
|
115644
|
+
await tx.run(INSERT_LINK_SQL, insertLinkArgs(memoryId, link, now));
|
|
115645
|
+
}
|
|
115646
|
+
});
|
|
115647
|
+
}
|
|
115648
|
+
function linkIdentity2(link) {
|
|
115649
|
+
return JSON.stringify([link.linkType, link.targetKind, link.targetId, link.sourceText ?? null]);
|
|
115650
|
+
}
|
|
115651
|
+
async function refreshLinks(memoryId, agentId, content) {
|
|
115652
|
+
const resolved = await resolveWikilinksToMemoryIds(agentId, resolveLinks(content));
|
|
115653
|
+
const nextIdentities = new Set(resolved.map((link) => linkIdentity2(link)));
|
|
115654
|
+
const now = new Date().toISOString();
|
|
115655
|
+
await getDbClient2().transaction(async (tx) => {
|
|
115656
|
+
const existing = await tx.query(`SELECT id, linkType, targetKind, targetId, sourceText
|
|
115657
|
+
FROM memory_link
|
|
115658
|
+
WHERE from_memory_id = ? AND linkType != 'sequel'`, [memoryId]);
|
|
115659
|
+
for (const row of existing) {
|
|
115660
|
+
if (!nextIdentities.has(linkIdentity2(row))) {
|
|
115661
|
+
await tx.run("DELETE FROM memory_link WHERE id = ?", [row.id]);
|
|
115662
|
+
}
|
|
115663
|
+
}
|
|
115664
|
+
for (const link of resolved) {
|
|
115665
|
+
await tx.run(INSERT_LINK_SQL, insertLinkArgs(memoryId, link, now));
|
|
115666
|
+
}
|
|
115667
|
+
});
|
|
115668
|
+
}
|
|
115669
|
+
|
|
115670
|
+
// src/be/memory/index-content.ts
|
|
115671
|
+
init_secret_scrubber();
|
|
115672
|
+
function taskCompletionMemoryKey(taskId) {
|
|
115673
|
+
return `/task-completions/${taskId.toLowerCase().replace(/[^a-z0-9._-]/g, "-")}`;
|
|
115674
|
+
}
|
|
115675
|
+
async function indexMemoryContent(params) {
|
|
115676
|
+
const { agentId, content, name, scope, source, sourceTaskId, sourcePath, tags } = params;
|
|
115677
|
+
const rowKey = params.key ?? (sourcePath || null);
|
|
115678
|
+
if (rowKey)
|
|
115679
|
+
assertKeyWritable(rowKey, params.key != null ? "key" : "sourcePath", params.writer);
|
|
115680
|
+
const contentChunks = chunkContent(content);
|
|
115681
|
+
if (contentChunks.length === 0) {
|
|
115682
|
+
contentChunks.push({
|
|
115683
|
+
content: content.trim(),
|
|
115684
|
+
chunkIndex: 0,
|
|
115685
|
+
totalChunks: 1,
|
|
115686
|
+
headings: []
|
|
115687
|
+
});
|
|
115688
|
+
}
|
|
115689
|
+
const store = getMemoryStore2();
|
|
115690
|
+
const provider = getEmbeddingProvider2();
|
|
115691
|
+
if (sourcePath && agentId && contentChunks.length === 1) {
|
|
115692
|
+
const existing = (await store.list(agentId, {
|
|
115693
|
+
scope,
|
|
115694
|
+
limit: 2,
|
|
115695
|
+
ownerAgentId: agentId,
|
|
115696
|
+
sourcePath
|
|
115697
|
+
})).filter((memory) => memory.sourcePath === sourcePath);
|
|
115698
|
+
if (existing.length === 1 && existing[0]?.totalChunks === 1) {
|
|
115699
|
+
const result = await store.edit({
|
|
115700
|
+
id: existing[0].id,
|
|
115701
|
+
mode: "replace",
|
|
115702
|
+
content: contentChunks[0].content,
|
|
115703
|
+
intent: "re-index memory source path",
|
|
115704
|
+
changedByAgentId: agentId
|
|
115705
|
+
});
|
|
115706
|
+
const embedding = await provider.embed(result.memory.content);
|
|
115707
|
+
if (embedding)
|
|
115708
|
+
await store.updateEmbedding(result.memory.id, embedding, provider.name);
|
|
115709
|
+
try {
|
|
115710
|
+
await refreshLinks(result.memory.id, agentId, result.memory.content);
|
|
115711
|
+
} catch (err) {
|
|
115712
|
+
console.error(`[memory] Link resolution failed for ${result.memory.id}:`, err.message);
|
|
115713
|
+
}
|
|
115714
|
+
return { queued: false, memoryIds: [result.memory.id], edited: result.changed, chunks: 1 };
|
|
115715
|
+
}
|
|
115716
|
+
}
|
|
115717
|
+
if (sourcePath && agentId) {
|
|
115718
|
+
await store.deleteBySourcePath(sourcePath, agentId);
|
|
115719
|
+
}
|
|
115720
|
+
const inputs = contentChunks.map((chunk) => ({
|
|
115721
|
+
agentId: agentId || null,
|
|
115722
|
+
content: chunk.content,
|
|
115723
|
+
name,
|
|
115724
|
+
scope,
|
|
115725
|
+
source,
|
|
115726
|
+
sourcePath: sourcePath || null,
|
|
115727
|
+
sourceTaskId: sourceTaskId || null,
|
|
115728
|
+
chunkIndex: chunk.chunkIndex,
|
|
115729
|
+
totalChunks: chunk.totalChunks,
|
|
115730
|
+
tags: tags || [],
|
|
115731
|
+
contextKey: params.contextKey ?? null,
|
|
115732
|
+
intent: params.intent ?? "index memory content",
|
|
115733
|
+
key: rowKey
|
|
115734
|
+
}));
|
|
115735
|
+
const memories = params.replaceExisting && params.key ? await store.replaceDocument({ key: params.key, scope, agentId: agentId || null, source }, inputs) : await store.storeBatch(inputs);
|
|
115736
|
+
if (agentId) {
|
|
115737
|
+
for (const memory of memories) {
|
|
115738
|
+
try {
|
|
115739
|
+
await storeLinks(memory.id, agentId, memory.content);
|
|
115740
|
+
} catch (err) {
|
|
115741
|
+
console.error(`[memory] Link resolution failed for ${memory.id}:`, err.message);
|
|
115742
|
+
}
|
|
115743
|
+
}
|
|
115744
|
+
}
|
|
115745
|
+
(async () => {
|
|
115746
|
+
try {
|
|
115747
|
+
const embeddings = await provider.embedBatch(memories.map((m) => m.content));
|
|
115748
|
+
for (let i = 0;i < embeddings.length; i++) {
|
|
115749
|
+
if (embeddings[i]) {
|
|
115750
|
+
await store.updateEmbedding(memories[i].id, embeddings[i], provider.name);
|
|
115751
|
+
}
|
|
115752
|
+
}
|
|
115753
|
+
} catch (err) {
|
|
115754
|
+
console.error("[memory] Batch embedding failed:", err.message);
|
|
115755
|
+
}
|
|
115756
|
+
})().catch((err) => console.error("[memory] batch embed failed:", scrubSecrets(err instanceof Error ? err.message : String(err))));
|
|
115757
|
+
return { queued: true, memoryIds: memories.map((m) => m.id), chunks: contentChunks.length };
|
|
115758
|
+
}
|
|
115759
|
+
|
|
114379
115760
|
// src/be/memory/raters/retrieval.ts
|
|
114380
115761
|
init_db3();
|
|
114381
115762
|
function dedupeMemoryDocumentIds(memories) {
|
|
@@ -115131,40 +116512,39 @@ ${safeFailureReason || "No reason provided"}
|
|
|
115131
116512
|
This task failed. Learn from this to avoid repeating the mistake.`;
|
|
115132
116513
|
if (taskContent.length < 30)
|
|
115133
116514
|
return;
|
|
115134
|
-
const
|
|
115135
|
-
|
|
115136
|
-
const memory = await store.store({
|
|
116515
|
+
const key = taskCompletionMemoryKey(taskId);
|
|
116516
|
+
await indexMemoryContent({
|
|
115137
116517
|
agentId: agentId ?? null,
|
|
115138
116518
|
content: taskContent,
|
|
115139
116519
|
name: `Task: ${safeTask.slice(0, 80)}`,
|
|
115140
116520
|
scope: "agent",
|
|
115141
116521
|
source: "task_completion",
|
|
115142
|
-
sourceTaskId: taskId
|
|
116522
|
+
sourceTaskId: taskId,
|
|
116523
|
+
key,
|
|
116524
|
+
intent: "task completion memory",
|
|
116525
|
+
replaceExisting: true
|
|
115143
116526
|
});
|
|
115144
|
-
const embedding = await provider.embed(taskContent);
|
|
115145
|
-
if (embedding) {
|
|
115146
|
-
await store.updateEmbedding(memory.id, embedding, provider.name);
|
|
115147
|
-
}
|
|
115148
116527
|
const shouldShareWithSwarm = status === "completed" && (task.taskType === "research" || task.tags?.includes("knowledge") || task.tags?.includes("shared"));
|
|
115149
116528
|
if (shouldShareWithSwarm) {
|
|
115150
116529
|
try {
|
|
115151
|
-
|
|
116530
|
+
await indexMemoryContent({
|
|
115152
116531
|
agentId: agentId ?? null,
|
|
115153
|
-
scope: "swarm",
|
|
115154
|
-
name: `Shared: ${safeTask.slice(0, 80)}`,
|
|
115155
116532
|
content: `Task completed by agent ${agentId}:
|
|
115156
116533
|
|
|
115157
116534
|
${taskContent}`,
|
|
116535
|
+
name: `Shared: ${safeTask.slice(0, 80)}`,
|
|
116536
|
+
scope: "swarm",
|
|
115158
116537
|
source: "task_completion",
|
|
115159
|
-
sourceTaskId: taskId
|
|
116538
|
+
sourceTaskId: taskId,
|
|
116539
|
+
key,
|
|
116540
|
+
intent: "task completion memory",
|
|
116541
|
+
replaceExisting: true
|
|
115160
116542
|
});
|
|
115161
|
-
const swarmEmbedding = await provider.embed(taskContent);
|
|
115162
|
-
if (swarmEmbedding) {
|
|
115163
|
-
await store.updateEmbedding(swarmMemory.id, swarmEmbedding, provider.name);
|
|
115164
|
-
}
|
|
115165
116543
|
} catch {}
|
|
115166
116544
|
}
|
|
115167
|
-
} catch {
|
|
116545
|
+
} catch (err) {
|
|
116546
|
+
console.error("[task-terminal-effects] task completion memory write failed:", scrubSecrets(err instanceof Error ? err.message : String(err)));
|
|
116547
|
+
}
|
|
115168
116548
|
})().catch((err) => console.error("[task-terminal-effects] task completion memory write failed:", scrubSecrets(err instanceof Error ? err.message : String(err))));
|
|
115169
116549
|
}
|
|
115170
116550
|
(async () => {
|
|
@@ -117855,258 +119235,7 @@ var registerMemoryDeleteTool = (server) => {
|
|
|
117855
119235
|
init_zod();
|
|
117856
119236
|
init_db3();
|
|
117857
119237
|
init_memory();
|
|
117858
|
-
|
|
117859
|
-
// src/be/memory/key-guard.ts
|
|
117860
|
-
init_rbac();
|
|
117861
119238
|
init_key_paths();
|
|
117862
|
-
|
|
117863
|
-
class MemoryKeyError extends Error {
|
|
117864
|
-
reason;
|
|
117865
|
-
constructor(message, reason) {
|
|
117866
|
-
super(message);
|
|
117867
|
-
this.reason = reason;
|
|
117868
|
-
this.name = "MemoryKeyError";
|
|
117869
|
-
}
|
|
117870
|
-
}
|
|
117871
|
-
var NO_AUTHORITY = {
|
|
117872
|
-
principal: { kind: "agent", agentId: "", isLead: false },
|
|
117873
|
-
source: "http"
|
|
117874
|
-
};
|
|
117875
|
-
function shapeError(key, origin) {
|
|
117876
|
-
if (key.length <= MEMORY_KEY_MAX_LENGTH && MEMORY_KEY_PATTERN.test(key))
|
|
117877
|
-
return null;
|
|
117878
|
-
const subject = origin === "sourcePath" ? `sourcePath "${key}" starts with ${LONGTERM_ROOT}, so it is used as the key, but it is not a valid key.` : `Key "${key}" is not a valid key.`;
|
|
117879
|
-
return `${subject} ${MEMORY_KEY_PATTERN_MESSAGE}`;
|
|
117880
|
-
}
|
|
117881
|
-
function assertKeyWritable(key, origin, writer) {
|
|
117882
|
-
if (origin === "sourcePath" && !isLongtermKey(key))
|
|
117883
|
-
return;
|
|
117884
|
-
const shape = shapeError(key, origin);
|
|
117885
|
-
if (shape)
|
|
117886
|
-
throw new MemoryKeyError(shape, "invalid");
|
|
117887
|
-
const pathError = longtermKeyError(key);
|
|
117888
|
-
if (pathError)
|
|
117889
|
-
throw new MemoryKeyError(pathError, "invalid");
|
|
117890
|
-
if (!isConsolidatedKey(key))
|
|
117891
|
-
return;
|
|
117892
|
-
const { principal, source } = writer ?? NO_AUTHORITY;
|
|
117893
|
-
const decision = can({
|
|
117894
|
-
principal,
|
|
117895
|
-
verb: "memory.write.consolidated",
|
|
117896
|
-
resource: { kind: "none" },
|
|
117897
|
-
source
|
|
117898
|
-
});
|
|
117899
|
-
if (!decision.allow)
|
|
117900
|
-
throw new MemoryKeyError(consolidatedKeyMessage(key), "forbidden");
|
|
117901
|
-
}
|
|
117902
|
-
|
|
117903
|
-
// src/tools/memory-edit.ts
|
|
117904
|
-
init_key_paths();
|
|
117905
|
-
|
|
117906
|
-
// src/be/memory/link-resolver.ts
|
|
117907
|
-
init_db3();
|
|
117908
|
-
init_constants2();
|
|
117909
|
-
var WIKILINK_RE = /\[\[([^\]]+)\]\]/g;
|
|
117910
|
-
var PR_HASH_RE = /(?:^|[\s(])#(\d{1,5})(?=[\s,.)!?]|$)/gm;
|
|
117911
|
-
var PR_PREFIX_RE = /\bPR\s*#(\d{1,5})\b/gi;
|
|
117912
|
-
var GITHUB_PR_URL_RE = /https?:\/\/github\.com\/([\w.-]+)\/([\w.-]+)\/pull\/(\d+)/g;
|
|
117913
|
-
var AGENT_FS_LIVE_HOSTS = String.raw`agent-fs|live\.agent-fs\.dev`;
|
|
117914
|
-
var AGENT_FS_FILE_ROUTE = String.raw`\/file\/~\/([a-f0-9-]+)\/([a-f0-9-]+)\/([\w/.%-]+)`;
|
|
117915
|
-
var AGENT_UI_PAGE_RE = /(?:app\.[^/]+|localhost:\d+)\/pages\/([a-f0-9-]+)/g;
|
|
117916
|
-
var AGENT_UI_TASK_RE = /(?:app\.[^/]+|localhost:\d+)\/tasks\/([a-f0-9-]+)/g;
|
|
117917
|
-
var wikilinkMatcher = (content) => {
|
|
117918
|
-
const results = [];
|
|
117919
|
-
for (const match of content.matchAll(WIKILINK_RE)) {
|
|
117920
|
-
const name = match[1].trim();
|
|
117921
|
-
if (!name)
|
|
117922
|
-
continue;
|
|
117923
|
-
results.push({
|
|
117924
|
-
linkType: "wikilink",
|
|
117925
|
-
targetKind: "memory",
|
|
117926
|
-
targetId: name,
|
|
117927
|
-
sourceText: match[0],
|
|
117928
|
-
resolver: "wikilink"
|
|
117929
|
-
});
|
|
117930
|
-
}
|
|
117931
|
-
return results;
|
|
117932
|
-
};
|
|
117933
|
-
var prMatcher = (content) => {
|
|
117934
|
-
const results = [];
|
|
117935
|
-
const seen = new Set;
|
|
117936
|
-
for (const match of content.matchAll(GITHUB_PR_URL_RE)) {
|
|
117937
|
-
const id = `github:${match[1]}/${match[2]}#${match[3]}`;
|
|
117938
|
-
if (seen.has(id))
|
|
117939
|
-
continue;
|
|
117940
|
-
seen.add(id);
|
|
117941
|
-
results.push({
|
|
117942
|
-
linkType: "pr",
|
|
117943
|
-
targetKind: "pr",
|
|
117944
|
-
targetId: id,
|
|
117945
|
-
sourceText: match[0],
|
|
117946
|
-
resolver: "pr-url",
|
|
117947
|
-
metadata: { owner: match[1], repo: match[2], number: Number(match[3]) }
|
|
117948
|
-
});
|
|
117949
|
-
}
|
|
117950
|
-
for (const match of content.matchAll(PR_PREFIX_RE)) {
|
|
117951
|
-
const id = `pr:${match[1]}`;
|
|
117952
|
-
if (seen.has(id))
|
|
117953
|
-
continue;
|
|
117954
|
-
seen.add(id);
|
|
117955
|
-
results.push({
|
|
117956
|
-
linkType: "pr",
|
|
117957
|
-
targetKind: "pr",
|
|
117958
|
-
targetId: id,
|
|
117959
|
-
sourceText: match[0].trim(),
|
|
117960
|
-
resolver: "pr-prefix",
|
|
117961
|
-
metadata: { number: Number(match[1]) }
|
|
117962
|
-
});
|
|
117963
|
-
}
|
|
117964
|
-
for (const match of content.matchAll(PR_HASH_RE)) {
|
|
117965
|
-
const id = `pr:${match[1]}`;
|
|
117966
|
-
if (seen.has(id))
|
|
117967
|
-
continue;
|
|
117968
|
-
seen.add(id);
|
|
117969
|
-
results.push({
|
|
117970
|
-
linkType: "pr",
|
|
117971
|
-
targetKind: "pr",
|
|
117972
|
-
targetId: id,
|
|
117973
|
-
sourceText: `#${match[1]}`,
|
|
117974
|
-
resolver: "pr-hash",
|
|
117975
|
-
metadata: { number: Number(match[1]) }
|
|
117976
|
-
});
|
|
117977
|
-
}
|
|
117978
|
-
return results;
|
|
117979
|
-
};
|
|
117980
|
-
function escapeRegExp2(value) {
|
|
117981
|
-
return value.replace(/[.*+?^${}()|[\]\\/]/g, "\\$&");
|
|
117982
|
-
}
|
|
117983
|
-
function agentFsPathRegex() {
|
|
117984
|
-
const appHosts = getConfiguredAppUrls().flatMap((value) => {
|
|
117985
|
-
try {
|
|
117986
|
-
const url = new URL(value);
|
|
117987
|
-
return [escapeRegExp2(`${url.host}${url.pathname.replace(/\/+$/, "")}`)];
|
|
117988
|
-
} catch {
|
|
117989
|
-
return [];
|
|
117990
|
-
}
|
|
117991
|
-
});
|
|
117992
|
-
const hosts = [AGENT_FS_LIVE_HOSTS, ...appHosts, String.raw`localhost:\d+`].join("|");
|
|
117993
|
-
return new RegExp(`(?<![\\w.-])(?:${hosts})${AGENT_FS_FILE_ROUTE}`, "gi");
|
|
117994
|
-
}
|
|
117995
|
-
var agentFsMatcher = (content) => {
|
|
117996
|
-
const results = [];
|
|
117997
|
-
for (const match of content.matchAll(agentFsPathRegex())) {
|
|
117998
|
-
const orgId = match[1];
|
|
117999
|
-
const driveId = match[2];
|
|
118000
|
-
const path = match[3];
|
|
118001
|
-
results.push({
|
|
118002
|
-
linkType: "agent-fs-file",
|
|
118003
|
-
targetKind: "agent-fs-file",
|
|
118004
|
-
targetId: `${orgId}/${driveId}/${path}`,
|
|
118005
|
-
sourceText: match[0],
|
|
118006
|
-
resolver: "agent-fs-path",
|
|
118007
|
-
metadata: { orgId, driveId, path }
|
|
118008
|
-
});
|
|
118009
|
-
}
|
|
118010
|
-
return results;
|
|
118011
|
-
};
|
|
118012
|
-
var agentUiMatcher = (content) => {
|
|
118013
|
-
const results = [];
|
|
118014
|
-
for (const match of content.matchAll(AGENT_UI_PAGE_RE)) {
|
|
118015
|
-
results.push({
|
|
118016
|
-
linkType: "agent-ui",
|
|
118017
|
-
targetKind: "agent-ui",
|
|
118018
|
-
targetId: `page:${match[1]}`,
|
|
118019
|
-
sourceText: match[0],
|
|
118020
|
-
resolver: "agent-ui-page"
|
|
118021
|
-
});
|
|
118022
|
-
}
|
|
118023
|
-
for (const match of content.matchAll(AGENT_UI_TASK_RE)) {
|
|
118024
|
-
results.push({
|
|
118025
|
-
linkType: "agent-ui",
|
|
118026
|
-
targetKind: "agent-ui",
|
|
118027
|
-
targetId: `task:${match[1]}`,
|
|
118028
|
-
sourceText: match[0],
|
|
118029
|
-
resolver: "agent-ui-task"
|
|
118030
|
-
});
|
|
118031
|
-
}
|
|
118032
|
-
return results;
|
|
118033
|
-
};
|
|
118034
|
-
var MATCHERS = [wikilinkMatcher, prMatcher, agentFsMatcher, agentUiMatcher];
|
|
118035
|
-
function resolveLinks(content) {
|
|
118036
|
-
const results = [];
|
|
118037
|
-
for (const matcher of MATCHERS) {
|
|
118038
|
-
for (const link of matcher(content)) {
|
|
118039
|
-
results.push({ ...link, strength: 1 });
|
|
118040
|
-
}
|
|
118041
|
-
}
|
|
118042
|
-
return results;
|
|
118043
|
-
}
|
|
118044
|
-
async function resolveWikilinksToMemoryIds(agentId, links) {
|
|
118045
|
-
const db = getDbClient2();
|
|
118046
|
-
const resolved = [];
|
|
118047
|
-
for (const link of links) {
|
|
118048
|
-
if (link.linkType !== "wikilink") {
|
|
118049
|
-
resolved.push(link);
|
|
118050
|
-
continue;
|
|
118051
|
-
}
|
|
118052
|
-
const row = await db.get("SELECT id FROM agent_memory WHERE name = ? AND (agentId = ? OR scope = 'swarm') LIMIT 1", [link.targetId, agentId]);
|
|
118053
|
-
resolved.push(row ? { ...link, targetId: row.id } : link);
|
|
118054
|
-
}
|
|
118055
|
-
return resolved;
|
|
118056
|
-
}
|
|
118057
|
-
var INSERT_LINK_SQL = `INSERT OR IGNORE INTO memory_link
|
|
118058
|
-
(id, from_memory_id, linkType, targetKind, targetId, strength, resolver, sourceText, metadata, createdAt, updatedAt)
|
|
118059
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`;
|
|
118060
|
-
function insertLinkArgs(memoryId, link, now) {
|
|
118061
|
-
return [
|
|
118062
|
-
crypto.randomUUID(),
|
|
118063
|
-
memoryId,
|
|
118064
|
-
link.linkType,
|
|
118065
|
-
link.targetKind,
|
|
118066
|
-
link.targetId,
|
|
118067
|
-
link.strength,
|
|
118068
|
-
link.resolver,
|
|
118069
|
-
link.sourceText,
|
|
118070
|
-
link.metadata ? JSON.stringify(link.metadata) : null,
|
|
118071
|
-
now,
|
|
118072
|
-
now
|
|
118073
|
-
];
|
|
118074
|
-
}
|
|
118075
|
-
async function storeLinks(memoryId, agentId, content) {
|
|
118076
|
-
const links = resolveLinks(content);
|
|
118077
|
-
if (links.length === 0)
|
|
118078
|
-
return;
|
|
118079
|
-
const resolved = await resolveWikilinksToMemoryIds(agentId, links);
|
|
118080
|
-
const now = new Date().toISOString();
|
|
118081
|
-
await getDbClient2().transaction(async (tx) => {
|
|
118082
|
-
for (const link of resolved) {
|
|
118083
|
-
await tx.run(INSERT_LINK_SQL, insertLinkArgs(memoryId, link, now));
|
|
118084
|
-
}
|
|
118085
|
-
});
|
|
118086
|
-
}
|
|
118087
|
-
function linkIdentity2(link) {
|
|
118088
|
-
return JSON.stringify([link.linkType, link.targetKind, link.targetId, link.sourceText ?? null]);
|
|
118089
|
-
}
|
|
118090
|
-
async function refreshLinks(memoryId, agentId, content) {
|
|
118091
|
-
const resolved = await resolveWikilinksToMemoryIds(agentId, resolveLinks(content));
|
|
118092
|
-
const nextIdentities = new Set(resolved.map((link) => linkIdentity2(link)));
|
|
118093
|
-
const now = new Date().toISOString();
|
|
118094
|
-
await getDbClient2().transaction(async (tx) => {
|
|
118095
|
-
const existing = await tx.query(`SELECT id, linkType, targetKind, targetId, sourceText
|
|
118096
|
-
FROM memory_link
|
|
118097
|
-
WHERE from_memory_id = ? AND linkType != 'sequel'`, [memoryId]);
|
|
118098
|
-
for (const row of existing) {
|
|
118099
|
-
if (!nextIdentities.has(linkIdentity2(row))) {
|
|
118100
|
-
await tx.run("DELETE FROM memory_link WHERE id = ?", [row.id]);
|
|
118101
|
-
}
|
|
118102
|
-
}
|
|
118103
|
-
for (const link of resolved) {
|
|
118104
|
-
await tx.run(INSERT_LINK_SQL, insertLinkArgs(memoryId, link, now));
|
|
118105
|
-
}
|
|
118106
|
-
});
|
|
118107
|
-
}
|
|
118108
|
-
|
|
118109
|
-
// src/tools/memory-edit.ts
|
|
118110
119239
|
init_rbac();
|
|
118111
119240
|
init_types();
|
|
118112
119241
|
var agentMemoryOutputSchema = looseObject({
|
|
@@ -118670,6 +119799,7 @@ async function expandCandidatesWithGraph(candidates, agentId, options = {}) {
|
|
|
118670
119799
|
// src/tools/memory-search.ts
|
|
118671
119800
|
init_key_paths();
|
|
118672
119801
|
init_reranker();
|
|
119802
|
+
init_search_candidates();
|
|
118673
119803
|
init_types();
|
|
118674
119804
|
var NUDGE_ELIGIBLE_SOURCES2 = new Set(["manual", "file_index"]);
|
|
118675
119805
|
function rateHintFor(memoryId) {
|
|
@@ -118725,7 +119855,7 @@ var registerMemorySearchTool = (server) => {
|
|
|
118725
119855
|
const store = getMemoryStore2();
|
|
118726
119856
|
const queryEmbedding = await provider.embed(query);
|
|
118727
119857
|
const candidateLimit = limit * CANDIDATE_SET_MULTIPLIER;
|
|
118728
|
-
const candidates = await store
|
|
119858
|
+
const candidates = await searchMemoryCandidates(store, queryEmbedding ?? new Float32Array(0), requestInfo.agentId, {
|
|
118729
119859
|
scope,
|
|
118730
119860
|
limit: candidateLimit,
|
|
118731
119861
|
source,
|
|
@@ -118813,242 +119943,6 @@ var registerMemorySearchTool = (server) => {
|
|
|
118813
119943
|
// src/tools/memory-store.ts
|
|
118814
119944
|
init_zod();
|
|
118815
119945
|
init_db3();
|
|
118816
|
-
|
|
118817
|
-
// src/be/chunking.ts
|
|
118818
|
-
var MAX_CHUNK_SIZE = 2000;
|
|
118819
|
-
var CHUNK_OVERLAP = 100;
|
|
118820
|
-
var MIN_CHUNK_SIZE = 50;
|
|
118821
|
-
function chunkContent(text) {
|
|
118822
|
-
const trimmed = text.trim();
|
|
118823
|
-
if (!trimmed || trimmed.length < MIN_CHUNK_SIZE) {
|
|
118824
|
-
return [];
|
|
118825
|
-
}
|
|
118826
|
-
if (trimmed.length <= MAX_CHUNK_SIZE) {
|
|
118827
|
-
return [{ content: trimmed, chunkIndex: 0, totalChunks: 1, headings: [] }];
|
|
118828
|
-
}
|
|
118829
|
-
const sections = splitByHeaders(trimmed);
|
|
118830
|
-
const rawChunks = [];
|
|
118831
|
-
for (const section of sections) {
|
|
118832
|
-
if (section.content.length <= MAX_CHUNK_SIZE) {
|
|
118833
|
-
rawChunks.push(section);
|
|
118834
|
-
} else {
|
|
118835
|
-
const subChunks = recursiveSplit(section.content);
|
|
118836
|
-
for (const sub of subChunks) {
|
|
118837
|
-
rawChunks.push({ content: sub, headings: section.headings });
|
|
118838
|
-
}
|
|
118839
|
-
}
|
|
118840
|
-
}
|
|
118841
|
-
const filtered = rawChunks.filter((c) => c.content.trim().length >= MIN_CHUNK_SIZE);
|
|
118842
|
-
if (filtered.length === 0) {
|
|
118843
|
-
return [{ content: trimmed, chunkIndex: 0, totalChunks: 1, headings: [] }];
|
|
118844
|
-
}
|
|
118845
|
-
return filtered.map((c, i) => ({
|
|
118846
|
-
content: c.headings.length > 0 ? `${c.headings.join(" > ")}
|
|
118847
|
-
|
|
118848
|
-
${c.content}` : c.content,
|
|
118849
|
-
chunkIndex: i,
|
|
118850
|
-
totalChunks: filtered.length,
|
|
118851
|
-
headings: c.headings
|
|
118852
|
-
}));
|
|
118853
|
-
}
|
|
118854
|
-
function splitByHeaders(text) {
|
|
118855
|
-
const lines = text.split(`
|
|
118856
|
-
`);
|
|
118857
|
-
const sections = [];
|
|
118858
|
-
let currentContent = [];
|
|
118859
|
-
const headingStack = [];
|
|
118860
|
-
for (const line of lines) {
|
|
118861
|
-
const headingMatch = line.match(/^(#{1,3})\s+(.+)$/);
|
|
118862
|
-
if (headingMatch) {
|
|
118863
|
-
if (currentContent.length > 0) {
|
|
118864
|
-
const content = currentContent.join(`
|
|
118865
|
-
`).trim();
|
|
118866
|
-
if (content) {
|
|
118867
|
-
sections.push({ content, headings: [...headingStack] });
|
|
118868
|
-
}
|
|
118869
|
-
currentContent = [];
|
|
118870
|
-
}
|
|
118871
|
-
const level = headingMatch[1].length;
|
|
118872
|
-
const title = headingMatch[2].trim();
|
|
118873
|
-
while (headingStack.length >= level) {
|
|
118874
|
-
headingStack.pop();
|
|
118875
|
-
}
|
|
118876
|
-
headingStack.push(`${"#".repeat(level)} ${title}`);
|
|
118877
|
-
} else {
|
|
118878
|
-
currentContent.push(line);
|
|
118879
|
-
}
|
|
118880
|
-
}
|
|
118881
|
-
if (currentContent.length > 0) {
|
|
118882
|
-
const content = currentContent.join(`
|
|
118883
|
-
`).trim();
|
|
118884
|
-
if (content) {
|
|
118885
|
-
sections.push({ content, headings: [...headingStack] });
|
|
118886
|
-
}
|
|
118887
|
-
}
|
|
118888
|
-
if (sections.length === 0) {
|
|
118889
|
-
return [{ content: text, headings: [] }];
|
|
118890
|
-
}
|
|
118891
|
-
return sections;
|
|
118892
|
-
}
|
|
118893
|
-
var SEPARATORS = [`
|
|
118894
|
-
|
|
118895
|
-
`, `
|
|
118896
|
-
`, ". ", " "];
|
|
118897
|
-
function recursiveSplit(text) {
|
|
118898
|
-
return recursiveSplitWithSeparators(text, 0);
|
|
118899
|
-
}
|
|
118900
|
-
function recursiveSplitWithSeparators(text, separatorIndex) {
|
|
118901
|
-
if (text.length <= MAX_CHUNK_SIZE) {
|
|
118902
|
-
return [text.trim()].filter((s) => s.length > 0);
|
|
118903
|
-
}
|
|
118904
|
-
if (separatorIndex >= SEPARATORS.length) {
|
|
118905
|
-
return hardSplit(text);
|
|
118906
|
-
}
|
|
118907
|
-
const separator = SEPARATORS[separatorIndex];
|
|
118908
|
-
const parts = text.split(separator);
|
|
118909
|
-
if (parts.length <= 1) {
|
|
118910
|
-
return recursiveSplitWithSeparators(text, separatorIndex + 1);
|
|
118911
|
-
}
|
|
118912
|
-
const chunks = [];
|
|
118913
|
-
let current = "";
|
|
118914
|
-
for (const part of parts) {
|
|
118915
|
-
const candidate = current ? current + separator + part : part;
|
|
118916
|
-
if (candidate.length <= MAX_CHUNK_SIZE) {
|
|
118917
|
-
current = candidate;
|
|
118918
|
-
} else {
|
|
118919
|
-
if (current) {
|
|
118920
|
-
chunks.push(current.trim());
|
|
118921
|
-
}
|
|
118922
|
-
if (part.length > MAX_CHUNK_SIZE) {
|
|
118923
|
-
chunks.push(...recursiveSplitWithSeparators(part, separatorIndex + 1));
|
|
118924
|
-
current = "";
|
|
118925
|
-
} else {
|
|
118926
|
-
current = part;
|
|
118927
|
-
}
|
|
118928
|
-
}
|
|
118929
|
-
}
|
|
118930
|
-
if (current.trim()) {
|
|
118931
|
-
chunks.push(current.trim());
|
|
118932
|
-
}
|
|
118933
|
-
return addOverlap(chunks, text);
|
|
118934
|
-
}
|
|
118935
|
-
function hardSplit(text) {
|
|
118936
|
-
const chunks = [];
|
|
118937
|
-
let start = 0;
|
|
118938
|
-
while (start < text.length) {
|
|
118939
|
-
const end = Math.min(start + MAX_CHUNK_SIZE, text.length);
|
|
118940
|
-
chunks.push(text.slice(start, end).trim());
|
|
118941
|
-
if (end === text.length)
|
|
118942
|
-
break;
|
|
118943
|
-
start = end - CHUNK_OVERLAP;
|
|
118944
|
-
}
|
|
118945
|
-
return chunks.filter((c) => c.length > 0);
|
|
118946
|
-
}
|
|
118947
|
-
function addOverlap(chunks, _originalText) {
|
|
118948
|
-
if (chunks.length <= 1)
|
|
118949
|
-
return chunks;
|
|
118950
|
-
const result = [chunks[0]];
|
|
118951
|
-
for (let i = 1;i < chunks.length; i++) {
|
|
118952
|
-
const prevChunk = chunks[i - 1];
|
|
118953
|
-
const chunk = chunks[i];
|
|
118954
|
-
const overlapText = prevChunk.slice(-CHUNK_OVERLAP);
|
|
118955
|
-
if (overlapText.length + chunk.length <= MAX_CHUNK_SIZE + CHUNK_OVERLAP) {
|
|
118956
|
-
result.push(overlapText + chunk);
|
|
118957
|
-
} else {
|
|
118958
|
-
result.push(chunk);
|
|
118959
|
-
}
|
|
118960
|
-
}
|
|
118961
|
-
return result;
|
|
118962
|
-
}
|
|
118963
|
-
|
|
118964
|
-
// src/be/memory/index-content.ts
|
|
118965
|
-
init_memory();
|
|
118966
|
-
init_secret_scrubber();
|
|
118967
|
-
async function indexMemoryContent(params) {
|
|
118968
|
-
const { agentId, content, name, scope, source, sourceTaskId, sourcePath, tags } = params;
|
|
118969
|
-
const rowKey = params.key ?? (sourcePath || null);
|
|
118970
|
-
if (rowKey)
|
|
118971
|
-
assertKeyWritable(rowKey, params.key != null ? "key" : "sourcePath", params.writer);
|
|
118972
|
-
const contentChunks = chunkContent(content);
|
|
118973
|
-
if (contentChunks.length === 0) {
|
|
118974
|
-
contentChunks.push({
|
|
118975
|
-
content: content.trim(),
|
|
118976
|
-
chunkIndex: 0,
|
|
118977
|
-
totalChunks: 1,
|
|
118978
|
-
headings: []
|
|
118979
|
-
});
|
|
118980
|
-
}
|
|
118981
|
-
const store = getMemoryStore2();
|
|
118982
|
-
const provider = getEmbeddingProvider2();
|
|
118983
|
-
if (sourcePath && agentId && contentChunks.length === 1) {
|
|
118984
|
-
const existing = (await store.list(agentId, {
|
|
118985
|
-
scope,
|
|
118986
|
-
limit: 2,
|
|
118987
|
-
ownerAgentId: agentId,
|
|
118988
|
-
sourcePath
|
|
118989
|
-
})).filter((memory) => memory.sourcePath === sourcePath);
|
|
118990
|
-
if (existing.length === 1 && existing[0]?.totalChunks === 1) {
|
|
118991
|
-
const result = await store.edit({
|
|
118992
|
-
id: existing[0].id,
|
|
118993
|
-
mode: "replace",
|
|
118994
|
-
content: contentChunks[0].content,
|
|
118995
|
-
intent: "re-index memory source path",
|
|
118996
|
-
changedByAgentId: agentId
|
|
118997
|
-
});
|
|
118998
|
-
const embedding = await provider.embed(result.memory.content);
|
|
118999
|
-
if (embedding)
|
|
119000
|
-
await store.updateEmbedding(result.memory.id, embedding, provider.name);
|
|
119001
|
-
try {
|
|
119002
|
-
await refreshLinks(result.memory.id, agentId, result.memory.content);
|
|
119003
|
-
} catch (err) {
|
|
119004
|
-
console.error(`[memory] Link resolution failed for ${result.memory.id}:`, err.message);
|
|
119005
|
-
}
|
|
119006
|
-
return { queued: false, memoryIds: [result.memory.id], edited: result.changed, chunks: 1 };
|
|
119007
|
-
}
|
|
119008
|
-
}
|
|
119009
|
-
if (sourcePath && agentId) {
|
|
119010
|
-
await store.deleteBySourcePath(sourcePath, agentId);
|
|
119011
|
-
}
|
|
119012
|
-
const memories = await store.storeBatch(contentChunks.map((chunk) => ({
|
|
119013
|
-
agentId: agentId || null,
|
|
119014
|
-
content: chunk.content,
|
|
119015
|
-
name,
|
|
119016
|
-
scope,
|
|
119017
|
-
source,
|
|
119018
|
-
sourcePath: sourcePath || null,
|
|
119019
|
-
sourceTaskId: sourceTaskId || null,
|
|
119020
|
-
chunkIndex: chunk.chunkIndex,
|
|
119021
|
-
totalChunks: chunk.totalChunks,
|
|
119022
|
-
tags: tags || [],
|
|
119023
|
-
contextKey: params.contextKey ?? null,
|
|
119024
|
-
intent: params.intent ?? "index memory content",
|
|
119025
|
-
key: rowKey
|
|
119026
|
-
})));
|
|
119027
|
-
if (agentId) {
|
|
119028
|
-
for (const memory of memories) {
|
|
119029
|
-
try {
|
|
119030
|
-
await storeLinks(memory.id, agentId, memory.content);
|
|
119031
|
-
} catch (err) {
|
|
119032
|
-
console.error(`[memory] Link resolution failed for ${memory.id}:`, err.message);
|
|
119033
|
-
}
|
|
119034
|
-
}
|
|
119035
|
-
}
|
|
119036
|
-
(async () => {
|
|
119037
|
-
try {
|
|
119038
|
-
const embeddings = await provider.embedBatch(memories.map((m) => m.content));
|
|
119039
|
-
for (let i = 0;i < embeddings.length; i++) {
|
|
119040
|
-
if (embeddings[i]) {
|
|
119041
|
-
await store.updateEmbedding(memories[i].id, embeddings[i], provider.name);
|
|
119042
|
-
}
|
|
119043
|
-
}
|
|
119044
|
-
} catch (err) {
|
|
119045
|
-
console.error("[memory] Batch embedding failed:", err.message);
|
|
119046
|
-
}
|
|
119047
|
-
})().catch((err) => console.error("[memory] batch embed failed:", scrubSecrets(err instanceof Error ? err.message : String(err))));
|
|
119048
|
-
return { queued: true, memoryIds: memories.map((m) => m.id), chunks: contentChunks.length };
|
|
119049
|
-
}
|
|
119050
|
-
|
|
119051
|
-
// src/tools/memory-store.ts
|
|
119052
119946
|
init_key_paths();
|
|
119053
119947
|
init_types();
|
|
119054
119948
|
var registerMemoryStoreTool = (server) => {
|
|
@@ -131584,33 +132478,35 @@ function formatFileSize2(bytes) {
|
|
|
131584
132478
|
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
131585
132479
|
return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;
|
|
131586
132480
|
}
|
|
131587
|
-
function buildAttachmentText(files, failed = []) {
|
|
132481
|
+
function buildAttachmentText(files, failed = [], notes = new Map) {
|
|
131588
132482
|
const reasons = new Map(failed.map((f) => [f.file.id, f.reason]));
|
|
131589
132483
|
return files.map((f) => {
|
|
131590
132484
|
const size = typeof f.size === "number" ? formatFileSize2(f.size) : "unknown size";
|
|
131591
132485
|
const line = `[File: ${f.name ?? f.id} (${f.mimetype ?? "unknown type"}, ${size}) id=${f.id}]`;
|
|
131592
132486
|
const reason = reasons.get(f.id);
|
|
131593
|
-
|
|
132487
|
+
const note = notes.get(f.id);
|
|
132488
|
+
return [reason ? `${line} (not attached: ${reason})` : line, note].filter(Boolean).join(`
|
|
132489
|
+
`);
|
|
131594
132490
|
}).join(`
|
|
131595
132491
|
`);
|
|
131596
132492
|
}
|
|
131597
|
-
function buildEffectiveText(text, files, failed) {
|
|
132493
|
+
function buildEffectiveText(text, files, failed, notes) {
|
|
131598
132494
|
const hasText = !!text?.trim();
|
|
131599
132495
|
const hasFiles = files && files.length > 0;
|
|
131600
132496
|
if (hasText && hasFiles) {
|
|
131601
132497
|
return `${text}
|
|
131602
132498
|
|
|
131603
|
-
${buildAttachmentText(files, failed)}`;
|
|
132499
|
+
${buildAttachmentText(files, failed, notes)}`;
|
|
131604
132500
|
}
|
|
131605
132501
|
if (hasFiles) {
|
|
131606
|
-
return buildAttachmentText(files, failed);
|
|
132502
|
+
return buildAttachmentText(files, failed, notes);
|
|
131607
132503
|
}
|
|
131608
132504
|
return text || "";
|
|
131609
132505
|
}
|
|
131610
132506
|
function bufferedFileFailures(files) {
|
|
131611
132507
|
return (files ?? []).map((file) => ({ file, reason: BUFFERED_REASON }));
|
|
131612
132508
|
}
|
|
131613
|
-
async function fetchSlackFiles(client, files) {
|
|
132509
|
+
async function fetchSlackFiles(client, files, options = {}) {
|
|
131614
132510
|
let dir;
|
|
131615
132511
|
const result = {
|
|
131616
132512
|
files: [],
|
|
@@ -131636,8 +132532,19 @@ async function fetchSlackFiles(client, files) {
|
|
|
131636
132532
|
result.fetched.push({ file, ...outcome });
|
|
131637
132533
|
}
|
|
131638
132534
|
}
|
|
132535
|
+
if (options.transcribe) {
|
|
132536
|
+
result.notes = await transcribeAudioNotes(result.fetched.filter(({ file }) => isSlackAudio(file)).map(({ file, path }) => ({
|
|
132537
|
+
key: file.id,
|
|
132538
|
+
name: file.name ?? file.id,
|
|
132539
|
+
data: Bun.file(path),
|
|
132540
|
+
mimeType: file.mimetype
|
|
132541
|
+
})), "[Slack]");
|
|
132542
|
+
}
|
|
131639
132543
|
return result;
|
|
131640
132544
|
}
|
|
132545
|
+
function isSlackAudio(file) {
|
|
132546
|
+
return file.subtype === "slack_audio" || Boolean(file.mimetype?.startsWith("audio/"));
|
|
132547
|
+
}
|
|
131641
132548
|
function looksLikeSignIn(head) {
|
|
131642
132549
|
const joined = new Uint8Array(head.reduce((total, part) => total + part.byteLength, 0));
|
|
131643
132550
|
let offset = 0;
|
|
@@ -133851,9 +134758,9 @@ var registerSystemOneDecideTool = (server) => {
|
|
|
133851
134758
|
createToolRegistrar(server)("system-one-decide", {
|
|
133852
134759
|
title: "Ask a SystemOne decision model",
|
|
133853
134760
|
annotations: { destructiveHint: false, openWorldHint: true },
|
|
133854
|
-
description: "Send a state and typed questions (noul, choice, score) to a SystemOne decision host such as Jev, and return the validated answers. " + "Same request, provider list, credentials and validation as the `system-one-decision` workflow node, without its human review band. " + "The provider credential is a global secret that stays on the server; this tool never returns it.",
|
|
134761
|
+
description: "Send a state and typed questions (noul, choice, score) to a SystemOne decision host such as Jev or Clef, and return the validated answers. " + "Same request, provider list, credentials and validation as the `system-one-decision` workflow node, without its human review band. " + "The provider credential is a global secret that stays on the server; this tool never returns it.",
|
|
133855
134762
|
inputSchema: object2({
|
|
133856
|
-
provider: _enum2(SYSTEM_ONE_PROVIDER_IDS).optional().describe("Decision host (default typesafe)"),
|
|
134763
|
+
provider: _enum2(SYSTEM_ONE_PROVIDER_IDS).optional().describe("Decision host (default: the SYSTEM_ONE_DEFAULT_PROVIDER global config, typesafe when unset)"),
|
|
133857
134764
|
model: string2().min(1).optional().describe("Provider model id (default: the provider's)"),
|
|
133858
134765
|
state: union2([string2(), array2(string2()), record2(string2(), unknown())]).describe("The state to decide on"),
|
|
133859
134766
|
questions: record2(string2(), record2(string2(), unknown())).describe("Questions by id, each `{ type: 'noul' | 'choice' | 'score', instructions, criteria }`"),
|
|
@@ -133864,7 +134771,8 @@ var registerSystemOneDecideTool = (server) => {
|
|
|
133864
134771
|
model: string2().optional(),
|
|
133865
134772
|
answers: record2(string2(), unknown()).optional(),
|
|
133866
134773
|
usage: record2(string2(), unknown()).optional(),
|
|
133867
|
-
requestId: string2().optional()
|
|
134774
|
+
requestId: string2().optional(),
|
|
134775
|
+
providerUnavailable: boolean().optional().describe("On an error: true when this deployment refuses the provider (e.g. OpenRouter behind a gateway) and no request was sent, so a caller choosing automatically can try its next provider")
|
|
133868
134776
|
})
|
|
133869
134777
|
}, async ({ provider, model, state, questions, timeoutMs, maxRetries }, requestInfo) => {
|
|
133870
134778
|
if (!requestInfo.agentId) {
|
|
@@ -133889,8 +134797,9 @@ var registerSystemOneDecideTool = (server) => {
|
|
|
133889
134797
|
return toolErr("The system-one-decision executor is not available");
|
|
133890
134798
|
}
|
|
133891
134799
|
const decided = await executor.decide(parsed.data);
|
|
133892
|
-
if (!decided.ok)
|
|
133893
|
-
return toolErr(decided.error);
|
|
134800
|
+
if (!decided.ok) {
|
|
134801
|
+
return toolErr(decided.error, decided.deploymentRefused ? { data: { providerUnavailable: true } } : {});
|
|
134802
|
+
}
|
|
133894
134803
|
const { output } = decided;
|
|
133895
134804
|
return toolOk(`Decision from ${output.model}`, {
|
|
133896
134805
|
data: {
|
|
@@ -135887,7 +136796,8 @@ async function createServer(opts = {}) {
|
|
|
135887
136796
|
...opts.preloadedTools?.length ? { instructions: resolveTemplate("system.agent.tool_preload", {}).text } : {},
|
|
135888
136797
|
capabilities: {
|
|
135889
136798
|
logging: {}
|
|
135890
|
-
}
|
|
136799
|
+
},
|
|
136800
|
+
maxToolInputElements: MCP_MAX_TOOL_INPUT_ELEMENTS
|
|
135891
136801
|
});
|
|
135892
136802
|
if (opts.preloadedTools?.length)
|
|
135893
136803
|
setPreloadedTools(server, opts.preloadedTools);
|
|
@@ -136122,4 +137032,4 @@ async function createServer(opts = {}) {
|
|
|
136122
137032
|
return server;
|
|
136123
137033
|
}
|
|
136124
137034
|
|
|
136125
|
-
export { DEFAULT_NEGOTIATED_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS, isJSONRPCRequest, isJSONRPCResultResponse, isJSONRPCErrorResponse, JSONRPCMessageSchema, isInitializeRequest, McpServer, isGitHubEnabled, initGitHub, verifyWebhookSignature, isAgentMailEnabled, initAgentMail, verifyAgentMailWebhook, resolveIdentity, renderIdentity, createAdditiveBuffer, taskModelPin, resumedTaskModelSelection, listHarnessModelSupport, recordHarnessModelSupport, agentRanModel, getAgentHarnessCliVersion, setAgentHarnessCliVersion, sanitizeModelTierOverrides, parseModelTierOverridesHeader, setAgentModelTierOverrides, previewModelTiers, recordClaimModelResolution, harnessModelErrorFor, poolTaskRunsOnHarness, explicitModelError, explicitModelErrorForAgent, referencedBundlePaths, skillDirs, TaskCreationBlockedError, recordUnmappedIdentity, MAX_TASK_ATTACHMENT_BYTES, recordTaskAttachmentUpload, buildEffectiveText, bufferedFileFailures, fetchSlackFiles, createSlackTaskWithFiles, notifySlackFileFailures, isRuntimePoolWakeable, isAgentReachable, hasOtherUserMention, broadcastMatches, routeMessage, extractTaskFromMessage, extractSlackMessageText, recoverIncompleteRuns, handleWebhookTrigger, verifyHmacSignature, WebhookError, snapshotAndUpdateWorkflow, RawLlmConfigSchema, RawLlmOutputSchema, executeRawLlm, getExecutorRegistry2, initWorkflows2, dispatchScheduleTarget, calculateNextRun2, startScheduler2, stopScheduler2, runScheduleNow2, ExtensionAssetConflictError, ExtensionOwnershipError, getExtensionFiles, getExtensionById, getExtensionByName, listExtensions, listExtensionVersions, updateExtensionMeta, listExtensionRuns, SDK_ALLOWLIST, mcpToolNameForSdkMethod, mcpOverflowAuthError, hasKvViewArgs, resolveKvView, toolErr, createToolRegistrar, handleMcpBridge, Redacted, SCRIPT_SDK_RESPONSE_LIMIT_BYTES, readScriptSdkJsonResponse, ExtensionConfigError, ExtensionLifecycleError, setExtensionLoopbackBaseUrl, enableExtension, disableExtension, activateVersion, ExtensionAssetsInvalidError, installExtensionWithAssets, uninstallExtension, reloadExtension, loadEnabledExtensions, stopExtensionRuntime, ExtensionAbortedError2, isRegistered2, isExtensionAgentId2, getExtensionBridgeToken2, resolveBridgeCallOrigin2, extensionIdForAgent2, runContext2, registerLoaded2, unregister2, listRegistered2, dispatchPre2, dispatchPost2, stripSiblingBlock, createTaskWithSiblingAwareness, isInboxAllowed, isSenderAllowed, handleMessageReceived, isAzureDevOpsEnabled, initAzureDevOps, verifyAzureDevOpsWebhook, repointTrackerSyncBySwarmId, isAzureDevOpsUrl, canonicalAzureDevOpsRepoUrl, parseAzureDevOpsRepoUrl, createdPullRequestOf, commentedPayloadOf, handlePullRequestCreated, handlePullRequestCommented, handleWorkItemCreated, handleWorkItemUpdated, handleWorkItemCommented, handleWorkItemDeleted, handleWorkItemRestored, initAzureDevOpsOutbound, AGENT_MAX_TASKS_CONFIG_KEY, reconcileAgentMaxTasksPolicy, resetAgentMaxTasksMirror, upsertSwarmConfigWithPolicyMirror, runtimeStaleThresholdMinutes, upsertRuntimeInstance, getRuntimeInstanceById, insertProvisioningRuntime, markRuntimeTerminated, touchRuntimeInstance, countActiveRuntimeInstancesForAgent, listRuntimeInstancesForAgent, setRuntimeCredentialReady, reconcileAgentStatusFromRuntimes, agentsWithLiveRuntime, expireStaleRuntimeInstances, listRuntimeInstancesForPool, enqueueAuditRow, enqueueAdmissionRow, flushAuditBuffer, startAuditWriter, stopAuditWriter, startAuditGc, stopAuditGc, getTelemetryIngestAnchor, initApiTelemetry, syncTelemetryEnabled, handlePullRequest, handleIssue, handleComment, handlePullRequestReview, handleCheckRun, handleCheckSuite, handleWorkflowRun, isGitLabEnabled, initGitLab, verifyGitLabWebhook, handleMergeRequest, handleIssue2, handleNote, handlePipeline, isChatSdkEnabled, getChatSdkConfig, errorMessage, resolveAdapterApiUrl, trackBackground, TelegramBotApiError, callTelegramBotApi, isTrustedTeamsServiceUrl, isChatSdkStopping, startChatSdk, getChatInstance, isChatAdapterConfigured, getChatSdkHealth, stopChatSdk, getJiraMetadata, updateJiraMetadata, clearJiraMetadata, registerJiraWebhook, deleteJiraWebhook, isJiraEnabled, initJira, handleJiraWebhook, handleAgentSessionEvent, handleIssueUpdate, handleIssueDelete, handleAgentSessionPrompted, isLinearEnabled, initLinear,
|
|
137035
|
+
export { DEFAULT_NEGOTIATED_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS, isJSONRPCRequest, isJSONRPCResultResponse, isJSONRPCErrorResponse, JSONRPCMessageSchema, isInitializeRequest, McpServer, isGitHubEnabled, initGitHub, verifyWebhookSignature, isAgentMailEnabled, initAgentMail, verifyAgentMailWebhook, resolveIdentity, renderIdentity, createAdditiveBuffer, taskModelPin, resumedTaskModelSelection, listHarnessModelSupport, recordHarnessModelSupport, agentRanModel, getAgentHarnessCliVersion, setAgentHarnessCliVersion, sanitizeModelTierOverrides, parseModelTierOverridesHeader, setAgentModelTierOverrides, previewModelTiers, recordClaimModelResolution, harnessModelErrorFor, poolTaskRunsOnHarness, explicitModelError, explicitModelErrorForAgent, referencedBundlePaths, skillDirs, TaskCreationBlockedError, recordUnmappedIdentity, MAX_TASK_ATTACHMENT_BYTES, recordTaskAttachmentUpload, scopeFromAttachment, backingProviderId, transcribeAudioNotes, buildEffectiveText, bufferedFileFailures, fetchSlackFiles, createSlackTaskWithFiles, notifySlackFileFailures, isRuntimePoolWakeable, isAgentReachable, hasOtherUserMention, broadcastMatches, routeMessage, extractTaskFromMessage, extractSlackMessageText, recoverIncompleteRuns, handleWebhookTrigger, verifyHmacSignature, WebhookError, snapshotAndUpdateWorkflow, RawLlmConfigSchema, RawLlmOutputSchema, executeRawLlm, getExecutorRegistry2, initWorkflows2, dispatchScheduleTarget, calculateNextRun2, startScheduler2, stopScheduler2, runScheduleNow2, ExtensionAssetConflictError, ExtensionOwnershipError, getExtensionFiles, getExtensionById, getExtensionByName, listExtensions, listExtensionVersions, updateExtensionMeta, listExtensionRuns, SDK_ALLOWLIST, mcpToolNameForSdkMethod, mcpOverflowAuthError, hasKvViewArgs, resolveKvView, toolErr, createToolRegistrar, handleMcpBridge, Redacted, SCRIPT_SDK_RESPONSE_LIMIT_BYTES, readScriptSdkJsonResponse, ExtensionConfigError, ExtensionLifecycleError, setExtensionLoopbackBaseUrl, enableExtension, disableExtension, activateVersion, ExtensionAssetsInvalidError, installExtensionWithAssets, uninstallExtension, reloadExtension, loadEnabledExtensions, stopExtensionRuntime, ExtensionAbortedError2, isRegistered2, isExtensionAgentId2, getExtensionBridgeToken2, resolveBridgeCallOrigin2, extensionIdForAgent2, runContext2, registerLoaded2, unregister2, listRegistered2, dispatchPre2, dispatchPost2, stripSiblingBlock, createTaskWithSiblingAwareness, isInboxAllowed, isSenderAllowed, handleMessageReceived, isAzureDevOpsEnabled, initAzureDevOps, verifyAzureDevOpsWebhook, repointTrackerSyncBySwarmId, isAzureDevOpsUrl, canonicalAzureDevOpsRepoUrl, parseAzureDevOpsRepoUrl, createdPullRequestOf, commentedPayloadOf, handlePullRequestCreated, handlePullRequestCommented, handleWorkItemCreated, handleWorkItemUpdated, handleWorkItemCommented, handleWorkItemDeleted, handleWorkItemRestored, initAzureDevOpsOutbound, AGENT_MAX_TASKS_CONFIG_KEY, reconcileAgentMaxTasksPolicy, resetAgentMaxTasksMirror, upsertSwarmConfigWithPolicyMirror, runtimeStaleThresholdMinutes, upsertRuntimeInstance, getRuntimeInstanceById, insertProvisioningRuntime, markRuntimeTerminated, touchRuntimeInstance, countActiveRuntimeInstancesForAgent, listRuntimeInstancesForAgent, setRuntimeCredentialReady, reconcileAgentStatusFromRuntimes, agentsWithLiveRuntime, expireStaleRuntimeInstances, listRuntimeInstancesForPool, enqueueAuditRow, enqueueAdmissionRow, flushAuditBuffer, startAuditWriter, stopAuditWriter, startAuditGc, stopAuditGc, getTelemetryIngestAnchor, initApiTelemetry, syncTelemetryEnabled, handlePullRequest, handleIssue, handleComment, handlePullRequestReview, handleCheckRun, handleCheckSuite, handleWorkflowRun, isGitLabEnabled, initGitLab, verifyGitLabWebhook, handleMergeRequest, handleIssue2, handleNote, handlePipeline, isChatSdkEnabled, getChatSdkConfig, errorMessage, resolveAdapterApiUrl, trackBackground, TelegramBotApiError, callTelegramBotApi, isTrustedTeamsServiceUrl, isChatSdkStopping, startChatSdk, getChatInstance, isChatAdapterConfigured, getChatSdkHealth, stopChatSdk, getJiraMetadata, updateJiraMetadata, clearJiraMetadata, registerJiraWebhook, deleteJiraWebhook, isJiraEnabled, initJira, handleJiraWebhook, handleAgentSessionEvent, handleIssueUpdate, handleIssueDelete, handleAgentSessionPrompted, isLinearEnabled, initLinear, isCookieSafePageId, extractPageSession, extractLegacyPageSession, extractAndVerifyCookie, pageSessionSetCookies, resolveHttpRequestAuth, loadGlobalConfigsIntoEnv, reloadGlobalConfigsAndIntegrations, scheduleIntegrationsReload, handleCore, MCP_MAX_TOOL_INPUT_ELEMENTS, MCP_MAX_REQUEST_BODY_BYTES, userCtx, requestPrincipal, agentFirstPrincipal, rejectGuest, handleApps, cancelApprovalRequest, cancelApprovalRequestAndRun, getUserCommsPrefs, getTaskDetailsInputSchema, getTaskDetailsOutputSchema, getTaskDetailsHandler, cancelTaskInputSchema, cancelTaskOutputSchema, cancelTaskHandler, executeReadOnlyQuery, assertSelectOnlyQuery, handleDbQuery, snapshotMetric, AssetKeyAuthorizationError, authorizeAssetKeyWrite, getPageEditCounter, snapshotPage, assertOAuthAppUrlsSafe, assertOAuthEgressUrlSafe, listOAuthPresets, listOAuthPresetIds, getOAuthPreset, hydrateOAuthAppFromPreset, scopedResourceScopeIdSchema, resolveScopedResourceId, MemoryKeyError, refreshLinks, indexMemoryContent, dedupeMemoryDocumentIds, recordMemoryAccesses, recordRetrievals, ExplicitSelfDuplicateError, applyRating, shouldPersistAutomaticTaskMemory, REBOOT_RETRY_PIN_TAG, getPinCandidateAgent, resolveLeadOnlyRecoveryAssignment, getResumeGeneration, getNextResumeGeneration, inheritedModelSelection, createWorkerTaskFollowUp, createResumeFollowUp, createRerouteDecisionTask, createPoolStarvationDecisionTask, guardTerminalTaskResultWrite, getTasksInputSchema, getTasksOutputSchema, getTasksHandler, reservedNamespaceError, reservedRoomKeyError, updateMcpServerChecked, updateTouchesStdioExecution, canReadMemory, getLinksForMemory, expandCandidatesWithGraph, isApiDraining, drainApi, markKapsoMessageRead, sendKapsoReaction, getKapsoConfig, getKapsoNumberMapping, markKapsoMessageSeen, changesAllowMerge, updateSwarmRepoChecked, getCombConfig, resolveRoomNamespace, roomRequestInfo, authorizeRoomNamespace, sessionAccessTopic, sessionPresenceRoot, RoomOperationSchema, removeAwarenessStates, roomTopic, decodeRoomSnapshot, roomView, getRoom, changeRoom, applyRoomUpdate, resetRoom, sweepRooms, closeRooms, removeNamespaceRooms, MEMORY_KEYS_DEFAULT_PREFIX, MEMORY_KEYS_MAX_LIMIT, estimateTokens, posteriorMean, listMemoryKeys, checkChunkIntegrity, getMemoryChunks, getPosteriorsByIds, createEvent, createEventsBatch, getEventCountsFiltered, getEventsFiltered, mergeScheduleTiming, validateRecurringTiming, checkOutputSchemaShape, sendTaskOutputSchema, sendTaskHandler, steerTaskUserInputSchema, steerTaskOutputSchema, steerTaskHandler, canClaim, emitBudgetRefusalSideEffects, workflowModelErrors, patchWorkflowDefinition, resolveScriptsOnlyMode, ALL_CAPABILITIES, hasCapability, getEnabledCapabilities, createServer };
|