@agent-native/dispatch 0.40.36 → 0.40.37
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/CHANGELOG.md +12 -6
- package/dist/actions/provider-api-register.d.ts +11 -11
- package/dist/routes/pages/overview.d.ts +2 -2
- package/dist/server/lib/community-apps.js +1 -1
- package/dist/server/lib/community-apps.js.map +1 -1
- package/dist/server/lib/usage-metrics-store.js +2 -2
- package/dist/server/lib/usage-metrics-store.js.map +1 -1
- package/package.json +3 -3
- package/src/server/lib/community-apps.ts +1 -1
- package/src/server/lib/usage-metrics-store.spec.ts +6 -2
- package/src/server/lib/usage-metrics-store.ts +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @agent-native/dispatch
|
|
2
2
|
|
|
3
|
+
## 0.40.37
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- b07c13b: `describe-workspace-apps` now shows each app's authored "when to use" guidance, so the agent sees the same text the ranking matched on. Workspace usage tools now say plainly that they have no customer data and point to the app's own customer or billing actions or the owning app, instead of leading with the owner/admin permission rule.
|
|
8
|
+
- Release all public npm packages with a patch version bump.
|
|
9
|
+
- Updated dependencies [6c3f3cb]
|
|
10
|
+
- Updated dependencies [4c43f86]
|
|
11
|
+
- Updated dependencies
|
|
12
|
+
- Updated dependencies [9e4119f]
|
|
13
|
+
- @agent-native/toolkit@0.217.0
|
|
14
|
+
|
|
3
15
|
## 0.40.36
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
|
@@ -1323,10 +1335,4 @@
|
|
|
1323
1335
|
- Updated dependencies [a2f21dc]
|
|
1324
1336
|
- @agent-native/toolkit@0.16.6
|
|
1325
1337
|
|
|
1326
|
-
## 0.30.0
|
|
1327
|
-
|
|
1328
|
-
### Minor Changes
|
|
1329
|
-
|
|
1330
|
-
- a688849: Add organization groups and privacy controls for workspace apps. New apps use the organization default (organization-wide by default), while creators and organization admins can manage individual, group, and organization access from the shared popover.
|
|
1331
|
-
|
|
1332
1338
|
For the full list of releases, see the [changelog archive](./changelog/archive/CHANGELOG.md).
|
|
@@ -47,10 +47,10 @@ declare const _default: import("node_modules/@agent-native/core/dist").ActionDef
|
|
|
47
47
|
notes?: string | undefined;
|
|
48
48
|
scope?: "org" | "user" | undefined;
|
|
49
49
|
}, {
|
|
50
|
+
message?: undefined;
|
|
50
51
|
id?: undefined;
|
|
51
|
-
deleted?: undefined;
|
|
52
52
|
provider?: undefined;
|
|
53
|
-
|
|
53
|
+
deleted?: undefined;
|
|
54
54
|
providers: {
|
|
55
55
|
id: string;
|
|
56
56
|
label: string;
|
|
@@ -61,45 +61,45 @@ declare const _default: import("node_modules/@agent-native/core/dist").ActionDef
|
|
|
61
61
|
updatedAt: number;
|
|
62
62
|
}[];
|
|
63
63
|
count: number;
|
|
64
|
+
found?: undefined;
|
|
64
65
|
registered?: undefined;
|
|
65
66
|
label?: undefined;
|
|
66
|
-
message?: undefined;
|
|
67
67
|
} | {
|
|
68
|
+
message?: undefined;
|
|
68
69
|
id?: undefined;
|
|
69
|
-
deleted?: undefined;
|
|
70
70
|
count?: undefined;
|
|
71
|
+
deleted?: undefined;
|
|
71
72
|
providers?: undefined;
|
|
72
73
|
found: boolean;
|
|
73
74
|
provider: import("node_modules/@agent-native/core/dist/provider-api").CustomProviderConfig;
|
|
74
75
|
registered?: undefined;
|
|
75
76
|
label?: undefined;
|
|
76
|
-
message?: undefined;
|
|
77
77
|
} | {
|
|
78
|
-
|
|
78
|
+
message?: undefined;
|
|
79
79
|
provider?: undefined;
|
|
80
80
|
count?: undefined;
|
|
81
|
+
deleted?: undefined;
|
|
81
82
|
providers?: undefined;
|
|
82
83
|
found: boolean;
|
|
83
84
|
id: string;
|
|
84
85
|
registered?: undefined;
|
|
85
86
|
label?: undefined;
|
|
86
|
-
message?: undefined;
|
|
87
87
|
} | {
|
|
88
|
+
message?: undefined;
|
|
88
89
|
provider?: undefined;
|
|
89
90
|
count?: undefined;
|
|
90
|
-
found?: undefined;
|
|
91
91
|
providers?: undefined;
|
|
92
|
+
found?: undefined;
|
|
92
93
|
deleted: boolean;
|
|
93
94
|
id: string;
|
|
94
95
|
registered?: undefined;
|
|
95
96
|
label?: undefined;
|
|
96
|
-
message?: undefined;
|
|
97
97
|
} | {
|
|
98
|
-
deleted?: undefined;
|
|
99
98
|
provider?: undefined;
|
|
100
99
|
count?: undefined;
|
|
101
|
-
|
|
100
|
+
deleted?: undefined;
|
|
102
101
|
providers?: undefined;
|
|
102
|
+
found?: undefined;
|
|
103
103
|
registered: boolean;
|
|
104
104
|
id: string;
|
|
105
105
|
label: string;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
export declare function meta(): ({
|
|
2
|
-
title: string;
|
|
3
2
|
name?: undefined;
|
|
4
3
|
property?: undefined;
|
|
5
4
|
content?: undefined;
|
|
5
|
+
title: string;
|
|
6
6
|
} | {
|
|
7
7
|
title?: undefined;
|
|
8
|
+
property?: undefined;
|
|
8
9
|
name: string;
|
|
9
10
|
content: string;
|
|
10
|
-
property?: undefined;
|
|
11
11
|
} | {
|
|
12
12
|
title?: undefined;
|
|
13
13
|
name?: undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"community-apps.js","sourceRoot":"","sources":["../../../src/server/lib/community-apps.ts"],"names":[],"mappings":"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","sourcesContent":["import { fail } from \"@agent-native/core/action\";\nimport { getUserLabEnabled } from \"@agent-native/core/labs/server\";\nimport {\n getWorkspaceAppIdValidationError,\n normalizeWorkspaceAppId,\n} from \"@agent-native/core/shared\";\nimport {\n BUILTIN_AGENT_CATALOG_IDS,\n HIDDEN_FIRST_PARTY_AGENT_IDS,\n} from \"@agent-native/core/shared/first-party-agents\";\n\nimport { COMMUNITY_APPS_LAB } from \"../../shared/labs.js\";\nimport type {\n StartWorkspaceAppCreationResult,\n WorkspaceAppSummary,\n} from \"./app-creation-store.js\";\nimport {\n getAppCreationSettings,\n getWorkspaceInfo,\n isLocalAppCreationRuntime,\n listWorkspaceApps,\n startWorkspaceAppCreation,\n} from \"./app-creation-store.js\";\nimport {\n loadPinnedCommunitySourceAttachments,\n type PinnedCommunitySource,\n} from \"./community-source.js\";\nimport { CURATED_WORKSPACE_TEMPLATES } from \"./curated-workspace-templates.js\";\nimport {\n currentOrgId,\n currentOwnerEmail,\n recordAudit,\n} from \"./dispatch-store.js\";\n\nexport interface CuratedCommunityAppSource extends PinnedCommunitySource {\n id: string;\n name: string;\n description: string;\n appId: string;\n license: string;\n provenance: string;\n}\n\nexport interface CuratedCommunityApp extends CuratedCommunityAppSource {\n installed: boolean;\n pending: boolean;\n installable: boolean;\n installUnavailableReason?:\n | \"workspace-required\"\n | \"app-id-conflict\"\n | \"builder-install-unverified\";\n}\n\nexport const CURATED_COMMUNITY_APP_SOURCES: readonly CuratedCommunityAppSource[] =\n [\n {\n id: \"community-qr\",\n name: \"QR\",\n description: \"Generate public PNG or SVG QR images from links or text.\",\n appId: \"community-qr\",\n repo: \"BuilderIO/agent-native\",\n ref: \"main\",\n license: \"MIT\",\n provenance:\n \"Reviewed Agent-Native Framework template, sanitized for independent installation.\",\n templatePath: \"templates/community/qr\",\n files: [\n {\n path: \"AGENTS.md\",\n blobSha: \"7dc9e18bc426dfd21526f91225cc615759450816\",\n },\n {\n path: \"LICENSE\",\n blobSha: \"69c7182efb3eb1a8b7f6fd5989f3e4fd737d0645\",\n },\n {\n path: \"README.md\",\n blobSha: \"e05e72bb9213732f56ccbc96f7dcb1c3a064cb19\",\n },\n {\n path: \"actions/generate-qr-code.spec.ts\",\n blobSha: \"3459217b7252c6ee0076c68cfdb83001cc74f29e\",\n },\n {\n path: \"actions/generate-qr-code.ts\",\n blobSha: \"98d30e218bfed796d5e402d5ce19a8626d8da0cf\",\n },\n {\n path: \"actions/run.ts\",\n blobSha: \"b46ab15b667c34741364ba08f010f7aca9d0f02e\",\n },\n {\n path: \"agent-native.json\",\n blobSha: \"accc32476792b84557f69e2b48b317c27b5546dc\",\n },\n {\n path: \"package.json\",\n blobSha: \"da9e7b9eb37664a191dfde80406c7d5b350bfe0b\",\n },\n {\n path: \"server/db/index.ts\",\n blobSha: \"17007b456530f75a72e7209bdfe9f4bd4c9224e0\",\n },\n {\n path: \"server/db/schema.ts\",\n blobSha: \"2e4cd01c5f46463e78bc7beb6e954f3e526c0b57\",\n },\n {\n path: \"server/plugins/db.ts\",\n blobSha: \"78a5b431c1ad1ea14f593123c090f5376a36df10\",\n },\n {\n path: \"tsconfig.json\",\n blobSha: \"5267473a32dcab8e5dc2c9d9a720afed7f40174c\",\n },\n ],\n },\n ];\n\nconst communitySourceById = new Map(\n CURATED_COMMUNITY_APP_SOURCES.map((source) => [source.id, source]),\n);\n\nfunction requireCommunitySource(sourceId: string): CuratedCommunityAppSource {\n const source = communitySourceById.get(sourceId.trim());\n if (!source) {\n fail(\"That community app is not in Dispatch's reviewed install catalog.\", {\n errorCode: \"unknown_community_app_source\",\n statusCode: 404,\n });\n }\n return source;\n}\n\nfunction communitySourceFailureKind(\n error: unknown,\n): \"unavailable\" | \"integrity\" {\n if (!(error instanceof Error) || !(\"failureKind\" in error)) {\n return \"unavailable\";\n }\n return error.failureKind === \"integrity\" ? \"integrity\" : \"unavailable\";\n}\n\nfunction requireNonShadowingCommunityAppId(appId: string): void {\n const error = getWorkspaceAppIdValidationError(appId);\n if (error) {\n fail(error, { errorCode: \"invalid_community_app_id\", statusCode: 400 });\n }\n if (\n CURATED_WORKSPACE_TEMPLATES.some((template) => template.id === appId) ||\n BUILTIN_AGENT_CATALOG_IDS.includes(appId) ||\n HIDDEN_FIRST_PARTY_AGENT_IDS.has(appId)\n ) {\n fail(\"Community apps cannot use a first-party template app id.\", {\n errorCode: \"community_app_id_shadows_first_party\",\n statusCode: 409,\n });\n }\n}\n\nasync function requireCommunityAppsLab(): Promise<void> {\n const userEmail = currentOwnerEmail().trim();\n const orgId = currentOrgId();\n if (!userEmail || !orgId) {\n fail(\"Sign in to an organization to browse community apps.\", {\n errorCode: \"community_apps_identity_required\",\n statusCode: 403,\n });\n }\n const enabled = await getUserLabEnabled(userEmail, COMMUNITY_APPS_LAB, {\n orgId,\n });\n if (!enabled) {\n fail(\"Community app catalog and installs are disabled for this account.\", {\n errorCode: \"community_apps_lab_disabled\",\n statusCode: 403,\n });\n }\n}\n\nasync function hasAssociatedWorkspace(\n localRuntime = isLocalAppCreationRuntime(),\n): Promise<boolean> {\n if (localRuntime) return Boolean(getWorkspaceInfo().rootPath);\n return Boolean((await getAppCreationSettings()).builderProjectId);\n}\n\nexport async function listCuratedCommunityApps(): Promise<\n CuratedCommunityApp[]\n> {\n await requireCommunityAppsLab();\n const localRuntime = isLocalAppCreationRuntime();\n const [apps, workspaceAvailable] = await Promise.all([\n listWorkspaceApps({ includeAgentCards: false, includeArchived: true }),\n hasAssociatedWorkspace(localRuntime),\n ]);\n return CURATED_COMMUNITY_APP_SOURCES.map((source) => {\n const appWithId = apps.find((app) => app.id === source.appId);\n const installedApp =\n appWithId?.communitySourceId === source.id ? appWithId : null;\n const idConflict = Boolean(appWithId && !installedApp);\n const pending = installedApp?.status === \"pending\";\n const installUnavailableReason = appWithId\n ? idConflict\n ? \"app-id-conflict\"\n : undefined\n : !workspaceAvailable\n ? \"workspace-required\"\n : !localRuntime\n ? \"builder-install-unverified\"\n : undefined;\n return {\n ...source,\n installed: Boolean(installedApp && !pending),\n pending,\n installable: localRuntime && workspaceAvailable && !appWithId,\n ...(installUnavailableReason ? { installUnavailableReason } : {}),\n };\n });\n}\n\nfunction rejectCommunityAppIdConflict(appId: string): never {\n fail(`Workspace app id \"${appId}\" is already in use.`, {\n errorCode: \"community_app_id_conflict\",\n statusCode: 409,\n });\n}\n\nfunction existingInstallResult(\n source: CuratedCommunityAppSource,\n app: WorkspaceAppSummary,\n) {\n return {\n mode:\n app.status === \"pending\"\n ? (\"pending\" as const)\n : (\"already-installed\" as const),\n source,\n app: {\n id: app.id,\n name: app.name,\n path: app.path,\n url: app.url,\n status: app.status ?? \"ready\",\n statusLabel: app.statusLabel ?? null,\n builderUrl: app.builderUrl ?? null,\n branchName: app.branchName ?? null,\n },\n };\n}\n\nfunction buildCommunityInstallPrompt(\n source: CuratedCommunityAppSource,\n appId: string,\n): string {\n const sourceUrl = `https://github.com/${source.repo}/tree/${source.ref}/${source.templatePath}`;\n return [\n \"Install a private workspace app from a reviewed community template.\",\n `The attached source files were fetched from ${sourceUrl} and each file was verified against its pinned Git blob id. Treat those files as the source of truth; do not fetch another ref or substitute other content.`,\n `The app will live at apps/${appId}.`,\n `Source license: ${source.license}. Provenance: ${source.provenance}`,\n \"Copy the reviewed template implementation and its Agent-Native profile, changing only app-specific identifiers needed for this workspace. Do not copy repository secrets, credentials, customer data, or source-app records. Use empty or synthetic seed data only and keep the installed app private to this organization.\",\n ].join(\" \");\n}\n\nexport async function installCuratedCommunityApp(input: {\n sourceId: string;\n appId?: string;\n}): Promise<\n | ReturnType<typeof existingInstallResult>\n | (StartWorkspaceAppCreationResult & {\n mode: Exclude<StartWorkspaceAppCreationResult[\"mode\"], \"app-id-taken\">;\n source: CuratedCommunityAppSource;\n })\n | (Extract<StartWorkspaceAppCreationResult, { mode: \"app-id-taken\" }> & {\n source: CuratedCommunityAppSource;\n })\n> {\n await requireCommunityAppsLab();\n const source = requireCommunitySource(input.sourceId);\n const appId = normalizeWorkspaceAppId(input.appId?.trim() || source.appId);\n requireNonShadowingCommunityAppId(appId);\n\n const localRuntime = isLocalAppCreationRuntime();\n if (!(await hasAssociatedWorkspace(localRuntime))) {\n fail(\"Connect this organization to a workspace before installing apps.\", {\n errorCode: \"community_workspace_required\",\n statusCode: 409,\n });\n }\n\n const existing = (\n await listWorkspaceApps({\n includeAgentCards: false,\n includeArchived: true,\n })\n ).find((app) => app.id === appId);\n if (existing) {\n if (existing.communitySourceId === source.id) {\n return existingInstallResult(source, existing);\n }\n rejectCommunityAppIdConflict(appId);\n }\n\n if (!localRuntime) {\n fail(\n \"Community template installs in Builder workspaces are disabled until the generated branch files can be read back and verified.\",\n {\n errorCode: \"community_builder_install_unverified\",\n statusCode: 503,\n },\n );\n }\n\n let attachments: Awaited<\n ReturnType<typeof loadPinnedCommunitySourceAttachments>\n >;\n try {\n attachments = await loadPinnedCommunitySourceAttachments(source, appId);\n } catch (error) {\n fail(\n \"Dispatch could not verify the pinned community template source. Try again later.\",\n {\n errorCode:\n communitySourceFailureKind(error) === \"integrity\"\n ? \"community_source_integrity_failed\"\n : \"community_source_unavailable\",\n statusCode: 503,\n },\n );\n }\n\n const result = await startWorkspaceAppCreation({\n prompt: buildCommunityInstallPrompt(source, appId),\n appId,\n description: source.description,\n template: source.id,\n communitySourceId: source.id,\n attachments,\n });\n\n if (result.mode === \"app-id-taken\") {\n const raced = (\n await listWorkspaceApps({\n includeAgentCards: false,\n includeArchived: true,\n })\n ).find((app) => app.id === appId);\n if (raced?.communitySourceId === source.id) {\n return existingInstallResult(source, raced);\n }\n if (raced) rejectCommunityAppIdConflict(appId);\n return { ...result, source };\n }\n\n await recordAudit({\n action: \"workspace-app.community-install-requested\",\n targetType: \"workspace-app\",\n targetId: appId,\n summary: `Requested ${source.name} community app installation`,\n metadata: {\n sourceId: source.id,\n repo: source.repo,\n ref: source.ref,\n blobShas: source.files.map((file) => file.blobSha),\n license: source.license,\n },\n });\n return { ...result, source } as typeof result & {\n source: CuratedCommunityAppSource;\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"community-apps.js","sourceRoot":"","sources":["../../../src/server/lib/community-apps.ts"],"names":[],"mappings":"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","sourcesContent":["import { fail } from \"@agent-native/core/action\";\nimport { getUserLabEnabled } from \"@agent-native/core/labs/server\";\nimport {\n getWorkspaceAppIdValidationError,\n normalizeWorkspaceAppId,\n} from \"@agent-native/core/shared\";\nimport {\n BUILTIN_AGENT_CATALOG_IDS,\n HIDDEN_FIRST_PARTY_AGENT_IDS,\n} from \"@agent-native/core/shared/first-party-agents\";\n\nimport { COMMUNITY_APPS_LAB } from \"../../shared/labs.js\";\nimport type {\n StartWorkspaceAppCreationResult,\n WorkspaceAppSummary,\n} from \"./app-creation-store.js\";\nimport {\n getAppCreationSettings,\n getWorkspaceInfo,\n isLocalAppCreationRuntime,\n listWorkspaceApps,\n startWorkspaceAppCreation,\n} from \"./app-creation-store.js\";\nimport {\n loadPinnedCommunitySourceAttachments,\n type PinnedCommunitySource,\n} from \"./community-source.js\";\nimport { CURATED_WORKSPACE_TEMPLATES } from \"./curated-workspace-templates.js\";\nimport {\n currentOrgId,\n currentOwnerEmail,\n recordAudit,\n} from \"./dispatch-store.js\";\n\nexport interface CuratedCommunityAppSource extends PinnedCommunitySource {\n id: string;\n name: string;\n description: string;\n appId: string;\n license: string;\n provenance: string;\n}\n\nexport interface CuratedCommunityApp extends CuratedCommunityAppSource {\n installed: boolean;\n pending: boolean;\n installable: boolean;\n installUnavailableReason?:\n | \"workspace-required\"\n | \"app-id-conflict\"\n | \"builder-install-unverified\";\n}\n\nexport const CURATED_COMMUNITY_APP_SOURCES: readonly CuratedCommunityAppSource[] =\n [\n {\n id: \"community-qr\",\n name: \"QR\",\n description: \"Generate public PNG or SVG QR images from links or text.\",\n appId: \"community-qr\",\n repo: \"BuilderIO/agent-native\",\n ref: \"main\",\n license: \"MIT\",\n provenance:\n \"Reviewed Agent-Native Framework template, sanitized for independent installation.\",\n templatePath: \"templates/community/qr\",\n files: [\n {\n path: \"AGENTS.md\",\n blobSha: \"7dc9e18bc426dfd21526f91225cc615759450816\",\n },\n {\n path: \"LICENSE\",\n blobSha: \"69c7182efb3eb1a8b7f6fd5989f3e4fd737d0645\",\n },\n {\n path: \"README.md\",\n blobSha: \"e05e72bb9213732f56ccbc96f7dcb1c3a064cb19\",\n },\n {\n path: \"actions/generate-qr-code.spec.ts\",\n blobSha: \"3459217b7252c6ee0076c68cfdb83001cc74f29e\",\n },\n {\n path: \"actions/generate-qr-code.ts\",\n blobSha: \"98d30e218bfed796d5e402d5ce19a8626d8da0cf\",\n },\n {\n path: \"actions/run.ts\",\n blobSha: \"b46ab15b667c34741364ba08f010f7aca9d0f02e\",\n },\n {\n path: \"agent-native.json\",\n blobSha: \"accc32476792b84557f69e2b48b317c27b5546dc\",\n },\n {\n path: \"package.json\",\n blobSha: \"dbf733f4e0b751a91398233040e275ec32955a07\",\n },\n {\n path: \"server/db/index.ts\",\n blobSha: \"17007b456530f75a72e7209bdfe9f4bd4c9224e0\",\n },\n {\n path: \"server/db/schema.ts\",\n blobSha: \"2e4cd01c5f46463e78bc7beb6e954f3e526c0b57\",\n },\n {\n path: \"server/plugins/db.ts\",\n blobSha: \"78a5b431c1ad1ea14f593123c090f5376a36df10\",\n },\n {\n path: \"tsconfig.json\",\n blobSha: \"5267473a32dcab8e5dc2c9d9a720afed7f40174c\",\n },\n ],\n },\n ];\n\nconst communitySourceById = new Map(\n CURATED_COMMUNITY_APP_SOURCES.map((source) => [source.id, source]),\n);\n\nfunction requireCommunitySource(sourceId: string): CuratedCommunityAppSource {\n const source = communitySourceById.get(sourceId.trim());\n if (!source) {\n fail(\"That community app is not in Dispatch's reviewed install catalog.\", {\n errorCode: \"unknown_community_app_source\",\n statusCode: 404,\n });\n }\n return source;\n}\n\nfunction communitySourceFailureKind(\n error: unknown,\n): \"unavailable\" | \"integrity\" {\n if (!(error instanceof Error) || !(\"failureKind\" in error)) {\n return \"unavailable\";\n }\n return error.failureKind === \"integrity\" ? \"integrity\" : \"unavailable\";\n}\n\nfunction requireNonShadowingCommunityAppId(appId: string): void {\n const error = getWorkspaceAppIdValidationError(appId);\n if (error) {\n fail(error, { errorCode: \"invalid_community_app_id\", statusCode: 400 });\n }\n if (\n CURATED_WORKSPACE_TEMPLATES.some((template) => template.id === appId) ||\n BUILTIN_AGENT_CATALOG_IDS.includes(appId) ||\n HIDDEN_FIRST_PARTY_AGENT_IDS.has(appId)\n ) {\n fail(\"Community apps cannot use a first-party template app id.\", {\n errorCode: \"community_app_id_shadows_first_party\",\n statusCode: 409,\n });\n }\n}\n\nasync function requireCommunityAppsLab(): Promise<void> {\n const userEmail = currentOwnerEmail().trim();\n const orgId = currentOrgId();\n if (!userEmail || !orgId) {\n fail(\"Sign in to an organization to browse community apps.\", {\n errorCode: \"community_apps_identity_required\",\n statusCode: 403,\n });\n }\n const enabled = await getUserLabEnabled(userEmail, COMMUNITY_APPS_LAB, {\n orgId,\n });\n if (!enabled) {\n fail(\"Community app catalog and installs are disabled for this account.\", {\n errorCode: \"community_apps_lab_disabled\",\n statusCode: 403,\n });\n }\n}\n\nasync function hasAssociatedWorkspace(\n localRuntime = isLocalAppCreationRuntime(),\n): Promise<boolean> {\n if (localRuntime) return Boolean(getWorkspaceInfo().rootPath);\n return Boolean((await getAppCreationSettings()).builderProjectId);\n}\n\nexport async function listCuratedCommunityApps(): Promise<\n CuratedCommunityApp[]\n> {\n await requireCommunityAppsLab();\n const localRuntime = isLocalAppCreationRuntime();\n const [apps, workspaceAvailable] = await Promise.all([\n listWorkspaceApps({ includeAgentCards: false, includeArchived: true }),\n hasAssociatedWorkspace(localRuntime),\n ]);\n return CURATED_COMMUNITY_APP_SOURCES.map((source) => {\n const appWithId = apps.find((app) => app.id === source.appId);\n const installedApp =\n appWithId?.communitySourceId === source.id ? appWithId : null;\n const idConflict = Boolean(appWithId && !installedApp);\n const pending = installedApp?.status === \"pending\";\n const installUnavailableReason = appWithId\n ? idConflict\n ? \"app-id-conflict\"\n : undefined\n : !workspaceAvailable\n ? \"workspace-required\"\n : !localRuntime\n ? \"builder-install-unverified\"\n : undefined;\n return {\n ...source,\n installed: Boolean(installedApp && !pending),\n pending,\n installable: localRuntime && workspaceAvailable && !appWithId,\n ...(installUnavailableReason ? { installUnavailableReason } : {}),\n };\n });\n}\n\nfunction rejectCommunityAppIdConflict(appId: string): never {\n fail(`Workspace app id \"${appId}\" is already in use.`, {\n errorCode: \"community_app_id_conflict\",\n statusCode: 409,\n });\n}\n\nfunction existingInstallResult(\n source: CuratedCommunityAppSource,\n app: WorkspaceAppSummary,\n) {\n return {\n mode:\n app.status === \"pending\"\n ? (\"pending\" as const)\n : (\"already-installed\" as const),\n source,\n app: {\n id: app.id,\n name: app.name,\n path: app.path,\n url: app.url,\n status: app.status ?? \"ready\",\n statusLabel: app.statusLabel ?? null,\n builderUrl: app.builderUrl ?? null,\n branchName: app.branchName ?? null,\n },\n };\n}\n\nfunction buildCommunityInstallPrompt(\n source: CuratedCommunityAppSource,\n appId: string,\n): string {\n const sourceUrl = `https://github.com/${source.repo}/tree/${source.ref}/${source.templatePath}`;\n return [\n \"Install a private workspace app from a reviewed community template.\",\n `The attached source files were fetched from ${sourceUrl} and each file was verified against its pinned Git blob id. Treat those files as the source of truth; do not fetch another ref or substitute other content.`,\n `The app will live at apps/${appId}.`,\n `Source license: ${source.license}. Provenance: ${source.provenance}`,\n \"Copy the reviewed template implementation and its Agent-Native profile, changing only app-specific identifiers needed for this workspace. Do not copy repository secrets, credentials, customer data, or source-app records. Use empty or synthetic seed data only and keep the installed app private to this organization.\",\n ].join(\" \");\n}\n\nexport async function installCuratedCommunityApp(input: {\n sourceId: string;\n appId?: string;\n}): Promise<\n | ReturnType<typeof existingInstallResult>\n | (StartWorkspaceAppCreationResult & {\n mode: Exclude<StartWorkspaceAppCreationResult[\"mode\"], \"app-id-taken\">;\n source: CuratedCommunityAppSource;\n })\n | (Extract<StartWorkspaceAppCreationResult, { mode: \"app-id-taken\" }> & {\n source: CuratedCommunityAppSource;\n })\n> {\n await requireCommunityAppsLab();\n const source = requireCommunitySource(input.sourceId);\n const appId = normalizeWorkspaceAppId(input.appId?.trim() || source.appId);\n requireNonShadowingCommunityAppId(appId);\n\n const localRuntime = isLocalAppCreationRuntime();\n if (!(await hasAssociatedWorkspace(localRuntime))) {\n fail(\"Connect this organization to a workspace before installing apps.\", {\n errorCode: \"community_workspace_required\",\n statusCode: 409,\n });\n }\n\n const existing = (\n await listWorkspaceApps({\n includeAgentCards: false,\n includeArchived: true,\n })\n ).find((app) => app.id === appId);\n if (existing) {\n if (existing.communitySourceId === source.id) {\n return existingInstallResult(source, existing);\n }\n rejectCommunityAppIdConflict(appId);\n }\n\n if (!localRuntime) {\n fail(\n \"Community template installs in Builder workspaces are disabled until the generated branch files can be read back and verified.\",\n {\n errorCode: \"community_builder_install_unverified\",\n statusCode: 503,\n },\n );\n }\n\n let attachments: Awaited<\n ReturnType<typeof loadPinnedCommunitySourceAttachments>\n >;\n try {\n attachments = await loadPinnedCommunitySourceAttachments(source, appId);\n } catch (error) {\n fail(\n \"Dispatch could not verify the pinned community template source. Try again later.\",\n {\n errorCode:\n communitySourceFailureKind(error) === \"integrity\"\n ? \"community_source_integrity_failed\"\n : \"community_source_unavailable\",\n statusCode: 503,\n },\n );\n }\n\n const result = await startWorkspaceAppCreation({\n prompt: buildCommunityInstallPrompt(source, appId),\n appId,\n description: source.description,\n template: source.id,\n communitySourceId: source.id,\n attachments,\n });\n\n if (result.mode === \"app-id-taken\") {\n const raced = (\n await listWorkspaceApps({\n includeAgentCards: false,\n includeArchived: true,\n })\n ).find((app) => app.id === appId);\n if (raced?.communitySourceId === source.id) {\n return existingInstallResult(source, raced);\n }\n if (raced) rejectCommunityAppIdConflict(appId);\n return { ...result, source };\n }\n\n await recordAudit({\n action: \"workspace-app.community-install-requested\",\n targetType: \"workspace-app\",\n targetId: appId,\n summary: `Requested ${source.name} community app installation`,\n metadata: {\n sourceId: source.id,\n repo: source.repo,\n ref: source.ref,\n blobShas: source.files.map((file) => file.blobSha),\n license: source.license,\n },\n });\n return { ...result, source } as typeof result & {\n source: CuratedCommunityAppSource;\n };\n}\n"]}
|
|
@@ -587,7 +587,7 @@ async function assertCanViewMetrics(viewScope) {
|
|
|
587
587
|
throw new ForbiddenError("Only organization owners and admins can view workspace usage metrics.");
|
|
588
588
|
}
|
|
589
589
|
function failUserNotOrgMember(email) {
|
|
590
|
-
fail(`${email} is not a member of this organization
|
|
590
|
+
fail(`${email} is not a member of this organization, so list-dispatch-usage-metrics has no data on them. For a customer's or account's usage or credits, use this app's own customer or billing actions if it has any, or find the app that owns that data with describe-workspace-apps query="<what you need>" and delegate with call-agent.`, { errorCode: "usage_user_not_org_member", statusCode: 404 });
|
|
591
591
|
}
|
|
592
592
|
export async function listDispatchUsageMetrics(input) {
|
|
593
593
|
const viewScope = input.scope === "me" ? "me" : input.scope === "app" ? "app" : "workspace";
|
|
@@ -604,7 +604,7 @@ export async function listDispatchUsageMetrics(input) {
|
|
|
604
604
|
if (!isDispatchEnvironmentAdmin(callerEmail) &&
|
|
605
605
|
callerRole !== "owner" &&
|
|
606
606
|
callerRole !== "admin") {
|
|
607
|
-
fail(
|
|
607
|
+
fail(`list-dispatch-usage-metrics cannot answer this. For a teammate in this organization, only owners and admins can look up their usage. For a customer or other external user, list-dispatch-usage-metrics has no data: use this app's own customer or billing actions if it has any, or find the app that owns that data with describe-workspace-apps query="<what you need>" and delegate with call-agent.`, { errorCode: "usage_user_lookup_forbidden", statusCode: 403 });
|
|
608
608
|
}
|
|
609
609
|
if (!(await isOrgMember(callerOrgId, requestedEmail))) {
|
|
610
610
|
failUserNotOrgMember(requestedEmail);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usage-metrics-store.js","sourceRoot":"","sources":["../../../src/server/lib/usage-metrics-store.ts"],"names":[],"mappings":"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","sourcesContent":["import { fail } from \"@agent-native/core/action\";\nimport {\n detectEngineFromEnv,\n detectEngineFromUserSecrets,\n getAgentEngineEntry,\n isAgentEngineSettingConfigured,\n isStoredEngineUsable,\n readDefaultAgentEngineSetting,\n registerBuiltinEngines,\n} from \"@agent-native/core/agent/engine\";\nimport { getDbExec } from \"@agent-native/core/db\";\nimport { isOrgMember } from \"@agent-native/core/org\";\nimport { readOrgMemberRole } from \"@agent-native/core/server\";\nimport { ForbiddenError } from \"@agent-native/core/sharing\";\nimport {\n builderCreditsFromCostCents,\n getUsageSummary,\n isSelfScopedUsageRead,\n MIXED_USAGE_BILLING,\n UNKNOWN_USAGE_BILLING,\n usageBillingForEngine,\n usageOrgScope,\n type UsageBillingMode,\n} from \"@agent-native/core/usage\";\n\nimport { isDispatchEnvironmentAdmin } from \"./admin-config.js\";\nimport {\n listWorkspaceApps,\n type WorkspaceAppSummary,\n} from \"./app-creation-store.js\";\nimport { currentOrgId, currentOwnerEmail } from \"./dispatch-store.js\";\n\nconst DAY_MS = 86_400_000;\n\nregisterBuiltinEngines();\n\nexport interface UsageMetricBucket {\n key: string;\n label: string;\n costCents: number;\n calls: number;\n chatCalls: number;\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n activeUsers: number;\n lastActiveAt: number | null;\n}\n\nexport interface UserUsageMetric extends UsageMetricBucket {\n ownerEmail: string;\n chatThreads: number;\n chatMessages: number;\n lastChatAt: number | null;\n topApp: string | null;\n role: string | null;\n}\n\nexport interface AppAdoptionActionMetric {\n key: string;\n label: string;\n calls: number;\n activeUsers: number;\n lastActiveAt: number | null;\n}\n\nexport interface AppAccessMetric {\n id: string;\n name: string;\n path: string;\n status: WorkspaceAppSummary[\"status\"];\n statusLabel?: string;\n isDispatch: boolean;\n accessModel: \"workspace\" | \"solo\";\n accessLabel: string;\n accessUsers: number;\n ownerEmail: string | null;\n isOwnedByViewer: boolean;\n canViewUsage: boolean;\n usersWithUsage: number;\n dailyActiveUsers: number;\n weeklyActiveUsers: number;\n usageCalls: number;\n chatCalls: number;\n costCents: number;\n lastActiveAt: number | null;\n actionMetrics: AppAdoptionActionMetric[];\n}\n\nexport interface DailyUsageMetric {\n date: string;\n costCents: number;\n calls: number;\n chatCalls: number;\n activeUsers: number;\n dailyActiveUsers: number;\n weeklyActiveUsers: number | null;\n}\n\nexport interface MonthlyUserUsageMetric {\n month: string;\n ownerEmail: string;\n costCents: number;\n credits: number | null;\n calls: number;\n chatCalls: number;\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n}\n\ntype MonthlyUsageAggregate = Omit<MonthlyUserUsageMetric, \"credits\"> & {\n builderCredits: number;\n builderEstimatedCostX100: number;\n unclassifiedCalls: number;\n unpricedBuilderCalls: number;\n};\n\nexport interface WorkspaceAppCreationMetric {\n month: string;\n ownerEmail: string;\n count: number;\n appIds: string[];\n}\n\nexport interface RecentUsageMetric {\n id: number;\n createdAt: number;\n ownerEmail: string;\n app: string;\n label: string;\n model: string;\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n costCents: number;\n prompt: string | null;\n promptSource: \"thread\" | \"thread-preview\" | \"not-captured\" | \"unavailable\";\n threadId: string | null;\n runId: string | null;\n taskId: string | null;\n sourcePlatform: string | null;\n sourceId: string | null;\n}\n\nexport type UsageMetricsScope = \"me\" | \"workspace\" | \"app\";\n\nexport interface UsageUserOption {\n email: string;\n role: string | null;\n}\n\nexport interface DispatchUsageMetrics {\n billing: UsageBillingMode;\n viewScope: UsageMetricsScope;\n selectedUserEmail: string | null;\n selectedAppId: string | null;\n availableUsers: UsageUserOption[];\n sinceMs: number;\n sinceDays: number;\n generatedAt: number;\n access: {\n viewerEmail: string;\n orgId: string | null;\n role: string | null;\n scope: \"organization\" | \"solo\";\n totalUsers: number;\n };\n totals: {\n costCents: number;\n calls: number;\n chatCalls: number;\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n activeUsers: number;\n chatThreads: number;\n chatMessages: number;\n workspaceApps: number;\n };\n byApp: UsageMetricBucket[];\n byUser: UserUsageMetric[];\n byLabel: UsageMetricBucket[];\n byModel: UsageMetricBucket[];\n daily: DailyUsageMetric[];\n dailyAvailable: boolean;\n monthlyByUser: MonthlyUserUsageMetric[];\n workspaceAppCreationsByUserMonth: WorkspaceAppCreationMetric[];\n appAccess: AppAccessMetric[];\n recent: RecentUsageMetric[];\n}\n\ninterface MemberRecord {\n email: string;\n role: string | null;\n joinedAt: number | null;\n}\n\ninterface ChatStats {\n threads: number;\n messages: number;\n lastChatAt: number | null;\n}\n\nfunction numberField(row: Record<string, unknown>, key: string): number {\n return Number(row[key] ?? 0) || 0;\n}\n\nfunction stringField(row: Record<string, unknown>, key: string): string {\n const value = row[key];\n return typeof value === \"string\" || typeof value === \"number\"\n ? String(value)\n : value == null\n ? \"\"\n : JSON.stringify(value);\n}\n\nfunction nullableNumberField(\n row: Record<string, unknown>,\n key: string,\n): number | null {\n const value = row[key];\n if (value == null) return null;\n const numberValue = Number(value);\n return Number.isFinite(numberValue) ? numberValue : null;\n}\n\nfunction nullableStringField(\n row: Record<string, unknown>,\n key: string,\n): string | null {\n const value = row[key];\n if (typeof value !== \"string\") return null;\n const trimmed = value.trim();\n return trimmed || null;\n}\n\ntype ParsedThreadData =\n | { status: \"absent\"; value: null }\n | { status: \"invalid\"; value: null }\n | { status: \"parsed\"; value: Record<string, unknown> };\n\nfunction parseJson(value: unknown): ParsedThreadData {\n if (typeof value !== \"string\" || !value.trim()) {\n return { status: \"absent\", value: null };\n }\n try {\n const parsed = JSON.parse(value);\n return parsed && typeof parsed === \"object\"\n ? { status: \"parsed\", value: parsed as Record<string, unknown> }\n : { status: \"invalid\", value: null };\n } catch {\n return { status: \"invalid\", value: null };\n }\n}\n\nfunction textFromPromptContent(value: unknown): string {\n if (typeof value === \"string\") return value.trim();\n if (!Array.isArray(value)) return \"\";\n return value\n .map((part) => {\n if (!part || typeof part !== \"object\") return \"\";\n const item = part as Record<string, unknown>;\n return item.type === \"text\" && typeof item.text === \"string\"\n ? item.text.trim()\n : \"\";\n })\n .filter(Boolean)\n .join(\"\\n\")\n .trim();\n}\n\nfunction truncatePrompt(value: string, maxLength = 360): string {\n if (value.length <= maxLength) return value;\n return `${value.slice(0, maxLength - 1).trimEnd()}…`;\n}\n\nfunction firstUserPrompt(threadData: unknown): string | null {\n const parsed = parseJson(threadData);\n if (parsed.status !== \"parsed\") return null;\n const messages = parsed.value.messages;\n if (!Array.isArray(messages)) return null;\n\n for (const entry of messages) {\n if (!entry || typeof entry !== \"object\") continue;\n const record = entry as Record<string, unknown>;\n const message =\n record.message && typeof record.message === \"object\"\n ? (record.message as Record<string, unknown>)\n : record;\n const role = typeof message.role === \"string\" ? message.role : \"\";\n if (role !== \"user\" && role !== \"human\") continue;\n const text = textFromPromptContent(message.content);\n if (text) return truncatePrompt(text);\n }\n return null;\n}\n\ninterface ThreadPromptRow {\n id?: unknown;\n preview?: unknown;\n thread_data?: unknown;\n}\n\nasync function hydrateRecentPrompts(\n rows: Array<Record<string, unknown>>,\n): Promise<RecentUsageMetric[]> {\n const threadIds = [\n ...new Set(\n rows\n .map((row) => nullableStringField(row, \"thread_id\"))\n .filter((value): value is string => Boolean(value)),\n ),\n ];\n const threads = new Map<string, ThreadPromptRow>();\n let threadQueryUnavailable = false;\n\n if (threadIds.length > 0) {\n try {\n const result = await getDbExec().execute({\n sql: `SELECT id, preview, thread_data FROM chat_threads WHERE id IN (${threadIds.map(() => \"?\").join(\", \")})`,\n args: threadIds,\n });\n for (const row of result.rows as ThreadPromptRow[]) {\n const id = typeof row.id === \"string\" ? row.id : \"\";\n if (id) threads.set(id, row);\n }\n } catch {\n threadQueryUnavailable = true;\n }\n }\n\n return rows.map((row) => {\n const threadId = nullableStringField(row, \"thread_id\");\n const thread = threadId ? threads.get(threadId) : undefined;\n const prompt = thread ? firstUserPrompt(thread.thread_data) : null;\n const preview =\n typeof thread?.preview === \"string\" ? thread.preview.trim() : \"\";\n const promptSource = prompt\n ? \"thread\"\n : preview\n ? \"thread-preview\"\n : threadQueryUnavailable && threadId\n ? \"unavailable\"\n : \"not-captured\";\n\n return {\n id: numberField(row, \"id\"),\n createdAt: numberField(row, \"created_at\"),\n ownerEmail: stringField(row, \"owner_email\"),\n app: stringField(row, \"app\") || \"unattributed\",\n label: stringField(row, \"label\") || \"chat\",\n model: stringField(row, \"model\") || \"unknown\",\n inputTokens: numberField(row, \"input_tokens\"),\n outputTokens: numberField(row, \"output_tokens\"),\n cacheReadTokens: numberField(row, \"cache_read_tokens\"),\n cacheWriteTokens: numberField(row, \"cache_write_tokens\"),\n costCents: numberField(row, \"cost_cents_x100\") / 100,\n prompt: prompt ?? (preview ? truncatePrompt(preview) : null),\n promptSource,\n threadId,\n runId: nullableStringField(row, \"run_id\"),\n taskId: nullableStringField(row, \"task_id\"),\n sourcePlatform: nullableStringField(row, \"source_platform\"),\n sourceId: nullableStringField(row, \"source_id\"),\n } satisfies RecentUsageMetric;\n });\n}\n\nfunction labelForKey(value: string): string {\n const trimmed = value.trim();\n return trimmed || \"Unattributed\";\n}\n\nfunction appUsageKey(value: string | null | undefined): string {\n const raw = (value ?? \"\").trim().toLowerCase();\n return raw || \"unattributed\";\n}\n\nfunction appOwner(app: WorkspaceAppSummary): string | null {\n const owner = app.owner?.trim();\n return owner || null;\n}\n\nasync function detectUsageEngineName(): Promise<string | null> {\n try {\n const stored = (await readDefaultAgentEngineSetting()) as {\n engine?: string;\n } | null;\n if (isAgentEngineSettingConfigured(stored)) {\n return (stored as { engine: string }).engine;\n }\n if (stored && typeof stored.engine === \"string\") {\n const entry = getAgentEngineEntry(stored.engine);\n if (entry && isStoredEngineUsable(stored, entry)) {\n return stored.engine;\n }\n }\n\n const detectedFromUser = await detectEngineFromUserSecrets();\n if (detectedFromUser) return detectedFromUser.name;\n\n return detectEngineFromEnv()?.name ?? null;\n } catch {\n return null;\n }\n}\n\nasync function queryRows<T extends Record<string, unknown>>(\n sql: string,\n args: unknown[] = [],\n): Promise<T[]> {\n try {\n const result = await getDbExec().execute({ sql, args });\n return result.rows as T[];\n } catch {\n return [];\n }\n}\n\nasync function initializeUsageMetricsTable(sinceMs: number): Promise<void> {\n try {\n await getUsageSummary({ ownerEmail: \"__dispatch_metrics_init__\", sinceMs });\n } catch {\n // Metrics should still render an empty state if usage storage is locked,\n // stale, or unavailable; each aggregate read below is already best-effort.\n }\n}\n\nasync function listOrgMembers(orgId: string | null): Promise<MemberRecord[]> {\n if (!orgId) return [];\n const result = await getDbExec().execute({\n sql: `SELECT email, role, joined_at AS joined_at FROM org_members\n WHERE org_id = ? AND federation_removal_pending_at IS NULL\n ORDER BY joined_at ASC`,\n args: [orgId],\n });\n const rows = result.rows as Record<string, unknown>[];\n return rows\n .map((row) => ({\n email: stringField(row, \"email\").trim(),\n role: stringField(row, \"role\") || null,\n joinedAt: nullableNumberField(row, \"joined_at\"),\n }))\n .filter((member) => member.email);\n}\n\nfunction usageScope(\n sinceMs: number,\n memberEmails: string[],\n): { where: string; args: unknown[] } {\n if (memberEmails.length === 0) {\n return { where: \"created_at >= ?\", args: [sinceMs] };\n }\n const placeholders = memberEmails.map(() => \"?\").join(\", \");\n return {\n where: `created_at >= ? AND LOWER(owner_email) IN (${placeholders})`,\n args: [sinceMs, ...memberEmails.map((email) => email.toLowerCase())],\n };\n}\n\nfunction withOrgUsageScope(\n scope: { where: string; args: unknown[] },\n orgId: string | null,\n selfScoped: boolean,\n): { where: string; args: unknown[] } {\n const org = usageOrgScope({ orgId, selfScoped });\n return {\n where: `${scope.where} AND ${org.where || \"org_id IS NULL\"}`,\n args: [...scope.args, ...org.args],\n };\n}\n\nfunction threadScope(\n sinceMs: number,\n memberEmails: string[],\n): { where: string; args: unknown[] } {\n if (memberEmails.length === 0) {\n return { where: \"updated_at >= ?\", args: [sinceMs] };\n }\n const placeholders = memberEmails.map(() => \"?\").join(\", \");\n return {\n where: `updated_at >= ? AND LOWER(owner_email) IN (${placeholders})`,\n args: [sinceMs, ...memberEmails.map((email) => email.toLowerCase())],\n };\n}\n\nfunction ownerScope(\n sinceMs: number,\n ownerEmail: string,\n): {\n where: string;\n args: unknown[];\n} {\n return {\n where: \"created_at >= ? AND LOWER(owner_email) = ?\",\n args: [sinceMs, ownerEmail.toLowerCase()],\n };\n}\n\nfunction ownerThreadScope(\n sinceMs: number,\n ownerEmail: string,\n): {\n where: string;\n args: unknown[];\n} {\n return {\n where: \"updated_at >= ? AND LOWER(owner_email) = ?\",\n args: [sinceMs, ownerEmail.toLowerCase()],\n };\n}\n\nfunction appUsageScope(\n sinceMs: number,\n memberEmails: string[],\n appId: string,\n orgId: string | null,\n viewerEmail: string,\n): { where: string; args: unknown[] } {\n const scope = withOrgUsageScope(\n usageScope(sinceMs, memberEmails),\n orgId,\n isSelfScopedUsageRead(memberEmails, viewerEmail),\n );\n return {\n where: `${scope.where} AND LOWER(app) = ?`,\n args: [...scope.args, appUsageKey(appId)],\n };\n}\n\nfunction workspaceAppCreationScope(\n sinceMs: number,\n orgId: string | null,\n memberEmails: string[],\n): { where: string; args: unknown[] } {\n const filters = [\"created_at >= ?\", \"action = ?\"];\n const args: unknown[] = [sinceMs, \"workspace-app.pending\"];\n\n if (orgId) {\n filters.push(\"org_id = ?\");\n args.push(orgId);\n }\n if (memberEmails.length > 0) {\n filters.push(\n `LOWER(owner_email) IN (${memberEmails.map(() => \"?\").join(\", \")})`,\n );\n args.push(...memberEmails.map((email) => email.toLowerCase()));\n }\n\n return { where: filters.join(\" AND \"), args };\n}\n\nfunction bucketFromRow(row: Record<string, unknown>): UsageMetricBucket {\n const key = stringField(row, \"k\");\n return {\n key,\n label: labelForKey(key),\n costCents: numberField(row, \"cost_x100\") / 100,\n calls: numberField(row, \"calls\"),\n chatCalls: numberField(row, \"chat_calls\"),\n inputTokens: numberField(row, \"input_tokens\"),\n outputTokens: numberField(row, \"output_tokens\"),\n cacheReadTokens: numberField(row, \"cache_read_tokens\"),\n cacheWriteTokens: numberField(row, \"cache_write_tokens\"),\n activeUsers: numberField(row, \"active_users\"),\n lastActiveAt: nullableNumberField(row, \"last_active_at\"),\n };\n}\n\nasync function usageBuckets(\n columnExpression: string,\n where: string,\n args: unknown[],\n limit: number,\n): Promise<UsageMetricBucket[]> {\n const rows = await queryRows<Record<string, unknown>>(\n `SELECT ${columnExpression} AS k,\n COALESCE(SUM(cost_cents_x100), 0) AS cost_x100,\n COUNT(*) AS calls,\n SUM(CASE WHEN label = 'chat' THEN 1 ELSE 0 END) AS chat_calls,\n COALESCE(SUM(input_tokens), 0) AS input_tokens,\n COALESCE(SUM(output_tokens), 0) AS output_tokens,\n COALESCE(SUM(cache_read_tokens), 0) AS cache_read_tokens,\n COALESCE(SUM(cache_write_tokens), 0) AS cache_write_tokens,\n COUNT(DISTINCT owner_email) AS active_users,\n MAX(created_at) AS last_active_at\n FROM token_usage\n WHERE ${where}\n GROUP BY ${columnExpression}\n ORDER BY cost_x100 DESC\n LIMIT ?`,\n [...args, limit],\n );\n return rows.map(bucketFromRow);\n}\n\nconst adoptionActionKeySql = `CASE\n WHEN LOWER(TRIM(label)) = 'chat' THEN 'chat'\n WHEN LOWER(TRIM(label)) IN ('automation', 'manual-automation')\n OR LOWER(TRIM(label)) LIKE 'automation:%'\n OR LOWER(TRIM(label)) LIKE 'manual-automation:%'\n OR LOWER(TRIM(label)) LIKE 'recurring-job:%' THEN 'automation'\n WHEN LOWER(TRIM(label)) = 'custom-agent'\n OR LOWER(TRIM(label)) LIKE 'custom-agent:%' THEN 'custom-agent'\n ELSE 'other'\nEND`;\n\ninterface AppAdoptionAggregate {\n calls: number;\n costCents: number;\n chatCalls: number;\n activeUsers: number;\n dailyActiveUsers: number;\n weeklyActiveUsers: number;\n lastActiveAt: number | null;\n actions: Map<\n string,\n { calls: number; activeUsers: number; lastActiveAt: number | null }\n >;\n}\n\nfunction emptyAppAdoptionAggregate(): AppAdoptionAggregate {\n return {\n calls: 0,\n costCents: 0,\n chatCalls: 0,\n activeUsers: 0,\n dailyActiveUsers: 0,\n weeklyActiveUsers: 0,\n lastActiveAt: null,\n actions: new Map(),\n };\n}\n\nasync function loadAppAdoption(\n usage: { where: string; args: unknown[] },\n adoptionUsage: { where: string; args: unknown[] },\n generatedAt: number,\n): Promise<Map<string, AppAdoptionAggregate>> {\n const appExpression = \"COALESCE(NULLIF(app, ''), 'unattributed')\";\n const [selectedRows, adoptionRows, actionRows] = await Promise.all([\n queryRows<Record<string, unknown>>(\n `SELECT ${appExpression} AS app,\n COALESCE(SUM(cost_cents_x100), 0) AS cost_x100,\n COUNT(*) AS calls,\n SUM(CASE WHEN label = 'chat' THEN 1 ELSE 0 END) AS chat_calls,\n COUNT(DISTINCT owner_email) AS active_users,\n MAX(created_at) AS last_active_at\n FROM token_usage\n WHERE ${usage.where}\n GROUP BY ${appExpression}`,\n usage.args,\n ),\n queryRows<Record<string, unknown>>(\n `SELECT ${appExpression} AS app,\n COUNT(DISTINCT CASE WHEN created_at >= ? THEN owner_email END) AS daily_active_users,\n COUNT(DISTINCT CASE WHEN created_at >= ? THEN owner_email END) AS weekly_active_users\n FROM token_usage\n WHERE ${adoptionUsage.where}\n GROUP BY ${appExpression}`,\n [generatedAt - DAY_MS, generatedAt - 7 * DAY_MS, ...adoptionUsage.args],\n ),\n queryRows<Record<string, unknown>>(\n `SELECT ${appExpression} AS app,\n ${adoptionActionKeySql} AS action_key,\n COUNT(*) AS calls,\n COUNT(DISTINCT owner_email) AS active_users,\n MAX(created_at) AS last_active_at\n FROM token_usage\n WHERE ${usage.where}\n GROUP BY ${appExpression}, ${adoptionActionKeySql}`,\n usage.args,\n ),\n ]);\n\n const adoptionByApp = new Map<string, AppAdoptionAggregate>();\n const getAdoption = (app: string): AppAdoptionAggregate => {\n const key = appUsageKey(app);\n const existing = adoptionByApp.get(key);\n if (existing) return existing;\n const created = emptyAppAdoptionAggregate();\n adoptionByApp.set(key, created);\n return created;\n };\n\n for (const row of selectedRows) {\n const adoption = getAdoption(stringField(row, \"app\"));\n adoption.calls = numberField(row, \"calls\");\n adoption.costCents = numberField(row, \"cost_x100\") / 100;\n adoption.chatCalls = numberField(row, \"chat_calls\");\n adoption.activeUsers = numberField(row, \"active_users\");\n adoption.lastActiveAt = nullableNumberField(row, \"last_active_at\");\n }\n for (const row of adoptionRows) {\n const adoption = getAdoption(stringField(row, \"app\"));\n adoption.dailyActiveUsers = numberField(row, \"daily_active_users\");\n adoption.weeklyActiveUsers = numberField(row, \"weekly_active_users\");\n }\n for (const row of actionRows) {\n const adoption = getAdoption(stringField(row, \"app\"));\n adoption.actions.set(stringField(row, \"action_key\"), {\n calls: numberField(row, \"calls\"),\n activeUsers: numberField(row, \"active_users\"),\n lastActiveAt: nullableNumberField(row, \"last_active_at\"),\n });\n }\n\n return adoptionByApp;\n}\n\nasync function loadDailyAndMonthlyUsage(usage: {\n where: string;\n args: unknown[];\n}): Promise<{\n daily: DailyUsageMetric[];\n dailyAvailable: boolean;\n monthlyByUser: MonthlyUsageAggregate[];\n usersByDay: Map<string, Set<string>>;\n}> {\n const dayBucketExpression = `CAST(created_at / ${DAY_MS} AS INTEGER)`;\n let result;\n try {\n result = await getDbExec().execute({\n sql: `SELECT ${dayBucketExpression} AS day_bucket,\n owner_email,\n COALESCE(SUM(cost_cents_x100), 0) AS cost_x100,\n COALESCE(SUM(builder_credits_used), 0) AS builder_credits,\n COALESCE(SUM(CASE\n WHEN engine_name = 'builder' AND builder_credits_used IS NULL\n THEN cost_cents_x100 ELSE 0\n END), 0) AS builder_estimated_cost_x100,\n COUNT(*) FILTER (\n WHERE NULLIF(engine_name, '') IS NULL AND builder_credits_used IS NULL\n ) AS unclassified_calls,\n COUNT(*) FILTER (\n WHERE engine_name = 'builder' AND builder_credits_used IS NULL\n AND cost_source = 'unavailable' AND cost_cents_x100 <= 0\n ) AS unpriced_builder_calls,\n COUNT(*) AS calls,\n SUM(CASE WHEN label = 'chat' THEN 1 ELSE 0 END) AS chat_calls,\n COALESCE(SUM(input_tokens), 0) AS input_tokens,\n COALESCE(SUM(output_tokens), 0) AS output_tokens,\n COALESCE(SUM(cache_read_tokens), 0) AS cache_read_tokens,\n COALESCE(SUM(cache_write_tokens), 0) AS cache_write_tokens\n FROM token_usage\n WHERE ${usage.where}\n GROUP BY ${dayBucketExpression}, owner_email\n ORDER BY ${dayBucketExpression} ASC`,\n args: usage.args,\n });\n } catch {\n return {\n daily: [],\n dailyAvailable: false,\n monthlyByUser: [],\n usersByDay: new Map(),\n };\n }\n const rows = result.rows as Record<string, unknown>[];\n const dailyMap = new Map<\n string,\n { costX100: number; calls: number; chatCalls: number; users: Set<string> }\n >();\n const monthlyByUserMap = new Map<string, MonthlyUsageAggregate>();\n const usersByDay = new Map<string, Set<string>>();\n\n for (const row of rows) {\n const date = new Date(\n numberField(row, \"day_bucket\") * DAY_MS,\n ).toISOString();\n const day = date.slice(0, 10);\n const ownerEmail = stringField(row, \"owner_email\");\n const daily = dailyMap.get(day) ?? {\n costX100: 0,\n calls: 0,\n chatCalls: 0,\n users: new Set<string>(),\n };\n daily.costX100 += numberField(row, \"cost_x100\");\n daily.calls += numberField(row, \"calls\");\n daily.chatCalls += numberField(row, \"chat_calls\");\n daily.users.add(ownerEmail.toLowerCase());\n dailyMap.set(day, daily);\n const users = usersByDay.get(day) ?? new Set<string>();\n users.add(ownerEmail.toLowerCase());\n usersByDay.set(day, users);\n\n const month = day.slice(0, 7);\n const monthlyKey = `${ownerEmail}\\u0000${month}`;\n const monthly = monthlyByUserMap.get(monthlyKey) ?? {\n month,\n ownerEmail,\n costCents: 0,\n builderCredits: 0,\n builderEstimatedCostX100: 0,\n unclassifiedCalls: 0,\n unpricedBuilderCalls: 0,\n calls: 0,\n chatCalls: 0,\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n cacheWriteTokens: 0,\n };\n monthly.costCents += numberField(row, \"cost_x100\") / 100;\n monthly.builderCredits += numberField(row, \"builder_credits\");\n monthly.builderEstimatedCostX100 += numberField(\n row,\n \"builder_estimated_cost_x100\",\n );\n monthly.unclassifiedCalls += numberField(row, \"unclassified_calls\");\n monthly.unpricedBuilderCalls += numberField(row, \"unpriced_builder_calls\");\n monthly.calls += numberField(row, \"calls\");\n monthly.chatCalls += numberField(row, \"chat_calls\");\n monthly.inputTokens += numberField(row, \"input_tokens\");\n monthly.outputTokens += numberField(row, \"output_tokens\");\n monthly.cacheReadTokens += numberField(row, \"cache_read_tokens\");\n monthly.cacheWriteTokens += numberField(row, \"cache_write_tokens\");\n monthlyByUserMap.set(monthlyKey, monthly);\n }\n\n return {\n daily: [...dailyMap.entries()]\n .map(([date, value]) => ({\n date,\n costCents: value.costX100 / 100,\n calls: value.calls,\n chatCalls: value.chatCalls,\n activeUsers: value.users.size,\n dailyActiveUsers: value.users.size,\n weeklyActiveUsers: null,\n }))\n .sort((a, b) => a.date.localeCompare(b.date)),\n dailyAvailable: true,\n monthlyByUser: [...monthlyByUserMap.values()].sort(\n (a, b) =>\n a.month.localeCompare(b.month) ||\n a.ownerEmail.localeCompare(b.ownerEmail),\n ),\n usersByDay,\n };\n}\n\nasync function loadWeeklyActiveUsers(\n usage: { where: string; args: unknown[] },\n visibleUsersByDay: Map<string, Set<string>>,\n startDate: string,\n endDate: string,\n): Promise<Map<string, number> | null> {\n const dayBucketExpression = `CAST(created_at / ${DAY_MS} AS INTEGER)`;\n let result;\n try {\n result = await getDbExec().execute({\n sql: `SELECT ${dayBucketExpression} AS day_bucket, owner_email\n FROM token_usage\n WHERE ${usage.where}\n GROUP BY ${dayBucketExpression}, owner_email\n ORDER BY ${dayBucketExpression} ASC`,\n args: usage.args,\n });\n // coercion-ok: null distinguishes an unavailable optional trend from empty activity.\n } catch {\n return null;\n }\n const rows = result.rows as Record<string, unknown>[];\n const usersByDay = new Map(\n [...visibleUsersByDay.entries()].map(([day, users]) => [\n day,\n new Set(users),\n ]),\n );\n for (const row of rows) {\n const day = new Date(numberField(row, \"day_bucket\") * DAY_MS)\n .toISOString()\n .slice(0, 10);\n const users = usersByDay.get(day) ?? new Set<string>();\n users.add(stringField(row, \"owner_email\").toLowerCase());\n usersByDay.set(day, users);\n }\n\n const activityByDay = new Map<string, number>();\n const firstDay = Date.parse(`${startDate}T00:00:00Z`);\n const lastDay = Date.parse(`${endDate}T00:00:00Z`);\n for (let dayStart = firstDay; dayStart <= lastDay; dayStart += DAY_MS) {\n const day = new Date(dayStart).toISOString().slice(0, 10);\n const weeklyUsers = new Set<string>();\n for (\n let previousDayStart = dayStart;\n previousDayStart >= dayStart - 6 * DAY_MS;\n previousDayStart -= DAY_MS\n ) {\n const previousDay = new Date(previousDayStart).toISOString().slice(0, 10);\n for (const user of usersByDay.get(previousDay) ?? []) {\n weeklyUsers.add(user);\n }\n }\n activityByDay.set(day, weeklyUsers.size);\n }\n return activityByDay;\n}\n\nasync function loadChatStats(\n where: string,\n args: unknown[],\n): Promise<Map<string, ChatStats>> {\n const rows = await queryRows<Record<string, unknown>>(\n `SELECT owner_email AS owner_email,\n COUNT(*) AS threads,\n COALESCE(SUM(message_count), 0) AS messages,\n MAX(updated_at) AS last_chat_at\n FROM chat_threads\n WHERE ${where}\n GROUP BY owner_email`,\n args,\n );\n return new Map(\n rows.map((row) => [\n stringField(row, \"owner_email\"),\n {\n threads: numberField(row, \"threads\"),\n messages: numberField(row, \"messages\"),\n lastChatAt: nullableNumberField(row, \"last_chat_at\"),\n },\n ]),\n );\n}\n\nasync function assertCanViewMetrics(viewScope: UsageMetricsScope): Promise<{\n viewerEmail: string;\n orgId: string | null;\n role: string | null;\n}> {\n const viewerEmail = currentOwnerEmail();\n const orgId = currentOrgId();\n const role = orgId ? await readOrgMemberRole(orgId, viewerEmail) : null;\n if (\n viewScope === \"me\" ||\n isDispatchEnvironmentAdmin(viewerEmail) ||\n role === \"owner\" ||\n role === \"admin\"\n ) {\n return { viewerEmail, orgId, role };\n }\n if (!orgId) {\n return { viewerEmail, orgId, role };\n }\n throw new ForbiddenError(\n \"Only organization owners and admins can view workspace usage metrics.\",\n );\n}\n\nfunction failUserNotOrgMember(email: string): never {\n fail(\n `${email} is not a member of this organization. list-dispatch-usage-metrics only covers this workspace's own agent usage; usage, credits, or activity for customers, accounts, or companies belongs to the app that owns that data (see <relevant-apps> or run describe-workspace-apps with a query).`,\n { errorCode: \"usage_user_not_org_member\", statusCode: 404 },\n );\n}\n\nexport async function listDispatchUsageMetrics(input: {\n sinceDays?: number;\n scope?: UsageMetricsScope;\n userEmail?: string | null;\n appId?: string | null;\n}): Promise<DispatchUsageMetrics> {\n const viewScope: UsageMetricsScope =\n input.scope === \"me\" ? \"me\" : input.scope === \"app\" ? \"app\" : \"workspace\";\n // Another person's usage: unauthorized callers get one answer whether or not\n // the email is a member, so the lookup cannot probe the roster; authorized\n // callers asking about an outside email are pointed at the owning app.\n const requestedEmail =\n viewScope === \"workspace\" ? input.userEmail?.trim() || null : null;\n const callerEmail = currentOwnerEmail();\n const callerOrgId = currentOrgId();\n if (\n requestedEmail &&\n callerOrgId &&\n requestedEmail.toLowerCase() !== callerEmail.toLowerCase()\n ) {\n const callerRole = await readOrgMemberRole(callerOrgId, callerEmail);\n if (\n !isDispatchEnvironmentAdmin(callerEmail) &&\n callerRole !== \"owner\" &&\n callerRole !== \"admin\"\n ) {\n fail(\n \"Only organization owners and admins can look up another person's usage with list-dispatch-usage-metrics. Usage, credits, or activity for customers, accounts, or companies belongs to the app that owns that data (see <relevant-apps> or run describe-workspace-apps with a query).\",\n { errorCode: \"usage_user_lookup_forbidden\", statusCode: 403 },\n );\n }\n if (!(await isOrgMember(callerOrgId, requestedEmail))) {\n failUserNotOrgMember(requestedEmail);\n }\n }\n const { viewerEmail, orgId, role } = await assertCanViewMetrics(\n viewScope === \"app\" ? \"me\" : viewScope,\n );\n const sinceDays = Math.max(1, Math.min(365, input.sinceDays ?? 30));\n const generatedAt = Date.now();\n const sinceMs = generatedAt - sinceDays * DAY_MS;\n const apps = await listWorkspaceApps({ includeAgentCards: false });\n const requestedAppId = input.appId?.trim() || null;\n const selectedApp =\n viewScope === \"app\" && requestedAppId\n ? apps.find((app) => app.id === requestedAppId)\n : null;\n if (viewScope === \"app\" && !requestedAppId) {\n throw new Error(\"App metrics require an appId.\");\n }\n if (viewScope === \"app\" && !selectedApp) {\n throw new ForbiddenError(\n \"You do not have access to metrics for this workspace app.\",\n );\n }\n const selectedAppOwner = selectedApp ? appOwner(selectedApp) : null;\n const isMetricsAdmin = Boolean(\n isDispatchEnvironmentAdmin(viewerEmail) ||\n role === \"owner\" ||\n role === \"admin\",\n );\n if (\n viewScope === \"app\" &&\n !isMetricsAdmin &&\n selectedAppOwner?.toLowerCase() !== viewerEmail.toLowerCase()\n ) {\n throw new ForbiddenError(\n \"Only the app owner or an organization owner or admin can view app metrics.\",\n );\n }\n\n await initializeUsageMetricsTable(sinceMs);\n\n const rawMembers =\n viewScope === \"me\"\n ? [{ email: viewerEmail, role, joinedAt: null }]\n : orgId\n ? await listOrgMembers(orgId)\n : [{ email: viewerEmail, role: null, joinedAt: null }];\n const members =\n viewScope !== \"me\" && orgId && rawMembers.length === 0\n ? [{ email: viewerEmail, role, joinedAt: null }]\n : rawMembers;\n const requestedUserEmail =\n viewScope === \"app\" ? null : input.userEmail?.trim() || null;\n const selectedUserEmail =\n viewScope === \"me\"\n ? viewerEmail\n : requestedUserEmail\n ? (members.find(\n (member) =>\n member.email.toLowerCase() === requestedUserEmail.toLowerCase(),\n )?.email ?? null)\n : null;\n if (viewScope === \"workspace\" && requestedUserEmail && !selectedUserEmail) {\n failUserNotOrgMember(requestedUserEmail);\n }\n const memberEmails = selectedUserEmail\n ? [selectedUserEmail]\n : members.map((member) => member.email);\n const selfScopedUsage = isSelfScopedUsageRead(memberEmails, viewerEmail);\n const memberByEmail = new Map(\n members.map((member) => [member.email.toLowerCase(), member]),\n );\n const usage =\n viewScope === \"app\" && selectedApp\n ? appUsageScope(sinceMs, memberEmails, selectedApp.id, orgId, viewerEmail)\n : withOrgUsageScope(\n selectedUserEmail\n ? ownerScope(sinceMs, selectedUserEmail)\n : usageScope(sinceMs, memberEmails),\n orgId,\n selfScopedUsage,\n );\n const visibleSinceMs = Math.floor(sinceMs / DAY_MS) * DAY_MS;\n const adoptionSinceMs = Math.min(\n visibleSinceMs - 6 * DAY_MS,\n generatedAt - 7 * DAY_MS,\n );\n const adoptionUsage =\n viewScope === \"app\" && selectedApp\n ? appUsageScope(\n adoptionSinceMs,\n memberEmails,\n selectedApp.id,\n orgId,\n viewerEmail,\n )\n : withOrgUsageScope(\n selectedUserEmail\n ? ownerScope(adoptionSinceMs, selectedUserEmail)\n : usageScope(adoptionSinceMs, memberEmails),\n orgId,\n selfScopedUsage,\n );\n const weeklyLookbackUsage = {\n where: `${adoptionUsage.where} AND created_at < ?`,\n args: [...adoptionUsage.args, sinceMs],\n };\n const threads = selectedUserEmail\n ? ownerThreadScope(sinceMs, selectedUserEmail)\n : threadScope(sinceMs, memberEmails);\n\n const workspaceAppCreation = workspaceAppCreationScope(\n sinceMs,\n orgId,\n memberEmails,\n );\n\n const [\n totalsRows,\n byApp,\n byUserBase,\n byLabel,\n byModel,\n chatStats,\n workspaceAppCreationRows,\n ] = await Promise.all([\n queryRows<Record<string, unknown>>(\n `SELECT\n COALESCE(SUM(cost_cents_x100), 0) AS cost_x100,\n COUNT(*) AS calls,\n SUM(CASE WHEN label = 'chat' THEN 1 ELSE 0 END) AS chat_calls,\n COALESCE(SUM(input_tokens), 0) AS input_tokens,\n COALESCE(SUM(output_tokens), 0) AS output_tokens,\n COALESCE(SUM(cache_read_tokens), 0) AS cache_read_tokens,\n COALESCE(SUM(cache_write_tokens), 0) AS cache_write_tokens,\n COUNT(*) FILTER (WHERE engine_name = 'builder' OR builder_credits_used IS NOT NULL) AS builder_calls,\n COUNT(*) FILTER (WHERE NULLIF(engine_name, '') IS NOT NULL AND NULLIF(engine_name, '') <> 'builder' AND builder_credits_used IS NULL) AS provider_calls,\n COUNT(*) FILTER (WHERE NULLIF(engine_name, '') IS NULL AND builder_credits_used IS NULL) AS unknown_calls,\n COUNT(DISTINCT owner_email) AS active_users\n FROM token_usage\n WHERE ${usage.where}`,\n usage.args,\n ),\n usageBuckets(\n `COALESCE(NULLIF(app, ''), 'unattributed')`,\n usage.where,\n usage.args,\n 20,\n ),\n viewScope === \"app\"\n ? Promise.resolve([] as UsageMetricBucket[])\n : usageBuckets(\"owner_email\", usage.where, usage.args, 50),\n viewScope === \"app\"\n ? Promise.resolve([] as UsageMetricBucket[])\n : usageBuckets(\n `COALESCE(NULLIF(label, ''), 'chat')`,\n usage.where,\n usage.args,\n 20,\n ),\n usageBuckets(\n `COALESCE(NULLIF(model, ''), 'unknown')`,\n usage.where,\n usage.args,\n 20,\n ),\n viewScope === \"app\"\n ? Promise.resolve(new Map<string, ChatStats>())\n : loadChatStats(threads.where, threads.args),\n viewScope === \"app\"\n ? Promise.resolve([])\n : queryRows<Record<string, unknown>>(\n `SELECT owner_email, actor, target_id, created_at\n FROM dispatch_audit_events\n WHERE ${workspaceAppCreation.where}\n ORDER BY created_at ASC`,\n workspaceAppCreation.args,\n ),\n ]);\n\n const totals = totalsRows[0] ?? {};\n const builderCalls = numberField(totals, \"builder_calls\");\n const providerCalls = numberField(totals, \"provider_calls\");\n const unknownCalls = numberField(totals, \"unknown_calls\");\n const billing = unknownCalls\n ? UNKNOWN_USAGE_BILLING\n : builderCalls > 0 && providerCalls > 0\n ? MIXED_USAGE_BILLING\n : builderCalls > 0\n ? usageBillingForEngine(\"builder\")\n : providerCalls > 0\n ? usageBillingForEngine(\"external\")\n : usageBillingForEngine(await detectUsageEngineName());\n\n const topAppRows =\n viewScope === \"app\"\n ? []\n : await queryRows<Record<string, unknown>>(\n `SELECT owner_email AS owner_email,\n COALESCE(NULLIF(app, ''), 'unattributed') AS app,\n COALESCE(SUM(cost_cents_x100), 0) AS cost_x100\n FROM token_usage\n WHERE ${usage.where}\n GROUP BY owner_email, COALESCE(NULLIF(app, ''), 'unattributed')\n ORDER BY owner_email ASC, cost_x100 DESC`,\n usage.args,\n );\n const topAppByUser = new Map<string, string>();\n for (const row of topAppRows) {\n const email = stringField(row, \"owner_email\");\n if (!topAppByUser.has(email)) {\n topAppByUser.set(email, stringField(row, \"app\"));\n }\n }\n\n const byUserMap = new Map<string, UserUsageMetric>();\n for (const bucket of byUserBase) {\n const ownerEmail = bucket.key;\n const stats = chatStats.get(ownerEmail) ?? {\n threads: 0,\n messages: 0,\n lastChatAt: null,\n };\n const member = memberByEmail.get(ownerEmail.toLowerCase());\n byUserMap.set(ownerEmail, {\n ...bucket,\n ownerEmail,\n chatThreads: stats.threads,\n chatMessages: stats.messages,\n lastChatAt: stats.lastChatAt,\n topApp: topAppByUser.get(ownerEmail) ?? null,\n role: member?.role ?? null,\n });\n }\n for (const [ownerEmail, stats] of chatStats) {\n if (byUserMap.has(ownerEmail)) continue;\n const member = memberByEmail.get(ownerEmail.toLowerCase());\n byUserMap.set(ownerEmail, {\n key: ownerEmail,\n label: ownerEmail,\n ownerEmail,\n costCents: 0,\n calls: 0,\n chatCalls: 0,\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n cacheWriteTokens: 0,\n activeUsers: 1,\n lastActiveAt: stats.lastChatAt,\n chatThreads: stats.threads,\n chatMessages: stats.messages,\n lastChatAt: stats.lastChatAt,\n topApp: null,\n role: member?.role ?? null,\n });\n }\n\n const [\n {\n daily: usageDaily,\n dailyAvailable,\n monthlyByUser: monthlyUsage,\n usersByDay,\n },\n appAdoptionMap,\n ] = await Promise.all([\n loadDailyAndMonthlyUsage(usage),\n loadAppAdoption(usage, adoptionUsage, generatedAt),\n ]);\n const usageByDate = new Map(usageDaily.map((row) => [row.date, row]));\n const weeklyActiveUsers = dailyAvailable\n ? await loadWeeklyActiveUsers(\n weeklyLookbackUsage,\n usersByDay,\n new Date(visibleSinceMs).toISOString().slice(0, 10),\n new Date(generatedAt).toISOString().slice(0, 10),\n )\n : null;\n const daily = !dailyAvailable\n ? []\n : weeklyActiveUsers\n ? [...weeklyActiveUsers.entries()].map(([date, weeklyUsers]) => ({\n ...(usageByDate.get(date) ?? {\n date,\n costCents: 0,\n calls: 0,\n chatCalls: 0,\n activeUsers: 0,\n dailyActiveUsers: 0,\n weeklyActiveUsers: 0,\n }),\n weeklyActiveUsers: weeklyUsers,\n }))\n : usageDaily.map((row) => ({ ...row, weeklyActiveUsers: null }));\n\n const monthlyByUser =\n viewScope === \"app\"\n ? []\n : monthlyUsage.map(\n ({\n builderCredits,\n builderEstimatedCostX100,\n unclassifiedCalls,\n unpricedBuilderCalls,\n ...row\n }) => ({\n ...row,\n credits:\n billing.unit === \"usd\" ||\n billing.unit === \"unknown\" ||\n unclassifiedCalls > 0 ||\n unpricedBuilderCalls > 0\n ? null\n : builderCredits +\n builderCreditsFromCostCents(builderEstimatedCostX100 / 100),\n }),\n );\n\n const workspaceAppCreationMap = new Map<\n string,\n { month: string; ownerEmail: string; count: number; appIds: Set<string> }\n >();\n for (const row of workspaceAppCreationRows) {\n const month = new Date(numberField(row, \"created_at\"))\n .toISOString()\n .slice(0, 7);\n const ownerEmail =\n stringField(row, \"owner_email\") || stringField(row, \"actor\");\n if (!ownerEmail) continue;\n const key = `${ownerEmail}\\u0000${month}`;\n const current = workspaceAppCreationMap.get(key) ?? {\n month,\n ownerEmail,\n count: 0,\n appIds: new Set<string>(),\n };\n current.count += 1;\n const appId = stringField(row, \"target_id\");\n if (appId) current.appIds.add(appId);\n workspaceAppCreationMap.set(key, current);\n }\n const workspaceAppCreationsByUserMonth = [...workspaceAppCreationMap.values()]\n .map(({ appIds, ...row }) => ({\n ...row,\n appIds: [...appIds].sort(),\n }))\n .sort(\n (a, b) =>\n a.month.localeCompare(b.month) ||\n a.ownerEmail.localeCompare(b.ownerEmail),\n );\n\n const recentRows =\n viewScope === \"app\"\n ? []\n : await queryRows<Record<string, unknown>>(\n `SELECT id, created_at, owner_email, app, label, model,\n input_tokens, output_tokens, cache_read_tokens, cache_write_tokens,\n cost_cents_x100, thread_id, run_id, task_id, source_platform, source_id\n FROM token_usage\n WHERE ${usage.where}\n ORDER BY created_at DESC\n LIMIT 50`,\n usage.args,\n );\n const recent =\n viewScope === \"app\" ? [] : await hydrateRecentPrompts(recentRows);\n\n const appUsageByKey = new Map(\n byApp.map((bucket) => [appUsageKey(bucket.key), bucket]),\n );\n const accessUsers = members.length || byUserMap.size;\n const accessModel =\n viewScope === \"me\" ? \"solo\" : orgId ? \"workspace\" : \"solo\";\n const accessLabel =\n viewScope === \"me\"\n ? \"Your account\"\n : orgId\n ? \"Workspace members\"\n : \"Signed-in users\";\n const appRows = selectedApp ? [selectedApp] : apps;\n const appAccess = appRows.map((app) => {\n const usageBucket = appUsageByKey.get(appUsageKey(app.id));\n const adoption = appAdoptionMap.get(appUsageKey(app.id));\n const ownerEmail = appOwner(app);\n const isOwnedByViewer =\n ownerEmail?.toLowerCase() === viewerEmail.toLowerCase();\n const canViewUsage = isMetricsAdmin || isOwnedByViewer;\n const visibleUsageBucket = canViewUsage ? usageBucket : undefined;\n const visibleAdoption = canViewUsage ? adoption : undefined;\n return {\n id: app.id,\n name: app.name,\n path: app.path,\n status: app.status,\n statusLabel: app.statusLabel,\n isDispatch: app.isDispatch,\n accessModel,\n accessLabel,\n accessUsers,\n ownerEmail: canViewUsage ? ownerEmail : null,\n isOwnedByViewer,\n canViewUsage,\n usersWithUsage:\n visibleAdoption?.activeUsers ?? visibleUsageBucket?.activeUsers ?? 0,\n dailyActiveUsers: visibleAdoption?.dailyActiveUsers ?? 0,\n weeklyActiveUsers: visibleAdoption?.weeklyActiveUsers ?? 0,\n usageCalls: visibleAdoption?.calls ?? visibleUsageBucket?.calls ?? 0,\n chatCalls:\n visibleAdoption?.chatCalls ?? visibleUsageBucket?.chatCalls ?? 0,\n costCents:\n visibleAdoption?.costCents ?? visibleUsageBucket?.costCents ?? 0,\n lastActiveAt:\n visibleAdoption?.lastActiveAt ??\n visibleUsageBucket?.lastActiveAt ??\n null,\n actionMetrics: visibleAdoption\n ? [...visibleAdoption.actions.entries()]\n .map(([key, action]) => ({\n key,\n label: key,\n calls: action.calls,\n activeUsers: action.activeUsers,\n lastActiveAt: action.lastActiveAt,\n }))\n .sort((a, b) => b.calls - a.calls)\n : [],\n } satisfies AppAccessMetric;\n });\n\n const chatThreadTotals = [...chatStats.values()].reduce(\n (acc, value) => ({\n threads: acc.threads + value.threads,\n messages: acc.messages + value.messages,\n }),\n { threads: 0, messages: 0 },\n );\n\n return {\n billing,\n viewScope,\n selectedUserEmail,\n selectedAppId: selectedApp?.id ?? null,\n availableUsers:\n viewScope === \"app\"\n ? []\n : members\n .map(({ email, role }) => ({ email, role }))\n .sort((a, b) => a.email.localeCompare(b.email)),\n sinceMs,\n sinceDays,\n generatedAt,\n access: {\n viewerEmail,\n orgId,\n role,\n scope: orgId ? \"organization\" : \"solo\",\n totalUsers: accessUsers,\n },\n totals: {\n costCents: numberField(totals, \"cost_x100\") / 100,\n calls: numberField(totals, \"calls\"),\n chatCalls: numberField(totals, \"chat_calls\"),\n inputTokens: numberField(totals, \"input_tokens\"),\n outputTokens: numberField(totals, \"output_tokens\"),\n cacheReadTokens: numberField(totals, \"cache_read_tokens\"),\n cacheWriteTokens: numberField(totals, \"cache_write_tokens\"),\n activeUsers: numberField(totals, \"active_users\"),\n chatThreads: chatThreadTotals.threads,\n chatMessages: chatThreadTotals.messages,\n workspaceApps: apps.filter((app) => !app.isDispatch).length,\n },\n byApp,\n byUser:\n viewScope === \"app\"\n ? []\n : [...byUserMap.values()].sort((a, b) => {\n if (b.costCents !== a.costCents) return b.costCents - a.costCents;\n return (b.lastActiveAt ?? 0) - (a.lastActiveAt ?? 0);\n }),\n byLabel,\n byModel,\n daily,\n dailyAvailable,\n monthlyByUser,\n workspaceAppCreationsByUserMonth,\n appAccess,\n recent,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"usage-metrics-store.js","sourceRoot":"","sources":["../../../src/server/lib/usage-metrics-store.ts"],"names":[],"mappings":"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","sourcesContent":["import { fail } from \"@agent-native/core/action\";\nimport {\n detectEngineFromEnv,\n detectEngineFromUserSecrets,\n getAgentEngineEntry,\n isAgentEngineSettingConfigured,\n isStoredEngineUsable,\n readDefaultAgentEngineSetting,\n registerBuiltinEngines,\n} from \"@agent-native/core/agent/engine\";\nimport { getDbExec } from \"@agent-native/core/db\";\nimport { isOrgMember } from \"@agent-native/core/org\";\nimport { readOrgMemberRole } from \"@agent-native/core/server\";\nimport { ForbiddenError } from \"@agent-native/core/sharing\";\nimport {\n builderCreditsFromCostCents,\n getUsageSummary,\n isSelfScopedUsageRead,\n MIXED_USAGE_BILLING,\n UNKNOWN_USAGE_BILLING,\n usageBillingForEngine,\n usageOrgScope,\n type UsageBillingMode,\n} from \"@agent-native/core/usage\";\n\nimport { isDispatchEnvironmentAdmin } from \"./admin-config.js\";\nimport {\n listWorkspaceApps,\n type WorkspaceAppSummary,\n} from \"./app-creation-store.js\";\nimport { currentOrgId, currentOwnerEmail } from \"./dispatch-store.js\";\n\nconst DAY_MS = 86_400_000;\n\nregisterBuiltinEngines();\n\nexport interface UsageMetricBucket {\n key: string;\n label: string;\n costCents: number;\n calls: number;\n chatCalls: number;\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n activeUsers: number;\n lastActiveAt: number | null;\n}\n\nexport interface UserUsageMetric extends UsageMetricBucket {\n ownerEmail: string;\n chatThreads: number;\n chatMessages: number;\n lastChatAt: number | null;\n topApp: string | null;\n role: string | null;\n}\n\nexport interface AppAdoptionActionMetric {\n key: string;\n label: string;\n calls: number;\n activeUsers: number;\n lastActiveAt: number | null;\n}\n\nexport interface AppAccessMetric {\n id: string;\n name: string;\n path: string;\n status: WorkspaceAppSummary[\"status\"];\n statusLabel?: string;\n isDispatch: boolean;\n accessModel: \"workspace\" | \"solo\";\n accessLabel: string;\n accessUsers: number;\n ownerEmail: string | null;\n isOwnedByViewer: boolean;\n canViewUsage: boolean;\n usersWithUsage: number;\n dailyActiveUsers: number;\n weeklyActiveUsers: number;\n usageCalls: number;\n chatCalls: number;\n costCents: number;\n lastActiveAt: number | null;\n actionMetrics: AppAdoptionActionMetric[];\n}\n\nexport interface DailyUsageMetric {\n date: string;\n costCents: number;\n calls: number;\n chatCalls: number;\n activeUsers: number;\n dailyActiveUsers: number;\n weeklyActiveUsers: number | null;\n}\n\nexport interface MonthlyUserUsageMetric {\n month: string;\n ownerEmail: string;\n costCents: number;\n credits: number | null;\n calls: number;\n chatCalls: number;\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n}\n\ntype MonthlyUsageAggregate = Omit<MonthlyUserUsageMetric, \"credits\"> & {\n builderCredits: number;\n builderEstimatedCostX100: number;\n unclassifiedCalls: number;\n unpricedBuilderCalls: number;\n};\n\nexport interface WorkspaceAppCreationMetric {\n month: string;\n ownerEmail: string;\n count: number;\n appIds: string[];\n}\n\nexport interface RecentUsageMetric {\n id: number;\n createdAt: number;\n ownerEmail: string;\n app: string;\n label: string;\n model: string;\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n costCents: number;\n prompt: string | null;\n promptSource: \"thread\" | \"thread-preview\" | \"not-captured\" | \"unavailable\";\n threadId: string | null;\n runId: string | null;\n taskId: string | null;\n sourcePlatform: string | null;\n sourceId: string | null;\n}\n\nexport type UsageMetricsScope = \"me\" | \"workspace\" | \"app\";\n\nexport interface UsageUserOption {\n email: string;\n role: string | null;\n}\n\nexport interface DispatchUsageMetrics {\n billing: UsageBillingMode;\n viewScope: UsageMetricsScope;\n selectedUserEmail: string | null;\n selectedAppId: string | null;\n availableUsers: UsageUserOption[];\n sinceMs: number;\n sinceDays: number;\n generatedAt: number;\n access: {\n viewerEmail: string;\n orgId: string | null;\n role: string | null;\n scope: \"organization\" | \"solo\";\n totalUsers: number;\n };\n totals: {\n costCents: number;\n calls: number;\n chatCalls: number;\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n activeUsers: number;\n chatThreads: number;\n chatMessages: number;\n workspaceApps: number;\n };\n byApp: UsageMetricBucket[];\n byUser: UserUsageMetric[];\n byLabel: UsageMetricBucket[];\n byModel: UsageMetricBucket[];\n daily: DailyUsageMetric[];\n dailyAvailable: boolean;\n monthlyByUser: MonthlyUserUsageMetric[];\n workspaceAppCreationsByUserMonth: WorkspaceAppCreationMetric[];\n appAccess: AppAccessMetric[];\n recent: RecentUsageMetric[];\n}\n\ninterface MemberRecord {\n email: string;\n role: string | null;\n joinedAt: number | null;\n}\n\ninterface ChatStats {\n threads: number;\n messages: number;\n lastChatAt: number | null;\n}\n\nfunction numberField(row: Record<string, unknown>, key: string): number {\n return Number(row[key] ?? 0) || 0;\n}\n\nfunction stringField(row: Record<string, unknown>, key: string): string {\n const value = row[key];\n return typeof value === \"string\" || typeof value === \"number\"\n ? String(value)\n : value == null\n ? \"\"\n : JSON.stringify(value);\n}\n\nfunction nullableNumberField(\n row: Record<string, unknown>,\n key: string,\n): number | null {\n const value = row[key];\n if (value == null) return null;\n const numberValue = Number(value);\n return Number.isFinite(numberValue) ? numberValue : null;\n}\n\nfunction nullableStringField(\n row: Record<string, unknown>,\n key: string,\n): string | null {\n const value = row[key];\n if (typeof value !== \"string\") return null;\n const trimmed = value.trim();\n return trimmed || null;\n}\n\ntype ParsedThreadData =\n | { status: \"absent\"; value: null }\n | { status: \"invalid\"; value: null }\n | { status: \"parsed\"; value: Record<string, unknown> };\n\nfunction parseJson(value: unknown): ParsedThreadData {\n if (typeof value !== \"string\" || !value.trim()) {\n return { status: \"absent\", value: null };\n }\n try {\n const parsed = JSON.parse(value);\n return parsed && typeof parsed === \"object\"\n ? { status: \"parsed\", value: parsed as Record<string, unknown> }\n : { status: \"invalid\", value: null };\n } catch {\n return { status: \"invalid\", value: null };\n }\n}\n\nfunction textFromPromptContent(value: unknown): string {\n if (typeof value === \"string\") return value.trim();\n if (!Array.isArray(value)) return \"\";\n return value\n .map((part) => {\n if (!part || typeof part !== \"object\") return \"\";\n const item = part as Record<string, unknown>;\n return item.type === \"text\" && typeof item.text === \"string\"\n ? item.text.trim()\n : \"\";\n })\n .filter(Boolean)\n .join(\"\\n\")\n .trim();\n}\n\nfunction truncatePrompt(value: string, maxLength = 360): string {\n if (value.length <= maxLength) return value;\n return `${value.slice(0, maxLength - 1).trimEnd()}…`;\n}\n\nfunction firstUserPrompt(threadData: unknown): string | null {\n const parsed = parseJson(threadData);\n if (parsed.status !== \"parsed\") return null;\n const messages = parsed.value.messages;\n if (!Array.isArray(messages)) return null;\n\n for (const entry of messages) {\n if (!entry || typeof entry !== \"object\") continue;\n const record = entry as Record<string, unknown>;\n const message =\n record.message && typeof record.message === \"object\"\n ? (record.message as Record<string, unknown>)\n : record;\n const role = typeof message.role === \"string\" ? message.role : \"\";\n if (role !== \"user\" && role !== \"human\") continue;\n const text = textFromPromptContent(message.content);\n if (text) return truncatePrompt(text);\n }\n return null;\n}\n\ninterface ThreadPromptRow {\n id?: unknown;\n preview?: unknown;\n thread_data?: unknown;\n}\n\nasync function hydrateRecentPrompts(\n rows: Array<Record<string, unknown>>,\n): Promise<RecentUsageMetric[]> {\n const threadIds = [\n ...new Set(\n rows\n .map((row) => nullableStringField(row, \"thread_id\"))\n .filter((value): value is string => Boolean(value)),\n ),\n ];\n const threads = new Map<string, ThreadPromptRow>();\n let threadQueryUnavailable = false;\n\n if (threadIds.length > 0) {\n try {\n const result = await getDbExec().execute({\n sql: `SELECT id, preview, thread_data FROM chat_threads WHERE id IN (${threadIds.map(() => \"?\").join(\", \")})`,\n args: threadIds,\n });\n for (const row of result.rows as ThreadPromptRow[]) {\n const id = typeof row.id === \"string\" ? row.id : \"\";\n if (id) threads.set(id, row);\n }\n } catch {\n threadQueryUnavailable = true;\n }\n }\n\n return rows.map((row) => {\n const threadId = nullableStringField(row, \"thread_id\");\n const thread = threadId ? threads.get(threadId) : undefined;\n const prompt = thread ? firstUserPrompt(thread.thread_data) : null;\n const preview =\n typeof thread?.preview === \"string\" ? thread.preview.trim() : \"\";\n const promptSource = prompt\n ? \"thread\"\n : preview\n ? \"thread-preview\"\n : threadQueryUnavailable && threadId\n ? \"unavailable\"\n : \"not-captured\";\n\n return {\n id: numberField(row, \"id\"),\n createdAt: numberField(row, \"created_at\"),\n ownerEmail: stringField(row, \"owner_email\"),\n app: stringField(row, \"app\") || \"unattributed\",\n label: stringField(row, \"label\") || \"chat\",\n model: stringField(row, \"model\") || \"unknown\",\n inputTokens: numberField(row, \"input_tokens\"),\n outputTokens: numberField(row, \"output_tokens\"),\n cacheReadTokens: numberField(row, \"cache_read_tokens\"),\n cacheWriteTokens: numberField(row, \"cache_write_tokens\"),\n costCents: numberField(row, \"cost_cents_x100\") / 100,\n prompt: prompt ?? (preview ? truncatePrompt(preview) : null),\n promptSource,\n threadId,\n runId: nullableStringField(row, \"run_id\"),\n taskId: nullableStringField(row, \"task_id\"),\n sourcePlatform: nullableStringField(row, \"source_platform\"),\n sourceId: nullableStringField(row, \"source_id\"),\n } satisfies RecentUsageMetric;\n });\n}\n\nfunction labelForKey(value: string): string {\n const trimmed = value.trim();\n return trimmed || \"Unattributed\";\n}\n\nfunction appUsageKey(value: string | null | undefined): string {\n const raw = (value ?? \"\").trim().toLowerCase();\n return raw || \"unattributed\";\n}\n\nfunction appOwner(app: WorkspaceAppSummary): string | null {\n const owner = app.owner?.trim();\n return owner || null;\n}\n\nasync function detectUsageEngineName(): Promise<string | null> {\n try {\n const stored = (await readDefaultAgentEngineSetting()) as {\n engine?: string;\n } | null;\n if (isAgentEngineSettingConfigured(stored)) {\n return (stored as { engine: string }).engine;\n }\n if (stored && typeof stored.engine === \"string\") {\n const entry = getAgentEngineEntry(stored.engine);\n if (entry && isStoredEngineUsable(stored, entry)) {\n return stored.engine;\n }\n }\n\n const detectedFromUser = await detectEngineFromUserSecrets();\n if (detectedFromUser) return detectedFromUser.name;\n\n return detectEngineFromEnv()?.name ?? null;\n } catch {\n return null;\n }\n}\n\nasync function queryRows<T extends Record<string, unknown>>(\n sql: string,\n args: unknown[] = [],\n): Promise<T[]> {\n try {\n const result = await getDbExec().execute({ sql, args });\n return result.rows as T[];\n } catch {\n return [];\n }\n}\n\nasync function initializeUsageMetricsTable(sinceMs: number): Promise<void> {\n try {\n await getUsageSummary({ ownerEmail: \"__dispatch_metrics_init__\", sinceMs });\n } catch {\n // Metrics should still render an empty state if usage storage is locked,\n // stale, or unavailable; each aggregate read below is already best-effort.\n }\n}\n\nasync function listOrgMembers(orgId: string | null): Promise<MemberRecord[]> {\n if (!orgId) return [];\n const result = await getDbExec().execute({\n sql: `SELECT email, role, joined_at AS joined_at FROM org_members\n WHERE org_id = ? AND federation_removal_pending_at IS NULL\n ORDER BY joined_at ASC`,\n args: [orgId],\n });\n const rows = result.rows as Record<string, unknown>[];\n return rows\n .map((row) => ({\n email: stringField(row, \"email\").trim(),\n role: stringField(row, \"role\") || null,\n joinedAt: nullableNumberField(row, \"joined_at\"),\n }))\n .filter((member) => member.email);\n}\n\nfunction usageScope(\n sinceMs: number,\n memberEmails: string[],\n): { where: string; args: unknown[] } {\n if (memberEmails.length === 0) {\n return { where: \"created_at >= ?\", args: [sinceMs] };\n }\n const placeholders = memberEmails.map(() => \"?\").join(\", \");\n return {\n where: `created_at >= ? AND LOWER(owner_email) IN (${placeholders})`,\n args: [sinceMs, ...memberEmails.map((email) => email.toLowerCase())],\n };\n}\n\nfunction withOrgUsageScope(\n scope: { where: string; args: unknown[] },\n orgId: string | null,\n selfScoped: boolean,\n): { where: string; args: unknown[] } {\n const org = usageOrgScope({ orgId, selfScoped });\n return {\n where: `${scope.where} AND ${org.where || \"org_id IS NULL\"}`,\n args: [...scope.args, ...org.args],\n };\n}\n\nfunction threadScope(\n sinceMs: number,\n memberEmails: string[],\n): { where: string; args: unknown[] } {\n if (memberEmails.length === 0) {\n return { where: \"updated_at >= ?\", args: [sinceMs] };\n }\n const placeholders = memberEmails.map(() => \"?\").join(\", \");\n return {\n where: `updated_at >= ? AND LOWER(owner_email) IN (${placeholders})`,\n args: [sinceMs, ...memberEmails.map((email) => email.toLowerCase())],\n };\n}\n\nfunction ownerScope(\n sinceMs: number,\n ownerEmail: string,\n): {\n where: string;\n args: unknown[];\n} {\n return {\n where: \"created_at >= ? AND LOWER(owner_email) = ?\",\n args: [sinceMs, ownerEmail.toLowerCase()],\n };\n}\n\nfunction ownerThreadScope(\n sinceMs: number,\n ownerEmail: string,\n): {\n where: string;\n args: unknown[];\n} {\n return {\n where: \"updated_at >= ? AND LOWER(owner_email) = ?\",\n args: [sinceMs, ownerEmail.toLowerCase()],\n };\n}\n\nfunction appUsageScope(\n sinceMs: number,\n memberEmails: string[],\n appId: string,\n orgId: string | null,\n viewerEmail: string,\n): { where: string; args: unknown[] } {\n const scope = withOrgUsageScope(\n usageScope(sinceMs, memberEmails),\n orgId,\n isSelfScopedUsageRead(memberEmails, viewerEmail),\n );\n return {\n where: `${scope.where} AND LOWER(app) = ?`,\n args: [...scope.args, appUsageKey(appId)],\n };\n}\n\nfunction workspaceAppCreationScope(\n sinceMs: number,\n orgId: string | null,\n memberEmails: string[],\n): { where: string; args: unknown[] } {\n const filters = [\"created_at >= ?\", \"action = ?\"];\n const args: unknown[] = [sinceMs, \"workspace-app.pending\"];\n\n if (orgId) {\n filters.push(\"org_id = ?\");\n args.push(orgId);\n }\n if (memberEmails.length > 0) {\n filters.push(\n `LOWER(owner_email) IN (${memberEmails.map(() => \"?\").join(\", \")})`,\n );\n args.push(...memberEmails.map((email) => email.toLowerCase()));\n }\n\n return { where: filters.join(\" AND \"), args };\n}\n\nfunction bucketFromRow(row: Record<string, unknown>): UsageMetricBucket {\n const key = stringField(row, \"k\");\n return {\n key,\n label: labelForKey(key),\n costCents: numberField(row, \"cost_x100\") / 100,\n calls: numberField(row, \"calls\"),\n chatCalls: numberField(row, \"chat_calls\"),\n inputTokens: numberField(row, \"input_tokens\"),\n outputTokens: numberField(row, \"output_tokens\"),\n cacheReadTokens: numberField(row, \"cache_read_tokens\"),\n cacheWriteTokens: numberField(row, \"cache_write_tokens\"),\n activeUsers: numberField(row, \"active_users\"),\n lastActiveAt: nullableNumberField(row, \"last_active_at\"),\n };\n}\n\nasync function usageBuckets(\n columnExpression: string,\n where: string,\n args: unknown[],\n limit: number,\n): Promise<UsageMetricBucket[]> {\n const rows = await queryRows<Record<string, unknown>>(\n `SELECT ${columnExpression} AS k,\n COALESCE(SUM(cost_cents_x100), 0) AS cost_x100,\n COUNT(*) AS calls,\n SUM(CASE WHEN label = 'chat' THEN 1 ELSE 0 END) AS chat_calls,\n COALESCE(SUM(input_tokens), 0) AS input_tokens,\n COALESCE(SUM(output_tokens), 0) AS output_tokens,\n COALESCE(SUM(cache_read_tokens), 0) AS cache_read_tokens,\n COALESCE(SUM(cache_write_tokens), 0) AS cache_write_tokens,\n COUNT(DISTINCT owner_email) AS active_users,\n MAX(created_at) AS last_active_at\n FROM token_usage\n WHERE ${where}\n GROUP BY ${columnExpression}\n ORDER BY cost_x100 DESC\n LIMIT ?`,\n [...args, limit],\n );\n return rows.map(bucketFromRow);\n}\n\nconst adoptionActionKeySql = `CASE\n WHEN LOWER(TRIM(label)) = 'chat' THEN 'chat'\n WHEN LOWER(TRIM(label)) IN ('automation', 'manual-automation')\n OR LOWER(TRIM(label)) LIKE 'automation:%'\n OR LOWER(TRIM(label)) LIKE 'manual-automation:%'\n OR LOWER(TRIM(label)) LIKE 'recurring-job:%' THEN 'automation'\n WHEN LOWER(TRIM(label)) = 'custom-agent'\n OR LOWER(TRIM(label)) LIKE 'custom-agent:%' THEN 'custom-agent'\n ELSE 'other'\nEND`;\n\ninterface AppAdoptionAggregate {\n calls: number;\n costCents: number;\n chatCalls: number;\n activeUsers: number;\n dailyActiveUsers: number;\n weeklyActiveUsers: number;\n lastActiveAt: number | null;\n actions: Map<\n string,\n { calls: number; activeUsers: number; lastActiveAt: number | null }\n >;\n}\n\nfunction emptyAppAdoptionAggregate(): AppAdoptionAggregate {\n return {\n calls: 0,\n costCents: 0,\n chatCalls: 0,\n activeUsers: 0,\n dailyActiveUsers: 0,\n weeklyActiveUsers: 0,\n lastActiveAt: null,\n actions: new Map(),\n };\n}\n\nasync function loadAppAdoption(\n usage: { where: string; args: unknown[] },\n adoptionUsage: { where: string; args: unknown[] },\n generatedAt: number,\n): Promise<Map<string, AppAdoptionAggregate>> {\n const appExpression = \"COALESCE(NULLIF(app, ''), 'unattributed')\";\n const [selectedRows, adoptionRows, actionRows] = await Promise.all([\n queryRows<Record<string, unknown>>(\n `SELECT ${appExpression} AS app,\n COALESCE(SUM(cost_cents_x100), 0) AS cost_x100,\n COUNT(*) AS calls,\n SUM(CASE WHEN label = 'chat' THEN 1 ELSE 0 END) AS chat_calls,\n COUNT(DISTINCT owner_email) AS active_users,\n MAX(created_at) AS last_active_at\n FROM token_usage\n WHERE ${usage.where}\n GROUP BY ${appExpression}`,\n usage.args,\n ),\n queryRows<Record<string, unknown>>(\n `SELECT ${appExpression} AS app,\n COUNT(DISTINCT CASE WHEN created_at >= ? THEN owner_email END) AS daily_active_users,\n COUNT(DISTINCT CASE WHEN created_at >= ? THEN owner_email END) AS weekly_active_users\n FROM token_usage\n WHERE ${adoptionUsage.where}\n GROUP BY ${appExpression}`,\n [generatedAt - DAY_MS, generatedAt - 7 * DAY_MS, ...adoptionUsage.args],\n ),\n queryRows<Record<string, unknown>>(\n `SELECT ${appExpression} AS app,\n ${adoptionActionKeySql} AS action_key,\n COUNT(*) AS calls,\n COUNT(DISTINCT owner_email) AS active_users,\n MAX(created_at) AS last_active_at\n FROM token_usage\n WHERE ${usage.where}\n GROUP BY ${appExpression}, ${adoptionActionKeySql}`,\n usage.args,\n ),\n ]);\n\n const adoptionByApp = new Map<string, AppAdoptionAggregate>();\n const getAdoption = (app: string): AppAdoptionAggregate => {\n const key = appUsageKey(app);\n const existing = adoptionByApp.get(key);\n if (existing) return existing;\n const created = emptyAppAdoptionAggregate();\n adoptionByApp.set(key, created);\n return created;\n };\n\n for (const row of selectedRows) {\n const adoption = getAdoption(stringField(row, \"app\"));\n adoption.calls = numberField(row, \"calls\");\n adoption.costCents = numberField(row, \"cost_x100\") / 100;\n adoption.chatCalls = numberField(row, \"chat_calls\");\n adoption.activeUsers = numberField(row, \"active_users\");\n adoption.lastActiveAt = nullableNumberField(row, \"last_active_at\");\n }\n for (const row of adoptionRows) {\n const adoption = getAdoption(stringField(row, \"app\"));\n adoption.dailyActiveUsers = numberField(row, \"daily_active_users\");\n adoption.weeklyActiveUsers = numberField(row, \"weekly_active_users\");\n }\n for (const row of actionRows) {\n const adoption = getAdoption(stringField(row, \"app\"));\n adoption.actions.set(stringField(row, \"action_key\"), {\n calls: numberField(row, \"calls\"),\n activeUsers: numberField(row, \"active_users\"),\n lastActiveAt: nullableNumberField(row, \"last_active_at\"),\n });\n }\n\n return adoptionByApp;\n}\n\nasync function loadDailyAndMonthlyUsage(usage: {\n where: string;\n args: unknown[];\n}): Promise<{\n daily: DailyUsageMetric[];\n dailyAvailable: boolean;\n monthlyByUser: MonthlyUsageAggregate[];\n usersByDay: Map<string, Set<string>>;\n}> {\n const dayBucketExpression = `CAST(created_at / ${DAY_MS} AS INTEGER)`;\n let result;\n try {\n result = await getDbExec().execute({\n sql: `SELECT ${dayBucketExpression} AS day_bucket,\n owner_email,\n COALESCE(SUM(cost_cents_x100), 0) AS cost_x100,\n COALESCE(SUM(builder_credits_used), 0) AS builder_credits,\n COALESCE(SUM(CASE\n WHEN engine_name = 'builder' AND builder_credits_used IS NULL\n THEN cost_cents_x100 ELSE 0\n END), 0) AS builder_estimated_cost_x100,\n COUNT(*) FILTER (\n WHERE NULLIF(engine_name, '') IS NULL AND builder_credits_used IS NULL\n ) AS unclassified_calls,\n COUNT(*) FILTER (\n WHERE engine_name = 'builder' AND builder_credits_used IS NULL\n AND cost_source = 'unavailable' AND cost_cents_x100 <= 0\n ) AS unpriced_builder_calls,\n COUNT(*) AS calls,\n SUM(CASE WHEN label = 'chat' THEN 1 ELSE 0 END) AS chat_calls,\n COALESCE(SUM(input_tokens), 0) AS input_tokens,\n COALESCE(SUM(output_tokens), 0) AS output_tokens,\n COALESCE(SUM(cache_read_tokens), 0) AS cache_read_tokens,\n COALESCE(SUM(cache_write_tokens), 0) AS cache_write_tokens\n FROM token_usage\n WHERE ${usage.where}\n GROUP BY ${dayBucketExpression}, owner_email\n ORDER BY ${dayBucketExpression} ASC`,\n args: usage.args,\n });\n } catch {\n return {\n daily: [],\n dailyAvailable: false,\n monthlyByUser: [],\n usersByDay: new Map(),\n };\n }\n const rows = result.rows as Record<string, unknown>[];\n const dailyMap = new Map<\n string,\n { costX100: number; calls: number; chatCalls: number; users: Set<string> }\n >();\n const monthlyByUserMap = new Map<string, MonthlyUsageAggregate>();\n const usersByDay = new Map<string, Set<string>>();\n\n for (const row of rows) {\n const date = new Date(\n numberField(row, \"day_bucket\") * DAY_MS,\n ).toISOString();\n const day = date.slice(0, 10);\n const ownerEmail = stringField(row, \"owner_email\");\n const daily = dailyMap.get(day) ?? {\n costX100: 0,\n calls: 0,\n chatCalls: 0,\n users: new Set<string>(),\n };\n daily.costX100 += numberField(row, \"cost_x100\");\n daily.calls += numberField(row, \"calls\");\n daily.chatCalls += numberField(row, \"chat_calls\");\n daily.users.add(ownerEmail.toLowerCase());\n dailyMap.set(day, daily);\n const users = usersByDay.get(day) ?? new Set<string>();\n users.add(ownerEmail.toLowerCase());\n usersByDay.set(day, users);\n\n const month = day.slice(0, 7);\n const monthlyKey = `${ownerEmail}\\u0000${month}`;\n const monthly = monthlyByUserMap.get(monthlyKey) ?? {\n month,\n ownerEmail,\n costCents: 0,\n builderCredits: 0,\n builderEstimatedCostX100: 0,\n unclassifiedCalls: 0,\n unpricedBuilderCalls: 0,\n calls: 0,\n chatCalls: 0,\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n cacheWriteTokens: 0,\n };\n monthly.costCents += numberField(row, \"cost_x100\") / 100;\n monthly.builderCredits += numberField(row, \"builder_credits\");\n monthly.builderEstimatedCostX100 += numberField(\n row,\n \"builder_estimated_cost_x100\",\n );\n monthly.unclassifiedCalls += numberField(row, \"unclassified_calls\");\n monthly.unpricedBuilderCalls += numberField(row, \"unpriced_builder_calls\");\n monthly.calls += numberField(row, \"calls\");\n monthly.chatCalls += numberField(row, \"chat_calls\");\n monthly.inputTokens += numberField(row, \"input_tokens\");\n monthly.outputTokens += numberField(row, \"output_tokens\");\n monthly.cacheReadTokens += numberField(row, \"cache_read_tokens\");\n monthly.cacheWriteTokens += numberField(row, \"cache_write_tokens\");\n monthlyByUserMap.set(monthlyKey, monthly);\n }\n\n return {\n daily: [...dailyMap.entries()]\n .map(([date, value]) => ({\n date,\n costCents: value.costX100 / 100,\n calls: value.calls,\n chatCalls: value.chatCalls,\n activeUsers: value.users.size,\n dailyActiveUsers: value.users.size,\n weeklyActiveUsers: null,\n }))\n .sort((a, b) => a.date.localeCompare(b.date)),\n dailyAvailable: true,\n monthlyByUser: [...monthlyByUserMap.values()].sort(\n (a, b) =>\n a.month.localeCompare(b.month) ||\n a.ownerEmail.localeCompare(b.ownerEmail),\n ),\n usersByDay,\n };\n}\n\nasync function loadWeeklyActiveUsers(\n usage: { where: string; args: unknown[] },\n visibleUsersByDay: Map<string, Set<string>>,\n startDate: string,\n endDate: string,\n): Promise<Map<string, number> | null> {\n const dayBucketExpression = `CAST(created_at / ${DAY_MS} AS INTEGER)`;\n let result;\n try {\n result = await getDbExec().execute({\n sql: `SELECT ${dayBucketExpression} AS day_bucket, owner_email\n FROM token_usage\n WHERE ${usage.where}\n GROUP BY ${dayBucketExpression}, owner_email\n ORDER BY ${dayBucketExpression} ASC`,\n args: usage.args,\n });\n // coercion-ok: null distinguishes an unavailable optional trend from empty activity.\n } catch {\n return null;\n }\n const rows = result.rows as Record<string, unknown>[];\n const usersByDay = new Map(\n [...visibleUsersByDay.entries()].map(([day, users]) => [\n day,\n new Set(users),\n ]),\n );\n for (const row of rows) {\n const day = new Date(numberField(row, \"day_bucket\") * DAY_MS)\n .toISOString()\n .slice(0, 10);\n const users = usersByDay.get(day) ?? new Set<string>();\n users.add(stringField(row, \"owner_email\").toLowerCase());\n usersByDay.set(day, users);\n }\n\n const activityByDay = new Map<string, number>();\n const firstDay = Date.parse(`${startDate}T00:00:00Z`);\n const lastDay = Date.parse(`${endDate}T00:00:00Z`);\n for (let dayStart = firstDay; dayStart <= lastDay; dayStart += DAY_MS) {\n const day = new Date(dayStart).toISOString().slice(0, 10);\n const weeklyUsers = new Set<string>();\n for (\n let previousDayStart = dayStart;\n previousDayStart >= dayStart - 6 * DAY_MS;\n previousDayStart -= DAY_MS\n ) {\n const previousDay = new Date(previousDayStart).toISOString().slice(0, 10);\n for (const user of usersByDay.get(previousDay) ?? []) {\n weeklyUsers.add(user);\n }\n }\n activityByDay.set(day, weeklyUsers.size);\n }\n return activityByDay;\n}\n\nasync function loadChatStats(\n where: string,\n args: unknown[],\n): Promise<Map<string, ChatStats>> {\n const rows = await queryRows<Record<string, unknown>>(\n `SELECT owner_email AS owner_email,\n COUNT(*) AS threads,\n COALESCE(SUM(message_count), 0) AS messages,\n MAX(updated_at) AS last_chat_at\n FROM chat_threads\n WHERE ${where}\n GROUP BY owner_email`,\n args,\n );\n return new Map(\n rows.map((row) => [\n stringField(row, \"owner_email\"),\n {\n threads: numberField(row, \"threads\"),\n messages: numberField(row, \"messages\"),\n lastChatAt: nullableNumberField(row, \"last_chat_at\"),\n },\n ]),\n );\n}\n\nasync function assertCanViewMetrics(viewScope: UsageMetricsScope): Promise<{\n viewerEmail: string;\n orgId: string | null;\n role: string | null;\n}> {\n const viewerEmail = currentOwnerEmail();\n const orgId = currentOrgId();\n const role = orgId ? await readOrgMemberRole(orgId, viewerEmail) : null;\n if (\n viewScope === \"me\" ||\n isDispatchEnvironmentAdmin(viewerEmail) ||\n role === \"owner\" ||\n role === \"admin\"\n ) {\n return { viewerEmail, orgId, role };\n }\n if (!orgId) {\n return { viewerEmail, orgId, role };\n }\n throw new ForbiddenError(\n \"Only organization owners and admins can view workspace usage metrics.\",\n );\n}\n\nfunction failUserNotOrgMember(email: string): never {\n fail(\n `${email} is not a member of this organization, so list-dispatch-usage-metrics has no data on them. For a customer's or account's usage or credits, use this app's own customer or billing actions if it has any, or find the app that owns that data with describe-workspace-apps query=\"<what you need>\" and delegate with call-agent.`,\n { errorCode: \"usage_user_not_org_member\", statusCode: 404 },\n );\n}\n\nexport async function listDispatchUsageMetrics(input: {\n sinceDays?: number;\n scope?: UsageMetricsScope;\n userEmail?: string | null;\n appId?: string | null;\n}): Promise<DispatchUsageMetrics> {\n const viewScope: UsageMetricsScope =\n input.scope === \"me\" ? \"me\" : input.scope === \"app\" ? \"app\" : \"workspace\";\n // Another person's usage: unauthorized callers get one answer whether or not\n // the email is a member, so the lookup cannot probe the roster; authorized\n // callers asking about an outside email are pointed at the owning app.\n const requestedEmail =\n viewScope === \"workspace\" ? input.userEmail?.trim() || null : null;\n const callerEmail = currentOwnerEmail();\n const callerOrgId = currentOrgId();\n if (\n requestedEmail &&\n callerOrgId &&\n requestedEmail.toLowerCase() !== callerEmail.toLowerCase()\n ) {\n const callerRole = await readOrgMemberRole(callerOrgId, callerEmail);\n if (\n !isDispatchEnvironmentAdmin(callerEmail) &&\n callerRole !== \"owner\" &&\n callerRole !== \"admin\"\n ) {\n fail(\n `list-dispatch-usage-metrics cannot answer this. For a teammate in this organization, only owners and admins can look up their usage. For a customer or other external user, list-dispatch-usage-metrics has no data: use this app's own customer or billing actions if it has any, or find the app that owns that data with describe-workspace-apps query=\"<what you need>\" and delegate with call-agent.`,\n { errorCode: \"usage_user_lookup_forbidden\", statusCode: 403 },\n );\n }\n if (!(await isOrgMember(callerOrgId, requestedEmail))) {\n failUserNotOrgMember(requestedEmail);\n }\n }\n const { viewerEmail, orgId, role } = await assertCanViewMetrics(\n viewScope === \"app\" ? \"me\" : viewScope,\n );\n const sinceDays = Math.max(1, Math.min(365, input.sinceDays ?? 30));\n const generatedAt = Date.now();\n const sinceMs = generatedAt - sinceDays * DAY_MS;\n const apps = await listWorkspaceApps({ includeAgentCards: false });\n const requestedAppId = input.appId?.trim() || null;\n const selectedApp =\n viewScope === \"app\" && requestedAppId\n ? apps.find((app) => app.id === requestedAppId)\n : null;\n if (viewScope === \"app\" && !requestedAppId) {\n throw new Error(\"App metrics require an appId.\");\n }\n if (viewScope === \"app\" && !selectedApp) {\n throw new ForbiddenError(\n \"You do not have access to metrics for this workspace app.\",\n );\n }\n const selectedAppOwner = selectedApp ? appOwner(selectedApp) : null;\n const isMetricsAdmin = Boolean(\n isDispatchEnvironmentAdmin(viewerEmail) ||\n role === \"owner\" ||\n role === \"admin\",\n );\n if (\n viewScope === \"app\" &&\n !isMetricsAdmin &&\n selectedAppOwner?.toLowerCase() !== viewerEmail.toLowerCase()\n ) {\n throw new ForbiddenError(\n \"Only the app owner or an organization owner or admin can view app metrics.\",\n );\n }\n\n await initializeUsageMetricsTable(sinceMs);\n\n const rawMembers =\n viewScope === \"me\"\n ? [{ email: viewerEmail, role, joinedAt: null }]\n : orgId\n ? await listOrgMembers(orgId)\n : [{ email: viewerEmail, role: null, joinedAt: null }];\n const members =\n viewScope !== \"me\" && orgId && rawMembers.length === 0\n ? [{ email: viewerEmail, role, joinedAt: null }]\n : rawMembers;\n const requestedUserEmail =\n viewScope === \"app\" ? null : input.userEmail?.trim() || null;\n const selectedUserEmail =\n viewScope === \"me\"\n ? viewerEmail\n : requestedUserEmail\n ? (members.find(\n (member) =>\n member.email.toLowerCase() === requestedUserEmail.toLowerCase(),\n )?.email ?? null)\n : null;\n if (viewScope === \"workspace\" && requestedUserEmail && !selectedUserEmail) {\n failUserNotOrgMember(requestedUserEmail);\n }\n const memberEmails = selectedUserEmail\n ? [selectedUserEmail]\n : members.map((member) => member.email);\n const selfScopedUsage = isSelfScopedUsageRead(memberEmails, viewerEmail);\n const memberByEmail = new Map(\n members.map((member) => [member.email.toLowerCase(), member]),\n );\n const usage =\n viewScope === \"app\" && selectedApp\n ? appUsageScope(sinceMs, memberEmails, selectedApp.id, orgId, viewerEmail)\n : withOrgUsageScope(\n selectedUserEmail\n ? ownerScope(sinceMs, selectedUserEmail)\n : usageScope(sinceMs, memberEmails),\n orgId,\n selfScopedUsage,\n );\n const visibleSinceMs = Math.floor(sinceMs / DAY_MS) * DAY_MS;\n const adoptionSinceMs = Math.min(\n visibleSinceMs - 6 * DAY_MS,\n generatedAt - 7 * DAY_MS,\n );\n const adoptionUsage =\n viewScope === \"app\" && selectedApp\n ? appUsageScope(\n adoptionSinceMs,\n memberEmails,\n selectedApp.id,\n orgId,\n viewerEmail,\n )\n : withOrgUsageScope(\n selectedUserEmail\n ? ownerScope(adoptionSinceMs, selectedUserEmail)\n : usageScope(adoptionSinceMs, memberEmails),\n orgId,\n selfScopedUsage,\n );\n const weeklyLookbackUsage = {\n where: `${adoptionUsage.where} AND created_at < ?`,\n args: [...adoptionUsage.args, sinceMs],\n };\n const threads = selectedUserEmail\n ? ownerThreadScope(sinceMs, selectedUserEmail)\n : threadScope(sinceMs, memberEmails);\n\n const workspaceAppCreation = workspaceAppCreationScope(\n sinceMs,\n orgId,\n memberEmails,\n );\n\n const [\n totalsRows,\n byApp,\n byUserBase,\n byLabel,\n byModel,\n chatStats,\n workspaceAppCreationRows,\n ] = await Promise.all([\n queryRows<Record<string, unknown>>(\n `SELECT\n COALESCE(SUM(cost_cents_x100), 0) AS cost_x100,\n COUNT(*) AS calls,\n SUM(CASE WHEN label = 'chat' THEN 1 ELSE 0 END) AS chat_calls,\n COALESCE(SUM(input_tokens), 0) AS input_tokens,\n COALESCE(SUM(output_tokens), 0) AS output_tokens,\n COALESCE(SUM(cache_read_tokens), 0) AS cache_read_tokens,\n COALESCE(SUM(cache_write_tokens), 0) AS cache_write_tokens,\n COUNT(*) FILTER (WHERE engine_name = 'builder' OR builder_credits_used IS NOT NULL) AS builder_calls,\n COUNT(*) FILTER (WHERE NULLIF(engine_name, '') IS NOT NULL AND NULLIF(engine_name, '') <> 'builder' AND builder_credits_used IS NULL) AS provider_calls,\n COUNT(*) FILTER (WHERE NULLIF(engine_name, '') IS NULL AND builder_credits_used IS NULL) AS unknown_calls,\n COUNT(DISTINCT owner_email) AS active_users\n FROM token_usage\n WHERE ${usage.where}`,\n usage.args,\n ),\n usageBuckets(\n `COALESCE(NULLIF(app, ''), 'unattributed')`,\n usage.where,\n usage.args,\n 20,\n ),\n viewScope === \"app\"\n ? Promise.resolve([] as UsageMetricBucket[])\n : usageBuckets(\"owner_email\", usage.where, usage.args, 50),\n viewScope === \"app\"\n ? Promise.resolve([] as UsageMetricBucket[])\n : usageBuckets(\n `COALESCE(NULLIF(label, ''), 'chat')`,\n usage.where,\n usage.args,\n 20,\n ),\n usageBuckets(\n `COALESCE(NULLIF(model, ''), 'unknown')`,\n usage.where,\n usage.args,\n 20,\n ),\n viewScope === \"app\"\n ? Promise.resolve(new Map<string, ChatStats>())\n : loadChatStats(threads.where, threads.args),\n viewScope === \"app\"\n ? Promise.resolve([])\n : queryRows<Record<string, unknown>>(\n `SELECT owner_email, actor, target_id, created_at\n FROM dispatch_audit_events\n WHERE ${workspaceAppCreation.where}\n ORDER BY created_at ASC`,\n workspaceAppCreation.args,\n ),\n ]);\n\n const totals = totalsRows[0] ?? {};\n const builderCalls = numberField(totals, \"builder_calls\");\n const providerCalls = numberField(totals, \"provider_calls\");\n const unknownCalls = numberField(totals, \"unknown_calls\");\n const billing = unknownCalls\n ? UNKNOWN_USAGE_BILLING\n : builderCalls > 0 && providerCalls > 0\n ? MIXED_USAGE_BILLING\n : builderCalls > 0\n ? usageBillingForEngine(\"builder\")\n : providerCalls > 0\n ? usageBillingForEngine(\"external\")\n : usageBillingForEngine(await detectUsageEngineName());\n\n const topAppRows =\n viewScope === \"app\"\n ? []\n : await queryRows<Record<string, unknown>>(\n `SELECT owner_email AS owner_email,\n COALESCE(NULLIF(app, ''), 'unattributed') AS app,\n COALESCE(SUM(cost_cents_x100), 0) AS cost_x100\n FROM token_usage\n WHERE ${usage.where}\n GROUP BY owner_email, COALESCE(NULLIF(app, ''), 'unattributed')\n ORDER BY owner_email ASC, cost_x100 DESC`,\n usage.args,\n );\n const topAppByUser = new Map<string, string>();\n for (const row of topAppRows) {\n const email = stringField(row, \"owner_email\");\n if (!topAppByUser.has(email)) {\n topAppByUser.set(email, stringField(row, \"app\"));\n }\n }\n\n const byUserMap = new Map<string, UserUsageMetric>();\n for (const bucket of byUserBase) {\n const ownerEmail = bucket.key;\n const stats = chatStats.get(ownerEmail) ?? {\n threads: 0,\n messages: 0,\n lastChatAt: null,\n };\n const member = memberByEmail.get(ownerEmail.toLowerCase());\n byUserMap.set(ownerEmail, {\n ...bucket,\n ownerEmail,\n chatThreads: stats.threads,\n chatMessages: stats.messages,\n lastChatAt: stats.lastChatAt,\n topApp: topAppByUser.get(ownerEmail) ?? null,\n role: member?.role ?? null,\n });\n }\n for (const [ownerEmail, stats] of chatStats) {\n if (byUserMap.has(ownerEmail)) continue;\n const member = memberByEmail.get(ownerEmail.toLowerCase());\n byUserMap.set(ownerEmail, {\n key: ownerEmail,\n label: ownerEmail,\n ownerEmail,\n costCents: 0,\n calls: 0,\n chatCalls: 0,\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n cacheWriteTokens: 0,\n activeUsers: 1,\n lastActiveAt: stats.lastChatAt,\n chatThreads: stats.threads,\n chatMessages: stats.messages,\n lastChatAt: stats.lastChatAt,\n topApp: null,\n role: member?.role ?? null,\n });\n }\n\n const [\n {\n daily: usageDaily,\n dailyAvailable,\n monthlyByUser: monthlyUsage,\n usersByDay,\n },\n appAdoptionMap,\n ] = await Promise.all([\n loadDailyAndMonthlyUsage(usage),\n loadAppAdoption(usage, adoptionUsage, generatedAt),\n ]);\n const usageByDate = new Map(usageDaily.map((row) => [row.date, row]));\n const weeklyActiveUsers = dailyAvailable\n ? await loadWeeklyActiveUsers(\n weeklyLookbackUsage,\n usersByDay,\n new Date(visibleSinceMs).toISOString().slice(0, 10),\n new Date(generatedAt).toISOString().slice(0, 10),\n )\n : null;\n const daily = !dailyAvailable\n ? []\n : weeklyActiveUsers\n ? [...weeklyActiveUsers.entries()].map(([date, weeklyUsers]) => ({\n ...(usageByDate.get(date) ?? {\n date,\n costCents: 0,\n calls: 0,\n chatCalls: 0,\n activeUsers: 0,\n dailyActiveUsers: 0,\n weeklyActiveUsers: 0,\n }),\n weeklyActiveUsers: weeklyUsers,\n }))\n : usageDaily.map((row) => ({ ...row, weeklyActiveUsers: null }));\n\n const monthlyByUser =\n viewScope === \"app\"\n ? []\n : monthlyUsage.map(\n ({\n builderCredits,\n builderEstimatedCostX100,\n unclassifiedCalls,\n unpricedBuilderCalls,\n ...row\n }) => ({\n ...row,\n credits:\n billing.unit === \"usd\" ||\n billing.unit === \"unknown\" ||\n unclassifiedCalls > 0 ||\n unpricedBuilderCalls > 0\n ? null\n : builderCredits +\n builderCreditsFromCostCents(builderEstimatedCostX100 / 100),\n }),\n );\n\n const workspaceAppCreationMap = new Map<\n string,\n { month: string; ownerEmail: string; count: number; appIds: Set<string> }\n >();\n for (const row of workspaceAppCreationRows) {\n const month = new Date(numberField(row, \"created_at\"))\n .toISOString()\n .slice(0, 7);\n const ownerEmail =\n stringField(row, \"owner_email\") || stringField(row, \"actor\");\n if (!ownerEmail) continue;\n const key = `${ownerEmail}\\u0000${month}`;\n const current = workspaceAppCreationMap.get(key) ?? {\n month,\n ownerEmail,\n count: 0,\n appIds: new Set<string>(),\n };\n current.count += 1;\n const appId = stringField(row, \"target_id\");\n if (appId) current.appIds.add(appId);\n workspaceAppCreationMap.set(key, current);\n }\n const workspaceAppCreationsByUserMonth = [...workspaceAppCreationMap.values()]\n .map(({ appIds, ...row }) => ({\n ...row,\n appIds: [...appIds].sort(),\n }))\n .sort(\n (a, b) =>\n a.month.localeCompare(b.month) ||\n a.ownerEmail.localeCompare(b.ownerEmail),\n );\n\n const recentRows =\n viewScope === \"app\"\n ? []\n : await queryRows<Record<string, unknown>>(\n `SELECT id, created_at, owner_email, app, label, model,\n input_tokens, output_tokens, cache_read_tokens, cache_write_tokens,\n cost_cents_x100, thread_id, run_id, task_id, source_platform, source_id\n FROM token_usage\n WHERE ${usage.where}\n ORDER BY created_at DESC\n LIMIT 50`,\n usage.args,\n );\n const recent =\n viewScope === \"app\" ? [] : await hydrateRecentPrompts(recentRows);\n\n const appUsageByKey = new Map(\n byApp.map((bucket) => [appUsageKey(bucket.key), bucket]),\n );\n const accessUsers = members.length || byUserMap.size;\n const accessModel =\n viewScope === \"me\" ? \"solo\" : orgId ? \"workspace\" : \"solo\";\n const accessLabel =\n viewScope === \"me\"\n ? \"Your account\"\n : orgId\n ? \"Workspace members\"\n : \"Signed-in users\";\n const appRows = selectedApp ? [selectedApp] : apps;\n const appAccess = appRows.map((app) => {\n const usageBucket = appUsageByKey.get(appUsageKey(app.id));\n const adoption = appAdoptionMap.get(appUsageKey(app.id));\n const ownerEmail = appOwner(app);\n const isOwnedByViewer =\n ownerEmail?.toLowerCase() === viewerEmail.toLowerCase();\n const canViewUsage = isMetricsAdmin || isOwnedByViewer;\n const visibleUsageBucket = canViewUsage ? usageBucket : undefined;\n const visibleAdoption = canViewUsage ? adoption : undefined;\n return {\n id: app.id,\n name: app.name,\n path: app.path,\n status: app.status,\n statusLabel: app.statusLabel,\n isDispatch: app.isDispatch,\n accessModel,\n accessLabel,\n accessUsers,\n ownerEmail: canViewUsage ? ownerEmail : null,\n isOwnedByViewer,\n canViewUsage,\n usersWithUsage:\n visibleAdoption?.activeUsers ?? visibleUsageBucket?.activeUsers ?? 0,\n dailyActiveUsers: visibleAdoption?.dailyActiveUsers ?? 0,\n weeklyActiveUsers: visibleAdoption?.weeklyActiveUsers ?? 0,\n usageCalls: visibleAdoption?.calls ?? visibleUsageBucket?.calls ?? 0,\n chatCalls:\n visibleAdoption?.chatCalls ?? visibleUsageBucket?.chatCalls ?? 0,\n costCents:\n visibleAdoption?.costCents ?? visibleUsageBucket?.costCents ?? 0,\n lastActiveAt:\n visibleAdoption?.lastActiveAt ??\n visibleUsageBucket?.lastActiveAt ??\n null,\n actionMetrics: visibleAdoption\n ? [...visibleAdoption.actions.entries()]\n .map(([key, action]) => ({\n key,\n label: key,\n calls: action.calls,\n activeUsers: action.activeUsers,\n lastActiveAt: action.lastActiveAt,\n }))\n .sort((a, b) => b.calls - a.calls)\n : [],\n } satisfies AppAccessMetric;\n });\n\n const chatThreadTotals = [...chatStats.values()].reduce(\n (acc, value) => ({\n threads: acc.threads + value.threads,\n messages: acc.messages + value.messages,\n }),\n { threads: 0, messages: 0 },\n );\n\n return {\n billing,\n viewScope,\n selectedUserEmail,\n selectedAppId: selectedApp?.id ?? null,\n availableUsers:\n viewScope === \"app\"\n ? []\n : members\n .map(({ email, role }) => ({ email, role }))\n .sort((a, b) => a.email.localeCompare(b.email)),\n sinceMs,\n sinceDays,\n generatedAt,\n access: {\n viewerEmail,\n orgId,\n role,\n scope: orgId ? \"organization\" : \"solo\",\n totalUsers: accessUsers,\n },\n totals: {\n costCents: numberField(totals, \"cost_x100\") / 100,\n calls: numberField(totals, \"calls\"),\n chatCalls: numberField(totals, \"chat_calls\"),\n inputTokens: numberField(totals, \"input_tokens\"),\n outputTokens: numberField(totals, \"output_tokens\"),\n cacheReadTokens: numberField(totals, \"cache_read_tokens\"),\n cacheWriteTokens: numberField(totals, \"cache_write_tokens\"),\n activeUsers: numberField(totals, \"active_users\"),\n chatThreads: chatThreadTotals.threads,\n chatMessages: chatThreadTotals.messages,\n workspaceApps: apps.filter((app) => !app.isDispatch).length,\n },\n byApp,\n byUser:\n viewScope === \"app\"\n ? []\n : [...byUserMap.values()].sort((a, b) => {\n if (b.costCents !== a.costCents) return b.costCents - a.costCents;\n return (b.lastActiveAt ?? 0) - (a.lastActiveAt ?? 0);\n }),\n byLabel,\n byModel,\n daily,\n dailyAvailable,\n monthlyByUser,\n workspaceAppCreationsByUserMonth,\n appAccess,\n recent,\n };\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/dispatch",
|
|
3
|
-
"version": "0.40.
|
|
3
|
+
"version": "0.40.37",
|
|
4
4
|
"description": "Dispatch — workspace control plane for agent-native apps. Vault, integrations, destinations, scheduled jobs, and cross-app delegation, shipped as a single drop-in package.",
|
|
5
5
|
"homepage": "https://github.com/BuilderIO/agent-native#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
"tailwind-merge": "^3.5.0",
|
|
91
91
|
"vaul": "^1.1.2",
|
|
92
92
|
"zod": "^4.3.6",
|
|
93
|
-
"@agent-native/toolkit": "0.
|
|
93
|
+
"@agent-native/toolkit": "0.217.0"
|
|
94
94
|
},
|
|
95
95
|
"devDependencies": {
|
|
96
96
|
"@react-router/dev": "^8.1.0",
|
|
@@ -104,7 +104,7 @@
|
|
|
104
104
|
"typescript-7": "npm:typescript@^7.0.2",
|
|
105
105
|
"vite": "8.1.0",
|
|
106
106
|
"vitest": "^4.1.5",
|
|
107
|
-
"@agent-native/core": "0.
|
|
107
|
+
"@agent-native/core": "0.217.0"
|
|
108
108
|
},
|
|
109
109
|
"peerDependencies": {
|
|
110
110
|
"@agent-native/core": ">=0.209.1",
|
|
@@ -95,7 +95,7 @@ export const CURATED_COMMUNITY_APP_SOURCES: readonly CuratedCommunityAppSource[]
|
|
|
95
95
|
},
|
|
96
96
|
{
|
|
97
97
|
path: "package.json",
|
|
98
|
-
blobSha: "
|
|
98
|
+
blobSha: "dbf733f4e0b751a91398233040e275ec32955a07",
|
|
99
99
|
},
|
|
100
100
|
{
|
|
101
101
|
path: "server/db/index.ts",
|
|
@@ -173,7 +173,9 @@ describe("listDispatchUsageMetrics", () => {
|
|
|
173
173
|
errorCode: "usage_user_lookup_forbidden",
|
|
174
174
|
statusCode: 403,
|
|
175
175
|
});
|
|
176
|
-
expect((error as Error).message).toContain(
|
|
176
|
+
expect((error as Error).message).toContain(
|
|
177
|
+
"own customer or billing actions",
|
|
178
|
+
);
|
|
177
179
|
expect(mocks.isOrgMember).not.toHaveBeenCalled();
|
|
178
180
|
expect(mocks.getUsageSummary).not.toHaveBeenCalled();
|
|
179
181
|
},
|
|
@@ -530,7 +532,9 @@ describe("listDispatchUsageMetrics", () => {
|
|
|
530
532
|
expect((error as Error).message).toContain(
|
|
531
533
|
"customer@customer.example is not a member of this organization",
|
|
532
534
|
);
|
|
533
|
-
expect((error as Error).message).toContain(
|
|
535
|
+
expect((error as Error).message).toContain(
|
|
536
|
+
"own customer or billing actions",
|
|
537
|
+
);
|
|
534
538
|
expect((error as Error).message).toContain("describe-workspace-apps");
|
|
535
539
|
});
|
|
536
540
|
|
|
@@ -956,7 +956,7 @@ async function assertCanViewMetrics(viewScope: UsageMetricsScope): Promise<{
|
|
|
956
956
|
|
|
957
957
|
function failUserNotOrgMember(email: string): never {
|
|
958
958
|
fail(
|
|
959
|
-
`${email} is not a member of this organization
|
|
959
|
+
`${email} is not a member of this organization, so list-dispatch-usage-metrics has no data on them. For a customer's or account's usage or credits, use this app's own customer or billing actions if it has any, or find the app that owns that data with describe-workspace-apps query="<what you need>" and delegate with call-agent.`,
|
|
960
960
|
{ errorCode: "usage_user_not_org_member", statusCode: 404 },
|
|
961
961
|
);
|
|
962
962
|
}
|
|
@@ -988,7 +988,7 @@ export async function listDispatchUsageMetrics(input: {
|
|
|
988
988
|
callerRole !== "admin"
|
|
989
989
|
) {
|
|
990
990
|
fail(
|
|
991
|
-
|
|
991
|
+
`list-dispatch-usage-metrics cannot answer this. For a teammate in this organization, only owners and admins can look up their usage. For a customer or other external user, list-dispatch-usage-metrics has no data: use this app's own customer or billing actions if it has any, or find the app that owns that data with describe-workspace-apps query="<what you need>" and delegate with call-agent.`,
|
|
992
992
|
{ errorCode: "usage_user_lookup_forbidden", statusCode: 403 },
|
|
993
993
|
);
|
|
994
994
|
}
|