@desplega.ai/agent-swarm 1.146.0 → 1.147.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/{acp-adapter-jnq4612m.js → acp-adapter-9n319wqc.js} +42 -4
- package/dist/{actions-s41xcn3f.js → actions-2vxqvpr9.js} +9 -8
- package/dist/{app-j8bfw3f6.js → app-w066xfy0.js} +6 -5
- package/dist/assistant-kt31dj2h.js +236 -0
- package/dist/{boot-reembed-jxdz46jp.js → boot-reembed-az5rassp.js} +7 -6
- package/dist/{boot-reembed-x1476agm.js → boot-reembed-j3mm3rfz.js} +8 -7
- package/dist/{boot-scrub-logs-rab9h5bt.js → boot-scrub-logs-b6h54817.js} +4 -4
- package/dist/{claude-adapter-ep6qekbm.js → claude-adapter-w1z04ann.js} +8 -6
- package/dist/{claude-managed-setup-w619jncn.js → claude-managed-setup-f5pmsyrp.js} +24 -3
- package/dist/{claude-sdk-session-0wp3qrcy.js → claude-sdk-session-f0cc1kec.js} +8 -6
- package/dist/{cli-bafd6xnf.js → cli-0b6y7kxm.js} +1 -1
- package/dist/{cli-jyy3e193.js → cli-12fz972k.js} +4 -4
- package/dist/{cli-pzfc7j7g.js → cli-1th1728g.js} +2 -2
- package/dist/{cli-68h2mfrn.js → cli-3tgwnf43.js} +3 -3
- package/dist/{cli-q3qr220d.js → cli-4nr988h6.js} +1 -1
- package/dist/{cli-m4xsy03s.js → cli-53s590z8.js} +1 -1
- package/dist/{cli-c8q7292f.js → cli-54wwve05.js} +5 -4
- package/dist/{cli-rymrjneb.js → cli-719k9j2c.js} +2 -2
- package/dist/{cli-zn65x0w8.js → cli-89xfd7f9.js} +21 -47
- package/dist/{cli-506z6jqa.js → cli-8v0g1yc8.js} +1 -1
- package/dist/cli-9d8ntetj.js +42 -0
- package/dist/{cli-dhg6j8h3.js → cli-atcve9y8.js} +826 -737
- package/dist/{cli-46yck6nj.js → cli-b5bq9crk.js} +14 -31
- package/dist/cli-d8brzxjb.js +190 -0
- package/dist/{cli-a960nkfb.js → cli-de14znh8.js} +2 -2
- package/dist/{cli-s8sbe32s.js → cli-dttph1bw.js} +2 -2
- package/dist/cli-ep19k3mb.js +19 -0
- package/dist/{cli-d9pnxgth.js → cli-f146mn5s.js} +7 -50
- package/dist/{cli-qar1f940.js → cli-f7dsy61y.js} +5 -3
- package/dist/{cli-d4xqde2b.js → cli-ftht3zzj.js} +2780 -2587
- package/dist/{cli-pmwbdw36.js → cli-hbv0kq6w.js} +2 -2
- package/dist/{cli-fhsz3twr.js → cli-jsp14b6c.js} +171 -1
- package/dist/{cli-2zvtzevh.js → cli-kpv03zhj.js} +13 -11
- package/dist/{cli-a9bn9svs.js → cli-m8yrsg97.js} +2 -2
- package/dist/cli-m9sxbkhm.js +779 -0
- package/dist/cli-mmemxxdc.js +823 -0
- package/dist/{cli-6xwhtc64.js → cli-n8508nre.js} +1 -1
- package/dist/{cli-q0qq1sxw.js → cli-p1d5b073.js} +37 -2
- package/dist/{cli-yqeb27t1.js → cli-rw51bq3j.js} +13 -10
- package/dist/{cli-zww3vcnm.js → cli-smby5m17.js} +7 -6
- package/dist/{cli-ah5hjk49.js → cli-tzvk9haz.js} +94 -372
- package/dist/{cli-yxwe913z.js → cli-w9kb3bk1.js} +1 -1
- package/dist/{cli-skd674mt.js → cli-y6b6fb76.js} +25 -3
- package/dist/{cli-3k2g3kg2.js → cli-yz3djrm0.js} +9 -9
- package/dist/{cli-4secrq32.js → cli-zhjmqxzh.js} +1 -1
- package/dist/cli.js +13 -13
- package/dist/{codex-adapter-d6qajxj3.js → codex-adapter-zw4dwsx7.js} +2 -2
- package/dist/{codex-hook-n7m5k7cr.js → codex-hook-bw8p5nh4.js} +2 -2
- package/dist/{codex-session-runner-v9krqe4x.js → codex-session-runner-k981s65v.js} +2 -2
- package/dist/{commands-923wsas7.js → commands-sykrxx7e.js} +4 -4
- package/dist/{db-m1hy4zh5.js → db-sfbsc8wt.js} +6 -4
- package/dist/handlers-0aspcejm.js +603 -0
- package/dist/{hook-ee4hff56.js → hook-4nvqj2sb.js} +7 -5
- package/dist/{hook-bxe3bkdy.js → hook-hxccs7m5.js} +24 -49
- package/dist/{http-a8rx91me.js → http-y06z517d.js} +223 -92
- package/dist/{index-697zfzv1.js → index-hssww7kj.js} +15 -14
- package/dist/{index-3x9g3nbg.js → index-k8znfx0z.js} +13 -12
- package/dist/{index-1j9va48r.js → index-tce1rss4.js} +371 -110
- package/dist/{index-jj4q3x59.js → index-x5j894zf.js} +14 -13
- package/dist/{keepalive-sds4e4ce.js → keepalive-w733ax66.js} +6 -6
- package/dist/{lead-ggq6szk8.js → lead-75bjqa9d.js} +29 -27
- package/dist/{maintenance-093p41d4.js → maintenance-w4f1zjck.js} +8 -7
- package/dist/{oauth-refresh-sweep-dvzq4ckj.js → oauth-refresh-sweep-wdetky26.js} +5 -5
- package/dist/{onboard-ydr9tzw5.js → onboard-bb5net8s.js} +2 -2
- package/dist/{otel-impl-zx3tdf3j.js → otel-impl-0w7c14ap.js} +1 -1
- package/dist/{pi-mono-adapter-dtkz4e7j.js → pi-mono-adapter-2has4gnp.js} +12 -2
- package/dist/{pricing-refresh-7e6pqnzp.js → pricing-refresh-9nzsrgcq.js} +6 -6
- package/dist/{rbac-roles-p2rh6d0r.js → rbac-roles-r3hqjp09.js} +5 -5
- package/dist/{rbac-roles-0dv1wt0w.js → rbac-roles-z1jrffbt.js} +4 -4
- package/dist/{registry-9kdck5ye.js → registry-v5wytg0s.js} +1 -2
- package/dist/{render-v2-4k3jt4r2.js → render-v2-vbr89fnb.js} +6 -5
- package/dist/{seed-pricing-2cc1qmcd.js → seed-pricing-g62hy1pk.js} +7 -5
- package/dist/{setup-c5yss30k.js → setup-gnfqnptp.js} +2 -2
- package/dist/{worker-7srgeqcr.js → worker-kznxp4qm.js} +29 -27
- package/openapi.json +263 -12
- package/package.json +1 -1
- package/plugin/commands/start-worker.md +4 -9
- package/plugin/pi-skills/start-worker/SKILL.md +4 -9
- package/src/be/db/agents.ts +556 -0
- package/src/be/db/context-versions.ts +117 -0
- package/src/be/db/runtime.ts +406 -0
- package/src/be/db/tasks/read.ts +1167 -0
- package/src/be/db/tasks/write.ts +953 -0
- package/src/be/db.ts +583 -3428
- package/src/be/migrations/147_scheduled_tasks_parent_task.sql +7 -0
- package/src/be/migrations/148_pages_svg.sql +123 -0
- package/src/be/migrations/149_session_tokens.sql +24 -0
- package/src/be/scripts/typecheck.ts +1 -0
- package/src/be/seed-pricing.ts +13 -8
- package/src/be/seed-scripts/catalog/ops-catalog-audit.inline.ts +1 -1
- package/src/be/seed-scripts/catalog/ops-catalog-audit.ts +1 -1
- package/src/be/seed-scripts/catalog/star-history-refresh.ts +101 -0
- package/src/be/seed-scripts/catalog/star-history-renderer.ts +119 -0
- package/src/be/seed-scripts/index.ts +17 -0
- package/src/be/seed-skills/index.ts +14 -0
- package/src/be/swarm-config-guard.ts +1 -1
- package/src/be/task-attachment-store.ts +70 -0
- package/src/be/users.ts +77 -0
- package/src/commands/attachments-section.ts +37 -0
- package/src/commands/claude-managed-setup.ts +45 -3
- package/src/commands/claude-md-session.ts +408 -0
- package/src/commands/context-preamble.ts +15 -3
- package/src/commands/profile-sync.ts +205 -5
- package/src/commands/provider-credentials.ts +60 -27
- package/src/commands/runner.ts +63 -58
- package/src/commands/templates.ts +25 -2
- package/src/hooks/hook.ts +26 -67
- package/src/http/agents.ts +40 -1
- package/src/http/auth.ts +13 -1
- package/src/http/fs.ts +21 -51
- package/src/http/mcp.ts +32 -0
- package/src/http/pages-public.ts +20 -4
- package/src/http/poll.ts +4 -0
- package/src/http/repos.ts +3 -3
- package/src/http/sessions.ts +82 -0
- package/src/http/tasks.ts +10 -2
- package/src/prompts/session-templates.ts +4 -2
- package/src/providers/acp-adapter.ts +42 -6
- package/src/providers/pi-mono-adapter.ts +23 -6
- package/src/scheduler/scheduler.test.ts +49 -2
- package/src/scheduler/scheduler.ts +4 -0
- package/src/scripts-runtime/sdk-allowlist.ts +1 -0
- package/src/scripts-runtime/types/stdlib.d.ts +8 -0
- package/src/scripts-runtime/types/swarm-sdk.d.ts +8 -0
- package/src/server.ts +2 -0
- package/src/slack/assistant.ts +87 -46
- package/src/slack/handlers.test.ts +1 -3
- package/src/slack/handlers.ts +102 -87
- package/src/slack/inbound-files.ts +466 -0
- package/src/slack/templates.ts +14 -0
- package/src/tasks/task-terminal-effects.ts +158 -0
- package/src/tests/acp-adapter.test.ts +327 -192
- package/src/tests/budget-claim-gate.test.ts +1 -0
- package/src/tests/build-pi-skills.test.ts +5 -7
- package/src/tests/claude-managed-setup.test.ts +52 -4
- package/src/tests/claude-md-session.test.ts +603 -0
- package/src/tests/codex-skill-resolver.test.ts +19 -0
- package/src/tests/context-versioning.test.ts +107 -0
- package/src/tests/credential-check.test.ts +157 -14
- package/src/tests/db-agents.test.ts +91 -0
- package/src/tests/db-context-versions.test.ts +37 -0
- package/src/tests/db-extraction-contract.test.ts +45 -0
- package/src/tests/db-runtime.test.ts +70 -0
- package/src/tests/db-task-read-contract.test.ts +624 -0
- package/src/tests/db-task-write-contract.test.ts +653 -0
- package/src/tests/db-tasks-read.test.ts +183 -0
- package/src/tests/db-tasks-write.test.ts +230 -0
- package/src/tests/defer-task.test.ts +389 -0
- package/src/tests/docs-index-footprint.test.js +2 -2
- package/src/tests/e2e-visuals-stage.test.ts +151 -0
- package/src/tests/file-lock.test.ts +144 -0
- package/src/tests/fixtures/file-lock-holder.ts +13 -0
- package/src/tests/fixtures/hold-file-lock.ts +25 -0
- package/src/tests/heartbeat-expiry.test.ts +188 -0
- package/src/tests/http-api-integration.test.ts +78 -1
- package/src/tests/pages-public-html.test.ts +43 -0
- package/src/tests/pages-svg-migration.test.ts +42 -0
- package/src/tests/preload.ts +4 -1
- package/src/tests/profile-sync-warning.test.ts +16 -0
- package/src/tests/profile-sync.test.ts +126 -0
- package/src/tests/prompt-template-session.test.ts +20 -4
- package/src/tests/provider-registration.test.ts +93 -0
- package/src/tests/rbac-e2e-helpers.test.ts +53 -0
- package/src/tests/rbac-e2e-helpers.ts +19 -2
- package/src/tests/routing-affinity-inventory.test.ts +1 -1
- package/src/tests/runner-attachments-section.test.ts +22 -2
- package/src/tests/runner-context-preamble.test.ts +30 -0
- package/src/tests/runner-deployment-resume.test.ts +107 -0
- package/src/tests/runner-repo-autostash.test.ts +12 -0
- package/src/tests/script-connections.test.ts +4 -0
- package/src/tests/seed-scripts.test.ts +2 -2
- package/src/tests/session-tokens.test.ts +279 -0
- package/src/tests/slack-file-tools-attachments.test.ts +408 -0
- package/src/tests/slack-inbound-files.test.ts +847 -0
- package/src/tests/star-history-refresh.test.ts +102 -0
- package/src/tests/swarm-repos.test.ts +20 -0
- package/src/tests/tool-annotations.test.ts +4 -3
- package/src/tests/ui-logs-parser.test.ts +176 -0
- package/src/tools/create-page.ts +4 -2
- package/src/tools/defer-task.ts +239 -0
- package/src/tools/repos/update-repo.ts +2 -2
- package/src/tools/schedules/create-schedule.ts +1 -0
- package/src/tools/schedules/list-schedules.ts +1 -0
- package/src/tools/schedules/patch-schedule.ts +1 -0
- package/src/tools/schedules/update-schedule.ts +1 -0
- package/src/tools/slack-download-file.ts +60 -29
- package/src/tools/slack-read.ts +73 -32
- package/src/tools/store-progress.ts +16 -146
- package/src/tools/tool-config.ts +1 -0
- package/src/tools/utils.ts +21 -0
- package/src/types.ts +37 -4
- package/src/utils/acp-session-token.ts +56 -0
- package/src/utils/file-lock.ts +111 -0
- package/src/utils/heartbeat-expiry.ts +78 -0
- package/src/utils/request-auth-context.ts +2 -0
- package/src/utils/task-attachment-links.ts +22 -0
- package/templates/skills/code-quality/content.md +8 -5
- package/templates/skills/download-task-attachment/content.md +2 -1
- package/{plugin/pi-skills → templates/skills}/review-offered-task/SKILL.md +5 -5
- package/templates/skills/review-offered-task/config.json +14 -0
- package/{plugin/commands/review-offered-task.md → templates/skills/review-offered-task/content.md} +3 -8
- package/templates/skills/scheduling/content.md +4 -0
- package/templates/skills/slack-interaction/content.md +2 -2
- package/templates/skills/work-on-task/SKILL.md +16 -0
- package/templates/skills/work-on-task/config.json +14 -0
- package/templates/skills/work-on-task/content.md +11 -0
- package/dist/assistant-dx3ew4d8.js +0 -212
- package/dist/cli-00kyrp1a.js +0 -317
- package/dist/cli-n1q8q14d.js +0 -177
- package/dist/cli-ss6vybmt.js +0 -269
- package/dist/handlers-e9vp2fr8.js +0 -592
- package/plugin/commands/work-on-task.md +0 -39
- package/plugin/pi-skills/work-on-task/SKILL.md +0 -39
|
@@ -11,17 +11,17 @@ import {
|
|
|
11
11
|
import {
|
|
12
12
|
calculateNextRun,
|
|
13
13
|
runScheduleNow
|
|
14
|
-
} from "./cli-
|
|
14
|
+
} from "./cli-smby5m17.js";
|
|
15
15
|
import {
|
|
16
16
|
startPricingRefreshLoop
|
|
17
|
-
} from "./cli-
|
|
17
|
+
} from "./cli-m8yrsg97.js";
|
|
18
18
|
import {
|
|
19
19
|
seedPricingFromModelsDev
|
|
20
|
-
} from "./cli-
|
|
20
|
+
} from "./cli-rw51bq3j.js";
|
|
21
21
|
import {
|
|
22
22
|
ensureRbacSeedsSynced,
|
|
23
23
|
getUserGrant
|
|
24
|
-
} from "./cli-
|
|
24
|
+
} from "./cli-8v0g1yc8.js";
|
|
25
25
|
import {
|
|
26
26
|
can,
|
|
27
27
|
decideAdmission,
|
|
@@ -48,7 +48,7 @@ import {
|
|
|
48
48
|
runSavedScriptAsAgent,
|
|
49
49
|
updateApp,
|
|
50
50
|
upgradeAppDefinition
|
|
51
|
-
} from "./cli-
|
|
51
|
+
} from "./cli-de14znh8.js";
|
|
52
52
|
import {
|
|
53
53
|
require_dist as require_dist2
|
|
54
54
|
} from "./cli-qgm2pfpq.js";
|
|
@@ -72,7 +72,7 @@ import {
|
|
|
72
72
|
updateTrackerSync,
|
|
73
73
|
updateTrackerSyncSwarmId,
|
|
74
74
|
upsertSwarmConfigWithPolicyMirror
|
|
75
|
-
} from "./cli-
|
|
75
|
+
} from "./cli-f7dsy61y.js";
|
|
76
76
|
import {
|
|
77
77
|
isMultiRuntimeEnabled
|
|
78
78
|
} from "./cli-07jd68a1.js";
|
|
@@ -86,7 +86,7 @@ import {
|
|
|
86
86
|
snapshotWorkflow,
|
|
87
87
|
startWorkflowExecution,
|
|
88
88
|
validateJsonSchema
|
|
89
|
-
} from "./cli-
|
|
89
|
+
} from "./cli-yz3djrm0.js";
|
|
90
90
|
import {
|
|
91
91
|
ConnectionAuthInputSchema,
|
|
92
92
|
SCRIPT_LONG_TIMEOUT_HINT_MS,
|
|
@@ -109,7 +109,7 @@ import {
|
|
|
109
109
|
upsertCredentialBinding,
|
|
110
110
|
upsertScriptConnection,
|
|
111
111
|
validateDefinition
|
|
112
|
-
} from "./cli-
|
|
112
|
+
} from "./cli-3tgwnf43.js";
|
|
113
113
|
import {
|
|
114
114
|
CANDIDATE_SET_MULTIPLIER,
|
|
115
115
|
computeScore,
|
|
@@ -121,7 +121,7 @@ import {
|
|
|
121
121
|
isGraphExpansionEnabled,
|
|
122
122
|
rerank,
|
|
123
123
|
rowToCandidate
|
|
124
|
-
} from "./cli-
|
|
124
|
+
} from "./cli-1th1728g.js";
|
|
125
125
|
import {
|
|
126
126
|
getApiKey
|
|
127
127
|
} from "./cli-f14fvzag.js";
|
|
@@ -139,22 +139,29 @@ import {
|
|
|
139
139
|
listAuthorizationsForApp,
|
|
140
140
|
onAuthorizationRefreshed,
|
|
141
141
|
upsertOAuthApp
|
|
142
|
-
} from "./cli-
|
|
142
|
+
} from "./cli-zhjmqxzh.js";
|
|
143
143
|
import {
|
|
144
144
|
ZodFirstPartyTypeKind,
|
|
145
145
|
objectType
|
|
146
146
|
} from "./cli-fad8m16k.js";
|
|
147
|
-
import {
|
|
148
|
-
AgentFsProvider
|
|
149
|
-
} from "./cli-fhsz3twr.js";
|
|
150
147
|
import {
|
|
151
148
|
require_dist
|
|
152
149
|
} from "./cli-51tf7ac3.js";
|
|
153
150
|
import {
|
|
151
|
+
DEFAULT_DOWNLOAD_DIR,
|
|
152
|
+
MAX_FILE_SIZE,
|
|
153
|
+
attachSlackFilesForAgent,
|
|
154
|
+
attachableTask,
|
|
154
155
|
createAdditiveBuffer,
|
|
156
|
+
downloadFile,
|
|
155
157
|
extractSlackMessageText,
|
|
156
|
-
|
|
157
|
-
|
|
158
|
+
getFileInfo,
|
|
159
|
+
parseSlackTs,
|
|
160
|
+
uploadFile
|
|
161
|
+
} from "./cli-mmemxxdc.js";
|
|
162
|
+
import {
|
|
163
|
+
AgentFsProvider
|
|
164
|
+
} from "./cli-jsp14b6c.js";
|
|
158
165
|
import {
|
|
159
166
|
findOrCreateUserByEmail,
|
|
160
167
|
findUserByExternalId,
|
|
@@ -166,14 +173,15 @@ import {
|
|
|
166
173
|
recordIdentityEvent,
|
|
167
174
|
recordUnmappedIdentity,
|
|
168
175
|
renderIdentity,
|
|
176
|
+
resolveBySessionToken,
|
|
169
177
|
resolveIdentity,
|
|
170
178
|
resolveIdentityByEmail,
|
|
171
179
|
resolveUserByToken,
|
|
172
180
|
unlinkIdentity
|
|
173
|
-
} from "./cli-
|
|
181
|
+
} from "./cli-p1d5b073.js";
|
|
174
182
|
import {
|
|
175
183
|
createTaskWithSiblingAwareness
|
|
176
|
-
} from "./cli-
|
|
184
|
+
} from "./cli-53s590z8.js";
|
|
177
185
|
import {
|
|
178
186
|
ensure,
|
|
179
187
|
getAgentDisplayName,
|
|
@@ -184,7 +192,7 @@ import {
|
|
|
184
192
|
startSlackApp,
|
|
185
193
|
stopSlackApp,
|
|
186
194
|
withSpan
|
|
187
|
-
} from "./cli-
|
|
195
|
+
} from "./cli-b5bq9crk.js";
|
|
188
196
|
import {
|
|
189
197
|
$OpenAPIRegistry,
|
|
190
198
|
$OpenApiGeneratorV31,
|
|
@@ -215,7 +223,7 @@ import {
|
|
|
215
223
|
PromptTemplateStateSchema,
|
|
216
224
|
ProviderNameSchema,
|
|
217
225
|
ReasoningEffortSchema,
|
|
218
|
-
|
|
226
|
+
RepoGuidelinesInputSchema,
|
|
219
227
|
RepoHooksSchema,
|
|
220
228
|
ScheduledTaskTargetTypeSchema,
|
|
221
229
|
ScriptRunStatusSchema,
|
|
@@ -431,13 +439,13 @@ import {
|
|
|
431
439
|
upsertPromptTemplate,
|
|
432
440
|
upsertService,
|
|
433
441
|
validateConfigValue
|
|
434
|
-
} from "./cli-
|
|
442
|
+
} from "./cli-ftht3zzj.js";
|
|
435
443
|
import {
|
|
436
444
|
generateDefaultClaudeMd,
|
|
437
445
|
generateDefaultIdentityMd,
|
|
438
446
|
generateDefaultSoulMd,
|
|
439
447
|
init_defaults
|
|
440
|
-
} from "./cli-
|
|
448
|
+
} from "./cli-y6b6fb76.js";
|
|
441
449
|
import {
|
|
442
450
|
getTemplateDefinition,
|
|
443
451
|
init_registry,
|
|
@@ -446,7 +454,7 @@ import {
|
|
|
446
454
|
interpolate,
|
|
447
455
|
registerTemplate,
|
|
448
456
|
resolveTemplate
|
|
449
|
-
} from "./cli-
|
|
457
|
+
} from "./cli-kpv03zhj.js";
|
|
450
458
|
import {
|
|
451
459
|
MAX_PROFILE_FILE_LENGTH,
|
|
452
460
|
getAppUrl,
|
|
@@ -507,7 +515,7 @@ import {
|
|
|
507
515
|
import {
|
|
508
516
|
init_package,
|
|
509
517
|
package_default
|
|
510
|
-
} from "./cli-
|
|
518
|
+
} from "./cli-w9kb3bk1.js";
|
|
511
519
|
import {
|
|
512
520
|
init_secret_scrubber,
|
|
513
521
|
refreshSecretScrubberCache,
|
|
@@ -22295,7 +22303,7 @@ async function notifySlack(text) {
|
|
|
22295
22303
|
return;
|
|
22296
22304
|
}
|
|
22297
22305
|
try {
|
|
22298
|
-
const { getSlackApp: getSlackApp2 } = await import("./app-
|
|
22306
|
+
const { getSlackApp: getSlackApp2 } = await import("./app-w066xfy0.js");
|
|
22299
22307
|
const app = getSlackApp2();
|
|
22300
22308
|
if (!app) {
|
|
22301
22309
|
console.warn("[Jira webhook keepalive] Slack not available, cannot send notification");
|
|
@@ -22366,7 +22374,7 @@ async function deleteJiraWebhook(webhookId) {
|
|
|
22366
22374
|
console.log(`[Jira webhook keepalive] Deleted webhook id=${webhookId}`);
|
|
22367
22375
|
}
|
|
22368
22376
|
async function overwriteWebhookIds(next) {
|
|
22369
|
-
const { getDbClient: getDbClient2 } = await import("./db-
|
|
22377
|
+
const { getDbClient: getDbClient2 } = await import("./db-sfbsc8wt.js");
|
|
22370
22378
|
await getDbClient2().transaction(async (tx) => {
|
|
22371
22379
|
const row = await tx.get("SELECT metadata FROM oauth_apps WHERE provider = 'jira'");
|
|
22372
22380
|
if (!row) {
|
|
@@ -95048,156 +95056,6 @@ function warnIfMcpBaseUrlLooksLikeAppUrl2() {
|
|
|
95048
95056
|
console.warn(`[Linear] WARNING: MCP_BASE_URL (${mcp}) equals APP_URL — surfaced webhook URL points at the dashboard host, not the API. Configure Linear with this URL only if the dashboard host also serves /api/*.`);
|
|
95049
95057
|
}
|
|
95050
95058
|
}
|
|
95051
|
-
// src/slack/files.ts
|
|
95052
|
-
import { createWriteStream } from "node:fs";
|
|
95053
|
-
import { mkdir } from "node:fs/promises";
|
|
95054
|
-
import { dirname } from "node:path";
|
|
95055
|
-
var MAX_FILE_SIZE = 1073741824;
|
|
95056
|
-
var DEFAULT_DOWNLOAD_DIR = `/workspace/shared/downloads/${process.env.AGENT_ID || "default"}/slack`;
|
|
95057
|
-
async function uploadFile(client, options) {
|
|
95058
|
-
const { file, filename, channelId, threadTs, initialComment, title } = options;
|
|
95059
|
-
try {
|
|
95060
|
-
if (Buffer.isBuffer(file) && file.length > MAX_FILE_SIZE) {
|
|
95061
|
-
return {
|
|
95062
|
-
success: false,
|
|
95063
|
-
error: `File size ${file.length} bytes exceeds maximum of ${MAX_FILE_SIZE} bytes (1 GB)`
|
|
95064
|
-
};
|
|
95065
|
-
}
|
|
95066
|
-
if (typeof file === "string") {
|
|
95067
|
-
const bunFile = Bun.file(file);
|
|
95068
|
-
const size = bunFile.size;
|
|
95069
|
-
if (size > MAX_FILE_SIZE) {
|
|
95070
|
-
return {
|
|
95071
|
-
success: false,
|
|
95072
|
-
error: `File size ${size} bytes exceeds maximum of ${MAX_FILE_SIZE} bytes (1 GB)`
|
|
95073
|
-
};
|
|
95074
|
-
}
|
|
95075
|
-
}
|
|
95076
|
-
const uploadArgs = {
|
|
95077
|
-
file,
|
|
95078
|
-
filename,
|
|
95079
|
-
title: title || filename
|
|
95080
|
-
};
|
|
95081
|
-
if (channelId) {
|
|
95082
|
-
uploadArgs.channel_id = channelId;
|
|
95083
|
-
if (threadTs) {
|
|
95084
|
-
uploadArgs.thread_ts = threadTs;
|
|
95085
|
-
}
|
|
95086
|
-
if (initialComment) {
|
|
95087
|
-
uploadArgs.initial_comment = initialComment;
|
|
95088
|
-
}
|
|
95089
|
-
}
|
|
95090
|
-
const result = await client.filesUploadV2(uploadArgs);
|
|
95091
|
-
const uploadedFile = result.files?.[0];
|
|
95092
|
-
const fileId = uploadedFile?.files?.[0]?.id;
|
|
95093
|
-
if (!fileId) {
|
|
95094
|
-
return {
|
|
95095
|
-
success: false,
|
|
95096
|
-
error: "Upload succeeded but no file ID returned"
|
|
95097
|
-
};
|
|
95098
|
-
}
|
|
95099
|
-
return {
|
|
95100
|
-
success: true,
|
|
95101
|
-
fileId
|
|
95102
|
-
};
|
|
95103
|
-
} catch (error) {
|
|
95104
|
-
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
95105
|
-
return {
|
|
95106
|
-
success: false,
|
|
95107
|
-
error: errorMsg
|
|
95108
|
-
};
|
|
95109
|
-
}
|
|
95110
|
-
}
|
|
95111
|
-
async function downloadFile(options) {
|
|
95112
|
-
const { file, savePath, token } = options;
|
|
95113
|
-
try {
|
|
95114
|
-
const downloadUrl = typeof file === "string" ? file : file.url_private_download;
|
|
95115
|
-
if (!downloadUrl) {
|
|
95116
|
-
return {
|
|
95117
|
-
success: false,
|
|
95118
|
-
error: "No download URL available for this file"
|
|
95119
|
-
};
|
|
95120
|
-
}
|
|
95121
|
-
let finalPath = savePath;
|
|
95122
|
-
if (typeof file !== "string" && (savePath.endsWith("/") || !savePath.includes("."))) {
|
|
95123
|
-
finalPath = savePath.endsWith("/") ? `${savePath}${file.name}` : `${savePath}/${file.name}`;
|
|
95124
|
-
}
|
|
95125
|
-
await mkdir(dirname(finalPath), { recursive: true });
|
|
95126
|
-
const response = await fetch(downloadUrl, {
|
|
95127
|
-
headers: {
|
|
95128
|
-
Authorization: `Bearer ${token}`
|
|
95129
|
-
}
|
|
95130
|
-
});
|
|
95131
|
-
if (!response.ok) {
|
|
95132
|
-
return {
|
|
95133
|
-
success: false,
|
|
95134
|
-
error: `HTTP error ${response.status}: ${response.statusText}`
|
|
95135
|
-
};
|
|
95136
|
-
}
|
|
95137
|
-
const body = response.body;
|
|
95138
|
-
if (!body) {
|
|
95139
|
-
return {
|
|
95140
|
-
success: false,
|
|
95141
|
-
error: "No response body"
|
|
95142
|
-
};
|
|
95143
|
-
}
|
|
95144
|
-
const writer = createWriteStream(finalPath);
|
|
95145
|
-
const reader = body.getReader();
|
|
95146
|
-
try {
|
|
95147
|
-
while (true) {
|
|
95148
|
-
const { done, value } = await reader.read();
|
|
95149
|
-
if (done)
|
|
95150
|
-
break;
|
|
95151
|
-
writer.write(value);
|
|
95152
|
-
}
|
|
95153
|
-
writer.end();
|
|
95154
|
-
} finally {
|
|
95155
|
-
reader.releaseLock();
|
|
95156
|
-
}
|
|
95157
|
-
await new Promise((resolve, reject) => {
|
|
95158
|
-
writer.on("finish", resolve);
|
|
95159
|
-
writer.on("error", reject);
|
|
95160
|
-
});
|
|
95161
|
-
return {
|
|
95162
|
-
success: true,
|
|
95163
|
-
savedPath: finalPath
|
|
95164
|
-
};
|
|
95165
|
-
} catch (error) {
|
|
95166
|
-
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
95167
|
-
return {
|
|
95168
|
-
success: false,
|
|
95169
|
-
error: errorMsg
|
|
95170
|
-
};
|
|
95171
|
-
}
|
|
95172
|
-
}
|
|
95173
|
-
async function getFileInfo(client, fileId) {
|
|
95174
|
-
try {
|
|
95175
|
-
const result = await client.files.info({ file: fileId });
|
|
95176
|
-
if (!result.file) {
|
|
95177
|
-
return null;
|
|
95178
|
-
}
|
|
95179
|
-
const f = result.file;
|
|
95180
|
-
return {
|
|
95181
|
-
id: f.id,
|
|
95182
|
-
name: f.name,
|
|
95183
|
-
title: f.title,
|
|
95184
|
-
mimetype: f.mimetype,
|
|
95185
|
-
filetype: f.filetype,
|
|
95186
|
-
size: f.size,
|
|
95187
|
-
url_private: f.url_private,
|
|
95188
|
-
url_private_download: f.url_private_download,
|
|
95189
|
-
thumb_64: f.thumb_64,
|
|
95190
|
-
thumb_80: f.thumb_80,
|
|
95191
|
-
thumb_160: f.thumb_160,
|
|
95192
|
-
thumb_360: f.thumb_360,
|
|
95193
|
-
thumb_480: f.thumb_480,
|
|
95194
|
-
user: f.user,
|
|
95195
|
-
created: f.created
|
|
95196
|
-
};
|
|
95197
|
-
} catch {
|
|
95198
|
-
return null;
|
|
95199
|
-
}
|
|
95200
|
-
}
|
|
95201
95059
|
// src/http/core.ts
|
|
95202
95060
|
init_request_auth_context();
|
|
95203
95061
|
init_secret_scrubber();
|
|
@@ -95421,6 +95279,12 @@ async function resolveHttpRequestAuth(req, apiKey) {
|
|
|
95421
95279
|
return { kind: "user", userId: user.id, user };
|
|
95422
95280
|
}
|
|
95423
95281
|
}
|
|
95282
|
+
if (bearer.startsWith("aseph_")) {
|
|
95283
|
+
const principal = await resolveBySessionToken(bearer);
|
|
95284
|
+
if (principal) {
|
|
95285
|
+
return { kind: "agent", agentId: principal.agentId, taskId: principal.taskId };
|
|
95286
|
+
}
|
|
95287
|
+
}
|
|
95424
95288
|
return null;
|
|
95425
95289
|
}
|
|
95426
95290
|
function isActiveUser(user) {
|
|
@@ -96016,7 +95880,7 @@ async function reloadGlobalConfigsAndIntegrations() {
|
|
|
96016
95880
|
}
|
|
96017
95881
|
async function reloadGlobalConfigsAndIntegrationsInner() {
|
|
96018
95882
|
const updated = await loadGlobalConfigsIntoEnv(true);
|
|
96019
|
-
const { resetFileStorageProvider } = await import("./registry-
|
|
95883
|
+
const { resetFileStorageProvider } = await import("./registry-v5wytg0s.js");
|
|
96020
95884
|
resetFileStorageProvider();
|
|
96021
95885
|
const integrations = [];
|
|
96022
95886
|
resetAgentMail();
|
|
@@ -96472,6 +96336,14 @@ var scriptRunNudge = (r) => {
|
|
|
96472
96336
|
const body = r.data?.data;
|
|
96473
96337
|
return !r.ok && body?.error === "timeout" ? SCRIPT_RUN_TIMEOUT_NUDGE : scriptAuthoringNudge(r);
|
|
96474
96338
|
};
|
|
96339
|
+
var SLACK_API_DISK_NUDGE = "That path is on the API server's disk, not in your container — call this from a task you own (or pass its taskId) to get the file as a task attachment with a fetchCommand.";
|
|
96340
|
+
var slackDownloadFileNudge = (r) => r.ok && r.data?.savedPath ? SLACK_API_DISK_NUDGE : undefined;
|
|
96341
|
+
var slackReadNudge = (r) => {
|
|
96342
|
+
if (!r.ok)
|
|
96343
|
+
return;
|
|
96344
|
+
const messages = r.data?.messages;
|
|
96345
|
+
return messages?.some((m) => m.files?.some((f) => Boolean(f.localPath))) ? SLACK_API_DISK_NUDGE : undefined;
|
|
96346
|
+
};
|
|
96475
96347
|
var workflowLongScriptTimeoutNudge = (r) => {
|
|
96476
96348
|
if (!r.ok)
|
|
96477
96349
|
return;
|
|
@@ -96479,6 +96351,7 @@ var workflowLongScriptTimeoutNudge = (r) => {
|
|
|
96479
96351
|
return hint ? WORKFLOW_LONG_SCRIPT_TIMEOUT_NUDGE : undefined;
|
|
96480
96352
|
};
|
|
96481
96353
|
var NUDGES = {
|
|
96354
|
+
"defer-task": (r) => r.ok ? "Stop working on this task now; the wake-up task will carry your note." : undefined,
|
|
96482
96355
|
"script-run": scriptRunNudge,
|
|
96483
96356
|
"script-upsert": scriptAuthoringNudge,
|
|
96484
96357
|
"launch-script-run": scriptAuthoringNudge,
|
|
@@ -96487,6 +96360,8 @@ var NUDGES = {
|
|
|
96487
96360
|
"update-workflow": workflowLongScriptTimeoutNudge,
|
|
96488
96361
|
"patch-workflow": workflowLongScriptTimeoutNudge,
|
|
96489
96362
|
"patch-workflow-node": workflowLongScriptTimeoutNudge,
|
|
96363
|
+
"slack-download-file": slackDownloadFileNudge,
|
|
96364
|
+
"slack-read": slackReadNudge,
|
|
96490
96365
|
"script-search": (r) => {
|
|
96491
96366
|
if (!r.ok)
|
|
96492
96367
|
return;
|
|
@@ -102028,8 +101903,8 @@ var registerCreatePageTool = (server) => {
|
|
|
102028
101903
|
key: AssetKeySchema.optional().describe("Logical namespace. Defaults to a shared/page:<id>/ resource key."),
|
|
102029
101904
|
title: string().min(1).describe("Human-readable title shown in listings."),
|
|
102030
101905
|
slug: string().min(1).optional().describe("URL slug. Defaults to the kebab-cased title. Same slug → updates the existing row."),
|
|
102031
|
-
body: string().min(1).describe("Full page body (HTML document or JSON-render spec, per contentType)."),
|
|
102032
|
-
contentType: PageContentTypeSchema.describe("'text/html'
|
|
101906
|
+
body: string().min(1).describe("Full page body (HTML document, SVG image, or JSON-render spec, per contentType)."),
|
|
101907
|
+
contentType: PageContentTypeSchema.describe("'text/html' and 'image/svg+xml' render directly at /p/:id; 'application/json' is rendered by the SPA."),
|
|
102033
101908
|
authMode: PageAuthModeSchema.default("authed").describe("'authed' — requires page-session cookie (default); 'public' — no gate and must be explicit; 'password' — requires key."),
|
|
102034
101909
|
password: string().min(1).optional().describe("Plaintext password, hashed before storage. Only meaningful for authMode='password'."),
|
|
102035
101910
|
description: string().optional().describe("Optional short description, used in listings + OG-tag unfurl."),
|
|
@@ -102728,6 +102603,688 @@ ${result.total} rows in ${result.elapsed}ms`;
|
|
|
102728
102603
|
});
|
|
102729
102604
|
};
|
|
102730
102605
|
|
|
102606
|
+
// src/tools/defer-task.ts
|
|
102607
|
+
init_zod();
|
|
102608
|
+
init_db();
|
|
102609
|
+
|
|
102610
|
+
// src/tasks/task-terminal-effects.ts
|
|
102611
|
+
init_db();
|
|
102612
|
+
|
|
102613
|
+
// src/be/memory/raters/retrieval.ts
|
|
102614
|
+
init_db();
|
|
102615
|
+
function dedupeMemoryDocumentIds(memories) {
|
|
102616
|
+
const documents = new Map;
|
|
102617
|
+
for (const memory of memories) {
|
|
102618
|
+
const identity = memory.sourcePath ?? memory.key;
|
|
102619
|
+
if (identity == null)
|
|
102620
|
+
continue;
|
|
102621
|
+
const documentKey = JSON.stringify([memory.agentId, memory.scope, identity]);
|
|
102622
|
+
if (!documents.has(documentKey))
|
|
102623
|
+
documents.set(documentKey, memory.id);
|
|
102624
|
+
}
|
|
102625
|
+
return [...documents.values()];
|
|
102626
|
+
}
|
|
102627
|
+
async function recordMemoryAccesses(memoryIds) {
|
|
102628
|
+
const ids = [...new Set(memoryIds)].filter(Boolean);
|
|
102629
|
+
if (ids.length === 0)
|
|
102630
|
+
return;
|
|
102631
|
+
const now = new Date().toISOString();
|
|
102632
|
+
await getDbClient().transaction(async (tx) => {
|
|
102633
|
+
for (const id of ids) {
|
|
102634
|
+
await tx.run("UPDATE agent_memory SET accessedAt = ?, accessCount = accessCount + 1 WHERE id = ?", [now, id]);
|
|
102635
|
+
}
|
|
102636
|
+
});
|
|
102637
|
+
}
|
|
102638
|
+
async function recordRetrievals(taskId, agentId, results, sessionId, extras) {
|
|
102639
|
+
if (!taskId || results.length === 0)
|
|
102640
|
+
return;
|
|
102641
|
+
const insertSql = `INSERT INTO memory_retrieval
|
|
102642
|
+
(id, taskId, agentId, sessionId, memoryId, similarity, retrievedAt, contextKey, intent, eventType, retrievalId, rank, retrievalSource)
|
|
102643
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`;
|
|
102644
|
+
const now = new Date().toISOString();
|
|
102645
|
+
const retrievalId = crypto.randomUUID();
|
|
102646
|
+
const contextKey = extras?.contextKey ?? null;
|
|
102647
|
+
const intent = extras?.intent ?? null;
|
|
102648
|
+
const eventType = extras?.eventType ?? "search";
|
|
102649
|
+
await getDbClient().transaction(async (tx) => {
|
|
102650
|
+
for (const [rank, r] of results.entries()) {
|
|
102651
|
+
await tx.run(insertSql, [
|
|
102652
|
+
crypto.randomUUID(),
|
|
102653
|
+
taskId,
|
|
102654
|
+
agentId,
|
|
102655
|
+
sessionId ?? null,
|
|
102656
|
+
r.memoryId,
|
|
102657
|
+
r.similarity,
|
|
102658
|
+
now,
|
|
102659
|
+
contextKey,
|
|
102660
|
+
intent,
|
|
102661
|
+
eventType,
|
|
102662
|
+
retrievalId,
|
|
102663
|
+
rank,
|
|
102664
|
+
r.retrievalSource ?? null
|
|
102665
|
+
]);
|
|
102666
|
+
}
|
|
102667
|
+
});
|
|
102668
|
+
ensure({
|
|
102669
|
+
id: "memory_retrieved",
|
|
102670
|
+
flow: "task",
|
|
102671
|
+
runId: taskId,
|
|
102672
|
+
data: {
|
|
102673
|
+
count: results.length,
|
|
102674
|
+
taskId,
|
|
102675
|
+
agentId
|
|
102676
|
+
},
|
|
102677
|
+
validator: (data) => typeof data.count === "number" && data.count > 0 && typeof data.taskId === "string" && data.taskId.length > 0 && typeof data.agentId === "string" && data.agentId.length > 0
|
|
102678
|
+
});
|
|
102679
|
+
}
|
|
102680
|
+
async function getRetrievalsForTask(taskId) {
|
|
102681
|
+
return getDbClient().query("SELECT memoryId, similarity FROM memory_retrieval WHERE taskId = ?", [taskId]);
|
|
102682
|
+
}
|
|
102683
|
+
|
|
102684
|
+
// src/be/memory/raters/explicit-self.ts
|
|
102685
|
+
class ExplicitSelfRatingRater {
|
|
102686
|
+
name = "explicit-self";
|
|
102687
|
+
async rate() {
|
|
102688
|
+
return [];
|
|
102689
|
+
}
|
|
102690
|
+
}
|
|
102691
|
+
|
|
102692
|
+
// src/be/memory/raters/implicit-citation.ts
|
|
102693
|
+
class ImplicitCitationRater {
|
|
102694
|
+
name = "implicit-citation";
|
|
102695
|
+
async rate(ctx) {
|
|
102696
|
+
if (ctx.retrievedMemoryIds.length === 0)
|
|
102697
|
+
return [];
|
|
102698
|
+
const evidence = ctx.evidence ?? "";
|
|
102699
|
+
const events = [];
|
|
102700
|
+
for (const memoryId of ctx.retrievedMemoryIds) {
|
|
102701
|
+
if (evidence.length > 0 && evidence.includes(memoryId)) {
|
|
102702
|
+
events.push({ memoryId, signal: 1, weight: 0.5, source: "" });
|
|
102703
|
+
} else {
|
|
102704
|
+
events.push({ memoryId, signal: -1, weight: 0.25, source: "" });
|
|
102705
|
+
}
|
|
102706
|
+
}
|
|
102707
|
+
return events;
|
|
102708
|
+
}
|
|
102709
|
+
}
|
|
102710
|
+
|
|
102711
|
+
// src/be/memory/raters/noop.ts
|
|
102712
|
+
class NoopRater {
|
|
102713
|
+
name = "noop";
|
|
102714
|
+
async rate() {
|
|
102715
|
+
return [];
|
|
102716
|
+
}
|
|
102717
|
+
}
|
|
102718
|
+
|
|
102719
|
+
// src/be/memory/raters/registry.ts
|
|
102720
|
+
var FACTORIES = {
|
|
102721
|
+
noop: () => new NoopRater,
|
|
102722
|
+
"implicit-citation": () => new ImplicitCitationRater,
|
|
102723
|
+
"explicit-self": () => new ExplicitSelfRatingRater,
|
|
102724
|
+
llm: () => new LlmRater
|
|
102725
|
+
};
|
|
102726
|
+
var SERVER_RATERS = new Set(["implicit-citation"]);
|
|
102727
|
+
function getRegisteredRaters() {
|
|
102728
|
+
const raw = process.env.MEMORY_RATERS;
|
|
102729
|
+
if (!raw || raw.trim() === "") {
|
|
102730
|
+
return [new NoopRater];
|
|
102731
|
+
}
|
|
102732
|
+
const names = raw.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
102733
|
+
const raters = [];
|
|
102734
|
+
for (const name of names) {
|
|
102735
|
+
const factory = FACTORIES[name];
|
|
102736
|
+
if (!factory) {
|
|
102737
|
+
console.warn(`[memory-rater] Unknown rater "${name}" in MEMORY_RATERS — skipping`);
|
|
102738
|
+
continue;
|
|
102739
|
+
}
|
|
102740
|
+
raters.push(factory());
|
|
102741
|
+
}
|
|
102742
|
+
if (raters.length === 0) {
|
|
102743
|
+
return [new NoopRater];
|
|
102744
|
+
}
|
|
102745
|
+
return raters;
|
|
102746
|
+
}
|
|
102747
|
+
function getRaterWeightMultiplier(name) {
|
|
102748
|
+
const raw = process.env.MEMORY_RATER_WEIGHTS;
|
|
102749
|
+
if (!raw || raw.trim() === "")
|
|
102750
|
+
return 1;
|
|
102751
|
+
for (const pair of raw.split(",")) {
|
|
102752
|
+
const trimmed = pair.trim();
|
|
102753
|
+
if (trimmed === "")
|
|
102754
|
+
continue;
|
|
102755
|
+
const [rawName, rawMult] = trimmed.split(":");
|
|
102756
|
+
if (!rawName || !rawMult)
|
|
102757
|
+
continue;
|
|
102758
|
+
if (rawName.trim() !== name)
|
|
102759
|
+
continue;
|
|
102760
|
+
const mult = Number(rawMult);
|
|
102761
|
+
if (Number.isFinite(mult) && mult >= 0)
|
|
102762
|
+
return mult;
|
|
102763
|
+
}
|
|
102764
|
+
return 1;
|
|
102765
|
+
}
|
|
102766
|
+
|
|
102767
|
+
// src/be/memory/raters/store.ts
|
|
102768
|
+
init_db();
|
|
102769
|
+
class ExplicitSelfDuplicateError extends Error {
|
|
102770
|
+
event;
|
|
102771
|
+
constructor(message, event) {
|
|
102772
|
+
super(message);
|
|
102773
|
+
this.event = event;
|
|
102774
|
+
this.name = "ExplicitSelfDuplicateError";
|
|
102775
|
+
}
|
|
102776
|
+
}
|
|
102777
|
+
async function applyRating(events, ctx = {}) {
|
|
102778
|
+
if (events.length === 0) {
|
|
102779
|
+
return { applied: 0, rejected: [] };
|
|
102780
|
+
}
|
|
102781
|
+
const accepted = [];
|
|
102782
|
+
const rejected = [];
|
|
102783
|
+
for (const event of events) {
|
|
102784
|
+
const reason = validate(event);
|
|
102785
|
+
if (reason) {
|
|
102786
|
+
rejected.push({ event, reason });
|
|
102787
|
+
continue;
|
|
102788
|
+
}
|
|
102789
|
+
let sanitizedReferencesSource = null;
|
|
102790
|
+
if (event.referencesSource !== undefined) {
|
|
102791
|
+
if (event.referencesSource.length === 0) {
|
|
102792
|
+
rejected.push({ event, reason: "referencesSource must be non-empty" });
|
|
102793
|
+
continue;
|
|
102794
|
+
}
|
|
102795
|
+
if (event.referencesSource.length > REFERENCES_SOURCE_MAX_LENGTH) {
|
|
102796
|
+
rejected.push({
|
|
102797
|
+
event,
|
|
102798
|
+
reason: `referencesSource exceeds ${REFERENCES_SOURCE_MAX_LENGTH} chars`
|
|
102799
|
+
});
|
|
102800
|
+
continue;
|
|
102801
|
+
}
|
|
102802
|
+
sanitizedReferencesSource = sanitizeReferencesSource(event.referencesSource);
|
|
102803
|
+
if (sanitizedReferencesSource === null) {
|
|
102804
|
+
rejected.push({
|
|
102805
|
+
event,
|
|
102806
|
+
reason: "referencesSource contains a NUL byte or strips to empty"
|
|
102807
|
+
});
|
|
102808
|
+
continue;
|
|
102809
|
+
}
|
|
102810
|
+
}
|
|
102811
|
+
accepted.push({ event, sanitizedReferencesSource });
|
|
102812
|
+
}
|
|
102813
|
+
if (accepted.length === 0) {
|
|
102814
|
+
return { applied: 0, rejected };
|
|
102815
|
+
}
|
|
102816
|
+
const UPDATE_MEMORY_SQL = "UPDATE agent_memory SET alpha = alpha + ?, beta = beta + ? WHERE id = ?";
|
|
102817
|
+
const CHECK_EXISTS_SQL = "SELECT id FROM agent_memory WHERE id = ?";
|
|
102818
|
+
const INSERT_RATING_SQL = `INSERT INTO memory_rating
|
|
102819
|
+
(id, memoryId, taskId, source, signal, weight, reasoning, createdAt, contextKey)
|
|
102820
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`;
|
|
102821
|
+
const UPSERT_EDGE_SQL = `INSERT INTO agent_memory_edge (from_id, to_id, type, alpha, beta, createdAt)
|
|
102822
|
+
VALUES (?, ?, 'references-source', ?, ?, ?)
|
|
102823
|
+
ON CONFLICT(from_id, to_id, type) DO UPDATE SET
|
|
102824
|
+
alpha = alpha + excluded.alpha - 1.0,
|
|
102825
|
+
beta = beta + excluded.beta - 1.0`;
|
|
102826
|
+
const { applied, lateRejects, appliedEvents } = await getDbClient().transaction(async (tx) => {
|
|
102827
|
+
let applied2 = 0;
|
|
102828
|
+
const lateRejects2 = [];
|
|
102829
|
+
const appliedEvents2 = [];
|
|
102830
|
+
for (const { event, sanitizedReferencesSource } of accepted) {
|
|
102831
|
+
const exists = await tx.get(CHECK_EXISTS_SQL, [event.memoryId]);
|
|
102832
|
+
if (!exists) {
|
|
102833
|
+
lateRejects2.push({ event, reason: "memoryId not found in agent_memory" });
|
|
102834
|
+
continue;
|
|
102835
|
+
}
|
|
102836
|
+
const alphaDelta = Math.max(0, event.signal) * event.weight;
|
|
102837
|
+
const betaDelta = Math.max(0, -event.signal) * event.weight;
|
|
102838
|
+
await tx.run(UPDATE_MEMORY_SQL, [alphaDelta, betaDelta, event.memoryId]);
|
|
102839
|
+
try {
|
|
102840
|
+
await tx.run(INSERT_RATING_SQL, [
|
|
102841
|
+
crypto.randomUUID(),
|
|
102842
|
+
event.memoryId,
|
|
102843
|
+
ctx.taskId ?? null,
|
|
102844
|
+
event.source,
|
|
102845
|
+
event.signal,
|
|
102846
|
+
event.weight,
|
|
102847
|
+
event.reasoning ?? null,
|
|
102848
|
+
new Date().toISOString(),
|
|
102849
|
+
ctx.contextKey ?? null
|
|
102850
|
+
]);
|
|
102851
|
+
} catch (err) {
|
|
102852
|
+
if (isUniqueConstraintError(err)) {
|
|
102853
|
+
throw new ExplicitSelfDuplicateError(`duplicate explicit-self rating for memoryId=${event.memoryId} taskId=${ctx.taskId}`, event);
|
|
102854
|
+
}
|
|
102855
|
+
throw err;
|
|
102856
|
+
}
|
|
102857
|
+
if (sanitizedReferencesSource !== null) {
|
|
102858
|
+
await tx.run(UPSERT_EDGE_SQL, [
|
|
102859
|
+
event.memoryId,
|
|
102860
|
+
sanitizedReferencesSource,
|
|
102861
|
+
1 + alphaDelta,
|
|
102862
|
+
1 + betaDelta,
|
|
102863
|
+
new Date().toISOString()
|
|
102864
|
+
]);
|
|
102865
|
+
}
|
|
102866
|
+
appliedEvents2.push({ event, sanitizedReferencesSource });
|
|
102867
|
+
applied2 += 1;
|
|
102868
|
+
}
|
|
102869
|
+
return { applied: applied2, lateRejects: lateRejects2, appliedEvents: appliedEvents2 };
|
|
102870
|
+
});
|
|
102871
|
+
if (ctx.taskId && appliedEvents.length > 0) {
|
|
102872
|
+
for (const { event, sanitizedReferencesSource } of appliedEvents) {
|
|
102873
|
+
ensure({
|
|
102874
|
+
id: "memory_rated",
|
|
102875
|
+
flow: "task",
|
|
102876
|
+
runId: ctx.taskId,
|
|
102877
|
+
data: {
|
|
102878
|
+
memoryId: event.memoryId,
|
|
102879
|
+
source: event.source,
|
|
102880
|
+
signal: event.signal,
|
|
102881
|
+
weight: event.weight,
|
|
102882
|
+
hasReferencesSource: sanitizedReferencesSource !== null
|
|
102883
|
+
},
|
|
102884
|
+
validator: (data) => typeof data.memoryId === "string" && data.memoryId.length > 0 && typeof data.source === "string" && data.source.length > 0 && typeof data.signal === "number" && data.signal >= -1 && data.signal <= 1 && typeof data.weight === "number" && data.weight >= 0 && data.weight <= 1
|
|
102885
|
+
});
|
|
102886
|
+
}
|
|
102887
|
+
}
|
|
102888
|
+
return { applied, rejected: [...rejected, ...lateRejects] };
|
|
102889
|
+
}
|
|
102890
|
+
function validate(event) {
|
|
102891
|
+
if (!event.source || event.source.trim() === "") {
|
|
102892
|
+
return "source is required";
|
|
102893
|
+
}
|
|
102894
|
+
if (!Number.isFinite(event.signal) || event.signal < -1 || event.signal > 1) {
|
|
102895
|
+
return "signal must be in [-1, +1]";
|
|
102896
|
+
}
|
|
102897
|
+
if (!Number.isFinite(event.weight) || event.weight < 0 || event.weight > 1) {
|
|
102898
|
+
return "weight must be in [0, 1]";
|
|
102899
|
+
}
|
|
102900
|
+
if (!event.memoryId) {
|
|
102901
|
+
return "memoryId is required";
|
|
102902
|
+
}
|
|
102903
|
+
return null;
|
|
102904
|
+
}
|
|
102905
|
+
function isUniqueConstraintError(err) {
|
|
102906
|
+
if (!(err instanceof Error))
|
|
102907
|
+
return false;
|
|
102908
|
+
return /UNIQUE constraint failed|SQLITE_CONSTRAINT/i.test(err.message);
|
|
102909
|
+
}
|
|
102910
|
+
|
|
102911
|
+
// src/be/memory/raters/run-server-raters.ts
|
|
102912
|
+
async function runServerRaters(input, deps = {}) {
|
|
102913
|
+
const result = { ratersFired: 0, outcomes: [] };
|
|
102914
|
+
if (input.retrievedMemoryIds.length === 0)
|
|
102915
|
+
return result;
|
|
102916
|
+
const allRaters = deps.raters ?? getRegisteredRaters();
|
|
102917
|
+
const allowed = deps.serverRaterNames ?? SERVER_RATERS;
|
|
102918
|
+
const weightFor = deps.weightMultiplierFor ?? getRaterWeightMultiplier;
|
|
102919
|
+
const applyFn = deps.applyRating ?? applyRating;
|
|
102920
|
+
const serverRaters = allRaters.filter((r) => allowed.has(r.name));
|
|
102921
|
+
for (const rater of serverRaters) {
|
|
102922
|
+
const events = await rater.rate({
|
|
102923
|
+
taskId: input.taskId,
|
|
102924
|
+
agentId: input.agentId,
|
|
102925
|
+
retrievedMemoryIds: input.retrievedMemoryIds,
|
|
102926
|
+
evidence: input.evidence
|
|
102927
|
+
});
|
|
102928
|
+
if (events.length === 0)
|
|
102929
|
+
continue;
|
|
102930
|
+
const multiplier = weightFor(rater.name);
|
|
102931
|
+
const stamped = events.map((e) => ({
|
|
102932
|
+
...e,
|
|
102933
|
+
source: rater.name,
|
|
102934
|
+
weight: Math.max(0, Math.min(1, e.weight * multiplier))
|
|
102935
|
+
}));
|
|
102936
|
+
const applied = await applyFn(stamped, { taskId: input.taskId });
|
|
102937
|
+
result.ratersFired += 1;
|
|
102938
|
+
result.outcomes.push({ rater: rater.name, events: stamped, result: applied });
|
|
102939
|
+
}
|
|
102940
|
+
return result;
|
|
102941
|
+
}
|
|
102942
|
+
|
|
102943
|
+
// src/memory/automatic-task-gate.ts
|
|
102944
|
+
var SCHEDULE_TAG_PREFIX = "schedule:";
|
|
102945
|
+
var AUTOMATIC_TASK_TYPES = new Set([
|
|
102946
|
+
"boot-triage",
|
|
102947
|
+
"heartbeat",
|
|
102948
|
+
"heartbeat-checklist",
|
|
102949
|
+
"health-check",
|
|
102950
|
+
"health-probe",
|
|
102951
|
+
"monitor",
|
|
102952
|
+
"monitoring"
|
|
102953
|
+
]);
|
|
102954
|
+
function isAutomaticOrRecurringTaskCompletion(task) {
|
|
102955
|
+
const tags = task.tags ?? [];
|
|
102956
|
+
const taskType = task.taskType?.toLowerCase();
|
|
102957
|
+
return task.source === "schedule" || task.source === "system" || tags.includes("scheduled") || tags.includes("auto-generated") || tags.some((tag) => tag.startsWith(SCHEDULE_TAG_PREFIX)) || taskType !== undefined && (AUTOMATIC_TASK_TYPES.has(taskType) || taskType.endsWith("-monitor") || taskType.endsWith("-digest"));
|
|
102958
|
+
}
|
|
102959
|
+
function shouldPersistAutomaticTaskMemory(task, persistMemory) {
|
|
102960
|
+
if (persistMemory)
|
|
102961
|
+
return true;
|
|
102962
|
+
return !isAutomaticOrRecurringTaskCompletion(task);
|
|
102963
|
+
}
|
|
102964
|
+
var shouldPersistTaskCompletionMemory = shouldPersistAutomaticTaskMemory;
|
|
102965
|
+
|
|
102966
|
+
// src/tasks/task-terminal-effects.ts
|
|
102967
|
+
init_secret_scrubber();
|
|
102968
|
+
async function runTaskTerminalEffects(args) {
|
|
102969
|
+
const { task, status, output, failureReason, agentId, persistMemory } = args;
|
|
102970
|
+
const taskId = task.id;
|
|
102971
|
+
if (shouldPersistTaskCompletionMemory(task, persistMemory)) {
|
|
102972
|
+
(async () => {
|
|
102973
|
+
try {
|
|
102974
|
+
const taskContent = status === "completed" ? `Task: ${task.task}
|
|
102975
|
+
|
|
102976
|
+
Output:
|
|
102977
|
+
${output || "(no output)"}` : `Task: ${task.task}
|
|
102978
|
+
|
|
102979
|
+
Failure reason:
|
|
102980
|
+
${failureReason || "No reason provided"}
|
|
102981
|
+
|
|
102982
|
+
This task failed. Learn from this to avoid repeating the mistake.`;
|
|
102983
|
+
if (taskContent.length < 30)
|
|
102984
|
+
return;
|
|
102985
|
+
const store = getMemoryStore();
|
|
102986
|
+
const provider = getEmbeddingProvider();
|
|
102987
|
+
const memory = await store.store({
|
|
102988
|
+
agentId: agentId ?? null,
|
|
102989
|
+
content: taskContent,
|
|
102990
|
+
name: `Task: ${task.task.slice(0, 80)}`,
|
|
102991
|
+
scope: "agent",
|
|
102992
|
+
source: "task_completion",
|
|
102993
|
+
sourceTaskId: taskId
|
|
102994
|
+
});
|
|
102995
|
+
const embedding = await provider.embed(taskContent);
|
|
102996
|
+
if (embedding) {
|
|
102997
|
+
await store.updateEmbedding(memory.id, embedding, provider.name);
|
|
102998
|
+
}
|
|
102999
|
+
const shouldShareWithSwarm = status === "completed" && (task.taskType === "research" || task.tags?.includes("knowledge") || task.tags?.includes("shared"));
|
|
103000
|
+
if (shouldShareWithSwarm) {
|
|
103001
|
+
try {
|
|
103002
|
+
const swarmMemory = await store.store({
|
|
103003
|
+
agentId: agentId ?? null,
|
|
103004
|
+
scope: "swarm",
|
|
103005
|
+
name: `Shared: ${task.task.slice(0, 80)}`,
|
|
103006
|
+
content: `Task completed by agent ${agentId}:
|
|
103007
|
+
|
|
103008
|
+
${taskContent}`,
|
|
103009
|
+
source: "task_completion",
|
|
103010
|
+
sourceTaskId: taskId
|
|
103011
|
+
});
|
|
103012
|
+
const swarmEmbedding = await provider.embed(taskContent);
|
|
103013
|
+
if (swarmEmbedding) {
|
|
103014
|
+
await store.updateEmbedding(swarmMemory.id, swarmEmbedding, provider.name);
|
|
103015
|
+
}
|
|
103016
|
+
} catch {}
|
|
103017
|
+
}
|
|
103018
|
+
} catch {}
|
|
103019
|
+
})().catch((err) => console.error("[task-terminal-effects] task completion memory write failed:", scrubSecrets(err instanceof Error ? err.message : String(err))));
|
|
103020
|
+
}
|
|
103021
|
+
(async () => {
|
|
103022
|
+
try {
|
|
103023
|
+
const retrievals = await getRetrievalsForTask(taskId);
|
|
103024
|
+
if (retrievals.length === 0)
|
|
103025
|
+
return;
|
|
103026
|
+
const retrievedMemoryIds = retrievals.map((r) => r.memoryId);
|
|
103027
|
+
const logs = await getSessionLogsByTaskId(taskId);
|
|
103028
|
+
const evidence = logs.map((l) => l.content).join(`
|
|
103029
|
+
`);
|
|
103030
|
+
await runServerRaters({
|
|
103031
|
+
taskId,
|
|
103032
|
+
agentId: agentId ?? "",
|
|
103033
|
+
retrievedMemoryIds,
|
|
103034
|
+
evidence
|
|
103035
|
+
});
|
|
103036
|
+
} catch (err) {
|
|
103037
|
+
console.error("[task-terminal-effects] server-rater fire failed:", err instanceof Error ? err.message : String(err));
|
|
103038
|
+
}
|
|
103039
|
+
})().catch((err) => console.error("[task-terminal-effects] server rater run failed:", scrubSecrets(err instanceof Error ? err.message : String(err))));
|
|
103040
|
+
if (!task.workflowRunId) {
|
|
103041
|
+
try {
|
|
103042
|
+
const followUp = await createWorkerTaskFollowUp({ task, status, output, failureReason });
|
|
103043
|
+
if (followUp) {
|
|
103044
|
+
console.log(`[task-terminal-effects] Created follow-up task ${followUp.id.slice(0, 8)} for ${status} task ${taskId.slice(0, 8)}`);
|
|
103045
|
+
}
|
|
103046
|
+
} catch (err) {
|
|
103047
|
+
console.warn(`[task-terminal-effects] Failed to create follow-up task: ${err}`);
|
|
103048
|
+
}
|
|
103049
|
+
}
|
|
103050
|
+
}
|
|
103051
|
+
|
|
103052
|
+
// src/tasks/terminal-result-guard.ts
|
|
103053
|
+
init_db();
|
|
103054
|
+
init_types();
|
|
103055
|
+
init_secret_scrubber();
|
|
103056
|
+
function getTaskOutputValidationError(outputSchema, output) {
|
|
103057
|
+
if (!outputSchema || typeof outputSchema !== "object")
|
|
103058
|
+
return;
|
|
103059
|
+
const schema = outputSchema;
|
|
103060
|
+
if (!output) {
|
|
103061
|
+
return `Task has an outputSchema but no output was provided. You must call store-progress with a valid JSON output matching this schema:
|
|
103062
|
+
${JSON.stringify(schema, null, 2)}`;
|
|
103063
|
+
}
|
|
103064
|
+
let parsed;
|
|
103065
|
+
try {
|
|
103066
|
+
parsed = JSON.parse(output);
|
|
103067
|
+
} catch {
|
|
103068
|
+
return `Task output must be valid JSON matching the outputSchema. Got invalid JSON. Schema:
|
|
103069
|
+
${JSON.stringify(schema, null, 2)}`;
|
|
103070
|
+
}
|
|
103071
|
+
let validationErrors;
|
|
103072
|
+
try {
|
|
103073
|
+
validationErrors = validateJsonSchema(schema, parsed);
|
|
103074
|
+
} catch (error) {
|
|
103075
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
103076
|
+
return `Task outputSchema is malformed and cannot be validated (${detail}). Ask an operator to correct the task's outputSchema, or force-complete with store-progress force: true.`;
|
|
103077
|
+
}
|
|
103078
|
+
if (validationErrors.length > 0) {
|
|
103079
|
+
return `Task output does not match the outputSchema. Errors:
|
|
103080
|
+
${validationErrors.join(`
|
|
103081
|
+
`)}
|
|
103082
|
+
|
|
103083
|
+
Expected schema:
|
|
103084
|
+
${JSON.stringify(schema, null, 2)}
|
|
103085
|
+
|
|
103086
|
+
Please fix your output and retry.`;
|
|
103087
|
+
}
|
|
103088
|
+
return;
|
|
103089
|
+
}
|
|
103090
|
+
async function guardTerminalTaskResultWrite(task, write) {
|
|
103091
|
+
if (!isTerminalTaskStatus(task.status) || !write.status && !write.force) {
|
|
103092
|
+
return { handled: false };
|
|
103093
|
+
}
|
|
103094
|
+
const scrubbedOutput = write.output !== undefined ? scrubSecrets(write.output) : undefined;
|
|
103095
|
+
const scrubbedFailureReason = write.failureReason !== undefined ? scrubSecrets(write.failureReason) : undefined;
|
|
103096
|
+
const hasDifferingOutput = scrubbedOutput !== undefined && scrubbedOutput !== task.output;
|
|
103097
|
+
const hasDifferingFailureReason = scrubbedFailureReason !== undefined && scrubbedFailureReason !== task.failureReason;
|
|
103098
|
+
const hasDifferingResultText = hasDifferingOutput || hasDifferingFailureReason;
|
|
103099
|
+
if (hasDifferingResultText && write.force) {
|
|
103100
|
+
const outputValidationError = hasDifferingOutput ? getTaskOutputValidationError(task.outputSchema, write.output) : undefined;
|
|
103101
|
+
if (outputValidationError) {
|
|
103102
|
+
return { handled: true, success: false, message: outputValidationError, task };
|
|
103103
|
+
}
|
|
103104
|
+
const overwrittenTask = await overwriteTerminalTaskResultText(task.id, {
|
|
103105
|
+
...write.output !== undefined ? { output: write.output } : {},
|
|
103106
|
+
...write.failureReason !== undefined ? { failureReason: write.failureReason } : {}
|
|
103107
|
+
});
|
|
103108
|
+
if (!overwrittenTask) {
|
|
103109
|
+
return {
|
|
103110
|
+
handled: true,
|
|
103111
|
+
success: false,
|
|
103112
|
+
message: `Task "${task.id}" terminal result text could not be overwritten.`,
|
|
103113
|
+
task
|
|
103114
|
+
};
|
|
103115
|
+
}
|
|
103116
|
+
return {
|
|
103117
|
+
handled: true,
|
|
103118
|
+
success: true,
|
|
103119
|
+
message: `Task "${task.id}" is already ${task.status}; force-overwrote terminal result text ` + "without replaying completion side effects.",
|
|
103120
|
+
task: overwrittenTask,
|
|
103121
|
+
wasForcedOverwrite: true
|
|
103122
|
+
};
|
|
103123
|
+
}
|
|
103124
|
+
if (hasDifferingResultText) {
|
|
103125
|
+
return {
|
|
103126
|
+
handled: true,
|
|
103127
|
+
success: false,
|
|
103128
|
+
message: `Discarded write for already-${task.status} task "${task.id}"; ` + "existing output/failureReason and finishedAt were preserved. Retry with force: true " + "to overwrite terminal result text without replaying completion side effects.",
|
|
103129
|
+
task
|
|
103130
|
+
};
|
|
103131
|
+
}
|
|
103132
|
+
return {
|
|
103133
|
+
handled: true,
|
|
103134
|
+
success: true,
|
|
103135
|
+
message: `Task "${task.id}" is already ${task.status}; treating as no-op. ` + "Existing output preserved (first-call-wins).",
|
|
103136
|
+
task,
|
|
103137
|
+
wasNoOp: true
|
|
103138
|
+
};
|
|
103139
|
+
}
|
|
103140
|
+
|
|
103141
|
+
// src/tools/defer-task.ts
|
|
103142
|
+
init_types();
|
|
103143
|
+
|
|
103144
|
+
class DeferAbortedError extends Error {
|
|
103145
|
+
}
|
|
103146
|
+
function renderChecks(checks2) {
|
|
103147
|
+
if (!checks2 || checks2.length === 0)
|
|
103148
|
+
return "";
|
|
103149
|
+
return `
|
|
103150
|
+
|
|
103151
|
+
Checks:
|
|
103152
|
+
${checks2.map((c) => `- ${c}`).join(`
|
|
103153
|
+
`)}`;
|
|
103154
|
+
}
|
|
103155
|
+
var registerDeferTaskTool = (server) => {
|
|
103156
|
+
createToolRegistrar(server)("defer-task", {
|
|
103157
|
+
title: "Defer Task",
|
|
103158
|
+
annotations: { destructiveHint: false, idempotentHint: false },
|
|
103159
|
+
description: "Completes this task now with status `completed` and books a wake-up for you. Use when the result needs time: a build, a deploy, a reply. The task reaches its final state on this call; the lead sees your summary as its output. A one-off schedule wakes you up later with a child task that carries this task as its parent. Provide delayMs or runAt, a summary of what you did, and a note that says what is pending and what to check.",
|
|
103160
|
+
inputSchema: object({
|
|
103161
|
+
taskId: string().describe("The ID of the task you are working on."),
|
|
103162
|
+
delayMs: number().int().positive().optional().describe("Wake up after this many milliseconds (e.g. 1800000 for 30 min)."),
|
|
103163
|
+
runAt: string().datetime().optional().describe("Wake up at this ISO datetime (e.g. '2026-03-06T15:00:00Z'). Must be future."),
|
|
103164
|
+
summary: string().min(1).max(4000).describe("What you did so far and where things stand. This becomes the task's output; the lead and your wake-up run both read it."),
|
|
103165
|
+
note: string().min(1).max(2000).describe("What is pending, and what to check on wake-up."),
|
|
103166
|
+
checks: array(string().min(1)).max(20).optional().describe("Concrete things to verify on wake-up, one per entry.")
|
|
103167
|
+
}),
|
|
103168
|
+
outputSchema: swarmToolOutputSchema({
|
|
103169
|
+
yourAgentId: string().optional(),
|
|
103170
|
+
taskId: string().optional(),
|
|
103171
|
+
scheduleId: string().optional(),
|
|
103172
|
+
nextRunAt: string().optional()
|
|
103173
|
+
})
|
|
103174
|
+
}, async ({ taskId, delayMs, runAt, summary, note, checks: checks2 }, requestInfo, _meta) => {
|
|
103175
|
+
if (!requestInfo.agentId) {
|
|
103176
|
+
return toolErr('Agent ID not found. Set the "X-Agent-ID" header.');
|
|
103177
|
+
}
|
|
103178
|
+
const agent = await getAgentById(requestInfo.agentId);
|
|
103179
|
+
if (!agent) {
|
|
103180
|
+
return toolErr(`Agent not found: ${requestInfo.agentId}`);
|
|
103181
|
+
}
|
|
103182
|
+
const task = await getTaskById(taskId);
|
|
103183
|
+
if (!task) {
|
|
103184
|
+
return toolErr(`Task with ID "${taskId}" not found.`);
|
|
103185
|
+
}
|
|
103186
|
+
const forbidden = assertOwnsTask(ownerCtx(requestInfo), task);
|
|
103187
|
+
if (forbidden)
|
|
103188
|
+
return forbidden;
|
|
103189
|
+
if (task.agentId !== requestInfo.agentId) {
|
|
103190
|
+
return toolErr(`Task "${taskId}" is not assigned to you.`);
|
|
103191
|
+
}
|
|
103192
|
+
if (isTerminalTaskStatus(task.status)) {
|
|
103193
|
+
return toolErr(`Task ${taskId} is already ${task.status}; nothing to defer.`);
|
|
103194
|
+
}
|
|
103195
|
+
if (task.workflowRunId) {
|
|
103196
|
+
return toolErr(`Task ${taskId} is owned by workflow run ${task.workflowRunId}; workflow-owned tasks cannot be deferred.`);
|
|
103197
|
+
}
|
|
103198
|
+
if (!delayMs && !runAt) {
|
|
103199
|
+
return toolErr("Provide either delayMs or runAt.");
|
|
103200
|
+
}
|
|
103201
|
+
if (delayMs && runAt) {
|
|
103202
|
+
return toolErr("Provide either delayMs or runAt, not both.");
|
|
103203
|
+
}
|
|
103204
|
+
if (runAt && new Date(runAt).getTime() <= Date.now()) {
|
|
103205
|
+
return toolErr("runAt must be in the future.");
|
|
103206
|
+
}
|
|
103207
|
+
const nextRunAt = delayMs ? new Date(Date.now() + delayMs).toISOString() : runAt;
|
|
103208
|
+
const checksBlock = renderChecks(checks2);
|
|
103209
|
+
const taskTemplate = `Resume task ${taskId}: ${note}${checksBlock}`;
|
|
103210
|
+
const createdBy = await resolveTaskAuditUserId(requestInfo.sourceTaskId, requestInfo.agentId) ?? undefined;
|
|
103211
|
+
const previewOutput = `${summary}
|
|
103212
|
+
|
|
103213
|
+
Deferred until ${nextRunAt} (schedule pending). Pending: ${note}${checksBlock}`;
|
|
103214
|
+
const outputValidationError = getTaskOutputValidationError(task.outputSchema, previewOutput);
|
|
103215
|
+
if (outputValidationError) {
|
|
103216
|
+
return toolErr(`Task ${taskId} has an outputSchema; its terminal output must satisfy it, but a deferral note cannot. ${outputValidationError}`);
|
|
103217
|
+
}
|
|
103218
|
+
try {
|
|
103219
|
+
const committed = await getDbClient().transaction(async () => {
|
|
103220
|
+
const schedule = await createScheduledTask({
|
|
103221
|
+
name: `deferred-${taskId.slice(0, 8)}-${Date.now()}-${crypto.randomUUID()}`,
|
|
103222
|
+
description: note,
|
|
103223
|
+
taskTemplate,
|
|
103224
|
+
targetType: "agent-task",
|
|
103225
|
+
scheduleType: "one_time",
|
|
103226
|
+
nextRunAt,
|
|
103227
|
+
targetAgentId: requestInfo.agentId,
|
|
103228
|
+
createdByAgentId: requestInfo.agentId,
|
|
103229
|
+
taskType: "deferred",
|
|
103230
|
+
tags: ["deferred"],
|
|
103231
|
+
priority: task.priority,
|
|
103232
|
+
modelTier: task.modelTier,
|
|
103233
|
+
parentTaskId: taskId,
|
|
103234
|
+
createdBy
|
|
103235
|
+
});
|
|
103236
|
+
const output = `${summary}
|
|
103237
|
+
|
|
103238
|
+
Deferred until ${nextRunAt} (schedule ${schedule.id}). Pending: ${note}${checksBlock}`;
|
|
103239
|
+
const completed = await completeTask(taskId, output);
|
|
103240
|
+
if (!completed) {
|
|
103241
|
+
throw new DeferAbortedError(`Task ${taskId} reached a terminal state before this deferral committed.`);
|
|
103242
|
+
}
|
|
103243
|
+
getDbClient().afterCommit(() => {
|
|
103244
|
+
ensure({
|
|
103245
|
+
id: "completed",
|
|
103246
|
+
flow: "task",
|
|
103247
|
+
runId: taskId,
|
|
103248
|
+
depIds: task.wasPaused ? ["started", "resumed"] : ["started"],
|
|
103249
|
+
data: {
|
|
103250
|
+
taskId,
|
|
103251
|
+
agentId: task.agentId,
|
|
103252
|
+
previousStatus: task.status,
|
|
103253
|
+
hasOutput: true
|
|
103254
|
+
},
|
|
103255
|
+
validator: (data) => data.previousStatus === "in_progress",
|
|
103256
|
+
filter: ({}, ctx) => ctx.deps.length > 0,
|
|
103257
|
+
conditions: [{ timeout_ms: 3600000 }]
|
|
103258
|
+
});
|
|
103259
|
+
});
|
|
103260
|
+
if (task.agentId) {
|
|
103261
|
+
await updateAgentStatusFromCapacity(task.agentId);
|
|
103262
|
+
}
|
|
103263
|
+
return { scheduleId: schedule.id, output, completed };
|
|
103264
|
+
});
|
|
103265
|
+
await runTaskTerminalEffects({
|
|
103266
|
+
task: committed.completed,
|
|
103267
|
+
status: "completed",
|
|
103268
|
+
output: committed.output,
|
|
103269
|
+
agentId: requestInfo.agentId
|
|
103270
|
+
});
|
|
103271
|
+
return toolOk(`Task ${taskId} completed and deferred. Wake-up at ${nextRunAt} (schedule ${committed.scheduleId}). This task is final; the wake-up task continues the work.`, {
|
|
103272
|
+
data: {
|
|
103273
|
+
yourAgentId: requestInfo.agentId,
|
|
103274
|
+
taskId,
|
|
103275
|
+
scheduleId: committed.scheduleId,
|
|
103276
|
+
nextRunAt
|
|
103277
|
+
}
|
|
103278
|
+
});
|
|
103279
|
+
} catch (error) {
|
|
103280
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
103281
|
+
return toolErr(`Failed to defer task: ${message}`, {
|
|
103282
|
+
data: { yourAgentId: requestInfo.agentId, taskId }
|
|
103283
|
+
});
|
|
103284
|
+
}
|
|
103285
|
+
});
|
|
103286
|
+
};
|
|
103287
|
+
|
|
102731
103288
|
// src/tools/delete-channel.ts
|
|
102732
103289
|
init_zod();
|
|
102733
103290
|
init_db();
|
|
@@ -104891,77 +105448,6 @@ async function getLinksForMemory(memoryId, options = {}) {
|
|
|
104891
105448
|
return { links, backlinks };
|
|
104892
105449
|
}
|
|
104893
105450
|
|
|
104894
|
-
// src/be/memory/raters/retrieval.ts
|
|
104895
|
-
init_db();
|
|
104896
|
-
function dedupeMemoryDocumentIds(memories) {
|
|
104897
|
-
const documents = new Map;
|
|
104898
|
-
for (const memory of memories) {
|
|
104899
|
-
const identity = memory.sourcePath ?? memory.key;
|
|
104900
|
-
if (identity == null)
|
|
104901
|
-
continue;
|
|
104902
|
-
const documentKey = JSON.stringify([memory.agentId, memory.scope, identity]);
|
|
104903
|
-
if (!documents.has(documentKey))
|
|
104904
|
-
documents.set(documentKey, memory.id);
|
|
104905
|
-
}
|
|
104906
|
-
return [...documents.values()];
|
|
104907
|
-
}
|
|
104908
|
-
async function recordMemoryAccesses(memoryIds) {
|
|
104909
|
-
const ids = [...new Set(memoryIds)].filter(Boolean);
|
|
104910
|
-
if (ids.length === 0)
|
|
104911
|
-
return;
|
|
104912
|
-
const now = new Date().toISOString();
|
|
104913
|
-
await getDbClient().transaction(async (tx) => {
|
|
104914
|
-
for (const id of ids) {
|
|
104915
|
-
await tx.run("UPDATE agent_memory SET accessedAt = ?, accessCount = accessCount + 1 WHERE id = ?", [now, id]);
|
|
104916
|
-
}
|
|
104917
|
-
});
|
|
104918
|
-
}
|
|
104919
|
-
async function recordRetrievals(taskId, agentId, results, sessionId, extras) {
|
|
104920
|
-
if (!taskId || results.length === 0)
|
|
104921
|
-
return;
|
|
104922
|
-
const insertSql = `INSERT INTO memory_retrieval
|
|
104923
|
-
(id, taskId, agentId, sessionId, memoryId, similarity, retrievedAt, contextKey, intent, eventType, retrievalId, rank, retrievalSource)
|
|
104924
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`;
|
|
104925
|
-
const now = new Date().toISOString();
|
|
104926
|
-
const retrievalId = crypto.randomUUID();
|
|
104927
|
-
const contextKey = extras?.contextKey ?? null;
|
|
104928
|
-
const intent = extras?.intent ?? null;
|
|
104929
|
-
const eventType = extras?.eventType ?? "search";
|
|
104930
|
-
await getDbClient().transaction(async (tx) => {
|
|
104931
|
-
for (const [rank, r] of results.entries()) {
|
|
104932
|
-
await tx.run(insertSql, [
|
|
104933
|
-
crypto.randomUUID(),
|
|
104934
|
-
taskId,
|
|
104935
|
-
agentId,
|
|
104936
|
-
sessionId ?? null,
|
|
104937
|
-
r.memoryId,
|
|
104938
|
-
r.similarity,
|
|
104939
|
-
now,
|
|
104940
|
-
contextKey,
|
|
104941
|
-
intent,
|
|
104942
|
-
eventType,
|
|
104943
|
-
retrievalId,
|
|
104944
|
-
rank,
|
|
104945
|
-
r.retrievalSource ?? null
|
|
104946
|
-
]);
|
|
104947
|
-
}
|
|
104948
|
-
});
|
|
104949
|
-
ensure({
|
|
104950
|
-
id: "memory_retrieved",
|
|
104951
|
-
flow: "task",
|
|
104952
|
-
runId: taskId,
|
|
104953
|
-
data: {
|
|
104954
|
-
count: results.length,
|
|
104955
|
-
taskId,
|
|
104956
|
-
agentId
|
|
104957
|
-
},
|
|
104958
|
-
validator: (data) => typeof data.count === "number" && data.count > 0 && typeof data.taskId === "string" && data.taskId.length > 0 && typeof data.agentId === "string" && data.agentId.length > 0
|
|
104959
|
-
});
|
|
104960
|
-
}
|
|
104961
|
-
async function getRetrievalsForTask(taskId) {
|
|
104962
|
-
return getDbClient().query("SELECT memoryId, similarity FROM memory_retrieval WHERE taskId = ?", [taskId]);
|
|
104963
|
-
}
|
|
104964
|
-
|
|
104965
105451
|
// src/tools/memory-get.ts
|
|
104966
105452
|
init_types();
|
|
104967
105453
|
var NUDGE_ELIGIBLE_SOURCES = new Set(["manual", "file_index"]);
|
|
@@ -107116,7 +107602,7 @@ var registerUpdateRepoTool = (server) => {
|
|
|
107116
107602
|
defaultBranch: string().optional().describe("New default branch."),
|
|
107117
107603
|
autoClone: boolean().optional().describe("Whether to auto-clone."),
|
|
107118
107604
|
hooks: RepoHooksSchema.nullable().optional().describe("Repository hook install config. Set { enabled: true } to opt into best-effort worker hook installation, or null to disable."),
|
|
107119
|
-
guidelines:
|
|
107605
|
+
guidelines: RepoGuidelinesInputSchema.nullable().optional().describe("Repository guidelines: prChecks (commands before PR), mergeChecks (conditions before merge), allowMerge (default false), review (guidance for reviewers). Pass null to clear.")
|
|
107120
107606
|
}),
|
|
107121
107607
|
outputSchema: swarmToolOutputSchema({
|
|
107122
107608
|
repo: swarmRepoOutputShape2.nullable().optional()
|
|
@@ -113708,6 +114194,7 @@ var scheduleDataShape = {
|
|
|
113708
114194
|
lastRunAt: string().optional(),
|
|
113709
114195
|
nextRunAt: string().optional(),
|
|
113710
114196
|
createdByAgentId: string().optional(),
|
|
114197
|
+
parentTaskId: string().optional(),
|
|
113711
114198
|
timezone: string().optional(),
|
|
113712
114199
|
model: string().optional(),
|
|
113713
114200
|
modelTier: ModelTierSchema.optional(),
|
|
@@ -114120,6 +114607,7 @@ var scheduleRowShape = {
|
|
|
114120
114607
|
lastRunAt: string().optional(),
|
|
114121
114608
|
nextRunAt: string().optional(),
|
|
114122
114609
|
createdByAgentId: string().optional(),
|
|
114610
|
+
parentTaskId: string().optional(),
|
|
114123
114611
|
timezone: string().optional(),
|
|
114124
114612
|
consecutiveErrors: number().optional(),
|
|
114125
114613
|
lastErrorAt: string().optional(),
|
|
@@ -114258,6 +114746,7 @@ var scheduleDataShape2 = {
|
|
|
114258
114746
|
lastRunAt: string().optional(),
|
|
114259
114747
|
nextRunAt: string().optional(),
|
|
114260
114748
|
createdByAgentId: string().optional(),
|
|
114749
|
+
parentTaskId: string().optional(),
|
|
114261
114750
|
timezone: string().optional(),
|
|
114262
114751
|
model: string().optional(),
|
|
114263
114752
|
modelTier: ModelTierSchema.optional(),
|
|
@@ -114544,6 +115033,7 @@ var scheduleDataShape3 = {
|
|
|
114544
115033
|
lastRunAt: string().optional(),
|
|
114545
115034
|
nextRunAt: string().optional(),
|
|
114546
115035
|
createdByAgentId: string().optional(),
|
|
115036
|
+
parentTaskId: string().optional(),
|
|
114547
115037
|
timezone: string().optional(),
|
|
114548
115038
|
model: string().optional(),
|
|
114549
115039
|
modelTier: ModelTierSchema.optional(),
|
|
@@ -117100,19 +117590,26 @@ var registerSlackDeleteTool = (server) => {
|
|
|
117100
117590
|
// src/tools/slack-download-file.ts
|
|
117101
117591
|
init_zod();
|
|
117102
117592
|
init_db();
|
|
117593
|
+
function fileIdFromUrl(url) {
|
|
117594
|
+
return /\/files-pri\/[A-Z0-9]+-([A-Z0-9]+)\//.exec(url)?.[1];
|
|
117595
|
+
}
|
|
117103
117596
|
var registerSlackDownloadFileTool = (server) => {
|
|
117104
117597
|
createToolRegistrar(server)("slack-download-file", {
|
|
117105
117598
|
title: "Download file from Slack",
|
|
117106
|
-
description: "Download a file from Slack by file ID or URL.
|
|
117107
|
-
annotations: { readOnlyHint:
|
|
117599
|
+
description: "Download a file from Slack by file ID or URL. From a task, the file is stored as an attachment of that task and the result carries a ready-to-run `fetchCommand` to get the bytes into your container. Without a task, the file is saved on the API server's disk, which your container usually can't read.",
|
|
117600
|
+
annotations: { readOnlyHint: false, openWorldHint: true },
|
|
117108
117601
|
inputSchema: object({
|
|
117109
117602
|
fileId: string().optional().describe("The Slack file ID to download (e.g., 'F0RDC39U1')."),
|
|
117110
117603
|
url: string().url().optional().describe("Direct URL to download (url_private_download from a file object)."),
|
|
117111
|
-
|
|
117604
|
+
taskId: uuid().optional().describe("Task to attach the file to. Defaults to the task you are working on; must be a task you own or created."),
|
|
117605
|
+
savePath: string().optional().describe("Only without a task: where to save the file on the API server (directory or full path). Defaults to /workspace/shared/downloads/{agentId}/slack/."),
|
|
117112
117606
|
filename: string().optional().describe("Filename to use when saving. Only used if savePath is a directory.")
|
|
117113
117607
|
}),
|
|
117114
117608
|
outputSchema: swarmToolOutputSchema({
|
|
117115
|
-
|
|
117609
|
+
taskId: string().optional(),
|
|
117610
|
+
attachmentId: string().optional(),
|
|
117611
|
+
fetchCommand: string().optional(),
|
|
117612
|
+
savedPath: string().optional().describe("Only without a task: the path on the API server's disk, not in your container."),
|
|
117116
117613
|
fileInfo: looseObject({
|
|
117117
117614
|
id: string().optional(),
|
|
117118
117615
|
name: string().optional(),
|
|
@@ -117120,7 +117617,7 @@ var registerSlackDownloadFileTool = (server) => {
|
|
|
117120
117617
|
size: number().optional()
|
|
117121
117618
|
}).optional()
|
|
117122
117619
|
})
|
|
117123
|
-
}, async ({ fileId, url, savePath, filename }, requestInfo, _meta) => {
|
|
117620
|
+
}, async ({ fileId, url, taskId, savePath, filename }, requestInfo, _meta) => {
|
|
117124
117621
|
if (!requestInfo.agentId) {
|
|
117125
117622
|
return toolErr("Agent ID not found.");
|
|
117126
117623
|
}
|
|
@@ -117139,22 +117636,33 @@ var registerSlackDownloadFileTool = (server) => {
|
|
|
117139
117636
|
if (!token) {
|
|
117140
117637
|
return toolErr("Slack bot token not configured.");
|
|
117141
117638
|
}
|
|
117639
|
+
const task = await attachableTask(agent.id, taskId ?? requestInfo.sourceTaskId);
|
|
117640
|
+
if (taskId && !task) {
|
|
117641
|
+
return toolErr("You don't have context for this task.");
|
|
117642
|
+
}
|
|
117142
117643
|
try {
|
|
117143
|
-
|
|
117144
|
-
|
|
117145
|
-
if (fileId) {
|
|
117146
|
-
|
|
117644
|
+
const id2 = fileId ?? (url ? fileIdFromUrl(url) : undefined);
|
|
117645
|
+
const info = id2 ? await getFileInfo(app.client, id2) : null;
|
|
117646
|
+
if (fileId && !info) {
|
|
117647
|
+
return toolErr(`File not found: ${fileId}`);
|
|
117648
|
+
}
|
|
117649
|
+
const fileInfo = info ? { id: info.id, name: info.name, mimetype: info.mimetype, size: info.size } : undefined;
|
|
117650
|
+
if (task) {
|
|
117147
117651
|
if (!info) {
|
|
117148
|
-
return toolErr(
|
|
117652
|
+
return toolErr("Could not identify the Slack file in that URL; pass fileId instead.");
|
|
117149
117653
|
}
|
|
117150
|
-
|
|
117151
|
-
|
|
117152
|
-
|
|
117153
|
-
|
|
117154
|
-
|
|
117155
|
-
|
|
117156
|
-
|
|
117654
|
+
const outcome = (await attachSlackFilesForAgent(app.client, task, [info], agent.id)).get(info.id);
|
|
117655
|
+
if (!outcome || "reason" in outcome) {
|
|
117656
|
+
return toolErr(`Failed to attach file: ${outcome?.reason ?? "unknown error"}`);
|
|
117657
|
+
}
|
|
117658
|
+
const { attachment, fetchCommand } = outcome;
|
|
117659
|
+
return toolOk(`Attached ${attachment.name} to task ${task.id} (attachment ${attachment.id}).`, {
|
|
117660
|
+
details: `Get it into your container with:
|
|
117661
|
+
${fetchCommand}`,
|
|
117662
|
+
data: { taskId: task.id, attachmentId: attachment.id, fetchCommand, fileInfo }
|
|
117663
|
+
});
|
|
117157
117664
|
}
|
|
117665
|
+
const downloadUrl = info?.url_private_download ?? url;
|
|
117158
117666
|
if (!downloadUrl) {
|
|
117159
117667
|
return toolErr("No download URL available.");
|
|
117160
117668
|
}
|
|
@@ -117171,8 +117679,9 @@ var registerSlackDownloadFileTool = (server) => {
|
|
|
117171
117679
|
if (!result.success) {
|
|
117172
117680
|
return toolErr(`Failed to download file: ${result.error}`);
|
|
117173
117681
|
}
|
|
117174
|
-
|
|
117175
|
-
|
|
117682
|
+
return toolOk(`File saved on the API server at ${result.savedPath}.`, {
|
|
117683
|
+
data: { savedPath: result.savedPath, fileInfo }
|
|
117684
|
+
});
|
|
117176
117685
|
} catch (error) {
|
|
117177
117686
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
117178
117687
|
return toolErr(`Failed to download file: ${errorMsg}`);
|
|
@@ -117443,7 +117952,10 @@ var SlackFileSchema = looseObject({
|
|
|
117443
117952
|
filetype: string().optional(),
|
|
117444
117953
|
size: number().optional(),
|
|
117445
117954
|
url_private_download: string().optional(),
|
|
117446
|
-
|
|
117955
|
+
attachmentId: string().optional(),
|
|
117956
|
+
fetchCommand: string().optional(),
|
|
117957
|
+
notAttached: string().optional(),
|
|
117958
|
+
localPath: string().optional().describe("Only without a task: the path on the API server's disk, not in your container.")
|
|
117447
117959
|
});
|
|
117448
117960
|
var SlackMessageSchema = looseObject({
|
|
117449
117961
|
user: string().optional(),
|
|
@@ -117456,15 +117968,15 @@ var SlackMessageSchema = looseObject({
|
|
|
117456
117968
|
var registerSlackReadTool = (server) => {
|
|
117457
117969
|
createToolRegistrar(server)("slack-read", {
|
|
117458
117970
|
title: "Read Slack thread/channel history",
|
|
117459
|
-
description: "Read messages from a Slack thread or channel. Use inboxMessageId or taskId to read from a thread you have context for, or provide channelId directly for channel history (leads only).",
|
|
117460
|
-
annotations: { readOnlyHint:
|
|
117971
|
+
description: "Read messages from a Slack thread or channel. Use inboxMessageId or taskId to read from a thread you have context for, or provide channelId directly for channel history (leads only). From a task, files in the messages are stored as attachments of that task, each with a ready-to-run `fetchCommand`.",
|
|
117972
|
+
annotations: { readOnlyHint: false, openWorldHint: true },
|
|
117461
117973
|
inputSchema: object({
|
|
117462
117974
|
inboxMessageId: uuid().optional().describe("Read thread history for an inbox message."),
|
|
117463
117975
|
taskId: uuid().optional().describe("Read thread history for a task."),
|
|
117464
117976
|
channelId: string().optional().describe("Slack channel ID to read from (requires lead privileges)."),
|
|
117465
117977
|
threadTs: string().optional().describe("Thread timestamp (required with channelId for thread history)."),
|
|
117466
117978
|
limit: number().int().min(1).max(100).default(20).describe("Maximum number of messages to retrieve (default: 20, max: 100)."),
|
|
117467
|
-
includeFiles: boolean().default(true).describe("Include file attachments in the response (default: true).")
|
|
117979
|
+
includeFiles: boolean().default(true).describe("Include file attachments in the response (default: true). From a task, they are also stored as attachments of that task.")
|
|
117468
117980
|
}),
|
|
117469
117981
|
outputSchema: swarmToolOutputSchema({
|
|
117470
117982
|
channelId: string().optional(),
|
|
@@ -117481,6 +117993,7 @@ var registerSlackReadTool = (server) => {
|
|
|
117481
117993
|
}
|
|
117482
117994
|
let slackChannelId = channelId;
|
|
117483
117995
|
let slackThreadTs = threadTs;
|
|
117996
|
+
let contextTask = null;
|
|
117484
117997
|
if (inboxMessageId) {
|
|
117485
117998
|
const inboxMsg = await getInboxMessageById(inboxMessageId);
|
|
117486
117999
|
if (!inboxMsg) {
|
|
@@ -117501,6 +118014,7 @@ var registerSlackReadTool = (server) => {
|
|
|
117501
118014
|
}
|
|
117502
118015
|
slackChannelId = task.slackChannelId;
|
|
117503
118016
|
slackThreadTs = task.slackThreadTs;
|
|
118017
|
+
contextTask = task;
|
|
117504
118018
|
} else if (channelId) {
|
|
117505
118019
|
const decision = can({
|
|
117506
118020
|
principal: { kind: "agent", agentId: agent.id, isLead: agent.isLead },
|
|
@@ -117554,6 +118068,11 @@ var registerSlackReadTool = (server) => {
|
|
|
117554
118068
|
}
|
|
117555
118069
|
}
|
|
117556
118070
|
const token = process.env.SLACK_BOT_TOKEN;
|
|
118071
|
+
const attachTo = contextTask ?? await attachableTask(agent.id, taskId ?? requestInfo.sourceTaskId);
|
|
118072
|
+
if (taskId && !attachTo) {
|
|
118073
|
+
return toolErr("You don't have context for this task.", { data: { messages: [] } });
|
|
118074
|
+
}
|
|
118075
|
+
const toAttach = [];
|
|
117557
118076
|
const messages = [];
|
|
117558
118077
|
for (const m of rawMessages) {
|
|
117559
118078
|
const extractedText = extractSlackMessageText(m);
|
|
@@ -117578,7 +118097,9 @@ var registerSlackReadTool = (server) => {
|
|
|
117578
118097
|
size: f.size,
|
|
117579
118098
|
url_private_download: f.url_private_download
|
|
117580
118099
|
};
|
|
117581
|
-
if (
|
|
118100
|
+
if (attachTo) {
|
|
118101
|
+
toAttach.push({ raw: f, info: fileInfo });
|
|
118102
|
+
} else if (token && f.url_private_download) {
|
|
117582
118103
|
const savePath = `${AUTO_DOWNLOAD_DIR}/${f.id}_${f.name}`;
|
|
117583
118104
|
try {
|
|
117584
118105
|
const downloadResult = await downloadFile({
|
|
@@ -117603,13 +118124,29 @@ var registerSlackReadTool = (server) => {
|
|
|
117603
118124
|
files
|
|
117604
118125
|
});
|
|
117605
118126
|
}
|
|
118127
|
+
if (attachTo && toAttach.length > 0) {
|
|
118128
|
+
const outcomes = await attachSlackFilesForAgent(client, attachTo, toAttach.map(({ raw }) => raw), agent.id);
|
|
118129
|
+
for (const { info } of toAttach) {
|
|
118130
|
+
const outcome = outcomes.get(info.id);
|
|
118131
|
+
if (outcome && "attachment" in outcome) {
|
|
118132
|
+
info.attachmentId = outcome.attachment.id;
|
|
118133
|
+
info.fetchCommand = outcome.fetchCommand;
|
|
118134
|
+
} else {
|
|
118135
|
+
info.notAttached = outcome?.reason ?? "not downloaded";
|
|
118136
|
+
}
|
|
118137
|
+
}
|
|
118138
|
+
}
|
|
117606
118139
|
const textOutput = messages.map((m) => {
|
|
117607
118140
|
let text = `[${m.username || m.user || "Unknown"}]: ${m.text}`;
|
|
117608
118141
|
if (m.files && m.files.length > 0) {
|
|
117609
118142
|
const fileList = m.files.map((f) => {
|
|
117610
118143
|
let line = ` - ${f.name} (${f.mimetype}, ${Math.round(f.size / 1024)} KB)`;
|
|
117611
|
-
if (f.
|
|
117612
|
-
line += ` [
|
|
118144
|
+
if (f.fetchCommand) {
|
|
118145
|
+
line += ` [Task attachment ${f.attachmentId}: ${f.fetchCommand}]`;
|
|
118146
|
+
} else if (f.notAttached) {
|
|
118147
|
+
line += ` [Not attached: ${f.notAttached}]`;
|
|
118148
|
+
} else if (f.localPath) {
|
|
118149
|
+
line += ` [Downloaded on the API server: ${f.localPath}]`;
|
|
117613
118150
|
}
|
|
117614
118151
|
return line;
|
|
117615
118152
|
}).join(`
|
|
@@ -118222,379 +118759,6 @@ var registerSteerTaskTool = (server) => {
|
|
|
118222
118759
|
// src/tools/store-progress.ts
|
|
118223
118760
|
init_zod();
|
|
118224
118761
|
init_db();
|
|
118225
|
-
|
|
118226
|
-
// src/be/memory/raters/explicit-self.ts
|
|
118227
|
-
class ExplicitSelfRatingRater {
|
|
118228
|
-
name = "explicit-self";
|
|
118229
|
-
async rate() {
|
|
118230
|
-
return [];
|
|
118231
|
-
}
|
|
118232
|
-
}
|
|
118233
|
-
|
|
118234
|
-
// src/be/memory/raters/implicit-citation.ts
|
|
118235
|
-
class ImplicitCitationRater {
|
|
118236
|
-
name = "implicit-citation";
|
|
118237
|
-
async rate(ctx) {
|
|
118238
|
-
if (ctx.retrievedMemoryIds.length === 0)
|
|
118239
|
-
return [];
|
|
118240
|
-
const evidence = ctx.evidence ?? "";
|
|
118241
|
-
const events = [];
|
|
118242
|
-
for (const memoryId of ctx.retrievedMemoryIds) {
|
|
118243
|
-
if (evidence.length > 0 && evidence.includes(memoryId)) {
|
|
118244
|
-
events.push({ memoryId, signal: 1, weight: 0.5, source: "" });
|
|
118245
|
-
} else {
|
|
118246
|
-
events.push({ memoryId, signal: -1, weight: 0.25, source: "" });
|
|
118247
|
-
}
|
|
118248
|
-
}
|
|
118249
|
-
return events;
|
|
118250
|
-
}
|
|
118251
|
-
}
|
|
118252
|
-
|
|
118253
|
-
// src/be/memory/raters/noop.ts
|
|
118254
|
-
class NoopRater {
|
|
118255
|
-
name = "noop";
|
|
118256
|
-
async rate() {
|
|
118257
|
-
return [];
|
|
118258
|
-
}
|
|
118259
|
-
}
|
|
118260
|
-
|
|
118261
|
-
// src/be/memory/raters/registry.ts
|
|
118262
|
-
var FACTORIES = {
|
|
118263
|
-
noop: () => new NoopRater,
|
|
118264
|
-
"implicit-citation": () => new ImplicitCitationRater,
|
|
118265
|
-
"explicit-self": () => new ExplicitSelfRatingRater,
|
|
118266
|
-
llm: () => new LlmRater
|
|
118267
|
-
};
|
|
118268
|
-
var SERVER_RATERS = new Set(["implicit-citation"]);
|
|
118269
|
-
function getRegisteredRaters() {
|
|
118270
|
-
const raw = process.env.MEMORY_RATERS;
|
|
118271
|
-
if (!raw || raw.trim() === "") {
|
|
118272
|
-
return [new NoopRater];
|
|
118273
|
-
}
|
|
118274
|
-
const names = raw.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
118275
|
-
const raters = [];
|
|
118276
|
-
for (const name of names) {
|
|
118277
|
-
const factory = FACTORIES[name];
|
|
118278
|
-
if (!factory) {
|
|
118279
|
-
console.warn(`[memory-rater] Unknown rater "${name}" in MEMORY_RATERS — skipping`);
|
|
118280
|
-
continue;
|
|
118281
|
-
}
|
|
118282
|
-
raters.push(factory());
|
|
118283
|
-
}
|
|
118284
|
-
if (raters.length === 0) {
|
|
118285
|
-
return [new NoopRater];
|
|
118286
|
-
}
|
|
118287
|
-
return raters;
|
|
118288
|
-
}
|
|
118289
|
-
function getRaterWeightMultiplier(name) {
|
|
118290
|
-
const raw = process.env.MEMORY_RATER_WEIGHTS;
|
|
118291
|
-
if (!raw || raw.trim() === "")
|
|
118292
|
-
return 1;
|
|
118293
|
-
for (const pair of raw.split(",")) {
|
|
118294
|
-
const trimmed = pair.trim();
|
|
118295
|
-
if (trimmed === "")
|
|
118296
|
-
continue;
|
|
118297
|
-
const [rawName, rawMult] = trimmed.split(":");
|
|
118298
|
-
if (!rawName || !rawMult)
|
|
118299
|
-
continue;
|
|
118300
|
-
if (rawName.trim() !== name)
|
|
118301
|
-
continue;
|
|
118302
|
-
const mult = Number(rawMult);
|
|
118303
|
-
if (Number.isFinite(mult) && mult >= 0)
|
|
118304
|
-
return mult;
|
|
118305
|
-
}
|
|
118306
|
-
return 1;
|
|
118307
|
-
}
|
|
118308
|
-
|
|
118309
|
-
// src/be/memory/raters/store.ts
|
|
118310
|
-
init_db();
|
|
118311
|
-
class ExplicitSelfDuplicateError extends Error {
|
|
118312
|
-
event;
|
|
118313
|
-
constructor(message, event) {
|
|
118314
|
-
super(message);
|
|
118315
|
-
this.event = event;
|
|
118316
|
-
this.name = "ExplicitSelfDuplicateError";
|
|
118317
|
-
}
|
|
118318
|
-
}
|
|
118319
|
-
async function applyRating(events, ctx = {}) {
|
|
118320
|
-
if (events.length === 0) {
|
|
118321
|
-
return { applied: 0, rejected: [] };
|
|
118322
|
-
}
|
|
118323
|
-
const accepted = [];
|
|
118324
|
-
const rejected = [];
|
|
118325
|
-
for (const event of events) {
|
|
118326
|
-
const reason = validate(event);
|
|
118327
|
-
if (reason) {
|
|
118328
|
-
rejected.push({ event, reason });
|
|
118329
|
-
continue;
|
|
118330
|
-
}
|
|
118331
|
-
let sanitizedReferencesSource = null;
|
|
118332
|
-
if (event.referencesSource !== undefined) {
|
|
118333
|
-
if (event.referencesSource.length === 0) {
|
|
118334
|
-
rejected.push({ event, reason: "referencesSource must be non-empty" });
|
|
118335
|
-
continue;
|
|
118336
|
-
}
|
|
118337
|
-
if (event.referencesSource.length > REFERENCES_SOURCE_MAX_LENGTH) {
|
|
118338
|
-
rejected.push({
|
|
118339
|
-
event,
|
|
118340
|
-
reason: `referencesSource exceeds ${REFERENCES_SOURCE_MAX_LENGTH} chars`
|
|
118341
|
-
});
|
|
118342
|
-
continue;
|
|
118343
|
-
}
|
|
118344
|
-
sanitizedReferencesSource = sanitizeReferencesSource(event.referencesSource);
|
|
118345
|
-
if (sanitizedReferencesSource === null) {
|
|
118346
|
-
rejected.push({
|
|
118347
|
-
event,
|
|
118348
|
-
reason: "referencesSource contains a NUL byte or strips to empty"
|
|
118349
|
-
});
|
|
118350
|
-
continue;
|
|
118351
|
-
}
|
|
118352
|
-
}
|
|
118353
|
-
accepted.push({ event, sanitizedReferencesSource });
|
|
118354
|
-
}
|
|
118355
|
-
if (accepted.length === 0) {
|
|
118356
|
-
return { applied: 0, rejected };
|
|
118357
|
-
}
|
|
118358
|
-
const UPDATE_MEMORY_SQL = "UPDATE agent_memory SET alpha = alpha + ?, beta = beta + ? WHERE id = ?";
|
|
118359
|
-
const CHECK_EXISTS_SQL = "SELECT id FROM agent_memory WHERE id = ?";
|
|
118360
|
-
const INSERT_RATING_SQL = `INSERT INTO memory_rating
|
|
118361
|
-
(id, memoryId, taskId, source, signal, weight, reasoning, createdAt, contextKey)
|
|
118362
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`;
|
|
118363
|
-
const UPSERT_EDGE_SQL = `INSERT INTO agent_memory_edge (from_id, to_id, type, alpha, beta, createdAt)
|
|
118364
|
-
VALUES (?, ?, 'references-source', ?, ?, ?)
|
|
118365
|
-
ON CONFLICT(from_id, to_id, type) DO UPDATE SET
|
|
118366
|
-
alpha = alpha + excluded.alpha - 1.0,
|
|
118367
|
-
beta = beta + excluded.beta - 1.0`;
|
|
118368
|
-
const { applied, lateRejects, appliedEvents } = await getDbClient().transaction(async (tx) => {
|
|
118369
|
-
let applied2 = 0;
|
|
118370
|
-
const lateRejects2 = [];
|
|
118371
|
-
const appliedEvents2 = [];
|
|
118372
|
-
for (const { event, sanitizedReferencesSource } of accepted) {
|
|
118373
|
-
const exists = await tx.get(CHECK_EXISTS_SQL, [event.memoryId]);
|
|
118374
|
-
if (!exists) {
|
|
118375
|
-
lateRejects2.push({ event, reason: "memoryId not found in agent_memory" });
|
|
118376
|
-
continue;
|
|
118377
|
-
}
|
|
118378
|
-
const alphaDelta = Math.max(0, event.signal) * event.weight;
|
|
118379
|
-
const betaDelta = Math.max(0, -event.signal) * event.weight;
|
|
118380
|
-
await tx.run(UPDATE_MEMORY_SQL, [alphaDelta, betaDelta, event.memoryId]);
|
|
118381
|
-
try {
|
|
118382
|
-
await tx.run(INSERT_RATING_SQL, [
|
|
118383
|
-
crypto.randomUUID(),
|
|
118384
|
-
event.memoryId,
|
|
118385
|
-
ctx.taskId ?? null,
|
|
118386
|
-
event.source,
|
|
118387
|
-
event.signal,
|
|
118388
|
-
event.weight,
|
|
118389
|
-
event.reasoning ?? null,
|
|
118390
|
-
new Date().toISOString(),
|
|
118391
|
-
ctx.contextKey ?? null
|
|
118392
|
-
]);
|
|
118393
|
-
} catch (err) {
|
|
118394
|
-
if (isUniqueConstraintError(err)) {
|
|
118395
|
-
throw new ExplicitSelfDuplicateError(`duplicate explicit-self rating for memoryId=${event.memoryId} taskId=${ctx.taskId}`, event);
|
|
118396
|
-
}
|
|
118397
|
-
throw err;
|
|
118398
|
-
}
|
|
118399
|
-
if (sanitizedReferencesSource !== null) {
|
|
118400
|
-
await tx.run(UPSERT_EDGE_SQL, [
|
|
118401
|
-
event.memoryId,
|
|
118402
|
-
sanitizedReferencesSource,
|
|
118403
|
-
1 + alphaDelta,
|
|
118404
|
-
1 + betaDelta,
|
|
118405
|
-
new Date().toISOString()
|
|
118406
|
-
]);
|
|
118407
|
-
}
|
|
118408
|
-
appliedEvents2.push({ event, sanitizedReferencesSource });
|
|
118409
|
-
applied2 += 1;
|
|
118410
|
-
}
|
|
118411
|
-
return { applied: applied2, lateRejects: lateRejects2, appliedEvents: appliedEvents2 };
|
|
118412
|
-
});
|
|
118413
|
-
if (ctx.taskId && appliedEvents.length > 0) {
|
|
118414
|
-
for (const { event, sanitizedReferencesSource } of appliedEvents) {
|
|
118415
|
-
ensure({
|
|
118416
|
-
id: "memory_rated",
|
|
118417
|
-
flow: "task",
|
|
118418
|
-
runId: ctx.taskId,
|
|
118419
|
-
data: {
|
|
118420
|
-
memoryId: event.memoryId,
|
|
118421
|
-
source: event.source,
|
|
118422
|
-
signal: event.signal,
|
|
118423
|
-
weight: event.weight,
|
|
118424
|
-
hasReferencesSource: sanitizedReferencesSource !== null
|
|
118425
|
-
},
|
|
118426
|
-
validator: (data) => typeof data.memoryId === "string" && data.memoryId.length > 0 && typeof data.source === "string" && data.source.length > 0 && typeof data.signal === "number" && data.signal >= -1 && data.signal <= 1 && typeof data.weight === "number" && data.weight >= 0 && data.weight <= 1
|
|
118427
|
-
});
|
|
118428
|
-
}
|
|
118429
|
-
}
|
|
118430
|
-
return { applied, rejected: [...rejected, ...lateRejects] };
|
|
118431
|
-
}
|
|
118432
|
-
function validate(event) {
|
|
118433
|
-
if (!event.source || event.source.trim() === "") {
|
|
118434
|
-
return "source is required";
|
|
118435
|
-
}
|
|
118436
|
-
if (!Number.isFinite(event.signal) || event.signal < -1 || event.signal > 1) {
|
|
118437
|
-
return "signal must be in [-1, +1]";
|
|
118438
|
-
}
|
|
118439
|
-
if (!Number.isFinite(event.weight) || event.weight < 0 || event.weight > 1) {
|
|
118440
|
-
return "weight must be in [0, 1]";
|
|
118441
|
-
}
|
|
118442
|
-
if (!event.memoryId) {
|
|
118443
|
-
return "memoryId is required";
|
|
118444
|
-
}
|
|
118445
|
-
return null;
|
|
118446
|
-
}
|
|
118447
|
-
function isUniqueConstraintError(err) {
|
|
118448
|
-
if (!(err instanceof Error))
|
|
118449
|
-
return false;
|
|
118450
|
-
return /UNIQUE constraint failed|SQLITE_CONSTRAINT/i.test(err.message);
|
|
118451
|
-
}
|
|
118452
|
-
|
|
118453
|
-
// src/be/memory/raters/run-server-raters.ts
|
|
118454
|
-
async function runServerRaters(input, deps = {}) {
|
|
118455
|
-
const result = { ratersFired: 0, outcomes: [] };
|
|
118456
|
-
if (input.retrievedMemoryIds.length === 0)
|
|
118457
|
-
return result;
|
|
118458
|
-
const allRaters = deps.raters ?? getRegisteredRaters();
|
|
118459
|
-
const allowed = deps.serverRaterNames ?? SERVER_RATERS;
|
|
118460
|
-
const weightFor = deps.weightMultiplierFor ?? getRaterWeightMultiplier;
|
|
118461
|
-
const applyFn = deps.applyRating ?? applyRating;
|
|
118462
|
-
const serverRaters = allRaters.filter((r) => allowed.has(r.name));
|
|
118463
|
-
for (const rater of serverRaters) {
|
|
118464
|
-
const events = await rater.rate({
|
|
118465
|
-
taskId: input.taskId,
|
|
118466
|
-
agentId: input.agentId,
|
|
118467
|
-
retrievedMemoryIds: input.retrievedMemoryIds,
|
|
118468
|
-
evidence: input.evidence
|
|
118469
|
-
});
|
|
118470
|
-
if (events.length === 0)
|
|
118471
|
-
continue;
|
|
118472
|
-
const multiplier = weightFor(rater.name);
|
|
118473
|
-
const stamped = events.map((e) => ({
|
|
118474
|
-
...e,
|
|
118475
|
-
source: rater.name,
|
|
118476
|
-
weight: Math.max(0, Math.min(1, e.weight * multiplier))
|
|
118477
|
-
}));
|
|
118478
|
-
const applied = await applyFn(stamped, { taskId: input.taskId });
|
|
118479
|
-
result.ratersFired += 1;
|
|
118480
|
-
result.outcomes.push({ rater: rater.name, events: stamped, result: applied });
|
|
118481
|
-
}
|
|
118482
|
-
return result;
|
|
118483
|
-
}
|
|
118484
|
-
|
|
118485
|
-
// src/memory/automatic-task-gate.ts
|
|
118486
|
-
var SCHEDULE_TAG_PREFIX = "schedule:";
|
|
118487
|
-
var AUTOMATIC_TASK_TYPES = new Set([
|
|
118488
|
-
"boot-triage",
|
|
118489
|
-
"heartbeat",
|
|
118490
|
-
"heartbeat-checklist",
|
|
118491
|
-
"health-check",
|
|
118492
|
-
"health-probe",
|
|
118493
|
-
"monitor",
|
|
118494
|
-
"monitoring"
|
|
118495
|
-
]);
|
|
118496
|
-
function isAutomaticOrRecurringTaskCompletion(task) {
|
|
118497
|
-
const tags = task.tags ?? [];
|
|
118498
|
-
const taskType = task.taskType?.toLowerCase();
|
|
118499
|
-
return task.source === "schedule" || task.source === "system" || tags.includes("scheduled") || tags.includes("auto-generated") || tags.some((tag) => tag.startsWith(SCHEDULE_TAG_PREFIX)) || taskType !== undefined && (AUTOMATIC_TASK_TYPES.has(taskType) || taskType.endsWith("-monitor") || taskType.endsWith("-digest"));
|
|
118500
|
-
}
|
|
118501
|
-
function shouldPersistAutomaticTaskMemory(task, persistMemory) {
|
|
118502
|
-
if (persistMemory)
|
|
118503
|
-
return true;
|
|
118504
|
-
return !isAutomaticOrRecurringTaskCompletion(task);
|
|
118505
|
-
}
|
|
118506
|
-
var shouldPersistTaskCompletionMemory = shouldPersistAutomaticTaskMemory;
|
|
118507
|
-
|
|
118508
|
-
// src/tasks/terminal-result-guard.ts
|
|
118509
|
-
init_db();
|
|
118510
|
-
init_types();
|
|
118511
|
-
init_secret_scrubber();
|
|
118512
|
-
function getTaskOutputValidationError(outputSchema, output) {
|
|
118513
|
-
if (!outputSchema || typeof outputSchema !== "object")
|
|
118514
|
-
return;
|
|
118515
|
-
const schema = outputSchema;
|
|
118516
|
-
if (!output) {
|
|
118517
|
-
return `Task has an outputSchema but no output was provided. You must call store-progress with a valid JSON output matching this schema:
|
|
118518
|
-
${JSON.stringify(schema, null, 2)}`;
|
|
118519
|
-
}
|
|
118520
|
-
let parsed;
|
|
118521
|
-
try {
|
|
118522
|
-
parsed = JSON.parse(output);
|
|
118523
|
-
} catch {
|
|
118524
|
-
return `Task output must be valid JSON matching the outputSchema. Got invalid JSON. Schema:
|
|
118525
|
-
${JSON.stringify(schema, null, 2)}`;
|
|
118526
|
-
}
|
|
118527
|
-
let validationErrors;
|
|
118528
|
-
try {
|
|
118529
|
-
validationErrors = validateJsonSchema(schema, parsed);
|
|
118530
|
-
} catch (error) {
|
|
118531
|
-
const detail = error instanceof Error ? error.message : String(error);
|
|
118532
|
-
return `Task outputSchema is malformed and cannot be validated (${detail}). Ask an operator to correct the task's outputSchema, or force-complete with store-progress force: true.`;
|
|
118533
|
-
}
|
|
118534
|
-
if (validationErrors.length > 0) {
|
|
118535
|
-
return `Task output does not match the outputSchema. Errors:
|
|
118536
|
-
${validationErrors.join(`
|
|
118537
|
-
`)}
|
|
118538
|
-
|
|
118539
|
-
Expected schema:
|
|
118540
|
-
${JSON.stringify(schema, null, 2)}
|
|
118541
|
-
|
|
118542
|
-
Please fix your output and retry.`;
|
|
118543
|
-
}
|
|
118544
|
-
return;
|
|
118545
|
-
}
|
|
118546
|
-
async function guardTerminalTaskResultWrite(task, write2) {
|
|
118547
|
-
if (!isTerminalTaskStatus(task.status) || !write2.status && !write2.force) {
|
|
118548
|
-
return { handled: false };
|
|
118549
|
-
}
|
|
118550
|
-
const scrubbedOutput = write2.output !== undefined ? scrubSecrets(write2.output) : undefined;
|
|
118551
|
-
const scrubbedFailureReason = write2.failureReason !== undefined ? scrubSecrets(write2.failureReason) : undefined;
|
|
118552
|
-
const hasDifferingOutput = scrubbedOutput !== undefined && scrubbedOutput !== task.output;
|
|
118553
|
-
const hasDifferingFailureReason = scrubbedFailureReason !== undefined && scrubbedFailureReason !== task.failureReason;
|
|
118554
|
-
const hasDifferingResultText = hasDifferingOutput || hasDifferingFailureReason;
|
|
118555
|
-
if (hasDifferingResultText && write2.force) {
|
|
118556
|
-
const outputValidationError = hasDifferingOutput ? getTaskOutputValidationError(task.outputSchema, write2.output) : undefined;
|
|
118557
|
-
if (outputValidationError) {
|
|
118558
|
-
return { handled: true, success: false, message: outputValidationError, task };
|
|
118559
|
-
}
|
|
118560
|
-
const overwrittenTask = await overwriteTerminalTaskResultText(task.id, {
|
|
118561
|
-
...write2.output !== undefined ? { output: write2.output } : {},
|
|
118562
|
-
...write2.failureReason !== undefined ? { failureReason: write2.failureReason } : {}
|
|
118563
|
-
});
|
|
118564
|
-
if (!overwrittenTask) {
|
|
118565
|
-
return {
|
|
118566
|
-
handled: true,
|
|
118567
|
-
success: false,
|
|
118568
|
-
message: `Task "${task.id}" terminal result text could not be overwritten.`,
|
|
118569
|
-
task
|
|
118570
|
-
};
|
|
118571
|
-
}
|
|
118572
|
-
return {
|
|
118573
|
-
handled: true,
|
|
118574
|
-
success: true,
|
|
118575
|
-
message: `Task "${task.id}" is already ${task.status}; force-overwrote terminal result text ` + "without replaying completion side effects.",
|
|
118576
|
-
task: overwrittenTask,
|
|
118577
|
-
wasForcedOverwrite: true
|
|
118578
|
-
};
|
|
118579
|
-
}
|
|
118580
|
-
if (hasDifferingResultText) {
|
|
118581
|
-
return {
|
|
118582
|
-
handled: true,
|
|
118583
|
-
success: false,
|
|
118584
|
-
message: `Discarded write for already-${task.status} task "${task.id}"; ` + "existing output/failureReason and finishedAt were preserved. Retry with force: true " + "to overwrite terminal result text without replaying completion side effects.",
|
|
118585
|
-
task
|
|
118586
|
-
};
|
|
118587
|
-
}
|
|
118588
|
-
return {
|
|
118589
|
-
handled: true,
|
|
118590
|
-
success: true,
|
|
118591
|
-
message: `Task "${task.id}" is already ${task.status}; treating as no-op. ` + "Existing output preserved (first-call-wins).",
|
|
118592
|
-
task,
|
|
118593
|
-
wasNoOp: true
|
|
118594
|
-
};
|
|
118595
|
-
}
|
|
118596
|
-
|
|
118597
|
-
// src/tools/store-progress.ts
|
|
118598
118762
|
init_types();
|
|
118599
118763
|
init_secret_scrubber();
|
|
118600
118764
|
var storeProgressOutputSchema = swarmToolOutputSchema({
|
|
@@ -118814,91 +118978,15 @@ var registerStoreProgressTool = (server) => {
|
|
|
118814
118978
|
};
|
|
118815
118979
|
});
|
|
118816
118980
|
const shouldRunTerminalSideEffects = (status === "completed" || status === "failed") && result.success && result.task && !(("wasNoOp" in result) && result.wasNoOp) && !(("wasForcedOverwrite" in result) && result.wasForcedOverwrite);
|
|
118817
|
-
if (shouldRunTerminalSideEffects &&
|
|
118818
|
-
|
|
118819
|
-
|
|
118820
|
-
|
|
118821
|
-
|
|
118822
|
-
|
|
118823
|
-
|
|
118824
|
-
|
|
118825
|
-
|
|
118826
|
-
${failureReason || "No reason provided"}
|
|
118827
|
-
|
|
118828
|
-
This task failed. Learn from this to avoid repeating the mistake.`;
|
|
118829
|
-
if (taskContent.length < 30)
|
|
118830
|
-
return;
|
|
118831
|
-
const store = getMemoryStore();
|
|
118832
|
-
const provider = getEmbeddingProvider();
|
|
118833
|
-
const memory = await store.store({
|
|
118834
|
-
agentId: requestInfo.agentId ?? null,
|
|
118835
|
-
content: taskContent,
|
|
118836
|
-
name: `Task: ${result.task.task.slice(0, 80)}`,
|
|
118837
|
-
scope: "agent",
|
|
118838
|
-
source: "task_completion",
|
|
118839
|
-
sourceTaskId: taskId
|
|
118840
|
-
});
|
|
118841
|
-
const embedding = await provider.embed(taskContent);
|
|
118842
|
-
if (embedding) {
|
|
118843
|
-
await store.updateEmbedding(memory.id, embedding, provider.name);
|
|
118844
|
-
}
|
|
118845
|
-
const shouldShareWithSwarm = status === "completed" && (result.task.taskType === "research" || result.task.tags?.includes("knowledge") || result.task.tags?.includes("shared"));
|
|
118846
|
-
if (shouldShareWithSwarm) {
|
|
118847
|
-
try {
|
|
118848
|
-
const swarmMemory = await store.store({
|
|
118849
|
-
agentId: requestInfo.agentId ?? null,
|
|
118850
|
-
scope: "swarm",
|
|
118851
|
-
name: `Shared: ${result.task.task.slice(0, 80)}`,
|
|
118852
|
-
content: `Task completed by agent ${requestInfo.agentId}:
|
|
118853
|
-
|
|
118854
|
-
${taskContent}`,
|
|
118855
|
-
source: "task_completion",
|
|
118856
|
-
sourceTaskId: taskId
|
|
118857
|
-
});
|
|
118858
|
-
const swarmEmbedding = await provider.embed(taskContent);
|
|
118859
|
-
if (swarmEmbedding) {
|
|
118860
|
-
await store.updateEmbedding(swarmMemory.id, swarmEmbedding, provider.name);
|
|
118861
|
-
}
|
|
118862
|
-
} catch {}
|
|
118863
|
-
}
|
|
118864
|
-
} catch {}
|
|
118865
|
-
})().catch((err) => console.error("[store-progress] task completion memory write failed:", scrubSecrets(err instanceof Error ? err.message : String(err))));
|
|
118866
|
-
}
|
|
118867
|
-
if (shouldRunTerminalSideEffects) {
|
|
118868
|
-
(async () => {
|
|
118869
|
-
try {
|
|
118870
|
-
const retrievals = await getRetrievalsForTask(taskId);
|
|
118871
|
-
if (retrievals.length === 0)
|
|
118872
|
-
return;
|
|
118873
|
-
const retrievedMemoryIds = retrievals.map((r) => r.memoryId);
|
|
118874
|
-
const logs = await getSessionLogsByTaskId(taskId);
|
|
118875
|
-
const evidence = logs.map((l) => l.content).join(`
|
|
118876
|
-
`);
|
|
118877
|
-
await runServerRaters({
|
|
118878
|
-
taskId,
|
|
118879
|
-
agentId: requestInfo.agentId ?? "",
|
|
118880
|
-
retrievedMemoryIds,
|
|
118881
|
-
evidence
|
|
118882
|
-
});
|
|
118883
|
-
} catch (err) {
|
|
118884
|
-
console.error("[store-progress] server-rater fire failed:", err instanceof Error ? err.message : String(err));
|
|
118885
|
-
}
|
|
118886
|
-
})().catch((err) => console.error("[store-progress] server rater run failed:", scrubSecrets(err instanceof Error ? err.message : String(err))));
|
|
118887
|
-
}
|
|
118888
|
-
if (status && result.success && result.task && !result.task.workflowRunId && !(("wasNoOp" in result) && result.wasNoOp) && !(("wasForcedOverwrite" in result) && result.wasForcedOverwrite)) {
|
|
118889
|
-
try {
|
|
118890
|
-
const followUp = await createWorkerTaskFollowUp({
|
|
118891
|
-
task: result.task,
|
|
118892
|
-
status,
|
|
118893
|
-
output,
|
|
118894
|
-
failureReason
|
|
118895
|
-
});
|
|
118896
|
-
if (followUp) {
|
|
118897
|
-
console.log(`[store-progress] Created follow-up task ${followUp.id.slice(0, 8)} for ${status} task ${taskId.slice(0, 8)}`);
|
|
118898
|
-
}
|
|
118899
|
-
} catch (err) {
|
|
118900
|
-
console.warn(`[store-progress] Failed to create follow-up task: ${err}`);
|
|
118901
|
-
}
|
|
118981
|
+
if (shouldRunTerminalSideEffects && status) {
|
|
118982
|
+
await runTaskTerminalEffects({
|
|
118983
|
+
task: result.task,
|
|
118984
|
+
status,
|
|
118985
|
+
output,
|
|
118986
|
+
failureReason,
|
|
118987
|
+
agentId: requestInfo.agentId,
|
|
118988
|
+
persistMemory
|
|
118989
|
+
});
|
|
118902
118990
|
}
|
|
118903
118991
|
const { success, message } = result;
|
|
118904
118992
|
const task = result.task ? {
|
|
@@ -121350,6 +121438,7 @@ async function createServer(opts = {}) {
|
|
|
121350
121438
|
if (hasCapability2("scheduling")) {
|
|
121351
121439
|
registerListSchedulesTool(server);
|
|
121352
121440
|
registerCreateScheduleTool(server);
|
|
121441
|
+
registerDeferTaskTool(server);
|
|
121353
121442
|
registerUpdateScheduleTool(server);
|
|
121354
121443
|
registerPatchScheduleTool(server);
|
|
121355
121444
|
registerDeleteScheduleTool(server);
|
|
@@ -121510,7 +121599,7 @@ function isExplicitSelfRaterEnabled() {
|
|
|
121510
121599
|
|
|
121511
121600
|
// src/utils/skill-fs-writer.ts
|
|
121512
121601
|
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readdirSync, rmSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
121513
|
-
import { dirname
|
|
121602
|
+
import { dirname, join as join3 } from "node:path";
|
|
121514
121603
|
var SWARM_MARKER_FILE = ".swarm-managed";
|
|
121515
121604
|
function reconcileManagedSkillFiles(skillDir, currentRelativeFiles) {
|
|
121516
121605
|
if (!existsSync2(join3(skillDir, SWARM_MARKER_FILE)))
|
|
@@ -121614,7 +121703,7 @@ function writeSkillsToFilesystem(entries, harnessType = "all", home) {
|
|
|
121614
121703
|
}
|
|
121615
121704
|
const targetPath = join3(skillDir, file.path);
|
|
121616
121705
|
try {
|
|
121617
|
-
mkdirSync2(
|
|
121706
|
+
mkdirSync2(dirname(targetPath), { recursive: true });
|
|
121618
121707
|
writeFileSync2(targetPath, file.content, "utf-8");
|
|
121619
121708
|
} catch (err) {
|
|
121620
121709
|
const msg = err instanceof Error ? err.message : "Unknown error";
|
|
@@ -121647,4 +121736,4 @@ function writeSkillsToFilesystem(entries, harnessType = "all", home) {
|
|
|
121647
121736
|
return { synced, removed, errors };
|
|
121648
121737
|
}
|
|
121649
121738
|
|
|
121650
|
-
export { safeParseAsync2 as safeParseAsync, normalizeObjectSchema, getParseErrorMessage, DEFAULT_NEGOTIATED_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS, isJSONRPCRequest, isJSONRPCResultResponse, isJSONRPCErrorResponse, JSONRPCMessageSchema, isInitializeRequest, McpServer, isGitHubEnabled, initGitHub, verifyWebhookSignature, isAgentMailEnabled, initAgentMail, verifyAgentMailWebhook, isInboxAllowed, isSenderAllowed, handleMessageReceived, enqueueAuditRow, enqueueAdmissionRow, flushAuditBuffer, startAuditWriter, stopAuditWriter, startAuditGc, stopAuditGc, handlePullRequest, handleIssue, handleComment, handlePullRequestReview, handleCheckRun, handleCheckSuite, handleWorkflowRun, isGitLabEnabled, initGitLab, verifyGitLabWebhook, handleMergeRequest, handleIssue2 as handleIssue1, handleNote, handlePipeline, getJiraMetadata, updateJiraMetadata, clearJiraMetadata, registerJiraWebhook, deleteJiraWebhook, isJiraEnabled, initJira, handleJiraWebhook, handleAgentSessionEvent, handleIssueUpdate, handleIssueDelete, handleAgentSessionPrompted, isLinearEnabled, initLinear, parseCookieHeader, extractAndVerifyCookie, issuePageSessionCookie, resolveHttpRequestAuth, warnIfCorsAllowsAnyOrigin, isOriginAllowedForCredentials, setCorsHeaders, parseQueryParams, getPathSegments, wireHttpSpanLifecycle, safeRequestUrlForLog, agentWithCapacity, parseBody, BODY_TOO_LARGE, enforceContentLengthCap, json, jsonError, triggerSchemaErrorResponse, deriveApiBaseUrl, httpServerSemconvAttributes, runtimeInstanceHeader, describeRequestRoute, route, loadGlobalConfigsIntoEnv, reloadGlobalConfigsAndIntegrations, scheduleIntegrationsReload, handleCore, mcpOverflowAuthError, markScriptSdkRequestOrigin, toolErr, createToolRegistrar, userCtx, resolveTaskAuditUserId, resolveHttpAuditUserId, resolveHttpFavoriteOwner, handleApps, getUserCommsPrefs, getTaskDetailsInputSchema, getTaskDetailsOutputSchema, getTaskDetailsHandler, cancelTaskInputSchema, cancelTaskOutputSchema, cancelTaskHandler, executeReadOnlyQuery, assertSelectOnlyQuery, handleDbQuery, snapshotMetric, AssetKeyAuthorizationError, authorizeAssetKeyWrite, snapshotPage, assertOAuthAppUrlsSafe, assertOAuthEgressUrlSafe, listOAuthPresets, listOAuthPresetIds, getOAuthPreset, hydrateOAuthAppFromPreset, scopedResourceScopeIdSchema, resolveScopedResourceId, getTasksInputSchema, getTasksOutputSchema, getTasksHandler, reservedNamespaceError, reservedRoomKeyError, refreshLinks, canReadMemory, getLinksForMemory,
|
|
121739
|
+
export { safeParseAsync2 as safeParseAsync, normalizeObjectSchema, getParseErrorMessage, DEFAULT_NEGOTIATED_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS, isJSONRPCRequest, isJSONRPCResultResponse, isJSONRPCErrorResponse, JSONRPCMessageSchema, isInitializeRequest, McpServer, isGitHubEnabled, initGitHub, verifyWebhookSignature, isAgentMailEnabled, initAgentMail, verifyAgentMailWebhook, isInboxAllowed, isSenderAllowed, handleMessageReceived, enqueueAuditRow, enqueueAdmissionRow, flushAuditBuffer, startAuditWriter, stopAuditWriter, startAuditGc, stopAuditGc, handlePullRequest, handleIssue, handleComment, handlePullRequestReview, handleCheckRun, handleCheckSuite, handleWorkflowRun, isGitLabEnabled, initGitLab, verifyGitLabWebhook, handleMergeRequest, handleIssue2 as handleIssue1, handleNote, handlePipeline, getJiraMetadata, updateJiraMetadata, clearJiraMetadata, registerJiraWebhook, deleteJiraWebhook, isJiraEnabled, initJira, handleJiraWebhook, handleAgentSessionEvent, handleIssueUpdate, handleIssueDelete, handleAgentSessionPrompted, isLinearEnabled, initLinear, parseCookieHeader, extractAndVerifyCookie, issuePageSessionCookie, resolveHttpRequestAuth, warnIfCorsAllowsAnyOrigin, isOriginAllowedForCredentials, setCorsHeaders, parseQueryParams, getPathSegments, wireHttpSpanLifecycle, safeRequestUrlForLog, agentWithCapacity, parseBody, BODY_TOO_LARGE, enforceContentLengthCap, json, jsonError, triggerSchemaErrorResponse, deriveApiBaseUrl, httpServerSemconvAttributes, runtimeInstanceHeader, describeRequestRoute, route, loadGlobalConfigsIntoEnv, reloadGlobalConfigsAndIntegrations, scheduleIntegrationsReload, handleCore, mcpOverflowAuthError, markScriptSdkRequestOrigin, toolErr, createToolRegistrar, userCtx, resolveTaskAuditUserId, resolveHttpAuditUserId, resolveHttpFavoriteOwner, handleApps, getUserCommsPrefs, getTaskDetailsInputSchema, getTaskDetailsOutputSchema, getTaskDetailsHandler, cancelTaskInputSchema, cancelTaskOutputSchema, cancelTaskHandler, executeReadOnlyQuery, assertSelectOnlyQuery, handleDbQuery, snapshotMetric, AssetKeyAuthorizationError, authorizeAssetKeyWrite, snapshotPage, assertOAuthAppUrlsSafe, assertOAuthEgressUrlSafe, listOAuthPresets, listOAuthPresetIds, getOAuthPreset, hydrateOAuthAppFromPreset, scopedResourceScopeIdSchema, resolveScopedResourceId, dedupeMemoryDocumentIds, recordMemoryAccesses, recordRetrievals, ExplicitSelfDuplicateError, applyRating, shouldPersistAutomaticTaskMemory, guardTerminalTaskResultWrite, getTasksInputSchema, getTasksOutputSchema, getTasksHandler, reservedNamespaceError, reservedRoomKeyError, refreshLinks, canReadMemory, getLinksForMemory, expandCandidatesWithGraph, indexMemoryContent, markKapsoMessageRead, sendKapsoReaction, getKapsoConfig, getKapsoNumberMapping, markKapsoMessageSeen, resolveRoomNamespace, roomRequestInfo, authorizeRoomNamespace, RoomOperationSchema, removeAwarenessStates, roomTopic, decodeRoomSnapshot, roomView, getRoom, changeRoom, applyRoomUpdate, resetRoom, sweepRooms, closeRooms, removeNamespaceRooms, createEvent, createEventsBatch, getEventCountsFiltered, getEventsFiltered, mergeScheduleTiming, validateRecurringTiming, checkOutputSchemaShape, sendTaskOutputSchema, sendTaskHandler, parseSkillContent, steerTaskUserInputSchema, steerTaskOutputSchema, steerTaskHandler, canClaim, emitBudgetRefusalSideEffects, taskActionInputSchema, taskActionOutputSchema, taskActionHandler, patchWorkflowDefinition, resolveScriptsOnlyMode, ALL_CAPABILITIES, hasCapability, getEnabledCapabilities, createServer, SIMILARITY_THRESHOLD, renderMemoriesPrompt, writeSkillsToFilesystem };
|