@stigmer/server 3.24.0 → 3.26.0
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/dist/authorization/authorizer.d.ts +10 -4
- package/dist/authorization/authorizer.d.ts.map +1 -1
- package/dist/authorization/authorizer.js +11 -4
- package/dist/authorization/authorizer.js.map +1 -1
- package/dist/authorization/model/index.d.ts +4 -4
- package/dist/authorization/model/index.d.ts.map +1 -1
- package/dist/authorization/model/index.js +2 -0
- package/dist/authorization/model/index.js.map +1 -1
- package/dist/authorization/model/oauth_app.d.ts.map +1 -1
- package/dist/authorization/model/oauth_app.js +3 -2
- package/dist/authorization/model/oauth_app.js.map +1 -1
- package/dist/authorization/model/platform_client.d.ts +2 -0
- package/dist/authorization/model/platform_client.d.ts.map +1 -0
- package/dist/authorization/model/platform_client.js +31 -0
- package/dist/authorization/model/platform_client.js.map +1 -0
- package/dist/boot/compose.d.ts.map +1 -1
- package/dist/boot/compose.js +99 -13
- package/dist/boot/compose.js.map +1 -1
- package/dist/boot/list-indexes.d.ts +3 -0
- package/dist/boot/list-indexes.d.ts.map +1 -0
- package/dist/boot/list-indexes.js +24 -0
- package/dist/boot/list-indexes.js.map +1 -0
- package/dist/boot/route-shadowing.d.ts +25 -0
- package/dist/boot/route-shadowing.d.ts.map +1 -0
- package/dist/boot/route-shadowing.js +17 -0
- package/dist/boot/route-shadowing.js.map +1 -0
- package/dist/domain/agentexecution/controller.d.ts.map +1 -1
- package/dist/domain/agentexecution/controller.js +6 -8
- package/dist/domain/agentexecution/controller.js.map +1 -1
- package/dist/domain/agentexecution/list-index.d.ts +2 -0
- package/dist/domain/agentexecution/list-index.d.ts.map +1 -0
- package/dist/domain/agentexecution/list-index.js +23 -0
- package/dist/domain/agentexecution/list-index.js.map +1 -0
- package/dist/domain/agentexecution/steps.d.ts +17 -33
- package/dist/domain/agentexecution/steps.d.ts.map +1 -1
- package/dist/domain/agentexecution/steps.js +94 -95
- package/dist/domain/agentexecution/steps.js.map +1 -1
- package/dist/domain/agentexecution/usage.d.ts.map +1 -1
- package/dist/domain/agentexecution/usage.js +37 -14
- package/dist/domain/agentexecution/usage.js.map +1 -1
- package/dist/domain/artifact/controller.d.ts.map +1 -1
- package/dist/domain/artifact/controller.js +27 -15
- package/dist/domain/artifact/controller.js.map +1 -1
- package/dist/domain/artifact/list-index.d.ts +2 -0
- package/dist/domain/artifact/list-index.d.ts.map +1 -0
- package/dist/domain/artifact/list-index.js +21 -0
- package/dist/domain/artifact/list-index.js.map +1 -0
- package/dist/domain/iampolicy/membership.d.ts +6 -1
- package/dist/domain/iampolicy/membership.d.ts.map +1 -1
- package/dist/domain/iampolicy/membership.js +8 -2
- package/dist/domain/iampolicy/membership.js.map +1 -1
- package/dist/domain/identityaccount/constants.d.ts +13 -0
- package/dist/domain/identityaccount/constants.d.ts.map +1 -1
- package/dist/domain/identityaccount/constants.js +17 -0
- package/dist/domain/identityaccount/constants.js.map +1 -1
- package/dist/domain/identityaccount/controller.d.ts +3 -1
- package/dist/domain/identityaccount/controller.d.ts.map +1 -1
- package/dist/domain/identityaccount/controller.js +15 -6
- package/dist/domain/identityaccount/controller.js.map +1 -1
- package/dist/domain/identityaccount/operator.d.ts.map +1 -1
- package/dist/domain/identityaccount/operator.js +1 -0
- package/dist/domain/identityaccount/operator.js.map +1 -1
- package/dist/domain/identityaccount/provisioning.d.ts +18 -0
- package/dist/domain/identityaccount/provisioning.d.ts.map +1 -1
- package/dist/domain/identityaccount/provisioning.js +1 -0
- package/dist/domain/identityaccount/provisioning.js.map +1 -1
- package/dist/domain/identityaccount/resource-store.js +9 -5
- package/dist/domain/identityaccount/resource-store.js.map +1 -1
- package/dist/domain/identityaccount/steps.d.ts +11 -2
- package/dist/domain/identityaccount/steps.d.ts.map +1 -1
- package/dist/domain/identityaccount/steps.js +42 -4
- package/dist/domain/identityaccount/steps.js.map +1 -1
- package/dist/domain/identityaccount/store-contract.d.ts.map +1 -1
- package/dist/domain/identityaccount/store-contract.js +33 -0
- package/dist/domain/identityaccount/store-contract.js.map +1 -1
- package/dist/domain/identityaccount/store.d.ts +7 -5
- package/dist/domain/identityaccount/store.d.ts.map +1 -1
- package/dist/domain/identityaccount/store.js.map +1 -1
- package/dist/domain/platform/controller.d.ts +10 -0
- package/dist/domain/platform/controller.d.ts.map +1 -1
- package/dist/domain/platform/controller.js +2 -1
- package/dist/domain/platform/controller.js.map +1 -1
- package/dist/domain/platformclient/constants.d.ts +60 -0
- package/dist/domain/platformclient/constants.d.ts.map +1 -0
- package/dist/domain/platformclient/constants.js +78 -0
- package/dist/domain/platformclient/constants.js.map +1 -0
- package/dist/domain/platformclient/controller.d.ts +59 -0
- package/dist/domain/platformclient/controller.d.ts.map +1 -0
- package/dist/domain/platformclient/controller.js +191 -0
- package/dist/domain/platformclient/controller.js.map +1 -0
- package/dist/domain/platformclient/credentials.d.ts +13 -0
- package/dist/domain/platformclient/credentials.d.ts.map +1 -0
- package/dist/domain/platformclient/credentials.js +56 -0
- package/dist/domain/platformclient/credentials.js.map +1 -0
- package/dist/domain/platformclient/mint.d.ts +23 -0
- package/dist/domain/platformclient/mint.d.ts.map +1 -0
- package/dist/domain/platformclient/mint.js +254 -0
- package/dist/domain/platformclient/mint.js.map +1 -0
- package/dist/domain/platformclient/origin-guard.d.ts +9 -0
- package/dist/domain/platformclient/origin-guard.d.ts.map +1 -0
- package/dist/domain/platformclient/origin-guard.js +81 -0
- package/dist/domain/platformclient/origin-guard.js.map +1 -0
- package/dist/domain/platformclient/resource-store.d.ts +4 -0
- package/dist/domain/platformclient/resource-store.d.ts.map +1 -0
- package/dist/domain/platformclient/resource-store.js +117 -0
- package/dist/domain/platformclient/resource-store.js.map +1 -0
- package/dist/domain/platformclient/steps.d.ts +51 -0
- package/dist/domain/platformclient/steps.d.ts.map +1 -0
- package/dist/domain/platformclient/steps.js +339 -0
- package/dist/domain/platformclient/steps.js.map +1 -0
- package/dist/domain/platformclient/store-contract.d.ts +8 -0
- package/dist/domain/platformclient/store-contract.d.ts.map +1 -0
- package/dist/domain/platformclient/store-contract.js +208 -0
- package/dist/domain/platformclient/store-contract.js.map +1 -0
- package/dist/domain/platformclient/store.d.ts +58 -0
- package/dist/domain/platformclient/store.d.ts.map +1 -0
- package/dist/domain/platformclient/store.js +13 -0
- package/dist/domain/platformclient/store.js.map +1 -0
- package/dist/domain/platformclient/system-managed.d.ts +18 -0
- package/dist/domain/platformclient/system-managed.d.ts.map +1 -0
- package/dist/domain/platformclient/system-managed.js +80 -0
- package/dist/domain/platformclient/system-managed.js.map +1 -0
- package/dist/domain/platformclient/token-controller.d.ts +11 -0
- package/dist/domain/platformclient/token-controller.d.ts.map +1 -0
- package/dist/domain/platformclient/token-controller.js +32 -0
- package/dist/domain/platformclient/token-controller.js.map +1 -0
- package/dist/domain/platformclient/verifier.d.ts +10 -0
- package/dist/domain/platformclient/verifier.d.ts.map +1 -0
- package/dist/domain/platformclient/verifier.js +76 -0
- package/dist/domain/platformclient/verifier.js.map +1 -0
- package/dist/domain/session/list-index.d.ts +4 -0
- package/dist/domain/session/list-index.d.ts.map +1 -0
- package/dist/domain/session/list-index.js +26 -0
- package/dist/domain/session/list-index.js.map +1 -0
- package/dist/domain/session/steps.d.ts +7 -8
- package/dist/domain/session/steps.d.ts.map +1 -1
- package/dist/domain/session/steps.js +76 -78
- package/dist/domain/session/steps.js.map +1 -1
- package/dist/domain/workflowexecution/controller.d.ts.map +1 -1
- package/dist/domain/workflowexecution/controller.js +53 -55
- package/dist/domain/workflowexecution/controller.js.map +1 -1
- package/dist/domain/workflowexecution/execution-filter.d.ts +4 -0
- package/dist/domain/workflowexecution/execution-filter.d.ts.map +1 -1
- package/dist/domain/workflowexecution/execution-filter.js +11 -5
- package/dist/domain/workflowexecution/execution-filter.js.map +1 -1
- package/dist/domain/workflowexecution/get-execution-summary.d.ts.map +1 -1
- package/dist/domain/workflowexecution/get-execution-summary.js +23 -17
- package/dist/domain/workflowexecution/get-execution-summary.js.map +1 -1
- package/dist/domain/workflowexecution/list-index.d.ts +2 -0
- package/dist/domain/workflowexecution/list-index.d.ts.map +1 -0
- package/dist/domain/workflowexecution/list-index.js +21 -0
- package/dist/domain/workflowexecution/list-index.js.map +1 -0
- package/dist/domain/workflowexecution/list-pending-approvals.d.ts.map +1 -1
- package/dist/domain/workflowexecution/list-pending-approvals.js +69 -32
- package/dist/domain/workflowexecution/list-pending-approvals.js.map +1 -1
- package/dist/domain/workflowexecution/queries.d.ts +30 -4
- package/dist/domain/workflowexecution/queries.d.ts.map +1 -1
- package/dist/domain/workflowexecution/queries.js +76 -22
- package/dist/domain/workflowexecution/queries.js.map +1 -1
- package/dist/encryption/key-manager.d.ts +20 -3
- package/dist/encryption/key-manager.d.ts.map +1 -1
- package/dist/encryption/key-manager.js +64 -42
- package/dist/encryption/key-manager.js.map +1 -1
- package/dist/extensions/caller-guards.d.ts +8 -3
- package/dist/extensions/caller-guards.d.ts.map +1 -1
- package/dist/extensions/drivers.d.ts +37 -0
- package/dist/extensions/drivers.d.ts.map +1 -1
- package/dist/extensions/guest-token-minting.d.ts +26 -0
- package/dist/extensions/guest-token-minting.d.ts.map +1 -0
- package/dist/extensions/guest-token-minting.js +2 -0
- package/dist/extensions/guest-token-minting.js.map +1 -0
- package/dist/extensions/identity.d.ts +6 -4
- package/dist/extensions/identity.d.ts.map +1 -1
- package/dist/extensions/identity.js.map +1 -1
- package/dist/extensions/list-read-scope.d.ts +9 -12
- package/dist/extensions/list-read-scope.d.ts.map +1 -1
- package/dist/extensions/list-read-scope.js.map +1 -1
- package/dist/extensions/registry.d.ts +30 -1
- package/dist/extensions/registry.d.ts.map +1 -1
- package/dist/extensions/registry.js +34 -1
- package/dist/extensions/registry.js.map +1 -1
- package/dist/index.d.ts +15 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/pipeline/interceptors/auth.d.ts +14 -0
- package/dist/pipeline/interceptors/auth.d.ts.map +1 -1
- package/dist/pipeline/interceptors/auth.js +24 -0
- package/dist/pipeline/interceptors/auth.js.map +1 -1
- package/dist/pipeline/steps/build-update-state.d.ts +11 -1
- package/dist/pipeline/steps/build-update-state.d.ts.map +1 -1
- package/dist/pipeline/steps/build-update-state.js +5 -2
- package/dist/pipeline/steps/build-update-state.js.map +1 -1
- package/dist/pipeline/steps/list-page.d.ts +63 -0
- package/dist/pipeline/steps/list-page.d.ts.map +1 -0
- package/dist/pipeline/steps/list-page.js +187 -0
- package/dist/pipeline/steps/list-page.js.map +1 -0
- package/dist/platformtoken/envelope.d.ts +100 -0
- package/dist/platformtoken/envelope.d.ts.map +1 -0
- package/dist/platformtoken/envelope.js +184 -0
- package/dist/platformtoken/envelope.js.map +1 -0
- package/dist/platformtoken/key-ring.d.ts +85 -0
- package/dist/platformtoken/key-ring.d.ts.map +1 -0
- package/dist/platformtoken/key-ring.js +164 -0
- package/dist/platformtoken/key-ring.js.map +1 -0
- package/dist/query/activity/handler.d.ts +6 -7
- package/dist/query/activity/handler.d.ts.map +1 -1
- package/dist/query/activity/handler.js +42 -59
- package/dist/query/activity/handler.js.map +1 -1
- package/dist/store/interface.d.ts +29 -0
- package/dist/store/interface.d.ts.map +1 -1
- package/dist/store/interface.js.map +1 -1
- package/dist/store/list-index.d.ts +123 -0
- package/dist/store/list-index.d.ts.map +1 -0
- package/dist/store/list-index.js +277 -0
- package/dist/store/list-index.js.map +1 -0
- package/dist/store/logger.d.ts +3 -0
- package/dist/store/logger.d.ts.map +1 -1
- package/dist/store/logger.js +5 -1
- package/dist/store/logger.js.map +1 -1
- package/dist/store/postgres/migrations.d.ts +10 -6
- package/dist/store/postgres/migrations.d.ts.map +1 -1
- package/dist/store/postgres/migrations.js +64 -6
- package/dist/store/postgres/migrations.js.map +1 -1
- package/dist/store/postgres/store.d.ts +26 -5
- package/dist/store/postgres/store.d.ts.map +1 -1
- package/dist/store/postgres/store.js +377 -22
- package/dist/store/postgres/store.js.map +1 -1
- package/dist/store/sqlite/migrations.d.ts +11 -5
- package/dist/store/sqlite/migrations.d.ts.map +1 -1
- package/dist/store/sqlite/migrations.js +50 -4
- package/dist/store/sqlite/migrations.js.map +1 -1
- package/dist/store/sqlite/store.d.ts +18 -3
- package/dist/store/sqlite/store.d.ts.map +1 -1
- package/dist/store/sqlite/store.js +321 -15
- package/dist/store/sqlite/store.js.map +1 -1
- package/package.json +6 -6
- package/src/authorization/README.md +1 -1
- package/src/authorization/__tests__/authorizer.test.ts +6 -2
- package/src/authorization/__tests__/drivers.ts +6 -1
- package/src/authorization/__tests__/wire-permissions.test.ts +1 -0
- package/src/authorization/authorizer.ts +11 -4
- package/src/authorization/model/__tests__/registry.test.ts +8 -1
- package/src/authorization/model/index.ts +6 -4
- package/src/authorization/model/oauth_app.ts +3 -2
- package/src/authorization/model/platform_client.ts +43 -0
- package/src/boot/__tests__/auth-enabled-composition.test.ts +2 -1
- package/src/boot/__tests__/list-indexes.test.ts +65 -0
- package/src/boot/__tests__/route-shadowing.test.ts +67 -0
- package/src/boot/compose.ts +113 -18
- package/src/boot/list-indexes.ts +25 -0
- package/src/boot/route-shadowing.ts +47 -0
- package/src/domain/agentexecution/__tests__/agentexecution.test.ts +85 -3
- package/src/domain/agentexecution/controller.ts +8 -10
- package/src/domain/agentexecution/list-index.ts +24 -0
- package/src/domain/agentexecution/steps.ts +118 -115
- package/src/domain/agentexecution/usage.ts +38 -17
- package/src/domain/artifact/controller.ts +28 -18
- package/src/domain/artifact/list-index.ts +22 -0
- package/src/domain/iampolicy/__tests__/membership.test.ts +7 -0
- package/src/domain/iampolicy/membership.ts +8 -2
- package/src/domain/identityaccount/__tests__/platform-client-accounts.test.ts +124 -0
- package/src/domain/identityaccount/__tests__/resource-store.test.ts +1 -0
- package/src/domain/identityaccount/constants.ts +20 -0
- package/src/domain/identityaccount/controller.ts +16 -4
- package/src/domain/identityaccount/operator.ts +1 -0
- package/src/domain/identityaccount/provisioning.ts +17 -0
- package/src/domain/identityaccount/resource-store.ts +9 -5
- package/src/domain/identityaccount/steps.ts +58 -3
- package/src/domain/identityaccount/store-contract.ts +51 -0
- package/src/domain/identityaccount/store.ts +7 -5
- package/src/domain/platform/__tests__/platform.test.ts +7 -1
- package/src/domain/platform/controller.ts +12 -1
- package/src/domain/platformclient/__tests__/controller.test.ts +397 -0
- package/src/domain/platformclient/__tests__/credentials.test.ts +46 -0
- package/src/domain/platformclient/__tests__/mint.test.ts +415 -0
- package/src/domain/platformclient/__tests__/resource-store.test.ts +140 -0
- package/src/domain/platformclient/__tests__/system-managed.test.ts +101 -0
- package/src/domain/platformclient/__tests__/verifier-and-guard.test.ts +207 -0
- package/src/domain/platformclient/constants.ts +120 -0
- package/src/domain/platformclient/controller.ts +449 -0
- package/src/domain/platformclient/credentials.ts +68 -0
- package/src/domain/platformclient/mint.ts +412 -0
- package/src/domain/platformclient/origin-guard.ts +117 -0
- package/src/domain/platformclient/resource-store.ts +150 -0
- package/src/domain/platformclient/steps.ts +472 -0
- package/src/domain/platformclient/store-contract.ts +318 -0
- package/src/domain/platformclient/store.ts +63 -0
- package/src/domain/platformclient/system-managed.ts +115 -0
- package/src/domain/platformclient/token-controller.ts +49 -0
- package/src/domain/platformclient/verifier.ts +106 -0
- package/src/domain/session/list-index.ts +28 -0
- package/src/domain/session/steps.ts +108 -123
- package/src/domain/workflowexecution/__tests__/list-read-scope-summaries.test.ts +155 -99
- package/src/domain/workflowexecution/__tests__/workflowexecution.test.ts +193 -31
- package/src/domain/workflowexecution/controller.ts +54 -82
- package/src/domain/workflowexecution/execution-filter.ts +20 -7
- package/src/domain/workflowexecution/get-execution-summary.ts +31 -24
- package/src/domain/workflowexecution/list-index.ts +22 -0
- package/src/domain/workflowexecution/list-pending-approvals.ts +82 -25
- package/src/domain/workflowexecution/queries.ts +134 -23
- package/src/encryption/key-manager.ts +87 -44
- package/src/extensions/__tests__/extension-composition.test.ts +3 -2
- package/src/extensions/__tests__/platform-client-composed.test.ts +288 -0
- package/src/extensions/__tests__/registry.test.ts +4 -1
- package/src/extensions/__tests__/tier-truthfulness.test.ts +8 -0
- package/src/extensions/caller-guards.ts +8 -3
- package/src/extensions/drivers.ts +37 -0
- package/src/extensions/guest-token-minting.ts +32 -0
- package/src/extensions/identity.ts +6 -4
- package/src/extensions/list-read-scope.ts +9 -12
- package/src/extensions/registry.ts +77 -3
- package/src/index.ts +65 -1
- package/src/pipeline/interceptors/auth.ts +27 -0
- package/src/pipeline/steps/__tests__/list-page.test.ts +186 -0
- package/src/pipeline/steps/__tests__/references.test.ts +2 -0
- package/src/pipeline/steps/build-update-state.ts +5 -2
- package/src/pipeline/steps/list-page.ts +284 -0
- package/src/platformtoken/__tests__/envelope.test.ts +277 -0
- package/src/platformtoken/__tests__/key-ring.test.ts +205 -0
- package/src/platformtoken/envelope.ts +276 -0
- package/src/platformtoken/key-ring.ts +266 -0
- package/src/query/activity/handler.ts +57 -78
- package/src/runnerauth/__tests__/runner-subject-composed.test.ts +9 -3
- package/src/store/README.md +51 -32
- package/src/store/__tests__/list-index.measure.test.ts +293 -0
- package/src/store/__tests__/list-index.test.ts +328 -0
- package/src/store/__tests__/store-contract.ts +346 -3
- package/src/store/interface.ts +39 -0
- package/src/store/list-index.ts +465 -0
- package/src/store/logger.ts +8 -1
- package/src/store/postgres/__tests__/list-index-repair.test.ts +133 -0
- package/src/store/postgres/__tests__/migrations.test.ts +27 -19
- package/src/store/postgres/__tests__/store-contract.test.ts +50 -3
- package/src/store/postgres/migrations.ts +69 -7
- package/src/store/postgres/store.ts +485 -29
- package/src/store/sqlite/__tests__/migrations.test.ts +51 -7
- package/src/store/sqlite/__tests__/store-contract.test.ts +70 -16
- package/src/store/sqlite/__tests__/support.ts +12 -3
- package/src/store/sqlite/migrations.ts +57 -6
- package/src/store/sqlite/store.ts +462 -21
|
@@ -12,8 +12,9 @@
|
|
|
12
12
|
* byte-for-byte (sub-project DD-001: faithful-port + OSS issue);
|
|
13
13
|
* - getAgentUsageReport org scoping (oss#389) incl. the no-name-oracle
|
|
14
14
|
* rule (Go get_agent_usage_report_test.go case-for-case);
|
|
15
|
-
* - list/listBySession filter semantics over seeded rows
|
|
16
|
-
*
|
|
15
|
+
* - list/listBySession filter semantics over seeded rows; list's cursor
|
|
16
|
+
* pages (newest created first, one organization, a token refused on
|
|
17
|
+
* another request) and listBySession returning its parent whole;
|
|
17
18
|
* - update's status-clearing standard build and delete's audit-trail
|
|
18
19
|
* return, over the wire;
|
|
19
20
|
* - the populated getExecutionSummary arm (phase counts, active count,
|
|
@@ -28,6 +29,7 @@ import path from "node:path";
|
|
|
28
29
|
|
|
29
30
|
import { create, fromBinary } from "@bufbuild/protobuf";
|
|
30
31
|
import type { MessageInitShape } from "@bufbuild/protobuf";
|
|
32
|
+
import { timestampFromMs } from "@bufbuild/protobuf/wkt";
|
|
31
33
|
import { Code, ConnectError, createClient } from "@connectrpc/connect";
|
|
32
34
|
import type { Client, Transport } from "@connectrpc/connect";
|
|
33
35
|
import { createGrpcTransport } from "@connectrpc/connect-node";
|
|
@@ -146,6 +148,7 @@ function seedInput(overrides?: {
|
|
|
146
148
|
phase?: ExecutionPhase;
|
|
147
149
|
startedAt?: string;
|
|
148
150
|
completedAt?: string;
|
|
151
|
+
createdAtMs?: number;
|
|
149
152
|
}): MessageInitShape<typeof AgentExecutionSchema> & {
|
|
150
153
|
metadata: { id: string };
|
|
151
154
|
} {
|
|
@@ -170,6 +173,12 @@ function seedInput(overrides?: {
|
|
|
170
173
|
phase: overrides?.phase ?? ExecutionPhase.EXECUTION_COMPLETED,
|
|
171
174
|
startedAt: overrides?.startedAt ?? "",
|
|
172
175
|
completedAt: overrides?.completedAt ?? "",
|
|
176
|
+
audit:
|
|
177
|
+
overrides?.createdAtMs === undefined
|
|
178
|
+
? undefined
|
|
179
|
+
: {
|
|
180
|
+
specAudit: { createdAt: timestampFromMs(overrides.createdAtMs) },
|
|
181
|
+
},
|
|
173
182
|
},
|
|
174
183
|
};
|
|
175
184
|
}
|
|
@@ -322,7 +331,7 @@ describe("get / list / listBySession over the wire", () => {
|
|
|
322
331
|
expect(got.spec?.message).toBe("Say hello.");
|
|
323
332
|
});
|
|
324
333
|
|
|
325
|
-
it("list returns every row
|
|
334
|
+
it("list with no page_size returns every row whole (total_pages 1), filtered by phase on request", async () => {
|
|
326
335
|
const completed = await seed(
|
|
327
336
|
seedInput({ phase: ExecutionPhase.EXECUTION_COMPLETED }),
|
|
328
337
|
);
|
|
@@ -359,6 +368,79 @@ describe("get / list / listBySession over the wire", () => {
|
|
|
359
368
|
expect(ids).toContain(inSession);
|
|
360
369
|
expect(ids).not.toContain(outOfSession);
|
|
361
370
|
});
|
|
371
|
+
|
|
372
|
+
it("list pages one organization newest created first, with a token until the last page", async () => {
|
|
373
|
+
const org = "paging-org";
|
|
374
|
+
const base = Date.parse("2026-09-01T00:00:00Z");
|
|
375
|
+
const newestFirst: string[] = [];
|
|
376
|
+
for (let i = 0; i < 5; i++) {
|
|
377
|
+
newestFirst.unshift(
|
|
378
|
+
await seed(seedInput({ org, createdAtMs: base + i * 1000 })),
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
await seed(seedInput({ org: "other-org", createdAtMs: base + 10_000 }));
|
|
382
|
+
|
|
383
|
+
const walked: string[] = [];
|
|
384
|
+
let pageToken = "";
|
|
385
|
+
do {
|
|
386
|
+
const page = await query.list({ org, pageSize: 2, pageToken });
|
|
387
|
+
expect(page.entries.length).toBeLessThanOrEqual(2);
|
|
388
|
+
expect(page.totalPages).toBe(page.nextPageToken === "" ? 1 : 0);
|
|
389
|
+
walked.push(...page.entries.map((e) => e.metadata!.id));
|
|
390
|
+
pageToken = page.nextPageToken;
|
|
391
|
+
} while (pageToken !== "");
|
|
392
|
+
|
|
393
|
+
expect(walked).toEqual(newestFirst);
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
it("list refuses a page_token issued for another request, and a negative page_size", async () => {
|
|
397
|
+
const org = "token-org";
|
|
398
|
+
await seed(
|
|
399
|
+
seedInput({ org, createdAtMs: Date.parse("2026-09-02T00:00:00Z") }),
|
|
400
|
+
);
|
|
401
|
+
await seed(
|
|
402
|
+
seedInput({ org, createdAtMs: Date.parse("2026-09-02T00:00:01Z") }),
|
|
403
|
+
);
|
|
404
|
+
const first = await query.list({ org, pageSize: 1 });
|
|
405
|
+
expect(first.nextPageToken).not.toBe("");
|
|
406
|
+
|
|
407
|
+
const replayed = await expectCode(
|
|
408
|
+
() =>
|
|
409
|
+
query.list({
|
|
410
|
+
org,
|
|
411
|
+
phase: ExecutionPhase.EXECUTION_FAILED,
|
|
412
|
+
pageSize: 1,
|
|
413
|
+
pageToken: first.nextPageToken,
|
|
414
|
+
}),
|
|
415
|
+
Code.InvalidArgument,
|
|
416
|
+
);
|
|
417
|
+
expect(replayed.rawMessage).toBe(
|
|
418
|
+
"page_token was issued for a different request",
|
|
419
|
+
);
|
|
420
|
+
await expectCode(
|
|
421
|
+
() => query.list({ org, pageToken: "not-a-token" }),
|
|
422
|
+
Code.InvalidArgument,
|
|
423
|
+
);
|
|
424
|
+
await expectCode(
|
|
425
|
+
() => query.list({ org, pageSize: -1 }),
|
|
426
|
+
Code.InvalidArgument,
|
|
427
|
+
);
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
it("listBySession returns the session's executions whole, whatever page_size says", async () => {
|
|
431
|
+
const ids = new Set<string>();
|
|
432
|
+
for (let i = 0; i < 3; i++) {
|
|
433
|
+
ids.add(await seed(seedInput({ sessionId: "ses_whole" })));
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
const result = await query.listBySession({
|
|
437
|
+
sessionId: "ses_whole",
|
|
438
|
+
pageSize: 1,
|
|
439
|
+
});
|
|
440
|
+
expect(new Set(result.entries.map((e) => e.metadata!.id))).toEqual(ids);
|
|
441
|
+
expect(result.nextPageToken).toBe("");
|
|
442
|
+
expect(result.totalPages).toBe(1);
|
|
443
|
+
});
|
|
362
444
|
});
|
|
363
445
|
|
|
364
446
|
describe("update / delete over the wire", () => {
|
|
@@ -128,10 +128,8 @@ import { newValidateVisibilityStep } from "../../pipeline/steps/validate-visibil
|
|
|
128
128
|
import { newBuildNewStateStep } from "../../pipeline/steps/defaults.js";
|
|
129
129
|
import {
|
|
130
130
|
EXECUTION_LIST_KEY,
|
|
131
|
-
newApplyPhaseFilterStep,
|
|
132
131
|
newBuildExecutionListResponseStep,
|
|
133
|
-
|
|
134
|
-
newRestrictByReadScopeStep,
|
|
132
|
+
newQueryExecutionPageStep,
|
|
135
133
|
newQueryExecutionsBySessionStep,
|
|
136
134
|
newValidateListBySessionRequestStep,
|
|
137
135
|
newValidateListRequestStep,
|
|
@@ -527,9 +525,9 @@ async function get(
|
|
|
527
525
|
}
|
|
528
526
|
|
|
529
527
|
/**
|
|
530
|
-
* List — list.go:
|
|
531
|
-
*
|
|
532
|
-
*
|
|
528
|
+
* List — list.go: one page of the request's org (or every org), newest
|
|
529
|
+
* first, the optional phase filter and the read scope per batch
|
|
530
|
+
* (steps.ts, QueryExecutionPage).
|
|
533
531
|
*/
|
|
534
532
|
async function list(
|
|
535
533
|
deps: AgentExecutionControllerDeps,
|
|
@@ -553,16 +551,16 @@ async function list(
|
|
|
553
551
|
),
|
|
554
552
|
)
|
|
555
553
|
.addStep(newValidateListRequestStep())
|
|
556
|
-
.addStep(
|
|
557
|
-
|
|
558
|
-
|
|
554
|
+
.addStep(
|
|
555
|
+
newQueryExecutionPageStep(deps.store, deps.logger, deps.listReadScope),
|
|
556
|
+
)
|
|
559
557
|
.addStep(newBuildExecutionListResponseStep())
|
|
560
558
|
.build()
|
|
561
559
|
.execute(reqCtx);
|
|
562
560
|
return requireListResult(reqCtx.get(EXECUTION_LIST_KEY));
|
|
563
561
|
}
|
|
564
562
|
|
|
565
|
-
/** ListBySession — list_by_session.go:
|
|
563
|
+
/** ListBySession — list_by_session.go: the session's executions, whole, newest first. */
|
|
566
564
|
async function listBySession(
|
|
567
565
|
deps: AgentExecutionControllerDeps,
|
|
568
566
|
req: ListAgentExecutionsBySessionRequest,
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The agent-execution list index (store/list-index.ts): the kind whose
|
|
3
|
+
* rows are the fattest in the store (every message and tool call of a run
|
|
4
|
+
* rides the row), so a lane that decodes the whole kind to keep one
|
|
5
|
+
* session's runs pays for every run on the platform. `session` is the key
|
|
6
|
+
* `listBySession` reads; the organization and the creation order are
|
|
7
|
+
* every declaration's.
|
|
8
|
+
*
|
|
9
|
+
* A change to `keys` bumps `revision` (boot/__tests__/list-indexes.test.ts
|
|
10
|
+
* pins the pair).
|
|
11
|
+
*/
|
|
12
|
+
import { AgentExecutionSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
|
|
13
|
+
import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
|
|
14
|
+
|
|
15
|
+
import { declareListIndex, field } from "../../store/list-index.js";
|
|
16
|
+
|
|
17
|
+
export const agentExecutionListIndex = declareListIndex({
|
|
18
|
+
kind: ApiResourceKind.agent_execution,
|
|
19
|
+
schema: AgentExecutionSchema,
|
|
20
|
+
revision: 1,
|
|
21
|
+
keys: {
|
|
22
|
+
session: field("spec.session_id"),
|
|
23
|
+
},
|
|
24
|
+
});
|
|
@@ -3,10 +3,14 @@
|
|
|
3
3
|
* list_by_session.go, plus the full-scan load helper the usage reports
|
|
4
4
|
* share.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
6
|
+
* Both lists read through the list index (list-index.ts beside this file;
|
|
7
|
+
* the store's contract in store/interface.ts), newest first by spec-audit
|
|
8
|
+
* created_at. `list` pages (pipeline/steps/list-page.ts): the store
|
|
9
|
+
* narrows by the request's org, the phase filter and then the read scope
|
|
10
|
+
* run on each batch — the scope last, so a composed driver is asked about
|
|
11
|
+
* the rows the request keeps. `listBySession` returns the session's
|
|
12
|
+
* executions whole: a conversation is read as one, and its consumers (the
|
|
13
|
+
* transcript, the channel and guest turn limits) need all of it.
|
|
10
14
|
*/
|
|
11
15
|
import { create, fromBinary } from "@bufbuild/protobuf";
|
|
12
16
|
|
|
@@ -22,12 +26,19 @@ import type { ListReadScope } from "../../extensions/list-read-scope.js";
|
|
|
22
26
|
import { restrictListByReadScope } from "../../extensions/list-read-scope.js";
|
|
23
27
|
import { internalError, invalidArgumentError } from "../../pipeline/errors.js";
|
|
24
28
|
import type { PipelineStep } from "../../pipeline/pipeline.js";
|
|
29
|
+
import {
|
|
30
|
+
listPageFingerprint,
|
|
31
|
+
readListPage,
|
|
32
|
+
} from "../../pipeline/steps/list-page.js";
|
|
33
|
+
import type { ListPage } from "../../pipeline/steps/list-page.js";
|
|
25
34
|
import type { Store } from "../../store/interface.js";
|
|
35
|
+
import type { ListIndexRow } from "../../store/list-index.js";
|
|
36
|
+
import { agentExecutionListIndex } from "./list-index.js";
|
|
26
37
|
|
|
27
38
|
/**
|
|
28
|
-
* Inter-step key for the working
|
|
29
|
-
*
|
|
30
|
-
* the
|
|
39
|
+
* Inter-step key for the working page AND the final AgentExecutionList —
|
|
40
|
+
* Go reuses one key ("execution_list") for both, and the controller reads
|
|
41
|
+
* the final response from it.
|
|
31
42
|
*/
|
|
32
43
|
export const EXECUTION_LIST_KEY = "execution_list";
|
|
33
44
|
|
|
@@ -36,8 +47,9 @@ type ListBySessionDesc =
|
|
|
36
47
|
typeof AgentExecutionQueryController.method.listBySession.input;
|
|
37
48
|
|
|
38
49
|
/**
|
|
39
|
-
* Full-scan agent-execution load
|
|
40
|
-
*
|
|
50
|
+
* Full-scan agent-execution load for the usage reports, whose org match
|
|
51
|
+
* is case-insensitive (Go strings.EqualFold) where the list index's is
|
|
52
|
+
* exact; malformed rows warn + skip (Go's proto.Unmarshal-continue).
|
|
41
53
|
*/
|
|
42
54
|
export async function loadAllAgentExecutions(
|
|
43
55
|
store: Store,
|
|
@@ -49,21 +61,7 @@ export async function loadAllAgentExecutions(
|
|
|
49
61
|
} catch (error) {
|
|
50
62
|
throw internalError(error, "failed to list agent executions");
|
|
51
63
|
}
|
|
52
|
-
|
|
53
|
-
const executions: AgentExecution[] = [];
|
|
54
|
-
for (const data of rows) {
|
|
55
|
-
let execution: AgentExecution;
|
|
56
|
-
try {
|
|
57
|
-
execution = fromBinary(AgentExecutionSchema, data);
|
|
58
|
-
} catch (error) {
|
|
59
|
-
logger.warn("Failed to unmarshal execution, skipping", {
|
|
60
|
-
error: error instanceof Error ? error.message : String(error),
|
|
61
|
-
});
|
|
62
|
-
continue;
|
|
63
|
-
}
|
|
64
|
-
executions.push(execution);
|
|
65
|
-
}
|
|
66
|
-
return executions;
|
|
64
|
+
return decodeExecutions(rows, logger);
|
|
67
65
|
}
|
|
68
66
|
|
|
69
67
|
/** ValidateListRequest — list.go: no required fields today (a no-op). */
|
|
@@ -71,92 +69,54 @@ export function newValidateListRequestStep(): PipelineStep<ListDesc> {
|
|
|
71
69
|
return {
|
|
72
70
|
name: "ValidateListRequest",
|
|
73
71
|
execute() {
|
|
74
|
-
// Go validates nothing here yet;
|
|
75
|
-
//
|
|
72
|
+
// Go validates nothing here yet; page_size is protovalidate's and
|
|
73
|
+
// page_token the page reader's.
|
|
76
74
|
},
|
|
77
75
|
};
|
|
78
76
|
}
|
|
79
77
|
|
|
80
78
|
/**
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
* org and phase, not the kind (extensions/list-read-scope.ts, the
|
|
86
|
-
* header's last contract line).
|
|
79
|
+
* QueryExecutionPage — one page of the request's executions: its org
|
|
80
|
+
* through the index when it names one, its phase when it names one, the
|
|
81
|
+
* read scope last (census lane 4; with no scope composed, every matching
|
|
82
|
+
* execution — the OSS single-user posture).
|
|
87
83
|
*/
|
|
88
|
-
export function
|
|
84
|
+
export function newQueryExecutionPageStep(
|
|
89
85
|
store: Store,
|
|
90
86
|
logger: Logger,
|
|
91
|
-
): PipelineStep<ListDesc> {
|
|
92
|
-
return {
|
|
93
|
-
name: "QueryAllExecutions",
|
|
94
|
-
async execute(ctx) {
|
|
95
|
-
const executions = await loadAllAgentExecutions(store, logger);
|
|
96
|
-
logger.debug("Successfully queried executions", {
|
|
97
|
-
count: executions.length,
|
|
98
|
-
});
|
|
99
|
-
ctx.set(EXECUTION_LIST_KEY, executions);
|
|
100
|
-
},
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* RestrictByReadScope — the list chain's last per-row predicate (census
|
|
106
|
-
* lane 4). With a composed ListReadScope (20260830.01) the working list
|
|
107
|
-
* narrows to the caller's authorized executions ∩ the request's org (the
|
|
108
|
-
* Java AgentExecutionListHandler baseline: org set = one-org view, blank
|
|
109
|
-
* = permission-bounded across orgs; the guest cookie rule rides the
|
|
110
|
-
* driver); no scope = the working list unchanged, org a no-op —
|
|
111
|
-
* byte-identical. Placed after ApplyPhaseFilter so the driver is asked
|
|
112
|
-
* about the rows the request keeps, never about the whole kind.
|
|
113
|
-
*/
|
|
114
|
-
export function newRestrictByReadScopeStep(
|
|
115
87
|
listReadScope: ListReadScope | undefined,
|
|
116
88
|
): PipelineStep<ListDesc> {
|
|
117
89
|
return {
|
|
118
|
-
name: "
|
|
90
|
+
name: "QueryExecutionPage",
|
|
119
91
|
async execute(ctx) {
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* ApplyPhaseFilter — list.go: status.phase equality filter, skipped when
|
|
137
|
-
* the request carries no phase.
|
|
138
|
-
*/
|
|
139
|
-
export function newApplyPhaseFilterStep(
|
|
140
|
-
logger: Logger,
|
|
141
|
-
): PipelineStep<ListDesc> {
|
|
142
|
-
return {
|
|
143
|
-
name: "ApplyPhaseFilter",
|
|
144
|
-
execute(ctx) {
|
|
145
|
-
const executions = requireExecutions(ctx.get(EXECUTION_LIST_KEY));
|
|
146
|
-
if (ctx.input.phase === ExecutionPhase.EXECUTION_PHASE_UNSPECIFIED) {
|
|
147
|
-
logger.debug("No phase filter specified, skipping");
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
|
-
const filtered = executions.filter(
|
|
151
|
-
(execution) =>
|
|
92
|
+
const input = ctx.input;
|
|
93
|
+
const page = await readListPage({
|
|
94
|
+
store,
|
|
95
|
+
declaration: agentExecutionListIndex,
|
|
96
|
+
query: { org: input.org },
|
|
97
|
+
request: input,
|
|
98
|
+
fingerprint: listPageFingerprint({
|
|
99
|
+
lane: "agentExecution.list",
|
|
100
|
+
org: input.org,
|
|
101
|
+
phase: input.phase,
|
|
102
|
+
tags: input.tags,
|
|
103
|
+
}),
|
|
104
|
+
decode: (data) => decodeExecution(data, logger),
|
|
105
|
+
keep: (execution) =>
|
|
106
|
+
input.phase === ExecutionPhase.EXECUTION_PHASE_UNSPECIFIED ||
|
|
152
107
|
(execution.status?.phase ??
|
|
153
|
-
ExecutionPhase.EXECUTION_PHASE_UNSPECIFIED) ===
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
108
|
+
ExecutionPhase.EXECUTION_PHASE_UNSPECIFIED) === input.phase,
|
|
109
|
+
scope: (executions) =>
|
|
110
|
+
restrictListByReadScope(
|
|
111
|
+
listReadScope,
|
|
112
|
+
ctx.callerIdentity,
|
|
113
|
+
ApiResourceKind.agent_execution,
|
|
114
|
+
executions,
|
|
115
|
+
"",
|
|
116
|
+
),
|
|
117
|
+
failure: "failed to list agent executions",
|
|
158
118
|
});
|
|
159
|
-
ctx.set(EXECUTION_LIST_KEY,
|
|
119
|
+
ctx.set(EXECUTION_LIST_KEY, page);
|
|
160
120
|
},
|
|
161
121
|
};
|
|
162
122
|
}
|
|
@@ -176,9 +136,9 @@ export function newValidateListBySessionRequestStep(): PipelineStep<ListBySessio
|
|
|
176
136
|
}
|
|
177
137
|
|
|
178
138
|
/**
|
|
179
|
-
* QueryExecutionsBySession — list_by_session.go:
|
|
180
|
-
*
|
|
181
|
-
*
|
|
139
|
+
* QueryExecutionsBySession — list_by_session.go: the session's executions
|
|
140
|
+
* through the index's session key, whole and newest first, then the read
|
|
141
|
+
* scope (census lane 5; bounded by the session id, org never consulted).
|
|
182
142
|
*/
|
|
183
143
|
export function newQueryExecutionsBySessionStep(
|
|
184
144
|
store: Store,
|
|
@@ -188,31 +148,41 @@ export function newQueryExecutionsBySessionStep(
|
|
|
188
148
|
return {
|
|
189
149
|
name: "QueryExecutionsBySession",
|
|
190
150
|
async execute(ctx) {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
)
|
|
151
|
+
let rows: ListIndexRow[];
|
|
152
|
+
try {
|
|
153
|
+
rows = await store.queryResources(agentExecutionListIndex, {
|
|
154
|
+
anyKey: [{ name: "session", value: ctx.input.sessionId }],
|
|
155
|
+
});
|
|
156
|
+
} catch (error) {
|
|
157
|
+
throw internalError(error, "failed to list agent executions");
|
|
158
|
+
}
|
|
197
159
|
const executions = await restrictListByReadScope(
|
|
198
160
|
listReadScope,
|
|
199
161
|
ctx.callerIdentity,
|
|
200
162
|
ApiResourceKind.agent_execution,
|
|
201
|
-
|
|
163
|
+
decodeExecutions(
|
|
164
|
+
rows.map((row) => row.data),
|
|
165
|
+
logger,
|
|
166
|
+
),
|
|
202
167
|
"",
|
|
203
168
|
);
|
|
204
169
|
logger.debug("Successfully queried executions by session", {
|
|
205
170
|
sessionId: ctx.input.sessionId,
|
|
206
171
|
count: executions.length,
|
|
207
172
|
});
|
|
208
|
-
|
|
173
|
+
const page: ListPage<AgentExecution> = {
|
|
174
|
+
entries: executions,
|
|
175
|
+
nextPageToken: "",
|
|
176
|
+
};
|
|
177
|
+
ctx.set(EXECUTION_LIST_KEY, page);
|
|
209
178
|
},
|
|
210
179
|
};
|
|
211
180
|
}
|
|
212
181
|
|
|
213
182
|
/**
|
|
214
|
-
* BuildExecutionListResponse — both list files: wraps the
|
|
215
|
-
*
|
|
183
|
+
* BuildExecutionListResponse — both list files: wraps the page into
|
|
184
|
+
* AgentExecutionList; total_pages is 1 when the response is whole and 0
|
|
185
|
+
* when a token follows (the contract's "not computed").
|
|
216
186
|
*/
|
|
217
187
|
export function newBuildExecutionListResponseStep<
|
|
218
188
|
Desc extends ListDesc | ListBySessionDesc,
|
|
@@ -220,24 +190,57 @@ export function newBuildExecutionListResponseStep<
|
|
|
220
190
|
return {
|
|
221
191
|
name: "BuildExecutionListResponse",
|
|
222
192
|
execute(ctx) {
|
|
223
|
-
const
|
|
193
|
+
const page = requirePage(ctx.get(EXECUTION_LIST_KEY));
|
|
224
194
|
ctx.set(
|
|
225
195
|
EXECUTION_LIST_KEY,
|
|
226
196
|
create(AgentExecutionListSchema, {
|
|
227
|
-
totalPages: 1,
|
|
228
|
-
entries:
|
|
197
|
+
totalPages: page.nextPageToken === "" ? 1 : 0,
|
|
198
|
+
entries: page.entries,
|
|
199
|
+
nextPageToken: page.nextPageToken,
|
|
229
200
|
}),
|
|
230
201
|
);
|
|
231
202
|
},
|
|
232
203
|
};
|
|
233
204
|
}
|
|
234
205
|
|
|
235
|
-
function
|
|
236
|
-
|
|
206
|
+
function decodeExecution(
|
|
207
|
+
data: Uint8Array,
|
|
208
|
+
logger: Logger,
|
|
209
|
+
): AgentExecution | undefined {
|
|
210
|
+
try {
|
|
211
|
+
return fromBinary(AgentExecutionSchema, data);
|
|
212
|
+
} catch (error) {
|
|
213
|
+
logger.warn("Failed to unmarshal execution, skipping", {
|
|
214
|
+
error: error instanceof Error ? error.message : String(error),
|
|
215
|
+
});
|
|
216
|
+
return undefined;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function decodeExecutions(
|
|
221
|
+
rows: ReadonlyArray<Uint8Array>,
|
|
222
|
+
logger: Logger,
|
|
223
|
+
): AgentExecution[] {
|
|
224
|
+
const executions: AgentExecution[] = [];
|
|
225
|
+
for (const data of rows) {
|
|
226
|
+
const execution = decodeExecution(data, logger);
|
|
227
|
+
if (execution !== undefined) {
|
|
228
|
+
executions.push(execution);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return executions;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function requirePage(value: unknown): ListPage<AgentExecution> {
|
|
235
|
+
if (
|
|
236
|
+
typeof value !== "object" ||
|
|
237
|
+
value === null ||
|
|
238
|
+
!Array.isArray((value as { entries?: unknown }).entries)
|
|
239
|
+
) {
|
|
237
240
|
throw internalError(
|
|
238
241
|
new Error("execution list not found in context"),
|
|
239
242
|
"execution list not found in context",
|
|
240
243
|
);
|
|
241
244
|
}
|
|
242
|
-
return value as AgentExecution
|
|
245
|
+
return value as ListPage<AgentExecution>;
|
|
243
246
|
}
|
|
@@ -67,6 +67,7 @@ import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/
|
|
|
67
67
|
import type { Logger } from "../../boot/logger.js";
|
|
68
68
|
import type { Authorizer } from "../../extensions/authorizer.js";
|
|
69
69
|
import type { ListReadScope } from "../../extensions/list-read-scope.js";
|
|
70
|
+
import { restrictListByReadScope } from "../../extensions/list-read-scope.js";
|
|
70
71
|
import { internalError, invalidArgumentError } from "../../pipeline/errors.js";
|
|
71
72
|
import type { PipelineStep } from "../../pipeline/pipeline.js";
|
|
72
73
|
import { newPipeline } from "../../pipeline/pipeline.js";
|
|
@@ -74,8 +75,11 @@ import type { CallerIdentity } from "../../extensions/identity.js";
|
|
|
74
75
|
import { RequestContext } from "../../pipeline/request-context.js";
|
|
75
76
|
import { newAuthorizeStep } from "../../pipeline/steps/authorize.js";
|
|
76
77
|
import type { Store } from "../../store/interface.js";
|
|
78
|
+
import { listIndexInstantOfMillis } from "../../store/list-index.js";
|
|
79
|
+
import type { ListIndexRow } from "../../store/list-index.js";
|
|
77
80
|
|
|
78
81
|
import { executionUsageReportNotFoundMessage } from "./constants.js";
|
|
82
|
+
import { agentExecutionListIndex } from "./list-index.js";
|
|
79
83
|
import { EXECUTION_LIST_KEY, loadAllAgentExecutions } from "./steps.js";
|
|
80
84
|
|
|
81
85
|
export interface UsageReportDeps {
|
|
@@ -781,13 +785,11 @@ function requireReport<T>(value: unknown, message: string): T {
|
|
|
781
785
|
// absent from this shape (AD-DASH-005: the dashboard sources cost from
|
|
782
786
|
// getOrgUsageReport to prevent double-counting).
|
|
783
787
|
//
|
|
784
|
-
//
|
|
785
|
-
//
|
|
786
|
-
//
|
|
787
|
-
//
|
|
788
|
-
//
|
|
789
|
-
// header (workflowexecution/get-execution-summary.ts) for the full
|
|
790
|
-
// rationale. No scope composed = this full scan, byte-identical.
|
|
788
|
+
// The rows are the requested org's within the time window, read through
|
|
789
|
+
// the list index; with a composed ListReadScope they are offered to its
|
|
790
|
+
// restrict verb, and none visible answers the default instance — the Java
|
|
791
|
+
// AgentExecutionGetExecutionSummaryHandler baseline; see the twin's header
|
|
792
|
+
// (workflowexecution/get-execution-summary.ts) for the full rationale.
|
|
791
793
|
// ---------------------------------------------------------------------------
|
|
792
794
|
|
|
793
795
|
export async function getExecutionSummary(
|
|
@@ -795,25 +797,44 @@ export async function getExecutionSummary(
|
|
|
795
797
|
req: GetAgentExecutionSummaryRequest,
|
|
796
798
|
identity: CallerIdentity,
|
|
797
799
|
): Promise<AgentExecutionSummary> {
|
|
798
|
-
|
|
800
|
+
// The store's window is one millisecond wider than the loop's check
|
|
801
|
+
// below, which stays the authority: it only ever narrows the read.
|
|
802
|
+
const cutoffMs = resolveAgentTimeCutoffMs(req.timeWindow);
|
|
803
|
+
let rows: ListIndexRow[];
|
|
804
|
+
try {
|
|
805
|
+
rows = await deps.store.queryResources(agentExecutionListIndex, {
|
|
806
|
+
org: req.org,
|
|
807
|
+
...(cutoffMs === undefined
|
|
808
|
+
? {}
|
|
809
|
+
: { createdAtOrAfter: listIndexInstantOfMillis(cutoffMs - 1) }),
|
|
810
|
+
});
|
|
811
|
+
} catch (error) {
|
|
812
|
+
throw internalError(error, "failed to list agent executions");
|
|
813
|
+
}
|
|
814
|
+
let executions: AgentExecution[] = [];
|
|
815
|
+
for (const row of rows) {
|
|
816
|
+
try {
|
|
817
|
+
executions.push(fromBinary(AgentExecutionSchema, row.data));
|
|
818
|
+
} catch (error) {
|
|
819
|
+
deps.logger.warn("Failed to unmarshal execution, skipping", {
|
|
820
|
+
error: error instanceof Error ? error.message : String(error),
|
|
821
|
+
});
|
|
822
|
+
}
|
|
823
|
+
}
|
|
799
824
|
|
|
800
825
|
if (deps.listReadScope !== undefined) {
|
|
801
|
-
|
|
826
|
+
executions = await restrictListByReadScope(
|
|
827
|
+
deps.listReadScope,
|
|
802
828
|
identity,
|
|
803
829
|
ApiResourceKind.agent_execution,
|
|
830
|
+
executions,
|
|
831
|
+
"",
|
|
804
832
|
);
|
|
805
|
-
if (
|
|
833
|
+
if (executions.length === 0) {
|
|
806
834
|
return create(AgentExecutionSummarySchema);
|
|
807
835
|
}
|
|
808
|
-
executions = executions.filter(
|
|
809
|
-
(execution) =>
|
|
810
|
-
authorizedIds.has(execution.metadata?.id ?? "") &&
|
|
811
|
-
execution.metadata?.org === req.org,
|
|
812
|
-
);
|
|
813
836
|
}
|
|
814
837
|
|
|
815
|
-
const cutoffMs = resolveAgentTimeCutoffMs(req.timeWindow);
|
|
816
|
-
|
|
817
838
|
const phaseCounts: { [key: number]: number } = {};
|
|
818
839
|
let activeCount = 0;
|
|
819
840
|
const completedDurationsMs: number[] = [];
|