@capybara-hq/kernel 0.1.0-rc.2 → 0.1.0-rc.4
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/admin/admin.controller.d.ts +9 -4
- package/dist/admin/admin.controller.js +13 -4
- package/dist/admin/extensions.controller.d.ts +8 -1
- package/dist/admin/extensions.controller.js +22 -2
- package/dist/agents/agent-lookup.d.ts +3 -0
- package/dist/agents/agent-lookup.js +20 -2
- package/dist/agents/agent-profile.service.d.ts +29 -0
- package/dist/agents/agent-profile.service.js +117 -0
- package/dist/agents/agents.controller.d.ts +93 -3
- package/dist/agents/agents.controller.js +114 -4
- package/dist/agents/agents.module.js +6 -2
- package/dist/agents/agents.service.d.ts +13 -5
- package/dist/agents/agents.service.js +49 -13
- package/dist/agents/definition.d.ts +35 -8
- package/dist/agents/definition.js +203 -17
- package/dist/agents/instruction-files.d.ts +60 -0
- package/dist/agents/instruction-files.js +111 -0
- package/dist/agents/models.controller.d.ts +9 -3
- package/dist/agents/models.controller.js +19 -4
- package/dist/agents/profile.d.ts +96 -0
- package/dist/agents/profile.js +51 -0
- package/dist/agents/readiness.controller.d.ts +26 -0
- package/dist/agents/readiness.controller.js +56 -0
- package/dist/agents/templates.js +20 -5
- package/dist/background/background.controller.d.ts +38 -0
- package/dist/background/background.controller.js +87 -0
- package/dist/background/background.module.d.ts +10 -0
- package/dist/background/background.module.js +32 -0
- package/dist/background/finish.d.ts +43 -0
- package/dist/background/finish.js +94 -0
- package/dist/background/launch-lock.d.ts +14 -0
- package/dist/background/launch-lock.js +39 -0
- package/dist/background/launch.d.ts +36 -0
- package/dist/background/launch.js +70 -0
- package/dist/background/poll.job.d.ts +53 -0
- package/dist/background/poll.job.js +182 -0
- package/dist/background/render.d.ts +23 -0
- package/dist/background/render.js +48 -0
- package/dist/background/session.d.ts +37 -0
- package/dist/background/session.js +66 -0
- package/dist/background/status.d.ts +35 -0
- package/dist/background/status.js +57 -0
- package/dist/background/stop.d.ts +62 -0
- package/dist/background/stop.js +225 -0
- package/dist/background/store.d.ts +150 -0
- package/dist/background/store.js +351 -0
- package/dist/background/store.module.d.ts +6 -0
- package/dist/background/store.module.js +22 -0
- package/dist/background/tasks.service.d.ts +67 -0
- package/dist/background/tasks.service.js +186 -0
- package/dist/background/wake-rules.d.ts +57 -0
- package/dist/background/wake-rules.js +83 -0
- package/dist/background/wake.d.ts +28 -0
- package/dist/background/wake.js +57 -0
- package/dist/catalog/catalog-content.js +4 -1
- package/dist/catalog/claude/agents.js +15 -10
- package/dist/catalog/marketplaces.service.d.ts +1 -1
- package/dist/catalog/plugin-import.js +1 -1
- package/dist/catalog/plugin-upgrade.js +1 -1
- package/dist/channels/cards.d.ts +8 -2
- package/dist/channels/cards.js +17 -9
- package/dist/channels/connections.service.d.ts +16 -1
- package/dist/channels/connections.service.js +38 -4
- package/dist/channels/threads.d.ts +5 -0
- package/dist/channels/threads.js +8 -0
- package/dist/config/schema.d.ts +18 -0
- package/dist/config/schema.js +104 -2
- package/dist/conversations/access.js +2 -0
- package/dist/conversations/artifacts.d.ts +1 -1
- package/dist/conversations/artifacts.js +1 -1
- package/dist/conversations/attachments.service.d.ts +30 -0
- package/dist/conversations/attachments.service.js +130 -5
- package/dist/conversations/conversations.controller.d.ts +36 -5
- package/dist/conversations/conversations.controller.js +62 -12
- package/dist/conversations/conversations.module.js +3 -0
- package/dist/conversations/conversations.service.d.ts +44 -2
- package/dist/conversations/conversations.service.js +140 -12
- package/dist/conversations/event-log.d.ts +12 -1
- package/dist/conversations/event-log.js +29 -1
- package/dist/conversations/events.d.ts +81 -3
- package/dist/conversations/events.js +83 -16
- package/dist/conversations/queue.d.ts +3 -1
- package/dist/conversations/queue.js +13 -2
- package/dist/conversations/queue.service.js +3 -1
- package/dist/conversations/titles.d.ts +7 -0
- package/dist/conversations/titles.js +15 -0
- package/dist/db/kernel-schema.d.ts +60 -4
- package/dist/db/pool.d.ts +5 -0
- package/dist/db/pool.js +3 -0
- package/dist/errors.d.ts +8 -0
- package/dist/errors.js +8 -0
- package/dist/evals/recorded-tools.d.ts +27 -1
- package/dist/evals/recorded-tools.js +85 -10
- package/dist/evals/run-replay.d.ts +10 -2
- package/dist/evals/run-replay.js +49 -12
- package/dist/evals/step-replay.js +12 -6
- package/dist/evals/trajectory.d.ts +2 -2
- package/dist/evals/trajectory.js +1 -1
- package/dist/extensions/admin-ops.js +2 -0
- package/dist/extensions/admin-view.d.ts +3 -1
- package/dist/extensions/admin-view.js +10 -2
- package/dist/extensions/blobs.js +1 -0
- package/dist/extensions/config-issues.d.ts +13 -1
- package/dist/extensions/config-issues.js +22 -5
- package/dist/extensions/config-json-schema.d.ts +43 -7
- package/dist/extensions/config-json-schema.js +124 -58
- package/dist/extensions/deployment-config-store.d.ts +6 -0
- package/dist/extensions/deployment-config.d.ts +50 -3
- package/dist/extensions/deployment-config.js +125 -28
- package/dist/extensions/display-name.d.ts +22 -0
- package/dist/extensions/display-name.js +77 -0
- package/dist/extensions/extensions.module.js +6 -0
- package/dist/extensions/host.d.ts +26 -1
- package/dist/extensions/host.js +82 -9
- package/dist/extensions/org-config.controller.d.ts +11 -3
- package/dist/extensions/org-config.controller.js +14 -6
- package/dist/extensions/org-config.d.ts +6 -0
- package/dist/extensions/org-config.js +12 -13
- package/dist/extensions/package.d.ts +14 -1
- package/dist/extensions/package.js +51 -2
- package/dist/extensions/permission-view.d.ts +3 -0
- package/dist/extensions/point-defaults.controller.d.ts +34 -0
- package/dist/extensions/point-defaults.controller.js +71 -0
- package/dist/extensions/point-defaults.d.ts +64 -0
- package/dist/extensions/point-defaults.js +206 -0
- package/dist/extensions/registry.d.ts +1 -1
- package/dist/extensions/registry.js +2 -0
- package/dist/http/api.module.js +8 -0
- package/dist/http/nest-logger.d.ts +6 -5
- package/dist/http/nest-logger.js +24 -10
- package/dist/identity/auth.controller.js +9 -5
- package/dist/identity/cookies.d.ts +20 -5
- package/dist/identity/cookies.js +44 -6
- package/dist/identity/me.controller.d.ts +5 -1
- package/dist/identity/me.controller.js +12 -3
- package/dist/identity/sessions.d.ts +12 -0
- package/dist/identity/sessions.js +45 -0
- package/dist/identity/settings.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/infra/config/kernel-config.service.js +6 -0
- package/dist/infra/database/database.module.js +1 -0
- package/dist/infra/events/kernel-events.d.ts +8 -0
- package/dist/infra/lifecycle/process-guards.js +4 -0
- package/dist/infra/logging/logging.module.d.ts +4 -2
- package/dist/infra/logging/logging.module.js +24 -6
- package/dist/infra/queue/redis-connection.d.ts +6 -0
- package/dist/infra/queue/redis-connection.js +7 -0
- package/dist/infra/redis/redis.module.js +6 -2
- package/dist/infra/tokens.d.ts +6 -1
- package/dist/infra/tokens.js +6 -1
- package/dist/lifecycle/kernel-lifecycle.js +5 -0
- package/dist/log.d.ts +13 -1
- package/dist/log.js +93 -17
- package/dist/models/purposes.d.ts +23 -0
- package/dist/models/purposes.js +31 -10
- package/dist/orgs/offboarding.d.ts +3 -1
- package/dist/orgs/offboarding.js +26 -16
- package/dist/orgs/settings.service.d.ts +7 -2
- package/dist/orgs/settings.service.js +15 -4
- package/dist/roles/worker.module.js +6 -0
- package/dist/runtime/context/build.d.ts +15 -13
- package/dist/runtime/context/build.js +45 -27
- package/dist/runtime/context/claude-tools.d.ts +3 -1
- package/dist/runtime/context/claude-tools.js +12 -12
- package/dist/runtime/context/compaction.js +4 -0
- package/dist/runtime/context/legacy-text.d.ts +22 -0
- package/dist/runtime/context/legacy-text.js +37 -0
- package/dist/runtime/context/skills.d.ts +29 -11
- package/dist/runtime/context/skills.js +37 -30
- package/dist/runtime/langgraph-loop.js +3 -2
- package/dist/runtime/loop.d.ts +5 -4
- package/dist/runtime/maintenance.d.ts +4 -2
- package/dist/runtime/maintenance.js +17 -5
- package/dist/runtime/model-call.d.ts +17 -1
- package/dist/runtime/model-call.js +4 -3
- package/dist/runtime/providers.d.ts +6 -0
- package/dist/runtime/providers.js +8 -0
- package/dist/runtime/run-finish.d.ts +1 -1
- package/dist/runtime/run-queue.d.ts +28 -5
- package/dist/runtime/run-queue.js +131 -35
- package/dist/runtime/run-worker.d.ts +2 -2
- package/dist/runtime/run-worker.js +20 -7
- package/dist/runtime/runtime.module.js +8 -3
- package/dist/runtime/step-log.d.ts +6 -0
- package/dist/runtime/step-log.js +16 -2
- package/dist/runtime/subagents/definition.d.ts +1 -6
- package/dist/runtime/subagents/definition.js +14 -13
- package/dist/runtime/subagents/dispatch.d.ts +2 -2
- package/dist/runtime/subagents/dispatch.js +2 -2
- package/dist/runtime/subagents/org-agents.js +2 -1
- package/dist/runtime/subagents/roster.d.ts +1 -1
- package/dist/runtime/subagents/roster.js +1 -1
- package/dist/runtime/subagents/skill-fork.d.ts +2 -2
- package/dist/runtime/subagents/skill-fork.js +2 -2
- package/dist/runtime/subagents/subagents.service.d.ts +3 -3
- package/dist/runtime/subagents/subagents.service.js +3 -3
- package/dist/runtime/usage-report.d.ts +2 -1
- package/dist/runtime/usage-report.js +2 -1
- package/dist/runtime/waits.d.ts +13 -7
- package/dist/runtime/waits.js +42 -16
- package/dist/sandbox/sandbox.module.js +6 -1
- package/dist/sandbox/sandbox.service.d.ts +61 -3
- package/dist/sandbox/sandbox.service.js +141 -7
- package/dist/skills/catalog.d.ts +4 -4
- package/dist/skills/catalog.js +4 -4
- package/dist/skills/changes.service.d.ts +2 -2
- package/dist/skills/changes.service.js +5 -4
- package/dist/skills/invocation-keys.d.ts +1 -1
- package/dist/skills/invocation-keys.js +1 -1
- package/dist/skills/invoke.d.ts +1 -1
- package/dist/skills/invoke.js +5 -4
- package/dist/tools/approvals.service.d.ts +6 -0
- package/dist/tools/approvals.service.js +21 -1
- package/dist/tools/builtin-names.d.ts +91 -0
- package/dist/tools/builtin-names.js +143 -0
- package/dist/tools/builtins/agent.d.ts +7 -7
- package/dist/tools/builtins/agent.js +7 -11
- package/dist/tools/builtins/ask-user.d.ts +1 -1
- package/dist/tools/builtins/ask-user.js +2 -2
- package/dist/tools/builtins/builtin-tools.d.ts +17 -3
- package/dist/tools/builtins/builtin-tools.js +36 -4
- package/dist/tools/builtins/read-tool-output.d.ts +1 -1
- package/dist/tools/builtins/read-tool-output.js +2 -2
- package/dist/tools/builtins/sandbox/bash.d.ts +4 -4
- package/dist/tools/builtins/sandbox/bash.js +259 -29
- package/dist/tools/builtins/sandbox/common.d.ts +30 -7
- package/dist/tools/builtins/sandbox/common.js +9 -5
- package/dist/tools/builtins/sandbox/deliver.d.ts +1 -1
- package/dist/tools/builtins/sandbox/deliver.js +12 -12
- package/dist/tools/builtins/sandbox/edit.d.ts +1 -1
- package/dist/tools/builtins/sandbox/edit.js +41 -30
- package/dist/tools/builtins/sandbox/file-state.d.ts +34 -0
- package/dist/tools/builtins/sandbox/file-state.js +34 -0
- package/dist/tools/builtins/sandbox/glob-match.d.ts +1 -1
- package/dist/tools/builtins/sandbox/glob-match.js +1 -1
- package/dist/tools/builtins/sandbox/glob.d.ts +1 -1
- package/dist/tools/builtins/sandbox/glob.js +4 -4
- package/dist/tools/builtins/sandbox/grep.d.ts +7 -4
- package/dist/tools/builtins/sandbox/grep.js +147 -30
- package/dist/tools/builtins/sandbox/index.d.ts +3 -1
- package/dist/tools/builtins/sandbox/index.js +7 -1
- package/dist/tools/builtins/sandbox/read.d.ts +2 -2
- package/dist/tools/builtins/sandbox/read.js +21 -14
- package/dist/tools/builtins/sandbox/task-output.d.ts +63 -0
- package/dist/tools/builtins/sandbox/task-output.js +304 -0
- package/dist/tools/builtins/sandbox/task-stop.d.ts +10 -0
- package/dist/tools/builtins/sandbox/task-stop.js +112 -0
- package/dist/tools/builtins/sandbox/write.d.ts +1 -1
- package/dist/tools/builtins/sandbox/write.js +37 -33
- package/dist/tools/builtins/skill-load.d.ts +3 -3
- package/dist/tools/builtins/skill-load.js +32 -16
- package/dist/tools/builtins/skill-write.d.ts +4 -4
- package/dist/tools/builtins/skill-write.js +10 -10
- package/dist/tools/builtins/tool-search.d.ts +13 -9
- package/dist/tools/builtins/tool-search.js +25 -14
- package/dist/tools/builtins/web/errors.d.ts +8 -0
- package/dist/tools/builtins/web/errors.js +53 -0
- package/dist/tools/builtins/web/extract.d.ts +62 -0
- package/dist/tools/builtins/web/extract.js +267 -0
- package/dist/tools/builtins/web/fetch.d.ts +55 -0
- package/dist/tools/builtins/web/fetch.js +174 -0
- package/dist/tools/builtins/web/index.d.ts +13 -0
- package/dist/tools/builtins/web/index.js +12 -0
- package/dist/tools/builtins/web/page-cache.d.ts +25 -0
- package/dist/tools/builtins/web/page-cache.js +77 -0
- package/dist/tools/builtins/web/search.d.ts +25 -0
- package/dist/tools/builtins/web/search.js +209 -0
- package/dist/tools/builtins/web/url.d.ts +17 -0
- package/dist/tools/builtins/web/url.js +43 -0
- package/dist/tools/connectors.service.js +4 -4
- package/dist/tools/display-names.d.ts +9 -0
- package/dist/tools/display-names.js +24 -0
- package/dist/tools/drift.js +5 -5
- package/dist/tools/elicitation.js +1 -1
- package/dist/tools/info.d.ts +20 -4
- package/dist/tools/info.js +55 -32
- package/dist/tools/legacy-data.d.ts +34 -0
- package/dist/tools/legacy-data.js +76 -0
- package/dist/tools/legacy-keys.d.ts +51 -0
- package/dist/tools/legacy-keys.js +115 -0
- package/dist/tools/naming.d.ts +1 -5
- package/dist/tools/naming.js +1 -7
- package/dist/tools/oauth/flow-paths.d.ts +1 -1
- package/dist/tools/oauth/flow-paths.js +1 -1
- package/dist/tools/outputs.js +1 -1
- package/dist/tools/pipeline.d.ts +13 -7
- package/dist/tools/pipeline.js +112 -39
- package/dist/tools/policy.d.ts +1 -14
- package/dist/tools/policy.js +13 -19
- package/dist/tools/questions.controller.d.ts +1 -1
- package/dist/tools/questions.controller.js +1 -1
- package/dist/tools/questions.service.d.ts +1 -1
- package/dist/tools/registry.d.ts +38 -24
- package/dist/tools/registry.js +54 -47
- package/dist/tools/resources.d.ts +1 -1
- package/dist/tools/resources.js +1 -1
- package/dist/tools/tools.module.js +13 -1
- package/dist/tools/validate.js +1 -1
- package/package.json +3 -3
- package/src/migrations/0063_tool_keys_claude_code.sql +220 -0
- package/src/migrations/0064_account_last_org.sql +7 -0
- package/src/migrations/0065_conversation_archive.sql +8 -0
- package/src/migrations/0066_extension_display_name.sql +4 -0
- package/src/migrations/0067_agent_profiles.sql +20 -0
- package/src/migrations/0068_agent_avatar_uploads.sql +7 -0
- package/src/migrations/0069_attachments_agent_idx.sql +3 -0
- package/src/migrations/0070_background_tasks.sql +37 -0
- package/src/migrations/0071_background_tasks_reserve.sql +6 -0
- package/src/migrations/0072_background_tasks_stopping.sql +5 -0
- package/src/migrations/0073_org_extension_point_defaults.sql +11 -0
- package/dist/tools/builtins/sandbox/names.d.ts +0 -7
- package/dist/tools/builtins/sandbox/names.js +0 -20
|
@@ -8,11 +8,14 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
8
8
|
return function (target, key) { decorator(target, key, paramIndex); }
|
|
9
9
|
};
|
|
10
10
|
import { randomUUID } from "node:crypto";
|
|
11
|
+
import { getQueueToken } from "@nestjs/bullmq";
|
|
11
12
|
import { Inject, Injectable } from "@nestjs/common";
|
|
12
13
|
import { sql } from "kysely";
|
|
13
14
|
import { visibleTo } from "../agents/agent-lookup.js";
|
|
15
|
+
import { BG_WAKE_JOB, bgWakeJobId, wakeDecisionIn, } from "../background/wake-rules.js";
|
|
14
16
|
import { EventLog } from "../conversations/event-log.js";
|
|
15
17
|
import { dispatchQueuedIn, pauseQueueWith } from "../conversations/queue.js";
|
|
18
|
+
import { KernelConfigService } from "../infra/config/kernel-config.service.js";
|
|
16
19
|
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
17
20
|
import { TransactionHost } from "../infra/database/transaction-host.js";
|
|
18
21
|
import { Transactional } from "../infra/database/transactional.decorator.js";
|
|
@@ -21,6 +24,7 @@ import { KERNEL_LOGGER } from "../infra/tokens.js";
|
|
|
21
24
|
import { ToolPipeline } from "../tools/pipeline.js";
|
|
22
25
|
import { KyselyCheckpointSaver } from "./checkpointer.js";
|
|
23
26
|
import { ConversationLock } from "./conversation-lock.js";
|
|
27
|
+
import { MAINTENANCE_QUEUE_NAME } from "./maintenance-queue.js";
|
|
24
28
|
import { notifyFinished, RunFinish } from "./run-finish.js";
|
|
25
29
|
import { ACTIVE_RUN_STATUSES, RunJobs, runJobId, runQueueNameFor, } from "./run-jobs.js";
|
|
26
30
|
export { ACTIVE_RUN_STATUSES, RUN_QUEUE_NAME, runJobId, runQueueNameFor, SUBAGENT_RUN_QUEUE_NAME, } from "./run-jobs.js";
|
|
@@ -29,6 +33,12 @@ export { ACTIVE_RUN_STATUSES, RUN_QUEUE_NAME, runJobId, runQueueNameFor, SUBAGEN
|
|
|
29
33
|
* 只有进入 queued 超过这么久(`COALESCE(queued_at, created_at)`)仍没有任务的 queued 行才视为孤儿。
|
|
30
34
|
*/
|
|
31
35
|
const ORPHAN_QUEUED_GRACE_SECONDS = 30;
|
|
36
|
+
/**
|
|
37
|
+
* Margin added to the delayed wake job: its window is read on the database's clock, the delay runs
|
|
38
|
+
* on this process's and Redis's, so the job does not usually fire just before the window ends (one
|
|
39
|
+
* that does reschedules itself under its next retry id, `bgWakeJobId`).
|
|
40
|
+
*/
|
|
41
|
+
const WAKE_JOB_MARGIN_MS = 1000;
|
|
32
42
|
/**
|
|
33
43
|
* 运行队列(生产方):`ensureRun` 在会话有未消费的用户消息、且没有进行中的运行时插入 `runs` 行并投递任务。
|
|
34
44
|
* 「是否已有运行」以 PG 为准(会话行锁内检查 `runs` 中的 queued / running),并参考会话锁的持有者;
|
|
@@ -45,11 +55,15 @@ let RunQueue = class RunQueue {
|
|
|
45
55
|
events;
|
|
46
56
|
log;
|
|
47
57
|
txHost;
|
|
58
|
+
config;
|
|
59
|
+
maintenance;
|
|
48
60
|
constructor(kdb, eventLog, lock, jobs, finisher,
|
|
49
61
|
/** 运行以孤儿结束(标记失败 / 直接中止)后删除它的 checkpoint thread(thread_id = runId)。 */
|
|
50
62
|
checkpoints,
|
|
51
|
-
/** The run's open `
|
|
52
|
-
pipeline, events, log, txHost
|
|
63
|
+
/** The run's open `Agent` call results, in the orphan repair's transaction (sub-agents spec §12). */
|
|
64
|
+
pipeline, events, log, txHost, config,
|
|
65
|
+
/** The producer side of the delayed `bg-wake` job (`MaintenanceProcessor` consumes it). */
|
|
66
|
+
maintenance) {
|
|
53
67
|
this.kdb = kdb;
|
|
54
68
|
this.eventLog = eventLog;
|
|
55
69
|
this.lock = lock;
|
|
@@ -60,12 +74,14 @@ let RunQueue = class RunQueue {
|
|
|
60
74
|
this.events = events;
|
|
61
75
|
this.log = log;
|
|
62
76
|
this.txHost = txHost;
|
|
77
|
+
this.config = config;
|
|
78
|
+
this.maintenance = maintenance;
|
|
63
79
|
}
|
|
64
80
|
get db() {
|
|
65
81
|
return this.kdb.db;
|
|
66
82
|
}
|
|
67
83
|
/**
|
|
68
|
-
* The `beforeTerminal` of an orphan repair: writes the run's open `
|
|
84
|
+
* The `beforeTerminal` of an orphan repair: writes the run's open `Agent` call results in the
|
|
69
85
|
* repair's transaction; `fire()` runs their observe hooks after the commit (review m1).
|
|
70
86
|
*/
|
|
71
87
|
stopOpenCalls(runId) {
|
|
@@ -81,6 +97,11 @@ let RunQueue = class RunQueue {
|
|
|
81
97
|
* 有未消费的用户消息(最新 user_message 的 seq > `consumed_seq`)、会话锁无人持有、
|
|
82
98
|
* 且没有 queued / running / waiting 的运行时:插入 `runs`(queued)并投递任务,返回 runId;否则返回 null。
|
|
83
99
|
*
|
|
100
|
+
* The boundary (`trigger_seq`) is that newest message; with none unconsumed, the queue's head
|
|
101
|
+
* once it is sent; with no head either, a wake-eligible finished background task (background
|
|
102
|
+
* Bash spec §3, {@link wakeDecisionIn}): the run is then attributed to the task's trigger
|
|
103
|
+
* account, and a finish inside the wake window schedules the delayed `bg-wake` job instead.
|
|
104
|
+
*
|
|
84
105
|
* 孤儿清理(R29,按需进行,没有定时器):已有的 queued / running 运行若 BullMQ 任务已不存在、
|
|
85
106
|
* 会话锁也无人持有(queued 的还要超过宽限期),说明没有任何 worker 会再执行它——写
|
|
86
107
|
* `run_failed { code: "run.orphaned" }` 把它标记为失败(consumed_seq 推进到它的触发消息),
|
|
@@ -89,7 +110,9 @@ let RunQueue = class RunQueue {
|
|
|
89
110
|
*
|
|
90
111
|
* agent 已软删除的会话不起新运行(孤儿清理照常进行)。
|
|
91
112
|
*/
|
|
92
|
-
async ensureRun(conversationId
|
|
113
|
+
async ensureRun(conversationId,
|
|
114
|
+
/** From the `bg-wake` job: it fired `wakeRetry - 1` times before its window ended. */
|
|
115
|
+
opts = {}) {
|
|
93
116
|
if ((await this.lock.holder(conversationId)) !== null)
|
|
94
117
|
return null;
|
|
95
118
|
const st = {
|
|
@@ -97,11 +120,17 @@ let RunQueue = class RunQueue {
|
|
|
97
120
|
orphanRunId: null,
|
|
98
121
|
dispatchedSeq: null,
|
|
99
122
|
dispatchedSwitch: false,
|
|
123
|
+
dispatchedUnarchived: false,
|
|
100
124
|
pausedNow: false,
|
|
101
125
|
orphanStop: undefined,
|
|
126
|
+
wakeLater: null,
|
|
102
127
|
};
|
|
103
128
|
const created = await this.ensureRunIn(conversationId, st);
|
|
129
|
+
if (st.wakeLater !== null) {
|
|
130
|
+
await this.scheduleWake(conversationId, st.wakeLater, opts.wakeRetry ?? 0);
|
|
131
|
+
}
|
|
104
132
|
const { orphanSeq, orphanRunId, dispatchedSeq, dispatchedSwitch, pausedNow, orphanStop } = st;
|
|
133
|
+
const { dispatchedUnarchived } = st;
|
|
105
134
|
if (orphanSeq !== null) {
|
|
106
135
|
await notifyFinished(this.eventLog, conversationId, orphanSeq, "failed");
|
|
107
136
|
orphanStop?.fire();
|
|
@@ -114,6 +143,8 @@ let RunQueue = class RunQueue {
|
|
|
114
143
|
await this.eventLog.publishChanged(conversationId, "queue");
|
|
115
144
|
if (dispatchedSwitch)
|
|
116
145
|
await this.eventLog.publishChanged(conversationId, "selection");
|
|
146
|
+
if (dispatchedUnarchived)
|
|
147
|
+
await this.eventLog.publishChanged(conversationId, "archived");
|
|
117
148
|
}
|
|
118
149
|
if (orphanRunId !== null) {
|
|
119
150
|
await this.dropCheckpoints(orphanRunId);
|
|
@@ -153,14 +184,25 @@ let RunQueue = class RunQueue {
|
|
|
153
184
|
const t = this.db;
|
|
154
185
|
const conv = await t
|
|
155
186
|
.selectFrom("conversations")
|
|
156
|
-
.select([
|
|
187
|
+
.select([
|
|
188
|
+
"consumed_seq",
|
|
189
|
+
"org_id",
|
|
190
|
+
"agent_id",
|
|
191
|
+
"kind",
|
|
192
|
+
"queue_paused",
|
|
193
|
+
"account_id",
|
|
194
|
+
"deleted_at",
|
|
195
|
+
])
|
|
157
196
|
.where("id", "=", conversationId)
|
|
158
197
|
.forUpdate()
|
|
159
198
|
.executeTakeFirst();
|
|
160
199
|
// 评测回放的隐藏对话:运行由评测 worker 在里面直接驱动(工具只回放记录),绝不为它起真实运行
|
|
161
200
|
if (conv?.kind !== "chat")
|
|
162
201
|
return null;
|
|
163
|
-
|
|
202
|
+
// A deleted conversation starts no run, whatever is still unconsumed or queued
|
|
203
|
+
if (conv.deleted_at !== null)
|
|
204
|
+
return null;
|
|
205
|
+
const newest = await t
|
|
164
206
|
.selectFrom("conversation_events")
|
|
165
207
|
.select(["seq", "payload"])
|
|
166
208
|
.where("conversation_id", "=", conversationId)
|
|
@@ -168,11 +210,25 @@ let RunQueue = class RunQueue {
|
|
|
168
210
|
.orderBy("seq", "desc")
|
|
169
211
|
.limit(1)
|
|
170
212
|
.executeTakeFirst();
|
|
171
|
-
|
|
213
|
+
/** The run's boundary: its `trigger_seq` and the account it runs as. */
|
|
214
|
+
let last = newest && {
|
|
215
|
+
seq: newest.seq,
|
|
216
|
+
accountId: newest.payload.authorAccountId,
|
|
217
|
+
};
|
|
218
|
+
const idleActive = !last || Number(last.seq) <= Number(conv.consumed_seq)
|
|
219
|
+
? await this.activeRun(t, conversationId)
|
|
220
|
+
: undefined;
|
|
221
|
+
if (idleActive && Number(idleActive.trigger_seq) > Number(conv.consumed_seq)) {
|
|
222
|
+
// No unconsumed message, but a run whose boundary is not consumed yet (a wake run, whose
|
|
223
|
+
// boundary is a finished background task): it goes through the orphan check below with
|
|
224
|
+
// that boundary, as a message's run does
|
|
225
|
+
last = { seq: idleActive.trigger_seq, accountId: idleActive.trigger_account_id };
|
|
226
|
+
}
|
|
227
|
+
else if (!last || Number(last.seq) <= Number(conv.consumed_seq)) {
|
|
172
228
|
// Nothing unconsumed: the queue's head goes out when the conversation is idle (no active
|
|
173
229
|
// run, which includes runs waiting for approval or an answer) and the queue is not paused.
|
|
174
230
|
// Interjections are always unconsumed messages, so the queue never jumps ahead of them.
|
|
175
|
-
if (conv.queue_paused ||
|
|
231
|
+
if (conv.queue_paused || idleActive)
|
|
176
232
|
return null;
|
|
177
233
|
const owner = await t
|
|
178
234
|
.selectFrom("agents")
|
|
@@ -187,32 +243,46 @@ let RunQueue = class RunQueue {
|
|
|
187
243
|
.where("conversation_id", "=", conversationId)
|
|
188
244
|
.limit(1)
|
|
189
245
|
.executeTakeFirst();
|
|
190
|
-
if (
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
246
|
+
if (head) {
|
|
247
|
+
// A queued message may wait for hours: it goes out only while its author can still use
|
|
248
|
+
// the conversation (active, a member, the agent visible to them; the isAccessible rule).
|
|
249
|
+
// Otherwise the queue pauses instead of posting as someone who lost access.
|
|
250
|
+
if (!(await authorCanSend(t, conversationId, conv.account_id))) {
|
|
251
|
+
await pauseQueueWith(t, conversationId, "author_cannot_send");
|
|
252
|
+
st.pausedNow = true;
|
|
253
|
+
this.log.warn("queued message not sent: its author can no longer use the conversation", {
|
|
254
|
+
conversationId,
|
|
255
|
+
});
|
|
256
|
+
return null;
|
|
257
|
+
}
|
|
258
|
+
const sent = await dispatchQueuedIn(t, this.eventLog, conversationId);
|
|
259
|
+
if (!sent)
|
|
260
|
+
return null;
|
|
261
|
+
if ("paused" in sent) {
|
|
262
|
+
st.pausedNow = true;
|
|
263
|
+
this.log.warn("queued skill invocation not sent: the skill can no longer be invoked", {
|
|
264
|
+
conversationId,
|
|
265
|
+
});
|
|
266
|
+
return null;
|
|
267
|
+
}
|
|
268
|
+
st.dispatchedSeq = sent.event.seq;
|
|
269
|
+
st.dispatchedSwitch = sent.switched;
|
|
270
|
+
st.dispatchedUnarchived = sent.unarchived;
|
|
271
|
+
last = {
|
|
272
|
+
seq: String(sent.event.seq),
|
|
273
|
+
accountId: sent.event.payload.authorAccountId,
|
|
274
|
+
};
|
|
202
275
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
276
|
+
else {
|
|
277
|
+
// Nothing queued either: a finished background task may wake the idle conversation
|
|
278
|
+
// (background Bash spec §3; a person's message or the queue always goes first)
|
|
279
|
+
const wake = await wakeDecisionIn(t, { id: conversationId, orgId: conv.org_id }, Number(conv.consumed_seq), this.config.get().runtime.wakeOnBackgroundTask, (accountId) => authorCanSend(t, conversationId, accountId));
|
|
280
|
+
if (wake?.kind === "later")
|
|
281
|
+
st.wakeLater = wake;
|
|
282
|
+
if (wake?.kind !== "wake")
|
|
283
|
+
return null;
|
|
284
|
+
last = { seq: String(wake.seq), accountId: wake.triggerAccountId };
|
|
212
285
|
}
|
|
213
|
-
st.dispatchedSeq = sent.event.seq;
|
|
214
|
-
st.dispatchedSwitch = sent.switched;
|
|
215
|
-
last = { seq: String(sent.event.seq), payload: sent.event.payload };
|
|
216
286
|
}
|
|
217
287
|
const active = await this.activeRun(t, conversationId);
|
|
218
288
|
if (active) {
|
|
@@ -254,7 +324,9 @@ let RunQueue = class RunQueue {
|
|
|
254
324
|
.orderBy("seq")
|
|
255
325
|
.limit(1)
|
|
256
326
|
.executeTakeFirst();
|
|
257
|
-
const trigger = fork
|
|
327
|
+
const trigger = fork
|
|
328
|
+
? { seq: fork.seq, accountId: fork.payload.authorAccountId }
|
|
329
|
+
: last;
|
|
258
330
|
// BullMQ 对重复的 jobId 静默忽略(add 返回的 Job 由调用方数据构造,看不出是否真的入队):
|
|
259
331
|
// 先显式查同一触发点的任务;仍存在(例如属于刚结束、尚未从队列移除的运行)就不插入 runs 行。
|
|
260
332
|
const jobId = runJobId(conversationId, Number(trigger.seq));
|
|
@@ -283,12 +355,33 @@ let RunQueue = class RunQueue {
|
|
|
283
355
|
conversation_id: conversationId,
|
|
284
356
|
status: "queued",
|
|
285
357
|
agent_version: agent.current_version,
|
|
286
|
-
trigger_account_id: trigger.
|
|
358
|
+
trigger_account_id: trigger.accountId,
|
|
287
359
|
trigger_seq: Number(trigger.seq),
|
|
288
360
|
})
|
|
289
361
|
.execute();
|
|
290
362
|
return { runId, jobId };
|
|
291
363
|
}
|
|
364
|
+
/**
|
|
365
|
+
* Schedules the delayed `bg-wake` job at the end of the conversation's wake window (after the
|
|
366
|
+
* commit): one job per conversation and window end, so finishes inside one window share it. It
|
|
367
|
+
* calls {@link ensureRun}, which wakes the conversation if a finish is still unconsumed. A failed
|
|
368
|
+
* enqueue is logged: the next message, run end or page opening re-derives the wake.
|
|
369
|
+
*/
|
|
370
|
+
async scheduleWake(conversationId, w, retry) {
|
|
371
|
+
const data = { conversationId, ...(retry > 0 && { retry }) };
|
|
372
|
+
try {
|
|
373
|
+
await this.maintenance.add(BG_WAKE_JOB, data, {
|
|
374
|
+
// a job that fired early reschedules under a new id (its own is still taken)
|
|
375
|
+
jobId: bgWakeJobId(conversationId, w.windowEnd, retry),
|
|
376
|
+
delay: w.delayMs + WAKE_JOB_MARGIN_MS,
|
|
377
|
+
removeOnComplete: true,
|
|
378
|
+
removeOnFail: true,
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
catch (err) {
|
|
382
|
+
this.log.error("cannot schedule the background task wake", { conversationId, err });
|
|
383
|
+
}
|
|
384
|
+
}
|
|
292
385
|
/**
|
|
293
386
|
* Enqueues a run job under the caller's job id (resumes, dispatches, repairs), with the same
|
|
294
387
|
* options as {@link ensureRun} (see {@link RunJobs.enqueue}).
|
|
@@ -407,6 +500,7 @@ let RunQueue = class RunQueue {
|
|
|
407
500
|
"id",
|
|
408
501
|
"status",
|
|
409
502
|
"trigger_seq",
|
|
503
|
+
"trigger_account_id",
|
|
410
504
|
"job_id",
|
|
411
505
|
sql `COALESCE(queued_at, created_at) < now() - make_interval(secs => ${ORPHAN_QUEUED_GRACE_SECONDS})`.as("past_grace"),
|
|
412
506
|
])
|
|
@@ -462,7 +556,9 @@ RunQueue = __decorate([
|
|
|
462
556
|
__param(6, Inject(ToolPipeline)),
|
|
463
557
|
__param(7, Inject(KernelEvents)),
|
|
464
558
|
__param(8, Inject(KERNEL_LOGGER)),
|
|
465
|
-
__param(9, Inject(TransactionHost))
|
|
559
|
+
__param(9, Inject(TransactionHost)),
|
|
560
|
+
__param(10, Inject(KernelConfigService)),
|
|
561
|
+
__param(11, Inject(getQueueToken(MAINTENANCE_QUEUE_NAME)))
|
|
466
562
|
], RunQueue);
|
|
467
563
|
export { RunQueue };
|
|
468
564
|
/** The conversation's owner is active and can still see its agent (`isAccessible`'s rule). */
|
|
@@ -63,7 +63,7 @@ export declare class RunWorker {
|
|
|
63
63
|
/** Run start's skills catalog snapshot (reads the pinned skills' bodies, phase B). */
|
|
64
64
|
private readonly skillsCatalog;
|
|
65
65
|
/**
|
|
66
|
-
* In the terminal transaction of every run: writes its open `
|
|
66
|
+
* In the terminal transaction of every run: writes its open `Agent` call results
|
|
67
67
|
* (`stopOpenAgentCalls`; a no-op without dispatches); `fire` runs their observe hooks after the
|
|
68
68
|
* commit (sub-agents spec §12, review m1: a failed or stalled parent too).
|
|
69
69
|
*/
|
|
@@ -94,7 +94,7 @@ export declare class RunWorker {
|
|
|
94
94
|
/** Run start's skills catalog snapshot (reads the pinned skills' bodies, phase B). */
|
|
95
95
|
skillsCatalog: Pick<SkillsCatalogService, "record">,
|
|
96
96
|
/**
|
|
97
|
-
* In the terminal transaction of every run: writes its open `
|
|
97
|
+
* In the terminal transaction of every run: writes its open `Agent` call results
|
|
98
98
|
* (`stopOpenAgentCalls`; a no-op without dispatches); `fire` runs their observe hooks after the
|
|
99
99
|
* commit (sub-agents spec §12, review m1: a failed or stalled parent too).
|
|
100
100
|
*/
|
|
@@ -10,8 +10,8 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
10
10
|
import { Inject, Injectable, Optional } from "@nestjs/common";
|
|
11
11
|
import { DelayedError } from "bullmq";
|
|
12
12
|
import { sql } from "kysely";
|
|
13
|
-
import { normalizeStoredDefinition } from "../agents/definition.js";
|
|
14
13
|
import { conversationTopic, EventLog, } from "../conversations/event-log.js";
|
|
14
|
+
import { isAbsorbable, } from "../conversations/events.js";
|
|
15
15
|
import { effectiveDefinition, NO_SELECTION, readSelection, sameModel, sameSelection, } from "../conversations/selection.js";
|
|
16
16
|
import { TitleQueue } from "../conversations/titles.js";
|
|
17
17
|
import { ApiError } from "../errors.js";
|
|
@@ -24,6 +24,7 @@ import { Transactional } from "../infra/database/transactional.decorator.js";
|
|
|
24
24
|
import { KernelEvents } from "../infra/events/kernel-events.js";
|
|
25
25
|
import { KERNEL_BUS, KERNEL_LOGGER } from "../infra/tokens.js";
|
|
26
26
|
import { pinnedFailureText, SkillsCatalogService } from "../skills/catalog.js";
|
|
27
|
+
import { normalizeStoredDefinitionIn } from "../tools/legacy-data.js";
|
|
27
28
|
import { ToolPipeline } from "../tools/pipeline.js";
|
|
28
29
|
import { RunAbort } from "./abort.js";
|
|
29
30
|
import { KyselyCheckpointSaver } from "./checkpointer.js";
|
|
@@ -109,7 +110,7 @@ let RunWorker = class RunWorker {
|
|
|
109
110
|
/** Run start's skills catalog snapshot (reads the pinned skills' bodies, phase B). */
|
|
110
111
|
skillsCatalog,
|
|
111
112
|
/**
|
|
112
|
-
* In the terminal transaction of every run: writes its open `
|
|
113
|
+
* In the terminal transaction of every run: writes its open `Agent` call results
|
|
113
114
|
* (`stopOpenAgentCalls`; a no-op without dispatches); `fire` runs their observe hooks after the
|
|
114
115
|
* commit (sub-agents spec §12, review m1: a failed or stalled parent too).
|
|
115
116
|
*/
|
|
@@ -525,7 +526,7 @@ let RunWorker = class RunWorker {
|
|
|
525
526
|
// a follow-up runs with its task message's narrowing (final review I1): the frozen tools
|
|
526
527
|
// and org skills the current version still allows, recorded at its dispatch
|
|
527
528
|
const trigger = (await this.eventLog.readAfter(conversationId, Number(run.trigger_seq) - 1, 1))[0];
|
|
528
|
-
agent = childRunDefinition(
|
|
529
|
+
agent = childRunDefinition(await normalizeStoredDefinitionIn(this.db, conv.org_id, started.payload.definition), trigger?.type === "user_message" && trigger.seq === Number(run.trigger_seq)
|
|
529
530
|
? trigger.payload.dispatch?.narrowed
|
|
530
531
|
: undefined);
|
|
531
532
|
maxSteps = Math.min(started.payload.maxSteps, runtime.maxSteps);
|
|
@@ -552,7 +553,7 @@ let RunWorker = class RunWorker {
|
|
|
552
553
|
.where("agent_id", "=", conv.agent_id)
|
|
553
554
|
.where("version", "=", run.agent_version)
|
|
554
555
|
.executeTakeFirstOrThrow();
|
|
555
|
-
saved =
|
|
556
|
+
saved = await normalizeStoredDefinitionIn(this.db, conv.org_id, version.definition);
|
|
556
557
|
agent = saved;
|
|
557
558
|
}
|
|
558
559
|
let startedAt = run.started_at;
|
|
@@ -642,15 +643,16 @@ let RunWorker = class RunWorker {
|
|
|
642
643
|
.executeTakeFirstOrThrow();
|
|
643
644
|
const startConsumed = Number(consumed_seq);
|
|
644
645
|
let absorbed = startConsumed;
|
|
645
|
-
const
|
|
646
|
+
const pendingAbsorbable = async (afterSeq) => {
|
|
646
647
|
// loop 声明已吸收到 afterSeq(续跑时来自 checkpoint,可能包含之前进程吸收的消息)。
|
|
647
648
|
absorbed = Math.max(absorbed, afterSeq);
|
|
648
649
|
const out = [];
|
|
649
650
|
let after = Math.max(afterSeq, startConsumed);
|
|
650
651
|
for (;;) {
|
|
651
652
|
const page = await this.eventLog.readAfter(conversationId, after, READ_PAGE);
|
|
653
|
+
// messages and finished background tasks (spec 2026-11-05-background-bash-design §2.4)
|
|
652
654
|
for (const e of page)
|
|
653
|
-
if (e
|
|
655
|
+
if (isAbsorbable(e))
|
|
654
656
|
out.push(e);
|
|
655
657
|
const last = page.at(-1);
|
|
656
658
|
if (page.length < READ_PAGE || !last)
|
|
@@ -677,7 +679,7 @@ let RunWorker = class RunWorker {
|
|
|
677
679
|
signal: ac.signal,
|
|
678
680
|
shutdown: state.shutdown.signal,
|
|
679
681
|
sink: this.sinkFor(conversationId),
|
|
680
|
-
|
|
682
|
+
pendingAbsorbable,
|
|
681
683
|
limits: { maxSteps, deadline },
|
|
682
684
|
// a sub-agent's conversation fires hooks like a chat, with `parent` set (spec §11)
|
|
683
685
|
conversationKind: conv.kind === "eval" ? "eval" : conv.kind === "subagent" ? "subagent" : "chat",
|
|
@@ -814,6 +816,13 @@ let RunWorker = class RunWorker {
|
|
|
814
816
|
const agent = saved !== undefined
|
|
815
817
|
? effectiveDefinition(saved, await readSelection(t, conversationId))
|
|
816
818
|
: current;
|
|
819
|
+
// a wake run's boundary is a finished background task, not a message (background Bash §3)
|
|
820
|
+
const boundary = await t
|
|
821
|
+
.selectFrom("conversation_events")
|
|
822
|
+
.select("type")
|
|
823
|
+
.where("conversation_id", "=", conversationId)
|
|
824
|
+
.where("seq", "=", run.trigger_seq)
|
|
825
|
+
.executeTakeFirst();
|
|
817
826
|
const [ev] = await this.eventLog.appendIn(conversationId, [
|
|
818
827
|
{
|
|
819
828
|
type: "run_started",
|
|
@@ -823,6 +832,10 @@ let RunWorker = class RunWorker {
|
|
|
823
832
|
agentVersion: run.agent_version,
|
|
824
833
|
model: agent.model,
|
|
825
834
|
triggerAccountId: run.trigger_account_id,
|
|
835
|
+
...(boundary?.type === "background_task_finished" && {
|
|
836
|
+
trigger: "background_task",
|
|
837
|
+
triggerSeq: Number(run.trigger_seq),
|
|
838
|
+
}),
|
|
826
839
|
},
|
|
827
840
|
},
|
|
828
841
|
]);
|
|
@@ -5,6 +5,8 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
7
|
import { Module } from "@nestjs/common";
|
|
8
|
+
import { BackgroundModule } from "../background/background.module.js";
|
|
9
|
+
import { BackgroundWake } from "../background/wake.js";
|
|
8
10
|
import { ConversationAccessModule } from "../conversations/access.js";
|
|
9
11
|
import { AttachmentsModule } from "../conversations/attachments.module.js";
|
|
10
12
|
import { EventLogModule } from "../conversations/event-log.js";
|
|
@@ -28,7 +30,7 @@ import { RunJobsModule } from "./run-jobs.js";
|
|
|
28
30
|
import { RunQueue } from "./run-queue.js";
|
|
29
31
|
import { AgentLoops, RunSteps } from "./run-steps.js";
|
|
30
32
|
import { RunWorker } from "./run-worker.js";
|
|
31
|
-
import {
|
|
33
|
+
import { StepLogModule } from "./step-log.js";
|
|
32
34
|
import { ConversationStreams } from "./stream.js";
|
|
33
35
|
import { SubagentsModule } from "./subagents/subagents.service.js";
|
|
34
36
|
import { UsageReportModule } from "./usage-report.js";
|
|
@@ -58,6 +60,8 @@ RuntimeModule = __decorate([
|
|
|
58
60
|
SubagentsModule,
|
|
59
61
|
UsageReportModule,
|
|
60
62
|
TitlesModule,
|
|
63
|
+
StepLogModule,
|
|
64
|
+
BackgroundModule,
|
|
61
65
|
// the producer side of `wait-timeout` jobs (`MaintenanceProcessor` consumes them)
|
|
62
66
|
QueueModule.registerQueue(MAINTENANCE_QUEUE_NAME),
|
|
63
67
|
],
|
|
@@ -67,7 +71,6 @@ RuntimeModule = __decorate([
|
|
|
67
71
|
RunAbort,
|
|
68
72
|
KyselyCheckpointSaver,
|
|
69
73
|
RunFinish,
|
|
70
|
-
StepLog,
|
|
71
74
|
RunQueue,
|
|
72
75
|
Waits,
|
|
73
76
|
DecisionResumer,
|
|
@@ -75,6 +78,8 @@ RuntimeModule = __decorate([
|
|
|
75
78
|
AgentLoops,
|
|
76
79
|
RunSteps,
|
|
77
80
|
RunWorker,
|
|
81
|
+
// a finished background task wakes an idle conversation (background Bash spec §3)
|
|
82
|
+
BackgroundWake,
|
|
78
83
|
// one quota per key prefix (the org run quota, the org eval quota)
|
|
79
84
|
{
|
|
80
85
|
provide: RUN_QUOTA,
|
|
@@ -93,7 +98,7 @@ RuntimeModule = __decorate([
|
|
|
93
98
|
RunAbort,
|
|
94
99
|
KyselyCheckpointSaver,
|
|
95
100
|
RunFinish,
|
|
96
|
-
|
|
101
|
+
StepLogModule,
|
|
97
102
|
RunQueue,
|
|
98
103
|
Waits,
|
|
99
104
|
RunControl,
|
|
@@ -38,3 +38,9 @@ export declare class StepLog {
|
|
|
38
38
|
spec: ToolSpec;
|
|
39
39
|
}[], events: AppendEvent[]): Promise<ConversationEvent[]>;
|
|
40
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* The step writes ({@link StepLog}): a module of its own, so the tools domain (the `WebFetch`
|
|
43
|
+
* extraction's usage and denials) uses them without importing the runtime.
|
|
44
|
+
*/
|
|
45
|
+
export declare class StepLogModule {
|
|
46
|
+
}
|
package/dist/runtime/step-log.js
CHANGED
|
@@ -7,9 +7,9 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
7
|
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
8
8
|
return function (target, key) { decorator(target, key, paramIndex); }
|
|
9
9
|
};
|
|
10
|
-
import { Inject, Injectable } from "@nestjs/common";
|
|
10
|
+
import { Inject, Injectable, Module } from "@nestjs/common";
|
|
11
11
|
import { sql } from "kysely";
|
|
12
|
-
import { EventLog } from "../conversations/event-log.js";
|
|
12
|
+
import { EventLog, EventLogModule } from "../conversations/event-log.js";
|
|
13
13
|
import { usageTokens } from "../evals/budget.js";
|
|
14
14
|
import { audit } from "../identity/audit.js";
|
|
15
15
|
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
@@ -92,3 +92,17 @@ StepLog = __decorate([
|
|
|
92
92
|
__param(2, Inject(TransactionHost))
|
|
93
93
|
], StepLog);
|
|
94
94
|
export { StepLog };
|
|
95
|
+
/**
|
|
96
|
+
* The step writes ({@link StepLog}): a module of its own, so the tools domain (the `WebFetch`
|
|
97
|
+
* extraction's usage and denials) uses them without importing the runtime.
|
|
98
|
+
*/
|
|
99
|
+
let StepLogModule = class StepLogModule {
|
|
100
|
+
};
|
|
101
|
+
StepLogModule = __decorate([
|
|
102
|
+
Module({
|
|
103
|
+
imports: [EventLogModule],
|
|
104
|
+
providers: [StepLog],
|
|
105
|
+
exports: [StepLog],
|
|
106
|
+
})
|
|
107
|
+
], StepLogModule);
|
|
108
|
+
export { StepLogModule };
|
|
@@ -6,11 +6,7 @@ import type { KernelConfigService } from "../../infra/config/kernel-config.servi
|
|
|
6
6
|
import type { ModelPurposesService } from "../../models/purposes.js";
|
|
7
7
|
import type { ProviderRegistry } from "../providers.js";
|
|
8
8
|
import type { RosterEntry } from "./roster.js";
|
|
9
|
-
|
|
10
|
-
* Tools a sub-agent never gets (spec §5.3, §5.5): `agent` (depth 1), `ask_user` (the person does not
|
|
11
|
-
* see the child), `sandbox_deliver` (delivering files is the parent's job) and `skill_write`.
|
|
12
|
-
*/
|
|
13
|
-
export declare const CHILD_REMOVED_TOOLS: readonly ["agent", "ask_user", "sandbox_deliver", "skill_write"];
|
|
9
|
+
export { CHILD_REMOVED_TOOLS } from "../../tools/builtin-names.js";
|
|
14
10
|
/**
|
|
15
11
|
* The roster entry's template is gone (an inline template edited away, a plugin template
|
|
16
12
|
* uninstalled) between resolving the roster and reading it. The dispatch refuses the call as an
|
|
@@ -100,4 +96,3 @@ export declare function intersectTools(frozen: readonly AgentToolRef[], current:
|
|
|
100
96
|
export declare function narrowFollowUp(frozen: Pick<AgentDefinition, "tools" | "skills">, current: Pick<AgentDefinition, "tools" | "skills">): FollowUpNarrowing;
|
|
101
97
|
/** The definition a child run uses: the frozen one with its trigger's follow-up narrowing. */
|
|
102
98
|
export declare function childRunDefinition(frozen: AgentDefinition, narrowed: FollowUpNarrowing | undefined): AgentDefinition;
|
|
103
|
-
export {};
|
|
@@ -1,13 +1,9 @@
|
|
|
1
|
-
import { SKILL_ENTRY_FILE, sanitizeParams, } from "@capybara-hq/plugin-sdk";
|
|
1
|
+
import { connectorToolKey, extensionToolKey, parseToolKey, SKILL_ENTRY_FILE, sanitizeParams, } from "@capybara-hq/plugin-sdk";
|
|
2
2
|
import { loadTemplates } from "../../agents/templates.js";
|
|
3
3
|
import { ApiError } from "../../errors.js";
|
|
4
4
|
import { PINNED_SKILLS_LIMITS } from "../../skills/catalog.js";
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
* Tools a sub-agent never gets (spec §5.3, §5.5): `agent` (depth 1), `ask_user` (the person does not
|
|
8
|
-
* see the child), `sandbox_deliver` (delivering files is the parent's job) and `skill_write`.
|
|
9
|
-
*/
|
|
10
|
-
export const CHILD_REMOVED_TOOLS = ["agent", "ask_user", "sandbox_deliver", "skill_write"];
|
|
5
|
+
import { CHILD_REMOVED_TOOLS } from "../../tools/builtin-names.js";
|
|
6
|
+
export { CHILD_REMOVED_TOOLS } from "../../tools/builtin-names.js";
|
|
11
7
|
/**
|
|
12
8
|
* The roster entry's template is gone (an inline template edited away, a plugin template
|
|
13
9
|
* uninstalled) between resolving the roster and reading it. The dispatch refuses the call as an
|
|
@@ -72,7 +68,7 @@ async function loadConnectors(db, orgId, refs) {
|
|
|
72
68
|
/**
|
|
73
69
|
* Narrows tool refs by resolved key (spec §5.3): keeps a key when `allow` (if given) lists it and
|
|
74
70
|
* neither `deny` nor {@link CHILD_REMOVED_TOOLS} does. A connector ref with `tools: "all"` stays
|
|
75
|
-
* live only when nothing can narrow it (no allowlist and no deny key under
|
|
71
|
+
* live only when nothing can narrow it (no allowlist and no deny key under `mcp__<slug>__`), so a tool
|
|
76
72
|
* the connector gains later never slips past the template; otherwise it becomes the kept names, or
|
|
77
73
|
* is dropped. A connector that no longer exists keeps its ref only without an allowlist.
|
|
78
74
|
*/
|
|
@@ -86,7 +82,7 @@ function narrowTools(refs, connectors, allow, deny) {
|
|
|
86
82
|
out.push(ref);
|
|
87
83
|
}
|
|
88
84
|
else if (ref.kind === "plugin") {
|
|
89
|
-
if (keep(
|
|
85
|
+
if (keep(extensionToolKey(ref.plugin, ref.name)))
|
|
90
86
|
out.push(ref);
|
|
91
87
|
}
|
|
92
88
|
else {
|
|
@@ -96,13 +92,16 @@ function narrowTools(refs, connectors, allow, deny) {
|
|
|
96
92
|
out.push(ref);
|
|
97
93
|
continue;
|
|
98
94
|
}
|
|
99
|
-
const
|
|
100
|
-
|
|
95
|
+
const ownsKey = (k) => {
|
|
96
|
+
const parsed = parseToolKey(k);
|
|
97
|
+
return parsed?.kind === "connector" && parsed.slug === c.slug;
|
|
98
|
+
};
|
|
99
|
+
if (ref.tools === "all" && allow === null && ![...deny].some(ownsKey)) {
|
|
101
100
|
out.push(ref);
|
|
102
101
|
continue;
|
|
103
102
|
}
|
|
104
103
|
const names = ref.tools === "all" ? c.tools : ref.tools;
|
|
105
|
-
const kept = names.filter((name) => keep(
|
|
104
|
+
const kept = names.filter((name) => keep(connectorToolKey(c.slug, name)));
|
|
106
105
|
if (kept.length > 0)
|
|
107
106
|
out.push({ ...ref, tools: kept });
|
|
108
107
|
}
|
|
@@ -229,7 +228,9 @@ function orgAgentDefinition(d, a) {
|
|
|
229
228
|
}
|
|
230
229
|
const agentId = a.entry.agentId ?? "";
|
|
231
230
|
const own = a.orgAgent.definition;
|
|
232
|
-
|
|
231
|
+
// prompt files are authoring data: the child's model sees only `instructions` (their join), and
|
|
232
|
+
// `subagent_started.definition` keeps its shape (spec 2026-11-04 §3.3)
|
|
233
|
+
const { subagents: _subagents, skills, instructionFiles: _files, ...rest } = own;
|
|
233
234
|
const definition = {
|
|
234
235
|
...rest,
|
|
235
236
|
// its own tools, not intersected with the parent's; only the child-removed ones go
|
|
@@ -48,7 +48,7 @@ export type DispatchOutcome = {
|
|
|
48
48
|
};
|
|
49
49
|
/**
|
|
50
50
|
* A dispatch for a person's fork invocation (phase D spec §6.2, `advanceSkillForks`), not for a
|
|
51
|
-
* model's `
|
|
51
|
+
* model's `Agent` call: `general-purpose` is always available (the `Agent` tool and
|
|
52
52
|
* `subagents.general` do not gate it), an unknown type falls back to it with a warning, and the
|
|
53
53
|
* child records the invoked skill.
|
|
54
54
|
*/
|
|
@@ -83,7 +83,7 @@ export interface DispatchPlan {
|
|
|
83
83
|
tierFallback: boolean;
|
|
84
84
|
}
|
|
85
85
|
/**
|
|
86
|
-
* Dispatches the sub-agent of one `
|
|
86
|
+
* Dispatches the sub-agent of one `Agent` call (spec §7.1), after the pipeline's validation,
|
|
87
87
|
* policy, approval and `tool.preExecute` stages. A new sub-agent: resolves its type and effective
|
|
88
88
|
* definition, then in one transaction (holding the parent run's row lock, so the dispatches of one
|
|
89
89
|
* run serialize) inserts the child conversation, appends `subagent_started` and the task message,
|
|
@@ -20,7 +20,7 @@ const GENERAL_ENTRY = {
|
|
|
20
20
|
/** Idempotency key of the parent's `subagent_dispatched` event. */
|
|
21
21
|
export const dispatchedIdemKey = (runId, callId) => `subagent_dispatched:${runId}:${callId}`;
|
|
22
22
|
/**
|
|
23
|
-
* Dispatches the sub-agent of one `
|
|
23
|
+
* Dispatches the sub-agent of one `Agent` call (spec §7.1), after the pipeline's validation,
|
|
24
24
|
* policy, approval and `tool.preExecute` stages. A new sub-agent: resolves its type and effective
|
|
25
25
|
* definition, then in one transaction (holding the parent run's row lock, so the dispatches of one
|
|
26
26
|
* run serialize) inserts the child conversation, appends `subagent_started` and the task message,
|
|
@@ -274,7 +274,7 @@ async function orgAgentGates(db, a, agentId, agentType, resumed) {
|
|
|
274
274
|
}
|
|
275
275
|
const taskMessage = (ctx, callId, prompt, narrowed,
|
|
276
276
|
/**
|
|
277
|
-
* A fork invocation's record: the child's log then holds the invocation, so its `
|
|
277
|
+
* A fork invocation's record: the child's log then holds the invocation, so its `Skill`
|
|
278
278
|
* is offered and resolves the invoked version (phase D).
|
|
279
279
|
*/
|
|
280
280
|
skill) => ({
|