@capybara-hq/kernel 0.0.0-stage → 0.1.0-rc.1
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/LICENSE +202 -0
- package/NOTICE +2 -0
- package/README.md +20 -2
- package/bootstrap.json +26 -0
- package/dist/admin/admin.controller.d.ts +139 -0
- package/dist/admin/admin.controller.js +238 -0
- package/dist/admin/extensions.controller.d.ts +100 -0
- package/dist/admin/extensions.controller.js +226 -0
- package/dist/admin/setup.controller.d.ts +36 -0
- package/dist/admin/setup.controller.js +106 -0
- package/dist/admin/setup.service.d.ts +47 -0
- package/dist/admin/setup.service.js +90 -0
- package/dist/agents/agents.controller.d.ts +205 -0
- package/dist/agents/agents.controller.js +144 -0
- package/dist/agents/agents.service.d.ts +177 -0
- package/dist/agents/agents.service.js +677 -0
- package/dist/agents/definition.d.ts +198 -0
- package/dist/agents/definition.js +152 -0
- package/dist/agents/models.controller.d.ts +13 -0
- package/dist/agents/models.controller.js +31 -0
- package/dist/agents/templates.controller.d.ts +15 -0
- package/dist/agents/templates.controller.js +37 -0
- package/dist/agents/templates.d.ts +83 -0
- package/dist/agents/templates.js +173 -0
- package/dist/catalog/admin-catalog.controller.d.ts +143 -0
- package/dist/catalog/admin-catalog.controller.js +245 -0
- package/dist/catalog/catalog.service.d.ts +430 -0
- package/dist/catalog/catalog.service.js +882 -0
- package/dist/catalog/claude/agents.d.ts +27 -0
- package/dist/catalog/claude/agents.js +270 -0
- package/dist/catalog/claude/commands.d.ts +50 -0
- package/dist/catalog/claude/commands.js +179 -0
- package/dist/catalog/claude/manifest.d.ts +69 -0
- package/dist/catalog/claude/manifest.js +134 -0
- package/dist/catalog/claude/marketplace.d.ts +35 -0
- package/dist/catalog/claude/marketplace.js +194 -0
- package/dist/catalog/claude/mcp.d.ts +33 -0
- package/dist/catalog/claude/mcp.js +226 -0
- package/dist/catalog/claude/report.d.ts +86 -0
- package/dist/catalog/claude/report.js +121 -0
- package/dist/catalog/claude/translate.d.ts +56 -0
- package/dist/catalog/claude/translate.js +857 -0
- package/dist/catalog/cli.d.ts +46 -0
- package/dist/catalog/cli.js +211 -0
- package/dist/catalog/git-source.d.ts +127 -0
- package/dist/catalog/git-source.js +520 -0
- package/dist/catalog/marketplace-fetch.d.ts +99 -0
- package/dist/catalog/marketplace-fetch.js +203 -0
- package/dist/catalog/marketplaces.controller.d.ts +97 -0
- package/dist/catalog/marketplaces.controller.js +197 -0
- package/dist/catalog/marketplaces.service.d.ts +340 -0
- package/dist/catalog/marketplaces.service.js +1217 -0
- package/dist/catalog/org-catalog.controller.d.ts +128 -0
- package/dist/catalog/org-catalog.controller.js +277 -0
- package/dist/catalog/org-catalog.service.d.ts +246 -0
- package/dist/catalog/org-catalog.service.js +625 -0
- package/dist/catalog/plugin-import.d.ts +436 -0
- package/dist/catalog/plugin-import.js +1069 -0
- package/dist/catalog/plugin-install.d.ts +447 -0
- package/dist/catalog/plugin-install.js +1333 -0
- package/dist/catalog/plugin-package.d.ts +143 -0
- package/dist/catalog/plugin-package.js +382 -0
- package/dist/catalog/plugin-upgrade.d.ts +222 -0
- package/dist/catalog/plugin-upgrade.js +1219 -0
- package/dist/catalog/requests.service.d.ts +162 -0
- package/dist/catalog/requests.service.js +504 -0
- package/dist/catalog/schema-path.d.ts +7 -0
- package/dist/catalog/schema-path.js +63 -0
- package/dist/catalog/upgrade-targets.d.ts +59 -0
- package/dist/catalog/upgrade-targets.js +90 -0
- package/dist/catalog/versions.d.ts +31 -0
- package/dist/catalog/versions.js +44 -0
- package/dist/channels/actions.d.ts +37 -0
- package/dist/channels/actions.js +121 -0
- package/dist/channels/cards.d.ts +44 -0
- package/dist/channels/cards.js +156 -0
- package/dist/channels/connections.controller.d.ts +59 -0
- package/dist/channels/connections.controller.js +115 -0
- package/dist/channels/connections.service.d.ts +187 -0
- package/dist/channels/connections.service.js +534 -0
- package/dist/channels/features.d.ts +12 -0
- package/dist/channels/features.js +22 -0
- package/dist/channels/inbound.d.ts +120 -0
- package/dist/channels/inbound.js +332 -0
- package/dist/channels/outbound.d.ts +140 -0
- package/dist/channels/outbound.js +1126 -0
- package/dist/channels/phrases.d.ts +100 -0
- package/dist/channels/phrases.js +81 -0
- package/dist/channels/supervisor.d.ts +182 -0
- package/dist/channels/supervisor.js +625 -0
- package/dist/channels/threads.d.ts +29 -0
- package/dist/channels/threads.js +104 -0
- package/dist/channels/webhook-url.d.ts +16 -0
- package/dist/channels/webhook-url.js +34 -0
- package/dist/channels/webhook.controller.d.ts +19 -0
- package/dist/channels/webhook.controller.js +72 -0
- package/dist/channels/webhook.d.ts +73 -0
- package/dist/channels/webhook.js +274 -0
- package/dist/config/docs.d.ts +9 -0
- package/dist/config/docs.js +85 -0
- package/dist/config/env.d.ts +6 -0
- package/dist/config/env.js +73 -0
- package/dist/config/fields.d.ts +42 -0
- package/dist/config/fields.js +214 -0
- package/dist/config/file-source.d.ts +3 -0
- package/dist/config/file-source.js +31 -0
- package/dist/config/load.d.ts +20 -0
- package/dist/config/load.js +98 -0
- package/dist/config/nacos-source.d.ts +31 -0
- package/dist/config/nacos-source.js +229 -0
- package/dist/config/schema.d.ts +237 -0
- package/dist/config/schema.js +1192 -0
- package/dist/config/sources.d.ts +18 -0
- package/dist/config/sources.js +59 -0
- package/dist/config/types.d.ts +9 -0
- package/dist/config/types.js +7 -0
- package/dist/conversations/artifacts.d.ts +52 -0
- package/dist/conversations/artifacts.js +137 -0
- package/dist/conversations/attachments.controller.d.ts +28 -0
- package/dist/conversations/attachments.controller.js +96 -0
- package/dist/conversations/attachments.service.d.ts +180 -0
- package/dist/conversations/attachments.service.js +578 -0
- package/dist/conversations/conversations.controller.d.ts +288 -0
- package/dist/conversations/conversations.controller.js +607 -0
- package/dist/conversations/conversations.service.d.ts +321 -0
- package/dist/conversations/conversations.service.js +754 -0
- package/dist/conversations/event-log.d.ts +122 -0
- package/dist/conversations/event-log.js +259 -0
- package/dist/conversations/events.d.ts +856 -0
- package/dist/conversations/events.js +639 -0
- package/dist/conversations/files.d.ts +92 -0
- package/dist/conversations/files.js +213 -0
- package/dist/conversations/outputs-read.d.ts +34 -0
- package/dist/conversations/outputs-read.js +37 -0
- package/dist/conversations/queue.d.ts +169 -0
- package/dist/conversations/queue.js +527 -0
- package/dist/conversations/sandbox-status.d.ts +21 -0
- package/dist/conversations/sandbox-status.js +24 -0
- package/dist/conversations/selection.d.ts +46 -0
- package/dist/conversations/selection.js +75 -0
- package/dist/conversations/titles.d.ts +93 -0
- package/dist/conversations/titles.js +423 -0
- package/dist/ctx/bus.d.ts +16 -0
- package/dist/ctx/bus.js +101 -0
- package/dist/ctx/create-ctx.d.ts +109 -0
- package/dist/ctx/create-ctx.js +592 -0
- package/dist/ctx/kv.d.ts +4 -0
- package/dist/ctx/kv.js +31 -0
- package/dist/ctx/lock.d.ts +4 -0
- package/dist/ctx/lock.js +39 -0
- package/dist/ctx/namespace.d.ts +6 -0
- package/dist/ctx/namespace.js +12 -0
- package/dist/ctx/queue.d.ts +25 -0
- package/dist/ctx/queue.js +151 -0
- package/dist/ctx/secrets.d.ts +45 -0
- package/dist/ctx/secrets.js +175 -0
- package/dist/db/kernel-schema.d.ts +1122 -0
- package/dist/db/kernel-schema.js +5 -0
- package/dist/db/migrator.d.ts +28 -0
- package/dist/db/migrator.js +140 -0
- package/dist/db/pool.d.ts +21 -0
- package/dist/db/pool.js +28 -0
- package/dist/db/sql-statements.d.ts +34 -0
- package/dist/db/sql-statements.js +168 -0
- package/dist/errors.d.ts +211 -0
- package/dist/errors.js +213 -0
- package/dist/evals/budget.d.ts +61 -0
- package/dist/evals/budget.js +181 -0
- package/dist/evals/diff.d.ts +55 -0
- package/dist/evals/diff.js +133 -0
- package/dist/evals/judge.d.ts +53 -0
- package/dist/evals/judge.js +149 -0
- package/dist/evals/plan.d.ts +47 -0
- package/dist/evals/plan.js +77 -0
- package/dist/evals/reconstruct.d.ts +137 -0
- package/dist/evals/reconstruct.js +322 -0
- package/dist/evals/recorded-tools.d.ts +54 -0
- package/dist/evals/recorded-tools.js +167 -0
- package/dist/evals/run-replay.d.ts +86 -0
- package/dist/evals/run-replay.js +502 -0
- package/dist/evals/runs.controller.d.ts +100 -0
- package/dist/evals/runs.controller.js +199 -0
- package/dist/evals/runs.service.d.ts +275 -0
- package/dist/evals/runs.service.js +836 -0
- package/dist/evals/sets.controller.d.ts +61 -0
- package/dist/evals/sets.controller.js +183 -0
- package/dist/evals/sets.service.d.ts +128 -0
- package/dist/evals/sets.service.js +558 -0
- package/dist/evals/snapshot.d.ts +76 -0
- package/dist/evals/snapshot.js +207 -0
- package/dist/evals/step-replay.d.ts +113 -0
- package/dist/evals/step-replay.js +181 -0
- package/dist/evals/trajectory.controller.d.ts +41 -0
- package/dist/evals/trajectory.controller.js +88 -0
- package/dist/evals/trajectory.d.ts +144 -0
- package/dist/evals/trajectory.js +338 -0
- package/dist/evals/trajectory.service.d.ts +108 -0
- package/dist/evals/trajectory.service.js +323 -0
- package/dist/evals/worker.d.ts +101 -0
- package/dist/evals/worker.js +790 -0
- package/dist/extensions/admin-ops.d.ts +105 -0
- package/dist/extensions/admin-ops.js +353 -0
- package/dist/extensions/admin-view.d.ts +79 -0
- package/dist/extensions/admin-view.js +327 -0
- package/dist/extensions/approvals.d.ts +119 -0
- package/dist/extensions/approvals.js +205 -0
- package/dist/extensions/blobs.d.ts +45 -0
- package/dist/extensions/blobs.js +160 -0
- package/dist/extensions/bootstrap.d.ts +176 -0
- package/dist/extensions/bootstrap.js +535 -0
- package/dist/extensions/cli.d.ts +61 -0
- package/dist/extensions/cli.js +165 -0
- package/dist/extensions/config-json-schema.d.ts +9 -0
- package/dist/extensions/config-json-schema.js +73 -0
- package/dist/extensions/deployment-config.d.ts +138 -0
- package/dist/extensions/deployment-config.js +394 -0
- package/dist/extensions/enabled.d.ts +31 -0
- package/dist/extensions/enabled.js +55 -0
- package/dist/extensions/hooks.d.ts +161 -0
- package/dist/extensions/hooks.js +425 -0
- package/dist/extensions/host.d.ts +577 -0
- package/dist/extensions/host.js +2071 -0
- package/dist/extensions/inflight.d.ts +69 -0
- package/dist/extensions/inflight.js +277 -0
- package/dist/extensions/installs.d.ts +166 -0
- package/dist/extensions/installs.js +253 -0
- package/dist/extensions/instance.d.ts +167 -0
- package/dist/extensions/instance.js +329 -0
- package/dist/extensions/ledger.d.ts +30 -0
- package/dist/extensions/ledger.js +50 -0
- package/dist/extensions/lifecycle.d.ts +80 -0
- package/dist/extensions/lifecycle.js +152 -0
- package/dist/extensions/migrate-lock.d.ts +51 -0
- package/dist/extensions/migrate-lock.js +100 -0
- package/dist/extensions/org-config.controller.d.ts +24 -0
- package/dist/extensions/org-config.controller.js +59 -0
- package/dist/extensions/org-config.d.ts +169 -0
- package/dist/extensions/org-config.js +520 -0
- package/dist/extensions/package.d.ts +115 -0
- package/dist/extensions/package.js +246 -0
- package/dist/extensions/permission-set.d.ts +117 -0
- package/dist/extensions/permission-set.js +184 -0
- package/dist/extensions/permission-view.d.ts +194 -0
- package/dist/extensions/permission-view.js +284 -0
- package/dist/extensions/registry.d.ts +24 -0
- package/dist/extensions/registry.js +56 -0
- package/dist/extensions/resolve.d.ts +12 -0
- package/dist/extensions/resolve.js +71 -0
- package/dist/extensions/sources.d.ts +69 -0
- package/dist/extensions/sources.js +120 -0
- package/dist/extensions/sync.d.ts +40 -0
- package/dist/extensions/sync.js +242 -0
- package/dist/files/previewers.controller.d.ts +46 -0
- package/dist/files/previewers.controller.js +105 -0
- package/dist/files/previewers.d.ts +100 -0
- package/dist/files/previewers.js +250 -0
- package/dist/http/api.module.d.ts +114 -0
- package/dist/http/api.module.js +448 -0
- package/dist/http/app.d.ts +77 -0
- package/dist/http/app.js +220 -0
- package/dist/http/error.filter.d.ts +21 -0
- package/dist/http/error.filter.js +85 -0
- package/dist/http/gateway.module.d.ts +15 -0
- package/dist/http/gateway.module.js +13 -0
- package/dist/http/health.controller.d.ts +26 -0
- package/dist/http/health.controller.js +79 -0
- package/dist/http/nest-logger.d.ts +20 -0
- package/dist/http/nest-logger.js +28 -0
- package/dist/http/plugin-dispatch.d.ts +68 -0
- package/dist/http/plugin-dispatch.js +200 -0
- package/dist/http/tokens.d.ts +131 -0
- package/dist/http/tokens.js +131 -0
- package/dist/http/zod.pipe.d.ts +8 -0
- package/dist/http/zod.pipe.js +14 -0
- package/dist/identity/accounts.d.ts +93 -0
- package/dist/identity/accounts.js +367 -0
- package/dist/identity/api-tokens.d.ts +73 -0
- package/dist/identity/api-tokens.js +197 -0
- package/dist/identity/audit.d.ts +23 -0
- package/dist/identity/audit.js +41 -0
- package/dist/identity/auth.controller.d.ts +40 -0
- package/dist/identity/auth.controller.js +130 -0
- package/dist/identity/auth.guard.d.ts +41 -0
- package/dist/identity/auth.guard.js +162 -0
- package/dist/identity/binding.d.ts +47 -0
- package/dist/identity/binding.js +84 -0
- package/dist/identity/cookies.d.ts +16 -0
- package/dist/identity/cookies.js +32 -0
- package/dist/identity/credential-check.d.ts +17 -0
- package/dist/identity/credential-check.js +24 -0
- package/dist/identity/enterprise-admin.d.ts +14 -0
- package/dist/identity/enterprise-admin.js +27 -0
- package/dist/identity/external.d.ts +106 -0
- package/dist/identity/external.js +337 -0
- package/dist/identity/hash.d.ts +2 -0
- package/dist/identity/hash.js +3 -0
- package/dist/identity/login.d.ts +6 -0
- package/dist/identity/login.js +20 -0
- package/dist/identity/me.controller.d.ts +61 -0
- package/dist/identity/me.controller.js +159 -0
- package/dist/identity/passwords.d.ts +6 -0
- package/dist/identity/passwords.js +37 -0
- package/dist/identity/principal.d.ts +56 -0
- package/dist/identity/principal.js +38 -0
- package/dist/identity/rate-limit.d.ts +55 -0
- package/dist/identity/rate-limit.js +121 -0
- package/dist/identity/sessions.d.ts +84 -0
- package/dist/identity/sessions.js +306 -0
- package/dist/identity/settings.d.ts +121 -0
- package/dist/identity/settings.js +248 -0
- package/dist/identity/sso.controller.d.ts +59 -0
- package/dist/identity/sso.controller.js +192 -0
- package/dist/identity/sso.d.ts +83 -0
- package/dist/identity/sso.js +202 -0
- package/dist/inbox/inbox.service.d.ts +43 -0
- package/dist/inbox/inbox.service.js +57 -0
- package/dist/index.d.ts +69 -0
- package/dist/index.js +67 -0
- package/dist/kernel.d.ts +259 -0
- package/dist/kernel.js +1326 -0
- package/dist/log-config.d.ts +9 -0
- package/dist/log-config.js +27 -0
- package/dist/log-context.d.ts +32 -0
- package/dist/log-context.js +40 -0
- package/dist/log-loki.d.ts +34 -0
- package/dist/log-loki.js +145 -0
- package/dist/log.d.ts +79 -0
- package/dist/log.js +303 -0
- package/dist/models/prices.d.ts +53 -0
- package/dist/models/prices.js +121 -0
- package/dist/models/purposes.controller.d.ts +19 -0
- package/dist/models/purposes.controller.js +56 -0
- package/dist/models/purposes.d.ts +140 -0
- package/dist/models/purposes.js +267 -0
- package/dist/net/proxy.d.ts +44 -0
- package/dist/net/proxy.js +162 -0
- package/dist/net/public-address.d.ts +60 -0
- package/dist/net/public-address.js +272 -0
- package/dist/net/safe-fetch.d.ts +38 -0
- package/dist/net/safe-fetch.js +140 -0
- package/dist/orgs/directory-sync.controller.d.ts +14 -0
- package/dist/orgs/directory-sync.controller.js +40 -0
- package/dist/orgs/directory-sync.d.ts +166 -0
- package/dist/orgs/directory-sync.js +558 -0
- package/dist/orgs/invitations.controller.d.ts +58 -0
- package/dist/orgs/invitations.controller.js +137 -0
- package/dist/orgs/invitations.service.d.ts +80 -0
- package/dist/orgs/invitations.service.js +217 -0
- package/dist/orgs/members.service.d.ts +63 -0
- package/dist/orgs/members.service.js +234 -0
- package/dist/orgs/offboarding.d.ts +141 -0
- package/dist/orgs/offboarding.js +398 -0
- package/dist/orgs/org-lock.d.ts +32 -0
- package/dist/orgs/org-lock.js +46 -0
- package/dist/orgs/org.guard.d.ts +35 -0
- package/dist/orgs/org.guard.js +95 -0
- package/dist/orgs/orgs.controller.d.ts +78 -0
- package/dist/orgs/orgs.controller.js +192 -0
- package/dist/orgs/orgs.service.d.ts +61 -0
- package/dist/orgs/orgs.service.js +209 -0
- package/dist/orgs/roles.d.ts +13 -0
- package/dist/orgs/roles.js +58 -0
- package/dist/orgs/settings.controller.d.ts +20 -0
- package/dist/orgs/settings.controller.js +53 -0
- package/dist/orgs/settings.service.d.ts +120 -0
- package/dist/orgs/settings.service.js +178 -0
- package/dist/packages/npm.d.ts +50 -0
- package/dist/packages/npm.js +218 -0
- package/dist/packages/provenance.d.ts +47 -0
- package/dist/packages/provenance.js +147 -0
- package/dist/packages/tgz.d.ts +76 -0
- package/dist/packages/tgz.js +225 -0
- package/dist/runtime/abort.d.ts +32 -0
- package/dist/runtime/abort.js +71 -0
- package/dist/runtime/checkpointer.d.ts +32 -0
- package/dist/runtime/checkpointer.js +243 -0
- package/dist/runtime/context/build.d.ts +254 -0
- package/dist/runtime/context/build.js +693 -0
- package/dist/runtime/context/claude-tools.d.ts +11 -0
- package/dist/runtime/context/claude-tools.js +24 -0
- package/dist/runtime/context/compaction.d.ts +26 -0
- package/dist/runtime/context/compaction.js +195 -0
- package/dist/runtime/context/pairing.d.ts +11 -0
- package/dist/runtime/context/pairing.js +82 -0
- package/dist/runtime/context/reminders.d.ts +5 -0
- package/dist/runtime/context/reminders.js +11 -0
- package/dist/runtime/context/skills.d.ts +105 -0
- package/dist/runtime/context/skills.js +283 -0
- package/dist/runtime/context/tokens.d.ts +19 -0
- package/dist/runtime/context/tokens.js +104 -0
- package/dist/runtime/conversation-lock.d.ts +40 -0
- package/dist/runtime/conversation-lock.js +97 -0
- package/dist/runtime/hook-calls.d.ts +84 -0
- package/dist/runtime/hook-calls.js +136 -0
- package/dist/runtime/langgraph-loop.d.ts +52 -0
- package/dist/runtime/langgraph-loop.js +247 -0
- package/dist/runtime/loop.d.ts +93 -0
- package/dist/runtime/loop.js +7 -0
- package/dist/runtime/maintenance.d.ts +80 -0
- package/dist/runtime/maintenance.js +148 -0
- package/dist/runtime/media-cache.d.ts +21 -0
- package/dist/runtime/media-cache.js +51 -0
- package/dist/runtime/model-call.d.ts +176 -0
- package/dist/runtime/model-call.js +1049 -0
- package/dist/runtime/providers.d.ts +86 -0
- package/dist/runtime/providers.js +224 -0
- package/dist/runtime/quota.d.ts +29 -0
- package/dist/runtime/quota.js +70 -0
- package/dist/runtime/run-finish.d.ts +45 -0
- package/dist/runtime/run-finish.js +69 -0
- package/dist/runtime/run-queue.d.ts +121 -0
- package/dist/runtime/run-queue.js +493 -0
- package/dist/runtime/run-worker.d.ts +138 -0
- package/dist/runtime/run-worker.js +806 -0
- package/dist/runtime/stream.controller.d.ts +34 -0
- package/dist/runtime/stream.controller.js +122 -0
- package/dist/runtime/stream.d.ts +63 -0
- package/dist/runtime/stream.js +262 -0
- package/dist/runtime/subagents/child.d.ts +80 -0
- package/dist/runtime/subagents/child.js +225 -0
- package/dist/runtime/subagents/definition.d.ts +103 -0
- package/dist/runtime/subagents/definition.js +392 -0
- package/dist/runtime/subagents/dispatch.d.ts +69 -0
- package/dist/runtime/subagents/dispatch.js +502 -0
- package/dist/runtime/subagents/limits.d.ts +23 -0
- package/dist/runtime/subagents/limits.js +34 -0
- package/dist/runtime/subagents/org-agents.d.ts +50 -0
- package/dist/runtime/subagents/org-agents.js +70 -0
- package/dist/runtime/subagents/preamble.d.ts +7 -0
- package/dist/runtime/subagents/preamble.js +11 -0
- package/dist/runtime/subagents/progress.d.ts +26 -0
- package/dist/runtime/subagents/progress.js +36 -0
- package/dist/runtime/subagents/roster.d.ts +55 -0
- package/dist/runtime/subagents/roster.js +111 -0
- package/dist/runtime/subagents/skill-fork.d.ts +123 -0
- package/dist/runtime/subagents/skill-fork.js +259 -0
- package/dist/runtime/usage-report.d.ts +163 -0
- package/dist/runtime/usage-report.js +551 -0
- package/dist/runtime/waits.d.ts +233 -0
- package/dist/runtime/waits.js +883 -0
- package/dist/sandbox/leases.d.ts +169 -0
- package/dist/sandbox/leases.js +515 -0
- package/dist/sandbox/lifecycle.d.ts +21 -0
- package/dist/sandbox/lifecycle.js +68 -0
- package/dist/sandbox/sandbox.service.d.ts +249 -0
- package/dist/sandbox/sandbox.service.js +908 -0
- package/dist/skills/catalog.d.ts +149 -0
- package/dist/skills/catalog.js +405 -0
- package/dist/skills/changes.controller.d.ts +56 -0
- package/dist/skills/changes.controller.js +136 -0
- package/dist/skills/changes.service.d.ts +175 -0
- package/dist/skills/changes.service.js +805 -0
- package/dist/skills/invocable.controller.d.ts +23 -0
- package/dist/skills/invocable.controller.js +50 -0
- package/dist/skills/invocation-keys.d.ts +23 -0
- package/dist/skills/invocation-keys.js +44 -0
- package/dist/skills/invoke.d.ts +135 -0
- package/dist/skills/invoke.js +286 -0
- package/dist/skills/package.d.ts +87 -0
- package/dist/skills/package.js +227 -0
- package/dist/skills/skills.controller.d.ts +40 -0
- package/dist/skills/skills.controller.js +110 -0
- package/dist/skills/skills.service.d.ts +192 -0
- package/dist/skills/skills.service.js +567 -0
- package/dist/storage/prefix.d.ts +36 -0
- package/dist/storage/prefix.js +104 -0
- package/dist/storage/purge.d.ts +27 -0
- package/dist/storage/purge.js +75 -0
- package/dist/storage/storage.service.d.ts +44 -0
- package/dist/storage/storage.service.js +145 -0
- package/dist/text.d.ts +13 -0
- package/dist/text.js +13 -0
- package/dist/tools/approvals.controller.d.ts +53 -0
- package/dist/tools/approvals.controller.js +128 -0
- package/dist/tools/approvals.service.d.ts +172 -0
- package/dist/tools/approvals.service.js +568 -0
- package/dist/tools/breaker.d.ts +28 -0
- package/dist/tools/breaker.js +72 -0
- package/dist/tools/builtins/agent.d.ts +81 -0
- package/dist/tools/builtins/agent.js +223 -0
- package/dist/tools/builtins/ask-user.d.ts +28 -0
- package/dist/tools/builtins/ask-user.js +139 -0
- package/dist/tools/builtins/read-tool-output.d.ts +18 -0
- package/dist/tools/builtins/read-tool-output.js +108 -0
- package/dist/tools/builtins/sandbox/bash.d.ts +16 -0
- package/dist/tools/builtins/sandbox/bash.js +137 -0
- package/dist/tools/builtins/sandbox/common.d.ts +116 -0
- package/dist/tools/builtins/sandbox/common.js +306 -0
- package/dist/tools/builtins/sandbox/deliver.d.ts +5 -0
- package/dist/tools/builtins/sandbox/deliver.js +180 -0
- package/dist/tools/builtins/sandbox/edit.d.ts +4 -0
- package/dist/tools/builtins/sandbox/edit.js +98 -0
- package/dist/tools/builtins/sandbox/glob-match.d.ts +25 -0
- package/dist/tools/builtins/sandbox/glob-match.js +240 -0
- package/dist/tools/builtins/sandbox/glob.d.ts +4 -0
- package/dist/tools/builtins/sandbox/glob.js +104 -0
- package/dist/tools/builtins/sandbox/grep.d.ts +9 -0
- package/dist/tools/builtins/sandbox/grep.js +133 -0
- package/dist/tools/builtins/sandbox/index.d.ts +12 -0
- package/dist/tools/builtins/sandbox/index.js +27 -0
- package/dist/tools/builtins/sandbox/names.d.ts +7 -0
- package/dist/tools/builtins/sandbox/names.js +20 -0
- package/dist/tools/builtins/sandbox/read.d.ts +8 -0
- package/dist/tools/builtins/sandbox/read.js +121 -0
- package/dist/tools/builtins/sandbox/write.d.ts +4 -0
- package/dist/tools/builtins/sandbox/write.js +88 -0
- package/dist/tools/builtins/skill-load.d.ts +53 -0
- package/dist/tools/builtins/skill-load.js +446 -0
- package/dist/tools/builtins/skill-write.d.ts +59 -0
- package/dist/tools/builtins/skill-write.js +244 -0
- package/dist/tools/builtins/tool-search.d.ts +31 -0
- package/dist/tools/builtins/tool-search.js +171 -0
- package/dist/tools/connector-content.controller.d.ts +34 -0
- package/dist/tools/connector-content.controller.js +78 -0
- package/dist/tools/connector-content.d.ts +104 -0
- package/dist/tools/connector-content.js +267 -0
- package/dist/tools/connectors.controller.d.ts +210 -0
- package/dist/tools/connectors.controller.js +234 -0
- package/dist/tools/connectors.service.d.ts +303 -0
- package/dist/tools/connectors.service.js +1102 -0
- package/dist/tools/credentials.d.ts +139 -0
- package/dist/tools/credentials.js +351 -0
- package/dist/tools/drift.d.ts +141 -0
- package/dist/tools/drift.js +539 -0
- package/dist/tools/elicitation.d.ts +81 -0
- package/dist/tools/elicitation.js +266 -0
- package/dist/tools/endpoint.d.ts +18 -0
- package/dist/tools/endpoint.js +115 -0
- package/dist/tools/info.d.ts +67 -0
- package/dist/tools/info.js +113 -0
- package/dist/tools/naming.d.ts +27 -0
- package/dist/tools/naming.js +47 -0
- package/dist/tools/oauth/discovery.d.ts +65 -0
- package/dist/tools/oauth/discovery.js +307 -0
- package/dist/tools/oauth/flow.d.ts +63 -0
- package/dist/tools/oauth/flow.js +237 -0
- package/dist/tools/oauth/oauth.controller.d.ts +31 -0
- package/dist/tools/oauth/oauth.controller.js +95 -0
- package/dist/tools/oauth/tokens.d.ts +111 -0
- package/dist/tools/oauth/tokens.js +258 -0
- package/dist/tools/outputs.d.ts +61 -0
- package/dist/tools/outputs.js +156 -0
- package/dist/tools/pipeline.d.ts +322 -0
- package/dist/tools/pipeline.js +1236 -0
- package/dist/tools/policy.d.ts +60 -0
- package/dist/tools/policy.js +236 -0
- package/dist/tools/questions.controller.d.ts +24 -0
- package/dist/tools/questions.controller.js +58 -0
- package/dist/tools/questions.service.d.ts +103 -0
- package/dist/tools/questions.service.js +295 -0
- package/dist/tools/redact.d.ts +20 -0
- package/dist/tools/redact.js +60 -0
- package/dist/tools/registry.d.ts +246 -0
- package/dist/tools/registry.js +481 -0
- package/dist/tools/resources.d.ts +16 -0
- package/dist/tools/resources.js +76 -0
- package/dist/tools/specs.d.ts +14 -0
- package/dist/tools/specs.js +31 -0
- package/dist/tools/validate.d.ts +20 -0
- package/dist/tools/validate.js +183 -0
- package/dist/tools/view.d.ts +43 -0
- package/dist/tools/view.js +225 -0
- package/dist/ui/embed-token.d.ts +31 -0
- package/dist/ui/embed-token.js +132 -0
- package/dist/ui/registry.d.ts +58 -0
- package/dist/ui/registry.js +90 -0
- package/dist/ui/ui-stream.d.ts +37 -0
- package/dist/ui/ui-stream.js +162 -0
- package/dist/ui/views.controller.d.ts +81 -0
- package/dist/ui/views.controller.js +261 -0
- package/dist/ui/views.d.ts +155 -0
- package/dist/ui/views.js +306 -0
- package/dist/version.d.ts +5 -0
- package/dist/version.js +6 -0
- package/package.json +69 -3
- package/src/migrations/0001_init.sql +8 -0
- package/src/migrations/0002_secrets.sql +8 -0
- package/src/migrations/0003_identity.sql +117 -0
- package/src/migrations/0004_plugin_org_config_nullable.sql +3 -0
- package/src/migrations/0005_agents.sql +27 -0
- package/src/migrations/0006_conversations.sql +37 -0
- package/src/migrations/0007_checkpoints.sql +26 -0
- package/src/migrations/0008_runs_trigger_seq.sql +3 -0
- package/src/migrations/0009_runs_active_unique.sql +4 -0
- package/src/migrations/0010_tools.sql +125 -0
- package/src/migrations/0011_approvals_spec.sql +10 -0
- package/src/migrations/0012_run_waits.sql +24 -0
- package/src/migrations/0013_app_tools_source.sql +4 -0
- package/src/migrations/0014_tool_specs.sql +8 -0
- package/src/migrations/0015_tool_drift.sql +20 -0
- package/src/migrations/0016_plugin_permissions.sql +11 -0
- package/src/migrations/0017_identity_sources.sql +6 -0
- package/src/migrations/0018_channels.sql +74 -0
- package/src/migrations/0019_identity_trust.sql +17 -0
- package/src/migrations/0020_channel_card_lookup.sql +10 -0
- package/src/migrations/0021_org_storage_purge.sql +9 -0
- package/src/migrations/0022_attachments.sql +29 -0
- package/src/migrations/0023_sandboxes.sql +37 -0
- package/src/migrations/0024_skills.sql +46 -0
- package/src/migrations/0025_skills_catalog_idx.sql +6 -0
- package/src/migrations/0026_skill_changes.sql +34 -0
- package/src/migrations/0027_model_prices.sql +18 -0
- package/src/migrations/0028_evals.sql +105 -0
- package/src/migrations/0029_model_purposes.sql +18 -0
- package/src/migrations/0030_plugin_installs.sql +73 -0
- package/src/migrations/0031_plugin_snapshot_source.sql +6 -0
- package/src/migrations/0032_plugin_deployment_configs.sql +10 -0
- package/src/migrations/0033_rename_apps_to_connectors.sql +25 -0
- package/src/migrations/0034_directory.sql +49 -0
- package/src/migrations/0035_catalogs.sql +40 -0
- package/src/migrations/0036_app_import_staging.sql +17 -0
- package/src/migrations/0037_directory_installs.sql +92 -0
- package/src/migrations/0038_channel_inbound_mode.sql +6 -0
- package/src/migrations/0039_channel_card_pending.sql +8 -0
- package/src/migrations/0040_usage_report_sweep.sql +10 -0
- package/src/migrations/0041_rename_plugins_to_extensions.sql +38 -0
- package/src/migrations/0042_rename_directory_to_catalog.sql +80 -0
- package/src/migrations/0043_rename_app_installs_to_plugin_installs.sql +20 -0
- package/src/migrations/0044_catalog_one_kind.sql +90 -0
- package/src/migrations/0045_plugin_dependencies.sql +9 -0
- package/src/migrations/0046_git_sources.sql +25 -0
- package/src/migrations/0047_marketplace_entry_heads.sql +7 -0
- package/src/migrations/0048_marketplace_entry_trees.sql +8 -0
- package/src/migrations/0049_plugin_upgrades.sql +37 -0
- package/src/migrations/0050_bootstrap.sql +53 -0
- package/src/migrations/0051_claude_compat.sql +26 -0
- package/src/migrations/0052_conversations_account_agent_idx.sql +5 -0
- package/src/migrations/0053_subagents.sql +73 -0
- package/src/migrations/0054_subagent_wait_expiry.sql +7 -0
- package/src/migrations/0055_subagent_parent_indexes.sql +10 -0
- package/src/migrations/0056_approval_reason.sql +3 -0
- package/src/migrations/0057_conversation_titles.sql +11 -0
- package/src/migrations/0058_conversation_selection.sql +4 -0
- package/src/migrations/0059_conversation_queue.sql +22 -0
- package/src/migrations/0060_file_previewers.sql +10 -0
- package/src/migrations/0061_queue_selection.sql +5 -0
- package/src/migrations/0062_queued_skill.sql +8 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { FastifyReply, FastifyRequest } from "fastify";
|
|
2
|
+
import type { KernelConfig } from "../config/schema.js";
|
|
3
|
+
import type { AccountsService } from "./accounts.js";
|
|
4
|
+
import type { IdentityBinding, PendingBinding } from "./binding.js";
|
|
5
|
+
import type { ExternalIdentities, LinkedIdentity } from "./external.js";
|
|
6
|
+
import { type Principal } from "./principal.js";
|
|
7
|
+
import type { SessionService } from "./sessions.js";
|
|
8
|
+
import { type SsoFlow } from "./sso.js";
|
|
9
|
+
/**
|
|
10
|
+
* 第三方登录(`/api/v1/auth/sources`、`/api/v1/auth/sso/:plugin/*`,均为公开路由)。浏览器整页跳转,
|
|
11
|
+
* 发起与回调都以 302 结束;失败回登录页并带原因码(`/login?error=<code>`),不回显身份源文本。
|
|
12
|
+
*/
|
|
13
|
+
export declare class SsoController {
|
|
14
|
+
private readonly flow;
|
|
15
|
+
private readonly sessions;
|
|
16
|
+
private readonly accounts;
|
|
17
|
+
private readonly config;
|
|
18
|
+
constructor(flow: SsoFlow, sessions: SessionService, accounts: AccountsService, config: () => KernelConfig);
|
|
19
|
+
sources(): {
|
|
20
|
+
sources: {
|
|
21
|
+
plugin: string;
|
|
22
|
+
label: {
|
|
23
|
+
zh: string;
|
|
24
|
+
en: string;
|
|
25
|
+
};
|
|
26
|
+
}[];
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* 发起登录:302 到身份源的授权地址,并写浏览器绑定 Cookie `cap_sso`(HttpOnly、SameSite=Lax——身份源回跳是
|
|
30
|
+
* 跨站顶级 GET 导航,Lax 会带上;Path 只到 `/api/v1/auth/sso`)。已登录的用户同样可以发起(见 callback)。
|
|
31
|
+
*/
|
|
32
|
+
start(plugin: string, returnTo: unknown, principal: Principal | undefined, req: FastifyRequest, reply: FastifyReply): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* 身份源回跳:核对 state 与绑定 Cookie → 插件换取外部身份 → 解析到账号 → 建会话、写会话 Cookie → 302 回网页
|
|
35
|
+
* (`http.publicUrl` + returnTo)。账号已停用 → 登录页 `auth.account_disabled`,不建会话。
|
|
36
|
+
* 请求已带着 Web 会话时(已登录的用户发起,「登录状态下绑定」),把会话的账号交给 `SsoFlow.callback`:
|
|
37
|
+
* 与发起时记下的会话账号相同,经 IM 绑定建立的同一账号的身份才由此升级为可登录(Ruling A18)。
|
|
38
|
+
*/
|
|
39
|
+
callback(plugin: string, q: Record<string, unknown>, principal: Principal | undefined, req: FastifyRequest, reply: FastifyReply): Promise<void>;
|
|
40
|
+
}
|
|
41
|
+
export declare class BindController {
|
|
42
|
+
private readonly binding;
|
|
43
|
+
constructor(binding: IdentityBinding);
|
|
44
|
+
peek(principal: Principal, token: string): Promise<{
|
|
45
|
+
binding: PendingBinding;
|
|
46
|
+
}>;
|
|
47
|
+
bind(principal: Principal, token: string): Promise<{
|
|
48
|
+
binding: PendingBinding;
|
|
49
|
+
}>;
|
|
50
|
+
}
|
|
51
|
+
/** 本人绑定的外部身份(`/api/v1/me/identities`):列出、解除。 */
|
|
52
|
+
export declare class MeIdentitiesController {
|
|
53
|
+
private readonly external;
|
|
54
|
+
constructor(external: ExternalIdentities);
|
|
55
|
+
list(principal: Principal): Promise<{
|
|
56
|
+
identities: LinkedIdentity[];
|
|
57
|
+
}>;
|
|
58
|
+
unlink(principal: Principal, source: string, externalId: string): Promise<void>;
|
|
59
|
+
}
|
|
@@ -0,0 +1,192 @@
|
|
|
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, Delete, Get, HttpCode, Inject, Param, Post, Query, Req, Res, } from "@nestjs/common";
|
|
11
|
+
import { ACCOUNTS, EXTERNAL_IDENTITIES, IDENTITY_BINDING, KERNEL_CONFIG, SESSIONS, SSO_FLOW, } from "../http/tokens.js";
|
|
12
|
+
import { clientMeta } from "./auth.controller.js";
|
|
13
|
+
import { setSessionCookies } from "./cookies.js";
|
|
14
|
+
import { CurrentPrincipal, Public, requireUser, SessionOnly } from "./principal.js";
|
|
15
|
+
import { SSO_BINDING_COOKIE, SSO_COOKIE_PATH, SSO_STATE_TTL_SECONDS, ssoBrowserBinding, } from "./sso.js";
|
|
16
|
+
const MAX_QUERY_KEYS = 50;
|
|
17
|
+
const MAX_QUERY_VALUE = 4096;
|
|
18
|
+
/** 查询参数只取单值字符串(重复参数 / 数组 / 超长值丢弃)。 */
|
|
19
|
+
function stringQuery(q) {
|
|
20
|
+
const out = {};
|
|
21
|
+
for (const [k, v] of Object.entries(q).slice(0, MAX_QUERY_KEYS)) {
|
|
22
|
+
if (typeof v === "string" && v.length <= MAX_QUERY_VALUE)
|
|
23
|
+
out[k] = v;
|
|
24
|
+
}
|
|
25
|
+
return out;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* 第三方登录(`/api/v1/auth/sources`、`/api/v1/auth/sso/:plugin/*`,均为公开路由)。浏览器整页跳转,
|
|
29
|
+
* 发起与回调都以 302 结束;失败回登录页并带原因码(`/login?error=<code>`),不回显身份源文本。
|
|
30
|
+
*/
|
|
31
|
+
let SsoController = class SsoController {
|
|
32
|
+
flow;
|
|
33
|
+
sessions;
|
|
34
|
+
accounts;
|
|
35
|
+
config;
|
|
36
|
+
constructor(flow, sessions, accounts, config) {
|
|
37
|
+
this.flow = flow;
|
|
38
|
+
this.sessions = sessions;
|
|
39
|
+
this.accounts = accounts;
|
|
40
|
+
this.config = config;
|
|
41
|
+
}
|
|
42
|
+
sources() {
|
|
43
|
+
return { sources: this.flow.sources() };
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* 发起登录:302 到身份源的授权地址,并写浏览器绑定 Cookie `cap_sso`(HttpOnly、SameSite=Lax——身份源回跳是
|
|
47
|
+
* 跨站顶级 GET 导航,Lax 会带上;Path 只到 `/api/v1/auth/sso`)。已登录的用户同样可以发起(见 callback)。
|
|
48
|
+
*/
|
|
49
|
+
async start(plugin, returnTo, principal, req, reply) {
|
|
50
|
+
const binding = ssoBrowserBinding(req.cookies[SSO_BINDING_COOKIE]);
|
|
51
|
+
// 发起时的会话账号记进 state:回调时同一账号才升级经 IM 绑定的身份(见 callback)
|
|
52
|
+
const location = await this.flow.start(plugin, typeof returnTo === "string" ? returnTo : undefined, binding, sessionAccount(principal));
|
|
53
|
+
reply.setCookie(SSO_BINDING_COOKIE, binding, {
|
|
54
|
+
path: SSO_COOKIE_PATH,
|
|
55
|
+
httpOnly: true,
|
|
56
|
+
sameSite: "lax",
|
|
57
|
+
secure: this.flow.cookieSecure(),
|
|
58
|
+
maxAge: SSO_STATE_TTL_SECONDS,
|
|
59
|
+
});
|
|
60
|
+
await reply.header("cache-control", "no-store").redirect(location, 302);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* 身份源回跳:核对 state 与绑定 Cookie → 插件换取外部身份 → 解析到账号 → 建会话、写会话 Cookie → 302 回网页
|
|
64
|
+
* (`http.publicUrl` + returnTo)。账号已停用 → 登录页 `auth.account_disabled`,不建会话。
|
|
65
|
+
* 请求已带着 Web 会话时(已登录的用户发起,「登录状态下绑定」),把会话的账号交给 `SsoFlow.callback`:
|
|
66
|
+
* 与发起时记下的会话账号相同,经 IM 绑定建立的同一账号的身份才由此升级为可登录(Ruling A18)。
|
|
67
|
+
*/
|
|
68
|
+
async callback(plugin, q, principal, req, reply) {
|
|
69
|
+
const r = await this.flow.callback(plugin, stringQuery(q), req.cookies[SSO_BINDING_COOKIE], sessionAccount(principal));
|
|
70
|
+
let location;
|
|
71
|
+
if (!r.ok) {
|
|
72
|
+
location = this.flow.loginError(r.error);
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
const account = await this.accounts.get(r.accountId);
|
|
76
|
+
if (account?.status !== "active") {
|
|
77
|
+
location = this.flow.loginError("auth.account_disabled");
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
const session = await this.sessions.create(account.id, clientMeta(req));
|
|
81
|
+
setSessionCookies(reply, session, this.config());
|
|
82
|
+
location = this.flow.webUrl(r.returnTo);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
reply.clearCookie(SSO_BINDING_COOKIE, { path: SSO_COOKIE_PATH });
|
|
86
|
+
await reply.header("cache-control", "no-store").redirect(location, 302);
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
__decorate([
|
|
90
|
+
Get("sources"),
|
|
91
|
+
Public()
|
|
92
|
+
], SsoController.prototype, "sources", null);
|
|
93
|
+
__decorate([
|
|
94
|
+
Get("sso/:plugin/start"),
|
|
95
|
+
Public(),
|
|
96
|
+
__param(0, Param("plugin")),
|
|
97
|
+
__param(1, Query("returnTo")),
|
|
98
|
+
__param(2, CurrentPrincipal()),
|
|
99
|
+
__param(3, Req()),
|
|
100
|
+
__param(4, Res())
|
|
101
|
+
], SsoController.prototype, "start", null);
|
|
102
|
+
__decorate([
|
|
103
|
+
Get("sso/:plugin/callback"),
|
|
104
|
+
Public(),
|
|
105
|
+
__param(0, Param("plugin")),
|
|
106
|
+
__param(1, Query()),
|
|
107
|
+
__param(2, CurrentPrincipal()),
|
|
108
|
+
__param(3, Req()),
|
|
109
|
+
__param(4, Res())
|
|
110
|
+
], SsoController.prototype, "callback", null);
|
|
111
|
+
SsoController = __decorate([
|
|
112
|
+
Controller("api/v1/auth"),
|
|
113
|
+
__param(0, Inject(SSO_FLOW)),
|
|
114
|
+
__param(1, Inject(SESSIONS)),
|
|
115
|
+
__param(2, Inject(ACCOUNTS)),
|
|
116
|
+
__param(3, Inject(KERNEL_CONFIG))
|
|
117
|
+
], SsoController);
|
|
118
|
+
export { SsoController };
|
|
119
|
+
/**
|
|
120
|
+
* IM 身份绑定确认(`/api/v1/bind/:token`,需 Web 会话):GET 查看待绑定的身份,POST 绑到当前账号。
|
|
121
|
+
* 令牌单次有效;身份已绑定他人 → 409 `identity.taken`。
|
|
122
|
+
*/
|
|
123
|
+
/** 请求带着的 Web 会话的账号(PAT / 未登录时 undefined)。 */
|
|
124
|
+
function sessionAccount(principal) {
|
|
125
|
+
return principal?.kind === "user" && principal.via === "session"
|
|
126
|
+
? principal.account.id
|
|
127
|
+
: undefined;
|
|
128
|
+
}
|
|
129
|
+
let BindController = class BindController {
|
|
130
|
+
binding;
|
|
131
|
+
constructor(binding) {
|
|
132
|
+
this.binding = binding;
|
|
133
|
+
}
|
|
134
|
+
async peek(principal, token) {
|
|
135
|
+
requireUser(principal);
|
|
136
|
+
return { binding: await this.binding.peek(token) };
|
|
137
|
+
}
|
|
138
|
+
async bind(principal, token) {
|
|
139
|
+
const p = requireUser(principal);
|
|
140
|
+
return { binding: await this.binding.bind(token, p.account.id) };
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
__decorate([
|
|
144
|
+
Get(":token"),
|
|
145
|
+
SessionOnly(),
|
|
146
|
+
__param(0, CurrentPrincipal()),
|
|
147
|
+
__param(1, Param("token"))
|
|
148
|
+
], BindController.prototype, "peek", null);
|
|
149
|
+
__decorate([
|
|
150
|
+
Post(":token"),
|
|
151
|
+
SessionOnly(),
|
|
152
|
+
HttpCode(200),
|
|
153
|
+
__param(0, CurrentPrincipal()),
|
|
154
|
+
__param(1, Param("token"))
|
|
155
|
+
], BindController.prototype, "bind", null);
|
|
156
|
+
BindController = __decorate([
|
|
157
|
+
Controller("api/v1/bind"),
|
|
158
|
+
__param(0, Inject(IDENTITY_BINDING))
|
|
159
|
+
], BindController);
|
|
160
|
+
export { BindController };
|
|
161
|
+
/** 本人绑定的外部身份(`/api/v1/me/identities`):列出、解除。 */
|
|
162
|
+
let MeIdentitiesController = class MeIdentitiesController {
|
|
163
|
+
external;
|
|
164
|
+
constructor(external) {
|
|
165
|
+
this.external = external;
|
|
166
|
+
}
|
|
167
|
+
async list(principal) {
|
|
168
|
+
const p = requireUser(principal);
|
|
169
|
+
return { identities: await this.external.listForAccount(p.account.id) };
|
|
170
|
+
}
|
|
171
|
+
async unlink(principal, source, externalId) {
|
|
172
|
+
const p = requireUser(principal);
|
|
173
|
+
await this.external.unlink(p.account.id, source, externalId);
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
__decorate([
|
|
177
|
+
Get(),
|
|
178
|
+
__param(0, CurrentPrincipal())
|
|
179
|
+
], MeIdentitiesController.prototype, "list", null);
|
|
180
|
+
__decorate([
|
|
181
|
+
Delete(":source/:externalId"),
|
|
182
|
+
SessionOnly(),
|
|
183
|
+
HttpCode(204),
|
|
184
|
+
__param(0, CurrentPrincipal()),
|
|
185
|
+
__param(1, Param("source")),
|
|
186
|
+
__param(2, Param("externalId"))
|
|
187
|
+
], MeIdentitiesController.prototype, "unlink", null);
|
|
188
|
+
MeIdentitiesController = __decorate([
|
|
189
|
+
Controller("api/v1/me/identities"),
|
|
190
|
+
__param(0, Inject(EXTERNAL_IDENTITIES))
|
|
191
|
+
], MeIdentitiesController);
|
|
192
|
+
export { MeIdentitiesController };
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { type Logger } from "@capybara-hq/plugin-sdk";
|
|
2
|
+
import type { Redis } from "ioredis";
|
|
3
|
+
import type { KernelConfig } from "../config/schema.js";
|
|
4
|
+
import type { ExtensionHost } from "../extensions/host.js";
|
|
5
|
+
import { type ExternalIdentities } from "./external.js";
|
|
6
|
+
/** state 的有效期(秒)。 */
|
|
7
|
+
export declare const SSO_STATE_TTL_SECONDS = 600;
|
|
8
|
+
/** 浏览器绑定 Cookie:回调必须来自发起登录的同一个浏览器(防登录 CSRF / 把回跳链接转给别人)。 */
|
|
9
|
+
export declare const SSO_BINDING_COOKIE = "cap_sso";
|
|
10
|
+
/** 绑定 Cookie 的 Path:覆盖所有插件的回调。 */
|
|
11
|
+
export declare const SSO_COOKIE_PATH = "/api/v1/auth/sso";
|
|
12
|
+
/** 登录失败回到的网页(next-intl 会补语言前缀)。 */
|
|
13
|
+
export declare const LOGIN_PATH = "/login";
|
|
14
|
+
/** 插件 `callback` 的最长等待。 */
|
|
15
|
+
export declare const SSO_CALLBACK_TIMEOUT_MS = 15000;
|
|
16
|
+
/**
|
|
17
|
+
* 登录失败的原因码(放进回跳 URL `/login?error=<code>`,界面按码走 i18n;不回显身份源的任何文本)。
|
|
18
|
+
* `auth.account_disabled` 与 API 错误码同名。
|
|
19
|
+
*/
|
|
20
|
+
export type SsoLoginError = "sso.unavailable" | "sso.state_invalid" | "sso.session_mismatch" | "sso.access_denied" | "sso.provider_error" | "sso.identity_not_verified" | "auth.account_disabled";
|
|
21
|
+
/** 一个有效的浏览器绑定值(复用请求里已有的,否则新生成)。 */
|
|
22
|
+
export declare function ssoBrowserBinding(existing: string | undefined): string;
|
|
23
|
+
/** 回跳页面:站内相对路径(以单个 `/` 开头,非 `//`),否则 `/`(防开放重定向)。 */
|
|
24
|
+
export declare function safeReturnTo(p: string | undefined): string;
|
|
25
|
+
export interface SsoFlowDeps {
|
|
26
|
+
redis: Redis;
|
|
27
|
+
config: () => KernelConfig;
|
|
28
|
+
host: Pick<ExtensionHost, "list" | "deploymentConfig">;
|
|
29
|
+
external: ExternalIdentities;
|
|
30
|
+
log: Pick<Logger, "warn">;
|
|
31
|
+
}
|
|
32
|
+
/** 回调结果:成功给账号与回跳页面,失败给原因码。 */
|
|
33
|
+
export type SsoCallbackResult = {
|
|
34
|
+
ok: true;
|
|
35
|
+
accountId: string;
|
|
36
|
+
returnTo: string;
|
|
37
|
+
} | {
|
|
38
|
+
ok: false;
|
|
39
|
+
error: SsoLoginError;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* 第三方登录(`identity-source@1`):发起时生成 state(32 字节随机串,Redis `capk:sso-state:<state>` 10 分钟、
|
|
43
|
+
* 单次有效,内含插件名、nonce、PKCE verifier、redirect_uri、回跳页面与浏览器绑定值的哈希),授权地址带 PKCE
|
|
44
|
+
* challenge(S256);回调时先取后删 state、核对绑定 Cookie,再交给插件(连同 verifier)换取外部身份并解析到账号。
|
|
45
|
+
* 会话由 controller 在成功后创建。状态全部在 Redis,没有进程内状态。
|
|
46
|
+
*
|
|
47
|
+
* 已登录的用户也可以发起(「登录状态下绑定」):回调请求带着同一账号的 Web 会话时,经 IM 绑定链接建立的身份
|
|
48
|
+
* 由此证明本人控制该外部身份,升级为可登录(Ruling A18,见 `ExternalIdentities.resolve`)。
|
|
49
|
+
*/
|
|
50
|
+
export declare class SsoFlow {
|
|
51
|
+
private readonly deps;
|
|
52
|
+
constructor(deps: SsoFlowDeps);
|
|
53
|
+
/** 已启用的登录方式:`auth.loginSources` 中(按其顺序)且已加载、提供 `identity-source@1` 的插件。 */
|
|
54
|
+
sources(): {
|
|
55
|
+
plugin: string;
|
|
56
|
+
label: {
|
|
57
|
+
zh: string;
|
|
58
|
+
en: string;
|
|
59
|
+
};
|
|
60
|
+
}[];
|
|
61
|
+
private provider;
|
|
62
|
+
private redirectUri;
|
|
63
|
+
/** 绑定 Cookie 是否加 Secure:`auth.cookieSecure`,或 `http.publicUrl` 是 https(浏览器经 https 访问)。 */
|
|
64
|
+
cookieSecure(): boolean;
|
|
65
|
+
/** 网页地址:`http.publicUrl` + 站内路径(未配置 publicUrl 时为相对地址)。 */
|
|
66
|
+
webUrl(path: string): string;
|
|
67
|
+
/** 登录页并带原因码。 */
|
|
68
|
+
loginError(code: SsoLoginError): string;
|
|
69
|
+
/**
|
|
70
|
+
* 发起登录,返回 302 目标:插件的授权地址;插件未启用、未配置 `http.publicUrl` 或插件出错 → 登录页 `sso.unavailable`。
|
|
71
|
+
* `binding` 为本浏览器的绑定值(由 controller 写入 Cookie);`sessionAccountId` 为发起请求带着的 Web 会话账号。
|
|
72
|
+
*/
|
|
73
|
+
start(plugin: string, returnTo: string | undefined, binding: string, sessionAccountId?: string): Promise<string>;
|
|
74
|
+
/**
|
|
75
|
+
* 处理身份源的回跳。state 先取后删(无论成败都不能再用);state 属于别的插件 → `sso.state_invalid`;
|
|
76
|
+
* 绑定 Cookie 不符 → `sso.session_mismatch`;身份源报错只映射为原因码;插件交回的身份源键必须由内核推导得出
|
|
77
|
+
* (`${插件名}:${identity.tenantId}`,Ruling A19),否则按 `sso.provider_error` 拒绝。
|
|
78
|
+
* 身份行经 IM 绑定建立、且发起与回调时不是同一个已登录的本人账号 → `sso.identity_not_verified`
|
|
79
|
+
* (Ruling A18)。成功则解析到账号(不判断账号状态,由调用方处理)。
|
|
80
|
+
* `sessionAccountId`:回调请求已带着的 Web 会话的账号(未登录时省略)。
|
|
81
|
+
*/
|
|
82
|
+
callback(plugin: string, query: Record<string, string>, binding: string | undefined, sessionAccountId?: string): Promise<SsoCallbackResult>;
|
|
83
|
+
}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { createHash, randomBytes, timingSafeEqual } from "node:crypto";
|
|
2
|
+
import { IDENTITY_SOURCE_EXTENSION_POINT, } from "@capybara-hq/plugin-sdk";
|
|
3
|
+
import { ApiError } from "../errors.js";
|
|
4
|
+
import { isSafeReturnPath } from "../tools/oauth/flow.js";
|
|
5
|
+
import { IdentityNotVerified } from "./external.js";
|
|
6
|
+
/** state 的有效期(秒)。 */
|
|
7
|
+
export const SSO_STATE_TTL_SECONDS = 600;
|
|
8
|
+
/** 浏览器绑定 Cookie:回调必须来自发起登录的同一个浏览器(防登录 CSRF / 把回跳链接转给别人)。 */
|
|
9
|
+
export const SSO_BINDING_COOKIE = "cap_sso";
|
|
10
|
+
/** 绑定 Cookie 的 Path:覆盖所有插件的回调。 */
|
|
11
|
+
export const SSO_COOKIE_PATH = "/api/v1/auth/sso";
|
|
12
|
+
/** 登录失败回到的网页(next-intl 会补语言前缀)。 */
|
|
13
|
+
export const LOGIN_PATH = "/login";
|
|
14
|
+
/** 插件 `callback` 的最长等待。 */
|
|
15
|
+
export const SSO_CALLBACK_TIMEOUT_MS = 15_000;
|
|
16
|
+
const stateKey = (state) => `capk:sso-state:${state}`;
|
|
17
|
+
const STATE_RE = /^[A-Za-z0-9_-]{43}$/;
|
|
18
|
+
const BINDING_RE = /^[A-Za-z0-9_-]{43}$/;
|
|
19
|
+
const b64url = (n = 32) => randomBytes(n).toString("base64url");
|
|
20
|
+
const sha256 = (s) => createHash("sha256").update(s).digest("base64url");
|
|
21
|
+
/** 常量时间比较两个 base64url 哈希(长度不同直接不等)。 */
|
|
22
|
+
function sameHash(a, b) {
|
|
23
|
+
const x = Buffer.from(a);
|
|
24
|
+
const y = Buffer.from(b);
|
|
25
|
+
return x.length === y.length && timingSafeEqual(x, y);
|
|
26
|
+
}
|
|
27
|
+
/** 一个有效的浏览器绑定值(复用请求里已有的,否则新生成)。 */
|
|
28
|
+
export function ssoBrowserBinding(existing) {
|
|
29
|
+
return existing !== undefined && BINDING_RE.test(existing) ? existing : b64url();
|
|
30
|
+
}
|
|
31
|
+
/** 回跳页面:站内相对路径(以单个 `/` 开头,非 `//`),否则 `/`(防开放重定向)。 */
|
|
32
|
+
export function safeReturnTo(p) {
|
|
33
|
+
return p !== undefined && isSafeReturnPath(p) ? p : "/";
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* 第三方登录(`identity-source@1`):发起时生成 state(32 字节随机串,Redis `capk:sso-state:<state>` 10 分钟、
|
|
37
|
+
* 单次有效,内含插件名、nonce、PKCE verifier、redirect_uri、回跳页面与浏览器绑定值的哈希),授权地址带 PKCE
|
|
38
|
+
* challenge(S256);回调时先取后删 state、核对绑定 Cookie,再交给插件(连同 verifier)换取外部身份并解析到账号。
|
|
39
|
+
* 会话由 controller 在成功后创建。状态全部在 Redis,没有进程内状态。
|
|
40
|
+
*
|
|
41
|
+
* 已登录的用户也可以发起(「登录状态下绑定」):回调请求带着同一账号的 Web 会话时,经 IM 绑定链接建立的身份
|
|
42
|
+
* 由此证明本人控制该外部身份,升级为可登录(Ruling A18,见 `ExternalIdentities.resolve`)。
|
|
43
|
+
*/
|
|
44
|
+
export class SsoFlow {
|
|
45
|
+
deps;
|
|
46
|
+
constructor(deps) {
|
|
47
|
+
this.deps = deps;
|
|
48
|
+
}
|
|
49
|
+
/** 已启用的登录方式:`auth.loginSources` 中(按其顺序)且已加载、提供 `identity-source@1` 的插件。 */
|
|
50
|
+
sources() {
|
|
51
|
+
return this.deps.config().auth.loginSources.flatMap((plugin) => {
|
|
52
|
+
const src = this.provider(plugin);
|
|
53
|
+
return src ? [{ plugin, label: { zh: src.label.zh, en: src.label.en } }] : [];
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
provider(plugin) {
|
|
57
|
+
if (!this.deps.config().auth.loginSources.includes(plugin))
|
|
58
|
+
return undefined;
|
|
59
|
+
const entry = this.deps.host
|
|
60
|
+
.list("identity-source")
|
|
61
|
+
.find((e) => e.plugin === plugin && e.capability === IDENTITY_SOURCE_EXTENSION_POINT);
|
|
62
|
+
return entry?.impl;
|
|
63
|
+
}
|
|
64
|
+
redirectUri(plugin) {
|
|
65
|
+
const base = (this.deps.config().http.publicUrl ?? "").replace(/\/+$/, "");
|
|
66
|
+
return `${base}/api/v1/auth/sso/${encodeURIComponent(plugin)}/callback`;
|
|
67
|
+
}
|
|
68
|
+
/** 绑定 Cookie 是否加 Secure:`auth.cookieSecure`,或 `http.publicUrl` 是 https(浏览器经 https 访问)。 */
|
|
69
|
+
cookieSecure() {
|
|
70
|
+
const cfg = this.deps.config();
|
|
71
|
+
return cfg.auth.cookieSecure || (cfg.http.publicUrl ?? "").startsWith("https:");
|
|
72
|
+
}
|
|
73
|
+
/** 网页地址:`http.publicUrl` + 站内路径(未配置 publicUrl 时为相对地址)。 */
|
|
74
|
+
webUrl(path) {
|
|
75
|
+
const base = (this.deps.config().http.publicUrl ?? "").replace(/\/+$/, "");
|
|
76
|
+
return `${base}${path}`;
|
|
77
|
+
}
|
|
78
|
+
/** 登录页并带原因码。 */
|
|
79
|
+
loginError(code) {
|
|
80
|
+
return this.webUrl(`${LOGIN_PATH}?error=${encodeURIComponent(code)}`);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* 发起登录,返回 302 目标:插件的授权地址;插件未启用、未配置 `http.publicUrl` 或插件出错 → 登录页 `sso.unavailable`。
|
|
84
|
+
* `binding` 为本浏览器的绑定值(由 controller 写入 Cookie);`sessionAccountId` 为发起请求带着的 Web 会话账号。
|
|
85
|
+
*/
|
|
86
|
+
async start(plugin, returnTo, binding, sessionAccountId) {
|
|
87
|
+
const src = this.provider(plugin);
|
|
88
|
+
if (!src || !this.deps.config().http.publicUrl)
|
|
89
|
+
return this.loginError("sso.unavailable");
|
|
90
|
+
const state = b64url();
|
|
91
|
+
const nonce = b64url();
|
|
92
|
+
const codeVerifier = b64url();
|
|
93
|
+
const redirectUri = this.redirectUri(plugin);
|
|
94
|
+
let url;
|
|
95
|
+
try {
|
|
96
|
+
url = src.authorizeUrl({
|
|
97
|
+
config: this.deps.host.deploymentConfig(plugin),
|
|
98
|
+
redirectUri,
|
|
99
|
+
state,
|
|
100
|
+
nonce,
|
|
101
|
+
codeChallenge: sha256(codeVerifier),
|
|
102
|
+
codeChallengeMethod: "S256",
|
|
103
|
+
});
|
|
104
|
+
const proto = new URL(url).protocol;
|
|
105
|
+
if (proto !== "https:" && proto !== "http:")
|
|
106
|
+
throw new Error("authorize URL must be http(s)");
|
|
107
|
+
}
|
|
108
|
+
catch (err) {
|
|
109
|
+
this.deps.log.warn("identity source authorizeUrl failed", { plugin, err });
|
|
110
|
+
return this.loginError("sso.unavailable");
|
|
111
|
+
}
|
|
112
|
+
const rec = {
|
|
113
|
+
plugin,
|
|
114
|
+
nonce,
|
|
115
|
+
redirectUri,
|
|
116
|
+
returnTo: safeReturnTo(returnTo),
|
|
117
|
+
binding: sha256(binding),
|
|
118
|
+
codeVerifier,
|
|
119
|
+
...(sessionAccountId !== undefined && { sessionAccountId }),
|
|
120
|
+
};
|
|
121
|
+
await this.deps.redis.set(stateKey(state), JSON.stringify(rec), "EX", SSO_STATE_TTL_SECONDS);
|
|
122
|
+
return url;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* 处理身份源的回跳。state 先取后删(无论成败都不能再用);state 属于别的插件 → `sso.state_invalid`;
|
|
126
|
+
* 绑定 Cookie 不符 → `sso.session_mismatch`;身份源报错只映射为原因码;插件交回的身份源键必须由内核推导得出
|
|
127
|
+
* (`${插件名}:${identity.tenantId}`,Ruling A19),否则按 `sso.provider_error` 拒绝。
|
|
128
|
+
* 身份行经 IM 绑定建立、且发起与回调时不是同一个已登录的本人账号 → `sso.identity_not_verified`
|
|
129
|
+
* (Ruling A18)。成功则解析到账号(不判断账号状态,由调用方处理)。
|
|
130
|
+
* `sessionAccountId`:回调请求已带着的 Web 会话的账号(未登录时省略)。
|
|
131
|
+
*/
|
|
132
|
+
async callback(plugin, query, binding, sessionAccountId) {
|
|
133
|
+
const state = query.state;
|
|
134
|
+
if (state === undefined || !STATE_RE.test(state))
|
|
135
|
+
return { ok: false, error: "sso.state_invalid" };
|
|
136
|
+
const raw = await this.deps.redis.getdel(stateKey(state));
|
|
137
|
+
if (raw === null)
|
|
138
|
+
return { ok: false, error: "sso.state_invalid" };
|
|
139
|
+
const rec = JSON.parse(raw);
|
|
140
|
+
if (rec.plugin !== plugin)
|
|
141
|
+
return { ok: false, error: "sso.state_invalid" };
|
|
142
|
+
if (binding === undefined || !sameHash(sha256(binding), rec.binding)) {
|
|
143
|
+
return { ok: false, error: "sso.session_mismatch" };
|
|
144
|
+
}
|
|
145
|
+
if (query.error !== undefined) {
|
|
146
|
+
return {
|
|
147
|
+
ok: false,
|
|
148
|
+
error: query.error === "access_denied" ? "sso.access_denied" : "sso.provider_error",
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
const src = this.provider(plugin);
|
|
152
|
+
if (!src)
|
|
153
|
+
return { ok: false, error: "sso.unavailable" };
|
|
154
|
+
let identity;
|
|
155
|
+
try {
|
|
156
|
+
identity = await src.callback({
|
|
157
|
+
config: this.deps.host.deploymentConfig(plugin),
|
|
158
|
+
redirectUri: rec.redirectUri,
|
|
159
|
+
query,
|
|
160
|
+
nonce: rec.nonce,
|
|
161
|
+
signal: AbortSignal.timeout(SSO_CALLBACK_TIMEOUT_MS),
|
|
162
|
+
codeVerifier: rec.codeVerifier,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
catch (err) {
|
|
166
|
+
this.deps.log.warn("identity source callback failed", { plugin, err });
|
|
167
|
+
return { ok: false, error: "sso.provider_error" };
|
|
168
|
+
}
|
|
169
|
+
// 身份源键由内核推导(Ruling A19):插件只能为自己、为它报出的租户声明身份
|
|
170
|
+
if (typeof identity?.tenantId !== "string" ||
|
|
171
|
+
identity.source !== `${plugin}:${identity.tenantId}`) {
|
|
172
|
+
this.deps.log.warn("identity source returned a source key that does not match its tenant", {
|
|
173
|
+
plugin,
|
|
174
|
+
});
|
|
175
|
+
return { ok: false, error: "sso.provider_error" };
|
|
176
|
+
}
|
|
177
|
+
// 升级 bind 身份:发起与回调时是同一个已登录账号才算本人在登录状态下证明了对该身份的控制
|
|
178
|
+
const provedBy = rec.sessionAccountId !== undefined && rec.sessionAccountId === sessionAccountId
|
|
179
|
+
? sessionAccountId
|
|
180
|
+
: undefined;
|
|
181
|
+
let accountId;
|
|
182
|
+
try {
|
|
183
|
+
// 只有登录路径允许按已验证邮箱合并(Ruling A9)
|
|
184
|
+
accountId = (await this.deps.external.resolve(identity, undefined, {
|
|
185
|
+
allowMerge: true,
|
|
186
|
+
linkedVia: "sso",
|
|
187
|
+
login: provedBy === undefined ? {} : { sessionAccountId: provedBy },
|
|
188
|
+
})).accountId;
|
|
189
|
+
}
|
|
190
|
+
catch (err) {
|
|
191
|
+
if (err instanceof IdentityNotVerified) {
|
|
192
|
+
this.deps.log.warn("sign-in with an unverified linked identity refused", { plugin });
|
|
193
|
+
return { ok: false, error: "sso.identity_not_verified" };
|
|
194
|
+
}
|
|
195
|
+
if (!(err instanceof ApiError))
|
|
196
|
+
throw err;
|
|
197
|
+
this.deps.log.warn("external identity rejected", { plugin, err });
|
|
198
|
+
return { ok: false, error: "sso.provider_error" };
|
|
199
|
+
}
|
|
200
|
+
return { ok: true, accountId, returnTo: rec.returnTo };
|
|
201
|
+
}
|
|
202
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { type CatalogRequestsService, type CatalogRequestView } from "../catalog/requests.service.js";
|
|
2
|
+
import { type SkillChangesService, type SkillChangeView } from "../skills/changes.service.js";
|
|
3
|
+
import { type ApprovalsService, type ApprovalView } from "../tools/approvals.service.js";
|
|
4
|
+
/** 收件箱一次最多返回的事项数。 */
|
|
5
|
+
export declare const INBOX_MAX_ITEMS = 100;
|
|
6
|
+
/**
|
|
7
|
+
* 收件箱里的一项(按 `type` 区分,形状稳定):
|
|
8
|
+
* - `tool_approval`:当前用户能处理的待处理工具调用审批(与 `GET /approvals?status=pending` 同一视图);
|
|
9
|
+
* - `skill_change`:当前用户作为 agent 负责人能决定的待处理技能变更(M5 T15,R4);
|
|
10
|
+
* - `catalog_request`: pending catalog requests from members, when the current user is an org
|
|
11
|
+
* admin (M6 T26, C22).
|
|
12
|
+
*/
|
|
13
|
+
export type InboxItem = {
|
|
14
|
+
type: "tool_approval";
|
|
15
|
+
id: string;
|
|
16
|
+
createdAt: string;
|
|
17
|
+
approval: ApprovalView;
|
|
18
|
+
} | {
|
|
19
|
+
type: "skill_change";
|
|
20
|
+
id: string;
|
|
21
|
+
createdAt: string;
|
|
22
|
+
skillChange: SkillChangeView;
|
|
23
|
+
} | {
|
|
24
|
+
type: "catalog_request";
|
|
25
|
+
id: string;
|
|
26
|
+
createdAt: string;
|
|
27
|
+
request: CatalogRequestView;
|
|
28
|
+
};
|
|
29
|
+
/** `GET /inbox` 的结果:新的在前,最多 {@link INBOX_MAX_ITEMS} 项;`truncated` 为 true 表示还有更多。 */
|
|
30
|
+
export interface InboxView {
|
|
31
|
+
items: InboxItem[];
|
|
32
|
+
truncated: boolean;
|
|
33
|
+
}
|
|
34
|
+
/** 收件箱(计划取舍 C6):按类型汇总各来源的待处理事项。无状态,每次实时读 PG。 */
|
|
35
|
+
export declare class InboxService {
|
|
36
|
+
private readonly d;
|
|
37
|
+
constructor(d: {
|
|
38
|
+
approvals: Pick<ApprovalsService, "list">;
|
|
39
|
+
skillChanges: Pick<SkillChangesService, "listPending">;
|
|
40
|
+
catalogRequests?: Pick<CatalogRequestsService, "listForOrgAdmin">;
|
|
41
|
+
});
|
|
42
|
+
list(orgId: string, accountId: string): Promise<InboxView>;
|
|
43
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { CATALOG_REQUESTS_LIST_MAX, } from "../catalog/requests.service.js";
|
|
2
|
+
import { SKILL_CHANGES_LIST_MAX, } from "../skills/changes.service.js";
|
|
3
|
+
import { APPROVALS_LIST_MAX, } from "../tools/approvals.service.js";
|
|
4
|
+
/** 收件箱一次最多返回的事项数。 */
|
|
5
|
+
export const INBOX_MAX_ITEMS = 100;
|
|
6
|
+
/** 收件箱(计划取舍 C6):按类型汇总各来源的待处理事项。无状态,每次实时读 PG。 */
|
|
7
|
+
export class InboxService {
|
|
8
|
+
d;
|
|
9
|
+
constructor(d) {
|
|
10
|
+
this.d = d;
|
|
11
|
+
}
|
|
12
|
+
async list(orgId, accountId) {
|
|
13
|
+
const [approvals, changes, requests] = await Promise.all([
|
|
14
|
+
this.d.approvals.list(orgId, accountId, "pending"),
|
|
15
|
+
this.d.skillChanges.listPending(orgId, accountId),
|
|
16
|
+
this.d.catalogRequests?.listForOrgAdmin(orgId, accountId) ?? [],
|
|
17
|
+
]);
|
|
18
|
+
const all = [
|
|
19
|
+
...approvals.map((a) => ({
|
|
20
|
+
type: "tool_approval",
|
|
21
|
+
id: a.id,
|
|
22
|
+
createdAt: a.createdAt,
|
|
23
|
+
approval: a,
|
|
24
|
+
})),
|
|
25
|
+
...changes.map((c) => ({
|
|
26
|
+
type: "skill_change",
|
|
27
|
+
id: c.id,
|
|
28
|
+
createdAt: c.createdAt,
|
|
29
|
+
skillChange: c,
|
|
30
|
+
})),
|
|
31
|
+
...requests.map((r) => ({
|
|
32
|
+
type: "catalog_request",
|
|
33
|
+
id: r.id,
|
|
34
|
+
createdAt: r.createdAt,
|
|
35
|
+
request: r,
|
|
36
|
+
})),
|
|
37
|
+
];
|
|
38
|
+
// 新的在前;同一时刻按 id 定序(结果稳定)
|
|
39
|
+
all.sort((a, b) => a.createdAt !== b.createdAt
|
|
40
|
+
? a.createdAt < b.createdAt
|
|
41
|
+
? 1
|
|
42
|
+
: -1
|
|
43
|
+
: a.id < b.id
|
|
44
|
+
? -1
|
|
45
|
+
: a.id > b.id
|
|
46
|
+
? 1
|
|
47
|
+
: 0);
|
|
48
|
+
// 各来源自己也有上限:某个来源取满了也算还有更多
|
|
49
|
+
const full = approvals.length >= APPROVALS_LIST_MAX ||
|
|
50
|
+
changes.length >= SKILL_CHANGES_LIST_MAX ||
|
|
51
|
+
requests.length >= CATALOG_REQUESTS_LIST_MAX;
|
|
52
|
+
return {
|
|
53
|
+
items: all.slice(0, INBOX_MAX_ITEMS),
|
|
54
|
+
truncated: full || all.length > INBOX_MAX_ITEMS,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
}
|