@desplega.ai/agent-swarm 1.135.2 → 1.136.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/dist/{actions-3az2vwwn.js → actions-agcbc8nd.js} +6 -6
- package/dist/{app-vygnfvrh.js → app-g2s78xya.js} +3 -3
- package/dist/{assistant-2jr2frrm.js → assistant-yd3jkb9d.js} +8 -8
- package/dist/{boot-reembed-y7r9cxt0.js → boot-reembed-6spqw4q0.js} +3 -3
- package/dist/{boot-reembed-ncbg16rb.js → boot-reembed-b22s9w5x.js} +4 -4
- package/dist/{boot-scrub-logs-t82rwa0y.js → boot-scrub-logs-6h3cqkc0.js} +2 -2
- package/dist/{claude-adapter-vvx2aw3v.js → claude-adapter-ng5y8zd7.js} +4 -4
- package/dist/{cli-mfa2eaef.js → cli-35jknh9e.js} +5 -5
- package/dist/{cli-cv2vjg2y.js → cli-3y553gws.js} +1 -1
- package/dist/{cli-nhvym0d2.js → cli-4gzv54ss.js} +15 -6
- package/dist/{cli-4dakdn30.js → cli-4r4jkqep.js} +6 -6
- package/dist/{cli-83razmqg.js → cli-54ht104h.js} +3 -3
- package/dist/{cli-6290n4yz.js → cli-5bnz1t86.js} +1 -1
- package/dist/{cli-6bz2hzvw.js → cli-68vayryq.js} +2 -2
- package/dist/{cli-1z01xdqh.js → cli-6gwgzdgw.js} +2 -2
- package/dist/{cli-1dfatkzm.js → cli-84vrhesc.js} +1 -1
- package/dist/{cli-jfrh963q.js → cli-8v57p983.js} +10 -10
- package/dist/{cli-3f0tnh34.js → cli-ads0hfw2.js} +81 -23
- package/dist/{cli-fmha74ga.js → cli-bnq8h7ea.js} +3 -3
- package/dist/{cli-j3xnd5b4.js → cli-d5ygfv18.js} +7 -6
- package/dist/{cli-8f4h27gm.js → cli-edwrx42s.js} +1 -1
- package/dist/{cli-r5vwg1ma.js → cli-fpjmcbhz.js} +4 -4
- package/dist/{cli-w0ygcv43.js → cli-gpdtxzar.js} +6 -4
- package/dist/{cli-4rdjdddh.js → cli-hz5hp6wn.js} +1 -1
- package/dist/{cli-6mmwmy45.js → cli-j7qp8gtf.js} +1 -1
- package/dist/{cli-5a5nrq3g.js → cli-jjhnma34.js} +5 -5
- package/dist/{cli-ey09krp2.js → cli-m3z53bed.js} +1 -1
- package/dist/{cli-cf6vq6qa.js → cli-mgef08pc.js} +1 -1
- package/dist/{cli-0jhyxtdj.js → cli-qckgdqmr.js} +2 -2
- package/dist/{cli-a1zrc2g6.js → cli-qhfkxrpg.js} +108 -33
- package/dist/{cli-yw2z5kj9.js → cli-spf767vc.js} +1 -1
- package/dist/{cli-1857msnd.js → cli-tee8w7tq.js} +1 -1
- package/dist/{cli-qxn3g3yx.js → cli-tmn19cdz.js} +61 -6
- package/dist/{cli-7ccy0h4r.js → cli-y16cesaq.js} +2 -2
- package/dist/{cli-cm4z7w7w.js → cli-z6e8eqrm.js} +2 -2
- package/dist/cli.js +16 -16
- package/dist/{codex-adapter-6p290yq3.js → codex-adapter-kw11ps3j.js} +2 -2
- package/dist/{codex-session-runner-7b3dhpmx.js → codex-session-runner-sffb69v7.js} +2 -2
- package/dist/{commands-wxg1g4nq.js → commands-0xxp4tz8.js} +2 -2
- package/dist/{db-8fqeheve.js → db-0npp39zd.js} +6 -2
- package/dist/{handlers-gwtqp17c.js → handlers-5p7a1jx6.js} +15 -9
- package/dist/{hook-gd9fwfp0.js → hook-hpefr0a8.js} +2 -2
- package/dist/{hook-mrqygs7p.js → hook-jjpxn4se.js} +3 -3
- package/dist/{http-x4mc1mqg.js → http-wfp33653.js} +322 -61
- package/dist/{index-yd654kac.js → index-17h657rg.js} +12 -8
- package/dist/{index-pzgasj16.js → index-m2p7ctyh.js} +10 -10
- package/dist/{index-2mdqrd0n.js → index-racb4wfq.js} +9 -9
- package/dist/{index-4djjkp9z.js → index-zh66wm65.js} +8 -8
- package/dist/{keepalive-3tycspcy.js → keepalive-wxjd633a.js} +4 -4
- package/dist/{lead-js1h3z7d.js → lead-359ec2z0.js} +23 -23
- package/dist/{maintenance-y91ry8q4.js → maintenance-rr03qjtb.js} +4 -4
- package/dist/{mistral-conversations-hdmnkf6h.js → mistral-conversations-qdrnmrb8.js} +1 -1
- package/dist/{oauth-refresh-sweep-s33gtxrw.js → oauth-refresh-sweep-jwj22yb8.js} +3 -3
- package/dist/{onboard-vndj64mb.js → onboard-asnhchcv.js} +2 -2
- package/dist/{openai-completions-cwy2kkzg.js → openai-completions-yzftqrft.js} +33 -4
- package/dist/{otel-impl-d2p84k6e.js → otel-impl-54cra6mw.js} +18 -4
- package/dist/{pi-mono-adapter-1phspz2y.js → pi-mono-adapter-29g7axgj.js} +669 -335
- package/dist/{pricing-refresh-c2bwsyk5.js → pricing-refresh-mkyy7c2y.js} +4 -4
- package/dist/{rbac-roles-2pedz5e9.js → rbac-roles-ak56tr75.js} +2 -2
- package/dist/{rbac-roles-reef5y2d.js → rbac-roles-kb3afm95.js} +3 -3
- package/dist/{render-v2-zd5r5wgf.js → render-v2-434asg49.js} +3 -3
- package/dist/{seed-pricing-2kyk1vhg.js → seed-pricing-nbmd7ah8.js} +3 -3
- package/dist/{setup-5ys9pwyr.js → setup-wh4qmjs4.js} +2 -2
- package/dist/{worker-nb1f7k04.js → worker-j1d27tjv.js} +23 -23
- package/openapi.json +167 -2
- package/package.json +6 -6
- package/src/be/db-retention.ts +275 -0
- package/src/be/db.ts +82 -7
- package/src/be/swarm-config-guard.ts +30 -0
- package/src/heartbeat/heartbeat.ts +21 -0
- package/src/http/index.ts +33 -33
- package/src/http/route-def.ts +93 -4
- package/src/http/stats.ts +37 -1
- package/src/http/tasks.ts +93 -0
- package/src/http/utils.ts +94 -0
- package/src/otel-impl.ts +21 -3
- package/src/otel.ts +15 -4
- package/src/slack/blocks.ts +1 -0
- package/src/slack/handlers.ts +7 -0
- package/src/tasks/sibling-awareness.ts +1 -0
- package/src/tasks/sibling-block.ts +17 -4
- package/src/tests/artifact-sdk.test.ts +20 -15
- package/src/tests/db-retention.test.ts +344 -0
- package/src/tests/docs-index-footprint.test.js +4 -5
- package/src/tests/draft-task-dispatch-race.test.ts +189 -0
- package/src/tests/events-http.test.ts +70 -27
- package/src/tests/otel-abort-span.test.ts +156 -0
- package/src/tests/otel-span-kind.test.ts +59 -0
- package/src/tests/promote-draft-task-route.test.ts +175 -0
- package/src/tests/route-def-find-route.test.ts +90 -4
- package/src/tests/sibling-block.test.ts +29 -1
- package/src/tests/slack-assistant-comention-production.test.ts +7 -1
- package/src/tests/steering-enabled.test.ts +6 -0
- package/src/tests/swarm-config-reserved-keys.test.ts +27 -0
- package/src/types.ts +2 -1
- package/templates/skills/swarm-scripts/SKILL.md +4 -0
- package/templates/skills/swarm-scripts/content.md +4 -0
|
@@ -155,10 +155,11 @@ import {
|
|
|
155
155
|
verifyAgentMailWebhook,
|
|
156
156
|
verifyGitLabWebhook,
|
|
157
157
|
verifyWebhookSignature,
|
|
158
|
+
wireHttpSpanLifecycle,
|
|
158
159
|
withRemoteContext,
|
|
159
160
|
withSpanContext,
|
|
160
161
|
writeSkillsToFilesystem
|
|
161
|
-
} from "./cli-
|
|
162
|
+
} from "./cli-ads0hfw2.js";
|
|
162
163
|
import"./cli-mnm7w46e.js";
|
|
163
164
|
import {
|
|
164
165
|
Anthropic
|
|
@@ -179,7 +180,7 @@ import {
|
|
|
179
180
|
checkHeartbeatChecklist,
|
|
180
181
|
runHeartbeatSweep,
|
|
181
182
|
stopHeartbeat
|
|
182
|
-
} from "./cli-
|
|
183
|
+
} from "./cli-4gzv54ss.js";
|
|
183
184
|
import {
|
|
184
185
|
AGENT_MAX_TASKS_CONFIG_KEY,
|
|
185
186
|
createResumeFollowUp,
|
|
@@ -194,7 +195,7 @@ import {
|
|
|
194
195
|
touchRuntimeInstance,
|
|
195
196
|
upsertRuntimeInstance,
|
|
196
197
|
upsertSwarmConfigWithPolicyMirror
|
|
197
|
-
} from "./cli-
|
|
198
|
+
} from "./cli-5bnz1t86.js";
|
|
198
199
|
import {
|
|
199
200
|
isMultiRuntimeEnabled
|
|
200
201
|
} from "./cli-qh4sqfws.js";
|
|
@@ -204,16 +205,16 @@ import {
|
|
|
204
205
|
ensure,
|
|
205
206
|
initialize,
|
|
206
207
|
require_dist
|
|
207
|
-
} from "./cli-
|
|
208
|
+
} from "./cli-fpjmcbhz.js";
|
|
208
209
|
import {
|
|
209
210
|
getModelsCatalog
|
|
210
|
-
} from "./cli-
|
|
211
|
+
} from "./cli-z6e8eqrm.js";
|
|
211
212
|
import {
|
|
212
213
|
normalizeModelKey
|
|
213
|
-
} from "./cli-
|
|
214
|
+
} from "./cli-tee8w7tq.js";
|
|
214
215
|
import {
|
|
215
216
|
getUserGrant
|
|
216
|
-
} from "./cli-
|
|
217
|
+
} from "./cli-3y553gws.js";
|
|
217
218
|
import {
|
|
218
219
|
can,
|
|
219
220
|
clearAuditSink,
|
|
@@ -230,12 +231,12 @@ import {
|
|
|
230
231
|
scriptSdkTypesWithGeneratedApis,
|
|
231
232
|
scriptStdlibTypesWithGeneratedApis,
|
|
232
233
|
typecheckScript
|
|
233
|
-
} from "./cli-
|
|
234
|
+
} from "./cli-54ht104h.js";
|
|
234
235
|
import {
|
|
235
236
|
collectScriptReferences,
|
|
236
237
|
getApp,
|
|
237
238
|
listAppRecords
|
|
238
|
-
} from "./cli-
|
|
239
|
+
} from "./cli-68vayryq.js";
|
|
239
240
|
import {
|
|
240
241
|
RawLlmConfigSchema,
|
|
241
242
|
RawLlmOutputSchema,
|
|
@@ -254,7 +255,7 @@ import {
|
|
|
254
255
|
validateDefinition,
|
|
255
256
|
validateJsonSchema,
|
|
256
257
|
verifyHmacSignature
|
|
257
|
-
} from "./cli-
|
|
258
|
+
} from "./cli-jjhnma34.js";
|
|
258
259
|
import"./cli-3dpj7atn.js";
|
|
259
260
|
import {
|
|
260
261
|
ConnectionAuthInputSchema,
|
|
@@ -327,14 +328,14 @@ import {
|
|
|
327
328
|
upsertMcpOAuthToken,
|
|
328
329
|
upsertScriptByName,
|
|
329
330
|
upsertScriptConnection
|
|
330
|
-
} from "./cli-
|
|
331
|
+
} from "./cli-bnq8h7ea.js";
|
|
331
332
|
import"./cli-epan13p1.js";
|
|
332
333
|
import {
|
|
333
334
|
getApiKey
|
|
334
335
|
} from "./cli-f14fvzag.js";
|
|
335
336
|
import {
|
|
336
337
|
searchScripts
|
|
337
|
-
} from "./cli-
|
|
338
|
+
} from "./cli-qckgdqmr.js";
|
|
338
339
|
import {
|
|
339
340
|
CANDIDATE_SET_MULTIPLIER,
|
|
340
341
|
getEmbeddingProvider,
|
|
@@ -342,7 +343,7 @@ import {
|
|
|
342
343
|
init_constants as init_constants2,
|
|
343
344
|
init_reranker,
|
|
344
345
|
rerank
|
|
345
|
-
} from "./cli-
|
|
346
|
+
} from "./cli-hz5hp6wn.js";
|
|
346
347
|
import"./cli-dr5tcz68.js";
|
|
347
348
|
import"./cli-vsap7a8d.js";
|
|
348
349
|
import {
|
|
@@ -368,7 +369,7 @@ import {
|
|
|
368
369
|
updateAuthorizationIdentity,
|
|
369
370
|
updateOAuthAppById,
|
|
370
371
|
upsertAuthorization
|
|
371
|
-
} from "./cli-
|
|
372
|
+
} from "./cli-m3z53bed.js";
|
|
372
373
|
import"./cli-fad8m16k.js";
|
|
373
374
|
import {
|
|
374
375
|
getFileStorageProvider
|
|
@@ -377,7 +378,7 @@ import {
|
|
|
377
378
|
FilesError,
|
|
378
379
|
normalizeFilesError
|
|
379
380
|
} from "./cli-fhsz3twr.js";
|
|
380
|
-
import"./cli-
|
|
381
|
+
import"./cli-84vrhesc.js";
|
|
381
382
|
import {
|
|
382
383
|
findUserById,
|
|
383
384
|
fingerprintApiKey,
|
|
@@ -393,15 +394,15 @@ import {
|
|
|
393
394
|
resolveUserByToken,
|
|
394
395
|
revokeToken,
|
|
395
396
|
unlinkIdentity
|
|
396
|
-
} from "./cli-
|
|
397
|
+
} from "./cli-spf767vc.js";
|
|
397
398
|
import {
|
|
398
399
|
createTaskWithSiblingAwareness
|
|
399
|
-
} from "./cli-
|
|
400
|
+
} from "./cli-gpdtxzar.js";
|
|
400
401
|
import {
|
|
401
402
|
getSlackApp,
|
|
402
403
|
startSlackApp,
|
|
403
404
|
stopSlackApp
|
|
404
|
-
} from "./cli-
|
|
405
|
+
} from "./cli-d5ygfv18.js";
|
|
405
406
|
import"./cli-qf9kpsve.js";
|
|
406
407
|
import"./cli-g2p9bd1z.js";
|
|
407
408
|
import"./cli-5tnr64pm.js";
|
|
@@ -449,6 +450,7 @@ import {
|
|
|
449
450
|
KvNamespaceSchema,
|
|
450
451
|
KvTypeCollisionError,
|
|
451
452
|
KvValueTypeSchema,
|
|
453
|
+
MAX_DB_RETENTION_DAYS,
|
|
452
454
|
McpAuthMethodSchema,
|
|
453
455
|
McpServerSchema,
|
|
454
456
|
McpServerWithInstallInfoSchema,
|
|
@@ -729,6 +731,7 @@ import {
|
|
|
729
731
|
pageContextKey,
|
|
730
732
|
pauseTask,
|
|
731
733
|
placeholderForConfigKey,
|
|
734
|
+
promoteDraftTask,
|
|
732
735
|
recordBudgetRefusalNotification,
|
|
733
736
|
recordInlineScriptRun,
|
|
734
737
|
recordKeyRateLimitWindows,
|
|
@@ -789,7 +792,7 @@ import {
|
|
|
789
792
|
upsertSwarmConfig,
|
|
790
793
|
validateConfigValue,
|
|
791
794
|
withFavoriteFlags
|
|
792
|
-
} from "./cli-
|
|
795
|
+
} from "./cli-tmn19cdz.js";
|
|
793
796
|
import {
|
|
794
797
|
IDENTITY_FIELD_BUDGETS,
|
|
795
798
|
IdentityFieldBudgetError,
|
|
@@ -831,7 +834,7 @@ import {
|
|
|
831
834
|
import {
|
|
832
835
|
init_package,
|
|
833
836
|
package_default
|
|
834
|
-
} from "./cli-
|
|
837
|
+
} from "./cli-4r4jkqep.js";
|
|
835
838
|
import {
|
|
836
839
|
array,
|
|
837
840
|
exports_external,
|
|
@@ -883,6 +886,189 @@ import {
|
|
|
883
886
|
} from "node:http";
|
|
884
887
|
init_db();
|
|
885
888
|
|
|
889
|
+
// src/be/db-retention.ts
|
|
890
|
+
init_env_flag();
|
|
891
|
+
init_db();
|
|
892
|
+
init_swarm_config_guard();
|
|
893
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
894
|
+
var DAY_MS = 24 * 60 * 60 * 1000;
|
|
895
|
+
var RETENTION_INTERVAL_MS = 60 * 60 * 1000;
|
|
896
|
+
var BATCH_SIZE = 5000;
|
|
897
|
+
var PER_TABLE_BATCH_CAP = 40;
|
|
898
|
+
var WALL_CLOCK_CAP_MS = 60000;
|
|
899
|
+
var YIELD_MS = 5;
|
|
900
|
+
var DB_RETENTION_TABLES = [
|
|
901
|
+
{
|
|
902
|
+
table: "session_logs",
|
|
903
|
+
timeColumn: "createdAt",
|
|
904
|
+
envKey: "SESSION_LOG_RETENTION_DAYS",
|
|
905
|
+
metricsKey: "sessionLogs"
|
|
906
|
+
},
|
|
907
|
+
{
|
|
908
|
+
table: "agent_log",
|
|
909
|
+
timeColumn: "createdAt",
|
|
910
|
+
envKey: "AGENT_LOG_RETENTION_DAYS",
|
|
911
|
+
metricsKey: "agentLog"
|
|
912
|
+
},
|
|
913
|
+
{
|
|
914
|
+
table: "events",
|
|
915
|
+
timeColumn: "createdAt",
|
|
916
|
+
envKey: "EVENTS_RETENTION_DAYS",
|
|
917
|
+
metricsKey: "events"
|
|
918
|
+
}
|
|
919
|
+
];
|
|
920
|
+
var retentionTimer = null;
|
|
921
|
+
var retentionTickPromise = null;
|
|
922
|
+
var retentionAbortController = null;
|
|
923
|
+
var retentionStats = {};
|
|
924
|
+
var cumulativeRowsDeleted = {};
|
|
925
|
+
var scheduleContextFree = AsyncLocalStorage.snapshot();
|
|
926
|
+
function readPositiveIntEnv(key, env = process.env) {
|
|
927
|
+
const raw = env[key]?.trim();
|
|
928
|
+
if (!raw || !/^\d+$/.test(raw))
|
|
929
|
+
return null;
|
|
930
|
+
const value = Number(raw);
|
|
931
|
+
return Number.isSafeInteger(value) && value >= 1 && value <= MAX_DB_RETENTION_DAYS ? value : null;
|
|
932
|
+
}
|
|
933
|
+
function yieldTick() {
|
|
934
|
+
return new Promise((resolve) => setTimeout(resolve, YIELD_MS));
|
|
935
|
+
}
|
|
936
|
+
function retentionDays(table) {
|
|
937
|
+
return readPositiveIntEnv(table.envKey);
|
|
938
|
+
}
|
|
939
|
+
function dryRunEnabled(env = process.env) {
|
|
940
|
+
const raw = env.DB_RETENTION_DRY_RUN;
|
|
941
|
+
if (raw === undefined || raw.trim() === "")
|
|
942
|
+
return false;
|
|
943
|
+
return isEnvFlagEnabled("DB_RETENTION_DRY_RUN", true, env);
|
|
944
|
+
}
|
|
945
|
+
async function sweepTable(table, cutoff, dryRun, deadline, batchSize, perTableBatchCap, signal) {
|
|
946
|
+
const client = getDbClient();
|
|
947
|
+
let rowsDeleted = 0;
|
|
948
|
+
let batches = 0;
|
|
949
|
+
let pagesFetched = 0;
|
|
950
|
+
let cursor = null;
|
|
951
|
+
let complete = true;
|
|
952
|
+
let exhausted = false;
|
|
953
|
+
const pageLimit = dryRun ? Number.POSITIVE_INFINITY : perTableBatchCap;
|
|
954
|
+
while (!signal.aborted && pagesFetched < pageLimit && Date.now() < deadline) {
|
|
955
|
+
const page = await client.query(`SELECT id, ${table.timeColumn} AS createdAt
|
|
956
|
+
FROM ${table.table}
|
|
957
|
+
${cursor === null ? "" : "WHERE id > ?"}
|
|
958
|
+
ORDER BY id
|
|
959
|
+
LIMIT ?`, cursor === null ? [batchSize] : [cursor, batchSize]);
|
|
960
|
+
pagesFetched += 1;
|
|
961
|
+
if (Date.now() >= deadline || signal.aborted) {
|
|
962
|
+
complete = false;
|
|
963
|
+
break;
|
|
964
|
+
}
|
|
965
|
+
if (page.length === 0) {
|
|
966
|
+
exhausted = true;
|
|
967
|
+
break;
|
|
968
|
+
}
|
|
969
|
+
cursor = page[page.length - 1]?.id ?? null;
|
|
970
|
+
const expiredIds = page.filter((row) => row.createdAt < cutoff).map((row) => row.id);
|
|
971
|
+
if (expiredIds.length > 0) {
|
|
972
|
+
if (dryRun) {
|
|
973
|
+
rowsDeleted += expiredIds.length;
|
|
974
|
+
} else {
|
|
975
|
+
const placeholders = expiredIds.map(() => "?").join(", ");
|
|
976
|
+
const result = await client.run(`DELETE FROM ${table.table} WHERE id IN (${placeholders})`, expiredIds);
|
|
977
|
+
rowsDeleted += result.changes;
|
|
978
|
+
}
|
|
979
|
+
batches += 1;
|
|
980
|
+
}
|
|
981
|
+
if (page.length < batchSize) {
|
|
982
|
+
exhausted = true;
|
|
983
|
+
break;
|
|
984
|
+
}
|
|
985
|
+
await yieldTick();
|
|
986
|
+
}
|
|
987
|
+
return { rowsDeleted, batches, complete: !dryRun || complete && exhausted };
|
|
988
|
+
}
|
|
989
|
+
function runDbRetentionTick(options = {}) {
|
|
990
|
+
if (retentionTickPromise)
|
|
991
|
+
return retentionTickPromise;
|
|
992
|
+
const abortController = new AbortController;
|
|
993
|
+
retentionAbortController = abortController;
|
|
994
|
+
const promise = Promise.resolve().then(async () => {
|
|
995
|
+
try {
|
|
996
|
+
const tickStartedAt = Date.now();
|
|
997
|
+
const cutoffBase = options.now ?? new Date(tickStartedAt);
|
|
998
|
+
const dryRun = dryRunEnabled();
|
|
999
|
+
const batchSize = options.batchSize ?? BATCH_SIZE;
|
|
1000
|
+
const perTableBatchCap = options.perTableBatchCap ?? PER_TABLE_BATCH_CAP;
|
|
1001
|
+
const deadline = tickStartedAt + (options.wallClockCapMs ?? WALL_CLOCK_CAP_MS);
|
|
1002
|
+
let deletedAny = false;
|
|
1003
|
+
for (const table of DB_RETENTION_TABLES) {
|
|
1004
|
+
if (abortController.signal.aborted || Date.now() >= deadline)
|
|
1005
|
+
break;
|
|
1006
|
+
const days = retentionDays(table);
|
|
1007
|
+
if (days === null)
|
|
1008
|
+
continue;
|
|
1009
|
+
const startedAt = Date.now();
|
|
1010
|
+
try {
|
|
1011
|
+
const cutoff = new Date(cutoffBase.getTime() - days * DAY_MS).toISOString();
|
|
1012
|
+
const result = await sweepTable(table, cutoff, dryRun, deadline, batchSize, perTableBatchCap, abortController.signal);
|
|
1013
|
+
if (dryRun && !result.complete) {
|
|
1014
|
+
throw new Error("dry-run count stopped before completion");
|
|
1015
|
+
}
|
|
1016
|
+
deletedAny ||= !dryRun && result.rowsDeleted > 0;
|
|
1017
|
+
const cumulative = (cumulativeRowsDeleted[table.metricsKey] ?? 0) + (dryRun ? 0 : result.rowsDeleted);
|
|
1018
|
+
cumulativeRowsDeleted[table.metricsKey] = cumulative;
|
|
1019
|
+
retentionStats[table.metricsKey] = {
|
|
1020
|
+
at: new Date().toISOString(),
|
|
1021
|
+
rowsDeleted: result.rowsDeleted,
|
|
1022
|
+
batches: result.batches,
|
|
1023
|
+
durationMs: Date.now() - startedAt,
|
|
1024
|
+
dryRun,
|
|
1025
|
+
cumulativeRowsDeleted: cumulative
|
|
1026
|
+
};
|
|
1027
|
+
if (result.rowsDeleted > 0) {
|
|
1028
|
+
console.log(`[db-retention] ${table.table}: ${dryRun ? "would delete" : "deleted"} ${result.rowsDeleted} row(s) in ${result.batches} batch(es) after ${Date.now() - startedAt}ms`);
|
|
1029
|
+
}
|
|
1030
|
+
} catch (err) {
|
|
1031
|
+
console.error(`[db-retention] ${table.table} sweep failed:`, err.message);
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
if (deletedAny && !abortController.signal.aborted) {
|
|
1035
|
+
try {
|
|
1036
|
+
await getDbClient().run("PRAGMA incremental_vacuum(2000)");
|
|
1037
|
+
} catch (err) {
|
|
1038
|
+
console.error("[db-retention] incremental vacuum failed:", err.message);
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
} finally {
|
|
1042
|
+
if (retentionAbortController === abortController)
|
|
1043
|
+
retentionAbortController = null;
|
|
1044
|
+
retentionTickPromise = null;
|
|
1045
|
+
}
|
|
1046
|
+
});
|
|
1047
|
+
retentionTickPromise = promise;
|
|
1048
|
+
return promise;
|
|
1049
|
+
}
|
|
1050
|
+
function getDbRetentionStats() {
|
|
1051
|
+
return { ...retentionStats };
|
|
1052
|
+
}
|
|
1053
|
+
async function startDbRetention(intervalMs = RETENTION_INTERVAL_MS) {
|
|
1054
|
+
if (retentionTimer)
|
|
1055
|
+
return;
|
|
1056
|
+
const configured = DB_RETENTION_TABLES.map((table) => `${table.table}=${retentionDays(table) ?? "disabled"}`).join(", ");
|
|
1057
|
+
console.log(`[db-retention] starting (${configured}, dryRun=${dryRunEnabled()})`);
|
|
1058
|
+
retentionTimer = scheduleContextFree(() => setInterval(() => void runDbRetentionTick(), intervalMs));
|
|
1059
|
+
if (typeof retentionTimer.unref === "function")
|
|
1060
|
+
retentionTimer.unref();
|
|
1061
|
+
await runDbRetentionTick();
|
|
1062
|
+
}
|
|
1063
|
+
async function stopDbRetention() {
|
|
1064
|
+
if (retentionTimer) {
|
|
1065
|
+
clearInterval(retentionTimer);
|
|
1066
|
+
retentionTimer = null;
|
|
1067
|
+
}
|
|
1068
|
+
retentionAbortController?.abort();
|
|
1069
|
+
await retentionTickPromise;
|
|
1070
|
+
}
|
|
1071
|
+
|
|
886
1072
|
// src/be/scripts/retention.ts
|
|
887
1073
|
init_db();
|
|
888
1074
|
var SCRATCH_RETENTION_DAYS = 14;
|
|
@@ -18693,7 +18879,33 @@ var SwarmMetricsSchema = exports_external.object({
|
|
|
18693
18879
|
workflows: exports_external.object({ total: exports_external.number(), enabled: exports_external.number() }),
|
|
18694
18880
|
pages: exports_external.object({ total: exports_external.number() }),
|
|
18695
18881
|
sessions: exports_external.object({ active: exports_external.number() }),
|
|
18696
|
-
skills: exports_external.object({ total: exports_external.number() })
|
|
18882
|
+
skills: exports_external.object({ total: exports_external.number() }),
|
|
18883
|
+
retention: exports_external.object({
|
|
18884
|
+
sessionLogs: exports_external.object({
|
|
18885
|
+
at: exports_external.string(),
|
|
18886
|
+
rowsDeleted: exports_external.number(),
|
|
18887
|
+
batches: exports_external.number(),
|
|
18888
|
+
durationMs: exports_external.number(),
|
|
18889
|
+
dryRun: exports_external.boolean(),
|
|
18890
|
+
cumulativeRowsDeleted: exports_external.number()
|
|
18891
|
+
}).optional(),
|
|
18892
|
+
agentLog: exports_external.object({
|
|
18893
|
+
at: exports_external.string(),
|
|
18894
|
+
rowsDeleted: exports_external.number(),
|
|
18895
|
+
batches: exports_external.number(),
|
|
18896
|
+
durationMs: exports_external.number(),
|
|
18897
|
+
dryRun: exports_external.boolean(),
|
|
18898
|
+
cumulativeRowsDeleted: exports_external.number()
|
|
18899
|
+
}).optional(),
|
|
18900
|
+
events: exports_external.object({
|
|
18901
|
+
at: exports_external.string(),
|
|
18902
|
+
rowsDeleted: exports_external.number(),
|
|
18903
|
+
batches: exports_external.number(),
|
|
18904
|
+
durationMs: exports_external.number(),
|
|
18905
|
+
dryRun: exports_external.boolean(),
|
|
18906
|
+
cumulativeRowsDeleted: exports_external.number()
|
|
18907
|
+
}).optional()
|
|
18908
|
+
})
|
|
18697
18909
|
});
|
|
18698
18910
|
var ConcurrentContextSchema = exports_external.object({
|
|
18699
18911
|
processingInboxMessages: exports_external.array(exports_external.object({
|
|
@@ -18848,7 +19060,10 @@ async function handleStats(req, res, pathSegments, queryParams, myAgentId) {
|
|
|
18848
19060
|
return true;
|
|
18849
19061
|
}
|
|
18850
19062
|
if (getMetrics.match(req.method, pathSegments)) {
|
|
18851
|
-
getMetrics.respond(res, 200,
|
|
19063
|
+
getMetrics.respond(res, 200, {
|
|
19064
|
+
...await getSwarmMetrics(),
|
|
19065
|
+
retention: getDbRetentionStats()
|
|
19066
|
+
});
|
|
18852
19067
|
return true;
|
|
18853
19068
|
}
|
|
18854
19069
|
if (listServices.match(req.method, pathSegments)) {
|
|
@@ -19512,13 +19727,29 @@ var createTask = route({
|
|
|
19512
19727
|
requestedByUserId: exports_external.string().optional(),
|
|
19513
19728
|
model: exports_external.string().optional(),
|
|
19514
19729
|
modelTier: ModelTierSchema.optional(),
|
|
19515
|
-
effort: ReasoningEffortSchema.optional()
|
|
19730
|
+
effort: ReasoningEffortSchema.optional(),
|
|
19731
|
+
draft: exports_external.boolean().optional()
|
|
19516
19732
|
}),
|
|
19517
19733
|
responses: {
|
|
19518
19734
|
201: { description: "Task created", schema: AgentTaskSchema },
|
|
19519
19735
|
400: { description: "Validation error" }
|
|
19520
19736
|
}
|
|
19521
19737
|
});
|
|
19738
|
+
var promoteDraftTaskRoute = route({
|
|
19739
|
+
method: "post",
|
|
19740
|
+
path: "/api/tasks/{id}/promote-draft",
|
|
19741
|
+
pattern: ["api", "tasks", null, "promote-draft"],
|
|
19742
|
+
summary: "Promote a draft task out of the pre-dispatch draft state",
|
|
19743
|
+
description: "Transitions a `draft` task (#1240 — created with attachments still uploading) to its normal dispatch-eligible status: `offered` if it was offered to an agent, `pending` if it has an owning agent (the common case — UI-composer tasks default to Lead), otherwise `unassigned`. Called by the UI composer once its attachment upload batch settles, whether every file uploaded, some failed, or all failed — a draft must never be stranded by an upload error. Idempotent: calling it on a task that already left `draft` returns the current task unchanged rather than erroring, so a retried request is safe.",
|
|
19744
|
+
tags: ["Tasks"],
|
|
19745
|
+
params: exports_external.object({ id: exports_external.string() }),
|
|
19746
|
+
rbac: { permission: "task.action.own" },
|
|
19747
|
+
responses: {
|
|
19748
|
+
200: { description: "Task promoted (or already out of draft)", schema: AgentTaskSchema },
|
|
19749
|
+
403: { description: "Caller does not own this task" },
|
|
19750
|
+
404: { description: "Task not found" }
|
|
19751
|
+
}
|
|
19752
|
+
});
|
|
19522
19753
|
var updateSession = route({
|
|
19523
19754
|
method: "put",
|
|
19524
19755
|
path: "/api/tasks/{id}/session",
|
|
@@ -19867,6 +20098,30 @@ async function canSteerTask(req, myAgentId, task) {
|
|
|
19867
20098
|
}
|
|
19868
20099
|
return can({ principal, verb, resource, source: "http" }).allow;
|
|
19869
20100
|
}
|
|
20101
|
+
async function canActOnOwnTask(req, myAgentId, task) {
|
|
20102
|
+
const resource = {
|
|
20103
|
+
kind: "task",
|
|
20104
|
+
taskId: task.id,
|
|
20105
|
+
requestedByUserId: task.requestedByUserId,
|
|
20106
|
+
creatorAgentId: task.creatorAgentId,
|
|
20107
|
+
agentId: task.agentId
|
|
20108
|
+
};
|
|
20109
|
+
let principal;
|
|
20110
|
+
const auth = getRequestAuth(req);
|
|
20111
|
+
if (auth?.kind === "operator") {
|
|
20112
|
+
principal = { kind: "operator" };
|
|
20113
|
+
} else if (auth?.kind === "user") {
|
|
20114
|
+
principal = { kind: "user", userId: auth.userId };
|
|
20115
|
+
} else {
|
|
20116
|
+
if (!myAgentId)
|
|
20117
|
+
return false;
|
|
20118
|
+
const agent = await getAgentById(myAgentId);
|
|
20119
|
+
if (!agent)
|
|
20120
|
+
return false;
|
|
20121
|
+
principal = { kind: "agent", agentId: myAgentId, isLead: agent.isLead };
|
|
20122
|
+
}
|
|
20123
|
+
return can({ principal, verb: "task.action.own", resource, source: "http" }).allow;
|
|
20124
|
+
}
|
|
19870
20125
|
async function handleTasks(req, res, pathSegments, queryParams, myAgentId) {
|
|
19871
20126
|
if (listTasks.match(req.method, pathSegments)) {
|
|
19872
20127
|
const parsed = await listTasks.parse(req, res, pathSegments, queryParams);
|
|
@@ -19969,6 +20224,7 @@ async function handleTasks(req, res, pathSegments, queryParams, myAgentId) {
|
|
|
19969
20224
|
outputSchema: parsed.body.outputSchema || undefined,
|
|
19970
20225
|
contextKey: parsed.body.contextKey || undefined,
|
|
19971
20226
|
requestedByUserId,
|
|
20227
|
+
status: parsed.body.draft ? "draft" : undefined,
|
|
19972
20228
|
...splitLegacyModelAlias({
|
|
19973
20229
|
model: parsed.body.model,
|
|
19974
20230
|
modelTier: parsed.body.modelTier
|
|
@@ -19997,6 +20253,28 @@ async function handleTasks(req, res, pathSegments, queryParams, myAgentId) {
|
|
|
19997
20253
|
}
|
|
19998
20254
|
return true;
|
|
19999
20255
|
}
|
|
20256
|
+
if (promoteDraftTaskRoute.match(req.method, pathSegments)) {
|
|
20257
|
+
const parsed = await promoteDraftTaskRoute.parse(req, res, pathSegments, queryParams);
|
|
20258
|
+
if (!parsed)
|
|
20259
|
+
return true;
|
|
20260
|
+
const existingTask = await getTaskById(parsed.params.id);
|
|
20261
|
+
if (!existingTask) {
|
|
20262
|
+
jsonError(res, "Task not found", 404);
|
|
20263
|
+
return true;
|
|
20264
|
+
}
|
|
20265
|
+
const allowed = await canActOnOwnTask(req, myAgentId, existingTask);
|
|
20266
|
+
if (!allowed) {
|
|
20267
|
+
jsonError(res, "Not authorized to act on this task", 403);
|
|
20268
|
+
return true;
|
|
20269
|
+
}
|
|
20270
|
+
const promoted = existingTask.status === "draft" ? await promoteDraftTask(parsed.params.id) : existingTask;
|
|
20271
|
+
if (!promoted) {
|
|
20272
|
+
jsonError(res, "Task not found", 404);
|
|
20273
|
+
return true;
|
|
20274
|
+
}
|
|
20275
|
+
promoteDraftTaskRoute.respond(res, 200, promoted);
|
|
20276
|
+
return true;
|
|
20277
|
+
}
|
|
20000
20278
|
if (updateSession.match(req.method, pathSegments)) {
|
|
20001
20279
|
const parsed = await updateSession.parse(req, res, pathSegments, queryParams);
|
|
20002
20280
|
if (!parsed)
|
|
@@ -23745,7 +24023,6 @@ var transportActivityUser = globalState.__transportActivityUser ?? {};
|
|
|
23745
24023
|
var httpServer = createHttpServer(async (req, res) => {
|
|
23746
24024
|
const startTime = performance.now();
|
|
23747
24025
|
let statusCode = 200;
|
|
23748
|
-
let spanEnded = false;
|
|
23749
24026
|
const originalWriteHead = res.writeHead.bind(res);
|
|
23750
24027
|
res.writeHead = (code, ...args) => {
|
|
23751
24028
|
statusCode = code;
|
|
@@ -23763,8 +24040,10 @@ var httpServer = createHttpServer(async (req, res) => {
|
|
|
23763
24040
|
await withRemoteContext(req.headers, async () => {
|
|
23764
24041
|
const reqPath = req.url?.split("?")[0] ?? "";
|
|
23765
24042
|
const pathSegments = getPathSegments(req.url || "");
|
|
24043
|
+
const hasQueryString = (req.url ?? "").includes("?");
|
|
24044
|
+
const hasTrailingSlash = reqPath.length > 1 && reqPath.endsWith("/");
|
|
23766
24045
|
const skipSpan = reqPath === "/api/poll" && !isPollTracingEnabled();
|
|
23767
|
-
const { spanName, httpRoute } = describeRequestRoute(req.method, pathSegments);
|
|
24046
|
+
const { spanName, httpRoute } = describeRequestRoute(req.method, pathSegments, hasQueryString, hasTrailingSlash);
|
|
23768
24047
|
const semconv = httpServerSemconvAttributes(req);
|
|
23769
24048
|
const span = skipSpan ? null : startSpan(spanName, {
|
|
23770
24049
|
"http.request.method": req.method ?? "",
|
|
@@ -23776,29 +24055,9 @@ var httpServer = createHttpServer(async (req, res) => {
|
|
|
23776
24055
|
"user_agent.original": semconv["user_agent.original"],
|
|
23777
24056
|
"agent.id": req.headers["x-agent-id"],
|
|
23778
24057
|
"agentswarm.component": "api"
|
|
23779
|
-
});
|
|
24058
|
+
}, { kind: "server" });
|
|
23780
24059
|
if (span) {
|
|
23781
|
-
res
|
|
23782
|
-
if (spanEnded)
|
|
23783
|
-
return;
|
|
23784
|
-
spanEnded = true;
|
|
23785
|
-
span.setAttributes({
|
|
23786
|
-
"http.response.status_code": statusCode,
|
|
23787
|
-
"agentswarm.http.duration_ms": Math.round((performance.now() - startTime) * 10) / 10
|
|
23788
|
-
});
|
|
23789
|
-
if (statusCode >= 500) {
|
|
23790
|
-
span.setStatus({ code: 2, message: `HTTP ${statusCode}` });
|
|
23791
|
-
}
|
|
23792
|
-
span.end();
|
|
23793
|
-
});
|
|
23794
|
-
res.on("error", (err) => {
|
|
23795
|
-
if (spanEnded)
|
|
23796
|
-
return;
|
|
23797
|
-
spanEnded = true;
|
|
23798
|
-
span.recordException(err);
|
|
23799
|
-
span.setStatus({ code: 2, message: err.message });
|
|
23800
|
-
span.end();
|
|
23801
|
-
});
|
|
24060
|
+
wireHttpSpanLifecycle(res, span, () => statusCode, startTime);
|
|
23802
24061
|
}
|
|
23803
24062
|
const handleRequest = async () => {
|
|
23804
24063
|
setCorsHeaders(req, res);
|
|
@@ -23908,7 +24167,7 @@ async function shutdown() {
|
|
|
23908
24167
|
sessionsProcessed: getServerSessionsProcessed()
|
|
23909
24168
|
});
|
|
23910
24169
|
if (hasCapability("scheduling")) {
|
|
23911
|
-
const { stopScheduler } = await import("./index-
|
|
24170
|
+
const { stopScheduler } = await import("./index-racb4wfq.js");
|
|
23912
24171
|
stopScheduler();
|
|
23913
24172
|
}
|
|
23914
24173
|
stopHeartbeat();
|
|
@@ -23916,11 +24175,12 @@ async function shutdown() {
|
|
|
23916
24175
|
await stopScriptRunSupervisor();
|
|
23917
24176
|
await stopSlackApp();
|
|
23918
24177
|
if (process.env.OAUTH_KEEPALIVE_DISABLE !== "true") {
|
|
23919
|
-
const { stopOAuthKeepalive } = await import("./keepalive-
|
|
24178
|
+
const { stopOAuthKeepalive } = await import("./keepalive-wxjd633a.js");
|
|
23920
24179
|
await stopOAuthKeepalive();
|
|
23921
24180
|
}
|
|
23922
24181
|
stopOAuthPendingGc();
|
|
23923
24182
|
stopMemoryGc();
|
|
24183
|
+
await stopDbRetention();
|
|
23924
24184
|
stopScratchScriptGc();
|
|
23925
24185
|
stopAuditGc();
|
|
23926
24186
|
stopAuditWriter();
|
|
@@ -23980,15 +24240,15 @@ try {
|
|
|
23980
24240
|
console.warn("[startup] CAPABILITIES upgrade seed failed (non-fatal):", err);
|
|
23981
24241
|
}
|
|
23982
24242
|
try {
|
|
23983
|
-
const { seedPricingFromModelsDev } = await import("./seed-pricing-
|
|
24243
|
+
const { seedPricingFromModelsDev } = await import("./seed-pricing-nbmd7ah8.js");
|
|
23984
24244
|
seedPricingFromModelsDev();
|
|
23985
|
-
const { startPricingRefreshLoop } = await import("./pricing-refresh-
|
|
24245
|
+
const { startPricingRefreshLoop } = await import("./pricing-refresh-mkyy7c2y.js");
|
|
23986
24246
|
startPricingRefreshLoop();
|
|
23987
24247
|
} catch (err) {
|
|
23988
24248
|
console.error("[startup] Failed to seed pricing rows:", err);
|
|
23989
24249
|
}
|
|
23990
24250
|
try {
|
|
23991
|
-
const { ensureRbacSeedsSynced } = await import("./rbac-roles-
|
|
24251
|
+
const { ensureRbacSeedsSynced } = await import("./rbac-roles-kb3afm95.js");
|
|
23992
24252
|
ensureRbacSeedsSynced();
|
|
23993
24253
|
} catch (err) {
|
|
23994
24254
|
console.error("[startup] Failed to sync RBAC seed rows:", err);
|
|
@@ -23996,7 +24256,7 @@ try {
|
|
|
23996
24256
|
throw err;
|
|
23997
24257
|
}
|
|
23998
24258
|
try {
|
|
23999
|
-
const { runAllSeeders } = await import("./index-
|
|
24259
|
+
const { runAllSeeders } = await import("./index-17h657rg.js");
|
|
24000
24260
|
await runAllSeeders({ scriptEmbeddingMode: "skip" });
|
|
24001
24261
|
} catch (err) {
|
|
24002
24262
|
console.error("[startup] Failed to seed built-in entities:", err);
|
|
@@ -24034,35 +24294,36 @@ httpServer.listen(port, async () => {
|
|
|
24034
24294
|
await initWorkflows();
|
|
24035
24295
|
await startScriptRunSupervisor(getMcpBaseUrl());
|
|
24036
24296
|
if (hasCapability("scheduling")) {
|
|
24037
|
-
const { startScheduler } = await import("./index-
|
|
24038
|
-
const { getExecutorRegistry: getExecutorRegistry2 } = await import("./index-
|
|
24297
|
+
const { startScheduler } = await import("./index-racb4wfq.js");
|
|
24298
|
+
const { getExecutorRegistry: getExecutorRegistry2 } = await import("./index-zh66wm65.js");
|
|
24039
24299
|
const intervalMs = Number(process.env.SCHEDULER_INTERVAL_MS) || 1e4;
|
|
24040
24300
|
startScheduler(getExecutorRegistry2(), intervalMs, {
|
|
24041
24301
|
runId: globalState.__runId
|
|
24042
24302
|
});
|
|
24043
24303
|
}
|
|
24044
24304
|
if (!isEnvFlagEnabled("HEARTBEAT_DISABLE", false)) {
|
|
24045
|
-
const { startHeartbeat } = await import("./index-
|
|
24305
|
+
const { startHeartbeat } = await import("./index-m2p7ctyh.js");
|
|
24046
24306
|
const heartbeatMs = Number(process.env.HEARTBEAT_INTERVAL_MS) || 90000;
|
|
24047
24307
|
startHeartbeat(heartbeatMs);
|
|
24048
24308
|
}
|
|
24049
24309
|
if (process.env.OAUTH_KEEPALIVE_DISABLE !== "true") {
|
|
24050
|
-
const { startOAuthKeepalive } = await import("./keepalive-
|
|
24310
|
+
const { startOAuthKeepalive } = await import("./keepalive-wxjd633a.js");
|
|
24051
24311
|
startOAuthKeepalive();
|
|
24052
24312
|
}
|
|
24053
24313
|
if (process.env.OAUTH_REFRESH_SWEEP_DISABLE !== "true") {
|
|
24054
|
-
const { startOAuthRefreshSweep } = await import("./oauth-refresh-sweep-
|
|
24314
|
+
const { startOAuthRefreshSweep } = await import("./oauth-refresh-sweep-jwj22yb8.js");
|
|
24055
24315
|
startOAuthRefreshSweep();
|
|
24056
24316
|
}
|
|
24057
24317
|
startOAuthPendingGc();
|
|
24058
24318
|
await startMemoryGc();
|
|
24059
|
-
|
|
24319
|
+
await startDbRetention();
|
|
24320
|
+
import("./boot-reembed-6spqw4q0.js").then(({ runBootReembed }) => runBootReembed()).catch((err) => {
|
|
24060
24321
|
console.error("[boot-reembed] startup backfill failed (non-fatal):", err);
|
|
24061
24322
|
});
|
|
24062
|
-
import("./boot-reembed-
|
|
24323
|
+
import("./boot-reembed-b22s9w5x.js").then(({ runBootReembedScripts }) => runBootReembedScripts()).catch((err) => {
|
|
24063
24324
|
console.error("[boot-reembed-scripts] startup backfill failed (non-fatal):", err);
|
|
24064
24325
|
});
|
|
24065
|
-
import("./boot-scrub-logs-
|
|
24326
|
+
import("./boot-scrub-logs-6h3cqkc0.js").then(({ runBootScrubLogs }) => runBootScrubLogs()).catch((err) => {
|
|
24066
24327
|
console.error("[boot-scrub-logs] startup scrub failed (non-fatal):", err);
|
|
24067
24328
|
});
|
|
24068
24329
|
}).on("error", (err) => {
|