@desplega.ai/agent-swarm 2.4.4 → 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-thq04adh.js → acp-adapter-2wdkktv6.js} +1 -1
- package/dist/{actions-j6ywh6x5.js → actions-c40ebcm4.js} +18 -18
- package/dist/{amp-adapter-k8b5xmj8.js → amp-adapter-wb67m95z.js} +2 -2
- package/dist/{app-rb7vc02s.js → app-353vre8g.js} +3 -3
- package/dist/{assistant-ftta1zjf.js → assistant-sj1njh23.js} +21 -21
- package/dist/{boot-reembed-srp6v6af.js → boot-reembed-b9c3az3c.js} +1 -1
- package/dist/{boot-reembed-xns7h5h9.js → boot-reembed-qdkvxeem.js} +1 -1
- package/dist/{boot-scrub-sweep-3qqrh2mz.js → boot-scrub-sweep-m3wh8eks.js} +2 -2
- package/dist/{boot-seeds-9ks8hce7.js → boot-seeds-j2273s54.js} +4 -4
- package/dist/{claude-adapter-k5ksyres.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-n5a5eqks.js → claude-managed-setup-smrqk5j5.js} +3 -3
- package/dist/{claude-sdk-session-2j3j4kwn.js → claude-sdk-session-38xnz21e.js} +8284 -8267
- package/dist/{cli-cynvc9fj.js → cli-018r4jq6.js} +5 -5
- package/dist/{cli-9fhkkpj5.js → cli-1f3qzw6y.js} +1 -1
- package/dist/{cli-dqb4n629.js → cli-1sp861s4.js} +7 -7
- package/dist/{cli-gqvh8d8a.js → cli-1syn2xy1.js} +10 -10
- package/dist/{cli-qkhc5aqy.js → cli-37j04k05.js} +11 -11
- package/dist/{cli-1d70crsy.js → cli-3a45zcgm.js} +1 -1
- package/dist/{cli-t7cyef5g.js → cli-43x64hv3.js} +4 -4
- package/dist/{cli-hj3debgw.js → cli-4zfqgjc5.js} +2 -2
- package/dist/{cli-55qmbp6z.js → cli-7c9qs530.js} +1 -1
- package/dist/{cli-9qtjfd60.js → cli-848hxdwj.js} +1 -1
- package/dist/{cli-pccfmtb5.js → cli-94gwyg7m.js} +7 -7
- package/dist/{cli-51y09c6p.js → cli-9hstj09h.js} +5 -5
- package/dist/{cli-zrwpctp4.js → cli-9yqgm9nd.js} +22 -22
- package/dist/{cli-esxerzg7.js → cli-a92r1127.js} +1 -1
- package/dist/{cli-b8k7epj1.js → cli-be2161h1.js} +7 -7
- package/dist/{cli-xc27fwzg.js → cli-bnes4z6b.js} +2 -2
- package/dist/{cli-zrk6jxv8.js → cli-cxxe61f6.js} +1 -1
- package/dist/{cli-amyhm3gj.js → cli-dk44dxec.js} +1 -1
- package/dist/{cli-nc35pxb7.js → cli-eww120g8.js} +1 -0
- package/dist/{cli-a0kcty51.js → cli-f01h25yt.js} +1 -1
- package/dist/{cli-82d3nkc3.js → cli-f0g3pgvf.js} +1 -1
- package/dist/{cli-1ephgwnq.js → cli-ftc1g5tj.js} +2 -2
- package/dist/{cli-2v045xyf.js → cli-fv5hepyy.js} +3 -3
- package/dist/{cli-bnz0r3kc.js → cli-g35m2xwm.js} +4 -4
- package/dist/{cli-qje9k2nh.js → cli-g9ypd5en.js} +12 -2
- package/dist/{cli-w6nadkh4.js → cli-j99azg3g.js} +3 -3
- package/dist/{cli-er83cjbn.js → cli-k8g16gz3.js} +416 -116
- package/dist/{cli-4dg55wsk.js → cli-kpw04va0.js} +1 -1
- package/dist/{cli-3cgngyd8.js → cli-ms85309d.js} +33 -15
- package/dist/{cli-v3yr2gbg.js → cli-n72rg53p.js} +1471 -635
- package/dist/{cli-37yb7307.js → cli-p14m2cnp.js} +1 -1
- package/dist/{cli-2zqpkvtt.js → cli-qfxc84gh.js} +1 -1
- package/dist/{cli-44159k28.js → cli-qwhy2qma.js} +1 -1
- package/dist/{cli-2y91wnbh.js → cli-st8aw1m6.js} +221 -9
- package/dist/{cli-vq97g1jq.js → cli-tw4p90jb.js} +92 -192
- package/dist/{cli-te6b5wvg.js → cli-v0yrfmdh.js} +1 -1
- package/dist/{cli-xj0re5tm.js → cli-v8fjakwf.js} +1 -1
- package/dist/{cli-p20r8w42.js → cli-wt0jf9hm.js} +215 -80
- package/dist/{cli-q6r7t299.js → cli-xpa64rek.js} +33 -11
- package/dist/{cli-vdm20wej.js → cli-z7d29rw9.js} +2 -2
- package/dist/cli.js +19 -19
- package/dist/{codex-adapter-968xwfy7.js → codex-adapter-tn6k5mkg.js} +1 -1
- package/dist/{codex-session-runner-ht4z99fa.js → codex-session-runner-7vjt7jbw.js} +1 -1
- package/dist/{commands-pcymaeg9.js → commands-t7rz9146.js} +2 -2
- package/dist/{controller-fpjyk46r.js → controller-m2jasma5.js} +2 -2
- package/dist/{controllers-connect-mwzx1fh6.js → controllers-connect-9ftpex99.js} +19 -19
- package/dist/{cursor-adapter-cp4s2e2f.js → cursor-adapter-mjv79e4z.js} +1 -1
- package/dist/{db-xsjg9jqq.js → db-6sfrn9g3.js} +1 -1
- package/dist/{db-sgd12bt9.js → db-rn673r06.js} +3 -3
- package/dist/{dispatcher-x0jfw2c9.js → dispatcher-c155xz0p.js} +17 -17
- package/dist/{dsh-adapter-jrq7ma7h.js → dsh-adapter-3mmszc1x.js} +1 -1
- package/dist/{external-channel-8njj4h3b.js → external-channel-35k6tkv8.js} +2 -2
- package/dist/{grok-adapter-kkr97v2f.js → grok-adapter-tfrq7tg1.js} +2 -2
- package/dist/handlers-7gw64dxw.js +39 -0
- package/dist/{heartbeat-wd03zhn0.js → heartbeat-dyg4npkp.js} +20 -20
- package/dist/{hook-f0vghj42.js → hook-drspbwpe.js} +1 -1
- package/dist/{hook-xzj2ts2p.js → hook-x26b31bg.js} +1 -1
- package/dist/{http-4hwxv62p.js → http-pk972xyw.js} +355 -216
- package/dist/{index-ww2vznkp.js → index-arytgj5q.js} +1 -1
- package/dist/{index-hg0x2cdv.js → index-bgdyvcnv.js} +17 -17
- package/dist/{index-c4ykd0f1.js → index-dr94zbnh.js} +13348 -11611
- package/dist/{index-gdh8jrdm.js → index-gabbcdn2.js} +17 -17
- package/dist/{index-97q4xn03.js → index-jwxkkex2.js} +129 -75
- package/dist/index-tfb26zhy.js +41 -0
- package/dist/{keepalive-hrh7xnr9.js → keepalive-7yrng7px.js} +3 -3
- package/dist/{lead-ee8vazz2.js → lead-7e02z839.js} +29 -29
- package/dist/{maintenance-e8wnwnqx.js → maintenance-e6cemdqt.js} +1 -1
- package/dist/{node-3v3f08f7.js → node-de6akczr.js} +10 -9
- package/dist/{oauth-refresh-sweep-zm0yj4sj.js → oauth-refresh-sweep-yw3xdbcj.js} +2 -2
- package/dist/{onboard-dtwcq603.js → onboard-0a9y5yrc.js} +2 -2
- package/dist/{otel-impl-w3fbhpn0.js → otel-impl-trjpkfb7.js} +1 -1
- package/dist/{pricing-refresh-j38dehfs.js → pricing-refresh-d2b5my0y.js} +3 -3
- package/dist/{rbac-roles-ejxx9b35.js → rbac-roles-hey3yv9d.js} +2 -2
- package/dist/{rbac-roles-ae8yttq4.js → rbac-roles-nxh5ahwk.js} +1 -1
- package/dist/{registry-rxw10xzg.js → registry-ajhexe44.js} +1 -1
- package/dist/{render-v2-n16n0phe.js → render-v2-rr3p2atg.js} +3 -3
- package/dist/{resume-z0fgjc38.js → resume-2efkf1s1.js} +5 -5
- package/dist/{session-access-cv3mq6mc.js → session-access-s2mttxpw.js} +4 -4
- package/dist/{setup-mafhj3yt.js → setup-vypma5yt.js} +1 -1
- package/dist/{work-objects-8b86mgjp.js → work-objects-rvhckdkp.js} +20 -20
- package/dist/{worker-16s75hm5.js → worker-5snytpbd.js} +29 -29
- package/openapi.json +9 -2
- package/package.json +7 -7
- package/src/apps/catalog.generated.json +206 -4
- package/src/apps/page-validator.ts +13 -1
- 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/scripts/typecheck.ts +2 -0
- package/src/be/seed-scripts/catalog/heartbeat-jev-gate.ts +106 -54
- package/src/be/seed-scripts/index.ts +2 -2
- package/src/be/swarm-config-guard.ts +24 -1
- package/src/be/task-attachment-store.ts +30 -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/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/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/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/cursor-adapter.ts +1 -1
- 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/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/config-api-only-keys.test.ts +9 -0
- package/src/tests/cors-allowlist.test.ts +1 -1
- package/src/tests/extensions-example-slack-reply-gate.test.ts +262 -91
- 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 +242 -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/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/realtime-transport.test.ts +13 -7
- package/src/tests/script-runs-http.test.ts +84 -0
- package/src/tests/scripts-http.test.ts +10 -1
- 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/workflow-system-one-decision-providers.test.ts +98 -1
- package/src/tests/workflow-system-one-decision.test.ts +2 -1
- 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 +6 -0
- package/src/utils/config-env-export.ts +3 -1
- package/src/utils/page-session.ts +133 -20
- package/src/utils/transcription.ts +246 -0
- package/src/workflows/executors/system-one-decision.ts +28 -7
- package/src/workflows/executors/system-one-providers.ts +39 -4
- 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/skills/apps/SKILL.md +28 -6
- package/templates/skills/apps/content.md +28 -6
- 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 +5 -5
- 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/handlers-0pvee9nw.js +0 -39
- package/dist/index-thm0y6a8.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,
|
|
@@ -533,7 +535,7 @@ import {
|
|
|
533
535
|
definitionNodeIds,
|
|
534
536
|
validateDefinition,
|
|
535
537
|
applyDefinitionPatch
|
|
536
|
-
} from "./cli-
|
|
538
|
+
} from "./cli-xpa64rek.js";
|
|
537
539
|
import {
|
|
538
540
|
workflowEventBus2,
|
|
539
541
|
init_event_bus
|
|
@@ -564,19 +566,21 @@ import {
|
|
|
564
566
|
isPublicRoute,
|
|
565
567
|
findRoute,
|
|
566
568
|
route
|
|
567
|
-
} from "./cli-
|
|
569
|
+
} from "./cli-018r4jq6.js";
|
|
568
570
|
import {
|
|
569
571
|
isMultiRuntimeEnabled
|
|
570
572
|
} from "./cli-e8xyjvfc.js";
|
|
571
573
|
import {
|
|
574
|
+
FilesError,
|
|
572
575
|
providerPath,
|
|
576
|
+
normalizeStoredKey,
|
|
573
577
|
AgentFsProvider,
|
|
574
578
|
getFileStorageProvider2
|
|
575
|
-
} from "./cli-
|
|
579
|
+
} from "./cli-g9ypd5en.js";
|
|
576
580
|
import {
|
|
577
581
|
getRuntimePool2,
|
|
578
582
|
init_db
|
|
579
|
-
} from "./cli-
|
|
583
|
+
} from "./cli-j99azg3g.js";
|
|
580
584
|
import {
|
|
581
585
|
getMemoryRaterNames,
|
|
582
586
|
REFERENCES_SOURCE_MAX_LENGTH,
|
|
@@ -617,7 +621,7 @@ import {
|
|
|
617
621
|
resolveSessionToken,
|
|
618
622
|
fingerprintApiKey,
|
|
619
623
|
init_users
|
|
620
|
-
} from "./cli-
|
|
624
|
+
} from "./cli-1f3qzw6y.js";
|
|
621
625
|
import {
|
|
622
626
|
isRbacEnabled,
|
|
623
627
|
decideAdmission,
|
|
@@ -686,7 +690,7 @@ import {
|
|
|
686
690
|
KvNamespaceSchema,
|
|
687
691
|
KvKeySchema,
|
|
688
692
|
init_types
|
|
689
|
-
} from "./cli-
|
|
693
|
+
} from "./cli-eww120g8.js";
|
|
690
694
|
import {
|
|
691
695
|
generateDefaultClaudeMd2,
|
|
692
696
|
generateDefaultSoulMd2,
|
|
@@ -757,7 +761,7 @@ import {
|
|
|
757
761
|
import {
|
|
758
762
|
init_package,
|
|
759
763
|
package_default
|
|
760
|
-
} from "./cli-
|
|
764
|
+
} from "./cli-94gwyg7m.js";
|
|
761
765
|
import {
|
|
762
766
|
realtimeBus,
|
|
763
767
|
init_bus
|
|
@@ -786,6 +790,7 @@ import {
|
|
|
786
790
|
import {
|
|
787
791
|
scrubSecrets,
|
|
788
792
|
scrubObject,
|
|
793
|
+
createValueScrubber,
|
|
789
794
|
refreshSecretScrubberCache,
|
|
790
795
|
registerVolatileSecret,
|
|
791
796
|
registerSensitiveKeyName,
|
|
@@ -16809,6 +16814,9 @@ class Protocol {
|
|
|
16809
16814
|
this.setRequestHandler(GetTaskPayloadRequestSchema, async (request, extra) => {
|
|
16810
16815
|
const handleTaskResult = async () => {
|
|
16811
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
|
+
}
|
|
16812
16820
|
if (this._taskMessageQueue) {
|
|
16813
16821
|
let queuedMessage;
|
|
16814
16822
|
while (queuedMessage = await this._taskMessageQueue.dequeue(taskId, extra.sessionId)) {
|
|
@@ -16839,12 +16847,12 @@ class Protocol {
|
|
|
16839
16847
|
throw new McpError(ErrorCode.InvalidParams, `Task not found: ${taskId}`);
|
|
16840
16848
|
}
|
|
16841
16849
|
if (!isTerminal(task.status)) {
|
|
16842
|
-
await this._waitForTaskUpdate(taskId, extra.signal);
|
|
16850
|
+
await this._waitForTaskUpdate(taskId, extra.signal, extra.sessionId);
|
|
16843
16851
|
return await handleTaskResult();
|
|
16844
16852
|
}
|
|
16845
16853
|
if (isTerminal(task.status)) {
|
|
16846
16854
|
const result = await this._taskStore.getTaskResult(taskId, extra.sessionId);
|
|
16847
|
-
this._clearTaskQueue(taskId);
|
|
16855
|
+
this._clearTaskQueue(taskId, extra.sessionId);
|
|
16848
16856
|
return {
|
|
16849
16857
|
...result,
|
|
16850
16858
|
_meta: {
|
|
@@ -16881,7 +16889,7 @@ class Protocol {
|
|
|
16881
16889
|
throw new McpError(ErrorCode.InvalidParams, `Cannot cancel task in terminal status: ${task.status}`);
|
|
16882
16890
|
}
|
|
16883
16891
|
await this._taskStore.updateTaskStatus(request.params.taskId, "cancelled", "Client cancelled task execution.", extra.sessionId);
|
|
16884
|
-
this._clearTaskQueue(request.params.taskId);
|
|
16892
|
+
this._clearTaskQueue(request.params.taskId, extra.sessionId);
|
|
16885
16893
|
const cancelledTask = await this._taskStore.getTask(request.params.taskId, extra.sessionId);
|
|
16886
16894
|
if (!cancelledTask) {
|
|
16887
16895
|
throw new McpError(ErrorCode.InvalidParams, `Task not found after cancellation: ${request.params.taskId}`);
|
|
@@ -17004,6 +17012,19 @@ class Protocol {
|
|
|
17004
17012
|
const handler = this._requestHandlers.get(request.method) ?? this.fallbackRequestHandler;
|
|
17005
17013
|
const capturedTransport = this._transport;
|
|
17006
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
|
+
}
|
|
17007
17028
|
if (handler === undefined) {
|
|
17008
17029
|
const errorResponse = {
|
|
17009
17030
|
jsonrpc: "2.0",
|
|
@@ -17013,7 +17034,10 @@ class Protocol {
|
|
|
17013
17034
|
message: "Method not found"
|
|
17014
17035
|
}
|
|
17015
17036
|
};
|
|
17016
|
-
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) {
|
|
17017
17041
|
this._enqueueTaskMessage(relatedTaskId, {
|
|
17018
17042
|
type: "error",
|
|
17019
17043
|
message: errorResponse,
|
|
@@ -17064,7 +17088,10 @@ class Protocol {
|
|
|
17064
17088
|
closeSSEStream: extra?.closeSSEStream,
|
|
17065
17089
|
closeStandaloneSSEStream: extra?.closeStandaloneSSEStream
|
|
17066
17090
|
};
|
|
17067
|
-
Promise.resolve().then(() => {
|
|
17091
|
+
(relatedTaskLookup ?? Promise.resolve()).then(() => {
|
|
17092
|
+
if (relatedTaskLookup && abortController.signal.aborted) {
|
|
17093
|
+
throw new McpError(ErrorCode.ConnectionClosed, "Request was cancelled");
|
|
17094
|
+
}
|
|
17068
17095
|
if (taskCreationParams) {
|
|
17069
17096
|
this.assertTaskHandlerCapability(request.method);
|
|
17070
17097
|
}
|
|
@@ -17099,7 +17126,7 @@ class Protocol {
|
|
|
17099
17126
|
...error["data"] !== undefined && { data: error["data"] }
|
|
17100
17127
|
}
|
|
17101
17128
|
};
|
|
17102
|
-
if (relatedTaskId && this._taskMessageQueue) {
|
|
17129
|
+
if (relatedTaskId && this._taskMessageQueue && relatedTaskFound) {
|
|
17103
17130
|
await this._enqueueTaskMessage(relatedTaskId, {
|
|
17104
17131
|
type: "error",
|
|
17105
17132
|
message: errorResponse,
|
|
@@ -17487,7 +17514,7 @@ class Protocol {
|
|
|
17487
17514
|
throw new Error("Cannot enqueue task message: taskStore and taskMessageQueue are not configured");
|
|
17488
17515
|
}
|
|
17489
17516
|
const maxQueueSize = this._options?.maxTaskQueueSize;
|
|
17490
|
-
await this._taskMessageQueue.enqueue(taskId, message, sessionId, maxQueueSize);
|
|
17517
|
+
await this._taskMessageQueue.enqueue(taskId, message, sessionId ?? this._transport?.sessionId, maxQueueSize);
|
|
17491
17518
|
}
|
|
17492
17519
|
async _clearTaskQueue(taskId, sessionId) {
|
|
17493
17520
|
if (this._taskMessageQueue) {
|
|
@@ -17506,10 +17533,10 @@ class Protocol {
|
|
|
17506
17533
|
}
|
|
17507
17534
|
}
|
|
17508
17535
|
}
|
|
17509
|
-
async _waitForTaskUpdate(taskId, signal) {
|
|
17536
|
+
async _waitForTaskUpdate(taskId, signal, sessionId) {
|
|
17510
17537
|
let interval = this._options?.defaultTaskPollInterval ?? 1000;
|
|
17511
17538
|
try {
|
|
17512
|
-
const task = await this._taskStore?.getTask(taskId);
|
|
17539
|
+
const task = await this._taskStore?.getTask(taskId, sessionId);
|
|
17513
17540
|
if (task?.pollInterval) {
|
|
17514
17541
|
interval = task.pollInterval;
|
|
17515
17542
|
}
|
|
@@ -18178,6 +18205,42 @@ class ExperimentalMcpServerTasks {
|
|
|
18178
18205
|
|
|
18179
18206
|
// node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js
|
|
18180
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
|
+
}
|
|
18181
18244
|
|
|
18182
18245
|
class McpServer {
|
|
18183
18246
|
constructor(serverInfo, options) {
|
|
@@ -18190,6 +18253,7 @@ class McpServer {
|
|
|
18190
18253
|
this._resourceHandlersInitialized = false;
|
|
18191
18254
|
this._promptHandlersInitialized = false;
|
|
18192
18255
|
this.server = new Server(serverInfo, options);
|
|
18256
|
+
this._maxToolInputElements = resolveMaxToolInputElements(options?.maxToolInputElements);
|
|
18193
18257
|
}
|
|
18194
18258
|
get experimental() {
|
|
18195
18259
|
if (!this._experimental) {
|
|
@@ -18296,12 +18360,15 @@ class McpServer {
|
|
|
18296
18360
|
};
|
|
18297
18361
|
}
|
|
18298
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
|
+
}
|
|
18299
18366
|
if (!tool.inputSchema) {
|
|
18300
18367
|
return;
|
|
18301
18368
|
}
|
|
18302
18369
|
const inputObj = normalizeObjectSchema(tool.inputSchema);
|
|
18303
18370
|
const schemaToParse = inputObj ?? tool.inputSchema;
|
|
18304
|
-
const parseResult = await safeParseAsync2(schemaToParse, args);
|
|
18371
|
+
const parseResult = await safeParseAsync2(schemaToParse, args ?? {});
|
|
18305
18372
|
if (!parseResult.success) {
|
|
18306
18373
|
const error = "error" in parseResult ? parseResult.error : "Unknown error";
|
|
18307
18374
|
const errorMessage = getParseErrorMessage(error);
|
|
@@ -18526,7 +18593,7 @@ class McpServer {
|
|
|
18526
18593
|
}
|
|
18527
18594
|
if (prompt.argsSchema) {
|
|
18528
18595
|
const argsObj = normalizeObjectSchema(prompt.argsSchema);
|
|
18529
|
-
const parseResult = await safeParseAsync2(argsObj, request.params.arguments);
|
|
18596
|
+
const parseResult = await safeParseAsync2(argsObj, request.params.arguments ?? {});
|
|
18530
18597
|
if (!parseResult.success) {
|
|
18531
18598
|
const error = "error" in parseResult ? parseResult.error : "Unknown error";
|
|
18532
18599
|
const errorMessage = getParseErrorMessage(error);
|
|
@@ -21149,7 +21216,7 @@ class NotifyExecutor extends BaseExecutor {
|
|
|
21149
21216
|
}
|
|
21150
21217
|
}
|
|
21151
21218
|
case "slack": {
|
|
21152
|
-
const { getSlackApp } = await import("./app-
|
|
21219
|
+
const { getSlackApp } = await import("./app-353vre8g.js");
|
|
21153
21220
|
const app = getSlackApp();
|
|
21154
21221
|
if (!app) {
|
|
21155
21222
|
return {
|
|
@@ -24512,7 +24579,7 @@ function setPreloadedTools(server, names) {
|
|
|
24512
24579
|
async function applyPreToolCall(name, args, requestInfo, inputSchema) {
|
|
24513
24580
|
if (requestInfo.callOrigin !== "mcp")
|
|
24514
24581
|
return { args };
|
|
24515
|
-
const dispatcher = await import("./dispatcher-
|
|
24582
|
+
const dispatcher = await import("./dispatcher-c155xz0p.js");
|
|
24516
24583
|
const result = await dispatcher.dispatchPre("pre.tool.call", { tool: name, args, requestInfo }, inputSchema ? {
|
|
24517
24584
|
validateModify: async (data) => {
|
|
24518
24585
|
const schema = normalizeObjectSchema(inputSchema) ?? inputSchema;
|
|
@@ -31268,7 +31335,11 @@ async function loadAdapter(name, config, logger) {
|
|
|
31268
31335
|
switch (name) {
|
|
31269
31336
|
case "telegram": {
|
|
31270
31337
|
const { createTelegramAdapter } = await import("./index-g216q6jr.js");
|
|
31271
|
-
return createTelegramAdapter({
|
|
31338
|
+
return createTelegramAdapter({
|
|
31339
|
+
...base,
|
|
31340
|
+
allowUnverifiedWebhooks: false,
|
|
31341
|
+
mentionOnReply: true
|
|
31342
|
+
});
|
|
31272
31343
|
}
|
|
31273
31344
|
case "slack": {
|
|
31274
31345
|
const { createSlackAdapter } = await import("./index-zgvqzjsw.js");
|
|
@@ -31870,6 +31941,43 @@ function resetDiscordGatewayHealth() {
|
|
|
31870
31941
|
// src/integrations/chat-sdk/inbound.ts
|
|
31871
31942
|
init_zod();
|
|
31872
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
|
|
31873
31981
|
init_resolver();
|
|
31874
31982
|
init_context_key();
|
|
31875
31983
|
init_secret_scrubber();
|
|
@@ -31918,10 +32026,191 @@ async function recordTaskAttachmentUpload(input) {
|
|
|
31918
32026
|
throw error;
|
|
31919
32027
|
}
|
|
31920
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
|
+
}
|
|
31921
32205
|
|
|
31922
32206
|
// src/integrations/chat-sdk/attachments.ts
|
|
31923
32207
|
var DRAFT_LEASE_REFRESH_MS = 60000;
|
|
31924
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
|
+
}
|
|
31925
32214
|
function formatFileSize(bytes) {
|
|
31926
32215
|
if (bytes < 1024)
|
|
31927
32216
|
return `${bytes} B`;
|
|
@@ -31942,16 +32231,42 @@ function toChatFiles(adapter, messageId, attachments) {
|
|
|
31942
32231
|
attachment
|
|
31943
32232
|
}));
|
|
31944
32233
|
}
|
|
31945
|
-
function buildChatAttachmentText(files, failed = []) {
|
|
32234
|
+
function buildChatAttachmentText(files, failed = [], notes = new Map) {
|
|
31946
32235
|
const reasons = new Map(failed.map((f) => [f.file.id, f.reason]));
|
|
31947
32236
|
return files.map((f) => {
|
|
31948
32237
|
const size = typeof f.size === "number" ? formatFileSize(f.size) : "unknown size";
|
|
31949
32238
|
const line = `[File: ${f.name} (${f.mimeType ?? "unknown type"}, ${size}) id=${f.id}]`;
|
|
31950
32239
|
const reason = reasons.get(f.id);
|
|
31951
|
-
|
|
32240
|
+
const note = notes.get(f.id);
|
|
32241
|
+
return [reason ? `${line} (not attached: ${reason})` : line, note].filter(Boolean).join(`
|
|
32242
|
+
`);
|
|
31952
32243
|
}).join(`
|
|
31953
32244
|
`);
|
|
31954
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
|
+
}
|
|
31955
32270
|
async function readAttachment(attachment) {
|
|
31956
32271
|
if (attachment.data instanceof Blob)
|
|
31957
32272
|
return new Uint8Array(await attachment.data.arrayBuffer());
|
|
@@ -31975,17 +32290,25 @@ async function fetchChatFiles(files) {
|
|
|
31975
32290
|
};
|
|
31976
32291
|
if (files.length === 0)
|
|
31977
32292
|
return result;
|
|
31978
|
-
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
|
+
};
|
|
31979
32302
|
dir = await mkdtemp(join(tmpdir2(), "chat-files-"));
|
|
31980
32303
|
for (const [index, file] of files.entries()) {
|
|
31981
|
-
if (typeof file.size === "number" && file.size >
|
|
31982
|
-
result.failed.push(
|
|
32304
|
+
if (typeof file.size === "number" && file.size > chatInboundFileLimit(file.adapter)) {
|
|
32305
|
+
result.failed.push(tooLarge(file, file.size));
|
|
31983
32306
|
continue;
|
|
31984
32307
|
}
|
|
31985
32308
|
try {
|
|
31986
32309
|
const bytes = await readAttachment(file.attachment);
|
|
31987
|
-
if (bytes.byteLength >
|
|
31988
|
-
result.failed.push(
|
|
32310
|
+
if (bytes.byteLength > chatInboundFileLimit(file.adapter)) {
|
|
32311
|
+
result.failed.push(tooLarge(file, bytes.byteLength));
|
|
31989
32312
|
continue;
|
|
31990
32313
|
}
|
|
31991
32314
|
const path = join(dir, String(index));
|
|
@@ -32060,6 +32383,63 @@ async function attachChatFilesToTask(taskId, fetched) {
|
|
|
32060
32383
|
return unattached;
|
|
32061
32384
|
}
|
|
32062
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
|
+
|
|
32063
32443
|
// src/integrations/chat-sdk/outbound.ts
|
|
32064
32444
|
init_secret_scrubber();
|
|
32065
32445
|
init_event_bus();
|
|
@@ -32075,6 +32455,17 @@ var FALLBACK_LIMIT = 2000;
|
|
|
32075
32455
|
function chatMessageLimit(adapter) {
|
|
32076
32456
|
return CHAT_MESSAGE_LIMITS[adapter] ?? FALLBACK_LIMIT;
|
|
32077
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;
|
|
32078
32469
|
function splitChatMessage(text, limit) {
|
|
32079
32470
|
if (limit <= 0)
|
|
32080
32471
|
throw new Error("splitChatMessage: limit must be positive");
|
|
@@ -32115,6 +32506,15 @@ function adapterOfChatId(id) {
|
|
|
32115
32506
|
const index = id.indexOf(":");
|
|
32116
32507
|
return index === -1 ? id : id.slice(0, index);
|
|
32117
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
|
+
}
|
|
32118
32518
|
async function postChunks(adapter, target, text) {
|
|
32119
32519
|
const messageIds = [];
|
|
32120
32520
|
let threadId;
|
|
@@ -32125,6 +32525,125 @@ async function postChunks(adapter, target, text) {
|
|
|
32125
32525
|
}
|
|
32126
32526
|
return { messageIds, threadId };
|
|
32127
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
|
+
}
|
|
32128
32647
|
async function postChatMessage(args) {
|
|
32129
32648
|
assertTrustedChatTarget(args.threadId ?? args.channelId ?? "");
|
|
32130
32649
|
const chat = getChatInstance(args.adapter);
|
|
@@ -32132,27 +32651,42 @@ async function postChatMessage(args) {
|
|
|
32132
32651
|
throw new ChatAdapterUnavailableError(args.adapter);
|
|
32133
32652
|
const text = scrubSecrets(args.text);
|
|
32134
32653
|
let result;
|
|
32654
|
+
let target;
|
|
32135
32655
|
if (args.threadId) {
|
|
32136
32656
|
const thread = chat.thread(args.threadId);
|
|
32657
|
+
target = thread;
|
|
32137
32658
|
const sent = await postChunks(args.adapter, thread, text);
|
|
32138
32659
|
result = {
|
|
32139
32660
|
adapter: args.adapter,
|
|
32140
32661
|
threadId: thread.id,
|
|
32141
32662
|
channelId: thread.channelId,
|
|
32142
|
-
messageIds: sent.messageIds
|
|
32663
|
+
messageIds: sent.messageIds,
|
|
32664
|
+
unsentFiles: []
|
|
32143
32665
|
};
|
|
32144
32666
|
} else if (args.channelId) {
|
|
32145
32667
|
const channel = chat.channel(args.channelId);
|
|
32668
|
+
target = channel;
|
|
32146
32669
|
const sent = await postChunks(args.adapter, channel, text);
|
|
32147
32670
|
result = {
|
|
32148
32671
|
adapter: args.adapter,
|
|
32149
32672
|
threadId: sent.threadId ?? channel.id,
|
|
32150
32673
|
channelId: channel.id,
|
|
32151
|
-
messageIds: sent.messageIds
|
|
32674
|
+
messageIds: sent.messageIds,
|
|
32675
|
+
unsentFiles: []
|
|
32152
32676
|
};
|
|
32153
32677
|
} else {
|
|
32154
32678
|
throw new Error("postChatMessage needs a threadId or a channelId");
|
|
32155
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
|
+
}
|
|
32156
32690
|
emitChatMessageSent({
|
|
32157
32691
|
adapter: result.adapter,
|
|
32158
32692
|
channelId: result.channelId,
|
|
@@ -32218,9 +32752,19 @@ async function putChatChannelMapping(adapter, channelId, mapping) {
|
|
|
32218
32752
|
async function deleteChatChannelMapping(adapter, channelId) {
|
|
32219
32753
|
return deleteKv2(CHAT_CHANNELS_NAMESPACE, chatChannelKey(adapter, channelId));
|
|
32220
32754
|
}
|
|
32755
|
+
function hasRoutingToken(text) {
|
|
32756
|
+
return /swarm#(?:[a-f0-9-]{36}|all)/i.test(text);
|
|
32757
|
+
}
|
|
32221
32758
|
function stripRoutingTokens(text) {
|
|
32222
32759
|
return text.replace(/swarm#[a-f0-9-]{36}/gi, "").replace(/swarm#all/gi, "").trim();
|
|
32223
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
|
+
}
|
|
32224
32768
|
async function leadMatch(reachable, matchedText) {
|
|
32225
32769
|
const lead = reachable.find((agent) => agent.isLead) ?? await getLeadAgent2();
|
|
32226
32770
|
return { agent: lead, reason: "skill", matchedText };
|
|
@@ -32262,7 +32806,7 @@ async function routeChatMessage(text, ctx) {
|
|
|
32262
32806
|
}
|
|
32263
32807
|
console.warn(scrubSecrets(`[chat-sdk] Channel mapping for ${ctx.channelId} names unknown agent ${mapping.agentId}; using the default route`));
|
|
32264
32808
|
}
|
|
32265
|
-
const owner = await getAgentWorkingOnContextKey2(chatSdkContextKey(ctx.threadId), "chat");
|
|
32809
|
+
const owner = await getAgentWorkingOnContextKey2(chatSdkContextKey(ctx.threadId), "chat", ctx.adapter === "telegram" && !ctx.isDirectMessage ? chatOwnerWindowStart() : undefined);
|
|
32266
32810
|
if (owner && await isAgentReachable(owner)) {
|
|
32267
32811
|
return {
|
|
32268
32812
|
kind: "agents",
|
|
@@ -32292,6 +32836,9 @@ async function requestChatThreadSteering(args) {
|
|
|
32292
32836
|
const task = await getLatestLeadTaskByContextKey2(args.contextKey, "chat");
|
|
32293
32837
|
if (!task || task.status !== "in_progress")
|
|
32294
32838
|
return null;
|
|
32839
|
+
const senderUserId = await args.resolveSender();
|
|
32840
|
+
if (senderUserId !== task.requestedByUserId)
|
|
32841
|
+
return null;
|
|
32295
32842
|
try {
|
|
32296
32843
|
const result = await requestSteering({
|
|
32297
32844
|
taskId: task.id,
|
|
@@ -32299,7 +32846,8 @@ async function requestChatThreadSteering(args) {
|
|
|
32299
32846
|
mode: "queue",
|
|
32300
32847
|
onUnsupported: "degrade",
|
|
32301
32848
|
source: "chat",
|
|
32302
|
-
createdByKind: "user"
|
|
32849
|
+
createdByKind: "user",
|
|
32850
|
+
createdByUserId: senderUserId
|
|
32303
32851
|
});
|
|
32304
32852
|
return { task, result };
|
|
32305
32853
|
} catch (error) {
|
|
@@ -32393,6 +32941,18 @@ registerTemplate({
|
|
|
32393
32941
|
],
|
|
32394
32942
|
category: "system"
|
|
32395
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
|
+
});
|
|
32396
32956
|
|
|
32397
32957
|
// src/integrations/chat-sdk/inbound.ts
|
|
32398
32958
|
var ChatRouteModifySchema = object2({
|
|
@@ -32437,10 +32997,24 @@ async function handleChatInbound(thread, message, kind) {
|
|
|
32437
32997
|
if (immediate)
|
|
32438
32998
|
text = text.replace(/^!now\s*/i, "").trim();
|
|
32439
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
|
+
}
|
|
32440
33013
|
if (!immediate && attachments.length === 0 && text && !isChatThreadBuffered(thread.id)) {
|
|
32441
33014
|
const steering = await requestChatThreadSteering({
|
|
32442
33015
|
contextKey: chatSdkContextKey(thread.id),
|
|
32443
|
-
message: text
|
|
33016
|
+
message: text,
|
|
33017
|
+
resolveSender: () => resolveChatSender(adapter, message.author.userId)
|
|
32444
33018
|
});
|
|
32445
33019
|
if (steering) {
|
|
32446
33020
|
console.log(`[chat-sdk] ${adapter} message steered task ${steering.task.id} (${steering.result.outcome})`);
|
|
@@ -32469,8 +33043,10 @@ async function handleChatInbound(thread, message, kind) {
|
|
|
32469
33043
|
text,
|
|
32470
33044
|
userId: message.author.userId,
|
|
32471
33045
|
userName: message.author.userName || undefined,
|
|
32472
|
-
botMentioned:
|
|
32473
|
-
isDirectMessage
|
|
33046
|
+
botMentioned: mentioned || facts.replyToBot,
|
|
33047
|
+
isDirectMessage,
|
|
33048
|
+
addressed,
|
|
33049
|
+
facts,
|
|
32474
33050
|
attachments
|
|
32475
33051
|
});
|
|
32476
33052
|
if (kind !== "subscribed")
|
|
@@ -32479,6 +33055,47 @@ async function handleChatInbound(thread, message, kind) {
|
|
|
32479
33055
|
if (immediate)
|
|
32480
33056
|
await instantFlushChat(thread.id);
|
|
32481
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
|
+
}
|
|
32482
33099
|
async function getChatThreadContext(thread, exclude, since) {
|
|
32483
33100
|
try {
|
|
32484
33101
|
await thread.refresh();
|
|
@@ -32549,6 +33166,8 @@ async function flushChatThread(threadId, items, immediate) {
|
|
|
32549
33166
|
`);
|
|
32550
33167
|
const botMentioned = items.some((item) => item.botMentioned);
|
|
32551
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;
|
|
32552
33171
|
const resetAt = await getChatThreadResetAt(threadId);
|
|
32553
33172
|
const previousTask = await getLatestTaskByContextKey2(contextKey);
|
|
32554
33173
|
const mostRecentTask = previousTask && resetAt && new Date(previousTask.createdAt).getTime() <= resetAt.getTime() ? null : previousTask;
|
|
@@ -32561,6 +33180,9 @@ async function flushChatThread(threadId, items, immediate) {
|
|
|
32561
33180
|
text: rawText,
|
|
32562
33181
|
botMentioned,
|
|
32563
33182
|
isDirectMessage,
|
|
33183
|
+
...first.facts.chatType ? { chatType: first.facts.chatType } : {},
|
|
33184
|
+
...first.facts.isForum ? { isForum: true } : {},
|
|
33185
|
+
replyToBot: items.some((item) => item.facts.replyToBot),
|
|
32564
33186
|
...mostRecentTask ? { threadContext: { adapter, threadId } } : {}
|
|
32565
33187
|
}, {
|
|
32566
33188
|
validateModify: (data) => {
|
|
@@ -32611,7 +33233,16 @@ async function flushChatThread(threadId, items, immediate) {
|
|
|
32611
33233
|
const body = stripRoutingTokens(rawText);
|
|
32612
33234
|
const files = items.flatMap((item) => toChatFiles(adapter, item.messageId, item.attachments));
|
|
32613
33235
|
const inbound = __using(__stack, await fetchChatFiles(files), 1);
|
|
32614
|
-
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);
|
|
32615
33246
|
const combined = [body, fileText].filter(Boolean).join(`
|
|
32616
33247
|
|
|
32617
33248
|
`);
|
|
@@ -32619,9 +33250,17 @@ async function flushChatThread(threadId, items, immediate) {
|
|
|
32619
33250
|
|
|
32620
33251
|
${combined}` : combined;
|
|
32621
33252
|
const threadContext = mostRecentTask && thread ? await getChatThreadContext(thread, new Set(items.map((item) => item.messageId)), resetAt) : "";
|
|
32622
|
-
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(`
|
|
32623
33261
|
|
|
32624
|
-
|
|
33262
|
+
`);
|
|
33263
|
+
const requestedByUserId = otherSenders > 0 ? undefined : await resolveChatRequester(adapter, requester);
|
|
32625
33264
|
const latestActive = await getLatestActiveTaskByContextKey2(contextKey, "chat");
|
|
32626
33265
|
const dependsOn = !immediate && latestActive ? [latestActive.id] : undefined;
|
|
32627
33266
|
let created = 0;
|
|
@@ -32636,7 +33275,9 @@ ${marked}` : marked;
|
|
|
32636
33275
|
priority: 70,
|
|
32637
33276
|
contextKey,
|
|
32638
33277
|
dependsOn,
|
|
33278
|
+
requestedByUserId,
|
|
32639
33279
|
parentTaskId: mostRecentTask?.id,
|
|
33280
|
+
inheritParentRequester: false,
|
|
32640
33281
|
inheritParentOutputSchema: false
|
|
32641
33282
|
};
|
|
32642
33283
|
try {
|
|
@@ -32652,6 +33293,7 @@ ${marked}` : marked;
|
|
|
32652
33293
|
}
|
|
32653
33294
|
}
|
|
32654
33295
|
if (created > 0) {
|
|
33296
|
+
await rememberChatThreadRequester(threadId, requester.userId);
|
|
32655
33297
|
await subscribe(thread);
|
|
32656
33298
|
startTypingKeepalive(adapter, threadId);
|
|
32657
33299
|
} else {
|
|
@@ -32697,6 +33339,127 @@ init_db3();
|
|
|
32697
33339
|
init_context_key();
|
|
32698
33340
|
init_secret_scrubber();
|
|
32699
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
|
|
32700
33463
|
var RELAY_GIVE_UP_AFTER_MS = 24 * 60 * 60 * 1000;
|
|
32701
33464
|
var SWEEP_EVERY_N_TICKS = 20;
|
|
32702
33465
|
var EARLY_TICK_DEBOUNCE_MS = 250;
|
|
@@ -32746,7 +33509,8 @@ async function processPendingChatRelays(now = Date.now(), signal) {
|
|
|
32746
33509
|
adapter: target.adapter,
|
|
32747
33510
|
threadId: target.threadId,
|
|
32748
33511
|
text: formatChatRelayText(task),
|
|
32749
|
-
taskId: task.id
|
|
33512
|
+
taskId: task.id,
|
|
33513
|
+
files: await taskOutputChatFiles(task.id)
|
|
32750
33514
|
});
|
|
32751
33515
|
stopTypingKeepalive(target.threadId);
|
|
32752
33516
|
await markChatRelayDelivered2(task.id, now);
|
|
@@ -33404,43 +34168,6 @@ Original issue: {{issue_key}} — {{issue_summary}}`,
|
|
|
33404
34168
|
// src/jira/sync.ts
|
|
33405
34169
|
init_db3();
|
|
33406
34170
|
init_oauth();
|
|
33407
|
-
|
|
33408
|
-
// src/be/unmapped-identities.ts
|
|
33409
|
-
init_db3();
|
|
33410
|
-
var TTL_MS = 30 * 24 * 60 * 60 * 1000;
|
|
33411
|
-
function namespace(kind) {
|
|
33412
|
-
return `integration:unmapped:${kind}`;
|
|
33413
|
-
}
|
|
33414
|
-
async function recordUnmappedIdentity(kind, externalId, meta) {
|
|
33415
|
-
const ns = namespace(kind);
|
|
33416
|
-
const now = new Date().toISOString();
|
|
33417
|
-
const expiresAt = Date.now() + TTL_MS;
|
|
33418
|
-
const countKey = `${externalId}:count`;
|
|
33419
|
-
const countBefore = await getKv2(ns, countKey);
|
|
33420
|
-
await upsertKv2({
|
|
33421
|
-
namespace: ns,
|
|
33422
|
-
key: `${externalId}:meta`,
|
|
33423
|
-
value: {
|
|
33424
|
-
lastSeenAt: now,
|
|
33425
|
-
sampleEventType: meta.sampleEventType,
|
|
33426
|
-
sampleContext: meta.sampleContext.slice(0, 100)
|
|
33427
|
-
},
|
|
33428
|
-
valueType: "json",
|
|
33429
|
-
expiresAt
|
|
33430
|
-
});
|
|
33431
|
-
const incremented = await incrKv2(ns, countKey, 1);
|
|
33432
|
-
if (countBefore === null) {
|
|
33433
|
-
await upsertKv2({
|
|
33434
|
-
namespace: ns,
|
|
33435
|
-
key: countKey,
|
|
33436
|
-
value: Number(incremented.value),
|
|
33437
|
-
valueType: "integer",
|
|
33438
|
-
expiresAt
|
|
33439
|
-
});
|
|
33440
|
-
}
|
|
33441
|
-
}
|
|
33442
|
-
|
|
33443
|
-
// src/jira/sync.ts
|
|
33444
34171
|
init_users();
|
|
33445
34172
|
init_resolver();
|
|
33446
34173
|
init_context_key();
|
|
@@ -33826,7 +34553,7 @@ async function notifySlack(text) {
|
|
|
33826
34553
|
return;
|
|
33827
34554
|
}
|
|
33828
34555
|
try {
|
|
33829
|
-
const { getSlackApp } = await import("./app-
|
|
34556
|
+
const { getSlackApp } = await import("./app-353vre8g.js");
|
|
33830
34557
|
const app = getSlackApp();
|
|
33831
34558
|
if (!app) {
|
|
33832
34559
|
console.warn("[Jira webhook keepalive] Slack not available, cannot send notification");
|
|
@@ -33897,7 +34624,7 @@ async function deleteJiraWebhook(webhookId) {
|
|
|
33897
34624
|
console.log(`[Jira webhook keepalive] Deleted webhook id=${webhookId}`);
|
|
33898
34625
|
}
|
|
33899
34626
|
async function overwriteWebhookIds(next) {
|
|
33900
|
-
const { getDbClient } = await import("./db-
|
|
34627
|
+
const { getDbClient } = await import("./db-6sfrn9g3.js");
|
|
33901
34628
|
await getDbClient().transaction(async (tx) => {
|
|
33902
34629
|
const row = await tx.get("SELECT metadata FROM oauth_apps WHERE provider = 'jira'");
|
|
33903
34630
|
if (!row) {
|
|
@@ -106997,11 +107724,34 @@ function parseCookieHeader(cookieHeader, name) {
|
|
|
106997
107724
|
const match = header.match(re);
|
|
106998
107725
|
return match ? match[1] : undefined;
|
|
106999
107726
|
}
|
|
107000
|
-
|
|
107001
|
-
|
|
107002
|
-
|
|
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))
|
|
107003
107742
|
return null;
|
|
107004
|
-
|
|
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;
|
|
107005
107755
|
}
|
|
107006
107756
|
var PAGE_SESSION_TTL_SECONDS = 3600;
|
|
107007
107757
|
async function issuePageSessionCookie(pageId, opts) {
|
|
@@ -107013,13 +107763,11 @@ async function issuePageSessionCookie(pageId, opts) {
|
|
|
107013
107763
|
...opts.name ? { name: opts.name } : {},
|
|
107014
107764
|
...opts.op ? { op: true } : {}
|
|
107015
107765
|
});
|
|
107016
|
-
|
|
107017
|
-
|
|
107018
|
-
|
|
107019
|
-
|
|
107020
|
-
|
|
107021
|
-
];
|
|
107022
|
-
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) {
|
|
107023
107771
|
attrs.push("SameSite=Lax");
|
|
107024
107772
|
} else {
|
|
107025
107773
|
attrs.push("SameSite=None");
|
|
@@ -107027,6 +107775,30 @@ async function issuePageSessionCookie(pageId, opts) {
|
|
|
107027
107775
|
}
|
|
107028
107776
|
return attrs.join("; ");
|
|
107029
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
|
+
}
|
|
107030
107802
|
|
|
107031
107803
|
// src/http/auth.ts
|
|
107032
107804
|
function extractBearer(req) {
|
|
@@ -107247,14 +108019,14 @@ async function reloadGlobalConfigsAndIntegrations() {
|
|
|
107247
108019
|
return runWithoutRequestAuth(() => reloadGlobalConfigsAndIntegrationsInner());
|
|
107248
108020
|
}
|
|
107249
108021
|
async function reloadGlobalConfigsAndIntegrationsInner() {
|
|
107250
|
-
const { getEmbeddingProvider, resetEmbeddingProvider } = await import("./index-
|
|
108022
|
+
const { getEmbeddingProvider, resetEmbeddingProvider } = await import("./index-arytgj5q.js");
|
|
107251
108023
|
const wasEmbeddingsConfigured = getEmbeddingProvider().isConfigured();
|
|
107252
108024
|
const updated = await loadGlobalConfigsIntoEnv(true);
|
|
107253
108025
|
await syncTelemetryEnabled("settings").catch((err) => {
|
|
107254
108026
|
console.error("[config-reload] telemetry re-init failed (non-fatal):", err);
|
|
107255
108027
|
});
|
|
107256
108028
|
await stopSlackApp2();
|
|
107257
|
-
const { resetFileStorageProvider } = await import("./registry-
|
|
108029
|
+
const { resetFileStorageProvider } = await import("./registry-ajhexe44.js");
|
|
107258
108030
|
resetFileStorageProvider();
|
|
107259
108031
|
resetEmbeddingProvider();
|
|
107260
108032
|
const isEmbeddingsConfigured = getEmbeddingProvider().isConfigured();
|
|
@@ -107263,10 +108035,10 @@ async function reloadGlobalConfigsAndIntegrationsInner() {
|
|
|
107263
108035
|
integrations.push("embeddings");
|
|
107264
108036
|
}
|
|
107265
108037
|
if (!wasEmbeddingsConfigured && isEmbeddingsConfigured) {
|
|
107266
|
-
import("./boot-reembed-
|
|
108038
|
+
import("./boot-reembed-b9c3az3c.js").then(({ runBootReembed }) => runBootReembed()).catch((err) => {
|
|
107267
108039
|
console.error("[config-reload] memory backfill failed (non-fatal):", err);
|
|
107268
108040
|
});
|
|
107269
|
-
import("./boot-reembed-
|
|
108041
|
+
import("./boot-reembed-qdkvxeem.js").then(({ runBootReembedScripts }) => runBootReembedScripts()).catch((err) => {
|
|
107270
108042
|
console.error("[config-reload] script backfill failed (non-fatal):", err);
|
|
107271
108043
|
});
|
|
107272
108044
|
}
|
|
@@ -107678,6 +108450,10 @@ async function handleCore(req, res, myAgentId, apiKey) {
|
|
|
107678
108450
|
return false;
|
|
107679
108451
|
}
|
|
107680
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
|
+
|
|
107681
108457
|
// src/server.ts
|
|
107682
108458
|
init_resolver();
|
|
107683
108459
|
init_rbac();
|
|
@@ -112726,9 +113502,11 @@ var registerCancelTaskTool = (server) => {
|
|
|
112726
113502
|
init_zod();
|
|
112727
113503
|
|
|
112728
113504
|
// src/tools/chat-access.ts
|
|
113505
|
+
init_zod();
|
|
112729
113506
|
init_db3();
|
|
112730
113507
|
init_rbac();
|
|
112731
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.");
|
|
112732
113510
|
async function callerChatThread(requestInfo) {
|
|
112733
113511
|
if (!requestInfo.agentId)
|
|
112734
113512
|
return null;
|
|
@@ -112809,16 +113587,18 @@ var registerChatPostTool = (server) => {
|
|
|
112809
113587
|
adapter: _enum2(CHAT_SDK_ADAPTER_NAMES).describe("Chat SDK adapter name."),
|
|
112810
113588
|
threadId: string2().min(1).optional().describe("Full SDK thread id, such as telegram:12345 or slack:C123:1700000000.000100."),
|
|
112811
113589
|
channelId: string2().min(1).optional().describe("Full SDK channel id, such as slack:C123. Ignored when threadId is set."),
|
|
112812
|
-
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
|
|
112813
113592
|
}),
|
|
112814
113593
|
outputSchema: swarmToolOutputSchema({
|
|
112815
113594
|
yourAgentId: string2().optional(),
|
|
112816
113595
|
messageId: string2().optional(),
|
|
112817
113596
|
adapter: string2().optional(),
|
|
112818
113597
|
threadId: string2().optional(),
|
|
112819
|
-
channelId: string2().optional()
|
|
113598
|
+
channelId: string2().optional(),
|
|
113599
|
+
unsentFiles: array2(looseObject({ name: string2().optional(), reason: string2().optional() })).optional()
|
|
112820
113600
|
})
|
|
112821
|
-
}, async ({ adapter, threadId, channelId, text }, requestInfo) => {
|
|
113601
|
+
}, async ({ adapter, threadId, channelId, text, attachments }, requestInfo) => {
|
|
112822
113602
|
const data = { yourAgentId: requestInfo.agentId };
|
|
112823
113603
|
const target = threadId ?? channelId;
|
|
112824
113604
|
if (!target)
|
|
@@ -112829,20 +113609,25 @@ var registerChatPostTool = (server) => {
|
|
|
112829
113609
|
if (!await canUseChatVerb(requestInfo, "integration.chat.post")) {
|
|
112830
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 });
|
|
112831
113611
|
}
|
|
113612
|
+
const resolved = await resolveChatAttachmentRefs(attachments ?? [], requestInfo.sourceTaskId, requestInfo.agentId);
|
|
113613
|
+
if ("error" in resolved)
|
|
113614
|
+
return toolErr(resolved.error, { data });
|
|
112832
113615
|
try {
|
|
112833
113616
|
const sent = await postChatMessage({
|
|
112834
113617
|
adapter,
|
|
112835
113618
|
...threadId ? { threadId } : { channelId },
|
|
112836
113619
|
text,
|
|
112837
|
-
taskId: requestInfo.sourceTaskId
|
|
113620
|
+
taskId: requestInfo.sourceTaskId,
|
|
113621
|
+
files: resolved.files
|
|
112838
113622
|
});
|
|
112839
|
-
return toolOk(`Posted to ${adapter} ${threadId ? "thread" : "channel"} ${target}
|
|
113623
|
+
return toolOk(`Posted to ${adapter} ${threadId ? "thread" : "channel"} ${target}.${unsentFilesSummary(sent.unsentFiles)}`, {
|
|
112840
113624
|
data: {
|
|
112841
113625
|
...data,
|
|
112842
113626
|
messageId: sent.messageIds.at(-1),
|
|
112843
113627
|
adapter: sent.adapter,
|
|
112844
113628
|
threadId: sent.threadId,
|
|
112845
|
-
channelId: sent.channelId
|
|
113629
|
+
channelId: sent.channelId,
|
|
113630
|
+
unsentFiles: sent.unsentFiles
|
|
112846
113631
|
}
|
|
112847
113632
|
});
|
|
112848
113633
|
} catch (error) {
|
|
@@ -112923,18 +113708,20 @@ init_context_key();
|
|
|
112923
113708
|
var registerChatReplyTool = (server) => {
|
|
112924
113709
|
createToolRegistrar(server)("chat-reply", {
|
|
112925
113710
|
title: "Reply in the chat thread of this task",
|
|
112926
|
-
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.",
|
|
112927
113712
|
annotations: { openWorldHint: true },
|
|
112928
113713
|
inputSchema: object2({
|
|
112929
|
-
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
|
|
112930
113716
|
}),
|
|
112931
113717
|
outputSchema: swarmToolOutputSchema({
|
|
112932
113718
|
yourAgentId: string2().optional(),
|
|
112933
113719
|
messageId: string2().optional(),
|
|
112934
113720
|
adapter: string2().optional(),
|
|
112935
|
-
threadId: string2().optional()
|
|
113721
|
+
threadId: string2().optional(),
|
|
113722
|
+
unsentFiles: array2(looseObject({ name: string2().optional(), reason: string2().optional() })).optional()
|
|
112936
113723
|
})
|
|
112937
|
-
}, async ({ text }, requestInfo) => {
|
|
113724
|
+
}, async ({ text, attachments }, requestInfo) => {
|
|
112938
113725
|
if (!requestInfo.agentId)
|
|
112939
113726
|
return toolErr("Agent ID not found.");
|
|
112940
113727
|
const data = { yourAgentId: requestInfo.agentId };
|
|
@@ -112948,19 +113735,24 @@ var registerChatReplyTool = (server) => {
|
|
|
112948
113735
|
if (!thread) {
|
|
112949
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 });
|
|
112950
113737
|
}
|
|
113738
|
+
const resolved = await resolveChatAttachmentRefs(attachments ?? [], task.id, requestInfo.agentId);
|
|
113739
|
+
if ("error" in resolved)
|
|
113740
|
+
return toolErr(resolved.error, { data });
|
|
112951
113741
|
try {
|
|
112952
113742
|
const sent = await postChatMessage({
|
|
112953
113743
|
adapter: thread.adapter,
|
|
112954
113744
|
threadId: thread.threadId,
|
|
112955
113745
|
text,
|
|
112956
|
-
taskId: task.id
|
|
113746
|
+
taskId: task.id,
|
|
113747
|
+
files: resolved.files
|
|
112957
113748
|
});
|
|
112958
|
-
return toolOk(`Posted to ${thread.adapter} thread ${sent.threadId}
|
|
113749
|
+
return toolOk(`Posted to ${thread.adapter} thread ${sent.threadId}.${unsentFilesSummary(sent.unsentFiles)}`, {
|
|
112959
113750
|
data: {
|
|
112960
113751
|
...data,
|
|
112961
113752
|
messageId: sent.messageIds.at(-1),
|
|
112962
113753
|
adapter: sent.adapter,
|
|
112963
|
-
threadId: sent.threadId
|
|
113754
|
+
threadId: sent.threadId,
|
|
113755
|
+
unsentFiles: sent.unsentFiles
|
|
112964
113756
|
}
|
|
112965
113757
|
});
|
|
112966
113758
|
} catch (error) {
|
|
@@ -114448,8 +115240,523 @@ init_db3();
|
|
|
114448
115240
|
|
|
114449
115241
|
// src/tasks/task-terminal-effects.ts
|
|
114450
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
|
|
114451
115421
|
init_memory();
|
|
114452
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
|
+
|
|
114453
115760
|
// src/be/memory/raters/retrieval.ts
|
|
114454
115761
|
init_db3();
|
|
114455
115762
|
function dedupeMemoryDocumentIds(memories) {
|
|
@@ -115205,40 +116512,39 @@ ${safeFailureReason || "No reason provided"}
|
|
|
115205
116512
|
This task failed. Learn from this to avoid repeating the mistake.`;
|
|
115206
116513
|
if (taskContent.length < 30)
|
|
115207
116514
|
return;
|
|
115208
|
-
const
|
|
115209
|
-
|
|
115210
|
-
const memory = await store.store({
|
|
116515
|
+
const key = taskCompletionMemoryKey(taskId);
|
|
116516
|
+
await indexMemoryContent({
|
|
115211
116517
|
agentId: agentId ?? null,
|
|
115212
116518
|
content: taskContent,
|
|
115213
116519
|
name: `Task: ${safeTask.slice(0, 80)}`,
|
|
115214
116520
|
scope: "agent",
|
|
115215
116521
|
source: "task_completion",
|
|
115216
|
-
sourceTaskId: taskId
|
|
116522
|
+
sourceTaskId: taskId,
|
|
116523
|
+
key,
|
|
116524
|
+
intent: "task completion memory",
|
|
116525
|
+
replaceExisting: true
|
|
115217
116526
|
});
|
|
115218
|
-
const embedding = await provider.embed(taskContent);
|
|
115219
|
-
if (embedding) {
|
|
115220
|
-
await store.updateEmbedding(memory.id, embedding, provider.name);
|
|
115221
|
-
}
|
|
115222
116527
|
const shouldShareWithSwarm = status === "completed" && (task.taskType === "research" || task.tags?.includes("knowledge") || task.tags?.includes("shared"));
|
|
115223
116528
|
if (shouldShareWithSwarm) {
|
|
115224
116529
|
try {
|
|
115225
|
-
|
|
116530
|
+
await indexMemoryContent({
|
|
115226
116531
|
agentId: agentId ?? null,
|
|
115227
|
-
scope: "swarm",
|
|
115228
|
-
name: `Shared: ${safeTask.slice(0, 80)}`,
|
|
115229
116532
|
content: `Task completed by agent ${agentId}:
|
|
115230
116533
|
|
|
115231
116534
|
${taskContent}`,
|
|
116535
|
+
name: `Shared: ${safeTask.slice(0, 80)}`,
|
|
116536
|
+
scope: "swarm",
|
|
115232
116537
|
source: "task_completion",
|
|
115233
|
-
sourceTaskId: taskId
|
|
116538
|
+
sourceTaskId: taskId,
|
|
116539
|
+
key,
|
|
116540
|
+
intent: "task completion memory",
|
|
116541
|
+
replaceExisting: true
|
|
115234
116542
|
});
|
|
115235
|
-
const swarmEmbedding = await provider.embed(taskContent);
|
|
115236
|
-
if (swarmEmbedding) {
|
|
115237
|
-
await store.updateEmbedding(swarmMemory.id, swarmEmbedding, provider.name);
|
|
115238
|
-
}
|
|
115239
116543
|
} catch {}
|
|
115240
116544
|
}
|
|
115241
|
-
} catch {
|
|
116545
|
+
} catch (err) {
|
|
116546
|
+
console.error("[task-terminal-effects] task completion memory write failed:", scrubSecrets(err instanceof Error ? err.message : String(err)));
|
|
116547
|
+
}
|
|
115242
116548
|
})().catch((err) => console.error("[task-terminal-effects] task completion memory write failed:", scrubSecrets(err instanceof Error ? err.message : String(err))));
|
|
115243
116549
|
}
|
|
115244
116550
|
(async () => {
|
|
@@ -117929,258 +119235,7 @@ var registerMemoryDeleteTool = (server) => {
|
|
|
117929
119235
|
init_zod();
|
|
117930
119236
|
init_db3();
|
|
117931
119237
|
init_memory();
|
|
117932
|
-
|
|
117933
|
-
// src/be/memory/key-guard.ts
|
|
117934
|
-
init_rbac();
|
|
117935
119238
|
init_key_paths();
|
|
117936
|
-
|
|
117937
|
-
class MemoryKeyError extends Error {
|
|
117938
|
-
reason;
|
|
117939
|
-
constructor(message, reason) {
|
|
117940
|
-
super(message);
|
|
117941
|
-
this.reason = reason;
|
|
117942
|
-
this.name = "MemoryKeyError";
|
|
117943
|
-
}
|
|
117944
|
-
}
|
|
117945
|
-
var NO_AUTHORITY = {
|
|
117946
|
-
principal: { kind: "agent", agentId: "", isLead: false },
|
|
117947
|
-
source: "http"
|
|
117948
|
-
};
|
|
117949
|
-
function shapeError(key, origin) {
|
|
117950
|
-
if (key.length <= MEMORY_KEY_MAX_LENGTH && MEMORY_KEY_PATTERN.test(key))
|
|
117951
|
-
return null;
|
|
117952
|
-
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.`;
|
|
117953
|
-
return `${subject} ${MEMORY_KEY_PATTERN_MESSAGE}`;
|
|
117954
|
-
}
|
|
117955
|
-
function assertKeyWritable(key, origin, writer) {
|
|
117956
|
-
if (origin === "sourcePath" && !isLongtermKey(key))
|
|
117957
|
-
return;
|
|
117958
|
-
const shape = shapeError(key, origin);
|
|
117959
|
-
if (shape)
|
|
117960
|
-
throw new MemoryKeyError(shape, "invalid");
|
|
117961
|
-
const pathError = longtermKeyError(key);
|
|
117962
|
-
if (pathError)
|
|
117963
|
-
throw new MemoryKeyError(pathError, "invalid");
|
|
117964
|
-
if (!isConsolidatedKey(key))
|
|
117965
|
-
return;
|
|
117966
|
-
const { principal, source } = writer ?? NO_AUTHORITY;
|
|
117967
|
-
const decision = can({
|
|
117968
|
-
principal,
|
|
117969
|
-
verb: "memory.write.consolidated",
|
|
117970
|
-
resource: { kind: "none" },
|
|
117971
|
-
source
|
|
117972
|
-
});
|
|
117973
|
-
if (!decision.allow)
|
|
117974
|
-
throw new MemoryKeyError(consolidatedKeyMessage(key), "forbidden");
|
|
117975
|
-
}
|
|
117976
|
-
|
|
117977
|
-
// src/tools/memory-edit.ts
|
|
117978
|
-
init_key_paths();
|
|
117979
|
-
|
|
117980
|
-
// src/be/memory/link-resolver.ts
|
|
117981
|
-
init_db3();
|
|
117982
|
-
init_constants2();
|
|
117983
|
-
var WIKILINK_RE = /\[\[([^\]]+)\]\]/g;
|
|
117984
|
-
var PR_HASH_RE = /(?:^|[\s(])#(\d{1,5})(?=[\s,.)!?]|$)/gm;
|
|
117985
|
-
var PR_PREFIX_RE = /\bPR\s*#(\d{1,5})\b/gi;
|
|
117986
|
-
var GITHUB_PR_URL_RE = /https?:\/\/github\.com\/([\w.-]+)\/([\w.-]+)\/pull\/(\d+)/g;
|
|
117987
|
-
var AGENT_FS_LIVE_HOSTS = String.raw`agent-fs|live\.agent-fs\.dev`;
|
|
117988
|
-
var AGENT_FS_FILE_ROUTE = String.raw`\/file\/~\/([a-f0-9-]+)\/([a-f0-9-]+)\/([\w/.%-]+)`;
|
|
117989
|
-
var AGENT_UI_PAGE_RE = /(?:app\.[^/]+|localhost:\d+)\/pages\/([a-f0-9-]+)/g;
|
|
117990
|
-
var AGENT_UI_TASK_RE = /(?:app\.[^/]+|localhost:\d+)\/tasks\/([a-f0-9-]+)/g;
|
|
117991
|
-
var wikilinkMatcher = (content) => {
|
|
117992
|
-
const results = [];
|
|
117993
|
-
for (const match of content.matchAll(WIKILINK_RE)) {
|
|
117994
|
-
const name = match[1].trim();
|
|
117995
|
-
if (!name)
|
|
117996
|
-
continue;
|
|
117997
|
-
results.push({
|
|
117998
|
-
linkType: "wikilink",
|
|
117999
|
-
targetKind: "memory",
|
|
118000
|
-
targetId: name,
|
|
118001
|
-
sourceText: match[0],
|
|
118002
|
-
resolver: "wikilink"
|
|
118003
|
-
});
|
|
118004
|
-
}
|
|
118005
|
-
return results;
|
|
118006
|
-
};
|
|
118007
|
-
var prMatcher = (content) => {
|
|
118008
|
-
const results = [];
|
|
118009
|
-
const seen = new Set;
|
|
118010
|
-
for (const match of content.matchAll(GITHUB_PR_URL_RE)) {
|
|
118011
|
-
const id = `github:${match[1]}/${match[2]}#${match[3]}`;
|
|
118012
|
-
if (seen.has(id))
|
|
118013
|
-
continue;
|
|
118014
|
-
seen.add(id);
|
|
118015
|
-
results.push({
|
|
118016
|
-
linkType: "pr",
|
|
118017
|
-
targetKind: "pr",
|
|
118018
|
-
targetId: id,
|
|
118019
|
-
sourceText: match[0],
|
|
118020
|
-
resolver: "pr-url",
|
|
118021
|
-
metadata: { owner: match[1], repo: match[2], number: Number(match[3]) }
|
|
118022
|
-
});
|
|
118023
|
-
}
|
|
118024
|
-
for (const match of content.matchAll(PR_PREFIX_RE)) {
|
|
118025
|
-
const id = `pr:${match[1]}`;
|
|
118026
|
-
if (seen.has(id))
|
|
118027
|
-
continue;
|
|
118028
|
-
seen.add(id);
|
|
118029
|
-
results.push({
|
|
118030
|
-
linkType: "pr",
|
|
118031
|
-
targetKind: "pr",
|
|
118032
|
-
targetId: id,
|
|
118033
|
-
sourceText: match[0].trim(),
|
|
118034
|
-
resolver: "pr-prefix",
|
|
118035
|
-
metadata: { number: Number(match[1]) }
|
|
118036
|
-
});
|
|
118037
|
-
}
|
|
118038
|
-
for (const match of content.matchAll(PR_HASH_RE)) {
|
|
118039
|
-
const id = `pr:${match[1]}`;
|
|
118040
|
-
if (seen.has(id))
|
|
118041
|
-
continue;
|
|
118042
|
-
seen.add(id);
|
|
118043
|
-
results.push({
|
|
118044
|
-
linkType: "pr",
|
|
118045
|
-
targetKind: "pr",
|
|
118046
|
-
targetId: id,
|
|
118047
|
-
sourceText: `#${match[1]}`,
|
|
118048
|
-
resolver: "pr-hash",
|
|
118049
|
-
metadata: { number: Number(match[1]) }
|
|
118050
|
-
});
|
|
118051
|
-
}
|
|
118052
|
-
return results;
|
|
118053
|
-
};
|
|
118054
|
-
function escapeRegExp2(value) {
|
|
118055
|
-
return value.replace(/[.*+?^${}()|[\]\\/]/g, "\\$&");
|
|
118056
|
-
}
|
|
118057
|
-
function agentFsPathRegex() {
|
|
118058
|
-
const appHosts = getConfiguredAppUrls().flatMap((value) => {
|
|
118059
|
-
try {
|
|
118060
|
-
const url = new URL(value);
|
|
118061
|
-
return [escapeRegExp2(`${url.host}${url.pathname.replace(/\/+$/, "")}`)];
|
|
118062
|
-
} catch {
|
|
118063
|
-
return [];
|
|
118064
|
-
}
|
|
118065
|
-
});
|
|
118066
|
-
const hosts = [AGENT_FS_LIVE_HOSTS, ...appHosts, String.raw`localhost:\d+`].join("|");
|
|
118067
|
-
return new RegExp(`(?<![\\w.-])(?:${hosts})${AGENT_FS_FILE_ROUTE}`, "gi");
|
|
118068
|
-
}
|
|
118069
|
-
var agentFsMatcher = (content) => {
|
|
118070
|
-
const results = [];
|
|
118071
|
-
for (const match of content.matchAll(agentFsPathRegex())) {
|
|
118072
|
-
const orgId = match[1];
|
|
118073
|
-
const driveId = match[2];
|
|
118074
|
-
const path = match[3];
|
|
118075
|
-
results.push({
|
|
118076
|
-
linkType: "agent-fs-file",
|
|
118077
|
-
targetKind: "agent-fs-file",
|
|
118078
|
-
targetId: `${orgId}/${driveId}/${path}`,
|
|
118079
|
-
sourceText: match[0],
|
|
118080
|
-
resolver: "agent-fs-path",
|
|
118081
|
-
metadata: { orgId, driveId, path }
|
|
118082
|
-
});
|
|
118083
|
-
}
|
|
118084
|
-
return results;
|
|
118085
|
-
};
|
|
118086
|
-
var agentUiMatcher = (content) => {
|
|
118087
|
-
const results = [];
|
|
118088
|
-
for (const match of content.matchAll(AGENT_UI_PAGE_RE)) {
|
|
118089
|
-
results.push({
|
|
118090
|
-
linkType: "agent-ui",
|
|
118091
|
-
targetKind: "agent-ui",
|
|
118092
|
-
targetId: `page:${match[1]}`,
|
|
118093
|
-
sourceText: match[0],
|
|
118094
|
-
resolver: "agent-ui-page"
|
|
118095
|
-
});
|
|
118096
|
-
}
|
|
118097
|
-
for (const match of content.matchAll(AGENT_UI_TASK_RE)) {
|
|
118098
|
-
results.push({
|
|
118099
|
-
linkType: "agent-ui",
|
|
118100
|
-
targetKind: "agent-ui",
|
|
118101
|
-
targetId: `task:${match[1]}`,
|
|
118102
|
-
sourceText: match[0],
|
|
118103
|
-
resolver: "agent-ui-task"
|
|
118104
|
-
});
|
|
118105
|
-
}
|
|
118106
|
-
return results;
|
|
118107
|
-
};
|
|
118108
|
-
var MATCHERS = [wikilinkMatcher, prMatcher, agentFsMatcher, agentUiMatcher];
|
|
118109
|
-
function resolveLinks(content) {
|
|
118110
|
-
const results = [];
|
|
118111
|
-
for (const matcher of MATCHERS) {
|
|
118112
|
-
for (const link of matcher(content)) {
|
|
118113
|
-
results.push({ ...link, strength: 1 });
|
|
118114
|
-
}
|
|
118115
|
-
}
|
|
118116
|
-
return results;
|
|
118117
|
-
}
|
|
118118
|
-
async function resolveWikilinksToMemoryIds(agentId, links) {
|
|
118119
|
-
const db = getDbClient2();
|
|
118120
|
-
const resolved = [];
|
|
118121
|
-
for (const link of links) {
|
|
118122
|
-
if (link.linkType !== "wikilink") {
|
|
118123
|
-
resolved.push(link);
|
|
118124
|
-
continue;
|
|
118125
|
-
}
|
|
118126
|
-
const row = await db.get("SELECT id FROM agent_memory WHERE name = ? AND (agentId = ? OR scope = 'swarm') LIMIT 1", [link.targetId, agentId]);
|
|
118127
|
-
resolved.push(row ? { ...link, targetId: row.id } : link);
|
|
118128
|
-
}
|
|
118129
|
-
return resolved;
|
|
118130
|
-
}
|
|
118131
|
-
var INSERT_LINK_SQL = `INSERT OR IGNORE INTO memory_link
|
|
118132
|
-
(id, from_memory_id, linkType, targetKind, targetId, strength, resolver, sourceText, metadata, createdAt, updatedAt)
|
|
118133
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`;
|
|
118134
|
-
function insertLinkArgs(memoryId, link, now) {
|
|
118135
|
-
return [
|
|
118136
|
-
crypto.randomUUID(),
|
|
118137
|
-
memoryId,
|
|
118138
|
-
link.linkType,
|
|
118139
|
-
link.targetKind,
|
|
118140
|
-
link.targetId,
|
|
118141
|
-
link.strength,
|
|
118142
|
-
link.resolver,
|
|
118143
|
-
link.sourceText,
|
|
118144
|
-
link.metadata ? JSON.stringify(link.metadata) : null,
|
|
118145
|
-
now,
|
|
118146
|
-
now
|
|
118147
|
-
];
|
|
118148
|
-
}
|
|
118149
|
-
async function storeLinks(memoryId, agentId, content) {
|
|
118150
|
-
const links = resolveLinks(content);
|
|
118151
|
-
if (links.length === 0)
|
|
118152
|
-
return;
|
|
118153
|
-
const resolved = await resolveWikilinksToMemoryIds(agentId, links);
|
|
118154
|
-
const now = new Date().toISOString();
|
|
118155
|
-
await getDbClient2().transaction(async (tx) => {
|
|
118156
|
-
for (const link of resolved) {
|
|
118157
|
-
await tx.run(INSERT_LINK_SQL, insertLinkArgs(memoryId, link, now));
|
|
118158
|
-
}
|
|
118159
|
-
});
|
|
118160
|
-
}
|
|
118161
|
-
function linkIdentity2(link) {
|
|
118162
|
-
return JSON.stringify([link.linkType, link.targetKind, link.targetId, link.sourceText ?? null]);
|
|
118163
|
-
}
|
|
118164
|
-
async function refreshLinks(memoryId, agentId, content) {
|
|
118165
|
-
const resolved = await resolveWikilinksToMemoryIds(agentId, resolveLinks(content));
|
|
118166
|
-
const nextIdentities = new Set(resolved.map((link) => linkIdentity2(link)));
|
|
118167
|
-
const now = new Date().toISOString();
|
|
118168
|
-
await getDbClient2().transaction(async (tx) => {
|
|
118169
|
-
const existing = await tx.query(`SELECT id, linkType, targetKind, targetId, sourceText
|
|
118170
|
-
FROM memory_link
|
|
118171
|
-
WHERE from_memory_id = ? AND linkType != 'sequel'`, [memoryId]);
|
|
118172
|
-
for (const row of existing) {
|
|
118173
|
-
if (!nextIdentities.has(linkIdentity2(row))) {
|
|
118174
|
-
await tx.run("DELETE FROM memory_link WHERE id = ?", [row.id]);
|
|
118175
|
-
}
|
|
118176
|
-
}
|
|
118177
|
-
for (const link of resolved) {
|
|
118178
|
-
await tx.run(INSERT_LINK_SQL, insertLinkArgs(memoryId, link, now));
|
|
118179
|
-
}
|
|
118180
|
-
});
|
|
118181
|
-
}
|
|
118182
|
-
|
|
118183
|
-
// src/tools/memory-edit.ts
|
|
118184
119239
|
init_rbac();
|
|
118185
119240
|
init_types();
|
|
118186
119241
|
var agentMemoryOutputSchema = looseObject({
|
|
@@ -118744,6 +119799,7 @@ async function expandCandidatesWithGraph(candidates, agentId, options = {}) {
|
|
|
118744
119799
|
// src/tools/memory-search.ts
|
|
118745
119800
|
init_key_paths();
|
|
118746
119801
|
init_reranker();
|
|
119802
|
+
init_search_candidates();
|
|
118747
119803
|
init_types();
|
|
118748
119804
|
var NUDGE_ELIGIBLE_SOURCES2 = new Set(["manual", "file_index"]);
|
|
118749
119805
|
function rateHintFor(memoryId) {
|
|
@@ -118799,7 +119855,7 @@ var registerMemorySearchTool = (server) => {
|
|
|
118799
119855
|
const store = getMemoryStore2();
|
|
118800
119856
|
const queryEmbedding = await provider.embed(query);
|
|
118801
119857
|
const candidateLimit = limit * CANDIDATE_SET_MULTIPLIER;
|
|
118802
|
-
const candidates = await store
|
|
119858
|
+
const candidates = await searchMemoryCandidates(store, queryEmbedding ?? new Float32Array(0), requestInfo.agentId, {
|
|
118803
119859
|
scope,
|
|
118804
119860
|
limit: candidateLimit,
|
|
118805
119861
|
source,
|
|
@@ -118887,242 +119943,6 @@ var registerMemorySearchTool = (server) => {
|
|
|
118887
119943
|
// src/tools/memory-store.ts
|
|
118888
119944
|
init_zod();
|
|
118889
119945
|
init_db3();
|
|
118890
|
-
|
|
118891
|
-
// src/be/chunking.ts
|
|
118892
|
-
var MAX_CHUNK_SIZE = 2000;
|
|
118893
|
-
var CHUNK_OVERLAP = 100;
|
|
118894
|
-
var MIN_CHUNK_SIZE = 50;
|
|
118895
|
-
function chunkContent(text) {
|
|
118896
|
-
const trimmed = text.trim();
|
|
118897
|
-
if (!trimmed || trimmed.length < MIN_CHUNK_SIZE) {
|
|
118898
|
-
return [];
|
|
118899
|
-
}
|
|
118900
|
-
if (trimmed.length <= MAX_CHUNK_SIZE) {
|
|
118901
|
-
return [{ content: trimmed, chunkIndex: 0, totalChunks: 1, headings: [] }];
|
|
118902
|
-
}
|
|
118903
|
-
const sections = splitByHeaders(trimmed);
|
|
118904
|
-
const rawChunks = [];
|
|
118905
|
-
for (const section of sections) {
|
|
118906
|
-
if (section.content.length <= MAX_CHUNK_SIZE) {
|
|
118907
|
-
rawChunks.push(section);
|
|
118908
|
-
} else {
|
|
118909
|
-
const subChunks = recursiveSplit(section.content);
|
|
118910
|
-
for (const sub of subChunks) {
|
|
118911
|
-
rawChunks.push({ content: sub, headings: section.headings });
|
|
118912
|
-
}
|
|
118913
|
-
}
|
|
118914
|
-
}
|
|
118915
|
-
const filtered = rawChunks.filter((c) => c.content.trim().length >= MIN_CHUNK_SIZE);
|
|
118916
|
-
if (filtered.length === 0) {
|
|
118917
|
-
return [{ content: trimmed, chunkIndex: 0, totalChunks: 1, headings: [] }];
|
|
118918
|
-
}
|
|
118919
|
-
return filtered.map((c, i) => ({
|
|
118920
|
-
content: c.headings.length > 0 ? `${c.headings.join(" > ")}
|
|
118921
|
-
|
|
118922
|
-
${c.content}` : c.content,
|
|
118923
|
-
chunkIndex: i,
|
|
118924
|
-
totalChunks: filtered.length,
|
|
118925
|
-
headings: c.headings
|
|
118926
|
-
}));
|
|
118927
|
-
}
|
|
118928
|
-
function splitByHeaders(text) {
|
|
118929
|
-
const lines = text.split(`
|
|
118930
|
-
`);
|
|
118931
|
-
const sections = [];
|
|
118932
|
-
let currentContent = [];
|
|
118933
|
-
const headingStack = [];
|
|
118934
|
-
for (const line of lines) {
|
|
118935
|
-
const headingMatch = line.match(/^(#{1,3})\s+(.+)$/);
|
|
118936
|
-
if (headingMatch) {
|
|
118937
|
-
if (currentContent.length > 0) {
|
|
118938
|
-
const content = currentContent.join(`
|
|
118939
|
-
`).trim();
|
|
118940
|
-
if (content) {
|
|
118941
|
-
sections.push({ content, headings: [...headingStack] });
|
|
118942
|
-
}
|
|
118943
|
-
currentContent = [];
|
|
118944
|
-
}
|
|
118945
|
-
const level = headingMatch[1].length;
|
|
118946
|
-
const title = headingMatch[2].trim();
|
|
118947
|
-
while (headingStack.length >= level) {
|
|
118948
|
-
headingStack.pop();
|
|
118949
|
-
}
|
|
118950
|
-
headingStack.push(`${"#".repeat(level)} ${title}`);
|
|
118951
|
-
} else {
|
|
118952
|
-
currentContent.push(line);
|
|
118953
|
-
}
|
|
118954
|
-
}
|
|
118955
|
-
if (currentContent.length > 0) {
|
|
118956
|
-
const content = currentContent.join(`
|
|
118957
|
-
`).trim();
|
|
118958
|
-
if (content) {
|
|
118959
|
-
sections.push({ content, headings: [...headingStack] });
|
|
118960
|
-
}
|
|
118961
|
-
}
|
|
118962
|
-
if (sections.length === 0) {
|
|
118963
|
-
return [{ content: text, headings: [] }];
|
|
118964
|
-
}
|
|
118965
|
-
return sections;
|
|
118966
|
-
}
|
|
118967
|
-
var SEPARATORS = [`
|
|
118968
|
-
|
|
118969
|
-
`, `
|
|
118970
|
-
`, ". ", " "];
|
|
118971
|
-
function recursiveSplit(text) {
|
|
118972
|
-
return recursiveSplitWithSeparators(text, 0);
|
|
118973
|
-
}
|
|
118974
|
-
function recursiveSplitWithSeparators(text, separatorIndex) {
|
|
118975
|
-
if (text.length <= MAX_CHUNK_SIZE) {
|
|
118976
|
-
return [text.trim()].filter((s) => s.length > 0);
|
|
118977
|
-
}
|
|
118978
|
-
if (separatorIndex >= SEPARATORS.length) {
|
|
118979
|
-
return hardSplit(text);
|
|
118980
|
-
}
|
|
118981
|
-
const separator = SEPARATORS[separatorIndex];
|
|
118982
|
-
const parts = text.split(separator);
|
|
118983
|
-
if (parts.length <= 1) {
|
|
118984
|
-
return recursiveSplitWithSeparators(text, separatorIndex + 1);
|
|
118985
|
-
}
|
|
118986
|
-
const chunks = [];
|
|
118987
|
-
let current = "";
|
|
118988
|
-
for (const part of parts) {
|
|
118989
|
-
const candidate = current ? current + separator + part : part;
|
|
118990
|
-
if (candidate.length <= MAX_CHUNK_SIZE) {
|
|
118991
|
-
current = candidate;
|
|
118992
|
-
} else {
|
|
118993
|
-
if (current) {
|
|
118994
|
-
chunks.push(current.trim());
|
|
118995
|
-
}
|
|
118996
|
-
if (part.length > MAX_CHUNK_SIZE) {
|
|
118997
|
-
chunks.push(...recursiveSplitWithSeparators(part, separatorIndex + 1));
|
|
118998
|
-
current = "";
|
|
118999
|
-
} else {
|
|
119000
|
-
current = part;
|
|
119001
|
-
}
|
|
119002
|
-
}
|
|
119003
|
-
}
|
|
119004
|
-
if (current.trim()) {
|
|
119005
|
-
chunks.push(current.trim());
|
|
119006
|
-
}
|
|
119007
|
-
return addOverlap(chunks, text);
|
|
119008
|
-
}
|
|
119009
|
-
function hardSplit(text) {
|
|
119010
|
-
const chunks = [];
|
|
119011
|
-
let start = 0;
|
|
119012
|
-
while (start < text.length) {
|
|
119013
|
-
const end = Math.min(start + MAX_CHUNK_SIZE, text.length);
|
|
119014
|
-
chunks.push(text.slice(start, end).trim());
|
|
119015
|
-
if (end === text.length)
|
|
119016
|
-
break;
|
|
119017
|
-
start = end - CHUNK_OVERLAP;
|
|
119018
|
-
}
|
|
119019
|
-
return chunks.filter((c) => c.length > 0);
|
|
119020
|
-
}
|
|
119021
|
-
function addOverlap(chunks, _originalText) {
|
|
119022
|
-
if (chunks.length <= 1)
|
|
119023
|
-
return chunks;
|
|
119024
|
-
const result = [chunks[0]];
|
|
119025
|
-
for (let i = 1;i < chunks.length; i++) {
|
|
119026
|
-
const prevChunk = chunks[i - 1];
|
|
119027
|
-
const chunk = chunks[i];
|
|
119028
|
-
const overlapText = prevChunk.slice(-CHUNK_OVERLAP);
|
|
119029
|
-
if (overlapText.length + chunk.length <= MAX_CHUNK_SIZE + CHUNK_OVERLAP) {
|
|
119030
|
-
result.push(overlapText + chunk);
|
|
119031
|
-
} else {
|
|
119032
|
-
result.push(chunk);
|
|
119033
|
-
}
|
|
119034
|
-
}
|
|
119035
|
-
return result;
|
|
119036
|
-
}
|
|
119037
|
-
|
|
119038
|
-
// src/be/memory/index-content.ts
|
|
119039
|
-
init_memory();
|
|
119040
|
-
init_secret_scrubber();
|
|
119041
|
-
async function indexMemoryContent(params) {
|
|
119042
|
-
const { agentId, content, name, scope, source, sourceTaskId, sourcePath, tags } = params;
|
|
119043
|
-
const rowKey = params.key ?? (sourcePath || null);
|
|
119044
|
-
if (rowKey)
|
|
119045
|
-
assertKeyWritable(rowKey, params.key != null ? "key" : "sourcePath", params.writer);
|
|
119046
|
-
const contentChunks = chunkContent(content);
|
|
119047
|
-
if (contentChunks.length === 0) {
|
|
119048
|
-
contentChunks.push({
|
|
119049
|
-
content: content.trim(),
|
|
119050
|
-
chunkIndex: 0,
|
|
119051
|
-
totalChunks: 1,
|
|
119052
|
-
headings: []
|
|
119053
|
-
});
|
|
119054
|
-
}
|
|
119055
|
-
const store = getMemoryStore2();
|
|
119056
|
-
const provider = getEmbeddingProvider2();
|
|
119057
|
-
if (sourcePath && agentId && contentChunks.length === 1) {
|
|
119058
|
-
const existing = (await store.list(agentId, {
|
|
119059
|
-
scope,
|
|
119060
|
-
limit: 2,
|
|
119061
|
-
ownerAgentId: agentId,
|
|
119062
|
-
sourcePath
|
|
119063
|
-
})).filter((memory) => memory.sourcePath === sourcePath);
|
|
119064
|
-
if (existing.length === 1 && existing[0]?.totalChunks === 1) {
|
|
119065
|
-
const result = await store.edit({
|
|
119066
|
-
id: existing[0].id,
|
|
119067
|
-
mode: "replace",
|
|
119068
|
-
content: contentChunks[0].content,
|
|
119069
|
-
intent: "re-index memory source path",
|
|
119070
|
-
changedByAgentId: agentId
|
|
119071
|
-
});
|
|
119072
|
-
const embedding = await provider.embed(result.memory.content);
|
|
119073
|
-
if (embedding)
|
|
119074
|
-
await store.updateEmbedding(result.memory.id, embedding, provider.name);
|
|
119075
|
-
try {
|
|
119076
|
-
await refreshLinks(result.memory.id, agentId, result.memory.content);
|
|
119077
|
-
} catch (err) {
|
|
119078
|
-
console.error(`[memory] Link resolution failed for ${result.memory.id}:`, err.message);
|
|
119079
|
-
}
|
|
119080
|
-
return { queued: false, memoryIds: [result.memory.id], edited: result.changed, chunks: 1 };
|
|
119081
|
-
}
|
|
119082
|
-
}
|
|
119083
|
-
if (sourcePath && agentId) {
|
|
119084
|
-
await store.deleteBySourcePath(sourcePath, agentId);
|
|
119085
|
-
}
|
|
119086
|
-
const memories = await store.storeBatch(contentChunks.map((chunk) => ({
|
|
119087
|
-
agentId: agentId || null,
|
|
119088
|
-
content: chunk.content,
|
|
119089
|
-
name,
|
|
119090
|
-
scope,
|
|
119091
|
-
source,
|
|
119092
|
-
sourcePath: sourcePath || null,
|
|
119093
|
-
sourceTaskId: sourceTaskId || null,
|
|
119094
|
-
chunkIndex: chunk.chunkIndex,
|
|
119095
|
-
totalChunks: chunk.totalChunks,
|
|
119096
|
-
tags: tags || [],
|
|
119097
|
-
contextKey: params.contextKey ?? null,
|
|
119098
|
-
intent: params.intent ?? "index memory content",
|
|
119099
|
-
key: rowKey
|
|
119100
|
-
})));
|
|
119101
|
-
if (agentId) {
|
|
119102
|
-
for (const memory of memories) {
|
|
119103
|
-
try {
|
|
119104
|
-
await storeLinks(memory.id, agentId, memory.content);
|
|
119105
|
-
} catch (err) {
|
|
119106
|
-
console.error(`[memory] Link resolution failed for ${memory.id}:`, err.message);
|
|
119107
|
-
}
|
|
119108
|
-
}
|
|
119109
|
-
}
|
|
119110
|
-
(async () => {
|
|
119111
|
-
try {
|
|
119112
|
-
const embeddings = await provider.embedBatch(memories.map((m) => m.content));
|
|
119113
|
-
for (let i = 0;i < embeddings.length; i++) {
|
|
119114
|
-
if (embeddings[i]) {
|
|
119115
|
-
await store.updateEmbedding(memories[i].id, embeddings[i], provider.name);
|
|
119116
|
-
}
|
|
119117
|
-
}
|
|
119118
|
-
} catch (err) {
|
|
119119
|
-
console.error("[memory] Batch embedding failed:", err.message);
|
|
119120
|
-
}
|
|
119121
|
-
})().catch((err) => console.error("[memory] batch embed failed:", scrubSecrets(err instanceof Error ? err.message : String(err))));
|
|
119122
|
-
return { queued: true, memoryIds: memories.map((m) => m.id), chunks: contentChunks.length };
|
|
119123
|
-
}
|
|
119124
|
-
|
|
119125
|
-
// src/tools/memory-store.ts
|
|
119126
119946
|
init_key_paths();
|
|
119127
119947
|
init_types();
|
|
119128
119948
|
var registerMemoryStoreTool = (server) => {
|
|
@@ -131658,33 +132478,35 @@ function formatFileSize2(bytes) {
|
|
|
131658
132478
|
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
131659
132479
|
return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;
|
|
131660
132480
|
}
|
|
131661
|
-
function buildAttachmentText(files, failed = []) {
|
|
132481
|
+
function buildAttachmentText(files, failed = [], notes = new Map) {
|
|
131662
132482
|
const reasons = new Map(failed.map((f) => [f.file.id, f.reason]));
|
|
131663
132483
|
return files.map((f) => {
|
|
131664
132484
|
const size = typeof f.size === "number" ? formatFileSize2(f.size) : "unknown size";
|
|
131665
132485
|
const line = `[File: ${f.name ?? f.id} (${f.mimetype ?? "unknown type"}, ${size}) id=${f.id}]`;
|
|
131666
132486
|
const reason = reasons.get(f.id);
|
|
131667
|
-
|
|
132487
|
+
const note = notes.get(f.id);
|
|
132488
|
+
return [reason ? `${line} (not attached: ${reason})` : line, note].filter(Boolean).join(`
|
|
132489
|
+
`);
|
|
131668
132490
|
}).join(`
|
|
131669
132491
|
`);
|
|
131670
132492
|
}
|
|
131671
|
-
function buildEffectiveText(text, files, failed) {
|
|
132493
|
+
function buildEffectiveText(text, files, failed, notes) {
|
|
131672
132494
|
const hasText = !!text?.trim();
|
|
131673
132495
|
const hasFiles = files && files.length > 0;
|
|
131674
132496
|
if (hasText && hasFiles) {
|
|
131675
132497
|
return `${text}
|
|
131676
132498
|
|
|
131677
|
-
${buildAttachmentText(files, failed)}`;
|
|
132499
|
+
${buildAttachmentText(files, failed, notes)}`;
|
|
131678
132500
|
}
|
|
131679
132501
|
if (hasFiles) {
|
|
131680
|
-
return buildAttachmentText(files, failed);
|
|
132502
|
+
return buildAttachmentText(files, failed, notes);
|
|
131681
132503
|
}
|
|
131682
132504
|
return text || "";
|
|
131683
132505
|
}
|
|
131684
132506
|
function bufferedFileFailures(files) {
|
|
131685
132507
|
return (files ?? []).map((file) => ({ file, reason: BUFFERED_REASON }));
|
|
131686
132508
|
}
|
|
131687
|
-
async function fetchSlackFiles(client, files) {
|
|
132509
|
+
async function fetchSlackFiles(client, files, options = {}) {
|
|
131688
132510
|
let dir;
|
|
131689
132511
|
const result = {
|
|
131690
132512
|
files: [],
|
|
@@ -131710,8 +132532,19 @@ async function fetchSlackFiles(client, files) {
|
|
|
131710
132532
|
result.fetched.push({ file, ...outcome });
|
|
131711
132533
|
}
|
|
131712
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
|
+
}
|
|
131713
132543
|
return result;
|
|
131714
132544
|
}
|
|
132545
|
+
function isSlackAudio(file) {
|
|
132546
|
+
return file.subtype === "slack_audio" || Boolean(file.mimetype?.startsWith("audio/"));
|
|
132547
|
+
}
|
|
131715
132548
|
function looksLikeSignIn(head) {
|
|
131716
132549
|
const joined = new Uint8Array(head.reduce((total, part) => total + part.byteLength, 0));
|
|
131717
132550
|
let offset = 0;
|
|
@@ -133925,9 +134758,9 @@ var registerSystemOneDecideTool = (server) => {
|
|
|
133925
134758
|
createToolRegistrar(server)("system-one-decide", {
|
|
133926
134759
|
title: "Ask a SystemOne decision model",
|
|
133927
134760
|
annotations: { destructiveHint: false, openWorldHint: true },
|
|
133928
|
-
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.",
|
|
133929
134762
|
inputSchema: object2({
|
|
133930
|
-
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)"),
|
|
133931
134764
|
model: string2().min(1).optional().describe("Provider model id (default: the provider's)"),
|
|
133932
134765
|
state: union2([string2(), array2(string2()), record2(string2(), unknown())]).describe("The state to decide on"),
|
|
133933
134766
|
questions: record2(string2(), record2(string2(), unknown())).describe("Questions by id, each `{ type: 'noul' | 'choice' | 'score', instructions, criteria }`"),
|
|
@@ -133938,7 +134771,8 @@ var registerSystemOneDecideTool = (server) => {
|
|
|
133938
134771
|
model: string2().optional(),
|
|
133939
134772
|
answers: record2(string2(), unknown()).optional(),
|
|
133940
134773
|
usage: record2(string2(), unknown()).optional(),
|
|
133941
|
-
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")
|
|
133942
134776
|
})
|
|
133943
134777
|
}, async ({ provider, model, state, questions, timeoutMs, maxRetries }, requestInfo) => {
|
|
133944
134778
|
if (!requestInfo.agentId) {
|
|
@@ -133963,8 +134797,9 @@ var registerSystemOneDecideTool = (server) => {
|
|
|
133963
134797
|
return toolErr("The system-one-decision executor is not available");
|
|
133964
134798
|
}
|
|
133965
134799
|
const decided = await executor.decide(parsed.data);
|
|
133966
|
-
if (!decided.ok)
|
|
133967
|
-
return toolErr(decided.error);
|
|
134800
|
+
if (!decided.ok) {
|
|
134801
|
+
return toolErr(decided.error, decided.deploymentRefused ? { data: { providerUnavailable: true } } : {});
|
|
134802
|
+
}
|
|
133968
134803
|
const { output } = decided;
|
|
133969
134804
|
return toolOk(`Decision from ${output.model}`, {
|
|
133970
134805
|
data: {
|
|
@@ -135961,7 +136796,8 @@ async function createServer(opts = {}) {
|
|
|
135961
136796
|
...opts.preloadedTools?.length ? { instructions: resolveTemplate("system.agent.tool_preload", {}).text } : {},
|
|
135962
136797
|
capabilities: {
|
|
135963
136798
|
logging: {}
|
|
135964
|
-
}
|
|
136799
|
+
},
|
|
136800
|
+
maxToolInputElements: MCP_MAX_TOOL_INPUT_ELEMENTS
|
|
135965
136801
|
});
|
|
135966
136802
|
if (opts.preloadedTools?.length)
|
|
135967
136803
|
setPreloadedTools(server, opts.preloadedTools);
|
|
@@ -136196,4 +137032,4 @@ async function createServer(opts = {}) {
|
|
|
136196
137032
|
return server;
|
|
136197
137033
|
}
|
|
136198
137034
|
|
|
136199
|
-
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 };
|