@capybara-hq/kernel 0.1.0-rc.4 → 0.1.0-rc.6
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 +61 -5
- package/dist/admin/admin.controller.d.ts +51 -14
- package/dist/admin/admin.controller.js +60 -19
- package/dist/admin/extensions.controller.d.ts +16 -2
- package/dist/admin/extensions.controller.js +26 -6
- package/dist/admin/setup-lock.d.ts +1 -1
- package/dist/admin/setup-lock.js +1 -1
- package/dist/admin/setup.controller.d.ts +1 -1
- package/dist/admin/setup.controller.js +1 -1
- package/dist/admin/setup.service.d.ts +4 -4
- package/dist/admin/setup.service.js +8 -8
- package/dist/agents/agent-lookup.d.ts +16 -0
- package/dist/agents/agent-lookup.js +11 -0
- package/dist/agents/agents.controller.d.ts +76 -1
- package/dist/agents/agents.controller.js +90 -11
- package/dist/agents/agents.module.d.ts +4 -1
- package/dist/agents/agents.module.js +32 -6
- package/dist/agents/agents.service.d.ts +54 -23
- package/dist/agents/agents.service.js +180 -76
- package/dist/agents/definition.d.ts +49 -0
- package/dist/agents/definition.js +45 -0
- package/dist/agents/from-template.d.ts +106 -0
- package/dist/agents/from-template.js +649 -0
- package/dist/agents/from-template.service.d.ts +60 -0
- package/dist/agents/from-template.service.js +161 -0
- package/dist/agents/models.controller.d.ts +34 -5
- package/dist/agents/models.controller.js +50 -6
- package/dist/agents/org-templates.d.ts +176 -0
- package/dist/agents/org-templates.js +827 -0
- package/dist/agents/pending-connector-requests.d.ts +77 -0
- package/dist/agents/pending-connector-requests.js +215 -0
- package/dist/agents/pending-connectors.controller.d.ts +39 -0
- package/dist/agents/pending-connectors.controller.js +91 -0
- package/dist/agents/pending-connectors.service.d.ts +62 -0
- package/dist/agents/pending-connectors.service.js +282 -0
- package/dist/agents/readiness.controller.d.ts +5 -5
- package/dist/agents/readiness.controller.js +6 -6
- package/dist/agents/templates.controller.d.ts +86 -5
- package/dist/agents/templates.controller.js +171 -7
- package/dist/agents/templates.d.ts +127 -23
- package/dist/agents/templates.js +475 -52
- package/dist/background/background.module.js +8 -1
- package/dist/background/finish.d.ts +3 -2
- package/dist/background/launch-lock.d.ts +4 -3
- package/dist/background/launch-lock.js +4 -3
- package/dist/background/poll.job.d.ts +9 -6
- package/dist/background/poll.job.js +30 -22
- package/dist/background/session.d.ts +13 -2
- package/dist/background/session.js +13 -0
- package/dist/background/stop.d.ts +12 -6
- package/dist/background/stop.js +57 -39
- package/dist/background/store.d.ts +18 -6
- package/dist/background/store.js +12 -6
- package/dist/background/tasks.service.d.ts +15 -5
- package/dist/background/tasks.service.js +42 -17
- package/dist/background/wake-rules.d.ts +27 -18
- package/dist/background/wake-rules.js +52 -22
- package/dist/background/wake.d.ts +13 -11
- package/dist/background/wake.js +20 -14
- package/dist/catalog/admin-catalog.controller.d.ts +129 -30
- package/dist/catalog/admin-catalog.controller.js +213 -42
- package/dist/catalog/catalog-content.d.ts +58 -32
- package/dist/catalog/catalog-content.js +34 -8
- package/dist/catalog/catalog-import.module.d.ts +7 -0
- package/dist/catalog/catalog-import.module.js +60 -0
- package/dist/catalog/catalog-items.d.ts +111 -7
- package/dist/catalog/catalog-items.js +279 -13
- package/dist/catalog/catalog-scope.service.d.ts +260 -0
- package/dist/catalog/catalog-scope.service.js +1116 -0
- package/dist/catalog/catalog.module.d.ts +7 -9
- package/dist/catalog/catalog.module.js +41 -31
- package/dist/catalog/catalog.service.d.ts +101 -29
- package/dist/catalog/catalog.service.js +104 -106
- package/dist/catalog/cli.d.ts +11 -1
- package/dist/catalog/cli.js +26 -1
- package/dist/catalog/component-promotion.d.ts +96 -0
- package/dist/catalog/component-promotion.js +395 -0
- package/dist/catalog/component-scope.controller.d.ts +152 -0
- package/dist/catalog/component-scope.controller.js +287 -0
- package/dist/catalog/component-scope.service.d.ts +303 -0
- package/dist/catalog/component-scope.service.js +936 -0
- package/dist/catalog/component-state.d.ts +174 -0
- package/dist/catalog/component-state.js +437 -0
- package/dist/catalog/job-ids.d.ts +30 -0
- package/dist/catalog/job-ids.js +25 -0
- package/dist/catalog/marketplace-fetch.d.ts +1 -1
- package/dist/catalog/marketplaces.controller.d.ts +22 -5
- package/dist/catalog/marketplaces.controller.js +56 -7
- package/dist/catalog/marketplaces.service.d.ts +54 -14
- package/dist/catalog/marketplaces.service.js +71 -22
- package/dist/catalog/org-catalog.controller.d.ts +125 -34
- package/dist/catalog/org-catalog.controller.js +181 -65
- package/dist/catalog/org-catalog.service.d.ts +65 -33
- package/dist/catalog/org-catalog.service.js +324 -157
- package/dist/catalog/org-extension-switch.d.ts +41 -0
- package/dist/catalog/org-extension-switch.js +115 -0
- package/dist/catalog/org-extension.controller.d.ts +119 -0
- package/dist/catalog/org-extension.controller.js +266 -0
- package/dist/catalog/org-plugin-uploads.controller.d.ts +98 -0
- package/dist/catalog/org-plugin-uploads.controller.js +213 -0
- package/dist/catalog/org-plugin-uploads.d.ts +63 -0
- package/dist/catalog/org-plugin-uploads.js +116 -0
- package/dist/catalog/owned-items.d.ts +184 -0
- package/dist/catalog/owned-items.js +789 -0
- package/dist/catalog/owned-plugin-cleanup.d.ts +56 -0
- package/dist/catalog/owned-plugin-cleanup.js +194 -0
- package/dist/catalog/ownership.d.ts +172 -0
- package/dist/catalog/ownership.js +326 -0
- package/dist/catalog/platform-components.d.ts +221 -0
- package/dist/catalog/platform-components.js +761 -0
- package/dist/catalog/platform-migration.d.ts +115 -0
- package/dist/catalog/platform-migration.js +582 -0
- package/dist/catalog/plugin-import.d.ts +178 -34
- package/dist/catalog/plugin-import.js +622 -82
- package/dist/catalog/plugin-install.d.ts +185 -41
- package/dist/catalog/plugin-install.js +758 -126
- package/dist/catalog/plugin-upgrade.d.ts +260 -225
- package/dist/catalog/plugin-upgrade.js +1147 -1136
- package/dist/catalog/request-rules.d.ts +65 -0
- package/dist/catalog/request-rules.js +217 -0
- package/dist/catalog/requests.service.d.ts +193 -118
- package/dist/catalog/requests.service.js +526 -343
- package/dist/catalog/reserved-names.d.ts +8 -0
- package/dist/catalog/reserved-names.js +42 -0
- package/dist/catalog/scope-orgs.d.ts +21 -0
- package/dist/catalog/scope-orgs.js +67 -0
- package/dist/catalog/scope-state.d.ts +35 -0
- package/dist/catalog/scope-state.js +87 -0
- package/dist/catalog/scope-sync-workers.d.ts +7 -0
- package/dist/catalog/scope-sync-workers.js +29 -0
- package/dist/catalog/scope-sync.d.ts +176 -0
- package/dist/catalog/scope-sync.js +576 -0
- package/dist/catalog/scope.d.ts +42 -0
- package/dist/catalog/scope.js +42 -0
- package/dist/catalog/unshare.d.ts +22 -0
- package/dist/catalog/unshare.js +118 -0
- package/dist/channels/actions.js +1 -0
- package/dist/channels/cards.js +20 -2
- package/dist/channels/channels.module.js +2 -0
- package/dist/channels/inbound.d.ts +9 -1
- package/dist/channels/inbound.js +67 -5
- package/dist/channels/phrases.d.ts +35 -0
- package/dist/channels/phrases.js +29 -0
- package/dist/config/docs.js +3 -1
- package/dist/config/schema.d.ts +10 -2
- package/dist/config/schema.js +70 -22
- package/dist/conversations/access.d.ts +6 -4
- package/dist/conversations/access.js +27 -5
- package/dist/conversations/agent-tree.d.ts +46 -0
- package/dist/conversations/agent-tree.js +92 -0
- package/dist/conversations/conversations.controller.d.ts +43 -18
- package/dist/conversations/conversations.controller.js +79 -38
- package/dist/conversations/conversations.module.d.ts +1 -1
- package/dist/conversations/conversations.module.js +7 -7
- package/dist/conversations/conversations.service.d.ts +73 -15
- package/dist/conversations/conversations.service.js +115 -35
- package/dist/conversations/environment-status.d.ts +24 -0
- package/dist/conversations/environment-status.js +71 -0
- package/dist/conversations/event-log.d.ts +20 -5
- package/dist/conversations/event-log.js +60 -0
- package/dist/conversations/events.d.ts +84 -2
- package/dist/conversations/events.js +91 -17
- package/dist/conversations/queue.service.d.ts +1 -1
- package/dist/conversations/queue.service.js +5 -0
- package/dist/conversations/titles.d.ts +5 -3
- package/dist/conversations/titles.js +21 -8
- package/dist/conversations/tree.d.ts +17 -0
- package/dist/conversations/tree.js +42 -0
- package/dist/ctx/create-ctx.d.ts +20 -1
- package/dist/ctx/create-ctx.js +38 -7
- package/dist/db/kernel-schema.d.ts +386 -18
- package/dist/environments/access.d.ts +41 -0
- package/dist/environments/access.js +77 -0
- package/dist/environments/conversation-environments.d.ts +61 -0
- package/dist/environments/conversation-environments.js +170 -0
- package/dist/environments/dto.d.ts +25 -0
- package/dist/environments/dto.js +12 -0
- package/dist/environments/environments.controller.d.ts +33 -0
- package/dist/environments/environments.controller.js +110 -0
- package/dist/environments/environments.module.d.ts +8 -0
- package/dist/environments/environments.module.js +27 -0
- package/dist/environments/environments.service.d.ts +153 -0
- package/dist/environments/environments.service.js +541 -0
- package/dist/environments/legacy-cleanup.job.d.ts +34 -0
- package/dist/environments/legacy-cleanup.job.js +141 -0
- package/dist/errors.d.ts +85 -2
- package/dist/errors.js +85 -2
- package/dist/evals/reconstruct.d.ts +18 -9
- package/dist/evals/reconstruct.js +26 -7
- package/dist/evals/run-replay.d.ts +4 -2
- package/dist/evals/run-replay.js +20 -6
- package/dist/evals/runs.service.d.ts +2 -1
- package/dist/evals/runs.service.js +13 -12
- package/dist/evals/step-replay.d.ts +4 -6
- package/dist/evals/step-replay.js +4 -3
- package/dist/evals/trajectory.service.d.ts +8 -3
- package/dist/evals/trajectory.service.js +26 -14
- package/dist/evals/worker.d.ts +5 -5
- package/dist/evals/worker.js +9 -3
- package/dist/extensions/admin-ops.d.ts +36 -10
- package/dist/extensions/admin-ops.js +65 -42
- package/dist/extensions/admin-view.d.ts +37 -10
- package/dist/extensions/admin-view.js +103 -20
- package/dist/extensions/bootstrap.d.ts +17 -4
- package/dist/extensions/bootstrap.js +70 -9
- package/dist/extensions/cli.d.ts +12 -0
- package/dist/extensions/cli.js +11 -2
- package/dist/extensions/config-hash.d.ts +10 -0
- package/dist/extensions/config-hash.js +38 -0
- package/dist/extensions/deployment-config.d.ts +28 -5
- package/dist/extensions/deployment-config.js +48 -7
- package/dist/extensions/effective-config.d.ts +127 -0
- package/dist/extensions/effective-config.js +368 -0
- package/dist/extensions/extensions.module.js +11 -11
- package/dist/extensions/hooks.d.ts +37 -4
- package/dist/extensions/hooks.js +82 -16
- package/dist/extensions/host.d.ts +24 -10
- package/dist/extensions/host.js +49 -54
- package/dist/extensions/installs.d.ts +20 -8
- package/dist/extensions/installs.js +37 -15
- package/dist/extensions/org-config.d.ts +75 -6
- package/dist/extensions/org-config.js +184 -32
- package/dist/extensions/org-levels.d.ts +37 -0
- package/dist/extensions/org-levels.js +71 -0
- package/dist/extensions/org-overrides.d.ts +151 -0
- package/dist/extensions/org-overrides.js +524 -0
- package/dist/extensions/permission-view.d.ts +16 -4
- package/dist/extensions/permission-view.js +4 -4
- package/dist/extensions/plugin-items.d.ts +21 -0
- package/dist/extensions/plugin-items.js +42 -0
- package/dist/extensions/point-defaults.d.ts +12 -5
- package/dist/extensions/point-defaults.js +37 -9
- package/dist/extensions/resolve.d.ts +5 -1
- package/dist/extensions/resolve.js +15 -2
- package/dist/extensions/state.module.d.ts +9 -0
- package/dist/extensions/state.module.js +38 -0
- package/dist/files/previewers.d.ts +8 -1
- package/dist/files/previewers.js +35 -6
- package/dist/http/api.module.js +25 -3
- package/dist/http/app.d.ts +11 -2
- package/dist/http/app.js +31 -5
- package/dist/http/plugin-dispatch.d.ts +4 -1
- package/dist/http/plugin-dispatch.js +14 -2
- package/dist/identity/accounts.d.ts +29 -29
- package/dist/identity/accounts.js +47 -47
- package/dist/identity/audit.d.ts +2 -1
- package/dist/identity/auth.guard.d.ts +13 -5
- package/dist/identity/auth.guard.js +26 -9
- package/dist/identity/identity.module.d.ts +1 -1
- package/dist/identity/identity.module.js +4 -4
- package/dist/identity/me.controller.js +1 -1
- package/dist/identity/principal.d.ts +3 -3
- package/dist/identity/principal.js +3 -3
- package/dist/identity/settings.d.ts +22 -11
- package/dist/identity/settings.js +53 -18
- package/dist/identity/{enterprise-admin.d.ts → super-admin.d.ts} +5 -5
- package/dist/identity/{enterprise-admin.js → super-admin.js} +24 -24
- package/dist/inbox/inbox.module.d.ts +4 -1
- package/dist/inbox/inbox.module.js +7 -3
- package/dist/inbox/inbox.service.d.ts +62 -3
- package/dist/inbox/inbox.service.js +74 -4
- package/dist/inbox/org-notices.d.ts +63 -0
- package/dist/inbox/org-notices.js +91 -0
- package/dist/inbox/platform-inbox.controller.d.ts +23 -0
- package/dist/inbox/platform-inbox.controller.js +58 -0
- package/dist/inbox/platform-inbox.service.d.ts +151 -0
- package/dist/inbox/platform-inbox.service.js +263 -0
- package/dist/inbox/platform-notices.d.ts +19 -0
- package/dist/inbox/platform-notices.js +9 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/infra/cli/kernel-cli.module.js +9 -1
- package/dist/infra/config/kernel-config.service.js +24 -1
- package/dist/infra/database/xact-lock.d.ts +1 -1
- package/dist/infra/database/xact-lock.js +1 -1
- package/dist/infra/events/kernel-events.d.ts +19 -2
- package/dist/infra/queue/add-job-once.d.ts +14 -0
- package/dist/infra/queue/add-job-once.js +16 -0
- package/dist/kernel.module.js +6 -0
- package/dist/lifecycle/kernel-lifecycle.d.ts +1 -1
- package/dist/lifecycle/kernel-lifecycle.js +4 -4
- 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 +99 -0
- package/dist/models/enablement.js +263 -0
- package/dist/models/models.module.d.ts +5 -1
- package/dist/models/models.module.js +16 -4
- package/dist/models/prices.d.ts +5 -5
- package/dist/models/prices.js +4 -4
- package/dist/models/purposes.controller.d.ts +6 -4
- package/dist/models/purposes.controller.js +13 -7
- package/dist/models/purposes.d.ts +37 -12
- package/dist/models/purposes.js +63 -17
- package/dist/orgs/directory-sync.d.ts +14 -5
- package/dist/orgs/directory-sync.js +41 -17
- package/dist/orgs/offboarding.d.ts +9 -7
- package/dist/orgs/offboarding.js +28 -17
- package/dist/orgs/org-lock.d.ts +5 -0
- package/dist/orgs/org-lock.js +13 -0
- package/dist/orgs/org.guard.d.ts +10 -0
- package/dist/orgs/org.guard.js +43 -32
- package/dist/orgs/orgs.module.js +3 -0
- package/dist/orgs/orgs.service.d.ts +20 -7
- package/dist/orgs/orgs.service.js +32 -12
- package/dist/orgs/roles.d.ts +1 -1
- package/dist/orgs/roles.js +5 -1
- package/dist/orgs/settings.controller.d.ts +1 -1
- package/dist/orgs/settings.service.d.ts +15 -3
- package/dist/orgs/settings.service.js +6 -2
- package/dist/overrides.d.ts +3 -0
- package/dist/overrides.js +2 -0
- package/dist/platform/actor.d.ts +48 -0
- package/dist/platform/actor.js +100 -0
- package/dist/platform/agent-docs.d.ts +18 -0
- package/dist/platform/agent-docs.js +59 -0
- package/dist/platform/availability.d.ts +14 -0
- package/dist/platform/availability.js +43 -0
- package/dist/platform/errors.d.ts +11 -0
- package/dist/platform/errors.js +26 -0
- package/dist/platform/exclusions.d.ts +12 -0
- package/dist/platform/exclusions.js +1405 -0
- package/dist/platform/method.d.ts +6 -0
- package/dist/platform/method.js +15 -0
- package/dist/platform/operation.d.ts +92 -0
- package/dist/platform/operation.js +35 -0
- package/dist/platform/ops/agent-templates.ops.d.ts +14 -0
- package/dist/platform/ops/agent-templates.ops.js +92 -0
- package/dist/platform/ops/agents.ops.d.ts +19 -0
- package/dist/platform/ops/agents.ops.js +294 -0
- package/dist/platform/ops/connectors.ops.d.ts +15 -0
- package/dist/platform/ops/connectors.ops.js +126 -0
- package/dist/platform/ops/errors.d.ts +11 -0
- package/dist/platform/ops/errors.js +22 -0
- package/dist/platform/ops/extensions.ops.d.ts +19 -0
- package/dist/platform/ops/extensions.ops.js +116 -0
- package/dist/platform/ops/marketplaces.ops.d.ts +16 -0
- package/dist/platform/ops/marketplaces.ops.js +157 -0
- package/dist/platform/ops/paging.d.ts +14 -0
- package/dist/platform/ops/paging.js +20 -0
- package/dist/platform/ops/platform.ops.d.ts +23 -0
- package/dist/platform/ops/platform.ops.js +158 -0
- package/dist/platform/ops/plugins.ops.d.ts +33 -0
- package/dist/platform/ops/plugins.ops.js +377 -0
- package/dist/platform/ops/requests.ops.d.ts +14 -0
- package/dist/platform/ops/requests.ops.js +153 -0
- package/dist/platform/ops/role.d.ts +4 -0
- package/dist/platform/ops/role.js +10 -0
- package/dist/platform/ops/skills.ops.d.ts +13 -0
- package/dist/platform/ops/skills.ops.js +98 -0
- package/dist/platform/ops/summary.d.ts +10 -0
- package/dist/platform/ops/summary.js +18 -0
- package/dist/platform/platform-ops.module.d.ts +7 -0
- package/dist/platform/platform-ops.module.js +55 -0
- package/dist/platform/platform.module.d.ts +8 -0
- package/dist/platform/platform.module.js +25 -0
- package/dist/platform/redact-orgs.d.ts +7 -0
- package/dist/platform/redact-orgs.js +52 -0
- package/dist/platform/registry.d.ts +30 -0
- package/dist/platform/registry.js +111 -0
- package/dist/roles/worker-role.d.ts +6 -4
- package/dist/roles/worker-role.js +14 -7
- package/dist/roles/worker.module.d.ts +1 -1
- package/dist/roles/worker.module.js +9 -1
- package/dist/runtime/context/build.d.ts +6 -4
- package/dist/runtime/context/build.js +26 -7
- package/dist/runtime/context/claude-tools.d.ts +2 -1
- package/dist/runtime/context/claude-tools.js +5 -4
- package/dist/runtime/context/compaction.js +9 -0
- package/dist/runtime/context/reminders.d.ts +2 -0
- package/dist/runtime/context/reminders.js +2 -0
- package/dist/runtime/context/skills.js +9 -2
- package/dist/runtime/context/tool-changes.d.ts +27 -0
- package/dist/runtime/context/tool-changes.js +60 -0
- package/dist/runtime/hook-calls.d.ts +8 -1
- package/dist/runtime/hook-calls.js +40 -7
- package/dist/runtime/langgraph-loop.d.ts +3 -1
- package/dist/runtime/langgraph-loop.js +35 -17
- package/dist/runtime/loop.d.ts +32 -4
- package/dist/runtime/maintenance.d.ts +7 -4
- package/dist/runtime/maintenance.js +23 -8
- package/dist/runtime/model-call.d.ts +38 -11
- package/dist/runtime/model-call.js +97 -24
- package/dist/runtime/providers.d.ts +146 -32
- package/dist/runtime/providers.js +321 -67
- package/dist/runtime/run-control.d.ts +11 -1
- package/dist/runtime/run-control.js +12 -0
- package/dist/runtime/run-drafts.d.ts +85 -0
- package/dist/runtime/run-drafts.js +230 -0
- package/dist/runtime/run-jobs.d.ts +3 -5
- package/dist/runtime/run-jobs.js +3 -7
- package/dist/runtime/run-queue.d.ts +37 -3
- package/dist/runtime/run-queue.js +188 -11
- package/dist/runtime/run-worker.d.ts +12 -6
- package/dist/runtime/run-worker.js +58 -35
- package/dist/runtime/runtime.module.js +3 -0
- package/dist/runtime/step-log.d.ts +9 -4
- package/dist/runtime/step-log.js +8 -5
- package/dist/runtime/stream.controller.d.ts +23 -1
- package/dist/runtime/stream.controller.js +60 -3
- package/dist/runtime/stream.d.ts +4 -1
- package/dist/runtime/stream.js +27 -3
- package/dist/runtime/subagents/child.d.ts +55 -7
- package/dist/runtime/subagents/child.js +105 -7
- package/dist/runtime/subagents/definition.d.ts +12 -3
- package/dist/runtime/subagents/definition.js +46 -32
- package/dist/runtime/subagents/deliveries.d.ts +71 -0
- package/dist/runtime/subagents/deliveries.js +228 -0
- package/dist/runtime/subagents/dispatch.d.ts +115 -26
- package/dist/runtime/subagents/dispatch.js +212 -141
- package/dist/runtime/subagents/limits.d.ts +24 -5
- package/dist/runtime/subagents/limits.js +40 -6
- package/dist/runtime/subagents/messages.d.ts +95 -0
- package/dist/runtime/subagents/messages.js +328 -0
- package/dist/runtime/subagents/preamble.d.ts +4 -4
- package/dist/runtime/subagents/preamble.js +9 -7
- package/dist/runtime/subagents/progress.d.ts +8 -6
- package/dist/runtime/subagents/progress.js +11 -6
- package/dist/runtime/subagents/render.d.ts +30 -0
- package/dist/runtime/subagents/render.js +53 -0
- package/dist/runtime/subagents/roster.d.ts +24 -7
- package/dist/runtime/subagents/roster.js +47 -11
- package/dist/runtime/subagents/skill-fork.d.ts +3 -2
- package/dist/runtime/subagents/skill-fork.js +8 -4
- package/dist/runtime/subagents/status.d.ts +14 -0
- package/dist/runtime/subagents/status.js +23 -0
- package/dist/runtime/subagents/subagents.service.d.ts +7 -4
- package/dist/runtime/subagents/subagents.service.js +11 -6
- 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 +169 -96
- package/dist/runtime/waits.d.ts +140 -37
- package/dist/runtime/waits.js +394 -106
- package/dist/sandbox/jobs.d.ts +40 -13
- package/dist/sandbox/jobs.js +57 -20
- package/dist/sandbox/leases.d.ts +37 -54
- package/dist/sandbox/leases.js +71 -115
- package/dist/sandbox/providers.d.ts +2 -2
- package/dist/sandbox/providers.js +1 -1
- package/dist/sandbox/sandbox.module.d.ts +3 -2
- package/dist/sandbox/sandbox.module.js +4 -3
- package/dist/sandbox/sandbox.service.d.ts +229 -134
- package/dist/sandbox/sandbox.service.js +630 -409
- package/dist/skills/catalog.d.ts +3 -2
- package/dist/skills/catalog.js +21 -43
- package/dist/skills/changes.controller.d.ts +7 -0
- package/dist/skills/changes.controller.js +19 -1
- package/dist/skills/invoke.js +8 -3
- package/dist/skills/package.d.ts +20 -1
- package/dist/skills/package.js +28 -1
- package/dist/skills/skills.controller.d.ts +39 -4
- package/dist/skills/skills.controller.js +88 -10
- package/dist/skills/skills.module.js +10 -1
- package/dist/skills/skills.service.d.ts +106 -26
- package/dist/skills/skills.service.js +421 -75
- package/dist/skills/usable.d.ts +81 -0
- package/dist/skills/usable.js +379 -0
- package/dist/tools/approvals.service.d.ts +20 -2
- package/dist/tools/approvals.service.js +23 -4
- package/dist/tools/builtin-names.d.ts +21 -5
- package/dist/tools/builtin-names.js +30 -5
- package/dist/tools/builtins/agent.d.ts +23 -21
- package/dist/tools/builtins/agent.js +62 -55
- package/dist/tools/builtins/builtin-tools.d.ts +6 -2
- package/dist/tools/builtins/builtin-tools.js +37 -12
- package/dist/tools/builtins/handback.d.ts +28 -0
- package/dist/tools/builtins/handback.js +53 -0
- package/dist/tools/builtins/platform.d.ts +34 -0
- package/dist/tools/builtins/platform.js +362 -0
- package/dist/tools/builtins/sandbox/bash.js +13 -3
- package/dist/tools/builtins/sandbox/common.d.ts +43 -24
- package/dist/tools/builtins/sandbox/common.js +80 -45
- package/dist/tools/builtins/sandbox/edit.js +2 -2
- package/dist/tools/builtins/sandbox/glob.js +2 -2
- package/dist/tools/builtins/sandbox/grep.js +2 -4
- package/dist/tools/builtins/sandbox/index.d.ts +1 -1
- package/dist/tools/builtins/sandbox/index.js +1 -1
- package/dist/tools/builtins/sandbox/read.js +1 -1
- package/dist/tools/builtins/sandbox/task-output.d.ts +14 -3
- package/dist/tools/builtins/sandbox/task-output.js +30 -5
- package/dist/tools/builtins/sandbox/task-stop.js +2 -1
- package/dist/tools/builtins/sandbox/write.js +2 -2
- package/dist/tools/builtins/send-message.d.ts +56 -0
- package/dist/tools/builtins/send-message.js +100 -0
- package/dist/tools/builtins/skill-load.d.ts +22 -14
- package/dist/tools/builtins/skill-load.js +86 -57
- package/dist/tools/builtins/skill-write.js +1 -1
- package/dist/tools/builtins/web/extract.js +5 -1
- package/dist/tools/builtins/web/fetch.js +1 -0
- package/dist/tools/builtins/web/search.js +1 -0
- package/dist/tools/connectors.controller.d.ts +10 -0
- package/dist/tools/connectors.controller.js +12 -0
- package/dist/tools/connectors.service.d.ts +46 -5
- package/dist/tools/connectors.service.js +94 -15
- package/dist/tools/extension-tools.controller.d.ts +14 -0
- package/dist/tools/extension-tools.controller.js +37 -0
- package/dist/tools/info.d.ts +42 -1
- package/dist/tools/info.js +64 -1
- package/dist/tools/org-tool-switches.d.ts +74 -0
- package/dist/tools/org-tool-switches.js +184 -0
- package/dist/tools/pipeline.d.ts +46 -40
- package/dist/tools/pipeline.js +193 -364
- package/dist/tools/policy.d.ts +1 -1
- package/dist/tools/policy.js +36 -16
- package/dist/tools/registry.d.ts +98 -5
- package/dist/tools/registry.js +87 -9
- package/dist/tools/tools.module.js +12 -2
- package/dist/ui/views.d.ts +2 -1
- package/dist/ui/views.js +17 -3
- package/package.json +3 -3
- package/src/migrations/0074_subagent_tree.sql +50 -0
- package/src/migrations/0075_plugin_scope.sql +61 -0
- package/src/migrations/0076_skills_created_by_nullable.sql +6 -0
- package/src/migrations/0077_scope_requests.sql +52 -0
- package/src/migrations/0078_scope_grant_switches.sql +18 -0
- package/src/migrations/0079_scope_live_install_switches.sql +19 -0
- package/src/migrations/0080_rename_enterprise_admin.sql +18 -0
- package/src/migrations/0081_platform_components.sql +129 -0
- package/src/migrations/0082_platform_migration.sql +33 -0
- package/src/migrations/0083_plugin_scope_sync_failures.sql +15 -0
- package/src/migrations/0084_org_owned_items.sql +85 -0
- package/src/migrations/0085_agent_templates_phase4.sql +45 -0
- package/src/migrations/0086_org_layering.sql +30 -0
- package/src/migrations/0087_approval_summary.sql +6 -0
- package/src/migrations/0088_environments.sql +80 -0
- package/src/migrations/0089_model_kinds_usage.sql +38 -0
- package/dist/catalog/upgrade-targets.d.ts +0 -56
- package/dist/catalog/upgrade-targets.js +0 -90
- package/dist/conversations/sandbox-status.d.ts +0 -24
- package/dist/conversations/sandbox-status.js +0 -52
- package/dist/extensions/org-config.controller.d.ts +0 -32
- package/dist/extensions/org-config.controller.js +0 -70
|
@@ -0,0 +1,827 @@
|
|
|
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
|
+
// Org agent templates (plugin scope phase 4, spec §15, rulings P4-9 to P4-13): 另存为模板 writes
|
|
11
|
+
// an org row (`agent_templates`, no plugin, a bare `<name>`, version 1) from an agent, the template
|
|
12
|
+
// detail reads any template usable in the org, and the owner org's admins write new versions.
|
|
13
|
+
// Deleting and 可共享 are `OwnedItems`' (the P3 owner rules). No in-process state.
|
|
14
|
+
import { AGENT_TEMPLATE_LIMITS, extensionToolKey, parseAgentTemplate, parseToolKey, } from "@capybara-hq/plugin-sdk";
|
|
15
|
+
import { Inject, Injectable } from "@nestjs/common";
|
|
16
|
+
import { offeredNamed } from "../catalog/component-state.js";
|
|
17
|
+
import { ownerOf, ownersOf } from "../catalog/ownership.js";
|
|
18
|
+
import { ApiError } from "../errors.js";
|
|
19
|
+
import { audit } from "../identity/audit.js";
|
|
20
|
+
import { notifySharedUpdate } from "../inbox/org-notices.js";
|
|
21
|
+
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
22
|
+
import { TransactionHost } from "../infra/database/transaction-host.js";
|
|
23
|
+
import { Transactional } from "../infra/database/transactional.decorator.js";
|
|
24
|
+
import { OrgLock } from "../orgs/org-lock.js";
|
|
25
|
+
import { skillVersionsById } from "../skills/usable.js";
|
|
26
|
+
import { canonicalJson } from "../tools/canonical-json.js";
|
|
27
|
+
import { AgentLookup } from "./agent-lookup.js";
|
|
28
|
+
import { loadTemplates, putTemplateVersionIn, readOwnTemplate, templateTypeOf, templateViewOf, usableTemplates, } from "./templates.js";
|
|
29
|
+
/**
|
|
30
|
+
* Roster names no template may take (ruling T4-R15): `general-purpose`, always the roster's first
|
|
31
|
+
* entry. Claude Code's other built-in types (`Explore`, `Plan`) are capitalized, which the
|
|
32
|
+
* template name rule already refuses.
|
|
33
|
+
*/
|
|
34
|
+
export const RESERVED_TEMPLATE_NAMES = new Set(["general-purpose"]);
|
|
35
|
+
const EFFORTS = ["low", "medium", "high", "xhigh", "max"];
|
|
36
|
+
const TOOL_KEY_RE = /^[a-zA-Z0-9_-]{1,64}$/;
|
|
37
|
+
const notFound = () => new ApiError("component.not_found", "Agent template not found");
|
|
38
|
+
const agentNotFound = () => new ApiError("agent.not_found", "Agent not found");
|
|
39
|
+
/**
|
|
40
|
+
* A connector's URL as a template may record it (ruling P4-11): userinfo, query and fragment
|
|
41
|
+
* removed (they may carry credentials). Null when it is no absolute http(s) URL.
|
|
42
|
+
*/
|
|
43
|
+
export function sanitizeEndpoint(raw) {
|
|
44
|
+
let u;
|
|
45
|
+
try {
|
|
46
|
+
u = new URL(raw);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
if (u.protocol !== "https:" && u.protocol !== "http:")
|
|
52
|
+
return null;
|
|
53
|
+
u.username = "";
|
|
54
|
+
u.password = "";
|
|
55
|
+
u.search = "";
|
|
56
|
+
u.hash = "";
|
|
57
|
+
const out = u.toString();
|
|
58
|
+
return out.length <= 2048 ? out : null;
|
|
59
|
+
}
|
|
60
|
+
/** The URL a hand-configured connector's endpoint names: MCP `url`, OpenAPI `specUrl` / `baseUrl`. */
|
|
61
|
+
function endpointUrl(endpoint) {
|
|
62
|
+
if (endpoint === null || typeof endpoint !== "object" || Array.isArray(endpoint))
|
|
63
|
+
return null;
|
|
64
|
+
const e = endpoint;
|
|
65
|
+
for (const k of ["url", "specUrl", "baseUrl"]) {
|
|
66
|
+
if (typeof e[k] === "string")
|
|
67
|
+
return sanitizeEndpoint(e[k]);
|
|
68
|
+
}
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Validates a template definition the way an `agents/<name>.md` file is (the SDK parser, so the
|
|
73
|
+
* two never drift): the definition minus `instructions` as the frontmatter (JSON is YAML), then
|
|
74
|
+
* the instructions as the body. Problems -> 400 `validation_failed` naming each.
|
|
75
|
+
*/
|
|
76
|
+
export function parseTemplateDefinition(definition) {
|
|
77
|
+
const { instructions, ...front } = definition;
|
|
78
|
+
if (typeof instructions !== "string") {
|
|
79
|
+
throw new ApiError("validation_failed", "Invalid agent template: instructions is required", [
|
|
80
|
+
{ path: "definition.instructions", message: "instructions must be a string" },
|
|
81
|
+
]);
|
|
82
|
+
}
|
|
83
|
+
const parsed = parseAgentTemplate(`---\n${JSON.stringify(front)}\n---\n${instructions}`);
|
|
84
|
+
if ("errors" in parsed) {
|
|
85
|
+
throw new ApiError("validation_failed", `Invalid agent template: ${parsed.errors[0] ?? "unknown problem"}`, parsed.errors.map((message) => ({ path: "definition", message })));
|
|
86
|
+
}
|
|
87
|
+
return parsed.template;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Ruling P4-11 on an edit: a `connectors[].needs.endpoint` that carries userinfo, a query or a
|
|
91
|
+
* fragment, or is no http(s) URL of at most 2048 characters, is refused with 400
|
|
92
|
+
* `validation_failed` naming the field and what it carries (an edit is never stripped silently).
|
|
93
|
+
* One that differs only by normalization (a trailing slash, the host's case) is accepted:
|
|
94
|
+
* returns the template with each such endpoint in its canonical {@link sanitizeEndpoint} form.
|
|
95
|
+
*/
|
|
96
|
+
export function canonicalEndpoints(template) {
|
|
97
|
+
const details = [];
|
|
98
|
+
const connectors = (template.connectors ?? []).map((c, i) => {
|
|
99
|
+
if (!("needs" in c))
|
|
100
|
+
return c;
|
|
101
|
+
const raw = c.needs.endpoint;
|
|
102
|
+
const clean = sanitizeEndpoint(raw);
|
|
103
|
+
const path = `definition.connectors.${i}.needs.endpoint`;
|
|
104
|
+
if (clean === null) {
|
|
105
|
+
details.push({ path, message: "must be an http(s) URL of at most 2048 characters" });
|
|
106
|
+
return c;
|
|
107
|
+
}
|
|
108
|
+
const u = new URL(raw);
|
|
109
|
+
const carries = [
|
|
110
|
+
...(u.username !== "" || u.password !== "" ? ["userinfo"] : []),
|
|
111
|
+
...(u.search !== "" ? ["a query"] : []),
|
|
112
|
+
...(u.hash !== "" ? ["a fragment"] : []),
|
|
113
|
+
];
|
|
114
|
+
if (carries.length > 0) {
|
|
115
|
+
details.push({
|
|
116
|
+
path,
|
|
117
|
+
message: `must not carry ${carries.join(", ")} (they may hold credentials); use ${clean}`,
|
|
118
|
+
});
|
|
119
|
+
return c;
|
|
120
|
+
}
|
|
121
|
+
return clean === raw ? c : { ...c, needs: { ...c.needs, endpoint: clean } };
|
|
122
|
+
});
|
|
123
|
+
if (details.length > 0) {
|
|
124
|
+
throw new ApiError("validation_failed", "A connector endpoint in an agent template must be a plain http(s) URL (no userinfo, query or fragment)", details);
|
|
125
|
+
}
|
|
126
|
+
return template.connectors === undefined ? template : { ...template, connectors };
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* The template an agent is saved as (rulings P4-10, P4-11), with what was left out. Pure reads of
|
|
130
|
+
* the org's state through `db`.
|
|
131
|
+
*/
|
|
132
|
+
export async function templateFromAgent(db, orgId, agent, meta) {
|
|
133
|
+
const def = agent.definition;
|
|
134
|
+
const omitted = [];
|
|
135
|
+
const L = AGENT_TEMPLATE_LIMITS;
|
|
136
|
+
const blank = (s) => typeof s !== "string" || s.trim() === "";
|
|
137
|
+
// Model: `modelRef` and `effort` only; every other parameter and the fallback are listed
|
|
138
|
+
const effortParam = def.modelParams?.effort;
|
|
139
|
+
const effort = typeof effortParam === "string" && EFFORTS.includes(effortParam)
|
|
140
|
+
? effortParam
|
|
141
|
+
: undefined;
|
|
142
|
+
for (const key of Object.keys(def.modelParams ?? {})) {
|
|
143
|
+
if (key === "effort" && effort !== undefined)
|
|
144
|
+
continue;
|
|
145
|
+
omitted.push({ kind: "model_param", name: key, reason: "model_param" });
|
|
146
|
+
}
|
|
147
|
+
if (def.fallback != null) {
|
|
148
|
+
omitted.push({
|
|
149
|
+
kind: "fallback_model",
|
|
150
|
+
name: `${def.fallback.provider}/${def.fallback.model}`,
|
|
151
|
+
reason: "fallback",
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
// Tools: builtin and plugin tool keys; connector tools become `connectors` entries
|
|
155
|
+
const tools = [];
|
|
156
|
+
const connectorRefs = [];
|
|
157
|
+
// stored definitions are not parsed: fields with schema defaults may be missing
|
|
158
|
+
for (const r of def.tools ?? []) {
|
|
159
|
+
if (r.kind === "connector") {
|
|
160
|
+
connectorRefs.push({ connectorId: r.connectorId, tools: r.tools });
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
const key = r.kind === "builtin" ? r.name : extensionToolKey(r.plugin, r.name);
|
|
164
|
+
if (!TOOL_KEY_RE.test(key) || tools.includes(key))
|
|
165
|
+
continue;
|
|
166
|
+
if (tools.length >= L.tools) {
|
|
167
|
+
omitted.push({ kind: "tool", name: key, reason: "limit" });
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
tools.push(key);
|
|
171
|
+
}
|
|
172
|
+
// builtin / plugin keys stay keys; a connector tool's policy goes to its connector entry by
|
|
173
|
+
// tool name (`policies`), since the key embeds this org's connector slug
|
|
174
|
+
const toolPolicies = {};
|
|
175
|
+
const connectorPolicies = new Map();
|
|
176
|
+
for (const [k, v] of Object.entries(def.toolPolicies ?? {})) {
|
|
177
|
+
if (tools.includes(k)) {
|
|
178
|
+
toolPolicies[k] = v;
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
const parsed = parseToolKey(k);
|
|
182
|
+
if (parsed?.kind === "connector") {
|
|
183
|
+
const list = connectorPolicies.get(parsed.slug) ?? [];
|
|
184
|
+
list.push({ key: k, tool: parsed.tool, policy: v });
|
|
185
|
+
connectorPolicies.set(parsed.slug, list);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
const usedSlugs = new Set();
|
|
189
|
+
/** The `policies` of the entry of connector `slug` (tool names of at most 128 characters). */
|
|
190
|
+
const policiesOf = (slug) => {
|
|
191
|
+
const list = connectorPolicies.get(slug) ?? [];
|
|
192
|
+
if (list.length === 0)
|
|
193
|
+
return {};
|
|
194
|
+
usedSlugs.add(slug);
|
|
195
|
+
// capped with the entry's tools when it is pushed
|
|
196
|
+
return { policies: Object.fromEntries(list.map((p) => [p.tool, p.policy])) };
|
|
197
|
+
};
|
|
198
|
+
// Skills: ids -> names (pinned -> `skills`, the other selected ones -> `selectedSkills`)
|
|
199
|
+
const pinned = def.skills?.pinned ?? [];
|
|
200
|
+
const selected = def.skills?.orgSkills ?? [];
|
|
201
|
+
const inlineSkillIds = (def.subagents?.inline ?? []).flatMap((t) => t.skills ?? []);
|
|
202
|
+
const byId = await skillVersionsById(db, orgId, [...pinned, ...selected, ...inlineSkillIds]);
|
|
203
|
+
const agentSkillNames = new Map((await db
|
|
204
|
+
.selectFrom("skills")
|
|
205
|
+
.select(["id", "name"])
|
|
206
|
+
.where("org_id", "=", orgId)
|
|
207
|
+
.where("scope", "=", "agent")
|
|
208
|
+
.where("id", "in", ["", ...pinned, ...selected, ...inlineSkillIds])
|
|
209
|
+
.execute()).map((r) => [r.id, r.name]));
|
|
210
|
+
const reportedSkills = new Set();
|
|
211
|
+
const skillName = (id, report) => {
|
|
212
|
+
const s = byId.get(id);
|
|
213
|
+
if (s && s.scope === "org")
|
|
214
|
+
return s.name;
|
|
215
|
+
if (report && !reportedSkills.has(id)) {
|
|
216
|
+
reportedSkills.add(id);
|
|
217
|
+
const own = agentSkillNames.get(id) ?? s?.name;
|
|
218
|
+
omitted.push(own !== undefined
|
|
219
|
+
? { kind: "skill", name: own, id, reason: "agent_skill" }
|
|
220
|
+
: { kind: "skill", name: id, id, reason: "unavailable" });
|
|
221
|
+
}
|
|
222
|
+
return null;
|
|
223
|
+
};
|
|
224
|
+
const skills = [];
|
|
225
|
+
for (const id of pinned) {
|
|
226
|
+
const n = skillName(id, true);
|
|
227
|
+
if (n !== null && !skills.includes(n) && skills.length < L.skills)
|
|
228
|
+
skills.push(n);
|
|
229
|
+
}
|
|
230
|
+
const selectedSkills = [];
|
|
231
|
+
for (const id of selected) {
|
|
232
|
+
if (pinned.includes(id))
|
|
233
|
+
continue;
|
|
234
|
+
const n = skillName(id, true);
|
|
235
|
+
if (n === null || skills.includes(n) || selectedSkills.includes(n))
|
|
236
|
+
continue;
|
|
237
|
+
if (selectedSkills.length >= L.selectedSkills) {
|
|
238
|
+
omitted.push({ kind: "skill", name: n, id, reason: "limit" });
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
selectedSkills.push(n);
|
|
242
|
+
}
|
|
243
|
+
// Connectors (P4-11), then the agent's pending connectors as they are
|
|
244
|
+
const connectors = [];
|
|
245
|
+
const pushConnector = (entry, name, id) => {
|
|
246
|
+
if (connectors.length >= L.connectors) {
|
|
247
|
+
omitted.push({ kind: "connector", name, ...(id !== undefined && { id }), reason: "limit" });
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
let c = entry;
|
|
251
|
+
// an entry names at most `connectorTools` tools, its `tools` and its policy keys together
|
|
252
|
+
// (the SDK's limit): policies past that room are listed, never written
|
|
253
|
+
if (c.policies !== undefined) {
|
|
254
|
+
const named = "needs" in c ? c.needs.tools.length : (c.tools?.length ?? 0);
|
|
255
|
+
const valid = Object.entries(c.policies).filter(([tool]) => tool.trim() !== "" && [...tool].length <= 128);
|
|
256
|
+
const room = Math.max(0, L.connectorTools - named);
|
|
257
|
+
for (const [tool] of valid.slice(room)) {
|
|
258
|
+
omitted.push({
|
|
259
|
+
kind: "tool_policy",
|
|
260
|
+
name: tool,
|
|
261
|
+
...(id !== undefined && { id }),
|
|
262
|
+
reason: "limit",
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
const kept = valid.slice(0, room);
|
|
266
|
+
const { policies: _all, ...rest } = c;
|
|
267
|
+
c = kept.length > 0 ? { ...rest, policies: Object.fromEntries(kept) } : rest;
|
|
268
|
+
}
|
|
269
|
+
connectors.push(c);
|
|
270
|
+
};
|
|
271
|
+
const ids = [...new Set(connectorRefs.map((r) => r.connectorId))];
|
|
272
|
+
const rows = ids.length === 0
|
|
273
|
+
? []
|
|
274
|
+
: await db
|
|
275
|
+
.selectFrom("connectors as c")
|
|
276
|
+
.leftJoin("platform_connector_templates as p", (j) => j.onRef("p.id", "=", "c.platform_template_id").on("p.deleted_at", "is", null))
|
|
277
|
+
.select(["c.id", "c.name", "c.slug", "c.connector", "c.endpoint", "p.id as template_id"])
|
|
278
|
+
.where("c.org_id", "=", orgId)
|
|
279
|
+
.where("c.deleted_at", "is", null)
|
|
280
|
+
.where("c.id", "in", ids)
|
|
281
|
+
.execute();
|
|
282
|
+
const connectorById = new Map(rows.map((r) => [r.id, r]));
|
|
283
|
+
for (const id of ids) {
|
|
284
|
+
const c = connectorById.get(id);
|
|
285
|
+
if (!c) {
|
|
286
|
+
omitted.push({ kind: "connector", name: id, id, reason: "unavailable" });
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
289
|
+
const refs = connectorRefs.filter((r) => r.connectorId === id);
|
|
290
|
+
const named = refs.some((r) => r.tools === "all")
|
|
291
|
+
? null
|
|
292
|
+
: [...new Set(refs.flatMap((r) => r.tools))].slice(0, L.connectorTools);
|
|
293
|
+
if (c.template_id !== null) {
|
|
294
|
+
// only the platform connector template is recorded, not this connector: creating an agent
|
|
295
|
+
// from the template rebinds the entry to the org's oldest connector made from that
|
|
296
|
+
// template (P4-5 `several`), which may be another one than this
|
|
297
|
+
pushConnector({
|
|
298
|
+
template: c.template_id,
|
|
299
|
+
...(named !== null && { tools: named }),
|
|
300
|
+
...policiesOf(c.slug),
|
|
301
|
+
}, c.name, c.id);
|
|
302
|
+
continue;
|
|
303
|
+
}
|
|
304
|
+
if (c.connector !== "mcp" && c.connector !== "openapi") {
|
|
305
|
+
omitted.push({ kind: "connector", name: c.name, id: c.id, reason: "unsupported_protocol" });
|
|
306
|
+
continue;
|
|
307
|
+
}
|
|
308
|
+
const endpoint = endpointUrl(c.endpoint);
|
|
309
|
+
if (endpoint === null) {
|
|
310
|
+
omitted.push({ kind: "connector", name: c.name, id: c.id, reason: "no_endpoint" });
|
|
311
|
+
continue;
|
|
312
|
+
}
|
|
313
|
+
const enabled = named ??
|
|
314
|
+
(await db
|
|
315
|
+
.selectFrom("connector_tools")
|
|
316
|
+
.select("name")
|
|
317
|
+
.where("connector_id", "=", c.id)
|
|
318
|
+
.where("status", "=", "enabled")
|
|
319
|
+
.orderBy("name")
|
|
320
|
+
.execute())
|
|
321
|
+
.map((t) => t.name)
|
|
322
|
+
.slice(0, L.connectorTools);
|
|
323
|
+
pushConnector({
|
|
324
|
+
needs: {
|
|
325
|
+
protocol: c.connector,
|
|
326
|
+
endpoint,
|
|
327
|
+
tools: enabled.filter((t) => t.length <= 128),
|
|
328
|
+
label: [...c.name].slice(0, 80).join(""),
|
|
329
|
+
},
|
|
330
|
+
...policiesOf(c.slug),
|
|
331
|
+
}, c.name, c.id);
|
|
332
|
+
}
|
|
333
|
+
// a policy of a connector the template does not carry (left out above) cannot go anywhere
|
|
334
|
+
for (const [slug, list] of connectorPolicies) {
|
|
335
|
+
if (usedSlugs.has(slug))
|
|
336
|
+
continue;
|
|
337
|
+
for (const p of list) {
|
|
338
|
+
omitted.push({ kind: "tool_policy", name: p.key, reason: "connector_tool" });
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
const pending = def.pendingConnectors;
|
|
342
|
+
for (const p of Array.isArray(pending) ? pending : []) {
|
|
343
|
+
const e = p;
|
|
344
|
+
const pendingPolicies = e.policies !== null && typeof e.policies === "object" && Object.keys(e.policies).length > 0
|
|
345
|
+
? { policies: { ...e.policies } }
|
|
346
|
+
: {};
|
|
347
|
+
const label = typeof e.label === "string" ? e.label : "";
|
|
348
|
+
if (typeof e.source?.template === "string") {
|
|
349
|
+
pushConnector({
|
|
350
|
+
template: e.source.template,
|
|
351
|
+
...(Array.isArray(e.tools) && { tools: e.tools }),
|
|
352
|
+
...pendingPolicies,
|
|
353
|
+
}, label);
|
|
354
|
+
}
|
|
355
|
+
else if (e.source?.needs !== undefined) {
|
|
356
|
+
const n = e.source.needs;
|
|
357
|
+
const endpoint = sanitizeEndpoint(n.endpoint);
|
|
358
|
+
if (endpoint === null) {
|
|
359
|
+
omitted.push({ kind: "connector", name: label, reason: "no_endpoint" });
|
|
360
|
+
continue;
|
|
361
|
+
}
|
|
362
|
+
pushConnector({ needs: { ...n, endpoint }, ...pendingPolicies }, label);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
// Sub-agents: template ids -> types, inline skill ids -> names; org agents are left out
|
|
366
|
+
const sub = def.subagents;
|
|
367
|
+
let subagents;
|
|
368
|
+
if (sub !== undefined) {
|
|
369
|
+
const types = [];
|
|
370
|
+
const inline = [];
|
|
371
|
+
const room = () => types.length + inline.length < L.subagentTypes;
|
|
372
|
+
const found = await loadTemplates(db, orgId, sub.templates ?? []);
|
|
373
|
+
for (const id of sub.templates ?? []) {
|
|
374
|
+
const t = found.get(id);
|
|
375
|
+
if (!t) {
|
|
376
|
+
omitted.push({ kind: "subagent_template", name: id, id, reason: "unavailable" });
|
|
377
|
+
continue;
|
|
378
|
+
}
|
|
379
|
+
const type = templateTypeOf(t.plugin, t.name);
|
|
380
|
+
if (types.includes(type))
|
|
381
|
+
continue;
|
|
382
|
+
if (!room()) {
|
|
383
|
+
omitted.push({ kind: "subagent_template", name: type, id, reason: "limit" });
|
|
384
|
+
continue;
|
|
385
|
+
}
|
|
386
|
+
types.push(type);
|
|
387
|
+
}
|
|
388
|
+
for (const t of sub.inline ?? []) {
|
|
389
|
+
// a template requires both texts non-blank (the SDK rule); the agent's schema does not
|
|
390
|
+
const empty = blank(t.description)
|
|
391
|
+
? "description"
|
|
392
|
+
: blank(t.instructions)
|
|
393
|
+
? "instructions"
|
|
394
|
+
: null;
|
|
395
|
+
if (empty !== null) {
|
|
396
|
+
omitted.push({ kind: "subagent_inline", name: t.name, field: empty, reason: "empty_text" });
|
|
397
|
+
continue;
|
|
398
|
+
}
|
|
399
|
+
if (!room()) {
|
|
400
|
+
omitted.push({ kind: "subagent_inline", name: t.name, reason: "limit" });
|
|
401
|
+
continue;
|
|
402
|
+
}
|
|
403
|
+
// no allowlist stays none (all of the agent's tools); a list, even `[]`, is written
|
|
404
|
+
const listed = t.tools ?? [];
|
|
405
|
+
const ownTools = listed.filter((k) => TOOL_KEY_RE.test(k) && parseToolKey(k)?.kind !== "connector");
|
|
406
|
+
// a connector key embeds this org's slug: an allowlist cannot carry it elsewhere
|
|
407
|
+
if (listed.some((k) => parseToolKey(k)?.kind === "connector")) {
|
|
408
|
+
omitted.push({
|
|
409
|
+
kind: "subagent_inline",
|
|
410
|
+
name: t.name,
|
|
411
|
+
field: "tools",
|
|
412
|
+
reason: "connector_tool",
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
for (const field of ["disallowedTools", "toolPolicies", "effort", "maxSteps"]) {
|
|
416
|
+
if (t[field] !== undefined) {
|
|
417
|
+
omitted.push({
|
|
418
|
+
kind: "subagent_inline",
|
|
419
|
+
name: t.name,
|
|
420
|
+
field,
|
|
421
|
+
reason: "unsupported_field",
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
const inlineSkills = [];
|
|
426
|
+
for (const id of t.skills ?? []) {
|
|
427
|
+
const n = skillName(id, true);
|
|
428
|
+
if (n === null || inlineSkills.includes(n))
|
|
429
|
+
continue;
|
|
430
|
+
if (inlineSkills.length >= L.skills) {
|
|
431
|
+
omitted.push({ kind: "skill", name: n, id, reason: "limit" });
|
|
432
|
+
continue;
|
|
433
|
+
}
|
|
434
|
+
inlineSkills.push(n);
|
|
435
|
+
}
|
|
436
|
+
inline.push({
|
|
437
|
+
name: t.name,
|
|
438
|
+
description: t.description,
|
|
439
|
+
instructions: t.instructions,
|
|
440
|
+
...(t.tools !== undefined && { tools: [...new Set(ownTools)].slice(0, L.tools) }),
|
|
441
|
+
skills: inlineSkills,
|
|
442
|
+
model: t.model ?? "inherit",
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
for (const a of sub.agents ?? []) {
|
|
446
|
+
omitted.push({ kind: "subagent_agent", name: a.as, id: a.agentId, reason: "org_agent" });
|
|
447
|
+
}
|
|
448
|
+
subagents = {
|
|
449
|
+
...(sub.general !== undefined && { general: sub.general }),
|
|
450
|
+
...(types.length > 0 && { types }),
|
|
451
|
+
...(inline.length > 0 && { inline }),
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
const quickActions = [];
|
|
455
|
+
for (const q of agent.profile.quickActions) {
|
|
456
|
+
if (blank(q.title) || blank(q.body)) {
|
|
457
|
+
omitted.push({ kind: "quick_action", name: q.title, reason: "empty_text" });
|
|
458
|
+
continue;
|
|
459
|
+
}
|
|
460
|
+
quickActions.push({ title: q.title, body: q.body });
|
|
461
|
+
}
|
|
462
|
+
const template = {
|
|
463
|
+
name: meta.name,
|
|
464
|
+
description: meta.description,
|
|
465
|
+
instructions: def.instructions ?? "",
|
|
466
|
+
tools,
|
|
467
|
+
...(Object.keys(toolPolicies).length > 0 && { toolPolicies }),
|
|
468
|
+
model: "standard",
|
|
469
|
+
modelRef: `${def.model.provider}/${def.model.model}`,
|
|
470
|
+
...(effort !== undefined && { effort }),
|
|
471
|
+
...(skills.length > 0 && { skills }),
|
|
472
|
+
...(selectedSkills.length > 0 && { selectedSkills }),
|
|
473
|
+
...(connectors.length > 0 && { connectors }),
|
|
474
|
+
...(subagents !== undefined && { subagents }),
|
|
475
|
+
...(quickActions.length > 0 && { quickActions }),
|
|
476
|
+
...(def.instructionFiles !== undefined && {
|
|
477
|
+
instructionFiles: def.instructionFiles.map((f) => ({ name: f.name, content: f.content })),
|
|
478
|
+
}),
|
|
479
|
+
};
|
|
480
|
+
// the same rules as a template file: a template that would not load is never written
|
|
481
|
+
return {
|
|
482
|
+
template: parseTemplateDefinition(template),
|
|
483
|
+
omitted,
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* The org's agent templates beyond the plugin ones (rulings P4-9 to P4-12): 另存为模板, the detail
|
|
488
|
+
* of a usable template and the owner's new versions. Writes run under the org row lock, with
|
|
489
|
+
* `agents.manage` re-checked there.
|
|
490
|
+
*/
|
|
491
|
+
let OrgAgentTemplates = class OrgAgentTemplates {
|
|
492
|
+
kdb;
|
|
493
|
+
orgLock;
|
|
494
|
+
agents;
|
|
495
|
+
txHost;
|
|
496
|
+
constructor(kdb, orgLock, agents, txHost) {
|
|
497
|
+
this.kdb = kdb;
|
|
498
|
+
this.orgLock = orgLock;
|
|
499
|
+
this.agents = agents;
|
|
500
|
+
this.txHost = txHost;
|
|
501
|
+
}
|
|
502
|
+
get db() {
|
|
503
|
+
return this.kdb.db;
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* 另存为模板 (ruling P4-9): the org's live agent `agentId` (any one: an org admin may edit every
|
|
507
|
+
* agent of the org) saved as the org template `name` (version 1, `plugin_name` null), mapped
|
|
508
|
+
* by {@link templateFromAgent}. The bare name must be free in the org (rule 10): a usable
|
|
509
|
+
* template of that type, one of the org's own rows of that name, or a live platform template
|
|
510
|
+
* the org created under that name -> 409 `agent_template.name_taken` naming its owner (details
|
|
511
|
+
* `[{ owner, templateId }]`). Audits `agent_template.created`.
|
|
512
|
+
*/
|
|
513
|
+
async saveAs(orgId, actor, agentId, meta, actorTokenId, auditDetail) {
|
|
514
|
+
const t = this.db;
|
|
515
|
+
await this.orgLock.lockAndAuthorize(orgId, actor, "agents.manage");
|
|
516
|
+
const live = await t
|
|
517
|
+
.selectFrom("agents")
|
|
518
|
+
.select("id")
|
|
519
|
+
.where("id", "=", agentId)
|
|
520
|
+
.where("org_id", "=", orgId)
|
|
521
|
+
.where("deleted_at", "is", null)
|
|
522
|
+
.executeTakeFirst();
|
|
523
|
+
if (!live)
|
|
524
|
+
throw agentNotFound();
|
|
525
|
+
const agent = await this.agents.view(agentId);
|
|
526
|
+
await this.assertNameFree(orgId, meta.name);
|
|
527
|
+
const { template, omitted } = await templateFromAgent(t, orgId, agent, meta);
|
|
528
|
+
const put = await putTemplateVersionIn(t, { orgId, plugin: null, catalogItemId: null, catalogVersion: null, sourceFormat: "capybara" }, template);
|
|
529
|
+
await audit(t, {
|
|
530
|
+
actorAccountId: actor,
|
|
531
|
+
...(actorTokenId !== undefined && { actorTokenId }),
|
|
532
|
+
orgId,
|
|
533
|
+
action: "agent_template.created",
|
|
534
|
+
target: put.id,
|
|
535
|
+
detail: {
|
|
536
|
+
name: template.name,
|
|
537
|
+
fromAgent: agentId,
|
|
538
|
+
omitted: omitted.length,
|
|
539
|
+
...auditDetail,
|
|
540
|
+
},
|
|
541
|
+
});
|
|
542
|
+
return { template: await this.detail(orgId, put.id), omitted };
|
|
543
|
+
}
|
|
544
|
+
/**
|
|
545
|
+
* Rule 10 for a new org template named `name` (a bare type): refused for a reserved roster name
|
|
546
|
+
* (details `[{ reserved: true }]`), and while the org's usable set has that type, the org has a
|
|
547
|
+
* live row of that name without a plugin (an unusable copy too: the live-name index), a
|
|
548
|
+
* plugin-less platform template of that name is offered to the org (ruling P2-3's alignment),
|
|
549
|
+
* or the platform has a live template the org created under that name (promotion would clash).
|
|
550
|
+
*/
|
|
551
|
+
async assertNameFree(orgId, name) {
|
|
552
|
+
const t = this.db;
|
|
553
|
+
const clash = (owner, templateId) => {
|
|
554
|
+
throw new ApiError("agent_template.name_taken", owner.kind === "platform"
|
|
555
|
+
? `An agent template named ${name} is already used in this organization (the platform's)`
|
|
556
|
+
: owner.orgId === orgId
|
|
557
|
+
? `An agent template named ${name} already exists in this organization`
|
|
558
|
+
: `An agent template named ${name} is already used in this organization (from organization ${owner.name})`, [{ owner, templateId }]);
|
|
559
|
+
};
|
|
560
|
+
if (RESERVED_TEMPLATE_NAMES.has(name)) {
|
|
561
|
+
throw new ApiError("agent_template.name_taken", `${name} is a built-in sub-agent type; choose another name`, [{ reserved: true }]);
|
|
562
|
+
}
|
|
563
|
+
const own = await t
|
|
564
|
+
.selectFrom("agent_templates")
|
|
565
|
+
.select("id")
|
|
566
|
+
.where("org_id", "=", orgId)
|
|
567
|
+
.where("plugin_name", "is", null)
|
|
568
|
+
.where("name", "=", name)
|
|
569
|
+
.where("deleted_at", "is", null)
|
|
570
|
+
.executeTakeFirst();
|
|
571
|
+
const self = ownerOf(orgId, await ownersOf(t, [orgId]));
|
|
572
|
+
if (own)
|
|
573
|
+
clash(self, own.id);
|
|
574
|
+
const usable = (await usableTemplates(t, orgId)).find((u) => templateTypeOf(u.plugin, u.name) === name);
|
|
575
|
+
if (usable)
|
|
576
|
+
clash(await this.ownerOfRow(orgId, usable), usable.id);
|
|
577
|
+
// offered to the org but not on (a switch away, as ruling P2-3 for skills): switching it on
|
|
578
|
+
// later would put the name in the org twice
|
|
579
|
+
const offered = (await offeredNamed(t, orgId, "agent_template", name)).find((c) => c.plugin === null);
|
|
580
|
+
if (offered) {
|
|
581
|
+
const ids = offered.ownerOrgId === null ? [] : [offered.ownerOrgId];
|
|
582
|
+
clash(ownerOf(offered.ownerOrgId, await ownersOf(t, ids)), offered.id);
|
|
583
|
+
}
|
|
584
|
+
const origin = await t
|
|
585
|
+
.selectFrom("platform_agent_templates")
|
|
586
|
+
.select(["id", "owner_org_id"])
|
|
587
|
+
.where("origin_org_id", "=", orgId)
|
|
588
|
+
.where("plugin_name", "is", null)
|
|
589
|
+
.where("name", "=", name)
|
|
590
|
+
.where("deleted_at", "is", null)
|
|
591
|
+
.executeTakeFirst();
|
|
592
|
+
if (origin) {
|
|
593
|
+
const ids = origin.owner_org_id === null ? [] : [origin.owner_org_id];
|
|
594
|
+
clash(ownerOf(origin.owner_org_id, await ownersOf(t, ids)), origin.id);
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
/**
|
|
598
|
+
* A template usable in the org by id ({@link loadTemplates}: an org row, a linked copy, a
|
|
599
|
+
* platform template on in the org), or the org's own template whatever its switch, with its
|
|
600
|
+
* definition, owner and the org's flags. Otherwise -> 404 `component.not_found`.
|
|
601
|
+
*/
|
|
602
|
+
async detail(orgId, id) {
|
|
603
|
+
const own = await this.ownRow(orgId, id, false);
|
|
604
|
+
// the owner opens its own template even while it is switched off in its own org (a promoted
|
|
605
|
+
// one whose platform row the org switched off is not in its usable set)
|
|
606
|
+
const inSet = (await loadTemplates(this.db, orgId, [id])).get(id);
|
|
607
|
+
const t = inSet ?? (own && (await this.ownServed(own)));
|
|
608
|
+
if (!t)
|
|
609
|
+
throw notFound();
|
|
610
|
+
let linked = [];
|
|
611
|
+
if (t.origin === "platform" && !t.ownedCopy && t.id === t.platformTemplateId) {
|
|
612
|
+
linked = (await this.db
|
|
613
|
+
.selectFrom("agent_templates")
|
|
614
|
+
.select("id")
|
|
615
|
+
.where("org_id", "=", orgId)
|
|
616
|
+
.where("deleted_at", "is", null)
|
|
617
|
+
.where("pinned_version", "is", null)
|
|
618
|
+
.where("platform_template_id", "=", t.id)
|
|
619
|
+
.orderBy("id")
|
|
620
|
+
.execute()).map((r) => r.id);
|
|
621
|
+
}
|
|
622
|
+
return {
|
|
623
|
+
...templateViewOf(t, linked),
|
|
624
|
+
definition: t.template,
|
|
625
|
+
owner: own
|
|
626
|
+
? ownerOf(orgId, await ownersOf(this.db, [orgId]))
|
|
627
|
+
: await this.ownerOfRow(orgId, t),
|
|
628
|
+
owned: own !== undefined,
|
|
629
|
+
shareable: own?.shareable ?? false,
|
|
630
|
+
promoted: own !== undefined && own.link !== null,
|
|
631
|
+
usable: inSet !== undefined,
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
/**
|
|
635
|
+
* A new version of the org's own template `id` (ruling P4-12; `agents.manage` re-checked under
|
|
636
|
+
* the org row lock): `definition` is validated like a template file and keeps its name;
|
|
637
|
+
* `expectedVersion` must be the version the editor read (else 409
|
|
638
|
+
* `agent_template.version_conflict`). An unshared template gets a new version of its org row; a
|
|
639
|
+
* promoted one a new version of its platform row (ruling P3-4), which the org row then serves
|
|
640
|
+
* (ruling P3-43), and the orgs using it are told (`shared_item_updated`). An unchanged
|
|
641
|
+
* definition writes nothing. Not the org's own -> 409 `catalog.not_owned`; missing -> 404.
|
|
642
|
+
* Agents created earlier are never touched. Audits `agent_template.updated`.
|
|
643
|
+
*/
|
|
644
|
+
async update(orgId, actor, id, body, actorTokenId) {
|
|
645
|
+
const t = this.db;
|
|
646
|
+
await this.orgLock.lockAndAuthorize(orgId, actor, "agents.manage");
|
|
647
|
+
const row = await this.ownRow(orgId, id, true);
|
|
648
|
+
if (!row)
|
|
649
|
+
throw await this.notOwnedOrMissing(orgId, id);
|
|
650
|
+
const template = canonicalEndpoints(parseTemplateDefinition(body.definition));
|
|
651
|
+
if (template.name !== row.name) {
|
|
652
|
+
throw new ApiError("validation_failed", "The name of an agent template cannot change", [
|
|
653
|
+
{ path: "definition.name", message: `must stay ${row.name}` },
|
|
654
|
+
]);
|
|
655
|
+
}
|
|
656
|
+
const conflict = (now) => new ApiError("agent_template.version_conflict", `The agent template was changed by someone else (now version ${now}, expected ${body.expectedVersion}); reload it and apply your changes again`);
|
|
657
|
+
if (row.link === null) {
|
|
658
|
+
if (row.current_version !== body.expectedVersion)
|
|
659
|
+
throw conflict(row.current_version);
|
|
660
|
+
const put = await putTemplateVersionIn(t, {
|
|
661
|
+
orgId,
|
|
662
|
+
plugin: null,
|
|
663
|
+
catalogItemId: null,
|
|
664
|
+
catalogVersion: null,
|
|
665
|
+
sourceFormat: "capybara",
|
|
666
|
+
}, template);
|
|
667
|
+
if (put.changed) {
|
|
668
|
+
await audit(t, {
|
|
669
|
+
actorAccountId: actor,
|
|
670
|
+
...(actorTokenId !== undefined && { actorTokenId }),
|
|
671
|
+
orgId,
|
|
672
|
+
action: "agent_template.updated",
|
|
673
|
+
target: id,
|
|
674
|
+
detail: { name: row.name, from: row.current_version, to: put.version },
|
|
675
|
+
});
|
|
676
|
+
}
|
|
677
|
+
return this.detail(orgId, id);
|
|
678
|
+
}
|
|
679
|
+
const p = await t
|
|
680
|
+
.selectFrom("platform_agent_templates as p")
|
|
681
|
+
.innerJoin("platform_agent_template_versions as v", (j) => j.onRef("v.template_id", "=", "p.id").onRef("v.version", "=", "p.current_version"))
|
|
682
|
+
.select(["p.current_version", "v.definition", "v.source_format"])
|
|
683
|
+
.where("p.id", "=", row.link)
|
|
684
|
+
.where("p.deleted_at", "is", null)
|
|
685
|
+
.forUpdate("p")
|
|
686
|
+
.executeTakeFirst();
|
|
687
|
+
if (!p)
|
|
688
|
+
throw notFound();
|
|
689
|
+
if (p.current_version !== body.expectedVersion)
|
|
690
|
+
throw conflict(p.current_version);
|
|
691
|
+
if (canonicalJson(p.definition) === canonicalJson(template))
|
|
692
|
+
return this.detail(orgId, id);
|
|
693
|
+
const to = p.current_version + 1;
|
|
694
|
+
await t
|
|
695
|
+
.updateTable("platform_agent_templates")
|
|
696
|
+
.set({ current_version: to, description: template.description, updated_at: new Date() })
|
|
697
|
+
.where("id", "=", row.link)
|
|
698
|
+
.execute();
|
|
699
|
+
await t
|
|
700
|
+
.insertInto("platform_agent_template_versions")
|
|
701
|
+
.values({
|
|
702
|
+
template_id: row.link,
|
|
703
|
+
version: to,
|
|
704
|
+
definition: JSON.stringify(template),
|
|
705
|
+
// an org template has no file: only its parsed definition is stored
|
|
706
|
+
object_prefix: null,
|
|
707
|
+
catalog_version: null,
|
|
708
|
+
source_format: p.source_format,
|
|
709
|
+
created_by: actor,
|
|
710
|
+
})
|
|
711
|
+
.execute();
|
|
712
|
+
await notifySharedUpdate(t, { kind: "agent_template", id: row.link }, { name: row.name, from: String(p.current_version), to: String(to) });
|
|
713
|
+
await audit(t, {
|
|
714
|
+
actorAccountId: actor,
|
|
715
|
+
...(actorTokenId !== undefined && { actorTokenId }),
|
|
716
|
+
orgId,
|
|
717
|
+
action: "agent_template.updated",
|
|
718
|
+
target: id,
|
|
719
|
+
detail: { name: row.name, platformId: row.link, from: p.current_version, to },
|
|
720
|
+
});
|
|
721
|
+
return this.detail(orgId, id);
|
|
722
|
+
}
|
|
723
|
+
/**
|
|
724
|
+
* The org's own template `id` ({@link readOwnTemplate}, the predicate `OwnedItems` shares), or
|
|
725
|
+
* undefined: another org's, a plugin's, or a copy of a platform template it does not own.
|
|
726
|
+
*/
|
|
727
|
+
async ownRow(orgId, id, forUpdate) {
|
|
728
|
+
const r = await readOwnTemplate(this.db, orgId, id, forUpdate);
|
|
729
|
+
return r !== undefined && "link" in r ? r : undefined;
|
|
730
|
+
}
|
|
731
|
+
/**
|
|
732
|
+
* What the org's own template serves, read directly (its usable-set entry is missing while the
|
|
733
|
+
* org switched its promoted template off): the platform row's current version when it is newer
|
|
734
|
+
* than the org row's (ruling P3-43), else the org row's.
|
|
735
|
+
*/
|
|
736
|
+
async ownServed(own) {
|
|
737
|
+
const db = this.db;
|
|
738
|
+
const platform = own.link === null
|
|
739
|
+
? undefined
|
|
740
|
+
: await db
|
|
741
|
+
.selectFrom("platform_agent_templates as p")
|
|
742
|
+
.innerJoin("platform_agent_template_versions as v", (j) => j.onRef("v.template_id", "=", "p.id").onRef("v.version", "=", "p.current_version"))
|
|
743
|
+
.select(["p.current_version", "v.definition", "v.source_format"])
|
|
744
|
+
.where("p.id", "=", own.link)
|
|
745
|
+
.executeTakeFirst();
|
|
746
|
+
const row = platform !== undefined && platform.current_version !== own.current_version
|
|
747
|
+
? platform
|
|
748
|
+
: await db
|
|
749
|
+
.selectFrom("agent_template_versions")
|
|
750
|
+
.select(["version as current_version", "definition", "source_format"])
|
|
751
|
+
.where("template_id", "=", own.id)
|
|
752
|
+
.where("version", "=", own.current_version)
|
|
753
|
+
.executeTakeFirst();
|
|
754
|
+
if (!row)
|
|
755
|
+
return undefined;
|
|
756
|
+
return {
|
|
757
|
+
id: own.id,
|
|
758
|
+
name: own.name,
|
|
759
|
+
plugin: null,
|
|
760
|
+
version: row.current_version,
|
|
761
|
+
template: row.definition,
|
|
762
|
+
sourceFormat: row.source_format,
|
|
763
|
+
catalogItemId: null,
|
|
764
|
+
catalogVersion: null,
|
|
765
|
+
origin: "org",
|
|
766
|
+
};
|
|
767
|
+
}
|
|
768
|
+
/** 409 `catalog.not_owned` for a template the org has but does not own, else 404. */
|
|
769
|
+
async notOwnedOrMissing(orgId, id) {
|
|
770
|
+
const t = (await loadTemplates(this.db, orgId, [id])).get(id);
|
|
771
|
+
if (!t)
|
|
772
|
+
return notFound();
|
|
773
|
+
return new ApiError("catalog.not_owned", `${t.name} is not this organization's own agent template; only its owner can change it`);
|
|
774
|
+
}
|
|
775
|
+
/**
|
|
776
|
+
* The owner of a usable template the org does not own itself: a platform template's (or a
|
|
777
|
+
* linked copy's) `owner_org_id`, a plugin template's catalog item owner, else the platform.
|
|
778
|
+
*/
|
|
779
|
+
async ownerOfRow(orgId, t) {
|
|
780
|
+
const db = this.db;
|
|
781
|
+
let ownerOrgId = null;
|
|
782
|
+
if (t.platformTemplateId !== undefined || t.ownedCopy) {
|
|
783
|
+
const pid = t.platformTemplateId ??
|
|
784
|
+
(await db
|
|
785
|
+
.selectFrom("agent_templates")
|
|
786
|
+
.select("platform_template_id")
|
|
787
|
+
.where("id", "=", t.id)
|
|
788
|
+
.executeTakeFirst())?.platform_template_id ??
|
|
789
|
+
null;
|
|
790
|
+
if (pid !== null) {
|
|
791
|
+
ownerOrgId =
|
|
792
|
+
(await db
|
|
793
|
+
.selectFrom("platform_agent_templates")
|
|
794
|
+
.select("owner_org_id")
|
|
795
|
+
.where("id", "=", pid)
|
|
796
|
+
.executeTakeFirst())?.owner_org_id ?? null;
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
else if (t.catalogItemId !== null) {
|
|
800
|
+
ownerOrgId =
|
|
801
|
+
(await db
|
|
802
|
+
.selectFrom("catalog_items")
|
|
803
|
+
.select("owner_org_id")
|
|
804
|
+
.where("id", "=", t.catalogItemId)
|
|
805
|
+
.executeTakeFirst())?.owner_org_id ?? null;
|
|
806
|
+
}
|
|
807
|
+
else if (t.plugin === null) {
|
|
808
|
+
// an org row without a plugin is the org's own
|
|
809
|
+
ownerOrgId = orgId;
|
|
810
|
+
}
|
|
811
|
+
return ownerOf(ownerOrgId, await ownersOf(db, ownerOrgId === null ? [] : [ownerOrgId]));
|
|
812
|
+
}
|
|
813
|
+
};
|
|
814
|
+
__decorate([
|
|
815
|
+
Transactional()
|
|
816
|
+
], OrgAgentTemplates.prototype, "saveAs", null);
|
|
817
|
+
__decorate([
|
|
818
|
+
Transactional()
|
|
819
|
+
], OrgAgentTemplates.prototype, "update", null);
|
|
820
|
+
OrgAgentTemplates = __decorate([
|
|
821
|
+
Injectable(),
|
|
822
|
+
__param(0, Inject(KernelDb)),
|
|
823
|
+
__param(1, Inject(OrgLock)),
|
|
824
|
+
__param(2, Inject(AgentLookup)),
|
|
825
|
+
__param(3, Inject(TransactionHost))
|
|
826
|
+
], OrgAgentTemplates);
|
|
827
|
+
export { OrgAgentTemplates };
|