@capybara-hq/kernel 0.1.0-rc.23 → 0.1.0-rc.24
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 +7 -3
- 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/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.module.d.ts +2 -1
- package/dist/catalog/catalog.module.js +5 -1
- package/dist/catalog/marketplaces.service.d.ts +1 -1
- 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 +36 -1
- package/dist/catalog/plugin-import.js +23 -1
- package/dist/catalog/plugin-upgrade.d.ts +18 -0
- package/dist/catalog/plugin-upgrade.js +19 -0
- 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 +2 -15
- package/dist/channels/jobs.d.ts +28 -18
- package/dist/channels/jobs.js +63 -26
- 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.service.d.ts +44 -14
- package/dist/conversations/conversations.service.js +52 -38
- package/dist/conversations/event-log.d.ts +7 -10
- package/dist/conversations/event-log.js +24 -15
- package/dist/conversations/events.js +2 -1
- package/dist/conversations/queue.service.d.ts +8 -3
- package/dist/conversations/queue.service.js +37 -13
- package/dist/conversations/titles.d.ts +21 -8
- package/dist/conversations/titles.js +42 -15
- package/dist/db/kernel-schema.d.ts +26 -8
- package/dist/devices/devices.service.d.ts +12 -3
- package/dist/devices/devices.service.js +18 -3
- package/dist/errors.d.ts +11 -0
- package/dist/errors.js +11 -0
- package/dist/evals/run-replay.js +14 -8
- package/dist/extensions/extensions.module.js +3 -0
- package/dist/extensions/lifecycle.d.ts +6 -1
- package/dist/extensions/lifecycle.js +9 -2
- 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/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 +120 -0
- package/dist/infra/outbox/registry.js +108 -0
- package/dist/infra/queue/queue-names.d.ts +8 -0
- package/dist/infra/queue/queue-names.js +16 -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/orgs.service.js +7 -0
- package/dist/overrides.d.ts +20 -3
- package/dist/overrides.js +10 -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/outbox.ops.d.ts +21 -0
- package/dist/platform/ops/outbox.ops.js +125 -0
- 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.module.js +9 -4
- package/dist/runtime/langgraph-loop.js +13 -5
- package/dist/runtime/limits.d.ts +15 -0
- package/dist/runtime/limits.js +25 -0
- package/dist/runtime/loop.d.ts +8 -3
- package/dist/runtime/loop.js +2 -1
- package/dist/runtime/maintenance.d.ts +4 -2
- package/dist/runtime/maintenance.js +17 -2
- package/dist/runtime/model-call.d.ts +14 -16
- package/dist/runtime/model-call.js +14 -24
- 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 +42 -5
- package/dist/runtime/run-control.js +66 -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 +64 -55
- package/dist/runtime/run-queue.js +147 -284
- package/dist/runtime/run-steps.d.ts +1 -2
- package/dist/runtime/run-steps.js +8 -11
- package/dist/runtime/run-worker.d.ts +6 -17
- package/dist/runtime/run-worker.js +32 -34
- package/dist/runtime/runtime.module.d.ts +2 -3
- package/dist/runtime/runtime.module.js +5 -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 +13 -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 +5 -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/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 +1 -3
- package/dist/schedules/fire.js +5 -10
- package/dist/schedules/run-tracker.d.ts +0 -5
- package/dist/schedules/run-tracker.js +0 -13
- package/dist/schedules/scan.job.js +15 -20
- 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 +16 -0
- package/dist/schedules/scheduled-tasks.service.js +53 -0
- package/dist/schedules/schedules.controller.d.ts +5 -1
- package/dist/schedules/schedules.controller.js +15 -1
- 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/tools/approvals.service.d.ts +26 -7
- package/dist/tools/approvals.service.js +88 -10
- 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 +1 -1
- package/dist/tools/pipeline.js +1 -1
- package/dist/tools/questions.service.d.ts +15 -6
- package/dist/tools/questions.service.js +20 -8
- package/dist/tools/registry.d.ts +4 -2
- package/dist/tools/registry.js +4 -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
|
@@ -24,6 +24,7 @@ import { LockService } from "../infra/lock/lock.service.js";
|
|
|
24
24
|
import { WithLock } from "../infra/lock/with-lock.decorator.js";
|
|
25
25
|
import { DevicePolicyService } from "../local-devices/device-policy.service.js";
|
|
26
26
|
import { ORG_ROLES, roleAtLeast } from "../orgs/roles.js";
|
|
27
|
+
import { RunResume } from "../runtime/run-jobs.js";
|
|
27
28
|
import { rootConversationOf } from "../runtime/subagents/child.js";
|
|
28
29
|
import { SandboxService } from "../sandbox/sandbox.service.js";
|
|
29
30
|
import { readScheduleSettings } from "../schedules/effective-settings.js";
|
|
@@ -102,10 +103,12 @@ function canHandle(a, initiator, accountId, role) {
|
|
|
102
103
|
* 工具调用审批:新建(loop 调用)、列出 / 查看 / 处理(HTTP),以及「以后都允许」授权的查看与撤销。
|
|
103
104
|
* 状态全部在 PG:处理决定在事务里 `SELECT … FOR UPDATE` 审批行,多副本并发处理同一审批时恰好一个生效。
|
|
104
105
|
*
|
|
105
|
-
* A decision
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
106
|
+
* A decision resumes its waiting run in the decision's transaction (`RunResume.resumeIn`, after the
|
|
107
|
+
* decided row: lock order approval, then run; transactional outbox spec §6). It is announced after
|
|
108
|
+
* the commit as the domain event `approval.decided` (exactly once: only the decision that changed
|
|
109
|
+
* the row from pending; no kernel subscriber: the IM card update is owed by the `approval_decided`
|
|
110
|
+
* append, transactional outbox spec §8.1). Events are appended in the context's transaction
|
|
111
|
+
* (`EventLog.appendIn`) and published after the commit.
|
|
109
112
|
*/
|
|
110
113
|
let ApprovalsService = class ApprovalsService {
|
|
111
114
|
db;
|
|
@@ -118,6 +121,7 @@ let ApprovalsService = class ApprovalsService {
|
|
|
118
121
|
policies;
|
|
119
122
|
lockService;
|
|
120
123
|
sandbox;
|
|
124
|
+
resumes;
|
|
121
125
|
constructor(db, config, eventLog, events, txHost, schedules,
|
|
122
126
|
/** A trial approval is kept only for a tool the task may hold as a grant (its agent's tools). */
|
|
123
127
|
registry,
|
|
@@ -126,7 +130,9 @@ let ApprovalsService = class ApprovalsService {
|
|
|
126
130
|
/** One decision of a network ask at a time, across replicas (the op is sent before the transaction). */
|
|
127
131
|
lockService,
|
|
128
132
|
/** A trial run's 「这次允许」 becomes a task grant only within the org's egress. */
|
|
129
|
-
sandbox
|
|
133
|
+
sandbox,
|
|
134
|
+
/** A decision resumes its waiting run in the decision's transaction. */
|
|
135
|
+
resumes) {
|
|
130
136
|
this.db = db;
|
|
131
137
|
this.config = config;
|
|
132
138
|
this.eventLog = eventLog;
|
|
@@ -137,6 +143,7 @@ let ApprovalsService = class ApprovalsService {
|
|
|
137
143
|
this.policies = policies;
|
|
138
144
|
this.lockService = lockService;
|
|
139
145
|
this.sandbox = sandbox;
|
|
146
|
+
this.resumes = resumes;
|
|
140
147
|
}
|
|
141
148
|
/**
|
|
142
149
|
* 新建 pending 审批(`expires_at` = 现在 + `tools.approvalTimeoutHours`)并写 `approval_requested`,同一事务。
|
|
@@ -549,7 +556,7 @@ let ApprovalsService = class ApprovalsService {
|
|
|
549
556
|
/** After the commit: the decision's events reach the page, the run's waits and IM delivery. */
|
|
550
557
|
async announceDecided(record, toSeq) {
|
|
551
558
|
await this.eventLog.notify(record.conversationId, toSeq);
|
|
552
|
-
//
|
|
559
|
+
// its IM delivery is enqueued (handler failures are logged); the run resumed in the decision
|
|
553
560
|
await this.events.emit("approval.decided", {
|
|
554
561
|
id: record.id,
|
|
555
562
|
orgId: record.orgId,
|
|
@@ -571,6 +578,9 @@ let ApprovalsService = class ApprovalsService {
|
|
|
571
578
|
// decision committed, even when a caller has a transaction open
|
|
572
579
|
async decideIn(orgId, id, accountId, body, actorTokenId, network) {
|
|
573
580
|
const t = this.db.db;
|
|
581
|
+
// lock order: the conversation, the approval, then the run (as a stop of the waiting run)
|
|
582
|
+
if (!(await this.lockConversationOf(id, orgId)))
|
|
583
|
+
throw notFound();
|
|
574
584
|
const locked = await t
|
|
575
585
|
.selectFrom("approvals")
|
|
576
586
|
.selectAll()
|
|
@@ -734,6 +744,7 @@ let ApprovalsService = class ApprovalsService {
|
|
|
734
744
|
...(reason !== undefined && { reason }),
|
|
735
745
|
},
|
|
736
746
|
});
|
|
747
|
+
await this.resumes.resumeIn(before.runId, id);
|
|
737
748
|
return { record: toRecord(updated), toSeq: Math.max(...written.map((e) => e.seq)) };
|
|
738
749
|
}
|
|
739
750
|
await audit(t, {
|
|
@@ -754,6 +765,9 @@ let ApprovalsService = class ApprovalsService {
|
|
|
754
765
|
...(reason !== undefined && { reason }),
|
|
755
766
|
},
|
|
756
767
|
});
|
|
768
|
+
// the run last (lock order: the decided row, then `runs`); a still-running run is resumed by
|
|
769
|
+
// its suspend's re-check
|
|
770
|
+
await this.resumes.resumeIn(before.runId, id);
|
|
757
771
|
return { record: toRecord(updated), toSeq: Math.max(...written.map((e) => e.seq)) };
|
|
758
772
|
}
|
|
759
773
|
/**
|
|
@@ -908,6 +922,8 @@ let ApprovalsService = class ApprovalsService {
|
|
|
908
922
|
}
|
|
909
923
|
async expireIn(id) {
|
|
910
924
|
const t = this.db.db;
|
|
925
|
+
if (!(await this.lockConversationOf(id)))
|
|
926
|
+
return { outcome: "settled" };
|
|
911
927
|
const locked = await t
|
|
912
928
|
.selectFrom("approvals")
|
|
913
929
|
.selectAll()
|
|
@@ -965,10 +981,22 @@ let ApprovalsService = class ApprovalsService {
|
|
|
965
981
|
*/
|
|
966
982
|
async cancelPendingFor(orgId, accountId) {
|
|
967
983
|
const t = this.db.db;
|
|
984
|
+
// the conversations first, in id order (lock order: conversation, then approval rows)
|
|
985
|
+
const convs = await this.lockConversations(t
|
|
986
|
+
.selectFrom("approvals")
|
|
987
|
+
.select("conversation_id")
|
|
988
|
+
.where("org_id", "=", orgId)
|
|
989
|
+
.where("requested_for", "=", accountId)
|
|
990
|
+
.where("status", "=", "pending"));
|
|
991
|
+
// only the conversations locked above: an approval asked meanwhile in another one is left to
|
|
992
|
+
// the run's stop or the sweep, so no conversation is locked after a row
|
|
993
|
+
if (convs.length === 0)
|
|
994
|
+
return { records: [], seqs: new Map() };
|
|
968
995
|
const rows = await t
|
|
969
996
|
.selectFrom("approvals")
|
|
970
997
|
.selectAll()
|
|
971
998
|
.where("org_id", "=", orgId)
|
|
999
|
+
.where("conversation_id", "in", convs)
|
|
972
1000
|
.where("requested_for", "=", accountId)
|
|
973
1001
|
.where("status", "=", "pending")
|
|
974
1002
|
.orderBy("created_at")
|
|
@@ -996,17 +1024,29 @@ let ApprovalsService = class ApprovalsService {
|
|
|
996
1024
|
* active runs `authorAccountId` started, in the conversation and in its sub-agents'
|
|
997
1025
|
* conversations at any depth (their asks are shown in the root). Each becomes `skipped` with
|
|
998
1026
|
* `approval_decided{skipped}` by the author; access stays blocked. Returns the skipped records and
|
|
999
|
-
* the highest seq written per conversation; the caller
|
|
1000
|
-
*
|
|
1027
|
+
* the highest seq written per conversation; the caller resumes their waiting runs in this
|
|
1028
|
+
* transaction once every skipped row is locked (`ConversationsService.skipWaitsIn`), and notifies
|
|
1029
|
+
* and emits the domain event `approval.decided{skipped}` after the commit (its IM card update is
|
|
1030
|
+
* owed by the append, transactional outbox spec §8.1).
|
|
1001
1031
|
*/
|
|
1002
1032
|
async skipNetworkIn(conversationId, authorAccountId) {
|
|
1003
1033
|
const t = this.db.db;
|
|
1004
1034
|
const tree = await this.subtreeOf(conversationId);
|
|
1035
|
+
// the sub-agents' conversations with a pending ask first, in id order (lock order:
|
|
1036
|
+
// conversation, then approval rows; the caller holds `conversationId`'s already)
|
|
1037
|
+
const convs = await this.lockConversations(t
|
|
1038
|
+
.selectFrom("approvals")
|
|
1039
|
+
.select("conversation_id")
|
|
1040
|
+
.where("conversation_id", "in", tree)
|
|
1041
|
+
.where("kind", "=", "network")
|
|
1042
|
+
.where("status", "=", "pending"));
|
|
1043
|
+
if (convs.length === 0)
|
|
1044
|
+
return { records: [], seqs: new Map() };
|
|
1005
1045
|
const rows = await t
|
|
1006
1046
|
.selectFrom("approvals as a")
|
|
1007
1047
|
.innerJoin("runs as r", "r.id", "a.run_id")
|
|
1008
1048
|
.selectAll("a")
|
|
1009
|
-
.where("a.conversation_id", "in",
|
|
1049
|
+
.where("a.conversation_id", "in", convs)
|
|
1010
1050
|
.where("a.kind", "=", "network")
|
|
1011
1051
|
.where("a.status", "=", "pending")
|
|
1012
1052
|
.where(sql `a.expires_at > now()`)
|
|
@@ -1031,6 +1071,43 @@ let ApprovalsService = class ApprovalsService {
|
|
|
1031
1071
|
}
|
|
1032
1072
|
return { records, seqs };
|
|
1033
1073
|
}
|
|
1074
|
+
/**
|
|
1075
|
+
* Locks the conversation row of approval `id` (`SELECT … FOR UPDATE`; re-entrant with the lock
|
|
1076
|
+
* `EventLog.appendIn` takes later). Every write to an approval row takes its conversation's lock
|
|
1077
|
+
* first, then the approval row, then the run row, as the stop of a waiting run
|
|
1078
|
+
* (`Waits.abortWaitingIn`) and the questions do, so no two of them can deadlock. False: no such
|
|
1079
|
+
* approval (in `orgId`).
|
|
1080
|
+
*/
|
|
1081
|
+
async lockConversationOf(id, orgId) {
|
|
1082
|
+
const t = this.db.db;
|
|
1083
|
+
let q = t.selectFrom("approvals").select("conversation_id").where("id", "=", id);
|
|
1084
|
+
if (orgId !== undefined)
|
|
1085
|
+
q = q.where("org_id", "=", orgId);
|
|
1086
|
+
const row = await q.executeTakeFirst();
|
|
1087
|
+
if (!row)
|
|
1088
|
+
return false;
|
|
1089
|
+
await t
|
|
1090
|
+
.selectFrom("conversations")
|
|
1091
|
+
.select("id")
|
|
1092
|
+
.where("id", "=", row.conversation_id)
|
|
1093
|
+
.forUpdate()
|
|
1094
|
+
.executeTakeFirst();
|
|
1095
|
+
return true;
|
|
1096
|
+
}
|
|
1097
|
+
/** Locks, in id order, the conversations `ids` selects; returns their ids. */
|
|
1098
|
+
async lockConversations(ids) {
|
|
1099
|
+
const found = [...new Set((await ids.execute()).map((r) => r.conversation_id))];
|
|
1100
|
+
if (found.length === 0)
|
|
1101
|
+
return [];
|
|
1102
|
+
const rows = await this.db.db
|
|
1103
|
+
.selectFrom("conversations")
|
|
1104
|
+
.select("id")
|
|
1105
|
+
.where("id", "in", found)
|
|
1106
|
+
.orderBy("id")
|
|
1107
|
+
.forUpdate()
|
|
1108
|
+
.execute();
|
|
1109
|
+
return rows.map((r) => r.id);
|
|
1110
|
+
}
|
|
1034
1111
|
/** `conversationId` and its sub-agents' conversations at any depth (at most 16 levels). */
|
|
1035
1112
|
async subtreeOf(conversationId) {
|
|
1036
1113
|
const all = [conversationId];
|
|
@@ -1252,6 +1329,7 @@ ApprovalsService = __decorate([
|
|
|
1252
1329
|
__param(6, Inject(ToolRegistry)),
|
|
1253
1330
|
__param(7, Inject(DevicePolicyService)),
|
|
1254
1331
|
__param(8, Inject(LockService)),
|
|
1255
|
-
__param(9, Inject(SandboxService))
|
|
1332
|
+
__param(9, Inject(SandboxService)),
|
|
1333
|
+
__param(10, Inject(RunResume))
|
|
1256
1334
|
], ApprovalsService);
|
|
1257
1335
|
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;
|