@capybara-hq/kernel 0.1.0-rc.23 → 0.1.0-rc.25
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/bootstrap.json +25 -25
- package/dist/admin/admin.module.d.ts +2 -1
- package/dist/admin/admin.module.js +9 -3
- package/dist/admin/health.service.d.ts +2 -2
- package/dist/admin/health.service.js +6 -2
- package/dist/admin/outbox-dead.controller.d.ts +23 -0
- package/dist/admin/outbox-dead.controller.js +62 -0
- package/dist/admin/outbox-dead.schemas.d.ts +8 -0
- package/dist/admin/outbox-dead.schemas.js +18 -0
- package/dist/admin/outbox-dead.service.d.ts +66 -0
- package/dist/admin/outbox-dead.service.js +179 -0
- package/dist/admin/overview.service.d.ts +40 -5
- package/dist/admin/overview.service.js +41 -7
- package/dist/agents/agents.module.js +3 -0
- package/dist/agents/agents.service.d.ts +6 -1
- package/dist/agents/agents.service.js +11 -2
- package/dist/agents/from-template.js +1 -1
- package/dist/background/finish.d.ts +5 -2
- package/dist/background/finish.js +14 -3
- package/dist/background/launch.d.ts +2 -1
- package/dist/background/launch.js +5 -2
- package/dist/background/store.d.ts +8 -0
- package/dist/background/store.js +24 -0
- package/dist/catalog/admin-catalog.controller.d.ts +21 -2
- package/dist/catalog/admin-catalog.controller.js +45 -6
- package/dist/catalog/admin-catalog.schemas.d.ts +5 -0
- package/dist/catalog/admin-catalog.schemas.js +8 -0
- package/dist/catalog/catalog-import.module.js +0 -4
- package/dist/catalog/catalog-scope.service.d.ts +63 -26
- package/dist/catalog/catalog-scope.service.js +146 -71
- package/dist/catalog/catalog.module.d.ts +2 -1
- package/dist/catalog/catalog.module.js +9 -4
- package/dist/catalog/catalog.service.d.ts +11 -4
- package/dist/catalog/catalog.service.js +21 -5
- package/dist/catalog/cli.d.ts +4 -3
- package/dist/catalog/cli.js +8 -13
- package/dist/catalog/job-ids.d.ts +8 -20
- package/dist/catalog/job-ids.js +11 -16
- package/dist/catalog/marketplaces.service.d.ts +1 -1
- package/dist/catalog/org-plugin-uploads.d.ts +11 -4
- package/dist/catalog/org-plugin-uploads.js +21 -6
- package/dist/catalog/owned-items.d.ts +6 -13
- package/dist/catalog/owned-items.js +11 -29
- package/dist/catalog/owned-plugin-cleanup.d.ts +8 -17
- package/dist/catalog/owned-plugin-cleanup.js +12 -66
- package/dist/catalog/platform-components.d.ts +56 -34
- package/dist/catalog/platform-components.js +68 -78
- package/dist/catalog/platform-import-update.d.ts +50 -0
- package/dist/catalog/platform-import-update.js +116 -0
- package/dist/catalog/plugin-import.d.ts +64 -26
- package/dist/catalog/plugin-import.js +113 -77
- package/dist/catalog/plugin-upgrade.d.ts +22 -4
- package/dist/catalog/plugin-upgrade.js +26 -19
- package/dist/catalog/scope-jobs.d.ts +59 -0
- package/dist/catalog/scope-jobs.js +65 -0
- package/dist/catalog/scope-sync-workers.d.ts +22 -0
- package/dist/catalog/scope-sync-workers.js +58 -2
- package/dist/catalog/scope-sync.d.ts +40 -65
- package/dist/catalog/scope-sync.js +114 -122
- package/dist/channels/channels.module.d.ts +5 -2
- package/dist/channels/channels.module.js +9 -2
- package/dist/channels/deliver-job.d.ts +25 -0
- package/dist/channels/deliver-job.js +25 -0
- package/dist/channels/inbound.d.ts +1 -1
- package/dist/channels/inbound.js +4 -17
- package/dist/channels/jobs.d.ts +28 -18
- package/dist/channels/jobs.js +63 -26
- package/dist/channels/threads.d.ts +4 -3
- package/dist/channels/threads.js +4 -3
- package/dist/config/schema.d.ts +0 -3
- package/dist/config/schema.js +11 -20
- package/dist/conversations/agent-tree.d.ts +16 -0
- package/dist/conversations/agent-tree.js +36 -0
- package/dist/conversations/conversations.controller.js +4 -2
- package/dist/conversations/conversations.service.d.ts +61 -19
- package/dist/conversations/conversations.service.js +69 -43
- package/dist/conversations/event-log.d.ts +7 -10
- package/dist/conversations/event-log.js +24 -15
- package/dist/conversations/events.d.ts +21 -0
- package/dist/conversations/events.js +26 -2
- package/dist/conversations/queue.service.d.ts +8 -3
- package/dist/conversations/queue.service.js +37 -13
- package/dist/conversations/source.d.ts +10 -0
- package/dist/conversations/source.js +17 -0
- package/dist/conversations/titles.d.ts +21 -8
- package/dist/conversations/titles.js +42 -15
- package/dist/conversations/tree.d.ts +10 -0
- package/dist/conversations/tree.js +35 -0
- package/dist/db/kernel-schema.d.ts +35 -22
- package/dist/devices/devices.service.d.ts +23 -11
- package/dist/devices/devices.service.js +34 -26
- package/dist/errors.d.ts +11 -0
- package/dist/errors.js +11 -0
- package/dist/evals/run-replay.d.ts +13 -2
- package/dist/evals/run-replay.js +42 -9
- package/dist/evals/snapshot.d.ts +7 -1
- package/dist/evals/snapshot.js +2 -1
- package/dist/extensions/extensions.module.js +3 -0
- package/dist/extensions/hooks.d.ts +22 -3
- package/dist/extensions/hooks.js +15 -1
- package/dist/extensions/lifecycle-hooks.d.ts +99 -0
- package/dist/extensions/lifecycle-hooks.js +273 -0
- package/dist/extensions/lifecycle.d.ts +6 -1
- package/dist/extensions/lifecycle.js +9 -2
- package/dist/extensions/org-config.d.ts +13 -1
- package/dist/extensions/org-config.js +19 -2
- package/dist/extensions/permission-view.d.ts +9 -5
- package/dist/extensions/permission-view.js +9 -4
- package/dist/extensions/point-defaults.d.ts +28 -1
- package/dist/extensions/point-defaults.js +44 -13
- package/dist/extensions/usage-subscribers.d.ts +43 -0
- package/dist/extensions/usage-subscribers.js +108 -0
- package/dist/http/api.module.js +2 -0
- package/dist/inbox/inbox.service.d.ts +6 -20
- package/dist/inbox/inbox.service.js +0 -3
- package/dist/inbox/org-notices.d.ts +1 -1
- package/dist/inbox/platform-inbox.service.d.ts +3 -32
- package/dist/inbox/platform-inbox.service.js +5 -54
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/infra/cli/kernel-cli.module.js +5 -0
- package/dist/infra/events/kernel-events.d.ts +9 -35
- package/dist/infra/outbox/outbox-relay.module.d.ts +6 -0
- package/dist/infra/outbox/outbox-relay.module.js +18 -0
- package/dist/infra/outbox/outbox.dispatcher.d.ts +103 -0
- package/dist/infra/outbox/outbox.dispatcher.js +310 -0
- package/dist/infra/outbox/outbox.module.d.ts +24 -0
- package/dist/infra/outbox/outbox.module.js +50 -0
- package/dist/infra/outbox/outbox.relay.d.ts +31 -0
- package/dist/infra/outbox/outbox.relay.js +76 -0
- package/dist/infra/outbox/outbox.service.d.ts +51 -0
- package/dist/infra/outbox/outbox.service.js +131 -0
- package/dist/infra/outbox/registry.d.ts +244 -0
- package/dist/infra/outbox/registry.js +234 -0
- package/dist/infra/queue/queue-names.d.ts +8 -0
- package/dist/infra/queue/queue-names.js +17 -0
- package/dist/kernel.module.js +3 -0
- package/dist/local-devices/device-policy.service.d.ts +4 -0
- package/dist/local-devices/device-policy.service.js +61 -3
- package/dist/local-devices/machines.d.ts +13 -5
- package/dist/local-devices/machines.js +45 -7
- package/dist/local-devices/policy-summary.d.ts +44 -1
- package/dist/local-devices/policy-summary.js +69 -0
- package/dist/models/embeddings.d.ts +9 -9
- package/dist/models/embeddings.js +11 -18
- package/dist/models/models.module.js +3 -0
- package/dist/orgs/directory-sync.js +1 -1
- package/dist/orgs/members.service.js +1 -1
- package/dist/orgs/offboarding.d.ts +50 -57
- package/dist/orgs/offboarding.js +117 -162
- package/dist/orgs/orgs.module.js +3 -0
- package/dist/orgs/orgs.service.d.ts +11 -5
- package/dist/orgs/orgs.service.js +22 -6
- package/dist/overrides.d.ts +23 -3
- package/dist/overrides.js +12 -2
- package/dist/platform/exclusions.js +5 -0
- package/dist/platform/ops/admin.ops.js +18 -2
- package/dist/platform/ops/catalog-admin.ops.d.ts +3 -1
- package/dist/platform/ops/catalog-admin.ops.js +32 -4
- package/dist/platform/ops/inbox.ops.js +4 -20
- package/dist/platform/ops/outbox.ops.d.ts +21 -0
- package/dist/platform/ops/outbox.ops.js +125 -0
- package/dist/platform/ops/platform.ops.d.ts +1 -0
- package/dist/platform/ops/platform.ops.js +6 -3
- package/dist/platform/ops/schedules.ops.js +40 -1
- package/dist/platform/platform-ops.module.d.ts +2 -1
- package/dist/platform/platform-ops.module.js +3 -0
- package/dist/platform/route-schemas.js +3 -0
- package/dist/roles/worker-role.d.ts +10 -5
- package/dist/roles/worker-role.js +19 -9
- package/dist/roles/worker.module.js +11 -8
- package/dist/runtime/context/build.d.ts +3 -0
- package/dist/runtime/context/build.js +15 -0
- package/dist/runtime/context/plugin-context.d.ts +20 -0
- package/dist/runtime/context/plugin-context.js +30 -0
- package/dist/runtime/langgraph-loop.js +17 -5
- package/dist/runtime/limits.d.ts +15 -0
- package/dist/runtime/limits.js +25 -0
- package/dist/runtime/loop.d.ts +16 -3
- package/dist/runtime/loop.js +2 -1
- package/dist/runtime/maintenance.d.ts +7 -3
- package/dist/runtime/maintenance.js +52 -12
- package/dist/runtime/model-call.d.ts +20 -17
- package/dist/runtime/model-call.js +15 -24
- package/dist/runtime/plugin-context.service.d.ts +69 -0
- package/dist/runtime/plugin-context.service.js +208 -0
- package/dist/runtime/queue-lost-jobs.d.ts +24 -0
- package/dist/runtime/queue-lost-jobs.js +51 -0
- package/dist/runtime/run-control.d.ts +47 -5
- package/dist/runtime/run-control.js +79 -12
- package/dist/runtime/run-finish.d.ts +39 -12
- package/dist/runtime/run-finish.js +97 -14
- package/dist/runtime/run-jobs.d.ts +95 -13
- package/dist/runtime/run-jobs.js +199 -28
- package/dist/runtime/run-orphan-check.job.d.ts +142 -0
- package/dist/runtime/run-orphan-check.job.js +339 -0
- package/dist/runtime/run-processors.d.ts +16 -9
- package/dist/runtime/run-processors.js +1 -1
- package/dist/runtime/run-queue.d.ts +75 -53
- package/dist/runtime/run-queue.js +189 -263
- package/dist/runtime/run-steps.d.ts +1 -2
- package/dist/runtime/run-steps.js +8 -11
- package/dist/runtime/run-worker.d.ts +26 -16
- package/dist/runtime/run-worker.js +132 -37
- package/dist/runtime/runtime.module.d.ts +2 -3
- package/dist/runtime/runtime.module.js +7 -6
- package/dist/runtime/step-log.d.ts +16 -4
- package/dist/runtime/step-log.js +26 -6
- package/dist/runtime/stream.controller.d.ts +2 -4
- package/dist/runtime/stream.controller.js +5 -11
- package/dist/runtime/subagents/child.js +1 -1
- package/dist/runtime/subagents/definition.d.ts +2 -1
- package/dist/runtime/subagents/definition.js +4 -2
- package/dist/runtime/subagents/deliveries.d.ts +6 -3
- package/dist/runtime/subagents/deliveries.js +16 -7
- package/dist/runtime/subagents/dispatch.d.ts +12 -12
- package/dist/runtime/subagents/dispatch.js +14 -38
- package/dist/runtime/subagents/messages.d.ts +5 -1
- package/dist/runtime/subagents/messages.js +11 -3
- package/dist/runtime/subagents/skill-fork.d.ts +3 -3
- package/dist/runtime/subagents/skill-fork.js +8 -5
- package/dist/runtime/subagents/subagents.service.js +1 -1
- package/dist/runtime/subagents/tree-jobs.d.ts +61 -0
- package/dist/runtime/subagents/tree-jobs.js +86 -0
- package/dist/runtime/usage-report-jobs.d.ts +23 -48
- package/dist/runtime/usage-report-jobs.js +67 -119
- package/dist/runtime/usage-report.d.ts +28 -77
- package/dist/runtime/usage-report.js +35 -213
- package/dist/runtime/waits.d.ts +48 -198
- package/dist/runtime/waits.js +103 -805
- package/dist/sandbox/jobs.d.ts +20 -10
- package/dist/sandbox/jobs.js +23 -17
- package/dist/sandbox/sandbox.service.d.ts +17 -4
- package/dist/sandbox/sandbox.service.js +55 -14
- package/dist/schedules/calendar.d.ts +134 -0
- package/dist/schedules/calendar.js +410 -0
- package/dist/schedules/fire.d.ts +26 -7
- package/dist/schedules/fire.js +91 -22
- package/dist/schedules/job-ids.d.ts +66 -17
- package/dist/schedules/job-ids.js +81 -13
- package/dist/schedules/run-tracker.d.ts +0 -5
- package/dist/schedules/run-tracker.js +2 -14
- package/dist/schedules/scan.job.d.ts +13 -32
- package/dist/schedules/scan.job.js +50 -164
- package/dist/schedules/schedule-math.d.ts +42 -0
- package/dist/schedules/schedule-math.js +52 -0
- package/dist/schedules/scheduled-tasks.service.d.ts +22 -6
- package/dist/schedules/scheduled-tasks.service.js +70 -14
- package/dist/schedules/schedules.controller.d.ts +5 -1
- package/dist/schedules/schedules.controller.js +15 -1
- package/dist/schedules/schedules.module.js +0 -4
- package/dist/schedules/schedules.schemas.d.ts +35 -0
- package/dist/schedules/schedules.schemas.js +27 -0
- package/dist/schedules/store.d.ts +5 -0
- package/dist/schedules/store.js +20 -0
- package/dist/skills/changes.controller.d.ts +1 -1
- package/dist/skills/changes.controller.js +1 -1
- package/dist/tools/approvals.service.d.ts +41 -11
- package/dist/tools/approvals.service.js +108 -14
- package/dist/tools/builtin-names.d.ts +5 -3
- package/dist/tools/builtin-names.js +12 -4
- package/dist/tools/builtins/builtin-tools.d.ts +1 -2
- package/dist/tools/builtins/builtin-tools.js +21 -17
- package/dist/tools/builtins/sandbox/bash.js +9 -3
- package/dist/tools/builtins/sandbox/common.d.ts +18 -1
- package/dist/tools/builtins/sandbox/common.js +14 -1
- package/dist/tools/builtins/sandbox/index.d.ts +2 -1
- package/dist/tools/builtins/sandbox/index.js +4 -1
- package/dist/tools/builtins/sandbox/task-list.d.ts +12 -0
- package/dist/tools/builtins/sandbox/task-list.js +130 -0
- package/dist/tools/builtins/sandbox/task-output.d.ts +8 -1
- package/dist/tools/builtins/sandbox/task-output.js +21 -3
- package/dist/tools/builtins/web/extract.d.ts +2 -4
- package/dist/tools/builtins/web/extract.js +2 -5
- package/dist/tools/pipeline.d.ts +12 -3
- package/dist/tools/pipeline.js +6 -1
- package/dist/tools/questions.service.d.ts +30 -10
- package/dist/tools/questions.service.js +41 -27
- package/dist/tools/registry.d.ts +12 -3
- package/dist/tools/registry.js +13 -3
- package/dist/tools/tools.module.js +4 -3
- package/package.json +3 -3
- package/src/migrations/0118_device_policy_ops.sql +6 -0
- package/src/migrations/0119_outbox.sql +22 -0
- package/src/migrations/0120_drop_usage_report_sweep.sql +7 -0
- package/src/migrations/0121_drop_platform_migration_runs.sql +12 -0
- package/src/migrations/0122_drop_scheduled_task_runs_rechecked_at.sql +5 -0
- package/src/migrations/0123_pgvector.sql +27 -0
- package/src/migrations/0124_conversation_source.sql +36 -0
- package/dist/catalog/platform-migration.d.ts +0 -115
- package/dist/catalog/platform-migration.js +0 -583
- package/dist/infra/queue/add-job-once.d.ts +0 -14
- package/dist/infra/queue/add-job-once.js +0 -16
|
@@ -13,6 +13,7 @@ import { Inject, Injectable } from "@nestjs/common";
|
|
|
13
13
|
import { sql } from "kysely";
|
|
14
14
|
import { EventLog } from "../conversations/event-log.js";
|
|
15
15
|
import { NETWORK_ASK_MAX_HOSTS, NETWORK_HOST_MAX_CHARS, } from "../conversations/events.js";
|
|
16
|
+
import { conversationSourceOf } from "../conversations/source.js";
|
|
16
17
|
import { ApiError } from "../errors.js";
|
|
17
18
|
import { audit } from "../identity/audit.js";
|
|
18
19
|
import { KernelConfigService } from "../infra/config/kernel-config.service.js";
|
|
@@ -24,6 +25,7 @@ import { LockService } from "../infra/lock/lock.service.js";
|
|
|
24
25
|
import { WithLock } from "../infra/lock/with-lock.decorator.js";
|
|
25
26
|
import { DevicePolicyService } from "../local-devices/device-policy.service.js";
|
|
26
27
|
import { ORG_ROLES, roleAtLeast } from "../orgs/roles.js";
|
|
28
|
+
import { RunResume } from "../runtime/run-jobs.js";
|
|
27
29
|
import { rootConversationOf } from "../runtime/subagents/child.js";
|
|
28
30
|
import { SandboxService } from "../sandbox/sandbox.service.js";
|
|
29
31
|
import { readScheduleSettings } from "../schedules/effective-settings.js";
|
|
@@ -102,10 +104,12 @@ function canHandle(a, initiator, accountId, role) {
|
|
|
102
104
|
* 工具调用审批:新建(loop 调用)、列出 / 查看 / 处理(HTTP),以及「以后都允许」授权的查看与撤销。
|
|
103
105
|
* 状态全部在 PG:处理决定在事务里 `SELECT … FOR UPDATE` 审批行,多副本并发处理同一审批时恰好一个生效。
|
|
104
106
|
*
|
|
105
|
-
* A decision
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
107
|
+
* A decision resumes its waiting run in the decision's transaction (`RunResume.resumeIn`, after the
|
|
108
|
+
* decided row: lock order approval, then run; transactional outbox spec §6). It is announced after
|
|
109
|
+
* the commit as the domain event `approval.decided` (exactly once: only the decision that changed
|
|
110
|
+
* the row from pending; no kernel subscriber: the IM card update is owed by the `approval_decided`
|
|
111
|
+
* append, transactional outbox spec §8.1). Events are appended in the context's transaction
|
|
112
|
+
* (`EventLog.appendIn`) and published after the commit.
|
|
109
113
|
*/
|
|
110
114
|
let ApprovalsService = class ApprovalsService {
|
|
111
115
|
db;
|
|
@@ -118,6 +122,7 @@ let ApprovalsService = class ApprovalsService {
|
|
|
118
122
|
policies;
|
|
119
123
|
lockService;
|
|
120
124
|
sandbox;
|
|
125
|
+
resumes;
|
|
121
126
|
constructor(db, config, eventLog, events, txHost, schedules,
|
|
122
127
|
/** A trial approval is kept only for a tool the task may hold as a grant (its agent's tools). */
|
|
123
128
|
registry,
|
|
@@ -126,7 +131,9 @@ let ApprovalsService = class ApprovalsService {
|
|
|
126
131
|
/** One decision of a network ask at a time, across replicas (the op is sent before the transaction). */
|
|
127
132
|
lockService,
|
|
128
133
|
/** A trial run's 「这次允许」 becomes a task grant only within the org's egress. */
|
|
129
|
-
sandbox
|
|
134
|
+
sandbox,
|
|
135
|
+
/** A decision resumes its waiting run in the decision's transaction. */
|
|
136
|
+
resumes) {
|
|
130
137
|
this.db = db;
|
|
131
138
|
this.config = config;
|
|
132
139
|
this.eventLog = eventLog;
|
|
@@ -137,6 +144,7 @@ let ApprovalsService = class ApprovalsService {
|
|
|
137
144
|
this.policies = policies;
|
|
138
145
|
this.lockService = lockService;
|
|
139
146
|
this.sandbox = sandbox;
|
|
147
|
+
this.resumes = resumes;
|
|
140
148
|
}
|
|
141
149
|
/**
|
|
142
150
|
* 新建 pending 审批(`expires_at` = 现在 + `tools.approvalTimeoutHours`)并写 `approval_requested`,同一事务。
|
|
@@ -549,7 +557,7 @@ let ApprovalsService = class ApprovalsService {
|
|
|
549
557
|
/** After the commit: the decision's events reach the page, the run's waits and IM delivery. */
|
|
550
558
|
async announceDecided(record, toSeq) {
|
|
551
559
|
await this.eventLog.notify(record.conversationId, toSeq);
|
|
552
|
-
//
|
|
560
|
+
// its IM delivery is enqueued (handler failures are logged); the run resumed in the decision
|
|
553
561
|
await this.events.emit("approval.decided", {
|
|
554
562
|
id: record.id,
|
|
555
563
|
orgId: record.orgId,
|
|
@@ -571,6 +579,9 @@ let ApprovalsService = class ApprovalsService {
|
|
|
571
579
|
// decision committed, even when a caller has a transaction open
|
|
572
580
|
async decideIn(orgId, id, accountId, body, actorTokenId, network) {
|
|
573
581
|
const t = this.db.db;
|
|
582
|
+
// lock order: the conversation, the approval, then the run (as a stop of the waiting run)
|
|
583
|
+
if (!(await this.lockConversationOf(id, orgId)))
|
|
584
|
+
throw notFound();
|
|
574
585
|
const locked = await t
|
|
575
586
|
.selectFrom("approvals")
|
|
576
587
|
.selectAll()
|
|
@@ -734,6 +745,7 @@ let ApprovalsService = class ApprovalsService {
|
|
|
734
745
|
...(reason !== undefined && { reason }),
|
|
735
746
|
},
|
|
736
747
|
});
|
|
748
|
+
await this.resumes.resumeIn(before.runId, id);
|
|
737
749
|
return { record: toRecord(updated), toSeq: Math.max(...written.map((e) => e.seq)) };
|
|
738
750
|
}
|
|
739
751
|
await audit(t, {
|
|
@@ -754,6 +766,9 @@ let ApprovalsService = class ApprovalsService {
|
|
|
754
766
|
...(reason !== undefined && { reason }),
|
|
755
767
|
},
|
|
756
768
|
});
|
|
769
|
+
// the run last (lock order: the decided row, then `runs`); a still-running run is resumed by
|
|
770
|
+
// its suspend's re-check
|
|
771
|
+
await this.resumes.resumeIn(before.runId, id);
|
|
757
772
|
return { record: toRecord(updated), toSeq: Math.max(...written.map((e) => e.seq)) };
|
|
758
773
|
}
|
|
759
774
|
/**
|
|
@@ -800,6 +815,8 @@ let ApprovalsService = class ApprovalsService {
|
|
|
800
815
|
disabledTools: def?.disabledTools ?? [],
|
|
801
816
|
subagentTools: def?.subagentTools,
|
|
802
817
|
subagents: def?.subagents,
|
|
818
|
+
// the tools of the trial run's conversation, where the approval was asked
|
|
819
|
+
source: await conversationSourceOf(t, a.conversationId),
|
|
803
820
|
});
|
|
804
821
|
const tool = tools.find((x) => x.key === a.toolKey);
|
|
805
822
|
const { forbiddenTools } = await readScheduleSettings(t, this.config, a.orgId);
|
|
@@ -908,6 +925,8 @@ let ApprovalsService = class ApprovalsService {
|
|
|
908
925
|
}
|
|
909
926
|
async expireIn(id) {
|
|
910
927
|
const t = this.db.db;
|
|
928
|
+
if (!(await this.lockConversationOf(id)))
|
|
929
|
+
return { outcome: "settled" };
|
|
911
930
|
const locked = await t
|
|
912
931
|
.selectFrom("approvals")
|
|
913
932
|
.selectAll()
|
|
@@ -959,16 +978,41 @@ let ApprovalsService = class ApprovalsService {
|
|
|
959
978
|
return out;
|
|
960
979
|
}
|
|
961
980
|
/**
|
|
962
|
-
*
|
|
963
|
-
*
|
|
964
|
-
*
|
|
981
|
+
* The conversations of `orgId` holding a pending approval `accountId` is asked to decide
|
|
982
|
+
* (`requested_for`), read without locks: offboarding locks them, by tree root first
|
|
983
|
+
* (`lockConversationTrees`), before {@link cancelPendingFor}.
|
|
965
984
|
*/
|
|
966
|
-
async
|
|
985
|
+
async pendingConversationsFor(orgId, accountId) {
|
|
986
|
+
const rows = await this.db
|
|
987
|
+
.selectFrom("approvals")
|
|
988
|
+
.select("conversation_id")
|
|
989
|
+
.distinct()
|
|
990
|
+
.where("org_id", "=", orgId)
|
|
991
|
+
.where("requested_for", "=", accountId)
|
|
992
|
+
.where("status", "=", "pending")
|
|
993
|
+
.execute();
|
|
994
|
+
return rows.map((r) => r.conversation_id);
|
|
995
|
+
}
|
|
996
|
+
/**
|
|
997
|
+
* In the caller's transaction (`mandatory`; offboarding): cancels every pending approval of
|
|
998
|
+
* `orgId` that `accountId` is asked to decide (`requested_for`) in `conversationIds`, the
|
|
999
|
+
* conversations the caller already locked (by tree root first, `lockConversationTrees`; lock
|
|
1000
|
+
* order: conversations, then approval rows), along the same path as {@link cancelPendingIn}:
|
|
1001
|
+
* `cancelled`, `approval_decided{cancelled}` with no decider. An approval asked meanwhile in
|
|
1002
|
+
* another conversation is left to its run's stop, so no conversation is locked after a row.
|
|
1003
|
+
* Returns the cancelled records and the highest seq written per conversation; the caller
|
|
1004
|
+
* publishes after the commit.
|
|
1005
|
+
*/
|
|
1006
|
+
async cancelPendingFor(orgId, accountId, conversationIds) {
|
|
967
1007
|
const t = this.db.db;
|
|
1008
|
+
const convs = [...conversationIds];
|
|
1009
|
+
if (convs.length === 0)
|
|
1010
|
+
return { records: [], seqs: new Map() };
|
|
968
1011
|
const rows = await t
|
|
969
1012
|
.selectFrom("approvals")
|
|
970
1013
|
.selectAll()
|
|
971
1014
|
.where("org_id", "=", orgId)
|
|
1015
|
+
.where("conversation_id", "in", convs)
|
|
972
1016
|
.where("requested_for", "=", accountId)
|
|
973
1017
|
.where("status", "=", "pending")
|
|
974
1018
|
.orderBy("created_at")
|
|
@@ -996,17 +1040,29 @@ let ApprovalsService = class ApprovalsService {
|
|
|
996
1040
|
* active runs `authorAccountId` started, in the conversation and in its sub-agents'
|
|
997
1041
|
* conversations at any depth (their asks are shown in the root). Each becomes `skipped` with
|
|
998
1042
|
* `approval_decided{skipped}` by the author; access stays blocked. Returns the skipped records and
|
|
999
|
-
* the highest seq written per conversation; the caller
|
|
1000
|
-
*
|
|
1043
|
+
* the highest seq written per conversation; the caller resumes their waiting runs in this
|
|
1044
|
+
* transaction once every skipped row is locked (`ConversationsService.skipWaitsIn`), and notifies
|
|
1045
|
+
* and emits the domain event `approval.decided{skipped}` after the commit (its IM card update is
|
|
1046
|
+
* owed by the append, transactional outbox spec §8.1).
|
|
1001
1047
|
*/
|
|
1002
1048
|
async skipNetworkIn(conversationId, authorAccountId) {
|
|
1003
1049
|
const t = this.db.db;
|
|
1004
1050
|
const tree = await this.subtreeOf(conversationId);
|
|
1051
|
+
// the sub-agents' conversations with a pending ask first, in id order (lock order:
|
|
1052
|
+
// conversation, then approval rows; the caller holds `conversationId`'s already)
|
|
1053
|
+
const convs = await this.lockConversations(t
|
|
1054
|
+
.selectFrom("approvals")
|
|
1055
|
+
.select("conversation_id")
|
|
1056
|
+
.where("conversation_id", "in", tree)
|
|
1057
|
+
.where("kind", "=", "network")
|
|
1058
|
+
.where("status", "=", "pending"));
|
|
1059
|
+
if (convs.length === 0)
|
|
1060
|
+
return { records: [], seqs: new Map() };
|
|
1005
1061
|
const rows = await t
|
|
1006
1062
|
.selectFrom("approvals as a")
|
|
1007
1063
|
.innerJoin("runs as r", "r.id", "a.run_id")
|
|
1008
1064
|
.selectAll("a")
|
|
1009
|
-
.where("a.conversation_id", "in",
|
|
1065
|
+
.where("a.conversation_id", "in", convs)
|
|
1010
1066
|
.where("a.kind", "=", "network")
|
|
1011
1067
|
.where("a.status", "=", "pending")
|
|
1012
1068
|
.where(sql `a.expires_at > now()`)
|
|
@@ -1031,6 +1087,43 @@ let ApprovalsService = class ApprovalsService {
|
|
|
1031
1087
|
}
|
|
1032
1088
|
return { records, seqs };
|
|
1033
1089
|
}
|
|
1090
|
+
/**
|
|
1091
|
+
* Locks the conversation row of approval `id` (`SELECT … FOR UPDATE`; re-entrant with the lock
|
|
1092
|
+
* `EventLog.appendIn` takes later). Every write to an approval row takes its conversation's lock
|
|
1093
|
+
* first, then the approval row, then the run row, as the stop of a waiting run
|
|
1094
|
+
* (`Waits.abortWaitingIn`) and the questions do, so no two of them can deadlock. False: no such
|
|
1095
|
+
* approval (in `orgId`).
|
|
1096
|
+
*/
|
|
1097
|
+
async lockConversationOf(id, orgId) {
|
|
1098
|
+
const t = this.db.db;
|
|
1099
|
+
let q = t.selectFrom("approvals").select("conversation_id").where("id", "=", id);
|
|
1100
|
+
if (orgId !== undefined)
|
|
1101
|
+
q = q.where("org_id", "=", orgId);
|
|
1102
|
+
const row = await q.executeTakeFirst();
|
|
1103
|
+
if (!row)
|
|
1104
|
+
return false;
|
|
1105
|
+
await t
|
|
1106
|
+
.selectFrom("conversations")
|
|
1107
|
+
.select("id")
|
|
1108
|
+
.where("id", "=", row.conversation_id)
|
|
1109
|
+
.forUpdate()
|
|
1110
|
+
.executeTakeFirst();
|
|
1111
|
+
return true;
|
|
1112
|
+
}
|
|
1113
|
+
/** Locks, in id order, the conversations `ids` selects; returns their ids. */
|
|
1114
|
+
async lockConversations(ids) {
|
|
1115
|
+
const found = [...new Set((await ids.execute()).map((r) => r.conversation_id))];
|
|
1116
|
+
if (found.length === 0)
|
|
1117
|
+
return [];
|
|
1118
|
+
const rows = await this.db.db
|
|
1119
|
+
.selectFrom("conversations")
|
|
1120
|
+
.select("id")
|
|
1121
|
+
.where("id", "in", found)
|
|
1122
|
+
.orderBy("id")
|
|
1123
|
+
.forUpdate()
|
|
1124
|
+
.execute();
|
|
1125
|
+
return rows.map((r) => r.id);
|
|
1126
|
+
}
|
|
1034
1127
|
/** `conversationId` and its sub-agents' conversations at any depth (at most 16 levels). */
|
|
1035
1128
|
async subtreeOf(conversationId) {
|
|
1036
1129
|
const all = [conversationId];
|
|
@@ -1252,6 +1345,7 @@ ApprovalsService = __decorate([
|
|
|
1252
1345
|
__param(6, Inject(ToolRegistry)),
|
|
1253
1346
|
__param(7, Inject(DevicePolicyService)),
|
|
1254
1347
|
__param(8, Inject(LockService)),
|
|
1255
|
-
__param(9, Inject(SandboxService))
|
|
1348
|
+
__param(9, Inject(SandboxService)),
|
|
1349
|
+
__param(10, Inject(RunResume))
|
|
1256
1350
|
], ApprovalsService);
|
|
1257
1351
|
export { ApprovalsService };
|
|
@@ -23,6 +23,7 @@ export declare const BUILTIN: {
|
|
|
23
23
|
readonly SubagentHandback: "SubagentHandback";
|
|
24
24
|
readonly TaskOutput: "TaskOutput";
|
|
25
25
|
readonly TaskStop: "TaskStop";
|
|
26
|
+
readonly TaskList: "TaskList";
|
|
26
27
|
readonly WebSearch: "WebSearch";
|
|
27
28
|
readonly WebFetch: "WebFetch";
|
|
28
29
|
readonly Platform: "Platform";
|
|
@@ -35,7 +36,8 @@ export declare const BUILTIN: {
|
|
|
35
36
|
export type BuiltinName = (typeof BUILTIN)[keyof typeof BUILTIN];
|
|
36
37
|
/**
|
|
37
38
|
* The builtin tools that run in the conversation's sandbox. `TaskOutput` and `TaskStop` read and
|
|
38
|
-
* stop the background tasks `Bash` started (background Bash spec §2.2, §2.3)
|
|
39
|
+
* stop the background tasks `Bash` started (background Bash spec §2.2, §2.3); `TaskList` lists them
|
|
40
|
+
* (and the conversation's sub-agents).
|
|
39
41
|
*/
|
|
40
42
|
export declare const SANDBOX_TOOL_NAMES: readonly BuiltinName[];
|
|
41
43
|
/** The builtin tools that reach the web through the org's web-search / web-fetch providers. */
|
|
@@ -47,7 +49,7 @@ export declare const WEB_TOOL_NAMES: readonly BuiltinName[];
|
|
|
47
49
|
export declare const BASH_COMPANION_TOOLS: readonly BuiltinName[];
|
|
48
50
|
/**
|
|
49
51
|
* Sandbox tools that need approval when the org setting `sandboxToolPolicy` is `ask` (not the
|
|
50
|
-
* read-only ones). Not `TaskOutput` or `
|
|
52
|
+
* read-only ones). Not `TaskOutput`, `TaskStop` or `TaskList`: they only read, list or stop tasks whose launch
|
|
51
53
|
* already went through `Bash`'s policy (background Bash spec §4.5).
|
|
52
54
|
*/
|
|
53
55
|
export declare const SANDBOX_ASK_TOOL_NAMES: ReadonlySet<string>;
|
|
@@ -110,7 +112,7 @@ export declare const CHILD_REMOVED_TOOLS: readonly ["AskUserQuestion", "Deliver"
|
|
|
110
112
|
/**
|
|
111
113
|
* The builtins every agent has unless it turns them off (tools default-on spec §4), in this
|
|
112
114
|
* order: {@link BUILTIN_TOOL_NAMES} without the ones the registry manages by rule (`ToolSearch`,
|
|
113
|
-
* `Skill`, `SendMessage`, `SubagentHandback`) and without `TaskOutput` / `TaskStop`, which come
|
|
115
|
+
* `Skill`, `SendMessage`, `SubagentHandback`) and without `TaskOutput` / `TaskStop` / `TaskList`, which come
|
|
114
116
|
* with `Bash` ({@link BASH_COMPANION_TOOLS}). These are also the builtins an agent can turn off.
|
|
115
117
|
*/
|
|
116
118
|
export declare const AGENT_BUILTIN_NAMES: readonly BuiltinName[];
|
|
@@ -23,6 +23,7 @@ export const BUILTIN = {
|
|
|
23
23
|
SubagentHandback: "SubagentHandback",
|
|
24
24
|
TaskOutput: "TaskOutput",
|
|
25
25
|
TaskStop: "TaskStop",
|
|
26
|
+
TaskList: "TaskList",
|
|
26
27
|
WebSearch: "WebSearch",
|
|
27
28
|
WebFetch: "WebFetch",
|
|
28
29
|
Platform: "Platform",
|
|
@@ -34,7 +35,8 @@ export const BUILTIN = {
|
|
|
34
35
|
};
|
|
35
36
|
/**
|
|
36
37
|
* The builtin tools that run in the conversation's sandbox. `TaskOutput` and `TaskStop` read and
|
|
37
|
-
* stop the background tasks `Bash` started (background Bash spec §2.2, §2.3)
|
|
38
|
+
* stop the background tasks `Bash` started (background Bash spec §2.2, §2.3); `TaskList` lists them
|
|
39
|
+
* (and the conversation's sub-agents).
|
|
38
40
|
*/
|
|
39
41
|
export const SANDBOX_TOOL_NAMES = [
|
|
40
42
|
BUILTIN.Bash,
|
|
@@ -46,6 +48,7 @@ export const SANDBOX_TOOL_NAMES = [
|
|
|
46
48
|
BUILTIN.Deliver,
|
|
47
49
|
BUILTIN.TaskOutput,
|
|
48
50
|
BUILTIN.TaskStop,
|
|
51
|
+
BUILTIN.TaskList,
|
|
49
52
|
];
|
|
50
53
|
/** The builtin tools that reach the web through the org's web-search / web-fetch providers. */
|
|
51
54
|
export const WEB_TOOL_NAMES = [BUILTIN.WebSearch, BUILTIN.WebFetch];
|
|
@@ -53,10 +56,14 @@ export const WEB_TOOL_NAMES = [BUILTIN.WebSearch, BUILTIN.WebFetch];
|
|
|
53
56
|
* The tools offered with `Bash` whenever it is offered (background Bash: a model that can start a
|
|
54
57
|
* background task can read and stop it). `ToolRegistry` adds them; an explicit ref is harmless.
|
|
55
58
|
*/
|
|
56
|
-
export const BASH_COMPANION_TOOLS = [
|
|
59
|
+
export const BASH_COMPANION_TOOLS = [
|
|
60
|
+
BUILTIN.TaskOutput,
|
|
61
|
+
BUILTIN.TaskStop,
|
|
62
|
+
BUILTIN.TaskList,
|
|
63
|
+
];
|
|
57
64
|
/**
|
|
58
65
|
* Sandbox tools that need approval when the org setting `sandboxToolPolicy` is `ask` (not the
|
|
59
|
-
* read-only ones). Not `TaskOutput` or `
|
|
66
|
+
* read-only ones). Not `TaskOutput`, `TaskStop` or `TaskList`: they only read, list or stop tasks whose launch
|
|
60
67
|
* already went through `Bash`'s policy (background Bash spec §4.5).
|
|
61
68
|
*/
|
|
62
69
|
export const SANDBOX_ASK_TOOL_NAMES = new Set([
|
|
@@ -158,7 +165,7 @@ export const CHILD_REMOVED_TOOLS = [
|
|
|
158
165
|
/**
|
|
159
166
|
* The builtins every agent has unless it turns them off (tools default-on spec §4), in this
|
|
160
167
|
* order: {@link BUILTIN_TOOL_NAMES} without the ones the registry manages by rule (`ToolSearch`,
|
|
161
|
-
* `Skill`, `SendMessage`, `SubagentHandback`) and without `TaskOutput` / `TaskStop`, which come
|
|
168
|
+
* `Skill`, `SendMessage`, `SubagentHandback`) and without `TaskOutput` / `TaskStop` / `TaskList`, which come
|
|
162
169
|
* with `Bash` ({@link BASH_COMPANION_TOOLS}). These are also the builtins an agent can turn off.
|
|
163
170
|
*/
|
|
164
171
|
export const AGENT_BUILTIN_NAMES = BUILTIN_TOOL_NAMES.filter((n) => n !== BUILTIN.ToolSearch &&
|
|
@@ -177,6 +184,7 @@ export const BUILTIN_TOOL_KINDS = {
|
|
|
177
184
|
[BUILTIN.Deliver]: "tool",
|
|
178
185
|
[BUILTIN.TaskOutput]: "read",
|
|
179
186
|
[BUILTIN.TaskStop]: "command",
|
|
187
|
+
[BUILTIN.TaskList]: "read",
|
|
180
188
|
[BUILTIN.ToolSearch]: "meta",
|
|
181
189
|
[BUILTIN.Skill]: "meta",
|
|
182
190
|
[BUILTIN.ReadToolOutput]: "meta",
|
|
@@ -14,7 +14,6 @@ import { AgentDocs } from "../../platform/agent-docs.js";
|
|
|
14
14
|
import { PlatformOperations } from "../../platform/registry.js";
|
|
15
15
|
import type { HookRunner } from "../../runtime/hook-calls.js";
|
|
16
16
|
import { StepLog } from "../../runtime/step-log.js";
|
|
17
|
-
import { UsageReporter } from "../../runtime/usage-report.js";
|
|
18
17
|
import { SandboxService } from "../../sandbox/sandbox.service.js";
|
|
19
18
|
import { ScheduledTaskStore } from "../../schedules/store.js";
|
|
20
19
|
import { StorageService } from "../../storage/storage.service.js";
|
|
@@ -34,7 +33,7 @@ export declare class BuiltinTools {
|
|
|
34
33
|
/** The WebFetch extraction call: the `web_fetch` purpose, its hooks, usage and denials. */
|
|
35
34
|
purposes: ModelPurposesService, host: {
|
|
36
35
|
readonly hooks?: HookRunner;
|
|
37
|
-
} | undefined,
|
|
36
|
+
} | undefined, stepLog: StepLog, log: Logger, background: BackgroundTaskStore, finisher: BackgroundTaskFinisher, stopper: BackgroundTaskStopper, platformOps: PlatformOperations, platformActor: PlatformActor, agentDocs: AgentDocs,
|
|
38
37
|
/** The schedule tools read tasks and grants; their writes go through the task service. */
|
|
39
38
|
scheduleStore: ScheduledTaskStore,
|
|
40
39
|
/** `ScheduleUpdate`'s write: its field change and grant changes in one transaction. */
|
|
@@ -11,8 +11,10 @@ import { Inject, Injectable, Optional } from "@nestjs/common";
|
|
|
11
11
|
import { BackgroundTaskFinisher } from "../../background/finish.js";
|
|
12
12
|
import { BackgroundTaskStopper } from "../../background/stop.js";
|
|
13
13
|
import { BackgroundTaskStore } from "../../background/store.js";
|
|
14
|
+
import { readChildAgents } from "../../conversations/agent-tree.js";
|
|
14
15
|
import { AttachmentsService } from "../../conversations/attachments.service.js";
|
|
15
16
|
import { EventLog } from "../../conversations/event-log.js";
|
|
17
|
+
import { conversationAncestors } from "../../conversations/tree.js";
|
|
16
18
|
import { ConversationDevices } from "../../devices/conversation-devices.js";
|
|
17
19
|
import { ExtensionHost } from "../../extensions/host.js";
|
|
18
20
|
import { ExtensionPointDefaults } from "../../extensions/point-defaults.js";
|
|
@@ -26,7 +28,6 @@ import { AgentDocs } from "../../platform/agent-docs.js";
|
|
|
26
28
|
import { PlatformOperations } from "../../platform/registry.js";
|
|
27
29
|
import { conversationTimeZone, RUN_CONTEXT_CLOCK } from "../../runtime/run-context.service.js";
|
|
28
30
|
import { StepLog } from "../../runtime/step-log.js";
|
|
29
|
-
import { UsageReporter } from "../../runtime/usage-report.js";
|
|
30
31
|
import { SandboxService } from "../../sandbox/sandbox.service.js";
|
|
31
32
|
import { ScheduledTaskStore } from "../../schedules/store.js";
|
|
32
33
|
import { StorageService } from "../../storage/storage.service.js";
|
|
@@ -53,7 +54,7 @@ let BuiltinTools = class BuiltinTools {
|
|
|
53
54
|
tools;
|
|
54
55
|
constructor(db, config, outputs, storage, attachments, eventLog, sandbox, devices, points, webPages,
|
|
55
56
|
/** The WebFetch extraction call: the `web_fetch` purpose, its hooks, usage and denials. */
|
|
56
|
-
purposes, host,
|
|
57
|
+
purposes, host, stepLog, log, background, finisher, stopper, platformOps, platformActor, agentDocs,
|
|
57
58
|
/** The schedule tools read tasks and grants; their writes go through the task service. */
|
|
58
59
|
scheduleStore,
|
|
59
60
|
/** `ScheduleUpdate`'s write: its field change and grant changes in one transaction. */
|
|
@@ -67,6 +68,10 @@ let BuiltinTools = class BuiltinTools {
|
|
|
67
68
|
devices,
|
|
68
69
|
background,
|
|
69
70
|
tasks: { finisher, stopper },
|
|
71
|
+
subagents: {
|
|
72
|
+
inTree: async (root, id) => id !== root && (await conversationAncestors(db.db, id)).includes(root),
|
|
73
|
+
childrenOf: (orgId, conversationId) => readChildAgents(db.db, orgId, conversationId),
|
|
74
|
+
},
|
|
70
75
|
attachments,
|
|
71
76
|
storage,
|
|
72
77
|
eventLog,
|
|
@@ -103,7 +108,7 @@ let BuiltinTools = class BuiltinTools {
|
|
|
103
108
|
points,
|
|
104
109
|
config,
|
|
105
110
|
cache: webPages,
|
|
106
|
-
extract: (ctx, page, prompt) => extractAnswer({ purposes, eventLog, stepLog, config, log, hooks: host?.hooks
|
|
111
|
+
extract: (ctx, page, prompt) => extractAnswer({ purposes, eventLog, stepLog, config, log, hooks: host?.hooks }, ctx, page, prompt),
|
|
107
112
|
}),
|
|
108
113
|
// the platform's own operations and docs, as the run's person (Platform tool spec)
|
|
109
114
|
platformTool({
|
|
@@ -149,19 +154,18 @@ BuiltinTools = __decorate([
|
|
|
149
154
|
__param(9, Inject(WebPages)),
|
|
150
155
|
__param(10, Inject(ModelPurposesService)),
|
|
151
156
|
__param(11, Inject(ExtensionHost)),
|
|
152
|
-
__param(12, Inject(
|
|
153
|
-
__param(13, Inject(
|
|
154
|
-
__param(14, Inject(
|
|
155
|
-
__param(15, Inject(
|
|
156
|
-
__param(16, Inject(
|
|
157
|
-
__param(17, Inject(
|
|
158
|
-
__param(18, Inject(
|
|
159
|
-
__param(19, Inject(
|
|
160
|
-
__param(20, Inject(
|
|
161
|
-
__param(21, Inject(
|
|
162
|
-
__param(22, Inject(
|
|
163
|
-
__param(23,
|
|
164
|
-
__param(
|
|
165
|
-
__param(24, Inject(RUN_CONTEXT_CLOCK))
|
|
157
|
+
__param(12, Inject(StepLog)),
|
|
158
|
+
__param(13, Inject(KERNEL_LOGGER)),
|
|
159
|
+
__param(14, Inject(BackgroundTaskStore)),
|
|
160
|
+
__param(15, Inject(BackgroundTaskFinisher)),
|
|
161
|
+
__param(16, Inject(BackgroundTaskStopper)),
|
|
162
|
+
__param(17, Inject(PlatformOperations)),
|
|
163
|
+
__param(18, Inject(PlatformActor)),
|
|
164
|
+
__param(19, Inject(AgentDocs)),
|
|
165
|
+
__param(20, Inject(ScheduledTaskStore)),
|
|
166
|
+
__param(21, Inject(ScheduleUpdates)),
|
|
167
|
+
__param(22, Inject(ScheduleToolsPort)),
|
|
168
|
+
__param(23, Optional()),
|
|
169
|
+
__param(23, Inject(RUN_CONTEXT_CLOCK))
|
|
166
170
|
], BuiltinTools);
|
|
167
171
|
export { BuiltinTools };
|
|
@@ -29,19 +29,25 @@ const SPEC = {
|
|
|
29
29
|
"Deliver. Other sub-agents of this conversation may run commands in this sandbox at " +
|
|
30
30
|
"the same time. Always pass description: a few words saying what the command is for; the " +
|
|
31
31
|
"user sees it instead of the command.\n\n" +
|
|
32
|
+
"Processes a normal call leaves running (started with '&' or nohup) may be stopped when the " +
|
|
33
|
+
"call ends, depending on the device, so use run_in_background for a dev server, a watcher or " +
|
|
34
|
+
"anything that must keep running after the call.\n\n" +
|
|
32
35
|
"You can use the run_in_background parameter to run the command in the background, which " +
|
|
33
36
|
"allows you to continue working while the command runs, e.g. a dev server, a long build or a " +
|
|
34
37
|
"test suite. The call returns at once with a task id and the command's output goes to a file " +
|
|
35
38
|
"under .capybara/tasks in the workspace directory. Read the output with TaskOutput (or Read) and stop the " +
|
|
36
|
-
"task with TaskStop; you will be told when it finishes.
|
|
39
|
+
"task with TaskStop; you will be told when it finishes. TaskList lists this conversation's " +
|
|
40
|
+
"background tasks and their ids, running ones first. You do not need to use '&' at the end " +
|
|
37
41
|
"of the command when using this parameter. In the background, timeout defaults to the " +
|
|
38
42
|
"deployment's background maximum (7200000 by default). A background task ends when its " +
|
|
39
43
|
"command exits, and processes it left running are stopped. A background task is lost if the " +
|
|
40
44
|
"sandbox is suspended (it is suspended after it has been running for a while, " +
|
|
41
45
|
"sandbox.limits.maxRunningMinutes), so keep its results in files under the workspace directory.\n\n" +
|
|
42
46
|
"Network access goes through a proxy set in HTTP_PROXY / HTTPS_PROXY / ALL_PROXY; a tool " +
|
|
43
|
-
"that ignores them fails with 'Operation not permitted'
|
|
44
|
-
"the
|
|
47
|
+
"that ignores them fails with 'Operation not permitted' or cannot resolve names. Such tools, " +
|
|
48
|
+
"browsers for example, need the proxy passed explicitly: for Chromium (also headless, as " +
|
|
49
|
+
"Playwright or Puppeteer launch it) pass --proxy-server=$HTTPS_PROXY. A blocked domain is " +
|
|
50
|
+
"reported after the output.",
|
|
45
51
|
inputSchema: {
|
|
46
52
|
type: "object",
|
|
47
53
|
properties: {
|
|
@@ -3,6 +3,7 @@ import type { BackgroundTaskFinisher } from "../../../background/finish.js";
|
|
|
3
3
|
import type { BackgroundTaskStopper } from "../../../background/stop.js";
|
|
4
4
|
import type { BackgroundTaskStore } from "../../../background/store.js";
|
|
5
5
|
import type { KernelConfig } from "../../../config/schema.js";
|
|
6
|
+
import type { ChildAgent } from "../../../conversations/agent-tree.js";
|
|
6
7
|
import type { AttachmentsService } from "../../../conversations/attachments.service.js";
|
|
7
8
|
import type { EventLog } from "../../../conversations/event-log.js";
|
|
8
9
|
import { type ConversationDevices } from "../../../devices/conversation-devices.js";
|
|
@@ -25,7 +26,16 @@ export interface SandboxToolDeps {
|
|
|
25
26
|
*/
|
|
26
27
|
devices: Pick<ConversationDevices, "forTool"> & Partial<Pick<ConversationDevices, "usableNow" | "sandboxLevel">>;
|
|
27
28
|
/** Background `Bash` tasks; absent in test stubs, where `run_in_background` is refused. */
|
|
28
|
-
background?: Pick<BackgroundTaskStore, "reserve" | "markStarted" | "failLaunch" | "finishStoppedLaunch" | "releaseStop" | "get" | "advanceOffset">;
|
|
29
|
+
background?: Pick<BackgroundTaskStore, "reserve" | "markStarted" | "failLaunch" | "finishStoppedLaunch" | "releaseStop" | "get" | "advanceOffset" | "runningOwnedBy" | "finishedOwnedBy">;
|
|
30
|
+
/**
|
|
31
|
+
* Whether `id` is a sub-agent conversation in the tree under `rootConversationId` (TaskOutput /
|
|
32
|
+
* TaskStop tell a sub-agent's agentId apart from an unknown task id), and the sub-agents a
|
|
33
|
+
* conversation dispatched itself (`TaskList`); absent in test stubs.
|
|
34
|
+
*/
|
|
35
|
+
subagents?: {
|
|
36
|
+
inTree(rootConversationId: string, id: string): Promise<boolean>;
|
|
37
|
+
childrenOf(orgId: string, conversationId: string): Promise<ChildAgent[]>;
|
|
38
|
+
};
|
|
29
39
|
/**
|
|
30
40
|
* What `TaskOutput` and `TaskStop` finish and stop tasks with; absent in test stubs, where both
|
|
31
41
|
* answer that background tasks are not available.
|
|
@@ -83,6 +93,13 @@ export declare function noSandboxError(): ToolError;
|
|
|
83
93
|
export declare const SANDBOX_UNREACHABLE_TEXT = "The sandbox provider can't be reached (the connection failed), so this call did nothing in the sandbox; retrying won't help until a super admin checks the sandbox extension's configuration (Admin console \u2192 Extensions). Continue without the sandbox, or ask the person to have a super admin check it.";
|
|
84
94
|
/** A provider connection that broke during the call: the provider may have acted before it broke. */
|
|
85
95
|
export declare const SANDBOX_CONNECTION_DROPPED_TEXT = "The connection to the sandbox provider broke during this call, so it may or may not have taken effect; check the sandbox state before retrying. If it fails again, continue without the sandbox and ask the person to have a super admin check the sandbox extension's configuration (Admin console \u2192 Extensions).";
|
|
96
|
+
/**
|
|
97
|
+
* A cloud provider refused the device's tier (`sandbox.tier_refused`, spec §5.3): the tier the
|
|
98
|
+
* device asks for, never the provider's own message (it may name its settings).
|
|
99
|
+
*/
|
|
100
|
+
export declare const sandboxTierRefusedText: (tier: string) => string;
|
|
101
|
+
/** A cloud provider failed to create the device's sandbox otherwise (`sandbox.create_failed`). */
|
|
102
|
+
export declare const SANDBOX_CREATE_FAILED_TEXT = "The cloud sandbox provider could not create this device's sandbox, so nothing ran in it. Retry once; if it fails again, continue without the sandbox and ask the person to have a super admin check the sandbox extension's settings (Admin console \u2192 Extensions).";
|
|
86
103
|
/** The directory of attachments in the device (each conversation has a subdirectory). */
|
|
87
104
|
export declare const attachmentsRoot: (roots: SandboxRoots) => string;
|
|
88
105
|
/** {@link attachmentsRoot} of an instance with the default roots. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DEFAULT_SANDBOX_ROOTS, DeviceProtocolError, isFileSystemGoneError, isSandboxGoneError, ToolError, validateSandboxPath, validateSandboxPathShape, } from "@capybara-hq/plugin-sdk";
|
|
1
|
+
import { DEFAULT_SANDBOX_ROOTS, DeviceProtocolError, isFileSystemGoneError, isSandboxGoneError, isSandboxTier, ToolError, validateSandboxPath, validateSandboxPathShape, } from "@capybara-hq/plugin-sdk";
|
|
2
2
|
import { ANONYMOUS_NO_DEVICE, } from "../../../devices/conversation-devices.js";
|
|
3
3
|
import { ApiError } from "../../../errors.js";
|
|
4
4
|
import { UNSANDBOXED_NOT_ALLOWED_ERROR } from "../../../local-devices/local-device-provider.js";
|
|
@@ -48,6 +48,13 @@ const DEVICE_OFFLINE_TEXT = "The device's machine is offline. Ask the person to
|
|
|
48
48
|
const DEVICE_OUTDATED_TEXT = "The device's machine runs an outdated capybara-device. Ask the person to update it on that machine and start it again.";
|
|
49
49
|
const DEVICE_REVOKED_TEXT = "The device's machine was disconnected. Ask the person to run capybara-device logout, then capybara-device login on it, or to start a new conversation on another device.";
|
|
50
50
|
const deviceProtocolText = (detail) => `The device's machine sent an answer the platform cannot read (${detail}). Ask the person to update capybara-device on that machine, then retry.`;
|
|
51
|
+
/**
|
|
52
|
+
* A cloud provider refused the device's tier (`sandbox.tier_refused`, spec §5.3): the tier the
|
|
53
|
+
* device asks for, never the provider's own message (it may name its settings).
|
|
54
|
+
*/
|
|
55
|
+
export const sandboxTierRefusedText = (tier) => `The cloud sandbox can't run this device at the ${tier} tier: the sandbox provider refused to create it there, so nothing ran in the sandbox and retrying won't help. Ask the person to lower the device's sandbox tier on its device page, or to have an org admin lower the org's highest tier in the sandbox settings, or a super admin to allow that tier in the sandbox extension's settings (Admin console → Extensions). Continue without the sandbox meanwhile.`;
|
|
56
|
+
/** A cloud provider failed to create the device's sandbox otherwise (`sandbox.create_failed`). */
|
|
57
|
+
export const SANDBOX_CREATE_FAILED_TEXT = "The cloud sandbox provider could not create this device's sandbox, so nothing ran in it. Retry once; if it fails again, continue without the sandbox and ask the person to have a super admin check the sandbox extension's settings (Admin console → Extensions).";
|
|
51
58
|
const LOCK_LOST_TEXT = "The sandbox operation was interrupted because the sandbox lock was lost; check the sandbox state and retry.";
|
|
52
59
|
/** The directory of attachments in the device (each conversation has a subdirectory). */
|
|
53
60
|
export const attachmentsRoot = (roots) => `${roots.workspace}/attachments`;
|
|
@@ -357,6 +364,12 @@ export function mapSandboxError(e, log) {
|
|
|
357
364
|
return new ToolError(UNSANDBOXED_TEXT);
|
|
358
365
|
if (e.code === "device.tier_not_granted")
|
|
359
366
|
return new ToolError(UNATTENDED_OPEN_TIER_ERROR);
|
|
367
|
+
if (e.code === "sandbox.tier_refused") {
|
|
368
|
+
const tier = detail?.tier;
|
|
369
|
+
return new ToolError(sandboxTierRefusedText(isSandboxTier(tier) ? tier : "requested"));
|
|
370
|
+
}
|
|
371
|
+
if (e.code === "sandbox.create_failed")
|
|
372
|
+
return new ToolError(SANDBOX_CREATE_FAILED_TEXT);
|
|
360
373
|
}
|
|
361
374
|
// an operation outside withSandbox's own mapping (it records lost files itself)
|
|
362
375
|
if (isFileSystemGoneError(e))
|
|
@@ -11,6 +11,7 @@ export { compileGlob, GlobPatternError, MAX_GLOB_STARS } from "./glob-match.js";
|
|
|
11
11
|
* a provider for it. Allowed by default; with the org setting `sandboxToolPolicy` set to ask,
|
|
12
12
|
* every one but Read / Glob / Grep needs approval (see policy.ts).
|
|
13
13
|
* `TaskOutput` and `TaskStop` read and stop background `Bash` tasks through
|
|
14
|
-
* `SandboxService.ifRunning` (never creating or resuming a sandbox);
|
|
14
|
+
* `SandboxService.ifRunning` (never creating or resuming a sandbox); `TaskList` lists them and the
|
|
15
|
+
* conversation's sub-agents from PG; all three always allowed.
|
|
15
16
|
*/
|
|
16
17
|
export declare function sandboxTools(deps: SandboxToolDeps): BuiltinTool[];
|
|
@@ -4,6 +4,7 @@ import { sandboxEditTool } from "./edit.js";
|
|
|
4
4
|
import { sandboxGlobTool } from "./glob.js";
|
|
5
5
|
import { sandboxGrepTool } from "./grep.js";
|
|
6
6
|
import { sandboxReadTool } from "./read.js";
|
|
7
|
+
import { taskListTool } from "./task-list.js";
|
|
7
8
|
import { taskOutputTool } from "./task-output.js";
|
|
8
9
|
import { taskStopTool } from "./task-stop.js";
|
|
9
10
|
import { sandboxWriteTool } from "./write.js";
|
|
@@ -18,7 +19,8 @@ export { compileGlob, GlobPatternError, MAX_GLOB_STARS } from "./glob-match.js";
|
|
|
18
19
|
* a provider for it. Allowed by default; with the org setting `sandboxToolPolicy` set to ask,
|
|
19
20
|
* every one but Read / Glob / Grep needs approval (see policy.ts).
|
|
20
21
|
* `TaskOutput` and `TaskStop` read and stop background `Bash` tasks through
|
|
21
|
-
* `SandboxService.ifRunning` (never creating or resuming a sandbox);
|
|
22
|
+
* `SandboxService.ifRunning` (never creating or resuming a sandbox); `TaskList` lists them and the
|
|
23
|
+
* conversation's sub-agents from PG; all three always allowed.
|
|
22
24
|
*/
|
|
23
25
|
export function sandboxTools(deps) {
|
|
24
26
|
return [
|
|
@@ -31,5 +33,6 @@ export function sandboxTools(deps) {
|
|
|
31
33
|
sandboxDeliverTool(deps),
|
|
32
34
|
taskOutputTool(deps),
|
|
33
35
|
taskStopTool(deps),
|
|
36
|
+
taskListTool(deps),
|
|
34
37
|
];
|
|
35
38
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { BuiltinTool } from "../../registry.js";
|
|
2
|
+
import { type SandboxToolDeps } from "./common.js";
|
|
3
|
+
/** How many finished background tasks (and finished sub-agents) `TaskList` lists at most. */
|
|
4
|
+
export declare const TASK_LIST_FINISHED_LIMIT = 20;
|
|
5
|
+
/**
|
|
6
|
+
* Built-in `TaskList`: the calling conversation's own background tasks (never its sub-agents' or
|
|
7
|
+
* another conversation's: owner `conversation_id`, as `TaskOutput` checks) and the sub-agents it
|
|
8
|
+
* dispatched itself. Running entries first (oldest first), then with `status: "all"` the
|
|
9
|
+
* {@link TASK_LIST_FINISHED_LIMIT} most recently finished. Reads PG only: it never checks a task in
|
|
10
|
+
* its sandbox, so a status is the poller's or a tool's last one.
|
|
11
|
+
*/
|
|
12
|
+
export declare function taskListTool(deps: SandboxToolDeps): BuiltinTool;
|