@agent-native/dispatch 0.40.34 → 0.40.36
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 +29 -13
- package/dist/actions/list-dispatch-usage-metrics.js +2 -2
- package/dist/actions/list-dispatch-usage-metrics.js.map +1 -1
- package/dist/actions/provider-api-register.d.ts +18 -18
- package/dist/server/lib/community-apps.js +1 -1
- package/dist/server/lib/community-apps.js.map +1 -1
- package/dist/server/lib/mcp-gateway.d.ts.map +1 -1
- package/dist/server/lib/mcp-gateway.js +21 -8
- package/dist/server/lib/mcp-gateway.js.map +1 -1
- package/dist/server/lib/usage-metrics-store.d.ts.map +1 -1
- package/dist/server/lib/usage-metrics-store.js +25 -1
- package/dist/server/lib/usage-metrics-store.js.map +1 -1
- package/package.json +3 -3
- package/src/actions/index.spec.ts +7 -3
- package/src/actions/list-dispatch-usage-metrics.ts +4 -2
- package/src/server/lib/community-apps.ts +1 -1
- package/src/server/lib/mcp-gateway.spec.ts +79 -0
- package/src/server/lib/mcp-gateway.ts +24 -6
- package/src/server/lib/usage-metrics-store.spec.ts +87 -0
- package/src/server/lib/usage-metrics-store.ts +37 -3
|
@@ -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 {\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 { 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\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 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 throw new ForbiddenError(\n \"The selected user is not available in this workspace.\",\n );\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. 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"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/dispatch",
|
|
3
|
-
"version": "0.40.
|
|
3
|
+
"version": "0.40.36",
|
|
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.216.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.216.0"
|
|
108
108
|
},
|
|
109
109
|
"peerDependencies": {
|
|
110
110
|
"@agent-native/core": ">=0.209.1",
|
|
@@ -93,9 +93,13 @@ describe("dispatch action registry", () => {
|
|
|
93
93
|
expect(action.tool.description).toContain(
|
|
94
94
|
"workspaceAppCreationsByUserMonth",
|
|
95
95
|
);
|
|
96
|
-
|
|
97
|
-
expect(
|
|
98
|
-
|
|
96
|
+
const firstSentence = action.tool.description.split(". ")[0];
|
|
97
|
+
expect(firstSentence).toContain("members of this organization");
|
|
98
|
+
expect(firstSentence).toContain("does NOT cover");
|
|
99
|
+
expect(firstSentence).toContain("external customers");
|
|
100
|
+
expect(firstSentence).toContain("describe-workspace-apps");
|
|
101
|
+
expect(JSON.stringify(action.tool.parameters)).toContain(
|
|
102
|
+
"Not for customers or other external accounts",
|
|
99
103
|
);
|
|
100
104
|
});
|
|
101
105
|
});
|
|
@@ -5,7 +5,7 @@ import { listDispatchUsageMetrics } from "../server/lib/usage-metrics-store.js";
|
|
|
5
5
|
|
|
6
6
|
export default defineAction({
|
|
7
7
|
description:
|
|
8
|
-
"
|
|
8
|
+
"Reports agent/LLM usage and spend for members of this organization (personal or workspace-wide) plus aggregate app adoption for Dispatch; it does NOT cover usage, credits, or activity of external customers, accounts, companies, or product usage, which belong to the app that owns that data (see <relevant-apps>, or search with describe-workspace-apps). Results may include active users, tracked app actions, app attribution, prompt previews, and recent activity. billing.unit is unknown when historical usage lacks engine metadata or mixes billing sources; monthlyByUser credits are null in that case. Workspace results also include monthlyByUser credit rows and workspaceAppCreationsByUserMonth rows from the shared token_usage and Dispatch audit tables. App scope is aggregate-only and returns daily/weekly active users plus tracked action counts for the selected app.",
|
|
9
9
|
schema: z.object({
|
|
10
10
|
sinceDays: z.coerce
|
|
11
11
|
.number()
|
|
@@ -25,7 +25,9 @@ export default defineAction({
|
|
|
25
25
|
.trim()
|
|
26
26
|
.min(1)
|
|
27
27
|
.optional()
|
|
28
|
-
.describe(
|
|
28
|
+
.describe(
|
|
29
|
+
"Optional email of a member of this organization to filter all usage to. Not for customers or other external accounts.",
|
|
30
|
+
),
|
|
29
31
|
appId: z
|
|
30
32
|
.string()
|
|
31
33
|
.trim()
|
|
@@ -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: "da9e7b9eb37664a191dfde80406c7d5b350bfe0b",
|
|
99
99
|
},
|
|
100
100
|
{
|
|
101
101
|
path: "server/db/index.ts",
|
|
@@ -1178,6 +1178,85 @@ describe("openGrantedDispatchMcpApp", () => {
|
|
|
1178
1178
|
});
|
|
1179
1179
|
});
|
|
1180
1180
|
|
|
1181
|
+
it("reads the target embed start URL from Core MCP response metadata", async () => {
|
|
1182
|
+
mocks.managerCallTool.mockResolvedValueOnce({
|
|
1183
|
+
structuredContent: {
|
|
1184
|
+
targetPath: "/dashboards?range=30d",
|
|
1185
|
+
expiresAt: 12345,
|
|
1186
|
+
},
|
|
1187
|
+
_meta: {
|
|
1188
|
+
"agent-native/embedStart": {
|
|
1189
|
+
startUrl:
|
|
1190
|
+
"http://localhost:8086/_agent-native/embed/start?ticket=remote",
|
|
1191
|
+
},
|
|
1192
|
+
},
|
|
1193
|
+
});
|
|
1194
|
+
|
|
1195
|
+
const result = await runWithRequestContext(
|
|
1196
|
+
{
|
|
1197
|
+
userEmail: "owner@example.test",
|
|
1198
|
+
requestOrigin: "http://localhost:8092",
|
|
1199
|
+
},
|
|
1200
|
+
() =>
|
|
1201
|
+
openGrantedDispatchMcpApp({
|
|
1202
|
+
app: "analytics",
|
|
1203
|
+
path: "/dashboards?range=30d",
|
|
1204
|
+
embed: true,
|
|
1205
|
+
chrome: "minimal",
|
|
1206
|
+
}),
|
|
1207
|
+
);
|
|
1208
|
+
|
|
1209
|
+
expect(result).toMatchObject({
|
|
1210
|
+
app: "analytics",
|
|
1211
|
+
embedStartUrl:
|
|
1212
|
+
"http://localhost:8086/_agent-native/embed/start?ticket=remote",
|
|
1213
|
+
embedTargetPath: "/dashboards?range=30d",
|
|
1214
|
+
embedExpiresAt: 12345,
|
|
1215
|
+
});
|
|
1216
|
+
});
|
|
1217
|
+
|
|
1218
|
+
it("reads the target embed start URL when Core returns JSON text", async () => {
|
|
1219
|
+
mocks.managerCallTool.mockResolvedValueOnce({
|
|
1220
|
+
content: [
|
|
1221
|
+
{
|
|
1222
|
+
type: "text",
|
|
1223
|
+
text: JSON.stringify({
|
|
1224
|
+
targetPath: "/dashboards?range=30d",
|
|
1225
|
+
expiresAt: 12345,
|
|
1226
|
+
}),
|
|
1227
|
+
},
|
|
1228
|
+
],
|
|
1229
|
+
_meta: {
|
|
1230
|
+
"agent-native/embedStart": {
|
|
1231
|
+
startUrl:
|
|
1232
|
+
"http://localhost:8086/_agent-native/embed/start?ticket=remote",
|
|
1233
|
+
},
|
|
1234
|
+
},
|
|
1235
|
+
});
|
|
1236
|
+
|
|
1237
|
+
const result = await runWithRequestContext(
|
|
1238
|
+
{
|
|
1239
|
+
userEmail: "owner@example.test",
|
|
1240
|
+
requestOrigin: "http://localhost:8092",
|
|
1241
|
+
},
|
|
1242
|
+
() =>
|
|
1243
|
+
openGrantedDispatchMcpApp({
|
|
1244
|
+
app: "analytics",
|
|
1245
|
+
path: "/dashboards?range=30d",
|
|
1246
|
+
embed: true,
|
|
1247
|
+
chrome: "minimal",
|
|
1248
|
+
}),
|
|
1249
|
+
);
|
|
1250
|
+
|
|
1251
|
+
expect(result).toMatchObject({
|
|
1252
|
+
app: "analytics",
|
|
1253
|
+
embedStartUrl:
|
|
1254
|
+
"http://localhost:8086/_agent-native/embed/start?ticket=remote",
|
|
1255
|
+
embedTargetPath: "/dashboards?range=30d",
|
|
1256
|
+
embedExpiresAt: 12345,
|
|
1257
|
+
});
|
|
1258
|
+
});
|
|
1259
|
+
|
|
1181
1260
|
it.each([408, 429, 502, 503, 504])(
|
|
1182
1261
|
"retries transient typed HTTP %i target MCP failures with HTML bodies",
|
|
1183
1262
|
async (status) => {
|
|
@@ -1013,18 +1013,36 @@ export async function openGrantedDispatchMcpApp(input: {
|
|
|
1013
1013
|
|
|
1014
1014
|
function parseMcpToolTextResult(result: unknown): Record<string, unknown> {
|
|
1015
1015
|
if (result && typeof result === "object") {
|
|
1016
|
-
const
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1016
|
+
const response = result as Record<string, unknown>;
|
|
1017
|
+
const meta =
|
|
1018
|
+
response._meta && typeof response._meta === "object"
|
|
1019
|
+
? (response._meta as Record<string, unknown>)
|
|
1020
|
+
: undefined;
|
|
1021
|
+
const embedStart =
|
|
1022
|
+
meta?.["agent-native/embedStart"] &&
|
|
1023
|
+
typeof meta["agent-native/embedStart"] === "object"
|
|
1024
|
+
? (meta["agent-native/embedStart"] as Record<string, unknown>)
|
|
1025
|
+
: undefined;
|
|
1026
|
+
const withEmbedStart = (parsed: Record<string, unknown>) =>
|
|
1027
|
+
typeof embedStart?.startUrl === "string"
|
|
1028
|
+
? { ...parsed, startUrl: embedStart.startUrl }
|
|
1029
|
+
: parsed;
|
|
1030
|
+
const structured = response.structuredContent;
|
|
1031
|
+
if (structured && typeof structured === "object") {
|
|
1032
|
+
return withEmbedStart(structured as Record<string, unknown>);
|
|
1033
|
+
}
|
|
1034
|
+
const parts = Array.isArray(response.content)
|
|
1035
|
+
? (response.content as Array<Record<string, unknown>>)
|
|
1020
1036
|
: [];
|
|
1021
1037
|
const text = parts.find(
|
|
1022
1038
|
(part) => part?.type === "text" && typeof part.text === "string",
|
|
1023
1039
|
)?.text;
|
|
1024
1040
|
if (typeof text === "string" && text.trim()) {
|
|
1025
|
-
if (
|
|
1041
|
+
if (response.isError) throw new Error(text.trim());
|
|
1026
1042
|
const parsed = JSON.parse(text);
|
|
1027
|
-
if (parsed && typeof parsed === "object")
|
|
1043
|
+
if (parsed && typeof parsed === "object") {
|
|
1044
|
+
return withEmbedStart(parsed as Record<string, unknown>);
|
|
1045
|
+
}
|
|
1028
1046
|
}
|
|
1029
1047
|
}
|
|
1030
1048
|
throw new Error("Target app did not return an embed session.");
|