@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
|
@@ -9,7 +9,6 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
9
9
|
};
|
|
10
10
|
import { randomUUID } from "node:crypto";
|
|
11
11
|
import { CHANNEL_EXTENSION_POINT } from "@capybara-hq/plugin-sdk";
|
|
12
|
-
import { getQueueToken } from "@nestjs/bullmq";
|
|
13
12
|
import { Inject, Injectable } from "@nestjs/common";
|
|
14
13
|
import { AgentLookup } from "../agents/agent-lookup.js";
|
|
15
14
|
import { ConversationAccess } from "../conversations/access.js";
|
|
@@ -18,24 +17,24 @@ import { ApiError } from "../errors.js";
|
|
|
18
17
|
import { ExtensionRegistry } from "../extensions/registry.js";
|
|
19
18
|
import { audit } from "../identity/audit.js";
|
|
20
19
|
import { KernelConfigService } from "../infra/config/kernel-config.service.js";
|
|
21
|
-
import { afterCommit } from "../infra/database/after-commit.js";
|
|
22
20
|
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
23
21
|
import { TransactionHost } from "../infra/database/transaction-host.js";
|
|
24
22
|
import { Transactional } from "../infra/database/transactional.decorator.js";
|
|
23
|
+
import { OutboxService } from "../infra/outbox/outbox.service.js";
|
|
25
24
|
import { KERNEL_LOGGER } from "../infra/tokens.js";
|
|
26
25
|
import { DevicePolicyService } from "../local-devices/device-policy.service.js";
|
|
27
26
|
import { orgAllows } from "../local-devices/network-grants.js";
|
|
28
27
|
import { OrgLock } from "../orgs/org-lock.js";
|
|
29
28
|
import { can, roleAtLeast } from "../orgs/roles.js";
|
|
30
|
-
import { MAINTENANCE_QUEUE_NAME } from "../runtime/maintenance-queue.js";
|
|
31
29
|
import { ProviderRegistry } from "../runtime/providers.js";
|
|
32
30
|
import { SandboxService } from "../sandbox/sandbox.service.js";
|
|
33
31
|
import { isTimeZone } from "../time-zone.js";
|
|
34
32
|
import { ToolRegistry } from "../tools/registry.js";
|
|
33
|
+
import { assembleCalendar, CALENDAR_LIMITS, CALENDAR_RANGE_DAYS, CALENDAR_TASK_RANGE_DAYS, calendarRunReadLimit, } from "./calendar.js";
|
|
35
34
|
import { readScheduleSettings } from "./effective-settings.js";
|
|
36
35
|
import { grantNotAllowed, scheduleDisabled, scheduleForbidden, scheduleNotFound, targetInvalid, } from "./errors.js";
|
|
37
36
|
import { grantRefusal, grantRefusalOf, isNetworkGrantKey, isPolicyGrantKey, isTierGrantKey, NETWORK_GRANT_PREFIX, NETWORK_GRANT_SPEC_HASH, networkGrantHost, networkGrantRefusal, TIER_GRANT_SPEC_HASH, tierGrantRefusal, } from "./grant-rules.js";
|
|
38
|
-
import {
|
|
37
|
+
import { oweSchedFire, oweSchedSettleUnfired } from "./job-ids.js";
|
|
39
38
|
import { pauseTaskIn } from "./pause.js";
|
|
40
39
|
import { jitterForGap, minGapMinutes, nextTick, validateTrigger } from "./schedule-math.js";
|
|
41
40
|
import { ScheduledTaskStore } from "./store.js";
|
|
@@ -74,14 +73,14 @@ let ScheduledTasksService = class ScheduledTasksService {
|
|
|
74
73
|
extensions;
|
|
75
74
|
providers;
|
|
76
75
|
log;
|
|
77
|
-
|
|
76
|
+
outbox;
|
|
78
77
|
sandbox;
|
|
79
78
|
devicePolicy;
|
|
80
79
|
constructor(db, txHost, config, store, orgLock, agents, access, tools, extensions,
|
|
81
80
|
/** A task's model must resolve for the org and declare its effort (as a message's switch). */
|
|
82
81
|
providers, log,
|
|
83
|
-
/** "Run now"
|
|
84
|
-
|
|
82
|
+
/** "Run now" owes the fire job (consumed by the worker role). */
|
|
83
|
+
outbox,
|
|
85
84
|
/** Network grants: the org's effective egress (network ask-to-allow spec §8.1). */
|
|
86
85
|
sandbox,
|
|
87
86
|
/** Network grants: the task's device's local policy summary (`remoteGrants`). */
|
|
@@ -97,7 +96,7 @@ let ScheduledTasksService = class ScheduledTasksService {
|
|
|
97
96
|
this.extensions = extensions;
|
|
98
97
|
this.providers = providers;
|
|
99
98
|
this.log = log;
|
|
100
|
-
this.
|
|
99
|
+
this.outbox = outbox;
|
|
101
100
|
this.sandbox = sandbox;
|
|
102
101
|
this.devicePolicy = devicePolicy;
|
|
103
102
|
}
|
|
@@ -363,6 +362,58 @@ let ScheduledTasksService = class ScheduledTasksService {
|
|
|
363
362
|
}
|
|
364
363
|
return this.withLastRuns(tasks);
|
|
365
364
|
}
|
|
365
|
+
/**
|
|
366
|
+
* The calendar between two instants (calendar spec §5): the runs and planned occurrences of the
|
|
367
|
+
* actor's own tasks, or with `all` (org admins only, else `forbidden`) every task of the org; with
|
|
368
|
+
* `taskId` only that task (one the actor may see, else `schedule.not_found`), never collapsed.
|
|
369
|
+
* Another creator's runs come without `conversationId`, `error` and `missingGrants` (§15 Q3).
|
|
370
|
+
* A range longer than 43 days (2 with `taskId`), or not forward, is `validation_failed`. `now`
|
|
371
|
+
* is for tests.
|
|
372
|
+
*/
|
|
373
|
+
async calendar(orgId, actor, q, now = new Date(), limits = CALENDAR_LIMITS) {
|
|
374
|
+
const role = await this.liveRole(orgId, actor.accountId);
|
|
375
|
+
const manage = can(role, "schedules.manage");
|
|
376
|
+
if (q.all === true && !manage) {
|
|
377
|
+
throw new ApiError("forbidden", "Only org admins can read every scheduled task");
|
|
378
|
+
}
|
|
379
|
+
const span = q.to.getTime() - q.from.getTime();
|
|
380
|
+
const maxDays = q.taskId === undefined ? CALENDAR_RANGE_DAYS : CALENDAR_TASK_RANGE_DAYS;
|
|
381
|
+
if (!(span > 0))
|
|
382
|
+
throw new ApiError("validation_failed", "from must be before to");
|
|
383
|
+
if (span > maxDays * DAY_MS) {
|
|
384
|
+
throw new ApiError("validation_failed", `The range is at most ${maxDays} days${q.taskId === undefined ? "" : " with taskId"}`);
|
|
385
|
+
}
|
|
386
|
+
const t = this.db.db;
|
|
387
|
+
let tasks;
|
|
388
|
+
if (q.taskId !== undefined) {
|
|
389
|
+
const task = await this.store.getTask(t, orgId, q.taskId);
|
|
390
|
+
if (!task || (task.accountId !== actor.accountId && !manage))
|
|
391
|
+
throw scheduleNotFound();
|
|
392
|
+
tasks = [task];
|
|
393
|
+
}
|
|
394
|
+
else {
|
|
395
|
+
tasks =
|
|
396
|
+
q.all === true
|
|
397
|
+
? await this.store.listForOrg(t, orgId)
|
|
398
|
+
: await this.store.listForAccount(t, orgId, actor.accountId);
|
|
399
|
+
}
|
|
400
|
+
const runs = await this.store.listRunsBetween(t, orgId, tasks.map((x) => x.id), q.from, q.to,
|
|
401
|
+
// one row past the caps tells the assembly where to cut
|
|
402
|
+
calendarRunReadLimit(limits));
|
|
403
|
+
const settings = await readScheduleSettings(t, this.config, orgId);
|
|
404
|
+
return assembleCalendar({
|
|
405
|
+
tasks,
|
|
406
|
+
runs,
|
|
407
|
+
viewerAccountId: actor.accountId,
|
|
408
|
+
from: q.from,
|
|
409
|
+
to: q.to,
|
|
410
|
+
timeZone: q.timeZone,
|
|
411
|
+
now,
|
|
412
|
+
plan: settings.enabled,
|
|
413
|
+
catchUpWindowMinutes: settings.catchUpWindowMinutes,
|
|
414
|
+
collapse: q.taskId === undefined,
|
|
415
|
+
}, limits);
|
|
416
|
+
}
|
|
366
417
|
/**
|
|
367
418
|
* The tasks of `tasks` that post into the conversation: a `conversation` task naming it, or a
|
|
368
419
|
* `chat` task whose chat the conversation is a thread of (spec §10 side panel).
|
|
@@ -472,6 +523,8 @@ let ScheduledTasksService = class ScheduledTasksService {
|
|
|
472
523
|
disabledTools: d.disabledTools ?? [],
|
|
473
524
|
subagentTools: d.subagentTools,
|
|
474
525
|
subagents: d.subagents,
|
|
526
|
+
// no conversation at hand: a web one's tools; a run elsewhere still refuses by spec.sources
|
|
527
|
+
source: "web",
|
|
475
528
|
});
|
|
476
529
|
const ctx = {
|
|
477
530
|
role,
|
|
@@ -736,6 +789,8 @@ let ScheduledTasksService = class ScheduledTasksService {
|
|
|
736
789
|
disabledTools: d.disabledTools ?? [],
|
|
737
790
|
subagentTools: d.subagentTools,
|
|
738
791
|
subagents: d.subagents,
|
|
792
|
+
// no conversation at hand: a web one's tools; a run elsewhere still refuses by spec.sources
|
|
793
|
+
source: "web",
|
|
739
794
|
});
|
|
740
795
|
return new Map(tools.map((x) => [
|
|
741
796
|
x.key,
|
|
@@ -767,7 +822,7 @@ let ScheduledTasksService = class ScheduledTasksService {
|
|
|
767
822
|
/**
|
|
768
823
|
* "Run now" (spec §6), creator only: a task run for the request time, outside the schedule (no
|
|
769
824
|
* unique-key conflict with a tick, and `next_run_at` does not move), fired at once through the
|
|
770
|
-
* fire job
|
|
825
|
+
* fire job its transaction owes. `trial`: an attended trial run whose approvals become the task's
|
|
771
826
|
* grants (§7). Counted in the rate limit like any run. An ended task cannot run; a paused one
|
|
772
827
|
* can (only its creator gets here: the run is `manual`, which the fire's paused check lets by).
|
|
773
828
|
*/
|
|
@@ -797,10 +852,9 @@ let ScheduledTasksService = class ScheduledTasksService {
|
|
|
797
852
|
target: task.id,
|
|
798
853
|
detail: { taskRunId: run.id, trial: opts.trial },
|
|
799
854
|
});
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
});
|
|
855
|
+
await oweSchedFire(this.outbox, run.id, orgId);
|
|
856
|
+
// a fire job that fails for good before its claim leaves the run to this check (`removed`)
|
|
857
|
+
await oweSchedSettleUnfired(this.outbox, run.id, orgId, run.scheduledFor, null);
|
|
804
858
|
return run;
|
|
805
859
|
}
|
|
806
860
|
/** The live role of a member of the org; not a member → `schedule.not_found`. */
|
|
@@ -1030,6 +1084,8 @@ let ScheduledTasksService = class ScheduledTasksService {
|
|
|
1030
1084
|
disabledTools: d.disabledTools ?? [],
|
|
1031
1085
|
subagentTools: d.subagentTools,
|
|
1032
1086
|
subagents: d.subagents,
|
|
1087
|
+
// no conversation at hand: a web one's tools; a run elsewhere still refuses by spec.sources
|
|
1088
|
+
source: "web",
|
|
1033
1089
|
});
|
|
1034
1090
|
for (const g of toolGrants) {
|
|
1035
1091
|
const tool = tools.find((x) => x.key === g.toolKey);
|
|
@@ -1115,7 +1171,7 @@ ScheduledTasksService = __decorate([
|
|
|
1115
1171
|
__param(8, Inject(ExtensionRegistry)),
|
|
1116
1172
|
__param(9, Inject(ProviderRegistry)),
|
|
1117
1173
|
__param(10, Inject(KERNEL_LOGGER)),
|
|
1118
|
-
__param(11, Inject(
|
|
1174
|
+
__param(11, Inject(OutboxService)),
|
|
1119
1175
|
__param(12, Inject(SandboxService)),
|
|
1120
1176
|
__param(13, Inject(DevicePolicyService))
|
|
1121
1177
|
], ScheduledTasksService);
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { z } from "zod";
|
|
2
2
|
import { type Principal } from "../identity/principal.js";
|
|
3
3
|
import { type OrgContext } from "../orgs/org.guard.js";
|
|
4
|
+
import type { CalendarAnswer } from "./calendar.js";
|
|
4
5
|
import { type ChatTarget, type GrantableTool, type ScheduledTaskGrantView, type ScheduledTaskListItem, ScheduledTasksService } from "./scheduled-tasks.service.js";
|
|
5
|
-
import { type ScheduleChatTargetsQuery, type ScheduleCreateBody, type ScheduleGrantableQuery, type ScheduleGrantParams, type ScheduleGrantsBody, type ScheduleListQuery, type ScheduleParams, type ScheduleRunBody, type ScheduleRunsQuery, type ScheduleUpdateBody } from "./schedules.schemas.js";
|
|
6
|
+
import { type ScheduleCalendarQuery, type ScheduleChatTargetsQuery, type ScheduleCreateBody, type ScheduleGrantableQuery, type ScheduleGrantParams, type ScheduleGrantsBody, type ScheduleListQuery, type ScheduleParams, type ScheduleRunBody, type ScheduleRunsQuery, type ScheduleUpdateBody } from "./schedules.schemas.js";
|
|
6
7
|
import type { ScheduledTask, ScheduledTaskGrant, TaskRun } from "./types.js";
|
|
7
8
|
/**
|
|
8
9
|
* Scheduled tasks (`/api/v1/orgs/:orgId/schedules`, spec 2026-11-11-scheduled-tasks §10); human
|
|
@@ -10,6 +11,8 @@ import type { ScheduledTask, ScheduledTaskGrant, TaskRun } from "./types.js";
|
|
|
10
11
|
* - `GET /` → `{ items }`: the caller's own tasks, each with its `lastRun`; `?all=true` every task
|
|
11
12
|
* of the org (org admins, `schedules.manage`, enforced by the service: 403 `forbidden`
|
|
12
13
|
* otherwise); `?conversationId=` only those posting into that conversation;
|
|
14
|
+
* - `GET /calendar?from&to&timeZone[&all][&taskId]` → the calendar (runs, planned occurrences,
|
|
15
|
+
* collapsed task-days; calendar spec §5.1), `org.read` like the list, `all` as the list's;
|
|
13
16
|
* - `GET /chat-targets` → `{ items }`: the chats the caller can point a `chat` task at;
|
|
14
17
|
* - `GET /grantable-tools?agentId=` → `{ items }`: the agent's tools, each grantable or why not;
|
|
15
18
|
* - `POST /` → 201 `{ task }` (`timeZone` is the browser zone, a fallback only);
|
|
@@ -30,6 +33,7 @@ export declare class SchedulesController {
|
|
|
30
33
|
list(principal: Principal, org: OrgContext, q: z.infer<typeof ScheduleListQuery>): Promise<{
|
|
31
34
|
items: ScheduledTaskListItem[];
|
|
32
35
|
}>;
|
|
36
|
+
calendar(principal: Principal, org: OrgContext, q: z.infer<typeof ScheduleCalendarQuery>): Promise<CalendarAnswer>;
|
|
33
37
|
chatTargets(principal: Principal, org: OrgContext, _q: z.infer<typeof ScheduleChatTargetsQuery>): Promise<{
|
|
34
38
|
items: ChatTarget[];
|
|
35
39
|
}>;
|
|
@@ -12,13 +12,15 @@ import { CurrentPrincipal, requireUser } from "../identity/principal.js";
|
|
|
12
12
|
import { ZBody, ZParam, ZQuery } from "../infra/validation/zod-params.js";
|
|
13
13
|
import { CurrentOrg, OrgAction } from "../orgs/org.guard.js";
|
|
14
14
|
import { ScheduledTasksService, } from "./scheduled-tasks.service.js";
|
|
15
|
-
import { createInputOf, grantsOf, ScheduleChatTargetsQueryDto, ScheduleCreateBodyDto, ScheduleGrantableQueryDto, ScheduleGrantParamsDto, ScheduleGrantsBodyDto, ScheduleListQueryDto, ScheduleParamsDto, ScheduleRunBodyDto, ScheduleRunsQueryDto, ScheduleUpdateBodyDto, updateInputOf, } from "./schedules.schemas.js";
|
|
15
|
+
import { calendarInputOf, createInputOf, grantsOf, ScheduleCalendarQueryDto, ScheduleChatTargetsQueryDto, ScheduleCreateBodyDto, ScheduleGrantableQueryDto, ScheduleGrantParamsDto, ScheduleGrantsBodyDto, ScheduleListQueryDto, ScheduleParamsDto, ScheduleRunBodyDto, ScheduleRunsQueryDto, ScheduleUpdateBodyDto, updateInputOf, } from "./schedules.schemas.js";
|
|
16
16
|
/**
|
|
17
17
|
* Scheduled tasks (`/api/v1/orgs/:orgId/schedules`, spec 2026-11-11-scheduled-tasks §10); human
|
|
18
18
|
* users only (a service token gets 403).
|
|
19
19
|
* - `GET /` → `{ items }`: the caller's own tasks, each with its `lastRun`; `?all=true` every task
|
|
20
20
|
* of the org (org admins, `schedules.manage`, enforced by the service: 403 `forbidden`
|
|
21
21
|
* otherwise); `?conversationId=` only those posting into that conversation;
|
|
22
|
+
* - `GET /calendar?from&to&timeZone[&all][&taskId]` → the calendar (runs, planned occurrences,
|
|
23
|
+
* collapsed task-days; calendar spec §5.1), `org.read` like the list, `all` as the list's;
|
|
22
24
|
* - `GET /chat-targets` → `{ items }`: the chats the caller can point a `chat` task at;
|
|
23
25
|
* - `GET /grantable-tools?agentId=` → `{ items }`: the agent's tools, each grantable or why not;
|
|
24
26
|
* - `POST /` → 201 `{ task }` (`timeZone` is the browser zone, a fallback only);
|
|
@@ -48,6 +50,11 @@ let SchedulesController = class SchedulesController {
|
|
|
48
50
|
});
|
|
49
51
|
return { items };
|
|
50
52
|
}
|
|
53
|
+
// declared before `:id`; org.read like the list (a creator demoted to guest still reads their own)
|
|
54
|
+
async calendar(principal, org, q) {
|
|
55
|
+
const p = requireUser(principal);
|
|
56
|
+
return this.tasks.calendar(org.orgId, { accountId: p.account.id }, calendarInputOf(q));
|
|
57
|
+
}
|
|
51
58
|
async chatTargets(principal, org, _q) {
|
|
52
59
|
const p = requireUser(principal);
|
|
53
60
|
return { items: await this.tasks.chatTargets(org.orgId, p.account.id) };
|
|
@@ -134,6 +141,13 @@ __decorate([
|
|
|
134
141
|
__param(1, CurrentOrg()),
|
|
135
142
|
__param(2, ZQuery(ScheduleListQueryDto))
|
|
136
143
|
], SchedulesController.prototype, "list", null);
|
|
144
|
+
__decorate([
|
|
145
|
+
Get("calendar"),
|
|
146
|
+
OrgAction("org.read"),
|
|
147
|
+
__param(0, CurrentPrincipal()),
|
|
148
|
+
__param(1, CurrentOrg()),
|
|
149
|
+
__param(2, ZQuery(ScheduleCalendarQueryDto))
|
|
150
|
+
], SchedulesController.prototype, "calendar", null);
|
|
137
151
|
__decorate([
|
|
138
152
|
Get("chat-targets"),
|
|
139
153
|
OrgAction("schedules.use"),
|
|
@@ -11,10 +11,8 @@ import { Inject, Module } from "@nestjs/common";
|
|
|
11
11
|
import { AgentLookupModule } from "../agents/agent-lookup.js";
|
|
12
12
|
import { ConversationAccessModule } from "../conversations/access.js";
|
|
13
13
|
import { ExtensionRegistryModule } from "../extensions/registry.js";
|
|
14
|
-
import { QueueModule } from "../infra/queue/queue.module.js";
|
|
15
14
|
import { LocalDevicesModule } from "../local-devices/local-devices.module.js";
|
|
16
15
|
import { OrgLockModule } from "../orgs/org-lock.js";
|
|
17
|
-
import { MAINTENANCE_QUEUE_NAME } from "../runtime/maintenance-queue.js";
|
|
18
16
|
import { ProvidersModule } from "../runtime/providers.js";
|
|
19
17
|
import { SandboxModule } from "../sandbox/sandbox.module.js";
|
|
20
18
|
import { ScheduleToolsPort } from "../tools/builtins/schedules.js";
|
|
@@ -53,8 +51,6 @@ SchedulesModule = __decorate([
|
|
|
53
51
|
// network grants: the org's effective egress and the task device's policy summary
|
|
54
52
|
SandboxModule,
|
|
55
53
|
LocalDevicesModule,
|
|
56
|
-
// "run now" enqueues the fire job
|
|
57
|
-
QueueModule.registerQueue(MAINTENANCE_QUEUE_NAME),
|
|
58
54
|
],
|
|
59
55
|
providers: [ScheduledTasksService],
|
|
60
56
|
exports: [ScheduledTasksService, ScheduledTaskStoreModule],
|
|
@@ -138,6 +138,21 @@ export declare const ScheduleListQuery: z.ZodObject<{
|
|
|
138
138
|
}>>;
|
|
139
139
|
conversationId: z.ZodOptional<z.ZodString>;
|
|
140
140
|
}, z.core.$strict>;
|
|
141
|
+
/**
|
|
142
|
+
* The calendar's range (`from < to`, at most 43 days, 2 with `taskId`: checked by the service),
|
|
143
|
+
* the viewer's zone (local days for the collapse and the cut), `all` (org admins) and `taskId`
|
|
144
|
+
* (one task, never collapsed).
|
|
145
|
+
*/
|
|
146
|
+
export declare const ScheduleCalendarQuery: z.ZodObject<{
|
|
147
|
+
from: z.ZodString;
|
|
148
|
+
to: z.ZodString;
|
|
149
|
+
timeZone: z.ZodString;
|
|
150
|
+
all: z.ZodOptional<z.ZodEnum<{
|
|
151
|
+
false: "false";
|
|
152
|
+
true: "true";
|
|
153
|
+
}>>;
|
|
154
|
+
taskId: z.ZodOptional<z.ZodString>;
|
|
155
|
+
}, z.core.$strict>;
|
|
141
156
|
export declare const ScheduleChatTargetsQuery: z.ZodObject<{}, z.core.$strict>;
|
|
142
157
|
export declare const ScheduleGrantableQuery: z.ZodObject<{
|
|
143
158
|
agentId: z.ZodString;
|
|
@@ -258,6 +273,18 @@ declare const ScheduleListQueryDto_base: import("../infra/validation/create-zod-
|
|
|
258
273
|
}, z.core.$strict>>;
|
|
259
274
|
export declare class ScheduleListQueryDto extends ScheduleListQueryDto_base {
|
|
260
275
|
}
|
|
276
|
+
declare const ScheduleCalendarQueryDto_base: import("../infra/validation/create-zod-dto.js").ZodDtoClass<z.ZodObject<{
|
|
277
|
+
from: z.ZodString;
|
|
278
|
+
to: z.ZodString;
|
|
279
|
+
timeZone: z.ZodString;
|
|
280
|
+
all: z.ZodOptional<z.ZodEnum<{
|
|
281
|
+
false: "false";
|
|
282
|
+
true: "true";
|
|
283
|
+
}>>;
|
|
284
|
+
taskId: z.ZodOptional<z.ZodString>;
|
|
285
|
+
}, z.core.$strict>>;
|
|
286
|
+
export declare class ScheduleCalendarQueryDto extends ScheduleCalendarQueryDto_base {
|
|
287
|
+
}
|
|
261
288
|
declare const ScheduleChatTargetsQueryDto_base: import("../infra/validation/create-zod-dto.js").ZodDtoClass<z.ZodObject<{}, z.core.$strict>>;
|
|
262
289
|
export declare class ScheduleChatTargetsQueryDto extends ScheduleChatTargetsQueryDto_base {
|
|
263
290
|
}
|
|
@@ -313,4 +340,12 @@ export declare function createInputOf(body: z.infer<typeof ScheduleCreateBody>):
|
|
|
313
340
|
};
|
|
314
341
|
/** A patch body as the service's input (an explicit `timeZone` changes the task's zone). */
|
|
315
342
|
export declare function updateInputOf(body: z.infer<typeof ScheduleUpdateBody>): UpdateTaskInput;
|
|
343
|
+
/** A calendar query as the service's input. */
|
|
344
|
+
export declare const calendarInputOf: (q: z.infer<typeof ScheduleCalendarQuery>) => {
|
|
345
|
+
from: Date;
|
|
346
|
+
to: Date;
|
|
347
|
+
timeZone: string;
|
|
348
|
+
all: boolean;
|
|
349
|
+
taskId?: string;
|
|
350
|
+
};
|
|
316
351
|
export {};
|
|
@@ -86,6 +86,22 @@ export const ScheduleListQuery = z
|
|
|
86
86
|
conversationId: Id.optional(),
|
|
87
87
|
})
|
|
88
88
|
.strict();
|
|
89
|
+
/** An instant with an offset (`2026-11-09T00:00:00+08:00`). */
|
|
90
|
+
const Instant = z.string().datetime({ offset: true });
|
|
91
|
+
/**
|
|
92
|
+
* The calendar's range (`from < to`, at most 43 days, 2 with `taskId`: checked by the service),
|
|
93
|
+
* the viewer's zone (local days for the collapse and the cut), `all` (org admins) and `taskId`
|
|
94
|
+
* (one task, never collapsed).
|
|
95
|
+
*/
|
|
96
|
+
export const ScheduleCalendarQuery = z
|
|
97
|
+
.object({
|
|
98
|
+
from: Instant,
|
|
99
|
+
to: Instant,
|
|
100
|
+
timeZone: IanaTimeZone,
|
|
101
|
+
all: z.enum(["true", "false"]).optional(),
|
|
102
|
+
taskId: Id.optional(),
|
|
103
|
+
})
|
|
104
|
+
.strict();
|
|
89
105
|
export const ScheduleChatTargetsQuery = z.object({}).strict();
|
|
90
106
|
export const ScheduleGrantableQuery = z.object({ agentId: Id }).strict();
|
|
91
107
|
export const ScheduleParams = z.object({ id: Id });
|
|
@@ -103,6 +119,8 @@ export class ScheduleUpdateBodyDto extends createZodDto(ScheduleUpdateBody, "Sch
|
|
|
103
119
|
}
|
|
104
120
|
export class ScheduleListQueryDto extends createZodDto(ScheduleListQuery, "ScheduleListQuery") {
|
|
105
121
|
}
|
|
122
|
+
export class ScheduleCalendarQueryDto extends createZodDto(ScheduleCalendarQuery, "ScheduleCalendarQuery") {
|
|
123
|
+
}
|
|
106
124
|
export class ScheduleChatTargetsQueryDto extends createZodDto(ScheduleChatTargetsQuery, "ScheduleChatTargetsQuery") {
|
|
107
125
|
}
|
|
108
126
|
export class ScheduleGrantableQueryDto extends createZodDto(ScheduleGrantableQuery, "ScheduleGrantableQuery") {
|
|
@@ -120,6 +138,7 @@ export class ScheduleGrantParamsDto extends createZodDto(ScheduleGrantParams, "S
|
|
|
120
138
|
/** The schedule routes the Platform operations mirror (`check:platform-ops` keys). */
|
|
121
139
|
export const SCHEDULE_ROUTES = [
|
|
122
140
|
{ route: "GET /api/v1/orgs/:orgId/schedules", query: ScheduleListQuery },
|
|
141
|
+
{ route: "GET /api/v1/orgs/:orgId/schedules/calendar", query: ScheduleCalendarQuery },
|
|
123
142
|
{ route: "GET /api/v1/orgs/:orgId/schedules/chat-targets", query: ScheduleChatTargetsQuery },
|
|
124
143
|
{ route: "GET /api/v1/orgs/:orgId/schedules/grantable-tools", query: ScheduleGrantableQuery },
|
|
125
144
|
{ route: "POST /api/v1/orgs/:orgId/schedules", body: ScheduleCreateBody },
|
|
@@ -184,3 +203,11 @@ export function updateInputOf(body) {
|
|
|
184
203
|
...(expiresAt !== undefined && { expiresAt: expiresAt === null ? null : new Date(expiresAt) }),
|
|
185
204
|
};
|
|
186
205
|
}
|
|
206
|
+
/** A calendar query as the service's input. */
|
|
207
|
+
export const calendarInputOf = (q) => ({
|
|
208
|
+
from: new Date(q.from),
|
|
209
|
+
to: new Date(q.to),
|
|
210
|
+
timeZone: q.timeZone,
|
|
211
|
+
all: q.all === "true",
|
|
212
|
+
...(q.taskId !== undefined && { taskId: q.taskId }),
|
|
213
|
+
});
|
|
@@ -68,6 +68,11 @@ export declare class ScheduledTaskStore {
|
|
|
68
68
|
countFiredSince(t: KernelSchemaDb, orgId: string, since: Date): Promise<number>;
|
|
69
69
|
/** A task's runs, latest tick first. */
|
|
70
70
|
listRuns(t: KernelSchemaDb, taskId: string, limit: number): Promise<TaskRun[]>;
|
|
71
|
+
/**
|
|
72
|
+
* The runs of these tasks of the org with `scheduled_for` in `[from, to)`, trial included, by tick, at most
|
|
73
|
+
* `limit` (the calendar; `scheduled_task_runs_task_idx` per task).
|
|
74
|
+
*/
|
|
75
|
+
listRunsBetween(t: KernelSchemaDb, orgId: string, taskIds: readonly string[], from: Date, to: Date, limit: number): Promise<TaskRun[]>;
|
|
71
76
|
listGrants(t: KernelSchemaDb, taskId: string): Promise<ScheduledTaskGrant[]>;
|
|
72
77
|
/** Adds a grant, replacing the task's grant of the same tool key. */
|
|
73
78
|
addGrant(t: KernelSchemaDb, taskId: string, grant: ScheduledTaskGrant): Promise<void>;
|
package/dist/schedules/store.js
CHANGED
|
@@ -329,6 +329,26 @@ let ScheduledTaskStore = class ScheduledTaskStore {
|
|
|
329
329
|
.execute();
|
|
330
330
|
return rows.map(toRun);
|
|
331
331
|
}
|
|
332
|
+
/**
|
|
333
|
+
* The runs of these tasks of the org with `scheduled_for` in `[from, to)`, trial included, by tick, at most
|
|
334
|
+
* `limit` (the calendar; `scheduled_task_runs_task_idx` per task).
|
|
335
|
+
*/
|
|
336
|
+
async listRunsBetween(t, orgId, taskIds, from, to, limit) {
|
|
337
|
+
if (taskIds.length === 0)
|
|
338
|
+
return [];
|
|
339
|
+
const rows = await t
|
|
340
|
+
.selectFrom("scheduled_task_runs")
|
|
341
|
+
.selectAll()
|
|
342
|
+
.where("org_id", "=", orgId)
|
|
343
|
+
.where("task_id", "in", [...taskIds])
|
|
344
|
+
.where("scheduled_for", ">=", from)
|
|
345
|
+
.where("scheduled_for", "<", to)
|
|
346
|
+
.orderBy("scheduled_for")
|
|
347
|
+
.orderBy("id")
|
|
348
|
+
.limit(limit)
|
|
349
|
+
.execute();
|
|
350
|
+
return rows.map(toRun);
|
|
351
|
+
}
|
|
332
352
|
async listGrants(t, taskId) {
|
|
333
353
|
const rows = await t
|
|
334
354
|
.selectFrom("scheduled_task_grants")
|
|
@@ -40,7 +40,7 @@ export declare class InboxController {
|
|
|
40
40
|
private readonly inbox;
|
|
41
41
|
constructor(inbox: InboxService);
|
|
42
42
|
list(principal: Principal, org: OrgContext): Promise<InboxView>;
|
|
43
|
-
/** An org admin dismisses an org notice
|
|
43
|
+
/** An org admin dismisses an org notice -> 204. */
|
|
44
44
|
dismissNotice(principal: Principal, org: OrgContext, params: z.infer<typeof NoticeParamsSchema>): Promise<void>;
|
|
45
45
|
}
|
|
46
46
|
export {};
|
|
@@ -86,7 +86,7 @@ let InboxController = class InboxController {
|
|
|
86
86
|
const p = requireUser(principal);
|
|
87
87
|
return this.inbox.list(org.orgId, p.account.id);
|
|
88
88
|
}
|
|
89
|
-
/** An org admin dismisses an org notice
|
|
89
|
+
/** An org admin dismisses an org notice -> 204. */
|
|
90
90
|
async dismissNotice(principal, org, params) {
|
|
91
91
|
const p = requireUser(principal);
|
|
92
92
|
await this.inbox.dismissNotice(org.orgId, p.account.id, params.id);
|
|
@@ -8,6 +8,7 @@ import { KernelEvents } from "../infra/events/kernel-events.js";
|
|
|
8
8
|
import { LockService } from "../infra/lock/lock.service.js";
|
|
9
9
|
import { DevicePolicyService } from "../local-devices/device-policy.service.js";
|
|
10
10
|
import { type OrgRole } from "../orgs/roles.js";
|
|
11
|
+
import { RunResume } from "../runtime/run-jobs.js";
|
|
11
12
|
import { SandboxService } from "../sandbox/sandbox.service.js";
|
|
12
13
|
import { ScheduledTaskStore } from "../schedules/store.js";
|
|
13
14
|
import type { ApprovalPolicySource } from "./pipeline.js";
|
|
@@ -206,10 +207,12 @@ export interface ToolGrantView {
|
|
|
206
207
|
* 工具调用审批:新建(loop 调用)、列出 / 查看 / 处理(HTTP),以及「以后都允许」授权的查看与撤销。
|
|
207
208
|
* 状态全部在 PG:处理决定在事务里 `SELECT … FOR UPDATE` 审批行,多副本并发处理同一审批时恰好一个生效。
|
|
208
209
|
*
|
|
209
|
-
* A decision
|
|
210
|
-
*
|
|
211
|
-
*
|
|
212
|
-
*
|
|
210
|
+
* A decision resumes its waiting run in the decision's transaction (`RunResume.resumeIn`, after the
|
|
211
|
+
* decided row: lock order approval, then run; transactional outbox spec §6). It is announced after
|
|
212
|
+
* the commit as the domain event `approval.decided` (exactly once: only the decision that changed
|
|
213
|
+
* the row from pending; no kernel subscriber: the IM card update is owed by the `approval_decided`
|
|
214
|
+
* append, transactional outbox spec §8.1). Events are appended in the context's transaction
|
|
215
|
+
* (`EventLog.appendIn`) and published after the commit.
|
|
213
216
|
*/
|
|
214
217
|
export declare class ApprovalsService {
|
|
215
218
|
private readonly db;
|
|
@@ -226,6 +229,8 @@ export declare class ApprovalsService {
|
|
|
226
229
|
readonly lockService: LockService;
|
|
227
230
|
/** A trial run's 「这次允许」 becomes a task grant only within the org's egress. */
|
|
228
231
|
private readonly sandbox;
|
|
232
|
+
/** A decision resumes its waiting run in the decision's transaction. */
|
|
233
|
+
private readonly resumes;
|
|
229
234
|
constructor(db: KernelDb, config: Pick<KernelConfigService, "get">, eventLog: Pick<EventLog, "appendIn" | "notify">, events: Pick<KernelEvents, "emit">, txHost: TransactionHost, schedules: Pick<ScheduledTaskStore, "addGrant">,
|
|
230
235
|
/** A trial approval is kept only for a tool the task may hold as a grant (its agent's tools). */
|
|
231
236
|
registry: Pick<ToolRegistry, "forAgent">,
|
|
@@ -234,7 +239,9 @@ export declare class ApprovalsService {
|
|
|
234
239
|
/** One decision of a network ask at a time, across replicas (the op is sent before the transaction). */
|
|
235
240
|
lockService: LockService,
|
|
236
241
|
/** A trial run's 「这次允许」 becomes a task grant only within the org's egress. */
|
|
237
|
-
sandbox: Pick<SandboxService, "ceilingLimits"
|
|
242
|
+
sandbox: Pick<SandboxService, "ceilingLimits">,
|
|
243
|
+
/** A decision resumes its waiting run in the decision's transaction. */
|
|
244
|
+
resumes: Pick<RunResume, "resumeIn">);
|
|
238
245
|
/**
|
|
239
246
|
* 新建 pending 审批(`expires_at` = 现在 + `tools.approvalTimeoutHours`)并写 `approval_requested`,同一事务。
|
|
240
247
|
* 按 (run_id, call_id, attempt) 幂等:已存在则返回已有记录(不覆盖),事件按 `approval_requested:<approvalId>` 幂等。
|
|
@@ -331,11 +338,22 @@ export declare class ApprovalsService {
|
|
|
331
338
|
*/
|
|
332
339
|
cancelPendingIn(runId: string): Promise<ApprovalRecord[]>;
|
|
333
340
|
/**
|
|
334
|
-
*
|
|
335
|
-
*
|
|
336
|
-
*
|
|
341
|
+
* The conversations of `orgId` holding a pending approval `accountId` is asked to decide
|
|
342
|
+
* (`requested_for`), read without locks: offboarding locks them, by tree root first
|
|
343
|
+
* (`lockConversationTrees`), before {@link cancelPendingFor}.
|
|
337
344
|
*/
|
|
338
|
-
|
|
345
|
+
pendingConversationsFor(orgId: string, accountId: string): Promise<string[]>;
|
|
346
|
+
/**
|
|
347
|
+
* In the caller's transaction (`mandatory`; offboarding): cancels every pending approval of
|
|
348
|
+
* `orgId` that `accountId` is asked to decide (`requested_for`) in `conversationIds`, the
|
|
349
|
+
* conversations the caller already locked (by tree root first, `lockConversationTrees`; lock
|
|
350
|
+
* order: conversations, then approval rows), along the same path as {@link cancelPendingIn}:
|
|
351
|
+
* `cancelled`, `approval_decided{cancelled}` with no decider. An approval asked meanwhile in
|
|
352
|
+
* another conversation is left to its run's stop, so no conversation is locked after a row.
|
|
353
|
+
* Returns the cancelled records and the highest seq written per conversation; the caller
|
|
354
|
+
* publishes after the commit.
|
|
355
|
+
*/
|
|
356
|
+
cancelPendingFor(orgId: string, accountId: string, conversationIds: readonly string[]): Promise<{
|
|
339
357
|
records: ApprovalRecord[];
|
|
340
358
|
seqs: Map<string, number>;
|
|
341
359
|
}>;
|
|
@@ -346,13 +364,25 @@ export declare class ApprovalsService {
|
|
|
346
364
|
* active runs `authorAccountId` started, in the conversation and in its sub-agents'
|
|
347
365
|
* conversations at any depth (their asks are shown in the root). Each becomes `skipped` with
|
|
348
366
|
* `approval_decided{skipped}` by the author; access stays blocked. Returns the skipped records and
|
|
349
|
-
* the highest seq written per conversation; the caller
|
|
350
|
-
*
|
|
367
|
+
* the highest seq written per conversation; the caller resumes their waiting runs in this
|
|
368
|
+
* transaction once every skipped row is locked (`ConversationsService.skipWaitsIn`), and notifies
|
|
369
|
+
* and emits the domain event `approval.decided{skipped}` after the commit (its IM card update is
|
|
370
|
+
* owed by the append, transactional outbox spec §8.1).
|
|
351
371
|
*/
|
|
352
372
|
skipNetworkIn(conversationId: string, authorAccountId: string): Promise<{
|
|
353
373
|
records: ApprovalRecord[];
|
|
354
374
|
seqs: Map<string, number>;
|
|
355
375
|
}>;
|
|
376
|
+
/**
|
|
377
|
+
* Locks the conversation row of approval `id` (`SELECT … FOR UPDATE`; re-entrant with the lock
|
|
378
|
+
* `EventLog.appendIn` takes later). Every write to an approval row takes its conversation's lock
|
|
379
|
+
* first, then the approval row, then the run row, as the stop of a waiting run
|
|
380
|
+
* (`Waits.abortWaitingIn`) and the questions do, so no two of them can deadlock. False: no such
|
|
381
|
+
* approval (in `orgId`).
|
|
382
|
+
*/
|
|
383
|
+
private lockConversationOf;
|
|
384
|
+
/** Locks, in id order, the conversations `ids` selects; returns their ids. */
|
|
385
|
+
private lockConversations;
|
|
356
386
|
/** `conversationId` and its sub-agents' conversations at any depth (at most 16 levels). */
|
|
357
387
|
private subtreeOf;
|
|
358
388
|
/**
|