@capybara-hq/kernel 0.1.0-rc.5 → 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 +21 -74
- package/dist/admin/admin.controller.js +50 -50
- 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 +16 -6
- package/dist/agents/agents.service.js +75 -19
- 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 +23 -6
- package/dist/agents/models.controller.d.ts +33 -5
- package/dist/agents/models.controller.js +50 -6
- 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/readiness.controller.d.ts +5 -5
- package/dist/agents/readiness.controller.js +6 -6
- 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/config/schema.d.ts +4 -0
- package/dist/config/schema.js +24 -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 +13 -4
- package/dist/conversations/conversations.service.js +32 -26
- 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/ctx/create-ctx.d.ts +15 -1
- package/dist/ctx/create-ctx.js +23 -2
- package/dist/db/kernel-schema.d.ts +44 -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 +6 -0
- package/dist/errors.js +6 -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 +17 -2
- package/dist/evals/runs.controller.d.ts +2 -57
- package/dist/evals/runs.controller.js +1 -42
- package/dist/evals/runs.service.d.ts +8 -7
- package/dist/evals/runs.service.js +45 -30
- 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/evals/step-replay.d.ts +2 -1
- package/dist/evals/step-replay.js +3 -2
- package/dist/extensions/admin-ops.d.ts +5 -3
- package/dist/extensions/admin-ops.js +17 -12
- package/dist/extensions/config-hash.d.ts +10 -0
- package/dist/extensions/config-hash.js +38 -0
- package/dist/extensions/deployment-config.d.ts +16 -1
- package/dist/extensions/deployment-config.js +83 -0
- package/dist/extensions/extensions.module.js +9 -12
- package/dist/extensions/host.d.ts +39 -12
- package/dist/extensions/host.js +129 -51
- 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/state.module.d.ts +9 -0
- package/dist/extensions/state.module.js +38 -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 +4 -0
- package/dist/http/plugin-dispatch.d.ts +4 -1
- package/dist/http/plugin-dispatch.js +14 -2
- 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/infra/config/kernel-config.service.js +3 -0
- package/dist/infra/events/kernel-events.d.ts +8 -0
- package/dist/lifecycle/kernel-lifecycle.js +4 -0
- package/dist/models/embeddings.d.ts +82 -0
- package/dist/models/embeddings.js +326 -0
- package/dist/models/enablement.controller.d.ts +40 -0
- package/dist/models/enablement.controller.js +74 -0
- package/dist/models/enablement.d.ts +101 -0
- package/dist/models/enablement.js +264 -0
- package/dist/models/models.module.d.ts +5 -1
- package/dist/models/models.module.js +16 -4
- 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 +30 -6
- package/dist/models/purposes.js +68 -17
- 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 -831
- 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/hook-calls.d.ts +8 -1
- package/dist/runtime/hook-calls.js +40 -9
- package/dist/runtime/model-call.d.ts +8 -3
- package/dist/runtime/model-call.js +30 -6
- package/dist/runtime/providers.d.ts +146 -32
- package/dist/runtime/providers.js +328 -67
- 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 +6 -1
- package/dist/runtime/run-worker.js +35 -10
- package/dist/runtime/runtime.module.js +2 -0
- package/dist/runtime/subagents/definition.d.ts +15 -15
- package/dist/runtime/subagents/definition.js +49 -118
- package/dist/runtime/usage-report-jobs.d.ts +88 -0
- package/dist/runtime/usage-report-jobs.js +158 -0
- package/dist/runtime/usage-report.d.ts +33 -38
- package/dist/runtime/usage-report.js +152 -84
- 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 +9 -1
- package/dist/tools/registry.d.ts +48 -51
- package/dist/tools/registry.js +222 -233
- package/package.json +3 -3
- package/src/migrations/0089_model_kinds_usage.sql +38 -0
- 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
package/dist/index.d.ts
CHANGED
|
@@ -63,6 +63,10 @@ export { type ContextJob, type JobWrapper, type LogContext, logContext, setJobWr
|
|
|
63
63
|
export { type Org, OrgsService } from "./orgs/orgs.service.js";
|
|
64
64
|
export type { KernelOverride } from "./overrides.js";
|
|
65
65
|
export { fetchNpmPackage, IntegrityMismatchError, type NpmFetchConfig, NpmFetchError, PackageTooLargeError, } from "./packages/npm.js";
|
|
66
|
+
export { checkInputParity, inputParity, type ParityFinding, type ParityOperation, } from "./platform/parity.js";
|
|
67
|
+
export { PLATFORM_OPERATION_PROVIDERS } from "./platform/platform-ops.module.js";
|
|
68
|
+
export { PlatformOperations } from "./platform/registry.js";
|
|
69
|
+
export { ROUTE_SCHEMAS, type RouteSchemas } from "./platform/route-schemas.js";
|
|
66
70
|
export { UNKNOWN_RESULT_TEXT } from "./runtime/context/pairing.js";
|
|
67
71
|
export type { AgentLoop, LoopContext, LoopOutcome } from "./runtime/loop.js";
|
|
68
72
|
export { MAINTENANCE_QUEUE_NAME } from "./runtime/maintenance-queue.js";
|
package/dist/index.js
CHANGED
|
@@ -60,6 +60,12 @@ export { createConfiguredLogger, loggerOptionsFromConfig } from "./log-config.js
|
|
|
60
60
|
export { logContext, setJobWrapper, setTraceContextSource, withJobContext, withLogContext, } from "./log-context.js";
|
|
61
61
|
export { OrgsService } from "./orgs/orgs.service.js";
|
|
62
62
|
export { fetchNpmPackage, IntegrityMismatchError, NpmFetchError, PackageTooLargeError, } from "./packages/npm.js";
|
|
63
|
+
// Test seam: the Platform input-parity test in tools/checks (no runtime caller).
|
|
64
|
+
export { checkInputParity, inputParity, } from "./platform/parity.js";
|
|
65
|
+
// Test seam (the parity test builds every operation from these without a Nest app).
|
|
66
|
+
export { PLATFORM_OPERATION_PROVIDERS } from "./platform/platform-ops.module.js";
|
|
67
|
+
export { PlatformOperations } from "./platform/registry.js";
|
|
68
|
+
export { ROUTE_SCHEMAS } from "./platform/route-schemas.js";
|
|
63
69
|
export { UNKNOWN_RESULT_TEXT } from "./runtime/context/pairing.js";
|
|
64
70
|
export { MAINTENANCE_QUEUE_NAME } from "./runtime/maintenance-queue.js";
|
|
65
71
|
export { runJobId } from "./runtime/run-queue.js";
|
|
@@ -28,6 +28,9 @@ const HOT_APPLIERS = {
|
|
|
28
28
|
"auth.trustedIdentitySources": () => { },
|
|
29
29
|
// The hook registry reads the time limit on every run.
|
|
30
30
|
"hooks.timeoutMs": () => { },
|
|
31
|
+
// The provider registry reads the list time limit at every listModels call.
|
|
32
|
+
"models.listTimeoutMs": () => { },
|
|
33
|
+
"models.embedTimeoutMs": () => { },
|
|
31
34
|
// SandboxService reads the shared-lease cap at every acquisition.
|
|
32
35
|
"sandbox.maxConcurrentCommands": () => { },
|
|
33
36
|
// The environments service reads the personal limit at every create.
|
|
@@ -95,6 +95,14 @@ export interface KernelEventMap {
|
|
|
95
95
|
"background_task.finished": {
|
|
96
96
|
conversationId: string;
|
|
97
97
|
};
|
|
98
|
+
/**
|
|
99
|
+
* An extension's `ctx.models.embed` call wrote a `model_usage` row (after the commit, spec B
|
|
100
|
+
* §5.4). The usage reporter enqueues its `usage.report` delivery; a lost event is re-derived by
|
|
101
|
+
* the usage sweep (rows whose `reported_at` is still null).
|
|
102
|
+
*/
|
|
103
|
+
"model_usage.recorded": {
|
|
104
|
+
id: string;
|
|
105
|
+
};
|
|
98
106
|
}
|
|
99
107
|
type Handler<K extends keyof KernelEventMap> = (payload: KernelEventMap[K]) => Promise<void> | void;
|
|
100
108
|
/** Typed in-process event emitter; handlers run in order, a failing one is logged and skipped. */
|
|
@@ -26,6 +26,7 @@ import { ExtensionRegistry } from "../extensions/registry.js";
|
|
|
26
26
|
import { ReplicaStatusStore } from "../extensions/sources.js";
|
|
27
27
|
import { syncPackage } from "../extensions/sync.js";
|
|
28
28
|
import { AccountsService } from "../identity/accounts.js";
|
|
29
|
+
import { insecurePublicUrlWarning } from "../identity/cookies.js";
|
|
29
30
|
import { waitWithin } from "../infra/close-within.js";
|
|
30
31
|
import { KernelConfigService } from "../infra/config/kernel-config.service.js";
|
|
31
32
|
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
@@ -277,6 +278,9 @@ let KernelLifecycle = class KernelLifecycle {
|
|
|
277
278
|
this.listening = await this.shutdown.trackInFlight(this.http.listen(port));
|
|
278
279
|
this.checkpoint();
|
|
279
280
|
this.log.info("kernel started", { roles: this.config.roles, port: this.listening });
|
|
281
|
+
const insecure = insecurePublicUrlWarning(this.config);
|
|
282
|
+
if (insecure !== null)
|
|
283
|
+
this.log.warn(insecure);
|
|
280
284
|
await this.warnIfSetupPending();
|
|
281
285
|
return this.listening;
|
|
282
286
|
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { type ExtensionEmbedRequest, type ExtensionEmbedResult, type ExtensionModelTarget, type ExtensionPermissions, type Logger } from "@capybara-hq/plugin-sdk";
|
|
2
|
+
import { KernelConfigService } from "../infra/config/kernel-config.service.js";
|
|
3
|
+
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
4
|
+
import { TransactionHost } from "../infra/database/transaction-host.js";
|
|
5
|
+
import { KernelEvents } from "../infra/events/kernel-events.js";
|
|
6
|
+
import { type HookRunner } from "../runtime/hook-calls.js";
|
|
7
|
+
import { ProviderRegistry } from "../runtime/providers.js";
|
|
8
|
+
import { ModelPurposesService } from "./purposes.js";
|
|
9
|
+
/** An extension's `permissions.models` (what it declared, as approved in its manifest). */
|
|
10
|
+
export type DeclaredModelPurposes = readonly NonNullable<ExtensionPermissions["models"]>[number][];
|
|
11
|
+
/** Most texts one `ctx.models.embed` call may carry (the kernel splits them by `maxBatch`). */
|
|
12
|
+
export declare const EMBED_MAX_INPUTS = 2048;
|
|
13
|
+
/**
|
|
14
|
+
* The `ctx.models` broker for embeddings (model platform spec B §5.4). Every call:
|
|
15
|
+
* - accepts only a purpose the calling extension declared in `permissions.models` with
|
|
16
|
+
* `kind: "embedding"` (`model.purpose_unknown` otherwise: the manifest is what was approved), for
|
|
17
|
+
* an org that enabled the extension (`extension.not_enabled`);
|
|
18
|
+
* - resolves the org's effective target ({@link ModelPurposesService.resolve}: unmapped, or mapped
|
|
19
|
+
* to a model the org cannot use, is `model.unconfigured`) and the model in the org's view, enabled
|
|
20
|
+
* and of kind `embedding` ({@link ProviderRegistry.resolve}, bound to the org's effective config);
|
|
21
|
+
* - fires `model.request` once (`purpose: "embedding"`, every text of the call, no conversation
|
|
22
|
+
* fields) through the host's hook registry before anything is sent; a policy denial (a deny, a
|
|
23
|
+
* hook error or timeout, a policy extension not loaded here or without a valid config in the org)
|
|
24
|
+
* writes one `hook.denied` audit row and rejects with `ApiError("model.hook_denied")` (403) whose
|
|
25
|
+
* message is the one a denied run step fails with: no provider call, no usage row. A call with no input sends nothing
|
|
26
|
+
* and fires nothing;
|
|
27
|
+
* - splits the input into batches of the model's `maxBatch`, calls the provider's `embed` once per
|
|
28
|
+
* batch in order with the extension's signal (plus the request's own `signal`), each batch
|
|
29
|
+
* limited by `models.embedTimeoutMs` (`ModelError("timeout")`), checks each result ({@link validateEmbedResult}: a
|
|
30
|
+
* wrong count, dimension or a non-finite number is a `ModelError` of kind `server`), and
|
|
31
|
+
* concatenates the vectors; no retries (an extension retries itself if it wants to);
|
|
32
|
+
* - writes one `model_usage` row (the sum of the batches' input tokens) and announces it after the
|
|
33
|
+
* commit (`model_usage.recorded`: the usage reporter's `ModelUsageJobs` enqueues its
|
|
34
|
+
* `usage.report` delivery; the usage sweep catches up a lost one). A call that fails after the
|
|
35
|
+
* provider answered some batches (an invalid result, a later batch failing) still records their
|
|
36
|
+
* input tokens before the error reaches the extension; one that fails before any answer records
|
|
37
|
+
* nothing.
|
|
38
|
+
* Purpose params are not sent: an `embed` request carries none (`EmbedRequest`).
|
|
39
|
+
*/
|
|
40
|
+
export declare class ModelEmbeddings {
|
|
41
|
+
private readonly kdb;
|
|
42
|
+
readonly txHost: TransactionHost;
|
|
43
|
+
private readonly purposes;
|
|
44
|
+
private readonly providers;
|
|
45
|
+
/** `model_usage.recorded`: the usage reporter enqueues the row's delivery. */
|
|
46
|
+
private readonly events;
|
|
47
|
+
private readonly log;
|
|
48
|
+
/** `models.embedTimeoutMs` (hot). */
|
|
49
|
+
private readonly config;
|
|
50
|
+
constructor(kdb: KernelDb, txHost: TransactionHost, purposes: Pick<ModelPurposesService, "resolve">, providers: Pick<ProviderRegistry, "resolve">,
|
|
51
|
+
/** `model_usage.recorded`: the usage reporter enqueues the row's delivery. */
|
|
52
|
+
events: Pick<KernelEvents, "emit">, log: Pick<Logger, "warn">,
|
|
53
|
+
/** `models.embedTimeoutMs` (hot). */
|
|
54
|
+
config: Pick<KernelConfigService, "get">);
|
|
55
|
+
/** Refuses a purpose `plugin` did not declare with kind `embedding`, or an org it is off in. */
|
|
56
|
+
private admit;
|
|
57
|
+
/** The org's target for the purpose and the model bound to the org's config. */
|
|
58
|
+
private target;
|
|
59
|
+
/**
|
|
60
|
+
* One batch to the provider, limited by `models.embedTimeoutMs` (hot, read per call): at the limit
|
|
61
|
+
* the call's signal aborts and the batch fails with `ModelError("timeout")`, even when the
|
|
62
|
+
* provider ignores the signal (its late answer is dropped).
|
|
63
|
+
*/
|
|
64
|
+
private callWithTimeout;
|
|
65
|
+
/**
|
|
66
|
+
* `ctx.models.embed` for `plugin` (its declared purposes), aborted by `signal`; `hooks` is the
|
|
67
|
+
* host's hook registry (`model.request`), absent only for a ctx built without a host (tests).
|
|
68
|
+
*/
|
|
69
|
+
embed(plugin: string, declared: DeclaredModelPurposes, request: ExtensionEmbedRequest, signal: AbortSignal, hooks: HookRunner | undefined): Promise<ExtensionEmbedResult>;
|
|
70
|
+
/**
|
|
71
|
+
* `model.request` for an embed call (policy hooks may deny it). Rejects with the caller's abort
|
|
72
|
+
* reason when `signal` aborts while the hooks run (an abort is never a deny).
|
|
73
|
+
*/
|
|
74
|
+
private checkHooks;
|
|
75
|
+
/** `ctx.models.describe` for `plugin`: null when the purpose maps to no model the org can use. */
|
|
76
|
+
describe(plugin: string, declared: DeclaredModelPurposes, req: {
|
|
77
|
+
orgId: string;
|
|
78
|
+
purpose: string;
|
|
79
|
+
}): Promise<ExtensionModelTarget | null>;
|
|
80
|
+
/** One `model_usage` row; its `usage.report` delivery is enqueued after the commit. */
|
|
81
|
+
private record;
|
|
82
|
+
}
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
8
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
9
|
+
};
|
|
10
|
+
import { ModelError, validateEmbedResult, } from "@capybara-hq/plugin-sdk";
|
|
11
|
+
import { Inject, Injectable } from "@nestjs/common";
|
|
12
|
+
import { ApiError } from "../errors.js";
|
|
13
|
+
import { isExtensionEnabled } from "../extensions/enabled.js";
|
|
14
|
+
import { audit } from "../identity/audit.js";
|
|
15
|
+
import { KernelConfigService } from "../infra/config/kernel-config.service.js";
|
|
16
|
+
import { afterCommit } from "../infra/database/after-commit.js";
|
|
17
|
+
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
18
|
+
import { TransactionHost } from "../infra/database/transaction-host.js";
|
|
19
|
+
import { Transactional } from "../infra/database/transactional.decorator.js";
|
|
20
|
+
import { KernelEvents } from "../infra/events/kernel-events.js";
|
|
21
|
+
import { KERNEL_LOGGER } from "../infra/tokens.js";
|
|
22
|
+
import { embeddingDeniedAudit } from "../runtime/hook-calls.js";
|
|
23
|
+
import { modelDeniedText } from "../runtime/model-call.js";
|
|
24
|
+
import { ProviderRegistry } from "../runtime/providers.js";
|
|
25
|
+
import { ModelPurposesService } from "./purposes.js";
|
|
26
|
+
/** Most texts one `ctx.models.embed` call may carry (the kernel splits them by `maxBatch`). */
|
|
27
|
+
export const EMBED_MAX_INPUTS = 2048;
|
|
28
|
+
/**
|
|
29
|
+
* The `ctx.models` broker for embeddings (model platform spec B §5.4). Every call:
|
|
30
|
+
* - accepts only a purpose the calling extension declared in `permissions.models` with
|
|
31
|
+
* `kind: "embedding"` (`model.purpose_unknown` otherwise: the manifest is what was approved), for
|
|
32
|
+
* an org that enabled the extension (`extension.not_enabled`);
|
|
33
|
+
* - resolves the org's effective target ({@link ModelPurposesService.resolve}: unmapped, or mapped
|
|
34
|
+
* to a model the org cannot use, is `model.unconfigured`) and the model in the org's view, enabled
|
|
35
|
+
* and of kind `embedding` ({@link ProviderRegistry.resolve}, bound to the org's effective config);
|
|
36
|
+
* - fires `model.request` once (`purpose: "embedding"`, every text of the call, no conversation
|
|
37
|
+
* fields) through the host's hook registry before anything is sent; a policy denial (a deny, a
|
|
38
|
+
* hook error or timeout, a policy extension not loaded here or without a valid config in the org)
|
|
39
|
+
* writes one `hook.denied` audit row and rejects with `ApiError("model.hook_denied")` (403) whose
|
|
40
|
+
* message is the one a denied run step fails with: no provider call, no usage row. A call with no input sends nothing
|
|
41
|
+
* and fires nothing;
|
|
42
|
+
* - splits the input into batches of the model's `maxBatch`, calls the provider's `embed` once per
|
|
43
|
+
* batch in order with the extension's signal (plus the request's own `signal`), each batch
|
|
44
|
+
* limited by `models.embedTimeoutMs` (`ModelError("timeout")`), checks each result ({@link validateEmbedResult}: a
|
|
45
|
+
* wrong count, dimension or a non-finite number is a `ModelError` of kind `server`), and
|
|
46
|
+
* concatenates the vectors; no retries (an extension retries itself if it wants to);
|
|
47
|
+
* - writes one `model_usage` row (the sum of the batches' input tokens) and announces it after the
|
|
48
|
+
* commit (`model_usage.recorded`: the usage reporter's `ModelUsageJobs` enqueues its
|
|
49
|
+
* `usage.report` delivery; the usage sweep catches up a lost one). A call that fails after the
|
|
50
|
+
* provider answered some batches (an invalid result, a later batch failing) still records their
|
|
51
|
+
* input tokens before the error reaches the extension; one that fails before any answer records
|
|
52
|
+
* nothing.
|
|
53
|
+
* Purpose params are not sent: an `embed` request carries none (`EmbedRequest`).
|
|
54
|
+
*/
|
|
55
|
+
let ModelEmbeddings = class ModelEmbeddings {
|
|
56
|
+
kdb;
|
|
57
|
+
txHost;
|
|
58
|
+
purposes;
|
|
59
|
+
providers;
|
|
60
|
+
events;
|
|
61
|
+
log;
|
|
62
|
+
config;
|
|
63
|
+
constructor(kdb, txHost, purposes, providers,
|
|
64
|
+
/** `model_usage.recorded`: the usage reporter enqueues the row's delivery. */
|
|
65
|
+
events, log,
|
|
66
|
+
/** `models.embedTimeoutMs` (hot). */
|
|
67
|
+
config) {
|
|
68
|
+
this.kdb = kdb;
|
|
69
|
+
this.txHost = txHost;
|
|
70
|
+
this.purposes = purposes;
|
|
71
|
+
this.providers = providers;
|
|
72
|
+
this.events = events;
|
|
73
|
+
this.log = log;
|
|
74
|
+
this.config = config;
|
|
75
|
+
}
|
|
76
|
+
/** Refuses a purpose `plugin` did not declare with kind `embedding`, or an org it is off in. */
|
|
77
|
+
async admit(plugin, declared, orgId, purpose) {
|
|
78
|
+
if (!declared.some((d) => d.purpose === purpose && d.kind === "embedding")) {
|
|
79
|
+
throw new ApiError("model.purpose_unknown", `Extension ${plugin} declared no embedding purpose "${purpose}" in permissions.models`);
|
|
80
|
+
}
|
|
81
|
+
if (!(await isExtensionEnabled(this.kdb.db, orgId, plugin))) {
|
|
82
|
+
throw new ApiError("extension.not_enabled", `Extension ${plugin} is not enabled in organization ${orgId}`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/** The org's target for the purpose and the model bound to the org's config. */
|
|
86
|
+
async target(orgId, purpose) {
|
|
87
|
+
const target = await this.purposes.resolve(orgId, purpose);
|
|
88
|
+
const { provider, info } = await this.providers.resolve(orgId, target.model, {
|
|
89
|
+
kind: "embedding",
|
|
90
|
+
});
|
|
91
|
+
if (info.embedding === undefined || provider.embed === undefined) {
|
|
92
|
+
// the registry drops such models from the list; kept as a guard
|
|
93
|
+
throw new ApiError("model.unconfigured", `The model configured for the "${purpose}" purpose cannot embed`);
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
ref: target.model,
|
|
97
|
+
info: info.embedding,
|
|
98
|
+
embed: provider.embed.bind(provider),
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* One batch to the provider, limited by `models.embedTimeoutMs` (hot, read per call): at the limit
|
|
103
|
+
* the call's signal aborts and the batch fails with `ModelError("timeout")`, even when the
|
|
104
|
+
* provider ignores the signal (its late answer is dropped).
|
|
105
|
+
*/
|
|
106
|
+
async callWithTimeout(embed, batch, signal, model) {
|
|
107
|
+
const ms = this.config.get().models.embedTimeoutMs;
|
|
108
|
+
const timer = new AbortController();
|
|
109
|
+
const both = AbortSignal.any([signal, timer.signal]);
|
|
110
|
+
let handle;
|
|
111
|
+
let onAbort;
|
|
112
|
+
const call = Promise.resolve().then(() => embed(batch, { signal: both }));
|
|
113
|
+
call.catch(() => { });
|
|
114
|
+
try {
|
|
115
|
+
return await Promise.race([
|
|
116
|
+
call,
|
|
117
|
+
new Promise((_, reject) => {
|
|
118
|
+
handle = setTimeout(() => {
|
|
119
|
+
const err = new ModelError("timeout", `Model ${model.provider}/${model.id} did not answer an embed call within ${ms} ms`);
|
|
120
|
+
timer.abort(err);
|
|
121
|
+
reject(err);
|
|
122
|
+
}, ms);
|
|
123
|
+
onAbort = () => reject(signal.reason);
|
|
124
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
125
|
+
}),
|
|
126
|
+
]);
|
|
127
|
+
}
|
|
128
|
+
finally {
|
|
129
|
+
clearTimeout(handle);
|
|
130
|
+
// ctx.signal lives as long as the instance: never leave a listener per batch on it
|
|
131
|
+
if (onAbort)
|
|
132
|
+
signal.removeEventListener("abort", onAbort);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* `ctx.models.embed` for `plugin` (its declared purposes), aborted by `signal`; `hooks` is the
|
|
137
|
+
* host's hook registry (`model.request`), absent only for a ctx built without a host (tests).
|
|
138
|
+
*/
|
|
139
|
+
async embed(plugin, declared, request, signal, hooks) {
|
|
140
|
+
checkRequest(request);
|
|
141
|
+
// a copy, read once: the texts the hooks see are the texts sent, whatever the extension does
|
|
142
|
+
// with its own request object meanwhile
|
|
143
|
+
const req = { ...request, input: request.input.slice() };
|
|
144
|
+
await this.admit(plugin, declared, req.orgId, req.purpose);
|
|
145
|
+
const t = await this.target(req.orgId, req.purpose);
|
|
146
|
+
const dimensions = req.dimensions ?? t.info.defaultDimensions;
|
|
147
|
+
if (!t.info.dimensions.includes(dimensions)) {
|
|
148
|
+
throw new ApiError("validation_failed", `Model ${t.ref.provider}/${t.ref.model} cannot produce ${dimensions} dimensions (it offers ${t.info.dimensions.join(", ")})`);
|
|
149
|
+
}
|
|
150
|
+
const model = { provider: t.ref.provider, id: t.ref.model };
|
|
151
|
+
if (req.input.length === 0)
|
|
152
|
+
return { vectors: [], model, dimensions };
|
|
153
|
+
const vectors = [];
|
|
154
|
+
/** Input tokens of the batches the provider answered (billed even if the call fails later). */
|
|
155
|
+
let inputTokens = 0;
|
|
156
|
+
let answered = 0;
|
|
157
|
+
const size = Math.max(1, t.info.maxBatch);
|
|
158
|
+
// the instance's signal (revocation) and the caller's own (e.g. its tool call aborted)
|
|
159
|
+
const callSignal = req.signal ? AbortSignal.any([signal, req.signal]) : signal;
|
|
160
|
+
await this.checkHooks(hooks, plugin, req, model, callSignal);
|
|
161
|
+
try {
|
|
162
|
+
for (let i = 0; i < req.input.length; i += size) {
|
|
163
|
+
callSignal.throwIfAborted();
|
|
164
|
+
const batch = {
|
|
165
|
+
model: t.ref.model,
|
|
166
|
+
input: req.input.slice(i, i + size),
|
|
167
|
+
...(req.dimensions !== undefined && { dimensions: req.dimensions }),
|
|
168
|
+
...(req.inputType !== undefined && { inputType: req.inputType }),
|
|
169
|
+
};
|
|
170
|
+
const res = await this.callWithTimeout(t.embed, batch, callSignal, model);
|
|
171
|
+
answered++;
|
|
172
|
+
inputTokens += tokensOf(res);
|
|
173
|
+
const problem = checkResult(batch, t.info, res);
|
|
174
|
+
if (problem !== null) {
|
|
175
|
+
throw new ModelError("server", `Model ${model.provider}/${model.id} returned an invalid embedding: ${problem}`);
|
|
176
|
+
}
|
|
177
|
+
for (const v of res.vectors)
|
|
178
|
+
vectors.push(v);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
catch (err) {
|
|
182
|
+
// the batches already answered were billed by the provider: recorded, then the error
|
|
183
|
+
if (answered > 0) {
|
|
184
|
+
await this.record(plugin, req.orgId, req.purpose, model, inputTokens).catch((e) => this.log.warn("cannot record the usage of a failed embed call", {
|
|
185
|
+
plugin,
|
|
186
|
+
orgId: req.orgId,
|
|
187
|
+
err: e,
|
|
188
|
+
}));
|
|
189
|
+
}
|
|
190
|
+
throw err;
|
|
191
|
+
}
|
|
192
|
+
await this.record(plugin, req.orgId, req.purpose, model, inputTokens);
|
|
193
|
+
return { vectors, model, dimensions };
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* `model.request` for an embed call (policy hooks may deny it). Rejects with the caller's abort
|
|
197
|
+
* reason when `signal` aborts while the hooks run (an abort is never a deny).
|
|
198
|
+
*/
|
|
199
|
+
async checkHooks(hooks, plugin, req, model, signal) {
|
|
200
|
+
if (!hooks?.has("model.request"))
|
|
201
|
+
return;
|
|
202
|
+
const call = {
|
|
203
|
+
purpose: "embedding",
|
|
204
|
+
orgId: req.orgId,
|
|
205
|
+
extension: plugin,
|
|
206
|
+
embeddingPurpose: req.purpose,
|
|
207
|
+
provider: model.provider,
|
|
208
|
+
model: model.id,
|
|
209
|
+
input: req.input,
|
|
210
|
+
...(req.dimensions !== undefined && { dimensions: req.dimensions }),
|
|
211
|
+
...(req.inputType !== undefined && { inputType: req.inputType }),
|
|
212
|
+
};
|
|
213
|
+
const verdict = await hooks.run("model.request", call, signal);
|
|
214
|
+
if (verdict.allowed)
|
|
215
|
+
return;
|
|
216
|
+
await audit(this.kdb.db, embeddingDeniedAudit(call, verdict));
|
|
217
|
+
this.log.warn("embed call blocked by a policy hook", {
|
|
218
|
+
plugin,
|
|
219
|
+
orgId: req.orgId,
|
|
220
|
+
hookPlugin: verdict.plugin,
|
|
221
|
+
cause: verdict.cause,
|
|
222
|
+
});
|
|
223
|
+
throw new ApiError("model.hook_denied", modelDeniedText(verdict.plugin, verdict.reason));
|
|
224
|
+
}
|
|
225
|
+
/** `ctx.models.describe` for `plugin`: null when the purpose maps to no model the org can use. */
|
|
226
|
+
async describe(plugin, declared, req) {
|
|
227
|
+
if (typeof req?.orgId !== "string" || typeof req.purpose !== "string") {
|
|
228
|
+
throw new ApiError("validation_failed", "describe needs orgId and purpose strings");
|
|
229
|
+
}
|
|
230
|
+
await this.admit(plugin, declared, req.orgId, req.purpose);
|
|
231
|
+
try {
|
|
232
|
+
const t = await this.target(req.orgId, req.purpose);
|
|
233
|
+
return {
|
|
234
|
+
provider: t.ref.provider,
|
|
235
|
+
id: t.ref.model,
|
|
236
|
+
kind: "embedding",
|
|
237
|
+
embedding: structuredClone(t.info),
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
catch (e) {
|
|
241
|
+
if (e instanceof ApiError && e.code === "model.unconfigured")
|
|
242
|
+
return null;
|
|
243
|
+
throw e;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
/** One `model_usage` row; its `usage.report` delivery is enqueued after the commit. */
|
|
247
|
+
async record(plugin, orgId, purpose, model, inputTokens) {
|
|
248
|
+
const row = await this.kdb.db
|
|
249
|
+
.insertInto("model_usage")
|
|
250
|
+
.values({
|
|
251
|
+
org_id: orgId,
|
|
252
|
+
extension: plugin,
|
|
253
|
+
purpose,
|
|
254
|
+
provider: model.provider,
|
|
255
|
+
model: model.id,
|
|
256
|
+
input_tokens: Math.round(inputTokens),
|
|
257
|
+
})
|
|
258
|
+
.returning("id")
|
|
259
|
+
.executeTakeFirstOrThrow();
|
|
260
|
+
// fire and forget: the extension's call never waits on the enqueue (PG, Redis); a lost one is
|
|
261
|
+
// caught up by the usage sweep
|
|
262
|
+
afterCommit(() => {
|
|
263
|
+
void this.events
|
|
264
|
+
.emit("model_usage.recorded", { id: row.id })
|
|
265
|
+
.catch((err) => this.log.warn("model usage event failed", { usageId: row.id, err }));
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
__decorate([
|
|
270
|
+
Transactional()
|
|
271
|
+
], ModelEmbeddings.prototype, "record", null);
|
|
272
|
+
ModelEmbeddings = __decorate([
|
|
273
|
+
Injectable(),
|
|
274
|
+
__param(0, Inject(KernelDb)),
|
|
275
|
+
__param(1, Inject(TransactionHost)),
|
|
276
|
+
__param(2, Inject(ModelPurposesService)),
|
|
277
|
+
__param(3, Inject(ProviderRegistry)),
|
|
278
|
+
__param(4, Inject(KernelEvents)),
|
|
279
|
+
__param(5, Inject(KERNEL_LOGGER)),
|
|
280
|
+
__param(6, Inject(KernelConfigService))
|
|
281
|
+
], ModelEmbeddings);
|
|
282
|
+
export { ModelEmbeddings };
|
|
283
|
+
/** A result's input tokens when it reports a usable number, else 0 (an invalid result). */
|
|
284
|
+
function tokensOf(res) {
|
|
285
|
+
const n = res?.usage?.inputTokens;
|
|
286
|
+
return typeof n === "number" && Number.isFinite(n) && n > 0 ? n : 0;
|
|
287
|
+
}
|
|
288
|
+
/** The request's shape (an extension is untyped JavaScript at run time). */
|
|
289
|
+
function checkRequest(req) {
|
|
290
|
+
const bad = (why) => {
|
|
291
|
+
throw new ApiError("validation_failed", `Invalid embed request: ${why}`);
|
|
292
|
+
};
|
|
293
|
+
if (typeof req !== "object" || req === null)
|
|
294
|
+
bad("expected an object");
|
|
295
|
+
if (typeof req.orgId !== "string" || req.orgId === "")
|
|
296
|
+
bad("orgId must be a string");
|
|
297
|
+
if (typeof req.purpose !== "string" || req.purpose === "")
|
|
298
|
+
bad("purpose must be a string");
|
|
299
|
+
if (!Array.isArray(req.input) || req.input.some((t) => typeof t !== "string")) {
|
|
300
|
+
bad("input must be an array of strings");
|
|
301
|
+
}
|
|
302
|
+
if (req.input.length > EMBED_MAX_INPUTS)
|
|
303
|
+
bad(`at most ${EMBED_MAX_INPUTS} inputs per call`);
|
|
304
|
+
if (req.dimensions !== undefined && !Number.isInteger(req.dimensions)) {
|
|
305
|
+
bad("dimensions must be an integer");
|
|
306
|
+
}
|
|
307
|
+
if (req.signal !== undefined && !(req.signal instanceof AbortSignal)) {
|
|
308
|
+
bad("signal must be an AbortSignal");
|
|
309
|
+
}
|
|
310
|
+
if (req.inputType !== undefined && req.inputType !== "query" && req.inputType !== "document") {
|
|
311
|
+
bad('inputType must be "query" or "document"');
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
/** {@link validateEmbedResult}, plus the result's own shape (a provider is untyped at run time). */
|
|
315
|
+
function checkResult(req, info, res) {
|
|
316
|
+
const r = res;
|
|
317
|
+
if (typeof r !== "object" || r === null || !Array.isArray(r.vectors))
|
|
318
|
+
return "no vectors";
|
|
319
|
+
if (!r.vectors.every((v) => Array.isArray(v)))
|
|
320
|
+
return "a vector is not an array";
|
|
321
|
+
const tokens = r.usage?.inputTokens;
|
|
322
|
+
if (typeof tokens !== "number" || !Number.isFinite(tokens) || tokens < 0) {
|
|
323
|
+
return "usage.inputTokens is not a non-negative number";
|
|
324
|
+
}
|
|
325
|
+
return validateEmbedResult(req, info, r);
|
|
326
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { type Principal } from "../identity/principal.js";
|
|
3
|
+
import { type OrgContext } from "../orgs/org.guard.js";
|
|
4
|
+
import { type ModelDisableResult, ModelEnablement } from "./enablement.js";
|
|
5
|
+
/** `:provider` of a disabled-list route. */
|
|
6
|
+
export declare const ModelProviderParams: z.ZodObject<{
|
|
7
|
+
provider: z.ZodString;
|
|
8
|
+
}, z.core.$strip>;
|
|
9
|
+
declare const ModelProviderParamsDto_base: import("../infra/validation/create-zod-dto.js").ZodDtoClass<z.ZodObject<{
|
|
10
|
+
provider: z.ZodString;
|
|
11
|
+
}, z.core.$strip>>;
|
|
12
|
+
export declare class ModelProviderParamsDto extends ModelProviderParamsDto_base {
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* The body of a disabled-list PATCH: the model ids of the provider to disable and to enable. An id
|
|
16
|
+
* in neither list keeps its stored state (a page never drops ids it does not show); an id in both
|
|
17
|
+
* is a 400 `validation_failed`.
|
|
18
|
+
*/
|
|
19
|
+
export declare const ModelDisabledPatch: z.ZodObject<{
|
|
20
|
+
disable: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
21
|
+
enable: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
22
|
+
}, z.core.$strict>;
|
|
23
|
+
declare const ModelDisabledPatchDto_base: import("../infra/validation/create-zod-dto.js").ZodDtoClass<z.ZodObject<{
|
|
24
|
+
disable: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
25
|
+
enable: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
26
|
+
}, z.core.$strict>>;
|
|
27
|
+
export declare class ModelDisabledPatchDto extends ModelDisabledPatchDto_base {
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The org's disabled models of one provider (`PATCH /api/v1/orgs/:orgId/models/:provider/disabled`,
|
|
31
|
+
* spec B §5.3): `org.models.manage`, people only. Disables and enables the ids the body names; the
|
|
32
|
+
* response lists the org's agents and purposes that now point at a newly disabled model (the
|
|
33
|
+
* disable is not refused for them).
|
|
34
|
+
*/
|
|
35
|
+
export declare class ModelEnablementController {
|
|
36
|
+
private readonly enablement;
|
|
37
|
+
constructor(enablement: ModelEnablement);
|
|
38
|
+
patch(principal: Principal, org: OrgContext, params: z.infer<typeof ModelProviderParams>, body: z.infer<typeof ModelDisabledPatch>): Promise<ModelDisableResult>;
|
|
39
|
+
}
|
|
40
|
+
export {};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
8
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
9
|
+
};
|
|
10
|
+
import { Controller, Inject, Patch } from "@nestjs/common";
|
|
11
|
+
import { z } from "zod";
|
|
12
|
+
import { CurrentPrincipal, patTokenId, requireUser, } from "../identity/principal.js";
|
|
13
|
+
import { createZodDto } from "../infra/validation/create-zod-dto.js";
|
|
14
|
+
import { ZBody, ZParam } from "../infra/validation/zod-params.js";
|
|
15
|
+
import { CurrentOrg, OrgAction } from "../orgs/org.guard.js";
|
|
16
|
+
import { ModelEnablement } from "./enablement.js";
|
|
17
|
+
/** `:provider` of a disabled-list route. */
|
|
18
|
+
export const ModelProviderParams = z.object({ provider: z.string().min(1).max(200) });
|
|
19
|
+
export class ModelProviderParamsDto extends createZodDto(ModelProviderParams, "ModelProviderParams") {
|
|
20
|
+
}
|
|
21
|
+
const modelIds = z.array(z.string().min(1).max(200)).max(5000).default([]);
|
|
22
|
+
/**
|
|
23
|
+
* The body of a disabled-list PATCH: the model ids of the provider to disable and to enable. An id
|
|
24
|
+
* in neither list keeps its stored state (a page never drops ids it does not show); an id in both
|
|
25
|
+
* is a 400 `validation_failed`.
|
|
26
|
+
*/
|
|
27
|
+
export const ModelDisabledPatch = z
|
|
28
|
+
.object({ disable: modelIds, enable: modelIds })
|
|
29
|
+
.strict()
|
|
30
|
+
.superRefine((v, ctx) => {
|
|
31
|
+
const disable = new Set(v.disable);
|
|
32
|
+
const both = [...new Set(v.enable.filter((m) => disable.has(m)))];
|
|
33
|
+
if (both.length > 0) {
|
|
34
|
+
ctx.addIssue({
|
|
35
|
+
code: "custom",
|
|
36
|
+
path: ["enable"],
|
|
37
|
+
message: `A model cannot be both disabled and enabled: ${both.join(", ")}`,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
export class ModelDisabledPatchDto extends createZodDto(ModelDisabledPatch, "ModelDisabledPatch") {
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The org's disabled models of one provider (`PATCH /api/v1/orgs/:orgId/models/:provider/disabled`,
|
|
45
|
+
* spec B §5.3): `org.models.manage`, people only. Disables and enables the ids the body names; the
|
|
46
|
+
* response lists the org's agents and purposes that now point at a newly disabled model (the
|
|
47
|
+
* disable is not refused for them).
|
|
48
|
+
*/
|
|
49
|
+
let ModelEnablementController = class ModelEnablementController {
|
|
50
|
+
enablement;
|
|
51
|
+
constructor(enablement) {
|
|
52
|
+
this.enablement = enablement;
|
|
53
|
+
}
|
|
54
|
+
async patch(principal, org, params, body) {
|
|
55
|
+
const p = requireUser(principal);
|
|
56
|
+
return this.enablement.setOrg(org.orgId, params.provider, body, {
|
|
57
|
+
accountId: p.account.id,
|
|
58
|
+
tokenId: patTokenId(p),
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
__decorate([
|
|
63
|
+
Patch(":provider/disabled"),
|
|
64
|
+
OrgAction("org.models.manage"),
|
|
65
|
+
__param(0, CurrentPrincipal()),
|
|
66
|
+
__param(1, CurrentOrg()),
|
|
67
|
+
__param(2, ZParam(ModelProviderParamsDto)),
|
|
68
|
+
__param(3, ZBody(ModelDisabledPatchDto))
|
|
69
|
+
], ModelEnablementController.prototype, "patch", null);
|
|
70
|
+
ModelEnablementController = __decorate([
|
|
71
|
+
Controller("api/v1/orgs/:orgId/models"),
|
|
72
|
+
__param(0, Inject(ModelEnablement))
|
|
73
|
+
], ModelEnablementController);
|
|
74
|
+
export { ModelEnablementController };
|