@capybara-hq/kernel 0.1.0-rc.21 → 0.1.0-rc.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin/admin.controller.d.ts +3 -3
- package/dist/admin/admin.controller.js +6 -2
- package/dist/admin/admin.schemas.d.ts +13 -0
- package/dist/agents/admin-agents.d.ts +16 -3
- package/dist/agents/admin-agents.js +65 -7
- package/dist/agents/agents.schemas.d.ts +24 -6
- package/dist/agents/agents.service.d.ts +4 -3
- package/dist/agents/agents.service.js +39 -26
- package/dist/agents/definition.d.ts +44 -6
- package/dist/agents/definition.js +86 -18
- package/dist/agents/from-template.d.ts +6 -3
- package/dist/agents/from-template.js +57 -44
- package/dist/agents/org-templates.js +97 -41
- package/dist/agents/templates.d.ts +6 -0
- package/dist/agents/templates.js +15 -1
- package/dist/background/launch.d.ts +43 -5
- package/dist/background/launch.js +88 -8
- package/dist/background/session.d.ts +14 -2
- package/dist/background/session.js +26 -4
- package/dist/background/status.d.ts +1 -1
- package/dist/background/status.js +3 -3
- package/dist/background/stop.d.ts +0 -2
- package/dist/background/stop.js +1 -21
- package/dist/catalog/admin-catalog.controller.d.ts +2 -4
- package/dist/catalog/admin-catalog.controller.js +2 -6
- package/dist/catalog/catalog-content.d.ts +5 -0
- package/dist/catalog/catalog-content.js +1 -0
- package/dist/catalog/catalog.module.js +3 -0
- package/dist/catalog/claude/report.d.ts +9 -2
- package/dist/catalog/claude/report.js +1 -0
- package/dist/catalog/claude/translate.js +1 -1
- package/dist/catalog/component-promotion.js +1 -2
- package/dist/catalog/component-state.d.ts +13 -1
- package/dist/catalog/component-state.js +14 -5
- package/dist/catalog/marketplaces.service.d.ts +1 -1
- package/dist/catalog/marketplaces.service.js +2 -1
- package/dist/catalog/org-catalog.controller.d.ts +13 -3
- package/dist/catalog/org-catalog.controller.js +26 -4
- package/dist/catalog/org-catalog.schemas.d.ts +13 -0
- package/dist/catalog/org-catalog.schemas.js +34 -0
- package/dist/catalog/org-plugin-uploads.controller.js +0 -1
- package/dist/catalog/org-plugin-uploads.d.ts +0 -1
- package/dist/catalog/org-plugin-uploads.js +0 -3
- package/dist/catalog/org-plugin-uploads.schemas.d.ts +0 -1
- package/dist/catalog/org-plugin-uploads.schemas.js +0 -2
- package/dist/catalog/platform-components.d.ts +0 -1
- package/dist/catalog/platform-components.js +3 -8
- package/dist/catalog/plugin-import.d.ts +0 -8
- package/dist/catalog/plugin-import.js +4 -35
- package/dist/catalog/plugin-install.d.ts +2 -2
- package/dist/catalog/plugin-install.js +2 -2
- package/dist/catalog/plugin-package.d.ts +7 -0
- package/dist/catalog/plugin-package.js +27 -1
- package/dist/catalog/plugin-upgrade.d.ts +5 -6
- package/dist/catalog/plugin-upgrade.js +5 -23
- package/dist/catalog/requests.service.d.ts +66 -10
- package/dist/catalog/requests.service.js +196 -15
- package/dist/channels/actions.d.ts +2 -0
- package/dist/channels/actions.js +19 -4
- package/dist/channels/cards.d.ts +16 -2
- package/dist/channels/cards.js +40 -7
- package/dist/channels/channels.module.js +3 -0
- package/dist/channels/outbound.d.ts +22 -1
- package/dist/channels/outbound.js +116 -7
- package/dist/channels/phrases.d.ts +25 -0
- package/dist/channels/phrases.js +19 -0
- package/dist/channels/threads.d.ts +12 -0
- package/dist/channels/threads.js +34 -0
- package/dist/config/schema.d.ts +23 -1
- package/dist/config/schema.js +107 -5
- package/dist/conversations/conversations.service.d.ts +42 -9
- package/dist/conversations/conversations.service.js +57 -25
- package/dist/conversations/events.d.ts +106 -11
- package/dist/conversations/events.js +121 -18
- package/dist/conversations/message-context.d.ts +6 -3
- package/dist/conversations/message-context.js +14 -10
- package/dist/conversations/queue.d.ts +15 -2
- package/dist/conversations/queue.js +22 -3
- package/dist/conversations/queue.service.d.ts +12 -6
- package/dist/conversations/queue.service.js +36 -13
- package/dist/db/kernel-schema.d.ts +105 -3
- package/dist/devices/conversation-devices.d.ts +8 -1
- package/dist/devices/conversation-devices.js +8 -0
- package/dist/devices/devices.controller.d.ts +21 -4
- package/dist/devices/devices.controller.js +46 -8
- package/dist/devices/devices.schemas.d.ts +9 -1
- package/dist/devices/devices.schemas.js +11 -3
- package/dist/devices/devices.service.d.ts +176 -4
- package/dist/devices/devices.service.js +347 -6
- package/dist/devices/dto.d.ts +56 -3
- package/dist/devices/dto.js +51 -1
- package/dist/devices/public-suffix.d.ts +6 -0
- package/dist/devices/public-suffix.js +79 -0
- package/dist/errors.d.ts +50 -5
- package/dist/errors.js +50 -5
- package/dist/evals/reconstruct.d.ts +18 -13
- package/dist/evals/reconstruct.js +50 -36
- package/dist/evals/recorded-tools.d.ts +7 -7
- package/dist/evals/recorded-tools.js +4 -3
- package/dist/evals/trajectory.d.ts +6 -1
- package/dist/evals/trajectory.js +7 -0
- package/dist/extensions/package.js +2 -2
- package/dist/http/api.module.js +5 -0
- package/dist/identity/settings.d.ts +53 -3
- package/dist/identity/settings.js +92 -9
- package/dist/inbox/inbox.module.js +2 -1
- package/dist/inbox/inbox.service.d.ts +19 -4
- package/dist/inbox/inbox.service.js +14 -3
- package/dist/infra/config/kernel-config.service.d.ts +7 -0
- package/dist/infra/config/kernel-config.service.js +31 -0
- package/dist/infra/events/kernel-events.d.ts +2 -1
- package/dist/local-devices/device-policy.service.d.ts +65 -0
- package/dist/local-devices/device-policy.service.js +217 -0
- package/dist/local-devices/local-device-gateway.d.ts +4 -2
- package/dist/local-devices/local-device-gateway.js +39 -11
- package/dist/local-devices/local-device-provider.d.ts +40 -3
- package/dist/local-devices/local-device-provider.js +109 -7
- package/dist/local-devices/local-devices.module.d.ts +2 -1
- package/dist/local-devices/local-devices.module.js +19 -3
- package/dist/local-devices/machines.d.ts +30 -3
- package/dist/local-devices/machines.js +79 -3
- package/dist/local-devices/network-grants.d.ts +104 -0
- package/dist/local-devices/network-grants.js +288 -0
- package/dist/local-devices/policy-summary.d.ts +20 -0
- package/dist/local-devices/policy-summary.js +63 -0
- package/dist/orgs/orgs.module.js +4 -10
- package/dist/orgs/roles.d.ts +1 -1
- package/dist/orgs/roles.js +4 -0
- package/dist/orgs/settings.controller.js +4 -3
- package/dist/orgs/settings.service.d.ts +172 -14
- package/dist/orgs/settings.service.js +229 -27
- package/dist/platform/exclusions.js +11 -1
- package/dist/platform/operation.js +4 -0
- package/dist/platform/ops/admin-items.ops.js +1 -1
- package/dist/platform/ops/admin.ops.js +32 -7
- package/dist/platform/ops/agent-skills.ops.js +2 -2
- package/dist/platform/ops/agent-templates.ops.js +2 -2
- package/dist/platform/ops/agents.ops.js +11 -15
- package/dist/platform/ops/devices.ops.js +3 -1
- package/dist/platform/ops/inbox.ops.js +19 -0
- package/dist/platform/ops/org-settings.ops.js +15 -6
- package/dist/platform/ops/orgs.ops.js +1 -0
- package/dist/platform/ops/platform.ops.d.ts +9 -1
- package/dist/platform/ops/platform.ops.js +34 -12
- package/dist/platform/ops/requests.ops.js +3 -2
- package/dist/platform/ops/schedules.ops.d.ts +21 -0
- package/dist/platform/ops/schedules.ops.js +470 -0
- package/dist/platform/ops/skills.ops.js +3 -3
- package/dist/platform/platform-ops.module.d.ts +2 -1
- package/dist/platform/platform-ops.module.js +5 -0
- package/dist/platform/route-schemas.js +3 -0
- package/dist/roles/worker.module.js +3 -0
- package/dist/runtime/context/build.js +13 -4
- package/dist/runtime/context/compaction.js +6 -3
- package/dist/runtime/context/device-paths.d.ts +43 -21
- package/dist/runtime/context/device-paths.js +104 -21
- package/dist/runtime/context/run-context.d.ts +9 -0
- package/dist/runtime/context/run-context.js +8 -0
- package/dist/runtime/context/skills.d.ts +14 -1
- package/dist/runtime/context/skills.js +36 -5
- package/dist/runtime/maintenance.d.ts +4 -2
- package/dist/runtime/maintenance.js +16 -5
- package/dist/runtime/run-finish.d.ts +6 -1
- package/dist/runtime/run-finish.js +16 -2
- package/dist/runtime/run-queue.js +21 -2
- package/dist/runtime/run-worker.js +14 -33
- package/dist/runtime/runtime.module.js +3 -0
- package/dist/runtime/subagents/definition.d.ts +32 -14
- package/dist/runtime/subagents/definition.js +106 -109
- package/dist/runtime/subagents/dispatch.js +4 -3
- package/dist/runtime/subagents/preamble.d.ts +2 -1
- package/dist/runtime/subagents/preamble.js +2 -1
- package/dist/runtime/waits.js +14 -4
- package/dist/sandbox/platform-tiers.d.ts +86 -0
- package/dist/sandbox/platform-tiers.js +97 -0
- package/dist/sandbox/sandbox.service.d.ts +121 -11
- package/dist/sandbox/sandbox.service.js +351 -30
- package/dist/sandbox/tiers.d.ts +98 -0
- package/dist/sandbox/tiers.js +104 -0
- package/dist/schedules/effective-settings.d.ts +16 -0
- package/dist/schedules/effective-settings.js +17 -0
- package/dist/schedules/errors.d.ts +8 -0
- package/dist/schedules/errors.js +8 -0
- package/dist/schedules/fire.d.ts +118 -0
- package/dist/schedules/fire.js +625 -0
- package/dist/schedules/grant-rules.d.ts +94 -0
- package/dist/schedules/grant-rules.js +126 -0
- package/dist/schedules/job-ids.d.ts +32 -0
- package/dist/schedules/job-ids.js +27 -0
- package/dist/schedules/pause.d.ts +9 -0
- package/dist/schedules/pause.js +33 -0
- package/dist/schedules/run-tracker.d.ts +81 -0
- package/dist/schedules/run-tracker.js +333 -0
- package/dist/schedules/scan.job.d.ts +64 -0
- package/dist/schedules/scan.job.js +303 -0
- package/dist/schedules/schedule-math.d.ts +31 -0
- package/dist/schedules/schedule-math.js +223 -0
- package/dist/schedules/scheduled-tasks.service.d.ts +351 -0
- package/dist/schedules/scheduled-tasks.service.js +1193 -0
- package/dist/schedules/schedules.controller.d.ts +68 -0
- package/dist/schedules/schedules.controller.js +242 -0
- package/dist/schedules/schedules.module.d.ts +16 -0
- package/dist/schedules/schedules.module.js +65 -0
- package/dist/schedules/schedules.schemas.d.ts +316 -0
- package/dist/schedules/schedules.schemas.js +186 -0
- package/dist/schedules/store.d.ts +81 -0
- package/dist/schedules/store.js +390 -0
- package/dist/schedules/store.module.d.ts +6 -0
- package/dist/schedules/store.module.js +21 -0
- package/dist/schedules/types.d.ts +108 -0
- package/dist/schedules/types.js +1 -0
- package/dist/schedules/unattended.d.ts +117 -0
- package/dist/schedules/unattended.js +228 -0
- package/dist/setup/oauth-token-probe.js +8 -4
- package/dist/skills/agent-skills.service.d.ts +4 -8
- package/dist/skills/agent-skills.service.js +18 -53
- package/dist/skills/catalog.d.ts +65 -62
- package/dist/skills/catalog.js +109 -206
- package/dist/skills/conversation-catalog.d.ts +3 -3
- package/dist/skills/conversation-catalog.js +5 -12
- package/dist/skills/invoke.d.ts +2 -2
- package/dist/skills/skills.controller.d.ts +3 -1
- package/dist/skills/skills.service.d.ts +38 -37
- package/dist/skills/skills.service.js +168 -107
- package/dist/skills/usable.d.ts +57 -8
- package/dist/skills/usable.js +172 -38
- package/dist/tools/approvals.controller.d.ts +4 -2
- package/dist/tools/approvals.controller.js +17 -2
- package/dist/tools/approvals.schemas.d.ts +1 -0
- package/dist/tools/approvals.schemas.js +3 -1
- package/dist/tools/approvals.service.d.ts +182 -7
- package/dist/tools/approvals.service.js +597 -13
- package/dist/tools/builtin-names.d.ts +25 -4
- package/dist/tools/builtin-names.js +45 -4
- package/dist/tools/builtins/builtin-tools.d.ts +8 -0
- package/dist/tools/builtins/builtin-tools.js +23 -2
- package/dist/tools/builtins/sandbox/bash.js +16 -7
- package/dist/tools/builtins/sandbox/common.d.ts +1 -1
- package/dist/tools/builtins/sandbox/common.js +33 -10
- package/dist/tools/builtins/sandbox/edit.js +7 -3
- package/dist/tools/builtins/sandbox/file-state.d.ts +31 -1
- package/dist/tools/builtins/sandbox/file-state.js +33 -3
- package/dist/tools/builtins/sandbox/write.js +8 -4
- package/dist/tools/builtins/schedules.d.ts +107 -0
- package/dist/tools/builtins/schedules.js +789 -0
- package/dist/tools/elicitation.d.ts +2 -0
- package/dist/tools/elicitation.js +1 -1
- package/dist/tools/fixed-ask.d.ts +7 -0
- package/dist/tools/fixed-ask.js +9 -0
- package/dist/tools/network-asks.d.ts +109 -0
- package/dist/tools/network-asks.js +221 -0
- package/dist/tools/pipeline.d.ts +53 -6
- package/dist/tools/pipeline.js +202 -13
- package/dist/tools/policy.d.ts +21 -8
- package/dist/tools/policy.js +63 -9
- package/dist/tools/registry.d.ts +10 -1
- package/dist/tools/tools.module.js +12 -0
- package/package.json +2 -2
- package/src/migrations/0113_scheduled_tasks.sql +108 -0
- package/src/migrations/0114_network_asks.sql +23 -0
- package/src/migrations/0115_network_requests.sql +28 -0
- package/src/migrations/0116_skills_default_on.sql +37 -0
- package/src/migrations/0117_sandbox_tiers.sql +11 -0
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { Injectable } from "@nestjs/common";
|
|
8
|
+
import { sql } from "kysely";
|
|
9
|
+
const NON_TERMINAL = ["pending", "running"];
|
|
10
|
+
const date = (v) => (v instanceof Date ? v : new Date(v));
|
|
11
|
+
const dateOrNull = (v) => (v === null ? null : date(v));
|
|
12
|
+
const toTask = (r) => ({
|
|
13
|
+
id: r.id,
|
|
14
|
+
orgId: r.org_id,
|
|
15
|
+
accountId: r.account_id,
|
|
16
|
+
agentId: r.agent_id,
|
|
17
|
+
name: r.name,
|
|
18
|
+
prompt: r.prompt,
|
|
19
|
+
trigger: r.trigger,
|
|
20
|
+
mode: r.mode,
|
|
21
|
+
conversationId: r.conversation_id,
|
|
22
|
+
chat: r.chat,
|
|
23
|
+
model: r.model,
|
|
24
|
+
effort: r.effort,
|
|
25
|
+
deviceId: r.device_id,
|
|
26
|
+
status: r.status,
|
|
27
|
+
pauseReason: r.pause_reason,
|
|
28
|
+
pausedBy: r.paused_by,
|
|
29
|
+
nextRunAt: dateOrNull(r.next_run_at),
|
|
30
|
+
jitterSeconds: r.jitter_seconds,
|
|
31
|
+
expiresAt: dateOrNull(r.expires_at),
|
|
32
|
+
consecutiveFailures: r.consecutive_failures,
|
|
33
|
+
createdAt: date(r.created_at),
|
|
34
|
+
updatedAt: date(r.updated_at),
|
|
35
|
+
});
|
|
36
|
+
const toRun = (r) => ({
|
|
37
|
+
id: r.id,
|
|
38
|
+
taskId: r.task_id,
|
|
39
|
+
orgId: r.org_id,
|
|
40
|
+
scheduledFor: date(r.scheduled_for),
|
|
41
|
+
firedAt: dateOrNull(r.fired_at),
|
|
42
|
+
trial: r.trial,
|
|
43
|
+
manual: r.manual,
|
|
44
|
+
conversationId: r.conversation_id,
|
|
45
|
+
runId: r.run_id,
|
|
46
|
+
status: r.status,
|
|
47
|
+
skipReason: r.skip_reason,
|
|
48
|
+
error: r.error,
|
|
49
|
+
missingGrants: r.missing_grants,
|
|
50
|
+
});
|
|
51
|
+
const json = (v) => (v === null ? null : JSON.stringify(v));
|
|
52
|
+
/** Maps a task patch to its columns; fields left undefined are not written. */
|
|
53
|
+
function taskColumns(p) {
|
|
54
|
+
const c = {};
|
|
55
|
+
if (p.agentId !== undefined)
|
|
56
|
+
c.agent_id = p.agentId;
|
|
57
|
+
if (p.name !== undefined)
|
|
58
|
+
c.name = p.name;
|
|
59
|
+
if (p.prompt !== undefined)
|
|
60
|
+
c.prompt = p.prompt;
|
|
61
|
+
if (p.trigger !== undefined)
|
|
62
|
+
c.trigger = JSON.stringify(p.trigger);
|
|
63
|
+
if (p.mode !== undefined)
|
|
64
|
+
c.mode = p.mode;
|
|
65
|
+
if (p.conversationId !== undefined)
|
|
66
|
+
c.conversation_id = p.conversationId;
|
|
67
|
+
if (p.chat !== undefined)
|
|
68
|
+
c.chat = json(p.chat);
|
|
69
|
+
if (p.model !== undefined)
|
|
70
|
+
c.model = json(p.model);
|
|
71
|
+
if (p.effort !== undefined)
|
|
72
|
+
c.effort = p.effort;
|
|
73
|
+
if (p.deviceId !== undefined)
|
|
74
|
+
c.device_id = p.deviceId;
|
|
75
|
+
if (p.status !== undefined)
|
|
76
|
+
c.status = p.status;
|
|
77
|
+
if (p.pauseReason !== undefined)
|
|
78
|
+
c.pause_reason = p.pauseReason;
|
|
79
|
+
if (p.pausedBy !== undefined)
|
|
80
|
+
c.paused_by = p.pausedBy;
|
|
81
|
+
if (p.nextRunAt !== undefined)
|
|
82
|
+
c.next_run_at = p.nextRunAt;
|
|
83
|
+
if (p.jitterSeconds !== undefined)
|
|
84
|
+
c.jitter_seconds = p.jitterSeconds;
|
|
85
|
+
if (p.expiresAt !== undefined)
|
|
86
|
+
c.expires_at = p.expiresAt;
|
|
87
|
+
if (p.consecutiveFailures !== undefined)
|
|
88
|
+
c.consecutive_failures = p.consecutiveFailures;
|
|
89
|
+
return c;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Scheduled tasks, their runs and grants (spec §4): reads and writes rows only. Every method takes
|
|
93
|
+
* the database handle first so the caller decides the transaction (the scanner's `lockDue` and
|
|
94
|
+
* `insertRun` run in one, under the rows' locks).
|
|
95
|
+
*/
|
|
96
|
+
let ScheduledTaskStore = class ScheduledTaskStore {
|
|
97
|
+
async insertTask(t, task) {
|
|
98
|
+
const row = await t
|
|
99
|
+
.insertInto("scheduled_tasks")
|
|
100
|
+
.values({
|
|
101
|
+
id: task.id,
|
|
102
|
+
org_id: task.orgId,
|
|
103
|
+
account_id: task.accountId,
|
|
104
|
+
agent_id: task.agentId,
|
|
105
|
+
name: task.name,
|
|
106
|
+
prompt: task.prompt,
|
|
107
|
+
trigger: JSON.stringify(task.trigger),
|
|
108
|
+
mode: task.mode,
|
|
109
|
+
conversation_id: task.conversationId,
|
|
110
|
+
chat: json(task.chat),
|
|
111
|
+
model: json(task.model),
|
|
112
|
+
effort: task.effort,
|
|
113
|
+
device_id: task.deviceId,
|
|
114
|
+
status: task.status,
|
|
115
|
+
next_run_at: task.nextRunAt,
|
|
116
|
+
jitter_seconds: task.jitterSeconds,
|
|
117
|
+
expires_at: task.expiresAt,
|
|
118
|
+
})
|
|
119
|
+
.returningAll()
|
|
120
|
+
.executeTakeFirstOrThrow();
|
|
121
|
+
return toTask(row);
|
|
122
|
+
}
|
|
123
|
+
/** A live (not deleted) task of the org; null when missing, deleted or in another org. */
|
|
124
|
+
async getTask(t, orgId, id) {
|
|
125
|
+
const row = await t
|
|
126
|
+
.selectFrom("scheduled_tasks")
|
|
127
|
+
.selectAll()
|
|
128
|
+
.where("org_id", "=", orgId)
|
|
129
|
+
.where("id", "=", id)
|
|
130
|
+
.where("deleted_at", "is", null)
|
|
131
|
+
.executeTakeFirst();
|
|
132
|
+
return row ? toTask(row) : null;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* {@link getTask} under `FOR UPDATE` (call it inside a transaction): a person's write holds the
|
|
136
|
+
* row, so the scanner's `lockDue` skips it until the write commits.
|
|
137
|
+
*/
|
|
138
|
+
async lockTask(t, orgId, id) {
|
|
139
|
+
const row = await t
|
|
140
|
+
.selectFrom("scheduled_tasks")
|
|
141
|
+
.selectAll()
|
|
142
|
+
.where("org_id", "=", orgId)
|
|
143
|
+
.where("id", "=", id)
|
|
144
|
+
.where("deleted_at", "is", null)
|
|
145
|
+
.forUpdate()
|
|
146
|
+
.executeTakeFirst();
|
|
147
|
+
return row ? toTask(row) : null;
|
|
148
|
+
}
|
|
149
|
+
/** Patches a live task; null when it is missing or deleted. */
|
|
150
|
+
async updateTask(t, id, patch) {
|
|
151
|
+
const row = await t
|
|
152
|
+
.updateTable("scheduled_tasks")
|
|
153
|
+
.set({ ...taskColumns(patch), updated_at: sql `now()` })
|
|
154
|
+
.where("id", "=", id)
|
|
155
|
+
.where("deleted_at", "is", null)
|
|
156
|
+
.returningAll()
|
|
157
|
+
.executeTakeFirst();
|
|
158
|
+
return row ? toTask(row) : null;
|
|
159
|
+
}
|
|
160
|
+
/** Deletes a task softly: hidden from every read and never due again. */
|
|
161
|
+
async softDelete(t, id) {
|
|
162
|
+
const r = await t
|
|
163
|
+
.updateTable("scheduled_tasks")
|
|
164
|
+
.set({ deleted_at: sql `now()`, updated_at: sql `now()`, next_run_at: null })
|
|
165
|
+
.where("id", "=", id)
|
|
166
|
+
.where("deleted_at", "is", null)
|
|
167
|
+
.executeTakeFirst();
|
|
168
|
+
return Number(r.numUpdatedRows) > 0;
|
|
169
|
+
}
|
|
170
|
+
/** A creator's live tasks, newest first. */
|
|
171
|
+
async listForAccount(t, orgId, accountId) {
|
|
172
|
+
const rows = await t
|
|
173
|
+
.selectFrom("scheduled_tasks")
|
|
174
|
+
.selectAll()
|
|
175
|
+
.where("org_id", "=", orgId)
|
|
176
|
+
.where("account_id", "=", accountId)
|
|
177
|
+
.where("deleted_at", "is", null)
|
|
178
|
+
.orderBy("created_at", "desc")
|
|
179
|
+
.orderBy("id")
|
|
180
|
+
.execute();
|
|
181
|
+
return rows.map(toTask);
|
|
182
|
+
}
|
|
183
|
+
/** Every live task of the org, newest first. */
|
|
184
|
+
async listForOrg(t, orgId) {
|
|
185
|
+
const rows = await t
|
|
186
|
+
.selectFrom("scheduled_tasks")
|
|
187
|
+
.selectAll()
|
|
188
|
+
.where("org_id", "=", orgId)
|
|
189
|
+
.where("deleted_at", "is", null)
|
|
190
|
+
.orderBy("created_at", "desc")
|
|
191
|
+
.orderBy("id")
|
|
192
|
+
.execute();
|
|
193
|
+
return rows.map(toTask);
|
|
194
|
+
}
|
|
195
|
+
/** Live tasks that count against the caps (`active` and `paused`), of the org or one creator. */
|
|
196
|
+
async countActive(t, orgId, accountId) {
|
|
197
|
+
let q = t
|
|
198
|
+
.selectFrom("scheduled_tasks")
|
|
199
|
+
.select((eb) => eb.fn.countAll().as("n"))
|
|
200
|
+
.where("org_id", "=", orgId)
|
|
201
|
+
.where("deleted_at", "is", null)
|
|
202
|
+
.where("status", "in", ["active", "paused"]);
|
|
203
|
+
if (accountId !== undefined)
|
|
204
|
+
q = q.where("account_id", "=", accountId);
|
|
205
|
+
const row = await q.executeTakeFirstOrThrow();
|
|
206
|
+
return Number(row.n);
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Locks up to `limit` due tasks (active, live, `next_run_at <= now`), oldest first, skipping
|
|
210
|
+
* rows another transaction holds (`FOR UPDATE SKIP LOCKED`). Call it inside a transaction: the
|
|
211
|
+
* locks last until it ends.
|
|
212
|
+
*/
|
|
213
|
+
async lockDue(t, now, limit) {
|
|
214
|
+
const rows = await t
|
|
215
|
+
.selectFrom("scheduled_tasks")
|
|
216
|
+
.selectAll()
|
|
217
|
+
.where("status", "=", "active")
|
|
218
|
+
.where("deleted_at", "is", null)
|
|
219
|
+
.where("next_run_at", "<=", now)
|
|
220
|
+
.orderBy("next_run_at")
|
|
221
|
+
.orderBy("id")
|
|
222
|
+
.limit(limit)
|
|
223
|
+
.forUpdate()
|
|
224
|
+
.skipLocked()
|
|
225
|
+
.execute();
|
|
226
|
+
return rows.map(toTask);
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Inserts a task run; null when a non-trial run for the same tick already exists (the
|
|
230
|
+
* exactly-once guard, `UNIQUE (task_id, scheduled_for) WHERE NOT trial`).
|
|
231
|
+
*/
|
|
232
|
+
async insertRun(t, run) {
|
|
233
|
+
const row = await t
|
|
234
|
+
.insertInto("scheduled_task_runs")
|
|
235
|
+
.values({
|
|
236
|
+
id: run.id,
|
|
237
|
+
task_id: run.taskId,
|
|
238
|
+
org_id: run.orgId,
|
|
239
|
+
scheduled_for: run.scheduledFor,
|
|
240
|
+
trial: run.trial,
|
|
241
|
+
manual: run.manual ?? false,
|
|
242
|
+
status: run.status ?? "pending",
|
|
243
|
+
skip_reason: run.skipReason ?? null,
|
|
244
|
+
fired_at: run.firedAt ?? null,
|
|
245
|
+
conversation_id: run.conversationId ?? null,
|
|
246
|
+
})
|
|
247
|
+
.onConflict((oc) => oc.columns(["task_id", "scheduled_for"]).where("trial", "=", false).doNothing())
|
|
248
|
+
.returningAll()
|
|
249
|
+
.executeTakeFirst();
|
|
250
|
+
return row ? toRun(row) : null;
|
|
251
|
+
}
|
|
252
|
+
/** Patches a task run; null when it does not exist. */
|
|
253
|
+
async updateRun(t, id, patch) {
|
|
254
|
+
const c = {};
|
|
255
|
+
if (patch.scheduledFor !== undefined)
|
|
256
|
+
c.scheduled_for = patch.scheduledFor;
|
|
257
|
+
if (patch.firedAt !== undefined)
|
|
258
|
+
c.fired_at = patch.firedAt;
|
|
259
|
+
if (patch.conversationId !== undefined)
|
|
260
|
+
c.conversation_id = patch.conversationId;
|
|
261
|
+
if (patch.runId !== undefined)
|
|
262
|
+
c.run_id = patch.runId;
|
|
263
|
+
if (patch.status !== undefined)
|
|
264
|
+
c.status = patch.status;
|
|
265
|
+
if (patch.skipReason !== undefined)
|
|
266
|
+
c.skip_reason = patch.skipReason;
|
|
267
|
+
if (patch.error !== undefined)
|
|
268
|
+
c.error = patch.error;
|
|
269
|
+
if (patch.missingGrants !== undefined)
|
|
270
|
+
c.missing_grants = JSON.stringify(patch.missingGrants);
|
|
271
|
+
if (Object.keys(c).length === 0) {
|
|
272
|
+
const row = await t
|
|
273
|
+
.selectFrom("scheduled_task_runs")
|
|
274
|
+
.selectAll()
|
|
275
|
+
.where("id", "=", id)
|
|
276
|
+
.executeTakeFirst();
|
|
277
|
+
return row ? toRun(row) : null;
|
|
278
|
+
}
|
|
279
|
+
const row = await t
|
|
280
|
+
.updateTable("scheduled_task_runs")
|
|
281
|
+
.set(c)
|
|
282
|
+
.where("id", "=", id)
|
|
283
|
+
.returningAll()
|
|
284
|
+
.executeTakeFirst();
|
|
285
|
+
return row ? toRun(row) : null;
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* The task's latest run still `pending` or `running` (the overlap check), other than `exceptId`
|
|
289
|
+
* (the run being fired); null when none.
|
|
290
|
+
*/
|
|
291
|
+
async latestNonTerminalRun(t, taskId, exceptId) {
|
|
292
|
+
let q = t
|
|
293
|
+
.selectFrom("scheduled_task_runs")
|
|
294
|
+
.selectAll()
|
|
295
|
+
.where("task_id", "=", taskId)
|
|
296
|
+
.where("status", "in", NON_TERMINAL);
|
|
297
|
+
if (exceptId !== undefined)
|
|
298
|
+
q = q.where("id", "!=", exceptId);
|
|
299
|
+
const row = await q
|
|
300
|
+
.orderBy("scheduled_for", "desc")
|
|
301
|
+
.orderBy("id", "desc")
|
|
302
|
+
.limit(1)
|
|
303
|
+
.executeTakeFirst();
|
|
304
|
+
return row ? toRun(row) : null;
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Runs of the org fired at or after `since` (the `maxRunsPerHour` count; trial runs included,
|
|
308
|
+
* skipped runs not: a run whose queued message a person removed was never run).
|
|
309
|
+
*/
|
|
310
|
+
async countFiredSince(t, orgId, since) {
|
|
311
|
+
const row = await t
|
|
312
|
+
.selectFrom("scheduled_task_runs")
|
|
313
|
+
.select((eb) => eb.fn.countAll().as("n"))
|
|
314
|
+
.where("org_id", "=", orgId)
|
|
315
|
+
.where("fired_at", ">=", since)
|
|
316
|
+
.where("status", "!=", "skipped")
|
|
317
|
+
.executeTakeFirstOrThrow();
|
|
318
|
+
return Number(row.n);
|
|
319
|
+
}
|
|
320
|
+
/** A task's runs, latest tick first. */
|
|
321
|
+
async listRuns(t, taskId, limit) {
|
|
322
|
+
const rows = await t
|
|
323
|
+
.selectFrom("scheduled_task_runs")
|
|
324
|
+
.selectAll()
|
|
325
|
+
.where("task_id", "=", taskId)
|
|
326
|
+
.orderBy("scheduled_for", "desc")
|
|
327
|
+
.orderBy("id", "desc")
|
|
328
|
+
.limit(limit)
|
|
329
|
+
.execute();
|
|
330
|
+
return rows.map(toRun);
|
|
331
|
+
}
|
|
332
|
+
async listGrants(t, taskId) {
|
|
333
|
+
const rows = await t
|
|
334
|
+
.selectFrom("scheduled_task_grants")
|
|
335
|
+
.select(["tool_key", "spec_hash", "connector_id"])
|
|
336
|
+
.where("task_id", "=", taskId)
|
|
337
|
+
.orderBy("tool_key")
|
|
338
|
+
.execute();
|
|
339
|
+
return rows.map((r) => ({
|
|
340
|
+
toolKey: r.tool_key,
|
|
341
|
+
specHash: r.spec_hash,
|
|
342
|
+
connectorId: r.connector_id,
|
|
343
|
+
}));
|
|
344
|
+
}
|
|
345
|
+
/** Adds a grant, replacing the task's grant of the same tool key. */
|
|
346
|
+
async addGrant(t, taskId, grant) {
|
|
347
|
+
await t
|
|
348
|
+
.insertInto("scheduled_task_grants")
|
|
349
|
+
.values({
|
|
350
|
+
task_id: taskId,
|
|
351
|
+
tool_key: grant.toolKey,
|
|
352
|
+
spec_hash: grant.specHash,
|
|
353
|
+
connector_id: grant.connectorId,
|
|
354
|
+
})
|
|
355
|
+
.onConflict((oc) => oc.columns(["task_id", "tool_key"]).doUpdateSet({
|
|
356
|
+
spec_hash: grant.specHash,
|
|
357
|
+
connector_id: grant.connectorId,
|
|
358
|
+
created_at: sql `now()`,
|
|
359
|
+
}))
|
|
360
|
+
.execute();
|
|
361
|
+
}
|
|
362
|
+
async removeGrant(t, taskId, toolKey) {
|
|
363
|
+
const r = await t
|
|
364
|
+
.deleteFrom("scheduled_task_grants")
|
|
365
|
+
.where("task_id", "=", taskId)
|
|
366
|
+
.where("tool_key", "=", toolKey)
|
|
367
|
+
.executeTakeFirst();
|
|
368
|
+
return Number(r.numDeletedRows) > 0;
|
|
369
|
+
}
|
|
370
|
+
};
|
|
371
|
+
ScheduledTaskStore = __decorate([
|
|
372
|
+
Injectable()
|
|
373
|
+
], ScheduledTaskStore);
|
|
374
|
+
export { ScheduledTaskStore };
|
|
375
|
+
/**
|
|
376
|
+
* Whether the task holds a grant for this tool as defined now: same key, same spec hash, same
|
|
377
|
+
* connector (null for plugin and builtin tools). A grant of an older definition does not count.
|
|
378
|
+
* A plain function too, for the tool policy (`createDecidePolicy`), which is not a provider.
|
|
379
|
+
*/
|
|
380
|
+
export async function findTaskGrant(t, taskId, toolKey, specHash, connectorId) {
|
|
381
|
+
const row = await t
|
|
382
|
+
.selectFrom("scheduled_task_grants")
|
|
383
|
+
.select("tool_key")
|
|
384
|
+
.where("task_id", "=", taskId)
|
|
385
|
+
.where("tool_key", "=", toolKey)
|
|
386
|
+
.where("spec_hash", "=", specHash)
|
|
387
|
+
.where(sql `connector_id IS NOT DISTINCT FROM ${connectorId}`)
|
|
388
|
+
.executeTakeFirst();
|
|
389
|
+
return row !== undefined;
|
|
390
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { Module } from "@nestjs/common";
|
|
8
|
+
import { ScheduledTaskStore } from "./store.js";
|
|
9
|
+
/**
|
|
10
|
+
* The scheduled task store alone, so the scanner (worker), the fire job, the HTTP API and the
|
|
11
|
+
* schedule tools can each import it without importing one another.
|
|
12
|
+
*/
|
|
13
|
+
let ScheduledTaskStoreModule = class ScheduledTaskStoreModule {
|
|
14
|
+
};
|
|
15
|
+
ScheduledTaskStoreModule = __decorate([
|
|
16
|
+
Module({
|
|
17
|
+
providers: [ScheduledTaskStore],
|
|
18
|
+
exports: [ScheduledTaskStore],
|
|
19
|
+
})
|
|
20
|
+
], ScheduledTaskStoreModule);
|
|
21
|
+
export { ScheduledTaskStoreModule };
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import type { ModelRef } from "../agents/definition.js";
|
|
2
|
+
/**
|
|
3
|
+
* Scheduled tasks (spec 2026-11-11-scheduled-tasks-design.md §4): the shapes the kernel reads and
|
|
4
|
+
* writes. The rows live in `capybara.scheduled_tasks`, `scheduled_task_runs` and
|
|
5
|
+
* `scheduled_task_grants` (migration 0113).
|
|
6
|
+
*/
|
|
7
|
+
/** When a task fires: a 5-field cron, or once at a local date-time, both in an IANA zone (§5). */
|
|
8
|
+
export type ScheduleTrigger = {
|
|
9
|
+
kind: "cron";
|
|
10
|
+
expr: string;
|
|
11
|
+
timeZone: string;
|
|
12
|
+
} | {
|
|
13
|
+
kind: "once";
|
|
14
|
+
at: string;
|
|
15
|
+
timeZone: string;
|
|
16
|
+
};
|
|
17
|
+
/** Where a run posts: a new conversation, one existing conversation, or an IM chat (§3). */
|
|
18
|
+
export type ScheduleMode = "new" | "conversation" | "chat";
|
|
19
|
+
/** The IM chat a `chat`-mode task posts into. */
|
|
20
|
+
export interface ScheduleChat {
|
|
21
|
+
connectionId: string;
|
|
22
|
+
chatId: string;
|
|
23
|
+
chatType: "dm" | "group";
|
|
24
|
+
}
|
|
25
|
+
export type ScheduleStatus = "active" | "paused" | "ended";
|
|
26
|
+
export type SchedulePauseReason = "creator" | "admin" | "failures" | "creator_inactive" | "agent_gone" | "target_gone" | "conversation_gone" | "org_disabled" | "expired"
|
|
27
|
+
/** The stored trigger cannot be evaluated (the scanner stops selecting the task). */
|
|
28
|
+
| "invalid_schedule";
|
|
29
|
+
export type TaskRunStatus = "pending" | "running" | "completed" | "failed" | "skipped";
|
|
30
|
+
export type TaskRunSkipReason = "missed" | "overlap" | "rate_limited" | "queue_paused" | "removed" | "device_offline" | "creator_inactive" | "agent_gone" | "target_gone" | "conversation_gone" | "org_disabled"
|
|
31
|
+
/** A group chat on a channel without threads (a group run needs its own thread). */
|
|
32
|
+
| "unsupported_target"
|
|
33
|
+
/** The task was deleted after the run was recorded. */
|
|
34
|
+
| "task_deleted"
|
|
35
|
+
/** The task was paused after the scan recorded the tick (a "run now" still runs). */
|
|
36
|
+
| "task_paused";
|
|
37
|
+
/** A task as the kernel reads it: the columns of `capybara.scheduled_tasks`, camel-cased. */
|
|
38
|
+
export interface ScheduledTask {
|
|
39
|
+
id: string;
|
|
40
|
+
orgId: string;
|
|
41
|
+
/** The creator: every run acts as this account. */
|
|
42
|
+
accountId: string;
|
|
43
|
+
agentId: string;
|
|
44
|
+
name: string;
|
|
45
|
+
prompt: string;
|
|
46
|
+
trigger: ScheduleTrigger;
|
|
47
|
+
mode: ScheduleMode;
|
|
48
|
+
/** The target conversation (`conversation` mode only). */
|
|
49
|
+
conversationId: string | null;
|
|
50
|
+
/** The target chat (`chat` mode only). */
|
|
51
|
+
chat: ScheduleChat | null;
|
|
52
|
+
/** Null = the agent's default model. */
|
|
53
|
+
model: ModelRef | null;
|
|
54
|
+
/** Null = the agent's default effort. */
|
|
55
|
+
effort: string | null;
|
|
56
|
+
/** Null = the default pick for new conversations. */
|
|
57
|
+
deviceId: string | null;
|
|
58
|
+
status: ScheduleStatus;
|
|
59
|
+
pauseReason: SchedulePauseReason | null;
|
|
60
|
+
/** The account that paused the task (creator or admin); null when not paused by a person. */
|
|
61
|
+
pausedBy: string | null;
|
|
62
|
+
/** The next fire time, jitter included; null when the task is not active. */
|
|
63
|
+
nextRunAt: Date | null;
|
|
64
|
+
jitterSeconds: number;
|
|
65
|
+
expiresAt: Date | null;
|
|
66
|
+
consecutiveFailures: number;
|
|
67
|
+
createdAt: Date;
|
|
68
|
+
updatedAt: Date;
|
|
69
|
+
}
|
|
70
|
+
/** One tick of a task (or a trial run): the columns of `capybara.scheduled_task_runs`. */
|
|
71
|
+
export interface TaskRun {
|
|
72
|
+
id: string;
|
|
73
|
+
taskId: string;
|
|
74
|
+
orgId: string;
|
|
75
|
+
/** The tick, before jitter (for a trial run: when it was requested). */
|
|
76
|
+
scheduledFor: Date;
|
|
77
|
+
firedAt: Date | null;
|
|
78
|
+
trial: boolean;
|
|
79
|
+
/** A person's "run now" (trial or not), outside the schedule. */
|
|
80
|
+
manual: boolean;
|
|
81
|
+
conversationId: string | null;
|
|
82
|
+
runId: string | null;
|
|
83
|
+
status: TaskRunStatus;
|
|
84
|
+
skipReason: TaskRunSkipReason | null;
|
|
85
|
+
error: string | null;
|
|
86
|
+
/** Tool keys refused for lack of a grant (§7). */
|
|
87
|
+
missingGrants: string[];
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* The marker a task's message carries (`conversation_queue.schedule`, then `user_message`): not
|
|
91
|
+
* model-visible as such; `taskName` and `localTime` feed the English header the model sees.
|
|
92
|
+
*/
|
|
93
|
+
export interface ScheduleMarker {
|
|
94
|
+
taskId: string;
|
|
95
|
+
taskRunId: string;
|
|
96
|
+
/** ISO timestamp of the tick. */
|
|
97
|
+
scheduledFor: string;
|
|
98
|
+
trial: boolean;
|
|
99
|
+
taskName: string;
|
|
100
|
+
/** The tick in the task's zone, as the header shows it. */
|
|
101
|
+
localTime: string;
|
|
102
|
+
}
|
|
103
|
+
/** A remembered "always allow" of a task (same meaning as `conversation_tool_grants`). */
|
|
104
|
+
export interface ScheduledTaskGrant {
|
|
105
|
+
toolKey: string;
|
|
106
|
+
specHash: string;
|
|
107
|
+
connectorId: string | null;
|
|
108
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import type { KernelSchemaDb } from "../db/kernel-schema.js";
|
|
2
|
+
import type { KernelConfigService } from "../infra/config/kernel-config.service.js";
|
|
3
|
+
/**
|
|
4
|
+
* The scheduled task run a kernel run serves (scheduled tasks spec §4, §7), or null for an attended
|
|
5
|
+
* run: `runs.scheduled_task_run_id`, set on the run a task's message triggered and inherited by the
|
|
6
|
+
* runs descending from it without a person (sub-agent runs, wake runs). A run whose task run row is
|
|
7
|
+
* gone is treated as attended.
|
|
8
|
+
*/
|
|
9
|
+
export declare function unattendedTaskRunOf(db: KernelSchemaDb, runId: string): Promise<{
|
|
10
|
+
taskRunId: string;
|
|
11
|
+
taskId: string;
|
|
12
|
+
trial: boolean;
|
|
13
|
+
} | null>;
|
|
14
|
+
/**
|
|
15
|
+
* The `scheduled_task_run_id` a new run whose boundary (`runs.trigger_seq`) is event `seq` of
|
|
16
|
+
* `conversationId` gets (scheduled tasks spec §4), read in the caller's transaction:
|
|
17
|
+
* - a `user_message`: its schedule marker's task run; a sub-agent's task or `SendMessage` message
|
|
18
|
+
* (`dispatch`): what its parent run has; a person's message: null;
|
|
19
|
+
* - a `background_task_finished`: what the run that launched the task has;
|
|
20
|
+
* - a `subagent_delivery`: what the child run that delivered it has (it inherited from its parent);
|
|
21
|
+
* - anything else, or no such event: null.
|
|
22
|
+
*/
|
|
23
|
+
export declare function scheduledTaskRunAt(t: KernelSchemaDb, conversationId: string, seq: number | string): Promise<string | null>;
|
|
24
|
+
/** The tool result of an ask outside the task's grants in an unattended run, `fail` mode (§7). */
|
|
25
|
+
export declare const UNATTENDED_ASK_ERROR: (tool: string) => string;
|
|
26
|
+
/**
|
|
27
|
+
* The Platform operations that change an agent's skills: an unattended run never calls them
|
|
28
|
+
* without a person (spec §7), even where a private agent's owner would not be asked. Each is a
|
|
29
|
+
* fixed ask there, outside every grant.
|
|
30
|
+
*/
|
|
31
|
+
export declare const UNATTENDED_SKILL_OPERATIONS: ReadonlySet<string>;
|
|
32
|
+
/** Whether a call's policy key (`Platform:<operation>`) is one of {@link UNATTENDED_SKILL_OPERATIONS}. */
|
|
33
|
+
export declare function changesAgentSkills(policyKey: string): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* The result of a fixed ask (R3, `requiresUserInteraction`, a skill change unattended, a per-call
|
|
36
|
+
* policy that never remembers) in an unattended run, `fail` mode: no grant can ever cover it, so
|
|
37
|
+
* it is not a missing grant either.
|
|
38
|
+
*/
|
|
39
|
+
export declare const UNATTENDED_FIXED_ASK_ERROR: (tool: string) => string;
|
|
40
|
+
/** The result of `AskUserQuestion` (or any other input request) in an unattended run, `fail` mode. */
|
|
41
|
+
export declare const UNATTENDED_QUESTION_ERROR = "No one is present in this scheduled run; decide with the information you have, or state the open question in your final answer.";
|
|
42
|
+
/** The result of a call that needs the creator's personal connection, unattended, `fail` mode. */
|
|
43
|
+
export declare const UNATTENDED_CONNECTION_ERROR: (connector: string) => string;
|
|
44
|
+
/** The note on a connector call whose elicitation was declined in an unattended run (`fail`). */
|
|
45
|
+
export declare const UNATTENDED_ELICITATION_NOTE = "[The app asked for user input, but no one is present in this scheduled run, so the request was declined. Decide with the information you have, or state the open question in your final answer.]";
|
|
46
|
+
/** The `missing_grants` entry of a personal connector the creator has not connected (§7). */
|
|
47
|
+
export declare const connectionGrantKey: (connectorSlug: string) => string;
|
|
48
|
+
/** The `missing_grants` entry of a refused network host (network ask-to-allow spec §8.1, §8.3). */
|
|
49
|
+
export declare const networkGrantKey: (host: string) => string;
|
|
50
|
+
/**
|
|
51
|
+
* What the tool policy knows of the scheduled task run a kernel run serves (`PolicyContext`): the
|
|
52
|
+
* task (its grants), the task run (its `missing_grants`), whether it is a trial run (attended), and
|
|
53
|
+
* the org's `unattendedAsk` and `forbiddenTools`, read live.
|
|
54
|
+
*/
|
|
55
|
+
export interface UnattendedRun {
|
|
56
|
+
taskId: string;
|
|
57
|
+
taskRunId: string;
|
|
58
|
+
trial: boolean;
|
|
59
|
+
unattendedAsk: "fail" | "wait";
|
|
60
|
+
forbiddenTools: string[];
|
|
61
|
+
}
|
|
62
|
+
/** An unattended run that is not a trial run: the §7 rules apply. */
|
|
63
|
+
export declare const unattendedRules: (u: UnattendedRun | null | undefined) => u is UnattendedRun;
|
|
64
|
+
/** In `fail` mode, an unattended run never waits for a person (§7). */
|
|
65
|
+
export declare const unattendedFails: (u: UnattendedRun | null | undefined) => boolean;
|
|
66
|
+
/**
|
|
67
|
+
* The scheduled task context of a run's tool calls (`PolicyContext.unattended`), or null when the
|
|
68
|
+
* run is attended: it serves no task run, or a person's message joined it ({@link personJoined}).
|
|
69
|
+
* A trial run is returned with `trial: true` (attended; its approvals become task grants).
|
|
70
|
+
*/
|
|
71
|
+
export declare function unattendedRunOf(db: KernelSchemaDb, config: Pick<KernelConfigService, "get">, orgId: string, runId: string): Promise<UnattendedRun | null>;
|
|
72
|
+
/**
|
|
73
|
+
* The scheduled task whose grants a run's actions use (spec §7; network ask-to-allow spec §8.1),
|
|
74
|
+
* or null: the run serves a task run that is no trial run and no person joined
|
|
75
|
+
* ({@link personJoined}): the same rule as {@link unattendedRules} on {@link unattendedRunOf},
|
|
76
|
+
* without the org's settings. `accountId`: the task's creator; `orgId`: the task's org.
|
|
77
|
+
*/
|
|
78
|
+
export declare function taskGrantsRunOf(db: KernelSchemaDb, runId: string): Promise<{
|
|
79
|
+
taskId: string;
|
|
80
|
+
accountId: string;
|
|
81
|
+
orgId: string;
|
|
82
|
+
} | null>;
|
|
83
|
+
/**
|
|
84
|
+
* Appends a key to a task run's `missing_grants` (a tool key, or `connection:<slug>`), once: one
|
|
85
|
+
* atomic update, so parallel calls of a run and of its sub-agents never lose or repeat a key.
|
|
86
|
+
*/
|
|
87
|
+
export declare function appendMissingGrant(db: KernelSchemaDb, taskRunId: string, key: string): Promise<void>;
|
|
88
|
+
/**
|
|
89
|
+
* The task grant that lets an unattended run use the open sandbox tier (sandbox dev tiers spec
|
|
90
|
+
* §11.4): without it a run of a scheduled task is capped at `dev` on a local device, and refused
|
|
91
|
+
* on an unsandboxed local device or a cloud device whose tier is open.
|
|
92
|
+
*/
|
|
93
|
+
export declare const TIER_OPEN_GRANT_KEY = "tier:open";
|
|
94
|
+
/** The `spec_hash` the `tier:open` grant is stored with (no tool definition behind it). */
|
|
95
|
+
export declare const TIER_GRANT_SPEC_HASH = "tier";
|
|
96
|
+
/**
|
|
97
|
+
* The tier rule of an unattended run on `deviceId` (spec §11.4), or null when the run is attended
|
|
98
|
+
* (no task run, a trial run, or a person joined: the same rule as {@link taskGrantsRunOf}).
|
|
99
|
+
* `openGranted`: the task holds the `tier:open` grant and `deviceId` is a live device of the task's
|
|
100
|
+
* org owned by its creator (a creator approves for their own devices only, as with network
|
|
101
|
+
* grants). A deleted task grants nothing.
|
|
102
|
+
*/
|
|
103
|
+
export declare function unattendedTierOf(db: KernelSchemaDb, runId: string, deviceId: string): Promise<{
|
|
104
|
+
taskRunId: string;
|
|
105
|
+
taskId: string;
|
|
106
|
+
openGranted: boolean;
|
|
107
|
+
} | null>;
|
|
108
|
+
/**
|
|
109
|
+
* The tool error of a scheduled run on a device whose tier is open (cloud) without the task's
|
|
110
|
+
* `tier:open` grant (spec §11.4).
|
|
111
|
+
*/
|
|
112
|
+
export declare const UNATTENDED_OPEN_TIER_ERROR = "This device's sandbox level is open, which a scheduled run may use only when its task allows the open sandbox level; the task's owner can add tier:open to the task's approved tools, or lower the device's sandbox level.";
|
|
113
|
+
/**
|
|
114
|
+
* The tool error of a scheduled run on a device that runs commands without a sandbox, without
|
|
115
|
+
* the task's `tier:open` grant (spec §11.4).
|
|
116
|
+
*/
|
|
117
|
+
export declare const UNATTENDED_UNSANDBOXED_ERROR = "This device runs commands without a sandbox, which a scheduled run may use only when its task allows the open sandbox level; the task's owner can add tier:open to the task's approved tools, or the device's owner can turn the sandbox back on with `capybara-device policy set isolation sandbox`.";
|