@agent-native/dispatch 0.40.5 → 0.40.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/CHANGELOG.md +21 -28
  2. package/dist/actions/create-workspace-resource.d.ts +13 -13
  3. package/dist/components/ui/tooltip.d.ts +1 -7
  4. package/dist/components/ui/tooltip.d.ts.map +1 -1
  5. package/dist/components/ui/tooltip.js +1 -10
  6. package/dist/components/ui/tooltip.js.map +1 -1
  7. package/dist/lib/overview-chat.d.ts +1 -0
  8. package/dist/lib/overview-chat.d.ts.map +1 -1
  9. package/dist/lib/overview-chat.js +1 -0
  10. package/dist/lib/overview-chat.js.map +1 -1
  11. package/dist/routes/pages/chat.d.ts.map +1 -1
  12. package/dist/routes/pages/chat.js +1 -0
  13. package/dist/routes/pages/chat.js.map +1 -1
  14. package/dist/server/lib/admin-config.d.ts +3 -0
  15. package/dist/server/lib/admin-config.d.ts.map +1 -0
  16. package/dist/server/lib/admin-config.js +16 -0
  17. package/dist/server/lib/admin-config.js.map +1 -0
  18. package/dist/server/lib/app-creation-store.d.ts.map +1 -1
  19. package/dist/server/lib/app-creation-store.js +3 -2
  20. package/dist/server/lib/app-creation-store.js.map +1 -1
  21. package/dist/server/lib/dispatch-integrations.d.ts.map +1 -1
  22. package/dist/server/lib/dispatch-integrations.js +2 -1
  23. package/dist/server/lib/dispatch-integrations.js.map +1 -1
  24. package/dist/server/lib/thread-debug-store.d.ts.map +1 -1
  25. package/dist/server/lib/thread-debug-store.js +2 -15
  26. package/dist/server/lib/thread-debug-store.js.map +1 -1
  27. package/dist/server/lib/usage-metrics-store.d.ts.map +1 -1
  28. package/dist/server/lib/usage-metrics-store.js +5 -16
  29. package/dist/server/lib/usage-metrics-store.js.map +1 -1
  30. package/package.json +4 -4
  31. package/src/components/ui/tooltip.tsx +1 -28
  32. package/src/lib/overview-chat.spec.ts +2 -0
  33. package/src/lib/overview-chat.ts +2 -0
  34. package/src/routes/pages/chat.tsx +1 -0
  35. package/src/server/lib/admin-config.ts +16 -0
  36. package/src/server/lib/app-creation-store.ts +3 -2
  37. package/src/server/lib/dispatch-integrations.ts +2 -1
  38. package/src/server/lib/thread-debug-store.spec.ts +14 -2
  39. package/src/server/lib/thread-debug-store.ts +2 -17
  40. package/src/server/lib/usage-metrics-store.spec.ts +26 -0
  41. package/src/server/lib/usage-metrics-store.ts +5 -18
@@ -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 { ForbiddenError } from \"@agent-native/core/sharing\";\nimport {\n builderCreditsFromCostCents,\n getUsageSummary,\n isSelfScopedUsageRead,\n usageBillingForEngine,\n usageOrgScope,\n type UsageBillingMode,\n} from \"@agent-native/core/usage\";\n\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;\n calls: number;\n chatCalls: number;\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: 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\nfunction envEmails(name: string): string[] {\n return (process.env[name] ?? \"\")\n .split(\",\")\n .map((value) => value.trim().toLowerCase())\n .filter(Boolean);\n}\n\nfunction isEnvAdmin(email: string): boolean {\n const normalized = email.trim().toLowerCase();\n return [\n ...envEmails(\"DISPATCH_ADMIN_EMAILS\"),\n ...envEmails(\"WORKSPACE_OWNER_EMAIL\"),\n ...envEmails(\"DISPATCH_DEFAULT_OWNER_EMAIL\"),\n ].includes(normalized);\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 getViewerOrgRole(\n orgId: string | null,\n email: string,\n): Promise<string | null> {\n if (!orgId) return null;\n const rows = await queryRows<{ role?: string }>(\n `SELECT role FROM org_members\n WHERE org_id = ? AND LOWER(email) = ?\n AND federation_removal_pending_at IS NULL\n LIMIT 1`,\n [orgId, email.toLowerCase()],\n );\n const role = rows[0]?.role;\n return typeof role === \"string\" ? role : null;\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: Omit<MonthlyUserUsageMetric, \"credits\">[];\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 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<\n string,\n Omit<MonthlyUserUsageMetric, \"credits\">\n >();\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 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.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 = await getViewerOrgRole(orgId, viewerEmail);\n if (\n viewScope === \"me\" ||\n isEnvAdmin(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 billing = usageBillingForEngine(await detectUsageEngineName());\n\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 isEnvAdmin(viewerEmail) || role === \"owner\" || 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(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 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((row) => ({\n ...row,\n credits: builderCreditsFromCostCents(row.costCents),\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 totals = totalsRows[0] ?? {};\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 {\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 { ForbiddenError } from \"@agent-native/core/sharing\";\nimport {\n builderCreditsFromCostCents,\n getUsageSummary,\n isSelfScopedUsageRead,\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;\n calls: number;\n chatCalls: number;\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: 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 getViewerOrgRole(\n orgId: string | null,\n email: string,\n): Promise<string | null> {\n if (!orgId) return null;\n const rows = await queryRows<{ role?: string }>(\n `SELECT role FROM org_members\n WHERE org_id = ? AND LOWER(email) = ?\n AND federation_removal_pending_at IS NULL\n LIMIT 1`,\n [orgId, email.toLowerCase()],\n );\n const role = rows[0]?.role;\n return typeof role === \"string\" ? role : null;\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: Omit<MonthlyUserUsageMetric, \"credits\">[];\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 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<\n string,\n Omit<MonthlyUserUsageMetric, \"credits\">\n >();\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 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.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 = await getViewerOrgRole(orgId, viewerEmail);\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 billing = usageBillingForEngine(await detectUsageEngineName());\n\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(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 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((row) => ({\n ...row,\n credits: builderCreditsFromCostCents(row.costCents),\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 totals = totalsRows[0] ?? {};\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.5",
3
+ "version": "0.40.7",
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": {
@@ -89,7 +89,7 @@
89
89
  "tailwind-merge": "^3.5.0",
90
90
  "vaul": "^1.1.2",
91
91
  "zod": "^4.3.6",
92
- "@agent-native/toolkit": "0.198.4"
92
+ "@agent-native/toolkit": "0.198.6"
93
93
  },
94
94
  "devDependencies": {
95
95
  "@react-router/dev": "^8.1.0",
@@ -103,10 +103,10 @@
103
103
  "typescript-7": "npm:typescript@^7.0.2",
104
104
  "vite": "8.1.0",
105
105
  "vitest": "^4.1.5",
106
- "@agent-native/core": "0.198.4"
106
+ "@agent-native/core": "0.198.6"
107
107
  },
108
108
  "peerDependencies": {
109
- "@agent-native/core": ">=0.8.0",
109
+ "@agent-native/core": ">=0.198.6",
110
110
  "react": ">=19.2.7",
111
111
  "react-dom": ">=19.2.7",
112
112
  "react-router": ">=8"
@@ -1,28 +1 @@
1
- import * as TooltipPrimitive from "@radix-ui/react-tooltip";
2
- import * as React from "react";
3
-
4
- import { cn } from "../../lib/utils";
5
-
6
- const TooltipProvider = TooltipPrimitive.Provider;
7
-
8
- const Tooltip = TooltipPrimitive.Root;
9
-
10
- const TooltipTrigger = TooltipPrimitive.Trigger;
11
-
12
- const TooltipContent = React.forwardRef<
13
- React.ElementRef<typeof TooltipPrimitive.Content>,
14
- React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>
15
- >(({ className, sideOffset = 4, ...props }, ref) => (
16
- <TooltipPrimitive.Content
17
- ref={ref}
18
- sideOffset={sideOffset}
19
- className={cn(
20
- "z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
21
- className,
22
- )}
23
- {...props}
24
- />
25
- ));
26
- TooltipContent.displayName = TooltipPrimitive.Content.displayName;
27
-
28
- export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
1
+ export * from "@agent-native/toolkit/ui/tooltip";
@@ -28,6 +28,7 @@ describe("submitOverviewPrompt", () => {
28
28
  it("can submit to a mounted page chat without opening the sidebar", () => {
29
29
  const tabId = submitOverviewPrompt(" build a metrics app ", "auto", {
30
30
  openSidebar: false,
31
+ reuseEmptyTab: true,
31
32
  selectedEngine: "openai",
32
33
  selectedEffort: "high",
33
34
  });
@@ -37,6 +38,7 @@ describe("submitOverviewPrompt", () => {
37
38
  message: "build a metrics app",
38
39
  submit: true,
39
40
  newTab: true,
41
+ reuseEmptyTab: true,
40
42
  model: "auto",
41
43
  engine: "openai",
42
44
  effort: "high",
@@ -5,6 +5,7 @@ import {
5
5
 
6
6
  interface OverviewChatOptions {
7
7
  openSidebar?: boolean;
8
+ reuseEmptyTab?: boolean;
8
9
  selectedEngine?: string | null;
9
10
  selectedEffort?: AgentChatMessage["effort"];
10
11
  }
@@ -21,6 +22,7 @@ export function submitOverviewPrompt(
21
22
  message: trimmed,
22
23
  submit: true,
23
24
  newTab: true,
25
+ ...(options?.reuseEmptyTab ? { reuseEmptyTab: true } : {}),
24
26
  model: selectedModel || undefined,
25
27
  ...(options?.selectedEngine ? { engine: options.selectedEngine } : {}),
26
28
  ...(options?.selectedEffort ? { effort: options.selectedEffort } : {}),
@@ -183,6 +183,7 @@ export default function ChatRoute() {
183
183
  setPendingOverviewPrompt(prompt ?? null);
184
184
  submitOverviewPrompt(message, prompt?.selectedModel, {
185
185
  openSidebar: false,
186
+ reuseEmptyTab: true,
186
187
  selectedEngine: prompt?.selectedEngine,
187
188
  selectedEffort: prompt?.selectedEffort,
188
189
  });
@@ -0,0 +1,16 @@
1
+ import { getAppConfig } from "@agent-native/core/server";
2
+
3
+ export function isDispatchEnvironmentAdmin(email: string): boolean {
4
+ const normalized = email.trim().toLowerCase();
5
+ if (!normalized) return false;
6
+ const config = getAppConfig().dispatch;
7
+ return [
8
+ ...config.adminEmails,
9
+ ...config.workspaceOwnerEmails,
10
+ ...(config.defaultOwnerEmail ? [config.defaultOwnerEmail] : []),
11
+ ].some((candidate) => candidate.trim().toLowerCase() === normalized);
12
+ }
13
+
14
+ export function getDispatchDefaultOwnerEmail(): string | null {
15
+ return getAppConfig().dispatch.defaultOwnerEmail?.trim() || null;
16
+ }
@@ -43,6 +43,7 @@ import { resolveAccess } from "@agent-native/core/sharing";
43
43
 
44
44
  import "../../db/index.js";
45
45
  import { isWorkspaceSsoAppUrl } from "../../shared/workspace-sso.js";
46
+ import { getDispatchDefaultOwnerEmail } from "./admin-config.js";
46
47
  import { identityKeyForIncoming } from "./dispatch-integrations.js";
47
48
  import {
48
49
  currentOrgId,
@@ -2510,7 +2511,7 @@ async function isCurrentIntegrationExplicitlyLinked(): Promise<boolean> {
2510
2511
  }
2511
2512
 
2512
2513
  async function defaultOwnerAppCreationAllowed(): Promise<boolean> {
2513
- const defaultOwner = process.env.DISPATCH_DEFAULT_OWNER_EMAIL?.trim();
2514
+ const defaultOwner = getDispatchDefaultOwnerEmail();
2514
2515
  if (!defaultOwner || defaultOwner !== currentOwnerEmail()) return false;
2515
2516
  if (await isCurrentIntegrationExplicitlyLinked()) return true;
2516
2517
  return (
@@ -2576,7 +2577,7 @@ async function remoteAppCreationAuthorization(): Promise<
2576
2577
  > {
2577
2578
  const ownerEmail = currentOwnerEmail();
2578
2579
  const isIntegrationCaller = isIntegrationCallerRequest();
2579
- const defaultOwner = process.env.DISPATCH_DEFAULT_OWNER_EMAIL?.trim();
2580
+ const defaultOwner = getDispatchDefaultOwnerEmail();
2580
2581
  if (isIntegrationCaller && defaultOwner && defaultOwner === ownerEmail) {
2581
2582
  if (await defaultOwnerAppCreationAllowed()) return { ok: true };
2582
2583
  return {
@@ -17,6 +17,7 @@ import type {
17
17
  PlatformAdapter,
18
18
  } from "@agent-native/core/server";
19
19
 
20
+ import { getDispatchDefaultOwnerEmail } from "./admin-config.js";
20
21
  import { handleRemoteCodeCommand } from "./dispatch-remote-commands.js";
21
22
  import {
22
23
  dispatchIntegrationRoutingHint,
@@ -85,7 +86,7 @@ function configuredDefaultOwnerForIncoming(
85
86
  incoming: IncomingMessage,
86
87
  ): string | null {
87
88
  if (incoming.platform !== "slack") return null;
88
- const email = process.env.DISPATCH_DEFAULT_OWNER_EMAIL?.trim();
89
+ const email = getDispatchDefaultOwnerEmail();
89
90
  if (!email) return null;
90
91
  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email) ? email : null;
91
92
  }
@@ -5,6 +5,11 @@ const mocks = vi.hoisted(() => ({
5
5
  createDbExec: vi.fn(),
6
6
  orgId: null as string | null,
7
7
  ownerEmail: "owner@example.com",
8
+ dispatchConfig: {
9
+ adminEmails: [] as string[],
10
+ workspaceOwnerEmails: [] as string[],
11
+ defaultOwnerEmail: undefined as string | undefined,
12
+ },
8
13
  }));
9
14
 
10
15
  vi.mock("@agent-native/core/db", () => ({
@@ -12,6 +17,10 @@ vi.mock("@agent-native/core/db", () => ({
12
17
  getDbExec: () => ({ execute: mocks.currentExecute }),
13
18
  }));
14
19
 
20
+ vi.mock("@agent-native/core/server", () => ({
21
+ getAppConfig: () => ({ dispatch: mocks.dispatchConfig }),
22
+ }));
23
+
15
24
  vi.mock("./dispatch-store.js", () => ({
16
25
  currentOrgId: () => mocks.orgId,
17
26
  currentOwnerEmail: () => mocks.ownerEmail,
@@ -100,6 +109,9 @@ describe("thread-debug-store", () => {
100
109
  beforeEach(() => {
101
110
  mocks.orgId = null;
102
111
  mocks.ownerEmail = "owner@example.com";
112
+ mocks.dispatchConfig.adminEmails = [];
113
+ mocks.dispatchConfig.workspaceOwnerEmails = [];
114
+ mocks.dispatchConfig.defaultOwnerEmail = undefined;
103
115
  mocks.currentExecute.mockReset();
104
116
  mocks.createDbExec.mockReset();
105
117
  mocks.currentExecute.mockImplementation(async ({ sql, args }) => ({
@@ -260,7 +272,7 @@ describe("thread-debug-store", () => {
260
272
  });
261
273
 
262
274
  it("merges all admin-visible sources, sorts globally, limits, and preserves partial health", async () => {
263
- vi.stubEnv("DISPATCH_ADMIN_EMAILS", "owner@example.com");
275
+ mocks.dispatchConfig.defaultOwnerEmail = "Owner@Example.com";
264
276
  vi.stubEnv("REMOTE_A_DATABASE_URL", "postgres://remote-a/db");
265
277
  vi.stubEnv("REMOTE_B_DATABASE_URL", "postgres://remote-b/db");
266
278
  vi.stubEnv("REMOTE_C_DATABASE_URL", "postgres://remote-c/db");
@@ -327,7 +339,7 @@ describe("thread-debug-store", () => {
327
339
  });
328
340
 
329
341
  it("retains disconnected configured sources without attempting a connection", async () => {
330
- vi.stubEnv("DISPATCH_ADMIN_EMAILS", "owner@example.com");
342
+ mocks.dispatchConfig.adminEmails = ["owner@example.com"];
331
343
  vi.stubEnv(
332
344
  "AGENT_NATIVE_THREAD_DEBUG_DATABASES",
333
345
  JSON.stringify([