@capybara-hq/kernel 0.1.0-rc.5 → 0.1.0-rc.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bootstrap.json +27 -3
- package/dist/admin/admin.controller.d.ts +21 -74
- package/dist/admin/admin.controller.js +50 -50
- package/dist/admin/admin.schemas.d.ts +57 -0
- package/dist/admin/admin.schemas.js +50 -0
- package/dist/admin/extensions.controller.d.ts +10 -0
- package/dist/admin/extensions.controller.js +18 -0
- package/dist/admin/extensions.schemas.d.ts +7 -0
- package/dist/admin/extensions.schemas.js +10 -0
- package/dist/admin/limit-defaults.d.ts +20 -0
- package/dist/admin/limit-defaults.js +10 -0
- package/dist/agents/agent-profile.service.d.ts +7 -5
- package/dist/agents/agent-profile.service.js +14 -9
- package/dist/agents/agents.controller.d.ts +7 -287
- package/dist/agents/agents.controller.js +7 -67
- package/dist/agents/agents.schemas.d.ts +389 -0
- package/dist/agents/agents.schemas.js +126 -0
- package/dist/agents/agents.service.d.ts +16 -6
- package/dist/agents/agents.service.js +75 -19
- package/dist/agents/definition.d.ts +47 -19
- package/dist/agents/definition.js +119 -38
- package/dist/agents/from-template.d.ts +2 -2
- package/dist/agents/from-template.js +76 -45
- package/dist/agents/from-template.service.d.ts +12 -0
- package/dist/agents/from-template.service.js +23 -6
- package/dist/agents/models.controller.d.ts +33 -5
- package/dist/agents/models.controller.js +50 -6
- package/dist/agents/org-templates.d.ts +13 -3
- package/dist/agents/org-templates.js +69 -28
- package/dist/agents/pending-connector-requests.d.ts +2 -0
- package/dist/agents/pending-connector-requests.js +1 -1
- package/dist/agents/pending-connectors.controller.d.ts +1 -1
- package/dist/agents/pending-connectors.controller.js +2 -2
- package/dist/agents/pending-connectors.service.d.ts +2 -2
- package/dist/agents/pending-connectors.service.js +19 -19
- package/dist/agents/profile.d.ts +18 -0
- package/dist/agents/profile.js +5 -1
- package/dist/agents/readiness.controller.d.ts +5 -5
- package/dist/agents/readiness.controller.js +6 -6
- package/dist/agents/templates.controller.d.ts +8 -17
- package/dist/agents/templates.controller.js +13 -31
- package/dist/agents/templates.schemas.d.ts +20 -0
- package/dist/agents/templates.schemas.js +45 -0
- package/dist/background/background.controller.js +3 -2
- package/dist/background/background.schemas.d.ts +10 -0
- package/dist/background/background.schemas.js +16 -0
- package/dist/background/tasks.service.d.ts +1 -1
- package/dist/background/tasks.service.js +7 -2
- package/dist/catalog/admin-catalog.controller.d.ts +4 -57
- package/dist/catalog/admin-catalog.controller.js +8 -45
- package/dist/catalog/admin-catalog.schemas.d.ts +72 -0
- package/dist/catalog/admin-catalog.schemas.js +92 -0
- package/dist/catalog/catalog-content.d.ts +12 -2
- package/dist/catalog/catalog-scope.service.js +8 -2
- package/dist/catalog/catalog.service.d.ts +2 -0
- package/dist/catalog/catalog.service.js +3 -0
- package/dist/catalog/component-scope.controller.d.ts +3 -65
- package/dist/catalog/component-scope.controller.js +3 -56
- package/dist/catalog/component-scope.schemas.d.ts +114 -0
- package/dist/catalog/component-scope.schemas.js +97 -0
- package/dist/catalog/component-scope.service.d.ts +28 -4
- package/dist/catalog/component-scope.service.js +55 -3
- package/dist/catalog/component-state.d.ts +9 -2
- package/dist/catalog/component-state.js +22 -13
- package/dist/catalog/marketplaces.controller.d.ts +5 -35
- package/dist/catalog/marketplaces.controller.js +6 -34
- package/dist/catalog/marketplaces.schemas.d.ts +48 -0
- package/dist/catalog/marketplaces.schemas.js +53 -0
- package/dist/catalog/marketplaces.service.d.ts +15 -1
- package/dist/catalog/marketplaces.service.js +22 -1
- package/dist/catalog/org-catalog.controller.d.ts +6 -62
- package/dist/catalog/org-catalog.controller.js +12 -66
- package/dist/catalog/org-catalog.schemas.d.ts +79 -0
- package/dist/catalog/org-catalog.schemas.js +82 -0
- package/dist/catalog/org-catalog.service.d.ts +9 -2
- package/dist/catalog/org-catalog.service.js +38 -5
- package/dist/catalog/org-extension.controller.d.ts +1 -12
- package/dist/catalog/org-extension.controller.js +1 -10
- package/dist/catalog/org-extension.schemas.d.ts +15 -0
- package/dist/catalog/org-extension.schemas.js +22 -0
- package/dist/catalog/org-plugin-uploads.controller.d.ts +2 -19
- package/dist/catalog/org-plugin-uploads.controller.js +15 -28
- package/dist/catalog/org-plugin-uploads.schemas.d.ts +20 -0
- package/dist/catalog/org-plugin-uploads.schemas.js +32 -0
- package/dist/catalog/owned-items.d.ts +6 -2
- package/dist/catalog/owned-items.js +16 -4
- package/dist/catalog/platform-components.d.ts +2 -0
- package/dist/catalog/platform-components.js +2 -0
- package/dist/catalog/plugin-import.js +1 -0
- package/dist/catalog/plugin-install.js +1 -1
- package/dist/catalog/requests.service.d.ts +2 -1
- package/dist/catalog/requests.service.js +6 -2
- package/dist/channels/channels.schemas.d.ts +33 -0
- package/dist/channels/channels.schemas.js +34 -0
- package/dist/channels/connections.controller.d.ts +2 -29
- package/dist/channels/connections.controller.js +1 -23
- package/dist/channels/connections.service.d.ts +8 -2
- package/dist/channels/connections.service.js +23 -5
- package/dist/channels/inbound.js +4 -0
- package/dist/config/schema.d.ts +4 -0
- package/dist/config/schema.js +24 -0
- package/dist/conversations/conversations.controller.d.ts +16 -37
- package/dist/conversations/conversations.controller.js +16 -56
- package/dist/conversations/conversations.schemas.d.ts +52 -0
- package/dist/conversations/conversations.schemas.js +79 -0
- package/dist/conversations/conversations.service.d.ts +13 -4
- package/dist/conversations/conversations.service.js +32 -26
- package/dist/conversations/events.d.ts +80 -6
- package/dist/conversations/events.js +60 -5
- package/dist/conversations/message-context.d.ts +28 -0
- package/dist/conversations/message-context.js +56 -0
- package/dist/conversations/queue.d.ts +2 -1
- package/dist/conversations/queue.js +11 -2
- package/dist/ctx/create-ctx.d.ts +15 -1
- package/dist/ctx/create-ctx.js +23 -2
- package/dist/db/kernel-schema.d.ts +44 -0
- package/dist/environments/environments.schemas.d.ts +3 -0
- package/dist/environments/environments.schemas.js +14 -0
- package/dist/environments/environments.service.d.ts +16 -4
- package/dist/environments/environments.service.js +58 -13
- package/dist/errors.d.ts +6 -0
- package/dist/errors.js +6 -0
- package/dist/evals/evals.schemas.d.ts +110 -0
- package/dist/evals/evals.schemas.js +107 -0
- package/dist/evals/reconstruct.js +18 -11
- package/dist/evals/recorded-tools.d.ts +2 -1
- package/dist/evals/recorded-tools.js +11 -3
- package/dist/evals/run-replay.d.ts +8 -1
- package/dist/evals/run-replay.js +17 -2
- package/dist/evals/runs.controller.d.ts +2 -57
- package/dist/evals/runs.controller.js +1 -42
- package/dist/evals/runs.service.d.ts +8 -7
- package/dist/evals/runs.service.js +45 -30
- package/dist/evals/sets.controller.d.ts +2 -28
- package/dist/evals/sets.controller.js +1 -31
- package/dist/evals/sets.service.d.ts +7 -7
- package/dist/evals/sets.service.js +23 -17
- package/dist/evals/snapshot.d.ts +3 -2
- package/dist/evals/snapshot.js +17 -4
- package/dist/evals/step-replay.d.ts +2 -1
- package/dist/evals/step-replay.js +3 -2
- package/dist/extensions/admin-ops.d.ts +5 -3
- package/dist/extensions/admin-ops.js +17 -12
- package/dist/extensions/config-hash.d.ts +10 -0
- package/dist/extensions/config-hash.js +38 -0
- package/dist/extensions/deployment-config.d.ts +16 -1
- package/dist/extensions/deployment-config.js +83 -0
- package/dist/extensions/extensions.module.js +9 -12
- package/dist/extensions/host.d.ts +39 -12
- package/dist/extensions/host.js +129 -51
- package/dist/extensions/installs.d.ts +5 -0
- package/dist/extensions/installs.js +12 -0
- package/dist/extensions/org-config.d.ts +17 -2
- package/dist/extensions/org-config.js +23 -4
- package/dist/extensions/point-defaults.controller.d.ts +2 -8
- package/dist/extensions/point-defaults.controller.js +1 -3
- package/dist/extensions/point-defaults.d.ts +3 -1
- package/dist/extensions/point-defaults.js +4 -2
- package/dist/extensions/point-defaults.schemas.d.ts +9 -0
- package/dist/extensions/point-defaults.schemas.js +14 -0
- package/dist/extensions/state.module.d.ts +9 -0
- package/dist/extensions/state.module.js +38 -0
- package/dist/extensions/unavailable.d.ts +49 -0
- package/dist/extensions/unavailable.js +113 -0
- package/dist/files/previewers.controller.js +2 -3
- package/dist/files/previewers.d.ts +1 -1
- package/dist/files/previewers.js +4 -4
- package/dist/files/previewers.schemas.d.ts +10 -0
- package/dist/files/previewers.schemas.js +9 -0
- package/dist/http/api.module.js +4 -0
- package/dist/http/plugin-dispatch.d.ts +4 -1
- package/dist/http/plugin-dispatch.js +14 -2
- package/dist/identity/accounts.d.ts +43 -4
- package/dist/identity/accounts.js +74 -6
- package/dist/identity/auth.guard.js +10 -1
- package/dist/identity/cookies.d.ts +6 -0
- package/dist/identity/cookies.js +14 -0
- package/dist/identity/identity.module.js +3 -0
- package/dist/identity/initial-passwords.controller.d.ts +22 -0
- package/dist/identity/initial-passwords.controller.js +49 -0
- package/dist/identity/initial-passwords.d.ts +61 -0
- package/dist/identity/initial-passwords.job.d.ts +16 -0
- package/dist/identity/initial-passwords.job.js +46 -0
- package/dist/identity/initial-passwords.js +159 -0
- package/dist/identity/me.controller.d.ts +14 -0
- package/dist/identity/me.controller.js +39 -1
- package/dist/identity/principal.d.ts +8 -0
- package/dist/identity/principal.js +8 -0
- package/dist/identity/settings.d.ts +3 -1
- package/dist/identity/settings.js +6 -4
- package/dist/inbox/inbox.schemas.d.ts +8 -0
- package/dist/inbox/inbox.schemas.js +11 -0
- package/dist/inbox/platform-inbox.controller.d.ts +1 -1
- package/dist/inbox/platform-inbox.controller.js +2 -2
- package/dist/index.d.ts +4 -0
- package/dist/index.js +6 -0
- package/dist/infra/config/kernel-config.service.js +3 -0
- package/dist/infra/events/kernel-events.d.ts +8 -0
- package/dist/lifecycle/kernel-lifecycle.js +4 -0
- package/dist/models/embeddings.d.ts +82 -0
- package/dist/models/embeddings.js +326 -0
- package/dist/models/enablement.controller.d.ts +40 -0
- package/dist/models/enablement.controller.js +74 -0
- package/dist/models/enablement.d.ts +101 -0
- package/dist/models/enablement.js +264 -0
- package/dist/models/models.module.d.ts +5 -1
- package/dist/models/models.module.js +16 -4
- package/dist/models/org-models.schemas.d.ts +8 -0
- package/dist/models/org-models.schemas.js +22 -0
- package/dist/models/prices.d.ts +3 -1
- package/dist/models/prices.js +7 -5
- package/dist/models/purposes.d.ts +30 -6
- package/dist/models/purposes.js +68 -17
- package/dist/orgs/orgs.controller.d.ts +2 -5
- package/dist/orgs/orgs.controller.js +3 -6
- package/dist/orgs/orgs.schemas.d.ts +8 -0
- package/dist/orgs/orgs.schemas.js +16 -0
- package/dist/orgs/orgs.service.d.ts +3 -1
- package/dist/orgs/orgs.service.js +6 -4
- package/dist/orgs/settings.service.d.ts +9 -1
- package/dist/orgs/settings.service.js +20 -5
- package/dist/overrides.d.ts +4 -0
- package/dist/overrides.js +2 -0
- package/dist/platform/errors.d.ts +21 -4
- package/dist/platform/errors.js +45 -6
- package/dist/platform/exclusions.d.ts +2 -3
- package/dist/platform/exclusions.js +68 -831
- package/dist/platform/method.js +1 -1
- package/dist/platform/operation.d.ts +82 -5
- package/dist/platform/operation.js +62 -7
- package/dist/platform/ops/accounts.ops.d.ts +32 -0
- package/dist/platform/ops/accounts.ops.js +291 -0
- package/dist/platform/ops/admin.ops.d.ts +36 -0
- package/dist/platform/ops/admin.ops.js +389 -0
- package/dist/platform/ops/agent-skills.ops.d.ts +24 -0
- package/dist/platform/ops/agent-skills.ops.js +226 -0
- package/dist/platform/ops/agent-templates.ops.d.ts +4 -1
- package/dist/platform/ops/agent-templates.ops.js +194 -14
- package/dist/platform/ops/agents.ops.d.ts +19 -1
- package/dist/platform/ops/agents.ops.js +481 -58
- package/dist/platform/ops/approvals.ops.d.ts +30 -0
- package/dist/platform/ops/approvals.ops.js +116 -0
- package/dist/platform/ops/background.ops.d.ts +14 -0
- package/dist/platform/ops/background.ops.js +134 -0
- package/dist/platform/ops/catalog-admin.ops.d.ts +74 -0
- package/dist/platform/ops/catalog-admin.ops.js +587 -0
- package/dist/platform/ops/channels.ops.d.ts +16 -0
- package/dist/platform/ops/channels.ops.js +195 -0
- package/dist/platform/ops/components.ops.d.ts +46 -0
- package/dist/platform/ops/components.ops.js +853 -0
- package/dist/platform/ops/connectors.ops.d.ts +4 -2
- package/dist/platform/ops/connectors.ops.js +68 -6
- package/dist/platform/ops/conversations.ops.d.ts +30 -0
- package/dist/platform/ops/conversations.ops.js +470 -0
- package/dist/platform/ops/environments.ops.d.ts +26 -0
- package/dist/platform/ops/environments.ops.js +289 -0
- package/dist/platform/ops/errors.d.ts +10 -5
- package/dist/platform/ops/errors.js +19 -11
- package/dist/platform/ops/evals.ops.d.ts +28 -0
- package/dist/platform/ops/evals.ops.js +783 -0
- package/dist/platform/ops/extensions-admin.ops.d.ts +25 -0
- package/dist/platform/ops/extensions-admin.ops.js +344 -0
- package/dist/platform/ops/extensions.ops.d.ts +7 -1
- package/dist/platform/ops/extensions.ops.js +248 -17
- package/dist/platform/ops/inbox.ops.d.ts +25 -0
- package/dist/platform/ops/inbox.ops.js +378 -0
- package/dist/platform/ops/marketplaces.ops.d.ts +7 -1
- package/dist/platform/ops/marketplaces.ops.js +326 -17
- package/dist/platform/ops/models.ops.d.ts +25 -0
- package/dist/platform/ops/models.ops.js +232 -0
- package/dist/platform/ops/org-plugins.ops.d.ts +29 -0
- package/dist/platform/ops/org-plugins.ops.js +329 -0
- package/dist/platform/ops/org-settings.ops.d.ts +16 -0
- package/dist/platform/ops/org-settings.ops.js +102 -0
- package/dist/platform/ops/orgs.ops.d.ts +28 -0
- package/dist/platform/ops/orgs.ops.js +295 -0
- package/dist/platform/ops/other-orgs.d.ts +20 -0
- package/dist/platform/ops/other-orgs.js +72 -0
- package/dist/platform/ops/platform.ops.d.ts +4 -4
- package/dist/platform/ops/platform.ops.js +23 -24
- package/dist/platform/ops/plugins.ops.d.ts +10 -8
- package/dist/platform/ops/plugins.ops.js +176 -77
- package/dist/platform/ops/previewers.ops.d.ts +14 -0
- package/dist/platform/ops/previewers.ops.js +109 -0
- package/dist/platform/ops/requests.ops.js +57 -19
- package/dist/platform/ops/skills.ops.d.ts +5 -1
- package/dist/platform/ops/skills.ops.js +129 -11
- package/dist/platform/ops/unavailable.d.ts +23 -0
- package/dist/platform/ops/unavailable.js +111 -0
- package/dist/platform/parity.d.ts +33 -0
- package/dist/platform/parity.js +272 -0
- package/dist/platform/platform-ops.module.d.ts +32 -0
- package/dist/platform/platform-ops.module.js +78 -11
- package/dist/platform/route-schemas.d.ts +18 -0
- package/dist/platform/route-schemas.js +60 -0
- package/dist/roles/worker.module.js +2 -0
- package/dist/runtime/context/build.d.ts +2 -0
- package/dist/runtime/context/build.js +28 -2
- package/dist/runtime/context/compaction.js +10 -1
- package/dist/runtime/context/run-context.d.ts +65 -0
- package/dist/runtime/context/run-context.js +215 -0
- package/dist/runtime/hook-calls.d.ts +8 -1
- package/dist/runtime/hook-calls.js +40 -9
- package/dist/runtime/model-call.d.ts +8 -3
- package/dist/runtime/model-call.js +30 -6
- package/dist/runtime/providers.d.ts +146 -32
- package/dist/runtime/providers.js +328 -67
- package/dist/runtime/run-context.service.d.ts +65 -0
- package/dist/runtime/run-context.service.js +220 -0
- package/dist/runtime/run-worker.d.ts +6 -1
- package/dist/runtime/run-worker.js +35 -10
- package/dist/runtime/runtime.module.js +2 -0
- package/dist/runtime/subagents/definition.d.ts +15 -15
- package/dist/runtime/subagents/definition.js +49 -118
- package/dist/runtime/usage-report-jobs.d.ts +88 -0
- package/dist/runtime/usage-report-jobs.js +158 -0
- package/dist/runtime/usage-report.d.ts +33 -38
- package/dist/runtime/usage-report.js +152 -84
- package/dist/skills/changes.controller.js +2 -1
- package/dist/skills/changes.service.d.ts +1 -1
- package/dist/skills/changes.service.js +4 -4
- package/dist/skills/invocable.controller.d.ts +1 -1
- package/dist/skills/invocable.controller.js +2 -2
- package/dist/skills/invoke.d.ts +2 -2
- package/dist/skills/invoke.js +8 -1
- package/dist/skills/skills.controller.d.ts +4 -13
- package/dist/skills/skills.controller.js +8 -24
- package/dist/skills/skills.schemas.d.ts +48 -0
- package/dist/skills/skills.schemas.js +61 -0
- package/dist/skills/skills.service.d.ts +11 -1
- package/dist/skills/skills.service.js +37 -14
- package/dist/time-zone.d.ts +5 -0
- package/dist/time-zone.js +19 -0
- package/dist/tools/approvals.controller.js +2 -3
- package/dist/tools/approvals.schemas.d.ts +21 -0
- package/dist/tools/approvals.schemas.js +15 -0
- package/dist/tools/builtin-names.d.ts +10 -8
- package/dist/tools/builtin-names.js +16 -11
- package/dist/tools/builtins/builtin-tools.d.ts +3 -1
- package/dist/tools/builtins/builtin-tools.js +15 -3
- package/dist/tools/builtins/current-time.d.ts +26 -0
- package/dist/tools/builtins/current-time.js +99 -0
- package/dist/tools/builtins/platform.d.ts +19 -2
- package/dist/tools/builtins/platform.js +105 -16
- package/dist/tools/connectors.controller.d.ts +1 -2
- package/dist/tools/connectors.controller.js +1 -4
- package/dist/tools/connectors.schemas.d.ts +12 -0
- package/dist/tools/connectors.schemas.js +19 -0
- package/dist/tools/connectors.service.d.ts +5 -2
- package/dist/tools/connectors.service.js +7 -5
- package/dist/tools/org-tool-switches.d.ts +16 -2
- package/dist/tools/org-tool-switches.js +26 -9
- package/dist/tools/pipeline.js +9 -1
- package/dist/tools/registry.d.ts +48 -51
- package/dist/tools/registry.js +222 -233
- package/package.json +3 -3
- package/src/migrations/0089_model_kinds_usage.sql +38 -0
- package/src/migrations/0090_initial_passwords.sql +27 -0
- package/src/migrations/0091_account_time_zone.sql +4 -0
- package/src/migrations/0092_tools_default_on.sql +27 -0
- package/dist/platform/redact-orgs.d.ts +0 -7
- package/dist/platform/redact-orgs.js +0 -52
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SKILL_ENTRY_FILE, sanitizeParams, } from "@capybara-hq/plugin-sdk";
|
|
2
|
+
import { canonicalDisabledTools, } from "../../agents/definition.js";
|
|
2
3
|
import { loadTemplates } from "../../agents/templates.js";
|
|
3
4
|
import { ApiError } from "../../errors.js";
|
|
4
5
|
import { PINNED_SKILLS_LIMITS } from "../../skills/catalog.js";
|
|
@@ -38,78 +39,28 @@ export function stricterPolicies(base, over) {
|
|
|
38
39
|
}
|
|
39
40
|
return out;
|
|
40
41
|
}
|
|
41
|
-
async function loadConnectors(db, orgId, refs) {
|
|
42
|
-
const ids = [...new Set(refs.flatMap((r) => (r.kind === "connector" ? [r.connectorId] : [])))];
|
|
43
|
-
const out = new Map();
|
|
44
|
-
if (ids.length === 0)
|
|
45
|
-
return out;
|
|
46
|
-
const rows = await db
|
|
47
|
-
.selectFrom("connectors")
|
|
48
|
-
.select(["id", "slug"])
|
|
49
|
-
.where("org_id", "=", orgId)
|
|
50
|
-
.where("deleted_at", "is", null)
|
|
51
|
-
.where("id", "in", ids)
|
|
52
|
-
.execute();
|
|
53
|
-
const tools = rows.length === 0
|
|
54
|
-
? []
|
|
55
|
-
: await db
|
|
56
|
-
.selectFrom("connector_tools")
|
|
57
|
-
.select(["connector_id", "name"])
|
|
58
|
-
.where("connector_id", "in", rows.map((r) => r.id))
|
|
59
|
-
.orderBy("name")
|
|
60
|
-
.execute();
|
|
61
|
-
for (const r of rows) {
|
|
62
|
-
out.set(r.id, {
|
|
63
|
-
slug: r.slug,
|
|
64
|
-
tools: tools.filter((t) => t.connector_id === r.id).map((t) => t.name),
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
return out;
|
|
68
|
-
}
|
|
69
42
|
/**
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
* is dropped. A connector that no longer exists keeps its ref only without an allowlist.
|
|
43
|
+
* A child's key filter (tools default-on spec §4): `deny` = the parent's own filter's (a nested
|
|
44
|
+
* child), {@link CHILD_REMOVED_TOOLS}, `Agent` when the child is at the depth limit, and the
|
|
45
|
+
* template's `disallowedTools`; `allow` = the template's `tools` allowlist met with the parent's
|
|
46
|
+
* (absent on both = everything the parent has). Keys are deduplicated in first-seen order.
|
|
75
47
|
*/
|
|
76
|
-
function
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
const c = connectors.get(ref.connectorId);
|
|
93
|
-
if (!c) {
|
|
94
|
-
if (allow === null)
|
|
95
|
-
out.push(ref);
|
|
96
|
-
continue;
|
|
97
|
-
}
|
|
98
|
-
const ownsKey = (k) => {
|
|
99
|
-
const parsed = parseToolKey(k);
|
|
100
|
-
return parsed?.kind === "connector" && parsed.slug === c.slug;
|
|
101
|
-
};
|
|
102
|
-
if (ref.tools === "all" && allow === null && ![...deny].some(ownsKey)) {
|
|
103
|
-
out.push(ref);
|
|
104
|
-
continue;
|
|
105
|
-
}
|
|
106
|
-
const names = ref.tools === "all" ? c.tools : ref.tools;
|
|
107
|
-
const kept = names.filter((name) => keep(connectorToolKey(c.slug, name)));
|
|
108
|
-
if (kept.length > 0)
|
|
109
|
-
out.push({ ...ref, tools: kept });
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
return out;
|
|
48
|
+
function childFilter(removeAgent, template, parent) {
|
|
49
|
+
const deny = [
|
|
50
|
+
...new Set([
|
|
51
|
+
...(parent?.deny ?? []),
|
|
52
|
+
...CHILD_REMOVED_TOOLS,
|
|
53
|
+
...(removeAgent ? [AGENT_TOOL] : []),
|
|
54
|
+
...(template?.disallowedTools ?? []),
|
|
55
|
+
]),
|
|
56
|
+
];
|
|
57
|
+
const own = template?.tools === undefined ? undefined : [...new Set(template.tools)];
|
|
58
|
+
const allow = own === undefined
|
|
59
|
+
? parent?.allow
|
|
60
|
+
: parent?.allow === undefined
|
|
61
|
+
? own
|
|
62
|
+
: own.filter((k) => parent.allow?.includes(k));
|
|
63
|
+
return { ...(allow !== undefined && { allow: [...allow] }), deny };
|
|
113
64
|
}
|
|
114
65
|
/**
|
|
115
66
|
* The template's skills the parent selects (its `orgSkills` or the parent agent's own skills),
|
|
@@ -184,9 +135,9 @@ selected = []) {
|
|
|
184
135
|
return { pinned, warnings };
|
|
185
136
|
}
|
|
186
137
|
/** The `effort` declaration of `model`, or null (or when the model cannot be resolved). */
|
|
187
|
-
async function effortDecl(registry, model) {
|
|
138
|
+
async function effortDecl(registry, orgId, model) {
|
|
188
139
|
try {
|
|
189
|
-
const { info } = await registry.resolve(model);
|
|
140
|
+
const { info } = await registry.resolve(orgId, model);
|
|
190
141
|
return info.parameters.find((p) => p.standard === "effort") ?? null;
|
|
191
142
|
}
|
|
192
143
|
catch {
|
|
@@ -236,10 +187,12 @@ function orgAgentDefinition(d, a) {
|
|
|
236
187
|
// block stays: it is the roster the child dispatches from (agent map spec §4.1); pending
|
|
237
188
|
// connectors are authoring data too (ruling P4-6)
|
|
238
189
|
const { skills, instructionFiles: _files, pendingConnectors: _pending, ...rest } = own;
|
|
190
|
+
const { subagentTools: _filter, ...ownRest } = rest;
|
|
239
191
|
const definition = {
|
|
240
|
-
...
|
|
192
|
+
...ownRest,
|
|
241
193
|
// its own tools, not intersected with the parent's; only the child-removed ones go
|
|
242
|
-
|
|
194
|
+
disabledTools: own.disabledTools ?? [],
|
|
195
|
+
subagentTools: childFilter(atMaxDepth(a), null),
|
|
243
196
|
// its policies, then the parent's on top, stricter wins (keys outside its tools are inert)
|
|
244
197
|
toolPolicies: stricterPolicies(own.toolPolicies ?? {}, a.parent.toolPolicies ?? {}),
|
|
245
198
|
...(skills !== undefined && {
|
|
@@ -298,15 +251,13 @@ export async function effectiveDefinition(d, a) {
|
|
|
298
251
|
...(row.platformTemplateId !== undefined && { platformTemplateId: row.platformTemplateId }),
|
|
299
252
|
};
|
|
300
253
|
}
|
|
301
|
-
const connectors = await loadConnectors(d.db, a.orgId, parent.tools);
|
|
302
|
-
const tools = narrowTools(parent.tools, connectors, template?.tools !== undefined ? new Set(template.tools) : null, new Set(template?.disallowedTools ?? []), atMaxDepth(a));
|
|
303
254
|
const toolPolicies = stricterPolicies(parent.toolPolicies ?? {}, template?.toolPolicies ?? {});
|
|
304
255
|
const { pinned, warnings } = await pinnedFor(d.db, a, template?.skills ?? [], entry.source === "plugin" ? { plugin: entry.plugin } : null, template?.selectedSkills ?? []);
|
|
305
256
|
const tier = a.tier ?? template?.model ?? "inherit";
|
|
306
257
|
const m = await resolveTier(d, a.orgId, parent, tier);
|
|
307
258
|
let modelParams = m.modelParams;
|
|
308
259
|
if (template?.effort !== undefined) {
|
|
309
|
-
const decl = await effortDecl(d.registry, m.model);
|
|
260
|
+
const decl = await effortDecl(d.registry, a.orgId, m.model);
|
|
310
261
|
if (decl) {
|
|
311
262
|
const v = sanitizeParams([decl], { [decl.key]: template.effort }).value[decl.key];
|
|
312
263
|
if (v !== undefined)
|
|
@@ -322,7 +273,8 @@ export async function effectiveDefinition(d, a) {
|
|
|
322
273
|
fallback: m.fallback,
|
|
323
274
|
modelParams,
|
|
324
275
|
fallbackParams: m.fallbackParams,
|
|
325
|
-
|
|
276
|
+
disabledTools: parent.disabledTools ?? [],
|
|
277
|
+
subagentTools: childFilter(atMaxDepth(a), template, parent.subagentTools),
|
|
326
278
|
toolPolicies,
|
|
327
279
|
...((parentSkills !== undefined || pinned.length > 0) && {
|
|
328
280
|
skills: {
|
|
@@ -341,57 +293,32 @@ export async function effectiveDefinition(d, a) {
|
|
|
341
293
|
tierFallback: m.tierFallback,
|
|
342
294
|
};
|
|
343
295
|
}
|
|
344
|
-
/**
|
|
345
|
-
* The refs of `frozen` that `current` still has: a builtin or plugin tool by name, a connector by
|
|
346
|
-
* id; a connector's `all` meets the other side's names (`all` on both stays `all`), and a
|
|
347
|
-
* connector left with no names is dropped. Pure: a connector `current` lists is not looked up.
|
|
348
|
-
*/
|
|
349
|
-
export function intersectTools(frozen, current) {
|
|
350
|
-
const out = [];
|
|
351
|
-
for (const ref of frozen) {
|
|
352
|
-
if (ref.kind === "builtin") {
|
|
353
|
-
if (current.some((c) => c.kind === "builtin" && c.name === ref.name))
|
|
354
|
-
out.push(ref);
|
|
355
|
-
}
|
|
356
|
-
else if (ref.kind === "plugin") {
|
|
357
|
-
if (current.some((c) => c.kind === "plugin" && c.plugin === ref.plugin && c.name === ref.name)) {
|
|
358
|
-
out.push(ref);
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
else {
|
|
362
|
-
const c = current.find((x) => x.kind === "connector" && x.connectorId === ref.connectorId);
|
|
363
|
-
if (!c)
|
|
364
|
-
continue;
|
|
365
|
-
if (c.tools === "all") {
|
|
366
|
-
out.push(ref);
|
|
367
|
-
continue;
|
|
368
|
-
}
|
|
369
|
-
const names = ref.tools === "all" ? c.tools : ref.tools.filter((n) => c.tools.includes(n));
|
|
370
|
-
if (names.length > 0)
|
|
371
|
-
out.push({ ...ref, tools: names });
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
return out;
|
|
375
|
-
}
|
|
376
296
|
/**
|
|
377
297
|
* The narrowing of a follow-up (final review I1): `frozen` (the child's `subagent_started`
|
|
378
298
|
* definition) against `current`, the definition a fresh dispatch would read now: the dispatching
|
|
379
299
|
* parent run's version for `general` / inline / plugin children, the dispatched org agent's
|
|
380
300
|
* current version for an org agent child (whose tools are its own at dispatch too, §5.5). Its
|
|
381
|
-
* `orgSkills` keep only those `current` still
|
|
382
|
-
* skills goes with it (the agent's own skills
|
|
301
|
+
* `disabledTools` are both lists together; its `orgSkills` keep only those `current` still
|
|
302
|
+
* selects; a pinned id that was one of the frozen org skills goes with it (the agent's own skills
|
|
303
|
+
* stay).
|
|
383
304
|
*/
|
|
384
305
|
export function narrowFollowUp(frozen, current) {
|
|
385
|
-
const
|
|
306
|
+
const disabledTools = canonicalDisabledTools([
|
|
307
|
+
...(frozen.disabledTools ?? []),
|
|
308
|
+
...(current.disabledTools ?? []),
|
|
309
|
+
]);
|
|
386
310
|
if (frozen.skills === undefined)
|
|
387
|
-
return {
|
|
311
|
+
return { disabledTools };
|
|
388
312
|
const frozenOrg = new Set(frozen.skills.orgSkills);
|
|
389
313
|
const now = new Set(current.skills?.orgSkills ?? []);
|
|
390
314
|
const orgSkills = frozen.skills.orgSkills.filter((id) => now.has(id));
|
|
391
315
|
const pinned = frozen.skills.pinned?.filter((id) => !frozenOrg.has(id) || now.has(id));
|
|
392
|
-
return {
|
|
316
|
+
return { disabledTools, skills: { orgSkills, ...(pinned !== undefined && { pinned }) } };
|
|
393
317
|
}
|
|
394
|
-
/**
|
|
318
|
+
/**
|
|
319
|
+
* The definition a child run uses: the frozen one with its trigger's follow-up narrowing. A
|
|
320
|
+
* narrowing logged before tools were on by default (no `disabledTools`) narrows only skills.
|
|
321
|
+
*/
|
|
395
322
|
export function childRunDefinition(frozen, narrowed) {
|
|
396
323
|
if (narrowed === undefined)
|
|
397
324
|
return frozen;
|
|
@@ -403,5 +330,9 @@ export function childRunDefinition(frozen, narrowed) {
|
|
|
403
330
|
orgSkills: narrowed.skills.orgSkills,
|
|
404
331
|
...(narrowed.skills.pinned !== undefined && { pinned: narrowed.skills.pinned }),
|
|
405
332
|
};
|
|
406
|
-
return {
|
|
333
|
+
return {
|
|
334
|
+
...rest,
|
|
335
|
+
...(Array.isArray(narrowed.disabledTools) && { disabledTools: narrowed.disabledTools }),
|
|
336
|
+
...(kept !== undefined && { skills: kept }),
|
|
337
|
+
};
|
|
407
338
|
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type { Logger } from "@capybara-hq/plugin-sdk";
|
|
2
|
+
import { type OnApplicationShutdown } from "@nestjs/common";
|
|
3
|
+
import type { JobsOptions, Queue } from "bullmq";
|
|
4
|
+
import type { KernelSchemaDb } from "../db/kernel-schema.js";
|
|
5
|
+
import { KernelConfigService } from "../infra/config/kernel-config.service.js";
|
|
6
|
+
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
7
|
+
import { KernelEvents } from "../infra/events/kernel-events.js";
|
|
8
|
+
/**
|
|
9
|
+
* The producer half of `usage.report` delivery for `model_usage` rows, and the queue's ids and job
|
|
10
|
+
* options shared with the reporter (`usage-report.ts`). The `ctx.models` broker sits below the
|
|
11
|
+
* extension host and must not register a queue there (CLI contexts that build the extensions
|
|
12
|
+
* module never connect to Redis eagerly), so it only announces a row (`model_usage.recorded`) and
|
|
13
|
+
* {@link ModelUsageJobs} enqueues it here.
|
|
14
|
+
*/
|
|
15
|
+
/** Queue of `usage.report` deliveries (no `:` in the name). */
|
|
16
|
+
export declare const USAGE_REPORT_QUEUE = "cap-kernel-usage-report";
|
|
17
|
+
/** The job name of every delivery. */
|
|
18
|
+
export declare const USAGE_REPORT_JOB = "usage-report";
|
|
19
|
+
/** One job per `usage` event (no `:`: conversation ids are UUIDs, seq is a number). */
|
|
20
|
+
export declare const usageReportJobId: (conversationId: string, seq: number) => string;
|
|
21
|
+
/** One job per `model_usage` row (spec B §5.4; row ids are UUIDs, so no clash with the above). */
|
|
22
|
+
export declare const modelUsageJobId: (usageId: string) => string;
|
|
23
|
+
/**
|
|
24
|
+
* Job data: ids only (the payload is read when the job runs): a conversation `usage` event
|
|
25
|
+
* (`conversationId` + `seq`), or a `model_usage` row (`usageId`).
|
|
26
|
+
*/
|
|
27
|
+
export type UsageReportJob = ({
|
|
28
|
+
conversationId: string;
|
|
29
|
+
seq: number;
|
|
30
|
+
usageId?: undefined;
|
|
31
|
+
} | {
|
|
32
|
+
usageId: string;
|
|
33
|
+
conversationId?: undefined;
|
|
34
|
+
seq?: undefined;
|
|
35
|
+
}) & {
|
|
36
|
+
/** Plugins not yet succeeded; absent = every subscriber (decided on the first attempt). */
|
|
37
|
+
pending?: string[];
|
|
38
|
+
/**
|
|
39
|
+
* Targets dropped so far (plugin → why), accumulated across attempts (m-2): when the job would
|
|
40
|
+
* otherwise complete it fails naming them, and `pending` is then exactly these plugins, so a
|
|
41
|
+
* manual retry reaches only them (m-1). A later delivery to one of them removes it.
|
|
42
|
+
*/
|
|
43
|
+
dropped?: Record<string, string>;
|
|
44
|
+
};
|
|
45
|
+
/** First attempt plus 5 retries (F11). */
|
|
46
|
+
export declare const USAGE_REPORT_ATTEMPTS = 6;
|
|
47
|
+
/** Retry backoff: 2 s, doubling (2, 4, 8, 16, 32 s). */
|
|
48
|
+
export declare const USAGE_REPORT_BACKOFF_MS = 2000;
|
|
49
|
+
/** The delivery retry policy: attempts and the first exponential backoff. */
|
|
50
|
+
export interface UsageReportRetry {
|
|
51
|
+
attempts: number;
|
|
52
|
+
backoffMs: number;
|
|
53
|
+
}
|
|
54
|
+
/** Optional provider: the {@link UsageReportRetry} instead of the defaults above (tests). */
|
|
55
|
+
export declare const USAGE_REPORT_RETRY: unique symbol;
|
|
56
|
+
/** The options of one delivery job: its id, the retry policy and the retention of finished jobs. */
|
|
57
|
+
export declare function usageReportJobOpts(jobId: string, retry: UsageReportRetry, keepHours: number): JobsOptions;
|
|
58
|
+
/**
|
|
59
|
+
* Plugins that subscribe to `usage.report` according to deployment state: an approved permission
|
|
60
|
+
* snapshot that declares the `usage.report` hook, for a plugin the deployment still knows: an enabled
|
|
61
|
+
* install, or a config-declared plugin with a replica status row that is not `unloaded`. With `orgId`, only plugins
|
|
62
|
+
* the organization enabled (org config rows and required bootstrap plugins).
|
|
63
|
+
*/
|
|
64
|
+
export declare function queryUsageSubscribers(db: KernelSchemaDb, orgId?: string): Promise<Set<string>>;
|
|
65
|
+
/**
|
|
66
|
+
* Enqueues the `usage.report` delivery of `model_usage` rows on `model_usage.recorded` (fast path;
|
|
67
|
+
* the reporter's sweep re-enqueues rows still unreported, so a lost event or enqueue is caught up).
|
|
68
|
+
*/
|
|
69
|
+
export declare class ModelUsageJobs implements OnApplicationShutdown {
|
|
70
|
+
private readonly kdb;
|
|
71
|
+
private readonly queue;
|
|
72
|
+
private readonly config;
|
|
73
|
+
private readonly log;
|
|
74
|
+
private readonly retry;
|
|
75
|
+
private readonly unsubscribe;
|
|
76
|
+
/** Set at shutdown: a late event enqueues nothing (the sweep offers the row later). */
|
|
77
|
+
private closed;
|
|
78
|
+
constructor(kdb: KernelDb, queue: Queue<UsageReportJob>, config: Pick<KernelConfigService, "get">, log: Logger, retry: UsageReportRetry | undefined, events: KernelEvents);
|
|
79
|
+
onApplicationShutdown(): void;
|
|
80
|
+
/**
|
|
81
|
+
* Enqueues the delivery of one row (job `usage-model-<rowId>`). Without any subscriber nothing is
|
|
82
|
+
* enqueued (the sweep marks the row). Never throws: a failure only logs; the sweep catches up.
|
|
83
|
+
*/
|
|
84
|
+
enqueue(usageId: string): Promise<void>;
|
|
85
|
+
}
|
|
86
|
+
/** The usage report queue and its `model_usage` producer (no dependency on the extension host). */
|
|
87
|
+
export declare class UsageReportJobsModule {
|
|
88
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
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 { getQueueToken } from "@nestjs/bullmq";
|
|
11
|
+
import { Inject, Injectable, Module, Optional } from "@nestjs/common";
|
|
12
|
+
import { sql } from "kysely";
|
|
13
|
+
import { enabledExtensionsQuery } from "../extensions/enabled.js";
|
|
14
|
+
import { KernelConfigService } from "../infra/config/kernel-config.service.js";
|
|
15
|
+
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
16
|
+
import { KernelEvents } from "../infra/events/kernel-events.js";
|
|
17
|
+
import { QueueModule } from "../infra/queue/queue.module.js";
|
|
18
|
+
import { KERNEL_LOGGER } from "../infra/tokens.js";
|
|
19
|
+
/**
|
|
20
|
+
* The producer half of `usage.report` delivery for `model_usage` rows, and the queue's ids and job
|
|
21
|
+
* options shared with the reporter (`usage-report.ts`). The `ctx.models` broker sits below the
|
|
22
|
+
* extension host and must not register a queue there (CLI contexts that build the extensions
|
|
23
|
+
* module never connect to Redis eagerly), so it only announces a row (`model_usage.recorded`) and
|
|
24
|
+
* {@link ModelUsageJobs} enqueues it here.
|
|
25
|
+
*/
|
|
26
|
+
/** Queue of `usage.report` deliveries (no `:` in the name). */
|
|
27
|
+
export const USAGE_REPORT_QUEUE = "cap-kernel-usage-report";
|
|
28
|
+
/** The job name of every delivery. */
|
|
29
|
+
export const USAGE_REPORT_JOB = "usage-report";
|
|
30
|
+
/** One job per `usage` event (no `:`: conversation ids are UUIDs, seq is a number). */
|
|
31
|
+
export const usageReportJobId = (conversationId, seq) => `usage-${conversationId}-${seq}`;
|
|
32
|
+
/** One job per `model_usage` row (spec B §5.4; row ids are UUIDs, so no clash with the above). */
|
|
33
|
+
export const modelUsageJobId = (usageId) => `usage-model-${usageId}`;
|
|
34
|
+
/** First attempt plus 5 retries (F11). */
|
|
35
|
+
export const USAGE_REPORT_ATTEMPTS = 6;
|
|
36
|
+
/** Retry backoff: 2 s, doubling (2, 4, 8, 16, 32 s). */
|
|
37
|
+
export const USAGE_REPORT_BACKOFF_MS = 2000;
|
|
38
|
+
/** Optional provider: the {@link UsageReportRetry} instead of the defaults above (tests). */
|
|
39
|
+
export const USAGE_REPORT_RETRY = Symbol("USAGE_REPORT_RETRY");
|
|
40
|
+
/** Failed jobs (given up) are kept for inspection, at most {@link KEEP_FAILED_MAX} of them. */
|
|
41
|
+
const KEEP_FAILED_S = 7 * 86_400;
|
|
42
|
+
/** Upper bound on kept failed jobs (I-2): a long outage of a billing endpoint cannot grow Redis. */
|
|
43
|
+
const KEEP_FAILED_MAX = 100_000;
|
|
44
|
+
/**
|
|
45
|
+
* Upper bound on kept finished jobs (Redis memory). At the default retention it only bites above
|
|
46
|
+
* ~1.1 usage events per second sustained for a day; dedupe needs the jobs only for the sweeper overlap.
|
|
47
|
+
*/
|
|
48
|
+
const KEEP_COMPLETED_MAX = 100_000;
|
|
49
|
+
/** The options of one delivery job: its id, the retry policy and the retention of finished jobs. */
|
|
50
|
+
export function usageReportJobOpts(jobId, retry, keepHours) {
|
|
51
|
+
return {
|
|
52
|
+
jobId,
|
|
53
|
+
attempts: retry.attempts,
|
|
54
|
+
backoff: { type: "exponential", delay: retry.backoffMs },
|
|
55
|
+
removeOnComplete: { age: keepHours * 3600, count: KEEP_COMPLETED_MAX },
|
|
56
|
+
removeOnFail: { age: KEEP_FAILED_S, count: KEEP_FAILED_MAX },
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Plugins that subscribe to `usage.report` according to deployment state: an approved permission
|
|
61
|
+
* snapshot that declares the `usage.report` hook, for a plugin the deployment still knows: an enabled
|
|
62
|
+
* install, or a config-declared plugin with a replica status row that is not `unloaded`. With `orgId`, only plugins
|
|
63
|
+
* the organization enabled (org config rows and required bootstrap plugins).
|
|
64
|
+
*/
|
|
65
|
+
export async function queryUsageSubscribers(db, orgId) {
|
|
66
|
+
let q = db
|
|
67
|
+
.selectFrom("extension_permission_snapshots as s")
|
|
68
|
+
.select("s.plugin")
|
|
69
|
+
.where(sql `s.permissions -> 'permissions' -> 'hooks' ? 'usage.report'`)
|
|
70
|
+
.where((eb) => eb.or([
|
|
71
|
+
eb.exists(eb
|
|
72
|
+
.selectFrom("extension_installs as i")
|
|
73
|
+
.select(sql `1`.as("one"))
|
|
74
|
+
.whereRef("i.name", "=", "s.plugin")
|
|
75
|
+
.where("i.desired_state", "=", "enabled")),
|
|
76
|
+
// config-declared plugins still declared (and not unloaded) on some replica; installs are
|
|
77
|
+
// covered by desired_state above (their replica rows linger as `unloaded` when disabled)
|
|
78
|
+
eb.exists(eb
|
|
79
|
+
.selectFrom("extension_replica_status as r")
|
|
80
|
+
.select(sql `1`.as("one"))
|
|
81
|
+
.whereRef("r.plugin", "=", "s.plugin")
|
|
82
|
+
.where("r.source", "=", "config")
|
|
83
|
+
.where("r.state", "<>", "unloaded")),
|
|
84
|
+
]));
|
|
85
|
+
if (orgId !== undefined) {
|
|
86
|
+
q = q.where("s.plugin", "in", enabledExtensionsQuery(db, orgId));
|
|
87
|
+
}
|
|
88
|
+
return new Set((await q.execute()).map((r) => r.plugin));
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Enqueues the `usage.report` delivery of `model_usage` rows on `model_usage.recorded` (fast path;
|
|
92
|
+
* the reporter's sweep re-enqueues rows still unreported, so a lost event or enqueue is caught up).
|
|
93
|
+
*/
|
|
94
|
+
let ModelUsageJobs = class ModelUsageJobs {
|
|
95
|
+
kdb;
|
|
96
|
+
queue;
|
|
97
|
+
config;
|
|
98
|
+
log;
|
|
99
|
+
retry;
|
|
100
|
+
unsubscribe;
|
|
101
|
+
/** Set at shutdown: a late event enqueues nothing (the sweep offers the row later). */
|
|
102
|
+
closed = false;
|
|
103
|
+
constructor(kdb, queue, config, log, retry = {
|
|
104
|
+
attempts: USAGE_REPORT_ATTEMPTS,
|
|
105
|
+
backoffMs: USAGE_REPORT_BACKOFF_MS,
|
|
106
|
+
}, events) {
|
|
107
|
+
this.kdb = kdb;
|
|
108
|
+
this.queue = queue;
|
|
109
|
+
this.config = config;
|
|
110
|
+
this.log = log;
|
|
111
|
+
this.retry = retry;
|
|
112
|
+
this.unsubscribe = events.on("model_usage.recorded", ({ id }) => this.enqueue(id));
|
|
113
|
+
}
|
|
114
|
+
onApplicationShutdown() {
|
|
115
|
+
this.closed = true;
|
|
116
|
+
this.unsubscribe();
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Enqueues the delivery of one row (job `usage-model-<rowId>`). Without any subscriber nothing is
|
|
120
|
+
* enqueued (the sweep marks the row). Never throws: a failure only logs; the sweep catches up.
|
|
121
|
+
*/
|
|
122
|
+
async enqueue(usageId) {
|
|
123
|
+
if (this.closed)
|
|
124
|
+
return;
|
|
125
|
+
try {
|
|
126
|
+
if ((await queryUsageSubscribers(this.kdb.db)).size === 0)
|
|
127
|
+
return;
|
|
128
|
+
await this.queue.add(USAGE_REPORT_JOB, { usageId }, usageReportJobOpts(modelUsageJobId(usageId), this.retry, this.config.get().hooks.usageReportKeepHours));
|
|
129
|
+
}
|
|
130
|
+
catch (err) {
|
|
131
|
+
this.log.warn("cannot enqueue model usage report", { usageId, err });
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
ModelUsageJobs = __decorate([
|
|
136
|
+
Injectable(),
|
|
137
|
+
__param(0, Inject(KernelDb)),
|
|
138
|
+
__param(1, Inject(getQueueToken(USAGE_REPORT_QUEUE))),
|
|
139
|
+
__param(2, Inject(KernelConfigService)),
|
|
140
|
+
__param(3, Inject(KERNEL_LOGGER)),
|
|
141
|
+
__param(4, Optional()),
|
|
142
|
+
__param(4, Inject(USAGE_REPORT_RETRY)),
|
|
143
|
+
__param(5, Inject(KernelEvents))
|
|
144
|
+
], ModelUsageJobs);
|
|
145
|
+
export { ModelUsageJobs };
|
|
146
|
+
/** The usage report queue's registration, shared by the producer and the reporter's module. */
|
|
147
|
+
const USAGE_REPORT_QUEUE_MODULE = QueueModule.registerQueue(USAGE_REPORT_QUEUE);
|
|
148
|
+
/** The usage report queue and its `model_usage` producer (no dependency on the extension host). */
|
|
149
|
+
let UsageReportJobsModule = class UsageReportJobsModule {
|
|
150
|
+
};
|
|
151
|
+
UsageReportJobsModule = __decorate([
|
|
152
|
+
Module({
|
|
153
|
+
imports: [USAGE_REPORT_QUEUE_MODULE],
|
|
154
|
+
providers: [ModelUsageJobs],
|
|
155
|
+
exports: [ModelUsageJobs, USAGE_REPORT_QUEUE_MODULE],
|
|
156
|
+
})
|
|
157
|
+
], UsageReportJobsModule);
|
|
158
|
+
export { UsageReportJobsModule };
|
|
@@ -6,34 +6,8 @@ import { KernelConfigService } from "../infra/config/kernel-config.service.js";
|
|
|
6
6
|
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
7
7
|
import { LockService } from "../infra/lock/lock.service.js";
|
|
8
8
|
import type { KernelLogger } from "../log.js";
|
|
9
|
-
|
|
10
|
-
export
|
|
11
|
-
/** One job per `usage` event (no `:`: conversation ids are UUIDs, seq is a number). */
|
|
12
|
-
export declare const usageReportJobId: (conversationId: string, seq: number) => string;
|
|
13
|
-
/** Job data: ids only (the payload is read from the event log when the job runs). */
|
|
14
|
-
export interface UsageReportJob {
|
|
15
|
-
conversationId: string;
|
|
16
|
-
seq: number;
|
|
17
|
-
/** Plugins not yet succeeded; absent = every subscriber (decided on the first attempt). */
|
|
18
|
-
pending?: string[];
|
|
19
|
-
/**
|
|
20
|
-
* Targets dropped so far (plugin → why), accumulated across attempts (m-2): when the job would
|
|
21
|
-
* otherwise complete it fails naming them, and `pending` is then exactly these plugins, so a
|
|
22
|
-
* manual retry reaches only them (m-1). A later delivery to one of them removes it.
|
|
23
|
-
*/
|
|
24
|
-
dropped?: Record<string, string>;
|
|
25
|
-
}
|
|
26
|
-
/** First attempt plus 5 retries (F11). */
|
|
27
|
-
export declare const USAGE_REPORT_ATTEMPTS = 6;
|
|
28
|
-
/** Retry backoff: 2 s, doubling (2, 4, 8, 16, 32 s). */
|
|
29
|
-
export declare const USAGE_REPORT_BACKOFF_MS = 2000;
|
|
30
|
-
/** The delivery retry policy of {@link UsageReporter}: attempts and the first exponential backoff. */
|
|
31
|
-
export interface UsageReportRetry {
|
|
32
|
-
attempts: number;
|
|
33
|
-
backoffMs: number;
|
|
34
|
-
}
|
|
35
|
-
/** Optional provider: the {@link UsageReportRetry} instead of the defaults above (tests). */
|
|
36
|
-
export declare const USAGE_REPORT_RETRY: unique symbol;
|
|
9
|
+
import { type UsageReportJob, type UsageReportRetry } from "./usage-report-jobs.js";
|
|
10
|
+
export { ModelUsageJobs, modelUsageJobId, queryUsageSubscribers, USAGE_REPORT_ATTEMPTS, USAGE_REPORT_BACKOFF_MS, USAGE_REPORT_QUEUE, USAGE_REPORT_RETRY, type UsageReportJob, UsageReportJobsModule, type UsageReportRetry, usageReportJobId, } from "./usage-report-jobs.js";
|
|
37
11
|
/** The sweeper's cron job name (no `:`; every minute, once across replicas). */
|
|
38
12
|
export declare const USAGE_SWEEP_JOB = "usage-report-sweep";
|
|
39
13
|
/** The maintenance scheduler the sweep ran on before it became a `@LockedCron` (retired). */
|
|
@@ -46,13 +20,6 @@ export declare const USAGE_SWEEP_LAG_MS = 30000;
|
|
|
46
20
|
* (`hooks.usageReportKeepHours` ≥ 1 h), so re-enqueued events dedupe on the kept job.
|
|
47
21
|
*/
|
|
48
22
|
export declare const USAGE_SWEEP_OVERLAP_MS: number;
|
|
49
|
-
/**
|
|
50
|
-
* Plugins that subscribe to `usage.report` according to deployment state: an approved permission
|
|
51
|
-
* snapshot that declares the `usage.report` hook, for a plugin the deployment still knows: an enabled
|
|
52
|
-
* install, or a config-declared plugin with a replica status row that is not `unloaded`. With `orgId`, only plugins
|
|
53
|
-
* the organization enabled (org config rows and required bootstrap plugins).
|
|
54
|
-
*/
|
|
55
|
-
export declare function queryUsageSubscribers(db: KernelSchemaDb, orgId?: string): Promise<Set<string>>;
|
|
56
23
|
/**
|
|
57
24
|
* Of `plugins`, those that are **definitely** unservable right now (I-2, N-3): live replicas report
|
|
58
25
|
* them (a `extension_replica_status` row with a heartbeat newer than `staleSeconds`), no live row is
|
|
@@ -91,11 +58,18 @@ export declare function narrowPending(stored: readonly string[] | undefined, fai
|
|
|
91
58
|
* most 100 000. Each call runs through the instance's `inflight.run`, limited by `hooks.timeoutMs`;
|
|
92
59
|
* when this replica stops, in-flight calls are aborted and the job goes back to the queue without
|
|
93
60
|
* using up an attempt.
|
|
94
|
-
* Handlers must be idempotent by `eventId` (`<conversationId>/<seq
|
|
95
|
-
* log (never model-visible). Compaction calls log usage too (`purpose: "compaction"`) and are reported,
|
|
61
|
+
* Handlers must be idempotent by `eventId` (`<conversationId>/<seq>`, or a `model_usage` row id).
|
|
62
|
+
* Nothing is written to the event log (never model-visible). Compaction calls log usage too (`purpose: "compaction"`) and are reported,
|
|
96
63
|
* as are conversation title calls (`purpose: "title"`, no run: `runId` is "") and `WebFetch`
|
|
97
64
|
* extraction calls (`purpose: "web_fetch"`).
|
|
98
65
|
* Single-step eval replays and judge requests log no usage: not reported (M7).
|
|
66
|
+
* - **Model usage outside conversations** (spec B §5.4): each `ctx.models.embed` call writes a
|
|
67
|
+
* `model_usage` row; on its `model_usage.recorded` event `ModelUsageJobs` (`usage-report-jobs.ts`)
|
|
68
|
+
* enqueues job `usage-model-<rowId>` (only while some plugin subscribes); the payload
|
|
69
|
+
* (`purpose: "embedding"`, `eventId` = the row id, the calling `extension`, no conversation fields)
|
|
70
|
+
* is read from the row when the job runs, and the row's `reported_at` is set once nothing is left
|
|
71
|
+
* to deliver; a job that gives up after its last attempt sets `report_failed_at`. The sweep
|
|
72
|
+
* re-enqueues recent rows that are neither (see {@link sweep}).
|
|
99
73
|
*/
|
|
100
74
|
export declare class UsageReporter {
|
|
101
75
|
private readonly kdb;
|
|
@@ -151,11 +125,21 @@ export declare class UsageReporter {
|
|
|
151
125
|
/**
|
|
152
126
|
* One sweep (R13): re-enqueues the `usage` events created in `[watermark - overlap, now - lag]` in
|
|
153
127
|
* pages, then advances the watermark to `now - lag`. With no subscriber it only advances. The first
|
|
154
|
-
* sweep starts at `now - lag - overlap`.
|
|
128
|
+
* sweep starts at `now - lag - overlap`. Also re-enqueues the `model_usage` rows of the same
|
|
129
|
+
* window that are neither reported nor given up (spec B §5.4),
|
|
130
|
+
* or, with no subscriber, marks those rows reported (nobody to deliver to). Returns the number of
|
|
131
|
+
* events and rows offered to the queue.
|
|
155
132
|
*/
|
|
156
133
|
sweep(opts?: {
|
|
157
134
|
now?: number;
|
|
158
135
|
}): Promise<number>;
|
|
136
|
+
/**
|
|
137
|
+
* The `model_usage` half of {@link sweep}: rows neither reported nor given up that occurred in
|
|
138
|
+
* the same window as the events (`[watermark - overlap, to]`), oldest first. Bounded like the
|
|
139
|
+
* event sweep, so a row whose job failed for good is never offered again, even after its failed
|
|
140
|
+
* job left Redis (no repeated backlog, no second delivery to plugins already served).
|
|
141
|
+
*/
|
|
142
|
+
private sweepModelUsage;
|
|
159
143
|
/**
|
|
160
144
|
* Starts consuming (worker role only): `worker` is the `@Processor` worker of
|
|
161
145
|
* {@link USAGE_REPORT_QUEUE} (built with the run queue's job lock and stalled detection).
|
|
@@ -170,6 +154,17 @@ export declare class UsageReporter {
|
|
|
170
154
|
* closes. The queue itself closes with the application.
|
|
171
155
|
*/
|
|
172
156
|
stop(): Promise<void>;
|
|
157
|
+
/** The payload of a job: a `usage` event's or a `model_usage` row's; null when it is gone. */
|
|
158
|
+
private payloadOfJob;
|
|
159
|
+
/**
|
|
160
|
+
* The payload of one `model_usage` row (spec B §5.4): purpose `embedding`, the calling extension,
|
|
161
|
+
* no conversation fields; `eventId` is the row id. Null when the row no longer exists.
|
|
162
|
+
*/
|
|
163
|
+
private payloadOfUsage;
|
|
164
|
+
/** A `model_usage` job is done (delivered, or nothing left to deliver to): marks the row. */
|
|
165
|
+
private markReported;
|
|
166
|
+
/** A `model_usage` job gave up after its last attempt: the sweep never offers the row again. */
|
|
167
|
+
private markFailed;
|
|
173
168
|
/** The payload of one usage event, read from the log; null when the event no longer exists. */
|
|
174
169
|
private payloadOf;
|
|
175
170
|
/**
|