@capybara-hq/kernel 0.1.0-rc.6 → 0.1.0-rc.7
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 +27 -3
- package/dist/admin/admin.controller.d.ts +8 -72
- package/dist/admin/admin.controller.js +21 -46
- package/dist/admin/admin.schemas.d.ts +57 -0
- package/dist/admin/admin.schemas.js +50 -0
- package/dist/admin/extensions.controller.d.ts +10 -0
- package/dist/admin/extensions.controller.js +18 -0
- package/dist/admin/extensions.schemas.d.ts +7 -0
- package/dist/admin/extensions.schemas.js +10 -0
- package/dist/admin/limit-defaults.d.ts +20 -0
- package/dist/admin/limit-defaults.js +10 -0
- package/dist/agents/agent-profile.service.d.ts +7 -5
- package/dist/agents/agent-profile.service.js +14 -9
- package/dist/agents/agents.controller.d.ts +7 -287
- package/dist/agents/agents.controller.js +7 -67
- package/dist/agents/agents.schemas.d.ts +389 -0
- package/dist/agents/agents.schemas.js +126 -0
- package/dist/agents/agents.service.d.ts +13 -5
- package/dist/agents/agents.service.js +67 -13
- package/dist/agents/definition.d.ts +47 -19
- package/dist/agents/definition.js +119 -38
- package/dist/agents/from-template.d.ts +2 -2
- package/dist/agents/from-template.js +76 -45
- package/dist/agents/from-template.service.d.ts +12 -0
- package/dist/agents/from-template.service.js +20 -3
- package/dist/agents/models.controller.d.ts +1 -2
- package/dist/agents/models.controller.js +1 -1
- package/dist/agents/org-templates.d.ts +13 -3
- package/dist/agents/org-templates.js +69 -28
- package/dist/agents/pending-connector-requests.d.ts +2 -0
- package/dist/agents/pending-connector-requests.js +1 -1
- package/dist/agents/pending-connectors.controller.d.ts +1 -1
- package/dist/agents/pending-connectors.controller.js +2 -2
- package/dist/agents/pending-connectors.service.d.ts +2 -2
- package/dist/agents/pending-connectors.service.js +19 -19
- package/dist/agents/profile.d.ts +18 -0
- package/dist/agents/profile.js +5 -1
- package/dist/agents/templates.controller.d.ts +8 -17
- package/dist/agents/templates.controller.js +13 -31
- package/dist/agents/templates.schemas.d.ts +20 -0
- package/dist/agents/templates.schemas.js +45 -0
- package/dist/background/background.controller.js +3 -2
- package/dist/background/background.schemas.d.ts +10 -0
- package/dist/background/background.schemas.js +16 -0
- package/dist/background/tasks.service.d.ts +1 -1
- package/dist/background/tasks.service.js +7 -2
- package/dist/catalog/admin-catalog.controller.d.ts +4 -57
- package/dist/catalog/admin-catalog.controller.js +8 -45
- package/dist/catalog/admin-catalog.schemas.d.ts +72 -0
- package/dist/catalog/admin-catalog.schemas.js +92 -0
- package/dist/catalog/catalog-content.d.ts +12 -2
- package/dist/catalog/catalog-scope.service.js +8 -2
- package/dist/catalog/catalog.service.d.ts +2 -0
- package/dist/catalog/catalog.service.js +3 -0
- package/dist/catalog/component-scope.controller.d.ts +3 -65
- package/dist/catalog/component-scope.controller.js +3 -56
- package/dist/catalog/component-scope.schemas.d.ts +114 -0
- package/dist/catalog/component-scope.schemas.js +97 -0
- package/dist/catalog/component-scope.service.d.ts +28 -4
- package/dist/catalog/component-scope.service.js +55 -3
- package/dist/catalog/component-state.d.ts +9 -2
- package/dist/catalog/component-state.js +22 -13
- package/dist/catalog/marketplaces.controller.d.ts +5 -35
- package/dist/catalog/marketplaces.controller.js +6 -34
- package/dist/catalog/marketplaces.schemas.d.ts +48 -0
- package/dist/catalog/marketplaces.schemas.js +53 -0
- package/dist/catalog/marketplaces.service.d.ts +15 -1
- package/dist/catalog/marketplaces.service.js +22 -1
- package/dist/catalog/org-catalog.controller.d.ts +6 -62
- package/dist/catalog/org-catalog.controller.js +12 -66
- package/dist/catalog/org-catalog.schemas.d.ts +79 -0
- package/dist/catalog/org-catalog.schemas.js +82 -0
- package/dist/catalog/org-catalog.service.d.ts +9 -2
- package/dist/catalog/org-catalog.service.js +38 -5
- package/dist/catalog/org-extension.controller.d.ts +1 -12
- package/dist/catalog/org-extension.controller.js +1 -10
- package/dist/catalog/org-extension.schemas.d.ts +15 -0
- package/dist/catalog/org-extension.schemas.js +22 -0
- package/dist/catalog/org-plugin-uploads.controller.d.ts +2 -19
- package/dist/catalog/org-plugin-uploads.controller.js +15 -28
- package/dist/catalog/org-plugin-uploads.schemas.d.ts +20 -0
- package/dist/catalog/org-plugin-uploads.schemas.js +32 -0
- package/dist/catalog/owned-items.d.ts +6 -2
- package/dist/catalog/owned-items.js +16 -4
- package/dist/catalog/platform-components.d.ts +2 -0
- package/dist/catalog/platform-components.js +2 -0
- package/dist/catalog/plugin-import.js +1 -0
- package/dist/catalog/plugin-install.js +1 -1
- package/dist/catalog/requests.service.d.ts +2 -1
- package/dist/catalog/requests.service.js +6 -2
- package/dist/channels/channels.schemas.d.ts +33 -0
- package/dist/channels/channels.schemas.js +34 -0
- package/dist/channels/connections.controller.d.ts +2 -29
- package/dist/channels/connections.controller.js +1 -23
- package/dist/channels/connections.service.d.ts +8 -2
- package/dist/channels/connections.service.js +23 -5
- package/dist/channels/inbound.js +4 -0
- package/dist/conversations/conversations.controller.d.ts +16 -37
- package/dist/conversations/conversations.controller.js +16 -56
- package/dist/conversations/conversations.schemas.d.ts +52 -0
- package/dist/conversations/conversations.schemas.js +79 -0
- package/dist/conversations/conversations.service.d.ts +9 -1
- package/dist/conversations/conversations.service.js +23 -18
- package/dist/conversations/events.d.ts +80 -6
- package/dist/conversations/events.js +60 -5
- package/dist/conversations/message-context.d.ts +28 -0
- package/dist/conversations/message-context.js +56 -0
- package/dist/conversations/queue.d.ts +2 -1
- package/dist/conversations/queue.js +11 -2
- package/dist/db/kernel-schema.d.ts +20 -0
- package/dist/environments/environments.schemas.d.ts +3 -0
- package/dist/environments/environments.schemas.js +14 -0
- package/dist/environments/environments.service.d.ts +16 -4
- package/dist/environments/environments.service.js +58 -13
- package/dist/errors.d.ts +3 -0
- package/dist/errors.js +3 -0
- package/dist/evals/evals.schemas.d.ts +110 -0
- package/dist/evals/evals.schemas.js +107 -0
- package/dist/evals/reconstruct.js +18 -11
- package/dist/evals/recorded-tools.d.ts +2 -1
- package/dist/evals/recorded-tools.js +11 -3
- package/dist/evals/run-replay.d.ts +8 -1
- package/dist/evals/run-replay.js +13 -0
- package/dist/evals/runs.controller.d.ts +2 -57
- package/dist/evals/runs.controller.js +1 -42
- package/dist/evals/runs.service.d.ts +6 -6
- package/dist/evals/runs.service.js +32 -18
- package/dist/evals/sets.controller.d.ts +2 -28
- package/dist/evals/sets.controller.js +1 -31
- package/dist/evals/sets.service.d.ts +7 -7
- package/dist/evals/sets.service.js +23 -17
- package/dist/evals/snapshot.d.ts +3 -2
- package/dist/evals/snapshot.js +17 -4
- package/dist/extensions/admin-ops.d.ts +5 -3
- package/dist/extensions/admin-ops.js +17 -12
- package/dist/extensions/deployment-config.d.ts +16 -1
- package/dist/extensions/deployment-config.js +83 -0
- package/dist/extensions/extensions.module.js +3 -0
- package/dist/extensions/host.d.ts +33 -2
- package/dist/extensions/host.js +107 -1
- package/dist/extensions/installs.d.ts +5 -0
- package/dist/extensions/installs.js +12 -0
- package/dist/extensions/org-config.d.ts +17 -2
- package/dist/extensions/org-config.js +23 -4
- package/dist/extensions/point-defaults.controller.d.ts +2 -8
- package/dist/extensions/point-defaults.controller.js +1 -3
- package/dist/extensions/point-defaults.d.ts +3 -1
- package/dist/extensions/point-defaults.js +4 -2
- package/dist/extensions/point-defaults.schemas.d.ts +9 -0
- package/dist/extensions/point-defaults.schemas.js +14 -0
- package/dist/extensions/unavailable.d.ts +49 -0
- package/dist/extensions/unavailable.js +113 -0
- package/dist/files/previewers.controller.js +2 -3
- package/dist/files/previewers.d.ts +1 -1
- package/dist/files/previewers.js +4 -4
- package/dist/files/previewers.schemas.d.ts +10 -0
- package/dist/files/previewers.schemas.js +9 -0
- package/dist/http/api.module.js +2 -0
- package/dist/identity/accounts.d.ts +43 -4
- package/dist/identity/accounts.js +74 -6
- package/dist/identity/auth.guard.js +10 -1
- package/dist/identity/cookies.d.ts +6 -0
- package/dist/identity/cookies.js +14 -0
- package/dist/identity/identity.module.js +3 -0
- package/dist/identity/initial-passwords.controller.d.ts +22 -0
- package/dist/identity/initial-passwords.controller.js +49 -0
- package/dist/identity/initial-passwords.d.ts +61 -0
- package/dist/identity/initial-passwords.job.d.ts +16 -0
- package/dist/identity/initial-passwords.job.js +46 -0
- package/dist/identity/initial-passwords.js +159 -0
- package/dist/identity/me.controller.d.ts +14 -0
- package/dist/identity/me.controller.js +39 -1
- package/dist/identity/principal.d.ts +8 -0
- package/dist/identity/principal.js +8 -0
- package/dist/identity/settings.d.ts +3 -1
- package/dist/identity/settings.js +6 -4
- package/dist/inbox/inbox.schemas.d.ts +8 -0
- package/dist/inbox/inbox.schemas.js +11 -0
- package/dist/inbox/platform-inbox.controller.d.ts +1 -1
- package/dist/inbox/platform-inbox.controller.js +2 -2
- package/dist/index.d.ts +4 -0
- package/dist/index.js +6 -0
- package/dist/lifecycle/kernel-lifecycle.js +4 -0
- package/dist/models/enablement.d.ts +2 -0
- package/dist/models/enablement.js +1 -0
- package/dist/models/org-models.schemas.d.ts +8 -0
- package/dist/models/org-models.schemas.js +22 -0
- package/dist/models/prices.d.ts +3 -1
- package/dist/models/prices.js +7 -5
- package/dist/models/purposes.d.ts +12 -2
- package/dist/models/purposes.js +22 -8
- package/dist/orgs/orgs.controller.d.ts +2 -5
- package/dist/orgs/orgs.controller.js +3 -6
- package/dist/orgs/orgs.schemas.d.ts +8 -0
- package/dist/orgs/orgs.schemas.js +16 -0
- package/dist/orgs/orgs.service.d.ts +3 -1
- package/dist/orgs/orgs.service.js +6 -4
- package/dist/orgs/settings.service.d.ts +9 -1
- package/dist/orgs/settings.service.js +20 -5
- package/dist/overrides.d.ts +4 -0
- package/dist/overrides.js +2 -0
- package/dist/platform/errors.d.ts +21 -4
- package/dist/platform/errors.js +45 -6
- package/dist/platform/exclusions.d.ts +2 -3
- package/dist/platform/exclusions.js +68 -849
- package/dist/platform/method.js +1 -1
- package/dist/platform/operation.d.ts +82 -5
- package/dist/platform/operation.js +62 -7
- package/dist/platform/ops/accounts.ops.d.ts +32 -0
- package/dist/platform/ops/accounts.ops.js +291 -0
- package/dist/platform/ops/admin.ops.d.ts +36 -0
- package/dist/platform/ops/admin.ops.js +389 -0
- package/dist/platform/ops/agent-skills.ops.d.ts +24 -0
- package/dist/platform/ops/agent-skills.ops.js +226 -0
- package/dist/platform/ops/agent-templates.ops.d.ts +4 -1
- package/dist/platform/ops/agent-templates.ops.js +194 -14
- package/dist/platform/ops/agents.ops.d.ts +19 -1
- package/dist/platform/ops/agents.ops.js +481 -58
- package/dist/platform/ops/approvals.ops.d.ts +30 -0
- package/dist/platform/ops/approvals.ops.js +116 -0
- package/dist/platform/ops/background.ops.d.ts +14 -0
- package/dist/platform/ops/background.ops.js +134 -0
- package/dist/platform/ops/catalog-admin.ops.d.ts +74 -0
- package/dist/platform/ops/catalog-admin.ops.js +587 -0
- package/dist/platform/ops/channels.ops.d.ts +16 -0
- package/dist/platform/ops/channels.ops.js +195 -0
- package/dist/platform/ops/components.ops.d.ts +46 -0
- package/dist/platform/ops/components.ops.js +853 -0
- package/dist/platform/ops/connectors.ops.d.ts +4 -2
- package/dist/platform/ops/connectors.ops.js +68 -6
- package/dist/platform/ops/conversations.ops.d.ts +30 -0
- package/dist/platform/ops/conversations.ops.js +470 -0
- package/dist/platform/ops/environments.ops.d.ts +26 -0
- package/dist/platform/ops/environments.ops.js +289 -0
- package/dist/platform/ops/errors.d.ts +10 -5
- package/dist/platform/ops/errors.js +19 -11
- package/dist/platform/ops/evals.ops.d.ts +28 -0
- package/dist/platform/ops/evals.ops.js +783 -0
- package/dist/platform/ops/extensions-admin.ops.d.ts +25 -0
- package/dist/platform/ops/extensions-admin.ops.js +344 -0
- package/dist/platform/ops/extensions.ops.d.ts +7 -1
- package/dist/platform/ops/extensions.ops.js +248 -17
- package/dist/platform/ops/inbox.ops.d.ts +25 -0
- package/dist/platform/ops/inbox.ops.js +378 -0
- package/dist/platform/ops/marketplaces.ops.d.ts +7 -1
- package/dist/platform/ops/marketplaces.ops.js +326 -17
- package/dist/platform/ops/models.ops.d.ts +25 -0
- package/dist/platform/ops/models.ops.js +232 -0
- package/dist/platform/ops/org-plugins.ops.d.ts +29 -0
- package/dist/platform/ops/org-plugins.ops.js +329 -0
- package/dist/platform/ops/org-settings.ops.d.ts +16 -0
- package/dist/platform/ops/org-settings.ops.js +102 -0
- package/dist/platform/ops/orgs.ops.d.ts +28 -0
- package/dist/platform/ops/orgs.ops.js +295 -0
- package/dist/platform/ops/other-orgs.d.ts +20 -0
- package/dist/platform/ops/other-orgs.js +72 -0
- package/dist/platform/ops/platform.ops.d.ts +4 -4
- package/dist/platform/ops/platform.ops.js +23 -24
- package/dist/platform/ops/plugins.ops.d.ts +10 -8
- package/dist/platform/ops/plugins.ops.js +176 -77
- package/dist/platform/ops/previewers.ops.d.ts +14 -0
- package/dist/platform/ops/previewers.ops.js +109 -0
- package/dist/platform/ops/requests.ops.js +57 -19
- package/dist/platform/ops/skills.ops.d.ts +5 -1
- package/dist/platform/ops/skills.ops.js +129 -11
- package/dist/platform/ops/unavailable.d.ts +23 -0
- package/dist/platform/ops/unavailable.js +111 -0
- package/dist/platform/parity.d.ts +33 -0
- package/dist/platform/parity.js +272 -0
- package/dist/platform/platform-ops.module.d.ts +32 -0
- package/dist/platform/platform-ops.module.js +78 -11
- package/dist/platform/route-schemas.d.ts +18 -0
- package/dist/platform/route-schemas.js +60 -0
- package/dist/roles/worker.module.js +2 -0
- package/dist/runtime/context/build.d.ts +2 -0
- package/dist/runtime/context/build.js +28 -2
- package/dist/runtime/context/compaction.js +10 -1
- package/dist/runtime/context/run-context.d.ts +65 -0
- package/dist/runtime/context/run-context.js +215 -0
- package/dist/runtime/model-call.js +2 -1
- package/dist/runtime/providers.js +8 -1
- package/dist/runtime/run-context.service.d.ts +65 -0
- package/dist/runtime/run-context.service.js +220 -0
- package/dist/runtime/run-worker.d.ts +5 -0
- package/dist/runtime/run-worker.js +31 -6
- package/dist/runtime/runtime.module.js +2 -0
- package/dist/runtime/subagents/definition.d.ts +15 -15
- package/dist/runtime/subagents/definition.js +46 -115
- package/dist/skills/changes.controller.js +2 -1
- package/dist/skills/changes.service.d.ts +1 -1
- package/dist/skills/changes.service.js +4 -4
- package/dist/skills/invocable.controller.d.ts +1 -1
- package/dist/skills/invocable.controller.js +2 -2
- package/dist/skills/invoke.d.ts +2 -2
- package/dist/skills/invoke.js +8 -1
- package/dist/skills/skills.controller.d.ts +4 -13
- package/dist/skills/skills.controller.js +8 -24
- package/dist/skills/skills.schemas.d.ts +48 -0
- package/dist/skills/skills.schemas.js +61 -0
- package/dist/skills/skills.service.d.ts +11 -1
- package/dist/skills/skills.service.js +37 -14
- package/dist/time-zone.d.ts +5 -0
- package/dist/time-zone.js +19 -0
- package/dist/tools/approvals.controller.js +2 -3
- package/dist/tools/approvals.schemas.d.ts +21 -0
- package/dist/tools/approvals.schemas.js +15 -0
- package/dist/tools/builtin-names.d.ts +10 -8
- package/dist/tools/builtin-names.js +16 -11
- package/dist/tools/builtins/builtin-tools.d.ts +3 -1
- package/dist/tools/builtins/builtin-tools.js +15 -3
- package/dist/tools/builtins/current-time.d.ts +26 -0
- package/dist/tools/builtins/current-time.js +99 -0
- package/dist/tools/builtins/platform.d.ts +19 -2
- package/dist/tools/builtins/platform.js +105 -16
- package/dist/tools/connectors.controller.d.ts +1 -2
- package/dist/tools/connectors.controller.js +1 -4
- package/dist/tools/connectors.schemas.d.ts +12 -0
- package/dist/tools/connectors.schemas.js +19 -0
- package/dist/tools/connectors.service.d.ts +5 -2
- package/dist/tools/connectors.service.js +7 -5
- package/dist/tools/org-tool-switches.d.ts +16 -2
- package/dist/tools/org-tool-switches.js +26 -9
- package/dist/tools/pipeline.js +3 -1
- package/dist/tools/registry.d.ts +48 -51
- package/dist/tools/registry.js +222 -233
- package/package.json +3 -3
- package/src/migrations/0090_initial_passwords.sql +27 -0
- package/src/migrations/0091_account_time_zone.sql +4 -0
- package/src/migrations/0092_tools_default_on.sql +27 -0
- package/dist/platform/redact-orgs.d.ts +0 -7
- package/dist/platform/redact-orgs.js +0 -52
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import type { KernelLogger } from "../../log.js";
|
|
1
2
|
import type { OrgSettings } from "../../orgs/settings.service.js";
|
|
2
3
|
import type { ActorFacts } from "../../platform/actor.js";
|
|
3
4
|
import type { AgentDocTopic } from "../../platform/agent-docs.js";
|
|
5
|
+
import { type PlatformOperation } from "../../platform/operation.js";
|
|
4
6
|
import type { PlatformOperations } from "../../platform/registry.js";
|
|
5
7
|
import type { BuiltinTool, CallPolicyContext } from "../registry.js";
|
|
6
8
|
/**
|
|
@@ -9,8 +11,12 @@ import type { BuiltinTool, CallPolicyContext } from "../registry.js";
|
|
|
9
11
|
* - `browse` / `search` / `describe` / `read` only read; their policy is the tool's `allow`.
|
|
10
12
|
* - `call` gets a per-call policy key `Platform:<operation>` ({@link BuiltinTool.callPolicy}): a
|
|
11
13
|
* read runs, a write asks (remembered only for `personal`), an operation that cannot run now is
|
|
12
|
-
* denied with its reason
|
|
13
|
-
*
|
|
14
|
+
* denied with its reason, and so is a write whose `precheck` knows it would fail (spec §14.2
|
|
15
|
+
* item 2: no card). The policy is derived again when an approved call resumes, so a precheck
|
|
16
|
+
* that fails by then returns its error and nothing runs. Right before `op.run` the availability
|
|
17
|
+
* is checked again on fresh facts (the actor may have lost the role while the confirmation
|
|
18
|
+
* waited).
|
|
19
|
+
* - An `ApiError` gets the next step the operation declares for its code and the actor's role.
|
|
14
20
|
* - The actor, the agent and the conversation come from the runtime context, never from input.
|
|
15
21
|
* - Results are JSON text; a list an operation returns is capped at {@link LIST_MAX} entries.
|
|
16
22
|
*/
|
|
@@ -30,5 +36,16 @@ export interface PlatformToolDeps {
|
|
|
30
36
|
};
|
|
31
37
|
/** The org setting `platformTool`. */
|
|
32
38
|
setting(orgId: string): Promise<OrgSettings["platformTool"]>;
|
|
39
|
+
/** How long a precheck may take; default {@link PRECHECK_TIMEOUT_MS} (a test seam). */
|
|
40
|
+
precheckTimeoutMs?: number;
|
|
41
|
+
/** A precheck that throws is logged (warn) and one that times out (debug), with the op id. */
|
|
42
|
+
log?: Pick<KernelLogger, "warn"> & Partial<Pick<KernelLogger, "debug">>;
|
|
33
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* An operation's input keys as `browse` and `search` show them, so a call needs no guess:
|
|
46
|
+
* `"itemId"`, `"agentId, updatedAt, avatar?, quickActions?"` (`?` = optional), `""` when it takes
|
|
47
|
+
* none. A union input lists the keys of every branch; a key is required when every branch requires
|
|
48
|
+
* it. Types, bounds and an example stay in `describe`.
|
|
49
|
+
*/
|
|
50
|
+
export declare function paramsLine(op: PlatformOperation): string;
|
|
34
51
|
export declare function platformTool(deps: PlatformToolDeps): BuiltinTool;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { ToolError } from "@capybara-hq/plugin-sdk";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { availability } from "../../platform/availability.js";
|
|
4
|
-
import { toToolError } from "../../platform/errors.js";
|
|
4
|
+
import { errorRoleOf, errorsFor, nextStepFor, OPERATION_ERROR_NEXT, resolveNext, sentence, toToolError, } from "../../platform/errors.js";
|
|
5
5
|
import { PLATFORM_METHOD } from "../../platform/method.js";
|
|
6
|
-
import { OPERATION_ID, operationDomain, } from "../../platform/operation.js";
|
|
6
|
+
import { OPERATION_ID, operationDomain, PRECHECK_TIMEOUT_MS, } from "../../platform/operation.js";
|
|
7
7
|
import { BUILTIN } from "../builtin-names.js";
|
|
8
8
|
/**
|
|
9
9
|
* The `Platform` builtin (Platform tool spec §3–§6): one tool through which an agent discovers and
|
|
@@ -11,8 +11,12 @@ import { BUILTIN } from "../builtin-names.js";
|
|
|
11
11
|
* - `browse` / `search` / `describe` / `read` only read; their policy is the tool's `allow`.
|
|
12
12
|
* - `call` gets a per-call policy key `Platform:<operation>` ({@link BuiltinTool.callPolicy}): a
|
|
13
13
|
* read runs, a write asks (remembered only for `personal`), an operation that cannot run now is
|
|
14
|
-
* denied with its reason
|
|
15
|
-
*
|
|
14
|
+
* denied with its reason, and so is a write whose `precheck` knows it would fail (spec §14.2
|
|
15
|
+
* item 2: no card). The policy is derived again when an approved call resumes, so a precheck
|
|
16
|
+
* that fails by then returns its error and nothing runs. Right before `op.run` the availability
|
|
17
|
+
* is checked again on fresh facts (the actor may have lost the role while the confirmation
|
|
18
|
+
* waited).
|
|
19
|
+
* - An `ApiError` gets the next step the operation declares for its code and the actor's role.
|
|
16
20
|
* - The actor, the agent and the conversation come from the runtime context, never from input.
|
|
17
21
|
* - Results are JSON text; a list an operation returns is capped at {@link LIST_MAX} entries.
|
|
18
22
|
*/
|
|
@@ -25,11 +29,13 @@ export const PLATFORM_UNAVAILABLE_OFF = "The org turned the Platform tool off; a
|
|
|
25
29
|
const ACTIONS = ["browse", "search", "describe", "call", "read"];
|
|
26
30
|
const SPEC = {
|
|
27
31
|
name: BUILTIN.Platform,
|
|
28
|
-
description: "Discover and use the platform's own operations (
|
|
29
|
-
"
|
|
30
|
-
|
|
31
|
-
'
|
|
32
|
-
|
|
32
|
+
description: "Discover and use the platform's own operations (agents, skills, templates, plugins, " +
|
|
33
|
+
"connectors, extensions, conversations, environments, models, evals, channels, requests, " +
|
|
34
|
+
"approvals and the inbox, org settings, and for admins accounts, orgs and the admin console) " +
|
|
35
|
+
'and its documentation, as the person you are working for. Start with action "browse", which ' +
|
|
36
|
+
'lists every domain, then "describe" an operation before you "call" it; never guess ' +
|
|
37
|
+
'parameters. Writes ask the person to confirm. Use "read" for how-to documentation (plugin ' +
|
|
38
|
+
"format, skills, extension points).",
|
|
33
39
|
inputSchema: {
|
|
34
40
|
type: "object",
|
|
35
41
|
properties: {
|
|
@@ -86,11 +92,43 @@ const firstSentence = (text) => {
|
|
|
86
92
|
};
|
|
87
93
|
const kindOf = (op) => op.confirm === "read" ? "read" : "write";
|
|
88
94
|
const availabilityFields = (a) => a.ok ? { available: true } : { available: false, reason: a.reason };
|
|
95
|
+
/** The most input keys a `params` line names before it ends in `…`. */
|
|
96
|
+
const PARAMS_MAX = 8;
|
|
97
|
+
const paramsCache = new WeakMap();
|
|
98
|
+
/**
|
|
99
|
+
* An operation's input keys as `browse` and `search` show them, so a call needs no guess:
|
|
100
|
+
* `"itemId"`, `"agentId, updatedAt, avatar?, quickActions?"` (`?` = optional), `""` when it takes
|
|
101
|
+
* none. A union input lists the keys of every branch; a key is required when every branch requires
|
|
102
|
+
* it. Types, bounds and an example stay in `describe`.
|
|
103
|
+
*/
|
|
104
|
+
export function paramsLine(op) {
|
|
105
|
+
const cached = paramsCache.get(op);
|
|
106
|
+
if (cached !== undefined)
|
|
107
|
+
return cached;
|
|
108
|
+
const schema = z.toJSONSchema(op.input, {
|
|
109
|
+
io: "input",
|
|
110
|
+
unrepresentable: "any",
|
|
111
|
+
});
|
|
112
|
+
const branches = schema.anyOf ?? schema.oneOf ?? [schema];
|
|
113
|
+
const keys = [];
|
|
114
|
+
for (const b of branches) {
|
|
115
|
+
for (const k of Object.keys(b.properties ?? {}))
|
|
116
|
+
if (!keys.includes(k))
|
|
117
|
+
keys.push(k);
|
|
118
|
+
}
|
|
119
|
+
const required = (k) => branches.every((b) => b.required?.includes(k) ?? false);
|
|
120
|
+
const ordered = [...keys.filter(required), ...keys.filter((k) => !required(k))];
|
|
121
|
+
const names = ordered.map((k) => (required(k) ? k : `${k}?`));
|
|
122
|
+
const text = names.length > PARAMS_MAX ? `${names.slice(0, PARAMS_MAX).join(", ")}, …` : names.join(", ");
|
|
123
|
+
paramsCache.set(op, text);
|
|
124
|
+
return text;
|
|
125
|
+
}
|
|
89
126
|
/** One operation as `browse` and `search` list it. */
|
|
90
127
|
const line = (op, facts) => ({
|
|
91
128
|
id: op.id,
|
|
92
129
|
description: firstSentence(op.description),
|
|
93
130
|
kind: kindOf(op),
|
|
131
|
+
params: paramsLine(op),
|
|
94
132
|
...availabilityFields(availability(op, facts)),
|
|
95
133
|
});
|
|
96
134
|
const capped = (items) => ({
|
|
@@ -115,6 +153,7 @@ const unknownOperationText = (id) => `Unknown operation "${id}". Use browse or s
|
|
|
115
153
|
const missingText = (action, field, what) => `Action ${action} needs "${field}": pass ${what}.`;
|
|
116
154
|
const invalidParamsText = (id, problems) => `Invalid params for ${id}: ${problems}. Call describe with operation "${id}" for its input schema and an example, then call again.`;
|
|
117
155
|
const unavailableOpText = (id, reason) => `Operation ${id} is unavailable, so do not call it again as is: ${reason}`;
|
|
156
|
+
const precheckText = (id, code, message, next) => `Operation ${id} cannot run now: ${code}: ${sentence(message)} ${next ?? OPERATION_ERROR_NEXT}`;
|
|
118
157
|
const outputRefText = (id) => `Operation ${id} writes, and its params hold a {"$output": ...} reference, which the person confirming would see instead of the content. Pass the content inline in params and call again.`;
|
|
119
158
|
/** Whether a value holds a `{"$output": …}` reference anywhere (the pipeline's form). */
|
|
120
159
|
function hasOutputRef(v) {
|
|
@@ -157,13 +196,14 @@ function paramsOf(op, params) {
|
|
|
157
196
|
* The operation context of a confirmation (`confirmFor`, `summary`): the runtime's ids, never
|
|
158
197
|
* input. Nothing aborts it; it only reads.
|
|
159
198
|
*/
|
|
160
|
-
const confirmCtx = (ctx) => ({
|
|
199
|
+
const confirmCtx = (ctx, errorRole) => ({
|
|
161
200
|
orgId: ctx.orgId,
|
|
162
201
|
actorAccountId: ctx.accountId,
|
|
163
202
|
agentId: ctx.agentId,
|
|
164
203
|
conversationId: ctx.conversationId,
|
|
165
204
|
runId: ctx.runId,
|
|
166
205
|
signal: new AbortController().signal,
|
|
206
|
+
errorRole,
|
|
167
207
|
});
|
|
168
208
|
const factsCtx = (ctx) => ({
|
|
169
209
|
orgId: ctx.orgId,
|
|
@@ -198,7 +238,8 @@ export function platformTool(deps) {
|
|
|
198
238
|
return deny(e.message);
|
|
199
239
|
throw e;
|
|
200
240
|
}
|
|
201
|
-
const
|
|
241
|
+
const f = await facts(ctx);
|
|
242
|
+
const verdict = availability(op, f);
|
|
202
243
|
if (!verdict.ok)
|
|
203
244
|
return deny(unavailableOpText(op.id, verdict.reason));
|
|
204
245
|
if (op.confirm === "read")
|
|
@@ -207,7 +248,13 @@ export function platformTool(deps) {
|
|
|
207
248
|
if (hasOutputRef(ctx.rawInput?.params)) {
|
|
208
249
|
return deny(outputRefText(op.id));
|
|
209
250
|
}
|
|
210
|
-
const
|
|
251
|
+
const role = errorRoleOf(f);
|
|
252
|
+
const failed = await precheckOf(op, params, ctx, role, deps.precheckTimeoutMs ?? PRECHECK_TIMEOUT_MS, deps.log);
|
|
253
|
+
if (failed !== null) {
|
|
254
|
+
const next = resolveNext(failed.next, role) ?? nextStepFor(op.errors, failed.code, role);
|
|
255
|
+
return deny(precheckText(op.id, failed.code, failed.message, next));
|
|
256
|
+
}
|
|
257
|
+
const octx = confirmCtx(ctx, role);
|
|
211
258
|
const [cls, summary] = await Promise.all([
|
|
212
259
|
classOf(op, params, octx),
|
|
213
260
|
summaryOf(op, params, octx),
|
|
@@ -216,7 +263,7 @@ export function platformTool(deps) {
|
|
|
216
263
|
key,
|
|
217
264
|
policy: "ask",
|
|
218
265
|
// org / platform writes are confirmed every time (spec §6.2)
|
|
219
|
-
remember: cls === "personal",
|
|
266
|
+
remember: cls === "personal" && op.rememberable !== false,
|
|
220
267
|
summary,
|
|
221
268
|
};
|
|
222
269
|
}
|
|
@@ -280,7 +327,8 @@ export function platformTool(deps) {
|
|
|
280
327
|
confirm: op.confirm,
|
|
281
328
|
inputSchema: z.toJSONSchema(op.input, { io: "input", unrepresentable: "any" }),
|
|
282
329
|
example: op.example,
|
|
283
|
-
...(op.errors !== undefined &&
|
|
330
|
+
...(op.errors !== undefined &&
|
|
331
|
+
op.errors.length > 0 && { errors: errorsFor(op.errors, errorRoleOf(f)) }),
|
|
284
332
|
...availabilityFields(availability(op, f)),
|
|
285
333
|
related: deps.ops
|
|
286
334
|
.inDomain(operationDomain(op.id))
|
|
@@ -292,9 +340,11 @@ export function platformTool(deps) {
|
|
|
292
340
|
const op = operationOf(deps, "call", input.operation);
|
|
293
341
|
const params = paramsOf(op, input.params);
|
|
294
342
|
// fresh facts right before running: the role may be gone since the confirmation (Review Focus 3)
|
|
295
|
-
const
|
|
343
|
+
const f = await facts(factsCtx(ctx));
|
|
344
|
+
const verdict = availability(op, f);
|
|
296
345
|
if (!verdict.ok)
|
|
297
346
|
throw new ToolError(unavailableOpText(op.id, verdict.reason));
|
|
347
|
+
const role = errorRoleOf(f);
|
|
298
348
|
let result;
|
|
299
349
|
try {
|
|
300
350
|
result = await op.run(params, {
|
|
@@ -303,11 +353,15 @@ export function platformTool(deps) {
|
|
|
303
353
|
agentId: ctx.agentId,
|
|
304
354
|
conversationId: ctx.conversationId,
|
|
305
355
|
runId: ctx.runId ?? null,
|
|
356
|
+
callId: ctx.callId,
|
|
306
357
|
signal: ctx.signal,
|
|
358
|
+
errorRole: role,
|
|
307
359
|
});
|
|
308
360
|
}
|
|
309
361
|
catch (e) {
|
|
310
|
-
|
|
362
|
+
// a service refusal after the approval (a race the precheck could not see) still names the
|
|
363
|
+
// next step for this actor (Review Focus 2)
|
|
364
|
+
throw toToolError(e, (code) => nextStepFor(op.errors, code, role));
|
|
311
365
|
}
|
|
312
366
|
return json(asResult(result), { zh: `调用平台操作 ${op.id}`, en: `Called ${op.id}` });
|
|
313
367
|
}
|
|
@@ -348,6 +402,41 @@ async function classOf(op, params, ctx) {
|
|
|
348
402
|
return "org";
|
|
349
403
|
}
|
|
350
404
|
}
|
|
405
|
+
/**
|
|
406
|
+
* The operation's precheck, bounded by `ms`: the failure it found, or null (none, passed, timed
|
|
407
|
+
* out, or threw: the write's own errors speak then; a throw is logged as a warning, a timeout at
|
|
408
|
+
* debug). Its signal aborts at the timeout or when the run's signal aborts.
|
|
409
|
+
*/
|
|
410
|
+
async function precheckOf(op, params, ctx, role, ms, log) {
|
|
411
|
+
if (op.precheck === undefined)
|
|
412
|
+
return null;
|
|
413
|
+
const ac = new AbortController();
|
|
414
|
+
const signal = ctx.signal === undefined ? ac.signal : AbortSignal.any([ac.signal, ctx.signal]);
|
|
415
|
+
let timer;
|
|
416
|
+
const timeout = new Promise((resolve) => {
|
|
417
|
+
timer = setTimeout(() => {
|
|
418
|
+
ac.abort();
|
|
419
|
+
log?.debug?.("platform precheck timed out; the card is shown", { operation: op.id, ms });
|
|
420
|
+
resolve(null);
|
|
421
|
+
}, ms);
|
|
422
|
+
});
|
|
423
|
+
try {
|
|
424
|
+
const r = await Promise.race([
|
|
425
|
+
op.precheck(params, { ...confirmCtx(ctx, role), signal }),
|
|
426
|
+
timeout,
|
|
427
|
+
]);
|
|
428
|
+
if (r === null || r.ok)
|
|
429
|
+
return null;
|
|
430
|
+
return { code: r.code, message: r.message, ...(r.next !== undefined && { next: r.next }) };
|
|
431
|
+
}
|
|
432
|
+
catch (err) {
|
|
433
|
+
log?.warn("platform precheck failed; the card is shown", { operation: op.id, err });
|
|
434
|
+
return null;
|
|
435
|
+
}
|
|
436
|
+
finally {
|
|
437
|
+
clearTimeout(timer);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
351
440
|
/** The card summary of a write, rendered from the validated params and kernel reads. */
|
|
352
441
|
async function summaryOf(op, params, ctx) {
|
|
353
442
|
try {
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { type Principal } from "../identity/principal.js";
|
|
3
3
|
import { type OrgContext } from "../orgs/org.guard.js";
|
|
4
|
+
import { CredentialValue } from "./connectors.schemas.js";
|
|
4
5
|
import { type ConnectorDetail, type ConnectorPreview, type ConnectorSummary, ConnectorsService, type ToolIssue } from "./connectors.service.js";
|
|
5
|
-
/** 凭据值:形状由 `Credentials.validate` 按认证方式校验(不回显值);这里只限大小。 */
|
|
6
|
-
export declare const CredentialValue: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
7
6
|
declare const CreateBody: z.ZodObject<{
|
|
8
7
|
name: z.ZodString;
|
|
9
8
|
slug: z.ZodOptional<z.ZodString>;
|
|
@@ -15,6 +15,7 @@ import { createZodDto } from "../infra/validation/create-zod-dto.js";
|
|
|
15
15
|
import { ZBody } from "../infra/validation/zod-params.js";
|
|
16
16
|
import { CurrentOrg, OrgAction } from "../orgs/org.guard.js";
|
|
17
17
|
import { can } from "../orgs/roles.js";
|
|
18
|
+
import { CredentialValue } from "./connectors.schemas.js";
|
|
18
19
|
import { ConnectorsService, } from "./connectors.service.js";
|
|
19
20
|
import { publicEndpoint } from "./endpoint.js";
|
|
20
21
|
/**
|
|
@@ -34,10 +35,6 @@ function forViewer(org, c) {
|
|
|
34
35
|
}
|
|
35
36
|
return view;
|
|
36
37
|
}
|
|
37
|
-
/** 凭据值:形状由 `Credentials.validate` 按认证方式校验(不回显值);这里只限大小。 */
|
|
38
|
-
export const CredentialValue = z
|
|
39
|
-
.record(z.string().max(100), z.unknown())
|
|
40
|
-
.refine((v) => JSON.stringify(v).length <= 16_384, { message: "Credential is too large" });
|
|
41
38
|
const CreateBody = z
|
|
42
39
|
.object({
|
|
43
40
|
name: z.string().trim().min(1).max(80),
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { RouteSchemas } from "../platform/route-schemas.js";
|
|
3
|
+
/**
|
|
4
|
+
* A credential value: `Credentials.validate` checks its shape by auth method (values are never
|
|
5
|
+
* echoed); this only bounds its size.
|
|
6
|
+
*/
|
|
7
|
+
export declare const CredentialValue: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
8
|
+
/** `:connectorId` as the routes take it (`@Param`). */
|
|
9
|
+
export declare const ConnectorPathParams: z.ZodObject<{
|
|
10
|
+
connectorId: z.ZodString;
|
|
11
|
+
}, z.core.$strip>;
|
|
12
|
+
export declare const CONNECTOR_ROUTES: readonly RouteSchemas[];
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* A credential value: `Credentials.validate` checks its shape by auth method (values are never
|
|
4
|
+
* echoed); this only bounds its size.
|
|
5
|
+
*/
|
|
6
|
+
export const CredentialValue = z
|
|
7
|
+
.record(z.string().max(100), z.unknown())
|
|
8
|
+
.refine((v) => JSON.stringify(v).length <= 16_384, { message: "Credential is too large" });
|
|
9
|
+
/** `:connectorId` as the routes take it (`@Param`). */
|
|
10
|
+
export const ConnectorPathParams = z.object({ connectorId: z.string().min(1) });
|
|
11
|
+
export const CONNECTOR_ROUTES = [
|
|
12
|
+
{ route: "GET /api/v1/orgs/:orgId/connectors" },
|
|
13
|
+
{ route: "GET /api/v1/orgs/:orgId/connectors/:connectorId", params: ConnectorPathParams },
|
|
14
|
+
{ route: "DELETE /api/v1/orgs/:orgId/connectors/:connectorId", params: ConnectorPathParams },
|
|
15
|
+
{
|
|
16
|
+
route: "POST /api/v1/orgs/:orgId/connectors/:connectorId/refresh",
|
|
17
|
+
params: ConnectorPathParams,
|
|
18
|
+
},
|
|
19
|
+
];
|
|
@@ -309,14 +309,16 @@ export declare class ConnectorsService {
|
|
|
309
309
|
/** 改名、启停连接器、工具启停与默认策略、批量把无注解工具改为 allow(`connectors.manage`)。 */
|
|
310
310
|
update(orgId: string, connectorId: string, actorAccountId: string, patch: UpdateConnectorInput, actorTokenId?: string): Promise<ConnectorDetail>;
|
|
311
311
|
/** 软删除,并删除该连接器的全部凭据(`connectors.manage`)。 */
|
|
312
|
-
remove(orgId: string, connectorId: string, actorAccountId: string, actorTokenId?: string): Promise<void>;
|
|
312
|
+
remove(orgId: string, connectorId: string, actorAccountId: string, actorTokenId?: string, auditDetail?: Record<string, unknown>): Promise<void>;
|
|
313
313
|
/**
|
|
314
314
|
* 在调用方事务里软删除连接器(调用方已锁组织行并按需复核角色;应用安装的回滚与卸载用):删全部凭据与授权,
|
|
315
315
|
* 审计 `connector.deleted`(`reason` 并进 detail)。已删除 / 不存在 → `connector.not_found`。
|
|
316
316
|
*/
|
|
317
317
|
removeIn(orgId: string, connectorId: string,
|
|
318
318
|
/** null: the kernel itself (the plugin scope sync uninstalling a plugin). */
|
|
319
|
-
actorAccountId: string | null, actorTokenId?: string, reason?: string
|
|
319
|
+
actorAccountId: string | null, actorTokenId?: string, reason?: string,
|
|
320
|
+
/** Merged into the audit detail (a write made through the Platform tool). */
|
|
321
|
+
auditDetail?: Record<string, unknown>): Promise<void>;
|
|
320
322
|
/**
|
|
321
323
|
* 重新 listTools 并按漂移检测的规则比对写入(见 drift.ts):新增 / 定义变化的工具待复核(旧定义保留供对比),
|
|
322
324
|
* 消失的工具停用;连接器从未拍过快照时首个快照直接启用。
|
|
@@ -326,6 +328,7 @@ export declare class ConnectorsService {
|
|
|
326
328
|
*/
|
|
327
329
|
refresh(orgId: string, connectorId: string, actorAccountId: string, actorTokenId?: string, opts?: {
|
|
328
330
|
trigger?: "first_connect";
|
|
331
|
+
auditDetail?: Record<string, unknown>;
|
|
329
332
|
}): Promise<{
|
|
330
333
|
connector: ConnectorDetail;
|
|
331
334
|
issues: ToolIssue[];
|
|
@@ -960,9 +960,9 @@ let ConnectorsService = class ConnectorsService {
|
|
|
960
960
|
return this.detail(t, orgId, connectorId, actorAccountId);
|
|
961
961
|
}
|
|
962
962
|
/** 软删除,并删除该连接器的全部凭据(`connectors.manage`)。 */
|
|
963
|
-
async remove(orgId, connectorId, actorAccountId, actorTokenId) {
|
|
963
|
+
async remove(orgId, connectorId, actorAccountId, actorTokenId, auditDetail) {
|
|
964
964
|
await this.orgLock.lockAndAuthorize(orgId, actorAccountId, "connectors.manage");
|
|
965
|
-
await this.removeIn(orgId, connectorId, actorAccountId, actorTokenId);
|
|
965
|
+
await this.removeIn(orgId, connectorId, actorAccountId, actorTokenId, undefined, auditDetail);
|
|
966
966
|
}
|
|
967
967
|
/**
|
|
968
968
|
* 在调用方事务里软删除连接器(调用方已锁组织行并按需复核角色;应用安装的回滚与卸载用):删全部凭据与授权,
|
|
@@ -970,7 +970,9 @@ let ConnectorsService = class ConnectorsService {
|
|
|
970
970
|
*/
|
|
971
971
|
async removeIn(orgId, connectorId,
|
|
972
972
|
/** null: the kernel itself (the plugin scope sync uninstalling a plugin). */
|
|
973
|
-
actorAccountId, actorTokenId, reason
|
|
973
|
+
actorAccountId, actorTokenId, reason,
|
|
974
|
+
/** Merged into the audit detail (a write made through the Platform tool). */
|
|
975
|
+
auditDetail) {
|
|
974
976
|
const t = this.db;
|
|
975
977
|
const app = await this.row(t, orgId, connectorId, true);
|
|
976
978
|
await t
|
|
@@ -991,7 +993,7 @@ let ConnectorsService = class ConnectorsService {
|
|
|
991
993
|
orgId,
|
|
992
994
|
action: "connector.deleted",
|
|
993
995
|
target: connectorId,
|
|
994
|
-
detail: { slug: app.slug, ...(reason !== undefined && { reason }) },
|
|
996
|
+
detail: { slug: app.slug, ...(reason !== undefined && { reason }), ...auditDetail },
|
|
995
997
|
});
|
|
996
998
|
}
|
|
997
999
|
/**
|
|
@@ -1033,7 +1035,7 @@ let ConnectorsService = class ConnectorsService {
|
|
|
1033
1035
|
orgId,
|
|
1034
1036
|
action: "connector.tools_refreshed",
|
|
1035
1037
|
target: connectorId,
|
|
1036
|
-
detail: { ...changes, ...(opts.trigger && { trigger: opts.trigger }) },
|
|
1038
|
+
detail: { ...changes, ...(opts.trigger && { trigger: opts.trigger }), ...opts.auditDetail },
|
|
1037
1039
|
});
|
|
1038
1040
|
return {
|
|
1039
1041
|
connector: await this.detail(t, orgId, connectorId, actorAccountId),
|
|
@@ -54,13 +54,22 @@ export declare class OrgToolSwitches {
|
|
|
54
54
|
private offRows;
|
|
55
55
|
/** Every tool the extension registers on this replica with its switch (default on). */
|
|
56
56
|
list(orgId: string, plugin: string): Promise<OrgToolSwitch[]>;
|
|
57
|
+
/**
|
|
58
|
+
* What turning one tool off would affect (nothing written): the agents selecting it and the
|
|
59
|
+
* confirm hash {@link set} takes, or null when it is off already. Unknown tool -> 404
|
|
60
|
+
* `extension.tool_not_found`.
|
|
61
|
+
*/
|
|
62
|
+
previewOff(orgId: string, plugin: string, tool: string): Promise<{
|
|
63
|
+
affectedAgents: AffectedAgent[];
|
|
64
|
+
confirm: string;
|
|
65
|
+
} | null>;
|
|
57
66
|
/** The model-visible keys (`plugin__<extension>__<tool>`) of the tools turned off in the org. */
|
|
58
67
|
offKeys(orgId: string): Promise<Set<string>>;
|
|
59
68
|
/** Whether the org turned off this tool. */
|
|
60
69
|
isToolOff(orgId: string, plugin: string, tool: string): Promise<boolean>;
|
|
61
70
|
/**
|
|
62
71
|
* Switches one tool in the org. On applies at once. Off, while the tool is on: without
|
|
63
|
-
* `confirm` the preview (the org's agents whose current version
|
|
72
|
+
* `confirm` the preview (the org's agents whose current version does not turn it off) and its hash,
|
|
64
73
|
* with the current hash the switch is written (a changed preview -> 409 `plugin.switch_stale`).
|
|
65
74
|
* A tool the extension does not register -> 404 `extension.tool_not_found`. A change writes the
|
|
66
75
|
* audit row `extension.tool_switched`.
|
|
@@ -68,7 +77,12 @@ export declare class OrgToolSwitches {
|
|
|
68
77
|
set(orgId: string, plugin: string, tool: string, enabled: boolean, actor: {
|
|
69
78
|
accountId: string;
|
|
70
79
|
tokenId?: string | undefined;
|
|
80
|
+
/** Merged into the audit detail (a write made through the Platform tool). */
|
|
81
|
+
auditDetail?: Record<string, unknown>;
|
|
71
82
|
}, confirm?: string): Promise<OrgToolSwitchResult>;
|
|
72
|
-
/**
|
|
83
|
+
/**
|
|
84
|
+
* The org's live agents whose current version has extension tool `tool` of `plugin` on: tools
|
|
85
|
+
* are on by default (tools default-on spec §4), so every agent that does not turn it off.
|
|
86
|
+
*/
|
|
73
87
|
private agentsSelecting;
|
|
74
88
|
}
|
|
@@ -11,6 +11,7 @@ import { createHash } from "node:crypto";
|
|
|
11
11
|
import { extensionToolKey } from "@capybara-hq/plugin-sdk";
|
|
12
12
|
import { Inject, Injectable } from "@nestjs/common";
|
|
13
13
|
import { sql } from "kysely";
|
|
14
|
+
import { extensionToolDisabled } from "../agents/definition.js";
|
|
14
15
|
import { ApiError } from "../errors.js";
|
|
15
16
|
import { ExtensionHost } from "../extensions/host.js";
|
|
16
17
|
import { extensionVisibleTo } from "../extensions/org-config.js";
|
|
@@ -88,6 +89,21 @@ let OrgToolSwitches = class OrgToolSwitches {
|
|
|
88
89
|
const off = new Set((await this.offRows(orgId, plugin)).map((r) => r.tool));
|
|
89
90
|
return tools.map((tool) => ({ tool, enabled: !off.has(tool) }));
|
|
90
91
|
}
|
|
92
|
+
/**
|
|
93
|
+
* What turning one tool off would affect (nothing written): the agents selecting it and the
|
|
94
|
+
* confirm hash {@link set} takes, or null when it is off already. Unknown tool -> 404
|
|
95
|
+
* `extension.tool_not_found`.
|
|
96
|
+
*/
|
|
97
|
+
async previewOff(orgId, plugin, tool) {
|
|
98
|
+
const tools = await this.toolsFor(orgId, plugin);
|
|
99
|
+
if (!tools.includes(tool)) {
|
|
100
|
+
throw new ApiError("extension.tool_not_found", `Extension ${plugin} does not register a tool named ${tool}`);
|
|
101
|
+
}
|
|
102
|
+
if (await this.isToolOff(orgId, plugin, tool))
|
|
103
|
+
return null;
|
|
104
|
+
const affectedAgents = await this.agentsSelecting(orgId, plugin, tool);
|
|
105
|
+
return { affectedAgents, confirm: switchOffHash(orgId, plugin, tool, affectedAgents) };
|
|
106
|
+
}
|
|
91
107
|
/** The model-visible keys (`plugin__<extension>__<tool>`) of the tools turned off in the org. */
|
|
92
108
|
async offKeys(orgId) {
|
|
93
109
|
return new Set((await this.offRows(orgId)).map((r) => extensionToolKey(r.plugin, r.tool)));
|
|
@@ -105,7 +121,7 @@ let OrgToolSwitches = class OrgToolSwitches {
|
|
|
105
121
|
}
|
|
106
122
|
/**
|
|
107
123
|
* Switches one tool in the org. On applies at once. Off, while the tool is on: without
|
|
108
|
-
* `confirm` the preview (the org's agents whose current version
|
|
124
|
+
* `confirm` the preview (the org's agents whose current version does not turn it off) and its hash,
|
|
109
125
|
* with the current hash the switch is written (a changed preview -> 409 `plugin.switch_stale`).
|
|
110
126
|
* A tool the extension does not register -> 404 `extension.tool_not_found`. A change writes the
|
|
111
127
|
* audit row `extension.tool_switched`.
|
|
@@ -143,11 +159,14 @@ let OrgToolSwitches = class OrgToolSwitches {
|
|
|
143
159
|
orgId,
|
|
144
160
|
action: "extension.tool_switched",
|
|
145
161
|
target: extensionToolKey(plugin, tool),
|
|
146
|
-
detail: { plugin, tool, from, to: enabled },
|
|
162
|
+
detail: { plugin, tool, from, to: enabled, ...actor.auditDetail },
|
|
147
163
|
});
|
|
148
164
|
return { applied: true };
|
|
149
165
|
}
|
|
150
|
-
/**
|
|
166
|
+
/**
|
|
167
|
+
* The org's live agents whose current version has extension tool `tool` of `plugin` on: tools
|
|
168
|
+
* are on by default (tools default-on spec §4), so every agent that does not turn it off.
|
|
169
|
+
*/
|
|
151
170
|
async agentsSelecting(orgId, plugin, tool) {
|
|
152
171
|
const rows = await this.db
|
|
153
172
|
.selectFrom("agents as a")
|
|
@@ -160,12 +179,10 @@ let OrgToolSwitches = class OrgToolSwitches {
|
|
|
160
179
|
const out = [];
|
|
161
180
|
for (const r of rows) {
|
|
162
181
|
const def = r.definition;
|
|
163
|
-
const
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
});
|
|
168
|
-
if (selects)
|
|
182
|
+
const off = Array.isArray(def?.disabledTools)
|
|
183
|
+
? extensionToolDisabled(def.disabledTools, plugin, tool)
|
|
184
|
+
: false;
|
|
185
|
+
if (!off)
|
|
169
186
|
out.push({ id: r.id, name: typeof def?.name === "string" ? def.name : r.id });
|
|
170
187
|
}
|
|
171
188
|
return out;
|
package/dist/tools/pipeline.js
CHANGED
|
@@ -243,7 +243,8 @@ let ToolPipeline = class ToolPipeline {
|
|
|
243
243
|
// skill invocation in the log → Skill is offered (see skillLoadOffered)
|
|
244
244
|
const skillLoad = await skillLoadOfferedIn(this.deps.db, this.deps.eventLog, ctx.conversationId);
|
|
245
245
|
resolved = await this.deps.registry.forAgent(ctx.orgId, {
|
|
246
|
-
|
|
246
|
+
disabledTools: ctx.agent.disabledTools,
|
|
247
|
+
subagentTools: ctx.agent.subagentTools,
|
|
247
248
|
skillLoad,
|
|
248
249
|
subagents: ctx.agent.subagents,
|
|
249
250
|
child: ctx.parent !== undefined,
|
|
@@ -384,6 +385,7 @@ let ToolPipeline = class ToolPipeline {
|
|
|
384
385
|
conversationId: ctx.conversationId,
|
|
385
386
|
runId: ctx.runId,
|
|
386
387
|
rawInput,
|
|
388
|
+
signal: ctx.signal,
|
|
387
389
|
})) ?? null;
|
|
388
390
|
// a deny with a reason (e.g. an unavailable operation): the reason is the tool error
|
|
389
391
|
if (callPolicy?.policy === "deny" && callPolicy.denyReason !== undefined) {
|