@desplega.ai/agent-swarm 1.114.0 → 1.116.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-bm8vdxys.js → actions-brtj223f.js} +6 -6
- package/dist/{app-bhwdxmvp.js → app-00sngzz7.js} +4 -4
- package/dist/{assistant-15mp2apr.js → assistant-j2ser3vg.js} +9 -9
- package/dist/{boot-reembed-b9sbk87z.js → boot-reembed-fv3r1kqg.js} +3 -3
- package/dist/{boot-reembed-awr2179r.js → boot-reembed-v4n0jphx.js} +4 -4
- package/dist/{boot-scrub-logs-c1zsaw9m.js → boot-scrub-logs-72sy5z1r.js} +2 -2
- package/dist/{claude-adapter-2k45y7p7.js → claude-adapter-3csn5bks.js} +2 -2
- package/dist/{cli-hq39e630.js → cli-0h9yzvhe.js} +95 -10
- package/dist/{cli-49j095n9.js → cli-0pwtr9f0.js} +1 -1
- package/dist/{cli-zmmp2r79.js → cli-2rxckty2.js} +13 -2
- package/dist/{cli-w3nq88yc.js → cli-3ys55x7x.js} +2 -2
- package/dist/{cli-7rgh0w0k.js → cli-50czs4qy.js} +10 -3
- package/dist/{cli-f9n2jg31.js → cli-5g3hx9cc.js} +2 -2
- package/dist/{cli-0kgcv878.js → cli-86fdnerz.js} +63 -2
- package/dist/{cli-a6tzw6vq.js → cli-96nd7vgs.js} +6 -6
- package/dist/{cli-2t4e4ayk.js → cli-9ys4kdd4.js} +46 -5
- package/dist/{cli-hvg05qwm.js → cli-b4hf0g0x.js} +1 -1
- package/dist/{cli-a0t7vapf.js → cli-bc89my0z.js} +1 -1
- package/dist/{cli-q4e2x252.js → cli-cjmz7pp9.js} +73 -24
- package/dist/{cli-tkmm5nf9.js → cli-e61fs2hp.js} +59 -2
- package/dist/{cli-5ktc9fd4.js → cli-et9ab56s.js} +1 -1
- package/dist/{cli-jzwtn8rm.js → cli-k4yp6w9w.js} +188 -18
- package/dist/{cli-6xd0bvf8.js → cli-ma04faw5.js} +1 -1
- package/dist/{cli-ggy8c7tk.js → cli-mnbgv3w7.js} +1 -1
- package/dist/{cli-312v3c41.js → cli-n9kkkmtm.js} +1 -1
- package/dist/{cli-f5pzfvwb.js → cli-qnnbe59j.js} +2 -2
- package/dist/{cli-113wmegp.js → cli-rmyjzd8s.js} +1 -1
- package/dist/{cli-k6h2zkw3.js → cli-tw7xjzk7.js} +1 -1
- package/dist/{cli-r3mtrrzp.js → cli-ty7qe0vp.js} +12 -12
- package/dist/{cli-w4wk3kx6.js → cli-vb7g0zgk.js} +2 -2
- package/dist/{cli-5afkmcfj.js → cli-vggz87j8.js} +6 -6
- package/dist/{cli-byjcad11.js → cli-vnvv6hvm.js} +1 -1
- package/dist/cli-wh91zby6.js +187222 -0
- package/dist/{cli-q1z5d5ss.js → cli-x4trwrcr.js} +4 -4
- package/dist/{cli-pnfyyp6h.js → cli-x9q6bghe.js} +6 -3
- package/dist/{cli-e2xbxmhd.js → cli-xj6zntcq.js} +90 -32
- package/dist/cli.js +11 -11
- package/dist/{codex-adapter-4z8m9mb5.js → codex-adapter-de3w0nch.js} +2 -2
- package/dist/{codex-session-runner-rbct46dg.js → codex-session-runner-bnw8cysk.js} +2 -2
- package/dist/{commands-zk4d6esf.js → commands-4jt6hvc9.js} +2 -2
- package/dist/{db-stn16jp2.js → db-1p5e9zj8.js} +12 -2
- package/dist/{handlers-gshprvpf.js → handlers-5n9gq3ek.js} +9 -9
- package/dist/{hook-amzx9tap.js → hook-ny4kv3r0.js} +1 -1
- package/dist/{http-6g0hfzax.js → http-bb3pva4d.js} +182 -65
- package/dist/{index-f03rnnrs.js → index-ajkj0aaf.js} +9 -9
- package/dist/{index-df8fmphk.js → index-dpcmhqy0.js} +331 -30
- package/dist/{index-jbm7qcqk.js → index-mheeg078.js} +8 -8
- package/dist/{index-ty42rxw9.js → index-nzghbv06.js} +10 -10
- package/dist/{keepalive-pm6g2wpw.js → keepalive-vbgjzp3y.js} +4 -4
- package/dist/{lead-h79fzpzw.js → lead-98bg3kfz.js} +24 -24
- package/dist/{maintenance-433zndy1.js → maintenance-1fp5fz08.js} +4 -4
- package/dist/{oauth-refresh-sweep-mjsbmsk2.js → oauth-refresh-sweep-91s6j3dq.js} +3 -3
- package/dist/{onboard-vdr9hc3f.js → onboard-n32hf2t4.js} +2 -2
- package/dist/{opencode-adapter-mqsxr170.js → opencode-adapter-p6bxnbm4.js} +2 -2
- package/dist/{otel-impl-yswd0fty.js → otel-impl-j42cnqry.js} +1 -1
- package/dist/{pi-mono-adapter-vbrvg1p8.js → pi-mono-adapter-05sck1ds.js} +1 -1
- package/dist/{pricing-refresh-2kk2ap9b.js → pricing-refresh-56gkeqaw.js} +4 -4
- package/dist/{rbac-roles-2wgh9b5t.js → rbac-roles-c1ky22v2.js} +11 -4
- package/dist/{rbac-roles-xdc5208b.js → rbac-roles-xwt8319h.js} +4 -4
- package/dist/{seed-pricing-m9h69d2t.js → seed-pricing-qagjzjqj.js} +3 -3
- package/dist/{setup-eynkvafa.js → setup-1kk84v0w.js} +2 -2
- package/dist/{worker-136q8dc2.js → worker-bmjqg3c6.js} +24 -24
- package/openapi.json +8 -4
- package/package.json +2 -2
- package/src/be/db.ts +253 -20
- package/src/be/migrations/113_task_routing_affinity.sql +9 -0
- package/src/be/migrations/114_backfill_gpt_5_6_pricing.sql +15 -0
- package/src/be/modelsdev-cache.json +135 -0
- package/src/be/rbac-audit.ts +19 -8
- package/src/be/rbac-roles.ts +8 -1
- package/src/be/script-connections.ts +4 -4
- package/src/be/scripts/typecheck.ts +11 -0
- package/src/be/seed-scripts/catalog/catalog-report.inline.ts +325 -24
- package/src/be/seed-scripts/catalog/catalog-report.ts +325 -24
- package/src/heartbeat/heartbeat.ts +143 -21
- package/src/http/favorites.ts +1 -5
- package/src/http/mcp-servers.ts +38 -0
- package/src/http/poll.ts +7 -2
- package/src/http/scripts.ts +6 -0
- package/src/http/skills.ts +11 -0
- package/src/http/tasks.ts +21 -9
- package/src/providers/codex-models.ts +100 -30
- package/src/providers/modelsdev-reasoning.json +51 -0
- package/src/providers/reasoning-effort.ts +11 -5
- package/src/rbac/admission.ts +26 -2
- package/src/rbac/index.ts +2 -2
- package/src/rbac/legacy-policy.ts +9 -0
- package/src/rbac/permissions.ts +36 -0
- package/src/scripts-runtime/api-client.ts +82 -6
- package/src/scripts-runtime/types/swarm-sdk.d.ts +11 -0
- package/src/server-user.ts +114 -59
- package/src/slack/responses.ts +91 -1
- package/src/slack/watcher.ts +9 -6
- package/src/tasks/worker-follow-up.ts +100 -3
- package/src/tests/codex-adapter.test.ts +46 -23
- package/src/tests/heartbeat.test.ts +48 -3
- package/src/tests/model-control.test.ts +8 -2
- package/src/tests/pool-affinity.test.ts +401 -0
- package/src/tests/rbac-admission-e2e.test.ts +152 -7
- package/src/tests/rbac-admission.test.ts +60 -1
- package/src/tests/rbac-engine.test.ts +9 -0
- package/src/tests/rbac-mcp-admission-e2e.test.ts +362 -0
- package/src/tests/rbac-roles.test.ts +2 -0
- package/src/tests/reasoning-effort.test.ts +15 -2
- package/src/tests/script-apis-mcp.test.ts +37 -13
- package/src/tests/script-connections.test.ts +27 -1
- package/src/tests/scripts-runtime.test.ts +187 -0
- package/src/tests/seed-scripts.test.ts +36 -0
- package/src/tests/slack-inline-output.test.ts +65 -0
- package/src/tests/user-token-rest-auth.test.ts +110 -0
- package/src/tools/script-apis.ts +62 -3
- package/src/tools/send-task.ts +15 -1
- package/src/tools/task-action.ts +34 -2
- package/src/tools/templates.ts +48 -0
- package/src/tools/utils.ts +2 -0
- package/src/types.ts +27 -5
- package/dist/cli-46b6kc7f.js +0 -1698
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
taskAttachmentDisplayUrl
|
|
3
3
|
} from "./cli-wspgs9bt.js";
|
|
4
4
|
import {
|
|
5
|
+
buildRoutingAffinityFromAgent,
|
|
5
6
|
createTaskExtended,
|
|
6
7
|
getActiveTaskCount,
|
|
7
8
|
getAgentById,
|
|
@@ -17,7 +18,7 @@ import {
|
|
|
17
18
|
init_templates1 as init_templates,
|
|
18
19
|
normalizeDateRequired,
|
|
19
20
|
resolveTemplate
|
|
20
|
-
} from "./cli-
|
|
21
|
+
} from "./cli-k4yp6w9w.js";
|
|
21
22
|
|
|
22
23
|
// src/be/db-queries/tracker.ts
|
|
23
24
|
init_date_utils();
|
|
@@ -147,6 +148,13 @@ function isGracefulResumePinEnabled() {
|
|
|
147
148
|
var RESUME_GENERATION_TAG_PREFIX = "resume-generation:";
|
|
148
149
|
var CRASH_RECOVERY_PIN_TAG = "crash-recovery-pin";
|
|
149
150
|
var GRACEFUL_SHUTDOWN_PIN_TAG = "graceful-shutdown-pin";
|
|
151
|
+
var REBOOT_RETRY_PIN_TAG = "reboot-retry-pin";
|
|
152
|
+
function getPinCandidateAgent(agentId) {
|
|
153
|
+
const candidate = getAgentById(agentId);
|
|
154
|
+
if (!candidate || candidate.status === "offline")
|
|
155
|
+
return null;
|
|
156
|
+
return candidate;
|
|
157
|
+
}
|
|
150
158
|
function getResumeGeneration(task) {
|
|
151
159
|
const tag = task.tags.find((value) => value.startsWith(RESUME_GENERATION_TAG_PREFIX));
|
|
152
160
|
if (!tag)
|
|
@@ -247,8 +255,8 @@ function createResumeFollowUp(args) {
|
|
|
247
255
|
}
|
|
248
256
|
let preferredAgentId;
|
|
249
257
|
if (parent.agentId) {
|
|
250
|
-
const candidate =
|
|
251
|
-
if (candidate
|
|
258
|
+
const candidate = getPinCandidateAgent(parent.agentId);
|
|
259
|
+
if (candidate) {
|
|
252
260
|
const lastActivity = candidate.lastActivityAt ? Date.parse(candidate.lastActivityAt) : 0;
|
|
253
261
|
const fresh = Number.isFinite(lastActivity) && Date.now() - lastActivity < WORKER_LIVENESS_WINDOW_SECONDS * 1000;
|
|
254
262
|
const activeCount = getActiveTaskCount(candidate.id);
|
|
@@ -289,6 +297,7 @@ function createResumeFollowUp(args) {
|
|
|
289
297
|
if (args.reason === "graceful_shutdown" && preferredAgentId !== undefined) {
|
|
290
298
|
tags.push(GRACEFUL_SHUTDOWN_PIN_TAG);
|
|
291
299
|
}
|
|
300
|
+
const routingAffinity = parent.agentId ? buildRoutingAffinityFromAgent(parent.agentId) ?? undefined : undefined;
|
|
292
301
|
const created = createTaskExtended(followUpDescription, {
|
|
293
302
|
agentId: preferredAgentId,
|
|
294
303
|
creatorAgentId: parent.creatorAgentId,
|
|
@@ -296,7 +305,8 @@ function createResumeFollowUp(args) {
|
|
|
296
305
|
taskType: "resume",
|
|
297
306
|
tags,
|
|
298
307
|
priority,
|
|
299
|
-
parentTaskId: parent.id
|
|
308
|
+
parentTaskId: parent.id,
|
|
309
|
+
routingAffinity
|
|
300
310
|
});
|
|
301
311
|
const repointed = repointTrackerSyncBySwarmId(parent.id, created.id);
|
|
302
312
|
if (repointed > 0) {
|
|
@@ -338,5 +348,36 @@ function createRerouteDecisionTask(args) {
|
|
|
338
348
|
});
|
|
339
349
|
return { kind: "created", task: created };
|
|
340
350
|
}
|
|
351
|
+
function createPoolStarvationDecisionTask(args) {
|
|
352
|
+
const { original } = args;
|
|
353
|
+
const leadAgent = getLeadAgent();
|
|
354
|
+
if (!leadAgent)
|
|
355
|
+
return { kind: "skipped", reason: "lead_not_found" };
|
|
356
|
+
if (hasNonTerminalRerouteDecisionChild(original.id)) {
|
|
357
|
+
return { kind: "skipped", reason: "duplicate_exists" };
|
|
358
|
+
}
|
|
359
|
+
const affinity = original.routingAffinity;
|
|
360
|
+
const requiredRole = affinity?.role ?? "(none declared)";
|
|
361
|
+
const requiredCapabilities = affinity?.capabilities && affinity.capabilities.length > 0 ? affinity.capabilities.join(", ") : "(none declared)";
|
|
362
|
+
const attachmentsBlock = formatAttachmentsBlock(getTaskAttachments(original.id));
|
|
363
|
+
const decision = resolveTemplate("task.pool.starved.decision", {
|
|
364
|
+
original_task_id: original.id,
|
|
365
|
+
task_desc: original.task.slice(0, 200),
|
|
366
|
+
required_role: requiredRole,
|
|
367
|
+
required_capabilities: requiredCapabilities,
|
|
368
|
+
artifacts_block: attachmentsBlock
|
|
369
|
+
});
|
|
370
|
+
const created = createTaskExtended(decision.text, {
|
|
371
|
+
agentId: leadAgent.id,
|
|
372
|
+
creatorAgentId: original.creatorAgentId,
|
|
373
|
+
source: "system",
|
|
374
|
+
taskType: "reroute-decision",
|
|
375
|
+
tags: ["reroute-decision", "pool-starvation"],
|
|
376
|
+
priority: Math.min(100, (original.priority ?? 50) + 10),
|
|
377
|
+
parentTaskId: original.id,
|
|
378
|
+
inheritParentOutputSchema: false
|
|
379
|
+
});
|
|
380
|
+
return { kind: "created", task: created };
|
|
381
|
+
}
|
|
341
382
|
|
|
342
|
-
export { getTrackerSync, getTrackerSyncByExternalId, createTrackerSyncIfAbsent, updateTrackerSyncSwarmId, repointTrackerSyncBySwarmId, createTrackerSync, updateTrackerSync, deleteTrackerSync, hasTrackerDelivery, markTrackerDelivery, getAllTrackerSyncs, createTrackerAgentMapping, getResumeGeneration, getNextResumeGeneration, createWorkerTaskFollowUp, createResumeFollowUp, createRerouteDecisionTask };
|
|
383
|
+
export { getTrackerSync, getTrackerSyncByExternalId, createTrackerSyncIfAbsent, updateTrackerSyncSwarmId, repointTrackerSyncBySwarmId, createTrackerSync, updateTrackerSync, deleteTrackerSync, hasTrackerDelivery, markTrackerDelivery, getAllTrackerSyncs, createTrackerAgentMapping, REBOOT_RETRY_PIN_TAG, getPinCandidateAgent, getResumeGeneration, getNextResumeGeneration, createWorkerTaskFollowUp, createResumeFollowUp, createRerouteDecisionTask, createPoolStarvationDecisionTask };
|
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
import {
|
|
2
|
+
REBOOT_RETRY_PIN_TAG,
|
|
3
|
+
createPoolStarvationDecisionTask,
|
|
2
4
|
createRerouteDecisionTask,
|
|
3
5
|
createResumeFollowUp,
|
|
4
6
|
getNextResumeGeneration,
|
|
7
|
+
getPinCandidateAgent,
|
|
5
8
|
getResumeGeneration,
|
|
6
9
|
repointTrackerSyncBySwarmId
|
|
7
|
-
} from "./cli-
|
|
10
|
+
} from "./cli-9ys4kdd4.js";
|
|
8
11
|
import {
|
|
9
12
|
getExecutorRegistry,
|
|
10
13
|
recoverIncompleteRuns
|
|
11
|
-
} from "./cli-
|
|
14
|
+
} from "./cli-96nd7vgs.js";
|
|
12
15
|
import {
|
|
13
16
|
MAX_EMPTY_POLLS,
|
|
14
17
|
assignUnassignedTaskPending,
|
|
15
18
|
backfillSupersedeTaskResumeTaskId,
|
|
19
|
+
buildRoutingAffinityFromAgent,
|
|
16
20
|
cleanupStaleSessions,
|
|
17
21
|
createTaskExtended,
|
|
18
22
|
deleteActiveSession,
|
|
@@ -28,6 +32,7 @@ import {
|
|
|
28
32
|
getRecentFailedCount,
|
|
29
33
|
getRecentFailedTasks,
|
|
30
34
|
getStalePinnedResumes,
|
|
35
|
+
getStaleUnassignedAffinityTasks,
|
|
31
36
|
getStalledInProgressTasks,
|
|
32
37
|
getTaskById,
|
|
33
38
|
getTaskStats,
|
|
@@ -37,6 +42,8 @@ import {
|
|
|
37
42
|
init_db,
|
|
38
43
|
init_registry,
|
|
39
44
|
init_resolver,
|
|
45
|
+
isAgentEligibleForTask,
|
|
46
|
+
isPoolAffinityEnforcementEnabled,
|
|
40
47
|
registerTemplate,
|
|
41
48
|
releaseStaleMentionProcessing,
|
|
42
49
|
releaseStaleProcessingInbox,
|
|
@@ -44,7 +51,7 @@ import {
|
|
|
44
51
|
resolveTemplate,
|
|
45
52
|
supersedeTask,
|
|
46
53
|
updateAgentStatus
|
|
47
|
-
} from "./cli-
|
|
54
|
+
} from "./cli-k4yp6w9w.js";
|
|
48
55
|
|
|
49
56
|
// src/heartbeat/heartbeat.ts
|
|
50
57
|
init_db();
|
|
@@ -155,6 +162,8 @@ var STALL_THRESHOLD_NO_SESSION_MIN = Number(process.env.HEARTBEAT_STALL_NO_SESSI
|
|
|
155
162
|
var STALL_THRESHOLD_STALE_HEARTBEAT_MIN = Number(process.env.HEARTBEAT_STALL_STALE_HB_MIN) || 15;
|
|
156
163
|
var STALE_CLEANUP_THRESHOLD_MINUTES = Number(process.env.HEARTBEAT_STALE_CLEANUP_MIN) || 30;
|
|
157
164
|
var MAX_AUTO_ASSIGN_PER_SWEEP = Number(process.env.HEARTBEAT_MAX_AUTO_ASSIGN) || 5;
|
|
165
|
+
var POOL_SCAN_BATCH_SIZE = Number(process.env.HEARTBEAT_POOL_SCAN_BATCH_SIZE) || 50;
|
|
166
|
+
var POOL_SCAN_CAP = Number(process.env.HEARTBEAT_POOL_SCAN_CAP) || 500;
|
|
158
167
|
var MAX_RESUME_GENERATIONS = Number(process.env.HEARTBEAT_MAX_RESUME_GENERATIONS) || 3;
|
|
159
168
|
var RESUME_BUDGET_EXHAUSTED_REASON = "resume_budget_exhausted";
|
|
160
169
|
var HEARTBEAT_RESUME_PIN_GRACE_MIN = (() => {
|
|
@@ -164,6 +173,7 @@ var HEARTBEAT_RESUME_PIN_GRACE_MIN = (() => {
|
|
|
164
173
|
const parsed = Number(raw);
|
|
165
174
|
return Number.isFinite(parsed) ? parsed : 10;
|
|
166
175
|
})();
|
|
176
|
+
var POOL_AFFINITY_ESCALATION_MIN = Number(process.env.POOL_AFFINITY_ESCALATION_MIN) || 15;
|
|
167
177
|
var HEARTBEAT_CHECKLIST_INTERVAL_MS = Number(process.env.HEARTBEAT_CHECKLIST_INTERVAL_MS) || 30 * 60 * 1000;
|
|
168
178
|
var HEARTBEAT_CHECKLIST_DISABLE = Boolean(process.env.HEARTBEAT_CHECKLIST_DISABLE);
|
|
169
179
|
var heartbeatInterval = null;
|
|
@@ -412,12 +422,28 @@ async function runRebootSweep() {
|
|
|
412
422
|
LIMIT 1`).get(task.id);
|
|
413
423
|
if (!existingRetry) {
|
|
414
424
|
try {
|
|
425
|
+
let preferredAgentId;
|
|
426
|
+
const candidate = getPinCandidateAgent(task.agentId);
|
|
427
|
+
if (candidate) {
|
|
428
|
+
const activeCount = getActiveTaskCount(candidate.id);
|
|
429
|
+
const hasCap = activeCount < (candidate.maxTasks ?? 1);
|
|
430
|
+
if (hasCap) {
|
|
431
|
+
preferredAgentId = candidate.id;
|
|
432
|
+
} else {
|
|
433
|
+
console.warn(`[Heartbeat] Reboot retry for task ${task.id.slice(0, 8)} NOT pinned: agent ${candidate.id.slice(0, 8)} at capacity (${activeCount}/${candidate.maxTasks ?? 1}); falling back to affinity-gated pool`);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
const tags = ["reboot-retry", "auto-generated"];
|
|
437
|
+
if (preferredAgentId !== undefined)
|
|
438
|
+
tags.push(REBOOT_RETRY_PIN_TAG);
|
|
415
439
|
const retryTask = createTaskExtended(task.task, {
|
|
416
440
|
parentTaskId: task.id,
|
|
417
|
-
|
|
441
|
+
agentId: preferredAgentId,
|
|
442
|
+
tags,
|
|
418
443
|
priority: task.priority,
|
|
419
444
|
source: task.source,
|
|
420
|
-
taskType: task.taskType ?? undefined
|
|
445
|
+
taskType: task.taskType ?? undefined,
|
|
446
|
+
routingAffinity: buildRoutingAffinityFromAgent(task.agentId) ?? undefined
|
|
421
447
|
});
|
|
422
448
|
retryTaskId = retryTask.id;
|
|
423
449
|
console.log(`[Heartbeat] Reboot retry created: ${retryTaskId} (parent: ${task.id})`);
|
|
@@ -461,10 +487,6 @@ function autoAssignPoolTasks(findings) {
|
|
|
461
487
|
const idleWorkers = getIdleWorkersWithCapacity().filter((w) => (w.emptyPollCount ?? 0) < MAX_EMPTY_POLLS);
|
|
462
488
|
if (idleWorkers.length === 0)
|
|
463
489
|
return;
|
|
464
|
-
const poolTasks = getUnassignedPoolTasks(MAX_AUTO_ASSIGN_PER_SWEEP);
|
|
465
|
-
if (poolTasks.length === 0)
|
|
466
|
-
return;
|
|
467
|
-
let workerIndex = 0;
|
|
468
490
|
const reservedByWorker = new Map;
|
|
469
491
|
const reservedForWorker = (agentId) => {
|
|
470
492
|
const cached = reservedByWorker.get(agentId);
|
|
@@ -475,24 +497,28 @@ function autoAssignPoolTasks(findings) {
|
|
|
475
497
|
reservedByWorker.set(agentId, reserved);
|
|
476
498
|
return reserved;
|
|
477
499
|
};
|
|
478
|
-
|
|
479
|
-
|
|
500
|
+
let assignedCount = 0;
|
|
501
|
+
let offset = 0;
|
|
502
|
+
while (assignedCount < MAX_AUTO_ASSIGN_PER_SWEEP && offset < POOL_SCAN_CAP) {
|
|
503
|
+
const batch = getUnassignedPoolTasks(POOL_SCAN_BATCH_SIZE, offset);
|
|
504
|
+
if (batch.length === 0)
|
|
480
505
|
break;
|
|
481
|
-
const
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
if (remaining <= 0) {
|
|
493
|
-
workerIndex++;
|
|
506
|
+
for (const task of batch) {
|
|
507
|
+
if (assignedCount >= MAX_AUTO_ASSIGN_PER_SWEEP)
|
|
508
|
+
break;
|
|
509
|
+
const worker = idleWorkers.find((w) => reservedForWorker(w.id) < (w.maxTasks ?? 1) && isAgentEligibleForTask(w, task));
|
|
510
|
+
if (!worker)
|
|
511
|
+
continue;
|
|
512
|
+
const assigned = assignUnassignedTaskPending(task.id, worker.id);
|
|
513
|
+
if (assigned) {
|
|
514
|
+
findings.autoAssigned.push({ taskId: task.id, agentId: worker.id });
|
|
515
|
+
reservedByWorker.set(worker.id, reservedForWorker(worker.id) + 1);
|
|
516
|
+
assignedCount++;
|
|
494
517
|
}
|
|
495
518
|
}
|
|
519
|
+
offset += batch.length;
|
|
520
|
+
if (batch.length < POOL_SCAN_BATCH_SIZE)
|
|
521
|
+
break;
|
|
496
522
|
}
|
|
497
523
|
})();
|
|
498
524
|
}
|
|
@@ -550,12 +576,35 @@ function escalateUnreclaimedResumes(findings) {
|
|
|
550
576
|
console.log(`[Heartbeat] Escalated unreclaimed pinned resume ${resume.id.slice(0, 8)} → Lead reroute-decision ${escalation.decisionTaskId.slice(0, 8)} (original ${original.id.slice(0, 8)})`);
|
|
551
577
|
}
|
|
552
578
|
}
|
|
579
|
+
function escalateStarvedPoolTasks(findings) {
|
|
580
|
+
if (!isPoolAffinityEnforcementEnabled())
|
|
581
|
+
return;
|
|
582
|
+
const cutoff = new Date(Date.now() - POOL_AFFINITY_ESCALATION_MIN * 60 * 1000).toISOString();
|
|
583
|
+
const candidates = getStaleUnassignedAffinityTasks(cutoff);
|
|
584
|
+
if (candidates.length === 0)
|
|
585
|
+
return;
|
|
586
|
+
const registeredAgents = getAllAgents().filter((a) => !a.isLead);
|
|
587
|
+
for (const task of candidates) {
|
|
588
|
+
const hasEligibleAgent = registeredAgents.some((agent) => isAgentEligibleForTask(agent, task));
|
|
589
|
+
if (hasEligibleAgent)
|
|
590
|
+
continue;
|
|
591
|
+
const decision = createPoolStarvationDecisionTask({ original: task });
|
|
592
|
+
if (decision.kind === "created") {
|
|
593
|
+
findings.escalatedReroutes.push({
|
|
594
|
+
originalTaskId: task.id,
|
|
595
|
+
decisionTaskId: decision.task.id
|
|
596
|
+
});
|
|
597
|
+
console.log(`[Heartbeat] Escalated starved pool task ${task.id.slice(0, 8)} → Lead reroute-decision ${decision.task.id.slice(0, 8)} (zero eligible agents)`);
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
}
|
|
553
601
|
async function cleanupStaleResources(findings) {
|
|
554
602
|
findings.staleCleanup.sessions = cleanupStaleSessions(STALE_CLEANUP_THRESHOLD_MINUTES);
|
|
555
603
|
findings.staleCleanup.reviewingTasks = releaseStaleReviewingTasks(STALE_CLEANUP_THRESHOLD_MINUTES);
|
|
556
604
|
findings.staleCleanup.mentionProcessing = releaseStaleMentionProcessing(STALE_CLEANUP_THRESHOLD_MINUTES);
|
|
557
605
|
findings.staleCleanup.inboxProcessing = releaseStaleProcessingInbox(STALE_CLEANUP_THRESHOLD_MINUTES);
|
|
558
606
|
escalateUnreclaimedResumes(findings);
|
|
607
|
+
escalateStarvedPoolTasks(findings);
|
|
559
608
|
try {
|
|
560
609
|
findings.staleCleanup.workflowRuns = await recoverIncompleteRuns(getExecutorRegistry());
|
|
561
610
|
} catch {
|
|
@@ -781,6 +781,57 @@ var modelsdev_reasoning_default = {
|
|
|
781
781
|
]
|
|
782
782
|
}
|
|
783
783
|
]
|
|
784
|
+
},
|
|
785
|
+
"gpt-5.6-sol": {
|
|
786
|
+
id: "gpt-5.6-sol",
|
|
787
|
+
reasoning: true,
|
|
788
|
+
reasoningOptions: [
|
|
789
|
+
{
|
|
790
|
+
type: "effort",
|
|
791
|
+
values: [
|
|
792
|
+
"none",
|
|
793
|
+
"low",
|
|
794
|
+
"medium",
|
|
795
|
+
"high",
|
|
796
|
+
"xhigh",
|
|
797
|
+
"max"
|
|
798
|
+
]
|
|
799
|
+
}
|
|
800
|
+
]
|
|
801
|
+
},
|
|
802
|
+
"gpt-5.6-terra": {
|
|
803
|
+
id: "gpt-5.6-terra",
|
|
804
|
+
reasoning: true,
|
|
805
|
+
reasoningOptions: [
|
|
806
|
+
{
|
|
807
|
+
type: "effort",
|
|
808
|
+
values: [
|
|
809
|
+
"none",
|
|
810
|
+
"low",
|
|
811
|
+
"medium",
|
|
812
|
+
"high",
|
|
813
|
+
"xhigh",
|
|
814
|
+
"max"
|
|
815
|
+
]
|
|
816
|
+
}
|
|
817
|
+
]
|
|
818
|
+
},
|
|
819
|
+
"gpt-5.6-luna": {
|
|
820
|
+
id: "gpt-5.6-luna",
|
|
821
|
+
reasoning: true,
|
|
822
|
+
reasoningOptions: [
|
|
823
|
+
{
|
|
824
|
+
type: "effort",
|
|
825
|
+
values: [
|
|
826
|
+
"none",
|
|
827
|
+
"low",
|
|
828
|
+
"medium",
|
|
829
|
+
"high",
|
|
830
|
+
"xhigh",
|
|
831
|
+
"max"
|
|
832
|
+
]
|
|
833
|
+
}
|
|
834
|
+
]
|
|
784
835
|
}
|
|
785
836
|
},
|
|
786
837
|
openrouter: {
|
|
@@ -4035,7 +4086,7 @@ var modelsdev_reasoning_default = {
|
|
|
4035
4086
|
};
|
|
4036
4087
|
|
|
4037
4088
|
// src/providers/reasoning-effort.ts
|
|
4038
|
-
var REASONING_EFFORT_LEVELS = ["off", "low", "medium", "high", "xhigh"];
|
|
4089
|
+
var REASONING_EFFORT_LEVELS = ["off", "low", "medium", "high", "xhigh", "max"];
|
|
4039
4090
|
var SNAPSHOT = modelsdev_reasoning_default;
|
|
4040
4091
|
var FALLBACK_LEVELS = ["low", "medium", "high"];
|
|
4041
4092
|
var EFFORT_VALUE_MAP = {
|
|
@@ -4043,7 +4094,8 @@ var EFFORT_VALUE_MAP = {
|
|
|
4043
4094
|
low: "low",
|
|
4044
4095
|
medium: "medium",
|
|
4045
4096
|
high: "high",
|
|
4046
|
-
xhigh: "xhigh"
|
|
4097
|
+
xhigh: "xhigh",
|
|
4098
|
+
max: "max"
|
|
4047
4099
|
};
|
|
4048
4100
|
function splitProviderModel(model) {
|
|
4049
4101
|
const slash = model.indexOf("/");
|
|
@@ -4080,6 +4132,9 @@ function applyHarnessOverrides(harness, model, entry, levels) {
|
|
|
4080
4132
|
result = ["off", ...result];
|
|
4081
4133
|
}
|
|
4082
4134
|
}
|
|
4135
|
+
if (harness !== "codex") {
|
|
4136
|
+
result = result.filter((l) => l !== "max");
|
|
4137
|
+
}
|
|
4083
4138
|
if (harness === "codex") {
|
|
4084
4139
|
const isCodexMax = /-codex-max$/.test(model);
|
|
4085
4140
|
const isCodexNonMax = /-codex$/.test(model) && !isCodexMax;
|
|
@@ -4133,6 +4188,8 @@ var ANTHROPIC_BUDGET_TOKENS_BY_LEVEL = {
|
|
|
4133
4188
|
};
|
|
4134
4189
|
function buildOpencodeReasoningOptions(providerId, level) {
|
|
4135
4190
|
if (providerId === "anthropic") {
|
|
4191
|
+
if (level === "max")
|
|
4192
|
+
return { reasoningEffort: level };
|
|
4136
4193
|
return { thinking: { type: "enabled", budgetTokens: ANTHROPIC_BUDGET_TOKENS_BY_LEVEL[level] } };
|
|
4137
4194
|
}
|
|
4138
4195
|
if (providerId === "openrouter") {
|