@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,104 @@
|
|
|
1
|
+
import { isSandboxTier, minTier, tierAtMost } from "@capybara-hq/plugin-sdk";
|
|
2
|
+
import { readPlatformTiers } from "./platform-tiers.js";
|
|
3
|
+
/**
|
|
4
|
+
* The platform side of the policy, read live: the `sandbox.limits` network fields of the config
|
|
5
|
+
* and the effective platform tiers (in the caller's transaction when there is one).
|
|
6
|
+
*/
|
|
7
|
+
export async function readDeploymentSandboxPolicy(db, config) {
|
|
8
|
+
return { limits: config.get().sandbox.limits, tiers: await readPlatformTiers(db, config) };
|
|
9
|
+
}
|
|
10
|
+
/** The org's base list `L`: see {@link BaseSandboxEgress}. */
|
|
11
|
+
export function baseSandboxEgress(deployment, org) {
|
|
12
|
+
if (deployment.egress === "none" || org?.mode === "none")
|
|
13
|
+
return { egress: "none", allowHosts: [] };
|
|
14
|
+
return { egress: "allowlist", allowHosts: [...(org?.allowHosts ?? deployment.allowHosts)] };
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* The network of `tier` over the base list (spec §4.2): `none` stays `none` in every tier; an
|
|
18
|
+
* allowlist is `L` in strict, `L ∪ D` in dev and open egress in open.
|
|
19
|
+
*/
|
|
20
|
+
export function networkForTier(base, devHosts, tier) {
|
|
21
|
+
if (base.egress === "none")
|
|
22
|
+
return { egress: "none", allowHosts: [] };
|
|
23
|
+
if (tier === "open")
|
|
24
|
+
return { egress: "open", allowHosts: [] };
|
|
25
|
+
if (tier === "dev") {
|
|
26
|
+
return { egress: "allowlist", allowHosts: [...new Set([...base.allowHosts, ...devHosts])] };
|
|
27
|
+
}
|
|
28
|
+
return { egress: "allowlist", allowHosts: [...base.allowHosts] };
|
|
29
|
+
}
|
|
30
|
+
/** The network of `tier` under `policy` (e.g. the ceiling's for a local device's exec args). */
|
|
31
|
+
export function limitsForTier(policy, tier) {
|
|
32
|
+
return networkForTier(policy.base, policy.devHosts, tier);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The effective sandbox policy (spec §4.2). `deviceTier` is the device's own choice (null =
|
|
36
|
+
* follow the org's default). The org's ceiling is its `sandboxTier.max` (absent = the platform's)
|
|
37
|
+
* cut to the platform's; its default is `sandboxTier.default ?? sandbox.tiers.default`, cut to the
|
|
38
|
+
* ceiling. Stored values above the platform (the platform lowered its max later) are cut, never
|
|
39
|
+
* honoured.
|
|
40
|
+
*/
|
|
41
|
+
export function effectiveSandboxPolicy(deployment, org, deviceTier) {
|
|
42
|
+
const platformMax = deployment.tiers.max;
|
|
43
|
+
const orgMax = org.sandboxTier?.max ?? platformMax;
|
|
44
|
+
const ceiling = minTier(orgMax, platformMax);
|
|
45
|
+
const chosenDefault = org.sandboxTier?.default ?? deployment.tiers.default;
|
|
46
|
+
const defaultTier = minTier(chosenDefault, ceiling);
|
|
47
|
+
const chosen = deviceTier ?? chosenDefault;
|
|
48
|
+
const tier = minTier(chosen, ceiling);
|
|
49
|
+
// the platform caps when its max is the lowest ceiling (an org max at or above it cuts nothing)
|
|
50
|
+
const cappedBy = tier === chosen ? null : tierAtMost(platformMax, orgMax) ? "platform" : "org";
|
|
51
|
+
const base = baseSandboxEgress(deployment.limits, org.sandboxEgress);
|
|
52
|
+
const devHosts = [...deployment.limits.devHosts];
|
|
53
|
+
return {
|
|
54
|
+
tier,
|
|
55
|
+
ceiling,
|
|
56
|
+
defaultTier,
|
|
57
|
+
cappedBy,
|
|
58
|
+
...networkForTier(base, devHosts, tier),
|
|
59
|
+
base,
|
|
60
|
+
devHosts,
|
|
61
|
+
allowUnsandboxed: deployment.tiers.allowUnsandboxed &&
|
|
62
|
+
(org.sandboxTier?.allowUnsandboxed ?? true) &&
|
|
63
|
+
ceiling === "open",
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/** The {@link AppliedLimits} of `limits`. */
|
|
67
|
+
export const appliedOf = (limits) => ({
|
|
68
|
+
tier: limits.tier,
|
|
69
|
+
egress: limits.egress,
|
|
70
|
+
});
|
|
71
|
+
/** Whether `a` and `b` are the same tier and egress mode (null, unknown, is never the same). */
|
|
72
|
+
export const sameApplied = (a, b) => a != null && a.tier === b.tier && a.egress === b.egress;
|
|
73
|
+
const EGRESS_MODES = ["none", "allowlist", "open"];
|
|
74
|
+
function appliedFrom(v) {
|
|
75
|
+
if (typeof v !== "object" || v === null)
|
|
76
|
+
return null;
|
|
77
|
+
const o = v;
|
|
78
|
+
if (!isSandboxTier(o.tier) || typeof o.egress !== "string" || !EGRESS_MODES.includes(o.egress)) {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
return { tier: o.tier, egress: o.egress };
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* `device_instances.instance_limits` read leniently: `applied` is what the instance runs with
|
|
85
|
+
* (null: unknown, e.g. an instance made before migration 0117, which differs from every effective
|
|
86
|
+
* value); `unapplied` is a newer value the provider could not apply without a file reset.
|
|
87
|
+
*/
|
|
88
|
+
export function readInstanceLimits(v) {
|
|
89
|
+
if (typeof v !== "object" || v === null)
|
|
90
|
+
return { applied: null, unapplied: null };
|
|
91
|
+
return {
|
|
92
|
+
applied: appliedFrom(v),
|
|
93
|
+
unapplied: appliedFrom(v.unapplied),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
/** The JSON written to `device_instances.instance_limits`. */
|
|
97
|
+
export function instanceLimitsJson(applied, unapplied) {
|
|
98
|
+
if (applied === null && unapplied === undefined)
|
|
99
|
+
return null;
|
|
100
|
+
return JSON.stringify({
|
|
101
|
+
...(applied !== null && appliedOf(applied)),
|
|
102
|
+
...(unapplied !== undefined && { unapplied: appliedOf(unapplied) }),
|
|
103
|
+
});
|
|
104
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { KernelSchemaDb } from "../db/kernel-schema.js";
|
|
2
|
+
import type { KernelConfigService } from "../infra/config/kernel-config.service.js";
|
|
3
|
+
import { type ScheduledTasksSettings } from "../orgs/settings.service.js";
|
|
4
|
+
/** The platform's bounds for the org settings (kernel config `schedules.*`). */
|
|
5
|
+
export interface ScheduleBounds {
|
|
6
|
+
minIntervalFloorMinutes: number;
|
|
7
|
+
maxTasksPerMemberCap: number;
|
|
8
|
+
maxTasksPerOrgCap: number;
|
|
9
|
+
maxRunsPerHourCap: number;
|
|
10
|
+
}
|
|
11
|
+
/** The org's scheduled-task settings after clamping to the platform bounds. */
|
|
12
|
+
export type EffectiveScheduleSettings = ScheduledTasksSettings;
|
|
13
|
+
/** An org value outside the platform bounds is clamped: the interval up, the counts down. */
|
|
14
|
+
export declare function effectiveScheduleSettings(org: ScheduledTasksSettings, bounds: ScheduleBounds): EffectiveScheduleSettings;
|
|
15
|
+
/** Read the org's effective settings live (PG and the current kernel config). */
|
|
16
|
+
export declare function readScheduleSettings(db: KernelSchemaDb, config: Pick<KernelConfigService, "get">, orgId: string): Promise<EffectiveScheduleSettings>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { readOrgSettings } from "../orgs/settings.service.js";
|
|
2
|
+
/** An org value outside the platform bounds is clamped: the interval up, the counts down. */
|
|
3
|
+
export function effectiveScheduleSettings(org, bounds) {
|
|
4
|
+
return {
|
|
5
|
+
...org,
|
|
6
|
+
forbiddenTools: [...org.forbiddenTools],
|
|
7
|
+
minIntervalMinutes: Math.max(org.minIntervalMinutes, bounds.minIntervalFloorMinutes),
|
|
8
|
+
maxTasksPerMember: Math.min(org.maxTasksPerMember, bounds.maxTasksPerMemberCap),
|
|
9
|
+
maxTasksPerOrg: Math.min(org.maxTasksPerOrg, bounds.maxTasksPerOrgCap),
|
|
10
|
+
maxRunsPerHour: Math.min(org.maxRunsPerHour, bounds.maxRunsPerHourCap),
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
/** Read the org's effective settings live (PG and the current kernel config). */
|
|
14
|
+
export async function readScheduleSettings(db, config, orgId) {
|
|
15
|
+
const org = await readOrgSettings(db, orgId);
|
|
16
|
+
return effectiveScheduleSettings(org.scheduledTasks, config.get().schedules);
|
|
17
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ApiError } from "../errors.js";
|
|
2
|
+
/** The task is missing, deleted, in another org or not the caller's to see (never 403). */
|
|
3
|
+
export declare const scheduleNotFound: () => ApiError;
|
|
4
|
+
/** An org admin acting on another person's task in a way only its creator may (spec §10). */
|
|
5
|
+
export declare const scheduleForbidden: () => ApiError;
|
|
6
|
+
export declare const scheduleDisabled: () => ApiError;
|
|
7
|
+
export declare const targetInvalid: (message: string) => ApiError;
|
|
8
|
+
export declare const grantNotAllowed: (message: string) => ApiError;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ApiError } from "../errors.js";
|
|
2
|
+
/** The task is missing, deleted, in another org or not the caller's to see (never 403). */
|
|
3
|
+
export const scheduleNotFound = () => new ApiError("schedule.not_found", "Scheduled task not found");
|
|
4
|
+
/** An org admin acting on another person's task in a way only its creator may (spec §10). */
|
|
5
|
+
export const scheduleForbidden = () => new ApiError("schedule.forbidden", "Only the task's creator can change its prompt, schedule, target or approved tools");
|
|
6
|
+
export const scheduleDisabled = () => new ApiError("schedule.disabled", "Scheduled tasks are turned off in this organization");
|
|
7
|
+
export const targetInvalid = (message) => new ApiError("schedule.target_invalid", message);
|
|
8
|
+
export const grantNotAllowed = (message) => new ApiError("schedule.grant_not_allowed", message);
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { AgentLookup } from "../agents/agent-lookup.js";
|
|
2
|
+
import { ChannelConnections } from "../channels/connections.service.js";
|
|
3
|
+
import { ConversationAccess } from "../conversations/access.js";
|
|
4
|
+
import { ConversationsService } from "../conversations/conversations.service.js";
|
|
5
|
+
import { ConversationQueue } from "../conversations/queue.service.js";
|
|
6
|
+
import { KernelConfigService } from "../infra/config/kernel-config.service.js";
|
|
7
|
+
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
8
|
+
import { TransactionHost } from "../infra/database/transaction-host.js";
|
|
9
|
+
import { LockService } from "../infra/lock/lock.service.js";
|
|
10
|
+
import type { KernelLogger } from "../log.js";
|
|
11
|
+
import { OrgLock } from "../orgs/org-lock.js";
|
|
12
|
+
import { RunControl } from "../runtime/run-control.js";
|
|
13
|
+
import { ScheduledTaskRunTracker } from "./run-tracker.js";
|
|
14
|
+
import { ScheduledTaskStore } from "./store.js";
|
|
15
|
+
/** A task run's message client id in a conversation's queue (never read back as "the task's"). */
|
|
16
|
+
export declare const scheduledClientMessageId: (taskRunId: string) => string;
|
|
17
|
+
/** The tick in the task's zone as the run's header shows it: `2026-11-11 09:00 (Asia/Shanghai)`. */
|
|
18
|
+
export declare function localTimeOf(at: Date, timeZone: string): string;
|
|
19
|
+
/**
|
|
20
|
+
* Checks and starts one task run (scheduled tasks spec §6), the body of the `sched-fire-<id>` job.
|
|
21
|
+
* Idempotent on the task run: only a `pending` one is fired. Two steps:
|
|
22
|
+
*
|
|
23
|
+
* 1. The claim, one transaction under the org row lock (which serializes the org's rate limit
|
|
24
|
+
* count), then the task run and the task rows: the checks in order (task paused since the
|
|
25
|
+
* scan, unless a person's "run now"; org disabled, creator
|
|
26
|
+
* inactive or not a member, agent gone or not visible, conversation gone, connection inactive,
|
|
27
|
+
* overlap, rate limit, device offline, queue paused), each a `skipped` run with its reason, the
|
|
28
|
+
* lasting ones also pausing the task; then `fired_at` is written, after the rate limit count.
|
|
29
|
+
* A run whose claim committed before (a retried job) goes straight to the start.
|
|
30
|
+
* 2. The start, idempotent: `new` creates the conversation with its first message keyed by the
|
|
31
|
+
* task run id (`create_request_id`); `conversation` queues the prompt in the target
|
|
32
|
+
* conversation's queue (never absorbed into a run in progress); `chat` finds the DM's live
|
|
33
|
+
* thread or creates and binds a conversation (one transaction), then queues the prompt there;
|
|
34
|
+
* a group chat gets a new conversation per run whose thread outbound binds at the run's first
|
|
35
|
+
* post (`openGroup`). A start that finds the target gone takes `fired_at` back and skips the run.
|
|
36
|
+
*
|
|
37
|
+
* Every message carries the schedule marker and the task's zone; the kernel run its message
|
|
38
|
+
* triggers takes the task run (`linkStartedRunIn`), and the run tracker follows it to its end.
|
|
39
|
+
*/
|
|
40
|
+
export declare class ScheduledTaskFirer {
|
|
41
|
+
private readonly kdb;
|
|
42
|
+
readonly txHost: TransactionHost;
|
|
43
|
+
private readonly config;
|
|
44
|
+
private readonly store;
|
|
45
|
+
private readonly tracker;
|
|
46
|
+
private readonly orgLock;
|
|
47
|
+
private readonly agents;
|
|
48
|
+
private readonly access;
|
|
49
|
+
private readonly conversations;
|
|
50
|
+
private readonly queue;
|
|
51
|
+
private readonly connections;
|
|
52
|
+
private readonly runs;
|
|
53
|
+
/** Reads a local device's connection lease (online or not). */
|
|
54
|
+
private readonly locks;
|
|
55
|
+
private readonly log;
|
|
56
|
+
constructor(kdb: KernelDb, txHost: TransactionHost, config: Pick<KernelConfigService, "get">, store: ScheduledTaskStore, tracker: Pick<ScheduledTaskRunTracker, "inFlightIn" | "failStartIn">, orgLock: Pick<OrgLock, "tryLock">, agents: Pick<AgentLookup, "get">, access: Pick<ConversationAccess, "isAccessible">, conversations: Pick<ConversationsService, "createWithMessage" | "create">, queue: Pick<ConversationQueue, "add">, connections: Pick<ChannelConnections, "row" | "channel">, runs: Pick<RunControl, "ensureRun">,
|
|
57
|
+
/** Reads a local device's connection lease (online or not). */
|
|
58
|
+
locks: Pick<LockService, "holderOf">, log: Pick<KernelLogger, "warn" | "info">);
|
|
59
|
+
private get db();
|
|
60
|
+
/** Fires task run `taskRunId` (see the class); a run not `pending` is left as it is. */
|
|
61
|
+
fire(taskRunId: string): Promise<void>;
|
|
62
|
+
/** Step 1 (see the class): a skip, the plan, or null when there is nothing to fire. */
|
|
63
|
+
private claim;
|
|
64
|
+
/** Step 2 (see the class). */
|
|
65
|
+
private start;
|
|
66
|
+
/**
|
|
67
|
+
* The DM's live conversation, or a new one bound to it (`findOrBindThread`), in one transaction:
|
|
68
|
+
* a conversation it creates is the task's (`conversations.scheduled_task_id`). Null when the
|
|
69
|
+
* live conversation's queue is paused (the run is skipped, `queue_paused`).
|
|
70
|
+
*/
|
|
71
|
+
private bindChat;
|
|
72
|
+
/**
|
|
73
|
+
* A group run's conversation (spec §8): a new one per run, the task's
|
|
74
|
+
* (`conversations.scheduled_task_id`), whose delivery goes to the group with its thread still to
|
|
75
|
+
* bind (`channel_deliveries.pending_thread_account_id` = the creator): outbound binds it at the
|
|
76
|
+
* run's first post, thread key = that message's id, so replies in that thread continue the
|
|
77
|
+
* conversation. One transaction; a retried start reuses the conversation it made before.
|
|
78
|
+
*/
|
|
79
|
+
private openGroup;
|
|
80
|
+
/** The start found the target gone: `fired_at` back to null, skipped with `reason`. */
|
|
81
|
+
private unstart;
|
|
82
|
+
/**
|
|
83
|
+
* The start was refused for another reason (a full queue, a model gone since the task was
|
|
84
|
+
* saved, …): the run failed, and counts toward the task's failures as a failed run does.
|
|
85
|
+
*/
|
|
86
|
+
private failStart;
|
|
87
|
+
private setConversation;
|
|
88
|
+
/** Marks a pending run skipped (never fired) and pauses the task for a lasting reason. */
|
|
89
|
+
private skipIn;
|
|
90
|
+
/** Another run of the task is still in flight (stale ones are settled on the way). */
|
|
91
|
+
private overlaps;
|
|
92
|
+
/** The creator is an active account and still a member of the org. */
|
|
93
|
+
private creatorActive;
|
|
94
|
+
/** The target conversation, live, the creator's chat with the task's agent and accessible. */
|
|
95
|
+
private targetConversation;
|
|
96
|
+
private queuePaused;
|
|
97
|
+
/**
|
|
98
|
+
* The DM thread key of the creator in `chatId` (the key inbound uses, `dm:<externalId>`), from
|
|
99
|
+
* their external ids on the connection's identity source (`<plugin>:<tenant>`): the id whose
|
|
100
|
+
* thread row in this chat is the newest (archived rows count); when none has a row there, the
|
|
101
|
+
* smallest id (deterministic). Without an identity (no tenant yet), the key of their newest DM
|
|
102
|
+
* thread row in the chat. Undefined when neither exists.
|
|
103
|
+
*/
|
|
104
|
+
private dmThreadKey;
|
|
105
|
+
/**
|
|
106
|
+
* The creator has written in the group (spec §8: a group thread row of theirs exists there,
|
|
107
|
+
* archived ones included), so a run may post there on their behalf.
|
|
108
|
+
*/
|
|
109
|
+
private inGroup;
|
|
110
|
+
/** The device is gone, or a local device whose machine is not connected now. */
|
|
111
|
+
private deviceOffline;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* The fire job and the scanner, worker only: imported by `MaintenanceModule` (which dispatches
|
|
115
|
+
* `sched-fire`) and `WorkerModule` (the scan's `@LockedCron`), never by another role.
|
|
116
|
+
*/
|
|
117
|
+
export declare class ScheduledTaskFireModule {
|
|
118
|
+
}
|