@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
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import type { KernelSchemaDb } from "../db/kernel-schema.js";
|
|
3
|
+
import { KernelConfigService } from "../infra/config/kernel-config.service.js";
|
|
3
4
|
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
4
5
|
import { TransactionHost } from "../infra/database/transaction-host.js";
|
|
5
6
|
import type { KernelLogger } from "../log.js";
|
|
7
|
+
import { type PlatformTiers, type PlatformTiersPatch, type PlatformTiersStored, type PlatformTiersView } from "../sandbox/platform-tiers.js";
|
|
6
8
|
import { type UiArrangement } from "../ui/arrangement.js";
|
|
7
9
|
import { SuperAdminLock } from "./super-admin.js";
|
|
8
10
|
/** 沙箱 cpu(核)与内存(MB)覆盖的范围(C19)。 */
|
|
@@ -105,6 +107,14 @@ export declare const DEPLOYMENT_SETTINGS: z.ZodObject<{
|
|
|
105
107
|
}, z.core.$strip>>;
|
|
106
108
|
}, z.core.$strip>;
|
|
107
109
|
export type DeploymentSettings = z.infer<typeof DEPLOYMENT_SETTINGS>;
|
|
110
|
+
/**
|
|
111
|
+
* What `GET /api/v1/admin/settings` answers: the stored settings, and the platform's sandbox tiers
|
|
112
|
+
* as they are in effect with where each field comes from (`env` / `file` / `nacos`: the startup
|
|
113
|
+
* config, read-only here; `db`: chosen in the admin console; `default`).
|
|
114
|
+
*/
|
|
115
|
+
export type DeploymentSettingsView = DeploymentSettings & {
|
|
116
|
+
sandboxTiers: PlatformTiersView;
|
|
117
|
+
};
|
|
108
118
|
/**
|
|
109
119
|
* 设置的修改(PUT /api/v1/admin/settings 的 body):只改给出的键。
|
|
110
120
|
* `runConcurrencyOverrides` 按组织合并:值为正整数 → 设置该组织的上限;值为 null → 删除该组织的覆盖
|
|
@@ -147,6 +157,19 @@ export declare const DEPLOYMENT_SETTINGS_PATCH: z.ZodObject<{
|
|
|
147
157
|
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
148
158
|
disabled: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
149
159
|
}, z.core.$strict>>;
|
|
160
|
+
sandboxTiers: z.ZodOptional<z.ZodObject<{
|
|
161
|
+
max: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
162
|
+
dev: "dev";
|
|
163
|
+
open: "open";
|
|
164
|
+
strict: "strict";
|
|
165
|
+
}>>>;
|
|
166
|
+
default: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
167
|
+
dev: "dev";
|
|
168
|
+
open: "open";
|
|
169
|
+
strict: "strict";
|
|
170
|
+
}>>>;
|
|
171
|
+
allowUnsandboxed: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
172
|
+
}, z.core.$strict>>;
|
|
150
173
|
}, z.core.$strict>;
|
|
151
174
|
export type DeploymentSettingsPatch = z.infer<typeof DEPLOYMENT_SETTINGS_PATCH>;
|
|
152
175
|
/**
|
|
@@ -198,7 +221,29 @@ export declare class SettingsService {
|
|
|
198
221
|
readonly txHost: TransactionHost;
|
|
199
222
|
private readonly adminLock;
|
|
200
223
|
private readonly log;
|
|
201
|
-
|
|
224
|
+
/** The startup config's `sandbox.tiers`, which wins over the stored choice. */
|
|
225
|
+
private readonly config;
|
|
226
|
+
constructor(db: KernelDb, txHost: TransactionHost, adminLock: SuperAdminLock, log: Pick<KernelLogger, "warn">,
|
|
227
|
+
/** The startup config's `sandbox.tiers`, which wins over the stored choice. */
|
|
228
|
+
config: Pick<KernelConfigService, "get" | "fieldSource">);
|
|
229
|
+
/** The settings with the platform's sandbox tiers in effect and their sources. */
|
|
230
|
+
view(): Promise<DeploymentSettingsView>;
|
|
231
|
+
private tiersView;
|
|
232
|
+
/**
|
|
233
|
+
* The refusals of a `sandboxTiers` change against the stored choice: a field set in the
|
|
234
|
+
* startup config (`deployment.setting_readonly`), a default above the max
|
|
235
|
+
* (`validation_failed`), and with `onlyNarrows` (an API token, the Platform tool) any widening:
|
|
236
|
+
* a higher max or default, unsandboxed allowed, in effect or in the stored choice (which
|
|
237
|
+
* applies once the startup config stops setting a field). Returns the next stored choice and
|
|
238
|
+
* the effective tiers before and after.
|
|
239
|
+
*/
|
|
240
|
+
checkSandboxTiers(patch: PlatformTiersPatch, opts?: {
|
|
241
|
+
onlyNarrows?: boolean;
|
|
242
|
+
}): Promise<{
|
|
243
|
+
next: PlatformTiersStored;
|
|
244
|
+
before: PlatformTiers;
|
|
245
|
+
after: PlatformTiers;
|
|
246
|
+
}>;
|
|
202
247
|
/**
|
|
203
248
|
* Reads every setting, in the context's transaction when there is one (a caller holding a
|
|
204
249
|
* transaction connection does not take a second one from the pool). Each key is validated on
|
|
@@ -206,9 +251,14 @@ export declare class SettingsService {
|
|
|
206
251
|
* valid keys apply; unknown keys (written by a newer version) are ignored.
|
|
207
252
|
*/
|
|
208
253
|
get(): Promise<DeploymentSettings>;
|
|
209
|
-
/**
|
|
254
|
+
/**
|
|
255
|
+
* Updates settings under the super admin lock, re-checking the actor (else `forbidden`).
|
|
256
|
+
* `onlyNarrows` (an API token, the Platform tool): `sandboxTiers` may only narrow.
|
|
257
|
+
*/
|
|
210
258
|
update(patch: DeploymentSettingsPatch, actorAccountId: string, actorTokenId?: string,
|
|
211
259
|
/** Merged into the audit detail (the Platform tool's `via: "agent"`). */
|
|
212
|
-
auditDetail?: Record<string, unknown
|
|
260
|
+
auditDetail?: Record<string, unknown>, opts?: {
|
|
261
|
+
onlyNarrows?: boolean;
|
|
262
|
+
}): Promise<DeploymentSettingsView>;
|
|
213
263
|
private write;
|
|
214
264
|
}
|
|
@@ -11,10 +11,12 @@ import { EXTENSION_NAME_RE } from "@capybara-hq/plugin-sdk";
|
|
|
11
11
|
import { Inject, Injectable } from "@nestjs/common";
|
|
12
12
|
import { z } from "zod";
|
|
13
13
|
import { ApiError } from "../errors.js";
|
|
14
|
+
import { KernelConfigService } from "../infra/config/kernel-config.service.js";
|
|
14
15
|
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
15
16
|
import { TransactionHost } from "../infra/database/transaction-host.js";
|
|
16
17
|
import { Transactional } from "../infra/database/transactional.decorator.js";
|
|
17
18
|
import { KERNEL_LOGGER } from "../infra/tokens.js";
|
|
19
|
+
import { applyPlatformTiersPatch, chosenPlatformDefault, PLATFORM_TIER_FIELDS, PLATFORM_TIERS_PATCH, PLATFORM_TIERS_SETTING, platformTiersWiden, readStoredPlatformTiers, resolvePlatformTiers, } from "../sandbox/platform-tiers.js";
|
|
18
20
|
import { assertPlatformDefaultEligible, lockThemeShared } from "../themes/theme-state.js";
|
|
19
21
|
import { mergeArrangement, UiArrangementPatchSchema, UiArrangementSchema, } from "../ui/arrangement.js";
|
|
20
22
|
import { audit } from "./audit.js";
|
|
@@ -153,6 +155,7 @@ export const DEPLOYMENT_SETTINGS = z.object({
|
|
|
153
155
|
clientExtensions: ClientExtensionsSetting.default(clientExtensionsDefault),
|
|
154
156
|
});
|
|
155
157
|
const DEFAULTS = DEPLOYMENT_SETTINGS.parse({});
|
|
158
|
+
const tierWidenRefused = () => new ApiError("deployment.sandbox_tier_not_allowed", "Raising the platform's sandbox level (sandboxTiers) needs a super admin in the admin console; an API token or the Platform tool may only lower it.");
|
|
156
159
|
/**
|
|
157
160
|
* 设置的修改(PUT /api/v1/admin/settings 的 body):只改给出的键。
|
|
158
161
|
* `runConcurrencyOverrides` 按组织合并:值为正整数 → 设置该组织的上限;值为 null → 删除该组织的覆盖
|
|
@@ -198,6 +201,14 @@ export const DEPLOYMENT_SETTINGS_PATCH = z
|
|
|
198
201
|
message: "give enabled, disabled or both",
|
|
199
202
|
})
|
|
200
203
|
.optional(),
|
|
204
|
+
/**
|
|
205
|
+
* The platform's sandbox tiers (sandbox dev tiers spec §4.1): each given field replaces the
|
|
206
|
+
* stored one, null clears it (back to the default: max dev, default dev, unsandboxed allowed).
|
|
207
|
+
* A field set in the startup config is read-only (409 `deployment.setting_readonly`); the
|
|
208
|
+
* default may not be above the max; an API token or the Platform tool may only narrow (400
|
|
209
|
+
* `deployment.sandbox_tier_not_allowed`).
|
|
210
|
+
*/
|
|
211
|
+
sandboxTiers: PLATFORM_TIERS_PATCH.optional(),
|
|
201
212
|
})
|
|
202
213
|
.strict();
|
|
203
214
|
/**
|
|
@@ -350,11 +361,66 @@ let SettingsService = class SettingsService {
|
|
|
350
361
|
txHost;
|
|
351
362
|
adminLock;
|
|
352
363
|
log;
|
|
353
|
-
|
|
364
|
+
config;
|
|
365
|
+
constructor(db, txHost, adminLock, log,
|
|
366
|
+
/** The startup config's `sandbox.tiers`, which wins over the stored choice. */
|
|
367
|
+
config) {
|
|
354
368
|
this.db = db;
|
|
355
369
|
this.txHost = txHost;
|
|
356
370
|
this.adminLock = adminLock;
|
|
357
371
|
this.log = log;
|
|
372
|
+
this.config = config;
|
|
373
|
+
}
|
|
374
|
+
/** The settings with the platform's sandbox tiers in effect and their sources. */
|
|
375
|
+
async view() {
|
|
376
|
+
const [settings, stored] = await Promise.all([
|
|
377
|
+
this.get(),
|
|
378
|
+
readStoredPlatformTiers(this.db.db, this.log),
|
|
379
|
+
]);
|
|
380
|
+
return { ...settings, sandboxTiers: this.tiersView(stored) };
|
|
381
|
+
}
|
|
382
|
+
tiersView(stored) {
|
|
383
|
+
const config = this.config.get().sandbox.tiers;
|
|
384
|
+
const sources = Object.fromEntries(PLATFORM_TIER_FIELDS.map((f) => [
|
|
385
|
+
f,
|
|
386
|
+
this.config.fieldSource(`sandbox.tiers.${f}`) ??
|
|
387
|
+
(stored[f] !== undefined ? "db" : "default"),
|
|
388
|
+
]));
|
|
389
|
+
return { ...resolvePlatformTiers(config, stored), sources };
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* The refusals of a `sandboxTiers` change against the stored choice: a field set in the
|
|
393
|
+
* startup config (`deployment.setting_readonly`), a default above the max
|
|
394
|
+
* (`validation_failed`), and with `onlyNarrows` (an API token, the Platform tool) any widening:
|
|
395
|
+
* a higher max or default, unsandboxed allowed, in effect or in the stored choice (which
|
|
396
|
+
* applies once the startup config stops setting a field). Returns the next stored choice and
|
|
397
|
+
* the effective tiers before and after.
|
|
398
|
+
*/
|
|
399
|
+
async checkSandboxTiers(patch, opts = {}) {
|
|
400
|
+
const readonly = PLATFORM_TIER_FIELDS.filter((f) => patch[f] !== undefined && this.config.fieldSource(`sandbox.tiers.${f}`) !== undefined);
|
|
401
|
+
if (readonly.length > 0) {
|
|
402
|
+
throw new ApiError("deployment.setting_readonly", `These sandbox tier settings are set in the startup config (file, Nacos or environment) and are read-only here: ${readonly.map((f) => `sandbox.tiers.${f}`).join(", ")}`, readonly.map((f) => ({
|
|
403
|
+
path: `sandboxTiers.${f}`,
|
|
404
|
+
source: this.config.fieldSource(`sandbox.tiers.${f}`),
|
|
405
|
+
})));
|
|
406
|
+
}
|
|
407
|
+
const config = this.config.get().sandbox.tiers;
|
|
408
|
+
const stored = await readStoredPlatformTiers(this.db.db, this.log);
|
|
409
|
+
const next = applyPlatformTiersPatch(stored, patch);
|
|
410
|
+
const before = resolvePlatformTiers(config, stored);
|
|
411
|
+
const after = resolvePlatformTiers(config, next);
|
|
412
|
+
const chosen = chosenPlatformDefault(config, next);
|
|
413
|
+
if ((patch.max !== undefined || patch.default !== undefined) && chosen !== after.default) {
|
|
414
|
+
throw new ApiError("validation_failed", `The default sandbox tier (${chosen}) cannot be above the highest (${after.max}); lower sandboxTiers.default as well`, [{ path: "sandboxTiers.default", message: `must be at most ${after.max}` }]);
|
|
415
|
+
}
|
|
416
|
+
if (opts.onlyNarrows) {
|
|
417
|
+
const none = {};
|
|
418
|
+
if (platformTiersWiden(before, after) ||
|
|
419
|
+
platformTiersWiden(resolvePlatformTiers(none, stored), resolvePlatformTiers(none, next))) {
|
|
420
|
+
throw tierWidenRefused();
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
return { next, before, after };
|
|
358
424
|
}
|
|
359
425
|
/**
|
|
360
426
|
* Reads every setting, in the context's transaction when there is one (a caller holding a
|
|
@@ -382,18 +448,21 @@ let SettingsService = class SettingsService {
|
|
|
382
448
|
}
|
|
383
449
|
return out;
|
|
384
450
|
}
|
|
385
|
-
/**
|
|
451
|
+
/**
|
|
452
|
+
* Updates settings under the super admin lock, re-checking the actor (else `forbidden`).
|
|
453
|
+
* `onlyNarrows` (an API token, the Platform tool): `sandboxTiers` may only narrow.
|
|
454
|
+
*/
|
|
386
455
|
async update(patch, actorAccountId, actorTokenId,
|
|
387
456
|
/** Merged into the audit detail (the Platform tool's `via: "agent"`). */
|
|
388
|
-
auditDetail) {
|
|
457
|
+
auditDetail, opts = {}) {
|
|
389
458
|
const check = DEPLOYMENT_SETTINGS_PATCH.safeParse(patch);
|
|
390
459
|
if (!check.success) {
|
|
391
460
|
throw new ApiError("validation_failed", "Invalid deployment settings", check.error.issues.map((i) => ({ path: i.path.join("."), message: i.message })));
|
|
392
461
|
}
|
|
393
|
-
await this.write(check.data, actorAccountId, actorTokenId, auditDetail);
|
|
394
|
-
return this.
|
|
462
|
+
await this.write(check.data, actorAccountId, actorTokenId, auditDetail, opts);
|
|
463
|
+
return this.view();
|
|
395
464
|
}
|
|
396
|
-
async write(patch, actorAccountId, actorTokenId, auditDetail) {
|
|
465
|
+
async write(patch, actorAccountId, actorTokenId, auditDetail, opts) {
|
|
397
466
|
await this.adminLock.lockAndAuthorize(actorAccountId);
|
|
398
467
|
// The super admin lock serializes every settings write: the current overrides are read
|
|
399
468
|
// and merged under it, so no concurrent change is lost
|
|
@@ -452,7 +521,16 @@ let SettingsService = class SettingsService {
|
|
|
452
521
|
next.subagentLimitOverrides = mergeByOrg(current.subagentLimitOverrides, subagentPatch);
|
|
453
522
|
}
|
|
454
523
|
}
|
|
455
|
-
|
|
524
|
+
// the platform's sandbox tiers: checked against the stored choice under the lock; lowering
|
|
525
|
+
// the max needs no org rewrite, the effective policy cuts every org's ceiling and default
|
|
526
|
+
let tiersChange;
|
|
527
|
+
const writes = Object.entries(next);
|
|
528
|
+
if (patch.sandboxTiers !== undefined) {
|
|
529
|
+
const r = await this.checkSandboxTiers(patch.sandboxTiers, opts);
|
|
530
|
+
tiersChange = { before: r.before, after: r.after };
|
|
531
|
+
writes.push([PLATFORM_TIERS_SETTING, r.next]);
|
|
532
|
+
}
|
|
533
|
+
for (const [key, value] of writes) {
|
|
456
534
|
if (value === undefined)
|
|
457
535
|
continue;
|
|
458
536
|
const json = JSON.stringify(value);
|
|
@@ -468,7 +546,11 @@ let SettingsService = class SettingsService {
|
|
|
468
546
|
actorAccountId,
|
|
469
547
|
...(actorTokenId !== undefined && { actorTokenId }),
|
|
470
548
|
action: "deployment.settings.updated",
|
|
471
|
-
detail: {
|
|
549
|
+
detail: {
|
|
550
|
+
...patch,
|
|
551
|
+
...(tiersChange !== undefined && { sandboxTiersEffective: tiersChange }),
|
|
552
|
+
...auditDetail,
|
|
553
|
+
},
|
|
472
554
|
});
|
|
473
555
|
}
|
|
474
556
|
};
|
|
@@ -480,6 +562,7 @@ SettingsService = __decorate([
|
|
|
480
562
|
__param(0, Inject(KernelDb)),
|
|
481
563
|
__param(1, Inject(TransactionHost)),
|
|
482
564
|
__param(2, Inject(SuperAdminLock)),
|
|
483
|
-
__param(3, Inject(KERNEL_LOGGER))
|
|
565
|
+
__param(3, Inject(KERNEL_LOGGER)),
|
|
566
|
+
__param(4, Inject(KernelConfigService))
|
|
484
567
|
], SettingsService);
|
|
485
568
|
export { SettingsService };
|
|
@@ -6,6 +6,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
6
6
|
};
|
|
7
7
|
import { Module } from "@nestjs/common";
|
|
8
8
|
import { CatalogModule } from "../catalog/catalog.module.js";
|
|
9
|
+
import { SchedulesModule } from "../schedules/schedules.module.js";
|
|
9
10
|
import { SkillsModule } from "../skills/skills.module.js";
|
|
10
11
|
import { ToolsModule } from "../tools/tools.module.js";
|
|
11
12
|
import { InboxService } from "./inbox.service.js";
|
|
@@ -18,7 +19,7 @@ let InboxModule = class InboxModule {
|
|
|
18
19
|
};
|
|
19
20
|
InboxModule = __decorate([
|
|
20
21
|
Module({
|
|
21
|
-
imports: [ToolsModule, SkillsModule, CatalogModule],
|
|
22
|
+
imports: [ToolsModule, SkillsModule, CatalogModule, SchedulesModule],
|
|
22
23
|
providers: [InboxService, PlatformInboxService],
|
|
23
24
|
exports: [InboxService, PlatformInboxService],
|
|
24
25
|
})
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { CatalogRequestsService, type CatalogRequestView } from "../catalog/requests.service.js";
|
|
2
2
|
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
3
|
+
import { type ScheduleAttention, ScheduledTasksService } from "../schedules/scheduled-tasks.service.js";
|
|
3
4
|
import { SkillChangesService, type SkillChangeView } from "../skills/changes.service.js";
|
|
4
5
|
import { ApprovalsService, type ApprovalView } from "../tools/approvals.service.js";
|
|
5
6
|
import type { OrgNoticeDetails } from "./org-notices.js";
|
|
@@ -40,11 +41,16 @@ export declare const INBOX_MAX_ITEMS = 100;
|
|
|
40
41
|
* - `tool_approval`:当前用户能处理的待处理工具调用审批(与 `GET /approvals?status=pending` 同一视图);
|
|
41
42
|
* - `skill_change`: pending skill share requests and proposed versions of shared skills, when the
|
|
42
43
|
* current user is an org admin (`skillChange.kind`; spec §5.4, §5.5);
|
|
43
|
-
* - `catalog_request`: pending `enable` requests from members and pending
|
|
44
|
-
* requests (`request.kind`; `
|
|
45
|
-
* P4-T6-5
|
|
44
|
+
* - `catalog_request`: pending `enable` and `network_allowlist` requests from members and pending
|
|
45
|
+
* `connector_setup` requests (`request.kind`; for `connector_setup` `request.agent` and
|
|
46
|
+
* `request.connectors` set, `item` null, ruling P4-T6-5; for `network_allowlist`
|
|
47
|
+
* `request.network` set, network ask-to-allow spec §5.3), when the current user is an org admin
|
|
48
|
+
* (M6 T26, C22; plugin scope spec §5.1);
|
|
46
49
|
* - `catalog_request_decided`: the current user's own requests in this org that were approved or
|
|
47
50
|
* rejected (with the reason), until dismissed (`POST catalog-requests/:id/dismiss`);
|
|
51
|
+
* - `schedule_attention`: the current user's own scheduled task that needs them (spec §8): paused
|
|
52
|
+
* for any reason but their own pause, its latest run failed, or its latest run was refused tools
|
|
53
|
+
* or connections; derived live, gone once the task is resumed or runs clean;
|
|
48
54
|
* - the org notices (`skill_renamed`, `item_shared`, `shared_item_updated`, `upload_confirmed`,
|
|
49
55
|
* `upload_rejected`; `type` = the notice's kind): for org admins, until one dismisses it
|
|
50
56
|
* (`POST inbox/notices/:id/dismiss`).
|
|
@@ -70,12 +76,20 @@ export type InboxItem = {
|
|
|
70
76
|
/** When it was decided. */
|
|
71
77
|
createdAt: string;
|
|
72
78
|
request: CatalogRequestView;
|
|
79
|
+
} | {
|
|
80
|
+
type: "schedule_attention";
|
|
81
|
+
/** `<taskId>:paused`, `<taskId>:failed` or `<taskId>:grants`. */
|
|
82
|
+
id: string;
|
|
83
|
+
createdAt: string;
|
|
84
|
+
attention: ScheduleAttentionView;
|
|
73
85
|
} | {
|
|
74
86
|
type: OrgNoticeView["kind"];
|
|
75
87
|
id: string;
|
|
76
88
|
createdAt: string;
|
|
77
89
|
notice: OrgNoticeView;
|
|
78
90
|
};
|
|
91
|
+
/** A scheduled task that needs its creator ({@link ScheduleAttention}, dates as ISO strings). */
|
|
92
|
+
export type ScheduleAttentionView = Omit<ScheduleAttention, "at">;
|
|
79
93
|
/** `GET /inbox` 的结果:新的在前,最多 {@link INBOX_MAX_ITEMS} 项;`truncated` 为 true 表示还有更多。 */
|
|
80
94
|
export interface InboxView {
|
|
81
95
|
items: InboxItem[];
|
|
@@ -87,7 +101,8 @@ export declare class InboxService {
|
|
|
87
101
|
private readonly skillChanges;
|
|
88
102
|
private readonly kdb;
|
|
89
103
|
private readonly catalogRequests;
|
|
90
|
-
|
|
104
|
+
private readonly schedules;
|
|
105
|
+
constructor(approvals: Pick<ApprovalsService, "list">, skillChanges: Pick<SkillChangesService, "listPending">, kdb: KernelDb, catalogRequests: Pick<CatalogRequestsService, "listForOrgAdmin" | "listDecidedForRequester">, schedules: Pick<ScheduledTasksService, "attentionFor">);
|
|
91
106
|
list(orgId: string, accountId: string): Promise<InboxView>;
|
|
92
107
|
/** The org's open notices when the account is an org admin (else none), newest first. */
|
|
93
108
|
private notices;
|
|
@@ -13,6 +13,7 @@ import { CATALOG_REQUESTS_LIST_MAX, CatalogRequestsService, } from "../catalog/r
|
|
|
13
13
|
import { ApiError } from "../errors.js";
|
|
14
14
|
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
15
15
|
import { roleAtLeast } from "../orgs/roles.js";
|
|
16
|
+
import { ScheduledTasksService, } from "../schedules/scheduled-tasks.service.js";
|
|
16
17
|
import { SKILL_CHANGES_LIST_MAX, SkillChangesService, } from "../skills/changes.service.js";
|
|
17
18
|
import { APPROVALS_LIST_MAX, ApprovalsService, } from "../tools/approvals.service.js";
|
|
18
19
|
/** The most open org notices one inbox read returns. */
|
|
@@ -25,19 +26,22 @@ let InboxService = class InboxService {
|
|
|
25
26
|
skillChanges;
|
|
26
27
|
kdb;
|
|
27
28
|
catalogRequests;
|
|
28
|
-
|
|
29
|
+
schedules;
|
|
30
|
+
constructor(approvals, skillChanges, kdb, catalogRequests, schedules) {
|
|
29
31
|
this.approvals = approvals;
|
|
30
32
|
this.skillChanges = skillChanges;
|
|
31
33
|
this.kdb = kdb;
|
|
32
34
|
this.catalogRequests = catalogRequests;
|
|
35
|
+
this.schedules = schedules;
|
|
33
36
|
}
|
|
34
37
|
async list(orgId, accountId) {
|
|
35
|
-
const [approvals, changes, requests, decided, notices] = await Promise.all([
|
|
38
|
+
const [approvals, changes, requests, decided, notices, attention] = await Promise.all([
|
|
36
39
|
this.approvals.list(orgId, accountId, "pending"),
|
|
37
40
|
this.skillChanges.listPending(orgId, accountId),
|
|
38
41
|
this.catalogRequests.listForOrgAdmin(orgId, accountId),
|
|
39
42
|
this.catalogRequests.listDecidedForRequester(orgId, accountId),
|
|
40
43
|
this.notices(orgId, accountId),
|
|
44
|
+
this.schedules.attentionFor(orgId, accountId),
|
|
41
45
|
]);
|
|
42
46
|
const all = [
|
|
43
47
|
...approvals.map((a) => ({
|
|
@@ -64,6 +68,12 @@ let InboxService = class InboxService {
|
|
|
64
68
|
createdAt: r.decidedAt ?? r.createdAt,
|
|
65
69
|
request: r,
|
|
66
70
|
})),
|
|
71
|
+
...attention.map(({ at, ...view }) => ({
|
|
72
|
+
type: "schedule_attention",
|
|
73
|
+
id: `${view.taskId}:${view.reason === "missing_grants" ? "grants" : view.reason === "failed" ? "failed" : "paused"}`,
|
|
74
|
+
createdAt: at.toISOString(),
|
|
75
|
+
attention: view,
|
|
76
|
+
})),
|
|
67
77
|
...notices.map((n) => ({ type: n.kind, id: n.id, createdAt: n.createdAt, notice: n })),
|
|
68
78
|
];
|
|
69
79
|
// 新的在前;同一时刻按 id 定序(结果稳定)
|
|
@@ -142,7 +152,8 @@ InboxService = __decorate([
|
|
|
142
152
|
__param(0, Inject(ApprovalsService)),
|
|
143
153
|
__param(1, Inject(SkillChangesService)),
|
|
144
154
|
__param(2, Inject(KernelDb)),
|
|
145
|
-
__param(3, Inject(CatalogRequestsService))
|
|
155
|
+
__param(3, Inject(CatalogRequestsService)),
|
|
156
|
+
__param(4, Inject(ScheduledTasksService))
|
|
146
157
|
], InboxService);
|
|
147
158
|
export { InboxService };
|
|
148
159
|
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
@@ -15,6 +15,13 @@ export declare class KernelConfigService {
|
|
|
15
15
|
private readonly listeners;
|
|
16
16
|
constructor(input: KernelConfigInput, log: KernelLogger);
|
|
17
17
|
get(): KernelConfig;
|
|
18
|
+
/**
|
|
19
|
+
* Where the current value of a field without a schema default comes from: `env` when an
|
|
20
|
+
* environment variable sets it, else the config source (`file` / `nacos`) when it is set at all;
|
|
21
|
+
* undefined when nothing sets it (a layer below the startup config decides, e.g. the deployment
|
|
22
|
+
* settings for `sandbox.tiers.*`). Such fields are read-only in the admin console.
|
|
23
|
+
*/
|
|
24
|
+
fieldSource(path: string): "env" | "file" | "nacos" | undefined;
|
|
18
25
|
/** Subscribes to applied changes (hot fields only); returns the unsubscribe function. */
|
|
19
26
|
onChange(listener: ConfigChangeListener): () => void;
|
|
20
27
|
/**
|
|
@@ -8,9 +8,11 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
8
8
|
return function (target, key) { decorator(target, key, paramIndex); }
|
|
9
9
|
};
|
|
10
10
|
import { Inject, Injectable } from "@nestjs/common";
|
|
11
|
+
import { envOverrides } from "../../config/env.js";
|
|
11
12
|
import { changedPaths, configFields, getPath, secretValues, setPath } from "../../config/fields.js";
|
|
12
13
|
import { resolveConfig } from "../../config/load.js";
|
|
13
14
|
import { KernelConfigSchema } from "../../config/schema.js";
|
|
15
|
+
import { configSourceKind } from "../../config/sources.js";
|
|
14
16
|
import { KERNEL_CONFIG_INPUT, KERNEL_LOGGER } from "../tokens.js";
|
|
15
17
|
/**
|
|
16
18
|
* Appliers of the hot-reloadable fields: the key is a dotted path marked `hot` in the schema. A
|
|
@@ -33,6 +35,10 @@ const HOT_APPLIERS = {
|
|
|
33
35
|
"models.embedTimeoutMs": () => { },
|
|
34
36
|
// SandboxService reads the shared-lease cap at every acquisition.
|
|
35
37
|
"sandbox.maxConcurrentCommands": () => { },
|
|
38
|
+
// Sandbox tiers are read at every device use, org settings read and Platform call.
|
|
39
|
+
"sandbox.tiers.max": () => { },
|
|
40
|
+
"sandbox.tiers.default": () => { },
|
|
41
|
+
"sandbox.tiers.allowUnsandboxed": () => { },
|
|
36
42
|
// The devices service reads the personal limit at every create.
|
|
37
43
|
"devices.maxPersonal": () => { },
|
|
38
44
|
// The local device relay reads the reconnect grace at every disconnect and token response.
|
|
@@ -48,6 +54,13 @@ const HOT_APPLIERS = {
|
|
|
48
54
|
"web.fetch.maxAnswerTokens": () => { },
|
|
49
55
|
"web.fetch.cacheSeconds": () => { },
|
|
50
56
|
"web.fetch.timeoutMs": () => { },
|
|
57
|
+
// Scheduled-task settings are clamped to these bounds on every read.
|
|
58
|
+
"schedules.minIntervalFloorMinutes": () => { },
|
|
59
|
+
"schedules.maxTasksPerMemberCap": () => { },
|
|
60
|
+
"schedules.maxTasksPerOrgCap": () => { },
|
|
61
|
+
"schedules.maxRunsPerHourCap": () => { },
|
|
62
|
+
// Run start reads the skills catalog budget when it records a snapshot.
|
|
63
|
+
"skills.catalogBudgetChars": () => { },
|
|
51
64
|
};
|
|
52
65
|
/**
|
|
53
66
|
* Environment variables of renamed config keys, with their replacements: warned about once when
|
|
@@ -90,6 +103,24 @@ let KernelConfigService = class KernelConfigService {
|
|
|
90
103
|
get() {
|
|
91
104
|
return this.current;
|
|
92
105
|
}
|
|
106
|
+
/**
|
|
107
|
+
* Where the current value of a field without a schema default comes from: `env` when an
|
|
108
|
+
* environment variable sets it, else the config source (`file` / `nacos`) when it is set at all;
|
|
109
|
+
* undefined when nothing sets it (a layer below the startup config decides, e.g. the deployment
|
|
110
|
+
* settings for `sandbox.tiers.*`). Such fields are read-only in the admin console.
|
|
111
|
+
*/
|
|
112
|
+
fieldSource(path) {
|
|
113
|
+
if (getPath(this.current, path) === undefined)
|
|
114
|
+
return undefined;
|
|
115
|
+
let fromEnv = false;
|
|
116
|
+
try {
|
|
117
|
+
fromEnv = getPath(envOverrides(this.env), path) !== undefined;
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
// conflicting variables fail the start; a later change here only loses the label
|
|
121
|
+
}
|
|
122
|
+
return fromEnv ? "env" : configSourceKind(this.env);
|
|
123
|
+
}
|
|
93
124
|
/** Subscribes to applied changes (hot fields only); returns the unsubscribe function. */
|
|
94
125
|
onChange(listener) {
|
|
95
126
|
this.listeners.add(listener);
|
|
@@ -31,7 +31,8 @@ export interface KernelEventMap {
|
|
|
31
31
|
orgId: string;
|
|
32
32
|
conversationId: string;
|
|
33
33
|
runId: string;
|
|
34
|
-
|
|
34
|
+
/** `skipped`: a network ask closed by the run's starter's message (network ask-to-allow §6.7). */
|
|
35
|
+
status: "approved" | "denied" | "skipped";
|
|
35
36
|
};
|
|
36
37
|
/**
|
|
37
38
|
* A person answered a tool call's input request, or skipped it with a message (after the commit,
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { type DeviceFeature, type DeviceLocalPolicySummary, type DevicePolicyArgs } from "@capybara-hq/plugin-sdk";
|
|
2
|
+
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
3
|
+
import { TransactionHost } from "../infra/database/transaction-host.js";
|
|
4
|
+
import type { KernelLogger } from "../log.js";
|
|
5
|
+
import { MachinesService } from "./machines.js";
|
|
6
|
+
import { LocalDeviceRelay } from "./relay.js";
|
|
7
|
+
/** How long the machine may take to apply a policy change. */
|
|
8
|
+
export declare const POLICY_DEADLINE_MS = 30000;
|
|
9
|
+
/** What became of a policy change. */
|
|
10
|
+
export type PolicyChangeOutcome = {
|
|
11
|
+
applied: true;
|
|
12
|
+
policy: DeviceLocalPolicySummary;
|
|
13
|
+
} | {
|
|
14
|
+
applied: false;
|
|
15
|
+
reason: "offline" | "refused" | "unsupported";
|
|
16
|
+
message: string;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Changes a local device's policy on its machine (network ask-to-allow spec §5.2; sandbox dev
|
|
20
|
+
* tiers spec §7.3: its hosts, its `tier`, and `isolation` back to `sandbox`): the kernel→device
|
|
21
|
+
* `policy` op over the {@link LocalDeviceRelay}. The machine is the authority: it
|
|
22
|
+
* refuses widening unless its owner allows remote grants, validates every host and answers with
|
|
23
|
+
* the policy as written, which the kernel then keeps on the active machine's row (§5.4) and
|
|
24
|
+
* audits as `device.policy_changed`.
|
|
25
|
+
*
|
|
26
|
+
* The op is sent outside any transaction (a decision records its outcome afterwards, in its own
|
|
27
|
+
* transaction); only the summary write and the audit row are transactional. Callers decide who
|
|
28
|
+
* may change a device's policy (the device owner, in a signed-in session); this service checks
|
|
29
|
+
* only that the device is a live device of the org.
|
|
30
|
+
*/
|
|
31
|
+
export declare class DevicePolicyService {
|
|
32
|
+
private readonly db;
|
|
33
|
+
readonly txHost: TransactionHost;
|
|
34
|
+
private readonly relay;
|
|
35
|
+
private readonly machines;
|
|
36
|
+
private readonly log;
|
|
37
|
+
constructor(db: KernelDb, txHost: TransactionHost, relay: Pick<LocalDeviceRelay, "call" | "holderLive">, machines: Pick<MachinesService, "activeFor">, log: Pick<KernelLogger, "warn">);
|
|
38
|
+
/**
|
|
39
|
+
* Sends the `policy` op (no transaction may be open), stores the returned summary and audits
|
|
40
|
+
* `device.policy_changed`. Never throws for an offline machine, a refusal or a program without
|
|
41
|
+
* the `policyOp` feature (nothing is sent to it); a device that is not a live device of `orgId`
|
|
42
|
+
* is `device.not_found`.
|
|
43
|
+
*/
|
|
44
|
+
apply(input: {
|
|
45
|
+
orgId: string;
|
|
46
|
+
deviceId: string;
|
|
47
|
+
change: Omit<DevicePolicyArgs, "source">;
|
|
48
|
+
source: DevicePolicyArgs["source"];
|
|
49
|
+
actorTokenId?: string;
|
|
50
|
+
}): Promise<PolicyChangeOutcome>;
|
|
51
|
+
/** The active machine's features and policy summary (null when no machine is connected). */
|
|
52
|
+
summary(deviceId: string): Promise<{
|
|
53
|
+
features: DeviceFeature[];
|
|
54
|
+
policy: DeviceLocalPolicySummary | null;
|
|
55
|
+
} | null>;
|
|
56
|
+
/**
|
|
57
|
+
* Keeps the policy the machine wrote on its row and audits the change (`confirmed`); with no
|
|
58
|
+
* policy (the answer never came) only audits the attempt, unconfirmed. The detail's `isolation`
|
|
59
|
+
* is the one asked for, or the one the machine now reports when it changed (a tier change turns
|
|
60
|
+
* the sandbox back on).
|
|
61
|
+
*/
|
|
62
|
+
private record;
|
|
63
|
+
/** The outcome of a failed op: offline, or the machine's refusal; a deleted device is thrown. */
|
|
64
|
+
private notApplied;
|
|
65
|
+
}
|