@aglyn/plugins-ai 1.0.0-beta.234 → 1.0.0-beta.236

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 (137) hide show
  1. package/package.json +17 -17
  2. package/src/lib/activity/ai-activity-actions.d.ts +25 -0
  3. package/src/lib/activity/ai-activity-actions.js +85 -4
  4. package/src/lib/activity/ai-activity-actions.js.map +1 -1
  5. package/src/lib/components/ai-brief-dialog.component.js +46 -2
  6. package/src/lib/components/ai-brief-dialog.component.js.map +1 -1
  7. package/src/lib/components/ai-campaign-create.component.js +1 -1
  8. package/src/lib/components/ai-campaign-create.component.js.map +1 -1
  9. package/src/lib/components/ai-credits-card.component.js +3 -3
  10. package/src/lib/components/ai-credits-card.component.js.map +1 -1
  11. package/src/lib/components/ai-crm-email-draft.component.js +1 -1
  12. package/src/lib/components/ai-crm-email-draft.component.js.map +1 -1
  13. package/src/lib/components/ai-crm-import-mapping.component.js +1 -1
  14. package/src/lib/components/ai-crm-import-mapping.component.js.map +1 -1
  15. package/src/lib/components/ai-crm-record-card.component.js +1 -1
  16. package/src/lib/components/ai-crm-record-card.component.js.map +1 -1
  17. package/src/lib/components/ai-describe-automation.component.js +4 -2
  18. package/src/lib/components/ai-describe-automation.component.js.map +1 -1
  19. package/src/lib/components/ai-describe-org-automation.component.js +1 -1
  20. package/src/lib/components/ai-describe-org-automation.component.js.map +1 -1
  21. package/src/lib/components/ai-experiment-cards.component.js +2 -2
  22. package/src/lib/components/ai-experiment-cards.component.js.map +1 -1
  23. package/src/lib/components/ai-explain-automation.component.js +1 -1
  24. package/src/lib/components/ai-explain-automation.component.js.map +1 -1
  25. package/src/lib/components/ai-insight-card.component.js +3 -1
  26. package/src/lib/components/ai-insight-card.component.js.map +1 -1
  27. package/src/lib/components/ai-jobs-list-page.component.d.ts +6 -1
  28. package/src/lib/components/ai-jobs-list-page.component.js +15 -2
  29. package/src/lib/components/ai-jobs-list-page.component.js.map +1 -1
  30. package/src/lib/components/ai-logic.component.js +5 -3
  31. package/src/lib/components/ai-logic.component.js.map +1 -1
  32. package/src/lib/components/ai-media-create.component.js +88 -16
  33. package/src/lib/components/ai-media-create.component.js.map +1 -1
  34. package/src/lib/components/ai-model-selector.component.js +8 -0
  35. package/src/lib/components/ai-model-selector.component.js.map +1 -1
  36. package/src/lib/components/ai-overlay-cards.component.js +2 -2
  37. package/src/lib/components/ai-overlay-cards.component.js.map +1 -1
  38. package/src/lib/components/ai-product-copy-card.component.js +2 -1
  39. package/src/lib/components/ai-product-copy-card.component.js.map +1 -1
  40. package/src/lib/components/ai-products-hub-card.component.js +2 -1
  41. package/src/lib/components/ai-products-hub-card.component.js.map +1 -1
  42. package/src/lib/components/ai-revise-automation.component.js +1 -1
  43. package/src/lib/components/ai-revise-automation.component.js.map +1 -1
  44. package/src/lib/components/ai-seo-fields-card.component.js +7 -3
  45. package/src/lib/components/ai-seo-fields-card.component.js.map +1 -1
  46. package/src/lib/components/ai-site-batch-card.component.js +7 -4
  47. package/src/lib/components/ai-site-batch-card.component.js.map +1 -1
  48. package/src/lib/components/ai-site-build-page.component.js +7 -3
  49. package/src/lib/components/ai-site-build-page.component.js.map +1 -1
  50. package/src/lib/components/ai-site-seo-start-card.component.js +7 -4
  51. package/src/lib/components/ai-site-seo-start-card.component.js.map +1 -1
  52. package/src/lib/components/ai-site-start-card.component.js +62 -29
  53. package/src/lib/components/ai-site-start-card.component.js.map +1 -1
  54. package/src/lib/components/ai-theme-proposal-card.component.js +1 -0
  55. package/src/lib/components/ai-theme-proposal-card.component.js.map +1 -1
  56. package/src/lib/components/ai-upsell-dialog.component.js +17 -3
  57. package/src/lib/components/ai-upsell-dialog.component.js.map +1 -1
  58. package/src/lib/components/ai-usage-strip.component.js +13 -2
  59. package/src/lib/components/ai-usage-strip.component.js.map +1 -1
  60. package/src/lib/components/assist-build-card.component.js +20 -3
  61. package/src/lib/components/assist-build-card.component.js.map +1 -1
  62. package/src/lib/components/assist-jobs-drawer.component.js +7 -1
  63. package/src/lib/components/assist-jobs-drawer.component.js.map +1 -1
  64. package/src/lib/components/billing-ai-allotments.component.js +2 -2
  65. package/src/lib/components/billing-ai-allotments.component.js.map +1 -1
  66. package/src/lib/components/billing-ai-top-users.component.js +1 -0
  67. package/src/lib/components/billing-ai-top-users.component.js.map +1 -1
  68. package/src/lib/components/billing-assist-overage-card.component.js +2 -2
  69. package/src/lib/components/billing-assist-overage-card.component.js.map +1 -1
  70. package/src/lib/components/host-ai-allotments.component.js +2 -2
  71. package/src/lib/components/host-ai-allotments.component.js.map +1 -1
  72. package/src/lib/components/member-ai-allotment-card.component.js +2 -2
  73. package/src/lib/components/member-ai-allotment-card.component.js.map +1 -1
  74. package/src/lib/components/staff-org-ai-card.component.js +1 -0
  75. package/src/lib/components/staff-org-ai-card.component.js.map +1 -1
  76. package/src/lib/components/staff-org-ai-conversations.component.d.ts +9 -3
  77. package/src/lib/components/staff-org-ai-conversations.component.js +174 -83
  78. package/src/lib/components/staff-org-ai-conversations.component.js.map +1 -1
  79. package/src/lib/components/staff-user-ai-usage-card.component.js +2 -1
  80. package/src/lib/components/staff-user-ai-usage-card.component.js.map +1 -1
  81. package/src/lib/jobs/ai-job-layout-language.js +4 -1
  82. package/src/lib/jobs/ai-job-layout-language.js.map +1 -1
  83. package/src/lib/jobs/ai-job-layout-site-pages.d.ts +12 -0
  84. package/src/lib/jobs/ai-job-layout-site-pages.js +20 -0
  85. package/src/lib/jobs/ai-job-layout-site-pages.js.map +1 -1
  86. package/src/lib/jobs/ai-job-page-language.d.ts +10 -1
  87. package/src/lib/jobs/ai-job-page-language.js +41 -8
  88. package/src/lib/jobs/ai-job-page-language.js.map +1 -1
  89. package/src/lib/jobs/ai-job-page-step.js +14 -3
  90. package/src/lib/jobs/ai-job-page-step.js.map +1 -1
  91. package/src/lib/jobs/ai-job-site-content.d.ts +75 -7
  92. package/src/lib/jobs/ai-job-site-content.js +205 -32
  93. package/src/lib/jobs/ai-job-site-content.js.map +1 -1
  94. package/src/lib/jobs/ai-job-site-step.d.ts +8 -0
  95. package/src/lib/jobs/ai-job-site-step.js +61 -12
  96. package/src/lib/jobs/ai-job-site-step.js.map +1 -1
  97. package/src/lib/layout-language/ai-layout-compiler.d.ts +8 -0
  98. package/src/lib/layout-language/ai-layout-compiler.js +308 -10
  99. package/src/lib/layout-language/ai-layout-compiler.js.map +1 -1
  100. package/src/lib/layout-language/ai-layout-design.d.ts +7 -0
  101. package/src/lib/layout-language/ai-layout-design.js +23 -11
  102. package/src/lib/layout-language/ai-layout-design.js.map +1 -1
  103. package/src/lib/layout-language/ai-layout-frame.d.ts +6 -0
  104. package/src/lib/layout-language/ai-layout-frame.js +12 -3
  105. package/src/lib/layout-language/ai-layout-frame.js.map +1 -1
  106. package/src/lib/layout-language/ai-layout-gaps.js +18 -2
  107. package/src/lib/layout-language/ai-layout-gaps.js.map +1 -1
  108. package/src/lib/layout-language/ai-layout-links.d.ts +26 -1
  109. package/src/lib/layout-language/ai-layout-links.js +24 -4
  110. package/src/lib/layout-language/ai-layout-links.js.map +1 -1
  111. package/src/lib/layout-language/ai-layout-listings.d.ts +125 -0
  112. package/src/lib/layout-language/ai-layout-listings.js +187 -0
  113. package/src/lib/layout-language/ai-layout-listings.js.map +1 -0
  114. package/src/lib/model/ai-site-build-progress.js +27 -12
  115. package/src/lib/model/ai-site-build-progress.js.map +1 -1
  116. package/src/lib/model/ai-site-job.d.ts +33 -8
  117. package/src/lib/model/ai-site-job.js +38 -18
  118. package/src/lib/model/ai-site-job.js.map +1 -1
  119. package/src/lib/model/ai-site-kinds.d.ts +30 -8
  120. package/src/lib/model/ai-site-kinds.js +731 -117
  121. package/src/lib/model/ai-site-kinds.js.map +1 -1
  122. package/src/lib/model/ai-site-start-seo.d.ts +30 -0
  123. package/src/lib/model/ai-site-start-seo.js +132 -11
  124. package/src/lib/model/ai-site-start-seo.js.map +1 -1
  125. package/src/lib/model/ai-site-start.d.ts +2 -2
  126. package/src/lib/model/ai-site-start.js +3 -3
  127. package/src/lib/model/ai-site-start.js.map +1 -1
  128. package/src/lib/plugin.js +15 -3
  129. package/src/lib/plugin.js.map +1 -1
  130. package/src/lib/runtime/ai-palette.generated.js +13 -3
  131. package/src/lib/runtime/ai-palette.generated.js.map +1 -1
  132. package/src/lib/server/ai-admin-conversations.d.ts +9 -0
  133. package/src/lib/server/ai-admin-conversations.js +151 -9
  134. package/src/lib/server/ai-admin-conversations.js.map +1 -1
  135. package/src/lib/usage/staff-org-ai-conversations.d.ts +23 -0
  136. package/src/lib/usage/staff-org-ai-conversations.js +45 -0
  137. package/src/lib/usage/staff-org-ai-conversations.js.map +1 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/member-ai-allotment-card.component.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport { pluginDocsHelp } from '@aglyn/aglyn/app-utils/docs-help'\nimport { CardDisplay } from '@aglyn/shared-ui-jsx'\nimport { useUser } from '@aglyn/tenant-feature-instance'\nimport { Button, Stack, Typography } from '@mui/material'\nimport { useState } from 'react'\nimport { AiAllotmentEditor, type AiAllotmentValue } from './ai-allotment-editor.component'\nimport { aiAllotmentSummary, aiAllotmentTone } from './billing-ai-allotments.component'\nimport { saveAiAllotments, useAiAllotments } from './use-ai-allotments'\n\nexport interface MemberAiAllotmentCardProps {\n orgId: string\n uid: string\n /** The org member document as the page loaded it. */\n member?: { hostAccess?: Record<string, string> } | null\n /** The org's sites, for naming a collaborator's. */\n hosts?: ReadonlyArray<{ $id: string; displayName?: string; subdomain?: string }>\n}\n\n/**\n * ONE MEMBER'S AI ALLOTMENT (AGL-2942), on their page beside their usage.\n *\n * A team member has one allotment, across every site. A site collaborator\n * has one per site they work on — each set here or on that site's Users\n * card. Read through `/api/ai/allotments?uid=`, which admits the person, the\n * Usage page's readers and — for a collaborator's sites — the site's admin;\n * a refusal renders no card.\n */\nexport function MemberAiAllotmentCard(props: MemberAiAllotmentCardProps) {\n const { orgId, uid } = props\n const { data: user } = useUser()\n const allotments = useAiAllotments({ orgId, uid })\n const [editing, setEditing] = useState<{ subject: string; title: string; initial: AiAllotmentValue | null; removable: boolean } | null>(null)\n const [busy, setBusy] = useState(false)\n const [error, setError] = useState<string | null>(null)\n if (allotments.status === 'refused') return null\n const data = allotments.data\n const person = data?.members.find((entry) => entry.uid === uid)\n const orgWide = person?.orgWide ?? true\n const siteName = (hostId: string) => {\n const host = props.hosts?.find((entry) => entry.$id === hostId)\n return host?.displayName ?? host?.subdomain ?? hostId\n }\n const rows = orgWide\n ? [{ subject: `member:${uid}`, label: 'Every site', hostId: null as string | null }]\n : Object.keys(props.member?.hostAccess ?? person?.byHost ?? {}).map((hostId) => ({\n subject: `collab:${hostId}:${uid}`,\n label: siteName(hostId),\n hostId,\n }))\n const mayEdit = (subject: string) =>\n Boolean(\n data &&\n (data.canEdit.billing ||\n (subject.startsWith('collab:') && data.canEdit.collaborators && uid !== data.callerUid)),\n )\n\n const run = async (body: Parameters<typeof saveAiAllotments>[1]) => {\n setBusy(true)\n setError(null)\n const result = await saveAiAllotments(user, body)\n setBusy(false)\n if (result.ok) setEditing(null)\n else setError(result.error)\n }\n\n return (\n <CardDisplay\n header={'AI allotment'}\n help={pluginDocsHelp('billing', {\n anchor: '#ai-allotments',\n excerpt: 'The share of the workspace’s AI credits this member may draw each month.',\n })}\n contentGutterX\n contentGutterY\n >\n {!data ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {allotments.status === 'error'\n ? 'Could not read this member’s AI allotment — a failed read, not none.'\n : 'Loading…'}\n </Typography>\n ) : (\n <Stack spacing={1}>\n {rows.map((entry) => {\n const row = data.allotments.find((allotment) => allotment.subject === entry.subject)\n const used = entry.hostId ? (person?.byHost[entry.hostId] ?? 0) : (person?.credits ?? 0)\n return (\n <Stack key={entry.subject} direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <Typography variant=\"body2\" sx={{ flexGrow: 1 }}>\n {`${entry.label}: `}\n <Typography component=\"span\" variant=\"body2\" sx={{ color: aiAllotmentTone(row) }}>\n {row ? aiAllotmentSummary(row) : `${used.toLocaleString()} credits this month, no allotment`}\n </Typography>\n </Typography>\n {mayEdit(entry.subject) ? (\n <Button\n size=\"small\"\n onClick={() => {\n setError(null)\n setEditing({\n subject: entry.subject,\n title: `AI allotment — ${person?.name ?? uid}${entry.hostId ? ` on ${entry.label}` : ''}`,\n initial: row ? { credits: row.credits, mode: row.mode, models: row.models } : null,\n removable: Boolean(row),\n })\n }}\n >\n {row ? 'Edit' : 'Set'}\n </Button>\n ) : null}\n </Stack>\n )\n })}\n <AiAllotmentEditor\n open={editing !== null}\n title={editing?.title ?? ''}\n initial={editing?.initial ?? null}\n models={data.models}\n poolLimit={data.pool.limit}\n busy={busy}\n error={error}\n onClose={() => setEditing(null)}\n onSave={(value) =>\n editing ? void run({ orgId: data.orgId, set: [{ subject: editing.subject, ...value }] }) : undefined\n }\n onRemove={\n editing?.removable\n ? () => void run({ orgId: data.orgId, remove: [editing.subject] })\n : undefined\n }\n />\n </Stack>\n )}\n </CardDisplay>\n )\n}\nMemberAiAllotmentCard.displayName = 'MemberAiAllotmentCard'\n\nexport default MemberAiAllotmentCard\n"],"names":["pluginDocsHelp","CardDisplay","useUser","Button","Stack","Typography","useState","AiAllotmentEditor","aiAllotmentSummary","aiAllotmentTone","saveAiAllotments","useAiAllotments","MemberAiAllotmentCard","props","orgId","uid","data","user","allotments","editing","setEditing","busy","setBusy","error","setError","status","person","members","find","entry","orgWide","siteName","hostId","host","hosts","$id","displayName","subdomain","rows","subject","label","Object","keys","member","hostAccess","byHost","map","mayEdit","Boolean","canEdit","billing","startsWith","collaborators","callerUid","run","body","result","ok","header","help","anchor","excerpt","contentGutterX","contentGutterY","variant","color","spacing","row","allotment","used","credits","direction","sx","alignItems","flexGrow","component","toLocaleString","size","onClick","title","name","initial","mode","models","removable","open","poolLimit","pool","limit","onClose","onSave","value","set","undefined","onRemove","remove"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/member-ai-allotment-card.component.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport { pluginDocsHelp } from '@aglyn/aglyn/app-utils/docs-help'\nimport { CardDisplay } from '@aglyn/shared-ui-jsx'\nimport { useUser } from '@aglyn/tenant-feature-instance'\nimport { Button, Stack, Typography } from '@mui/material'\nimport { useState } from 'react'\nimport { AiAllotmentEditor, type AiAllotmentValue } from './ai-allotment-editor.component'\nimport { aiAllotmentSummary, aiAllotmentTone } from './billing-ai-allotments.component'\nimport { saveAiAllotments, useAiAllotments } from './use-ai-allotments'\n\nexport interface MemberAiAllotmentCardProps {\n orgId: string\n uid: string\n /** The org member document as the page loaded it. */\n member?: { hostAccess?: Record<string, string> } | null\n /** The org's sites, for naming a collaborator's. */\n hosts?: ReadonlyArray<{ $id: string; displayName?: string; subdomain?: string }>\n}\n\n/**\n * ONE MEMBER'S AI ALLOTMENT (AGL-2942), on their page beside their usage.\n *\n * A team member has one allotment, across every site. A site collaborator\n * has one per site they work on — each set here or on that site's Users\n * card. Read through `/api/ai/allotments?uid=`, which admits the person, the\n * Usage page's readers and — for a collaborator's sites — the site's admin;\n * a refusal renders no card.\n */\nexport function MemberAiAllotmentCard(props: MemberAiAllotmentCardProps) {\n const { orgId, uid } = props\n const { data: user } = useUser()\n const allotments = useAiAllotments({ orgId, uid })\n const [editing, setEditing] = useState<{ subject: string; title: string; initial: AiAllotmentValue | null; removable: boolean } | null>(null)\n const [busy, setBusy] = useState(false)\n const [error, setError] = useState<string | null>(null)\n if (allotments.status === 'refused') return null\n const data = allotments.data\n const person = data?.members.find((entry) => entry.uid === uid)\n const orgWide = person?.orgWide ?? true\n const siteName = (hostId: string) => {\n const host = props.hosts?.find((entry) => entry.$id === hostId)\n return host?.displayName ?? host?.subdomain ?? hostId\n }\n const rows = orgWide\n ? [{ subject: `member:${uid}`, label: 'Every site', hostId: null as string | null }]\n : Object.keys(props.member?.hostAccess ?? person?.byHost ?? {}).map((hostId) => ({\n subject: `collab:${hostId}:${uid}`,\n label: siteName(hostId),\n hostId,\n }))\n const mayEdit = (subject: string) =>\n Boolean(\n data &&\n (data.canEdit.billing ||\n (subject.startsWith('collab:') && data.canEdit.collaborators && uid !== data.callerUid)),\n )\n\n const run = async (body: Parameters<typeof saveAiAllotments>[1]) => {\n setBusy(true)\n setError(null)\n const result = await saveAiAllotments(user, body)\n setBusy(false)\n if (result.ok) setEditing(null)\n else setError(result.error)\n }\n\n return (\n <CardDisplay\n header={'AI allotment'}\n help={pluginDocsHelp('aiAllotments', {\n anchor: '#a-members-allotment',\n excerpt: 'The share of the workspace’s AI credits this member may draw each month.',\n })}\n contentGutterX\n contentGutterY\n >\n {!data ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {allotments.status === 'error'\n ? 'Could not read this member’s AI allotment — a failed read, not none.'\n : 'Loading…'}\n </Typography>\n ) : (\n <Stack spacing={1}>\n {rows.map((entry) => {\n const row = data.allotments.find((allotment) => allotment.subject === entry.subject)\n const used = entry.hostId ? (person?.byHost[entry.hostId] ?? 0) : (person?.credits ?? 0)\n return (\n <Stack key={entry.subject} direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <Typography variant=\"body2\" sx={{ flexGrow: 1 }}>\n {`${entry.label}: `}\n <Typography component=\"span\" variant=\"body2\" sx={{ color: aiAllotmentTone(row) }}>\n {row ? aiAllotmentSummary(row) : `${used.toLocaleString()} credits this month, no allotment`}\n </Typography>\n </Typography>\n {mayEdit(entry.subject) ? (\n <Button\n size=\"small\"\n onClick={() => {\n setError(null)\n setEditing({\n subject: entry.subject,\n title: `AI allotment — ${person?.name ?? uid}${entry.hostId ? ` on ${entry.label}` : ''}`,\n initial: row ? { credits: row.credits, mode: row.mode, models: row.models } : null,\n removable: Boolean(row),\n })\n }}\n >\n {row ? 'Edit' : 'Set'}\n </Button>\n ) : null}\n </Stack>\n )\n })}\n <AiAllotmentEditor\n open={editing !== null}\n title={editing?.title ?? ''}\n initial={editing?.initial ?? null}\n models={data.models}\n poolLimit={data.pool.limit}\n busy={busy}\n error={error}\n onClose={() => setEditing(null)}\n onSave={(value) =>\n editing ? void run({ orgId: data.orgId, set: [{ subject: editing.subject, ...value }] }) : undefined\n }\n onRemove={\n editing?.removable\n ? () => void run({ orgId: data.orgId, remove: [editing.subject] })\n : undefined\n }\n />\n </Stack>\n )}\n </CardDisplay>\n )\n}\nMemberAiAllotmentCard.displayName = 'MemberAiAllotmentCard'\n\nexport default MemberAiAllotmentCard\n"],"names":["pluginDocsHelp","CardDisplay","useUser","Button","Stack","Typography","useState","AiAllotmentEditor","aiAllotmentSummary","aiAllotmentTone","saveAiAllotments","useAiAllotments","MemberAiAllotmentCard","props","orgId","uid","data","user","allotments","editing","setEditing","busy","setBusy","error","setError","status","person","members","find","entry","orgWide","siteName","hostId","host","hosts","$id","displayName","subdomain","rows","subject","label","Object","keys","member","hostAccess","byHost","map","mayEdit","Boolean","canEdit","billing","startsWith","collaborators","callerUid","run","body","result","ok","header","help","anchor","excerpt","contentGutterX","contentGutterY","variant","color","spacing","row","allotment","used","credits","direction","sx","alignItems","flexGrow","component","toLocaleString","size","onClick","title","name","initial","mode","models","removable","open","poolLimit","pool","limit","onClose","onSave","value","set","undefined","onRemove","remove"],"mappings":"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"}
@@ -471,6 +471,7 @@ const rate = (value)=>value == null ? '—' : `${Math.round(value * 100)}%`;
471
471
  quick: {
472
472
  icon: mdiOpenInNew.path,
473
473
  label: 'View account',
474
+ newTab: true,
474
475
  to: buildRoute(Route.ADMIN_USER_DETAIL, {
475
476
  uid: row.uid
476
477
  })
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/staff-org-ai-card.component.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport { aiAddonName } from '@aglyn/aglyn'\nimport { buildRoute, Route } from '@aglyn/aglyn/app-utils/console-routes'\nimport { pluginDocsHelp } from '@aglyn/aglyn/app-utils/docs-help'\nimport { mdiOpenInNew } from '@aglyn/shared-data-mdi'\nimport { AppLink, CardDisplay } from '@aglyn/shared-ui-jsx'\nimport {\n ListRowActions,\n ListTable,\n listActionsColumn,\n} from '@aglyn/shared-ui-jsx/components/list-table.component'\nimport { ScrollTable } from '@aglyn/shared-ui-jsx/components/scroll-table.component'\nimport { TABLE_ROW_HEIGHT } from '@aglyn/shared-ui-jsx/const/table-pagination'\nimport { useUser } from '@aglyn/tenant-feature-instance'\nimport { authorizedFetch } from '@aglyn/shared-util-http/authorized-token'\nimport {\n Alert,\n Chip,\n Stack,\n TableBody,\n TableCell,\n TableHead,\n TableRow,\n Typography,\n} from '@mui/material'\nimport type { GridColDef } from '@mui/x-data-grid'\nimport { useRouter } from 'next/navigation'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport type {\n StaffOrgAiJob,\n StaffOrgAiJobs,\n StaffOrgAiMargin,\n StaffOrgAiOverage,\n StaffOrgAiPool,\n StaffOrgAiRefusals,\n StaffOrgAiResponse,\n StaffOrgAiTokens,\n StaffOrgAiUser,\n} from '../usage/staff-org-ai'\nimport {\n StaffCreditReturnActions,\n StaffCreditReturnDialog,\n} from './staff-ai-credit-return.component'\n\n/**\n * THE STAFF AI CARD (AGL-2930): everything about one org's AI usage on the\n * page staff already open to look at that org.\n *\n * Read through `/api/ai/admin/org`, one request on mount. Every figure on it\n * is the route's, and every figure the route serves is composed from the\n * same helpers the meter refuses with — see `usage/staff-org-ai.ts`. This\n * file only lays them out.\n *\n * ## What each section is for\n *\n * - **Add-on** — is the org paying for AI, at what, since when.\n * - **Credit pool** — the band as three NAMED parts, because \"why does\n * this org have 13,000 credits\" has three answers (the plan, an override,\n * the add-on) and a single total cannot say which.\n * - **Overage** — what is past the band, what it is sold at, and the two\n * controls the org itself holds over it.\n * - **Refusals** — how often, and why, the gate said no this month.\n * - **Jobs** and **Top users** — the generative and per-person halves,\n * each of which says plainly when its rollup has nothing yet.\n * - **Tokens** — what each kind of request costs per request, what it\n * sends and generates, and how much of its prompt the cache served.\n * - **Margin** — spend against what AI brings in, red when it is over.\n * - **Actions** — where the override editor and the AI pause live.\n *\n * The header carries the card's two acts (AGL-3595): give credits back to\n * the band (and, on a Free workspace, to the owner's allowance), or reset\n * the month — and each recent job offers the same give-back, prefilled with\n * that job's spend.\n */\n\nconst credits = (value: number | null | undefined): string =>\n value == null ? '—' : Math.round(value).toLocaleString()\n\n/**\n * Four decimals under a dollar, two above (the assist-signals page's rule):\n * a month that really cost eight cents must not read as `$0.00`.\n */\nconst usd = (value: number | null | undefined): string => {\n if (value == null) return '—'\n const amount = Number(value) || 0\n return `$${amount.toFixed(Math.abs(amount) < 1 ? 4 : 2)}`\n}\n\nconst when = (iso: string | null): string =>\n iso ? new Date(iso).toLocaleDateString() : '—'\n\n/** The pool as one sentence naming every part that is non-zero. */\nexport function poolPartsSentence(pool: StaffOrgAiPool): string {\n const parts: string[] = []\n if (pool.overrideCredits !== null) {\n parts.push(`${credits(pool.overrideCredits)} staff override`)\n } else {\n parts.push(`${credits(pool.planCredits)} plan band`)\n }\n if (pool.addonCredits > 0) {\n parts.push(`${credits(pool.addonCredits)} ${aiAddonName()} add-on`)\n }\n return parts.join(' + ')\n}\n\n/**\n * The overage's state as one line: sold, walled, or capped — or, for an\n * uncapped staff comp (AGL-3049), nothing to sell past at all.\n */\nexport function overageStateSentence(\n overage: StaffOrgAiOverage,\n uncapped = false,\n): string {\n if (uncapped) {\n return 'Nothing is sold past a band: an uncapped staff comp has none, and bills nothing.'\n }\n if (overage.hardCap) return 'Stopped at the band — the org’s band switch is on.'\n if (!overage.sellsOverage) return 'Not sold past the band on this plan.'\n const rate =\n overage.rateUsdPer1k === null ? '' : ` at ${usd(overage.rateUsdPer1k)} per 1,000`\n if (overage.capUsd !== null) {\n return overage.capReached\n ? `Stopped — the org’s ${usd(overage.capUsd)} overage ceiling is reached.`\n : `Sold${rate}, up to the org’s ${usd(overage.capUsd)} ceiling.`\n }\n return `Sold${rate}, no ceiling set.`\n}\n\n/** Whether the margin section renders red. */\nexport function marginTone(margin: StaffOrgAiMargin): 'error' | 'warning' | 'success' {\n if (margin.underwater) return 'error'\n if (margin.multiple >= 1) return 'warning'\n return 'success'\n}\n\nfunction RefusalsRow({ refusals }: { refusals: StaffOrgAiRefusals }) {\n const labels: Record<keyof Omit<StaffOrgAiRefusals, 'total'>, string> = {\n band: 'band',\n cap: 'ceiling',\n messages: 'messages',\n budget: 'operator backstop',\n // A hard allotment a manager set on a member, a collaborator or a site\n // (AGL-2942).\n allotment: 'allotments',\n // The Free taste's rungs (AGL-2925): only a Free workspace collects these.\n account: 'free account',\n requests: 'free requests/day',\n refusals: 'free refusals/day',\n platform: 'platform ceiling',\n }\n return (\n <Stack direction=\"row\" spacing={1} useFlexGap sx={{ flexWrap: 'wrap' }}>\n {(Object.keys(labels) as Array<keyof typeof labels>).map((reason) => {\n // A reason the answering server does not yet count reads as zero,\n // so a console newer than its route draws the row rather than\n // failing the card.\n const count = Number(refusals[reason] ?? 0)\n return (\n <Chip\n key={reason}\n size=\"small\"\n variant={count > 0 ? 'filled' : 'outlined'}\n color={count > 0 ? 'warning' : 'default'}\n label={`${labels[reason]} ${count.toLocaleString()}`}\n />\n )\n })}\n </Stack>\n )\n}\n\nfunction JobsSection({\n jobs,\n onGiveBack,\n}: {\n jobs: StaffOrgAiJobs | null\n onGiveBack: (job: StaffOrgAiJob) => void\n}) {\n const columns = useMemo(() => jobColumns(onGiveBack), [onGiveBack])\n if (jobs === null) {\n return (\n <Alert severity=\"warning\">\n {'Could not read the generation jobs — a failed read, not an idle org.'}\n </Alert>\n )\n }\n const total = Object.values(jobs.counts).reduce((sum, n) => sum + n, 0)\n if (total === 0) {\n return (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'No generation jobs yet.'}\n </Typography>\n )\n }\n return (\n <Stack spacing={1}>\n <Stack direction=\"row\" spacing={1} useFlexGap sx={{ flexWrap: 'wrap' }}>\n {(['queued', 'running', 'needs_input', 'needs_review', 'failed'] as const).map((status) => (\n <Chip\n key={status}\n size=\"small\"\n color={\n status === 'failed' && jobs.counts[status] > 0\n ? 'error'\n : (status === 'needs_input' || status === 'needs_review') &&\n jobs.counts[status] > 0\n ? 'warning'\n : 'default'\n }\n label={`${status.replace('_', ' ')} ${jobs.counts[status]}`}\n />\n ))}\n <Chip size=\"small\" variant=\"outlined\" label={`done ${jobs.counts.done}`} />\n </Stack>\n {jobs.truncated ? (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {'Counted from the newest jobs only — these counts are a floor.'}\n </Typography>\n ) : null}\n {/* A record list: the grid scrolls its own columns, so a job id and a\n starter's uid never push the card's content past its edge. */}\n <ListTable\n rows={jobs.recent}\n columns={columns}\n getRowId={(job: StaffOrgAiJob) => job.id}\n rowHeight={TABLE_ROW_HEIGHT}\n noRowsLabel=\"No recent jobs\"\n // The route's ten newest jobs: a bounded readout, so no filter over\n // the rows it holds (AGL-3321).\n disableColumnFilter\n quickFilter={false}\n />\n </Stack>\n )\n}\n\n/**\n * The recent jobs, one column per fact. Who started a job is a column of\n * its own rather than a link tucked beside the date, so it sorts like the\n * rest; the credits sort by what was SPENT, which is the figure the\n * pool was charged. The row's action gives that spend back (AGL-3595).\n */\nconst jobColumns = (\n onGiveBack: (job: StaffOrgAiJob) => void,\n): GridColDef<StaffOrgAiJob>[] => [\n {\n field: 'id',\n headerName: 'Job',\n flex: 1,\n minWidth: 200,\n renderCell: ({ row }) => (\n <Typography variant=\"body2\" noWrap title={row.id} sx={{ fontFamily: 'monospace' }}>\n {row.id}\n </Typography>\n ),\n },\n {\n field: 'kind',\n headerName: 'Kind',\n width: 120,\n valueFormatter: (value: string) => value || '—',\n },\n {\n field: 'status',\n headerName: 'Status',\n width: 130,\n valueFormatter: (value: string) => String(value ?? '').replace('_', ' '),\n },\n {\n field: 'creditsSpent',\n headerName: 'Credits',\n type: 'number',\n align: 'right',\n headerAlign: 'right',\n width: 140,\n valueFormatter: (value: number, row) =>\n `${credits(value)} / ${credits(row.creditsReserved)}`,\n },\n {\n field: 'createdAt',\n headerName: 'Started',\n width: 120,\n valueFormatter: (value: string | null) => when(value),\n },\n {\n field: 'createdBy',\n headerName: 'Started by',\n flex: 1,\n minWidth: 240,\n renderCell: ({ row }) =>\n row.createdBy ? (\n <AppLink\n href={buildRoute(Route.ADMIN_USER_DETAIL, { uid: row.createdBy })}\n variant=\"body2\"\n underline=\"hover\"\n noWrap\n sx={{ fontFamily: 'monospace' }}\n >\n {row.createdBy}\n </AppLink>\n ) : (\n '—'\n ),\n },\n listActionsColumn((row: StaffOrgAiJob) => (\n <ListRowActions\n label={row.id}\n items={[\n {\n key: 'give-back',\n label: 'Give back this job’s credits',\n disabled: row.creditsSpent <= 0,\n disabledReason: row.creditsSpent <= 0 ? 'This job spent no credits.' : undefined,\n onClick: () => onGiveBack(row),\n },\n ]}\n />\n )),\n]\n\nconst tokenCount = (value: number): string => Math.round(value).toLocaleString()\n\nconst rate = (value: number | null): string =>\n value == null ? '—' : `${Math.round(value * 100)}%`\n\n/** The month's tokens, and what each kind of request spends of them (AGL-2937). */\nfunction TokensSection({ tokens }: { tokens: StaffOrgAiTokens }) {\n const { total } = tokens\n return (\n <Stack spacing={1}>\n <Stack direction=\"row\" spacing={1} useFlexGap sx={{ alignItems: 'center', flexWrap: 'wrap' }}>\n <Typography variant=\"body2\">\n {`${tokenCount(total.input)} sent · ${tokenCount(total.cached)} read from cache · ${tokenCount(total.cacheWrite)} written to cache · ${tokenCount(total.output)} generated`}\n </Typography>\n <Chip\n size=\"small\"\n color={tokens.cacheHitRate != null && tokens.cacheHitRate >= 0.5 ? 'success' : 'default'}\n label={`cache hit rate ${rate(tokens.cacheHitRate)}`}\n />\n </Stack>\n {tokens.kinds.length === 0 ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'No model requests recorded by kind this month.'}\n </Typography>\n ) : (\n <ScrollTable size=\"small\">\n <TableHead>\n <TableRow>\n <TableCell>{'Kind'}</TableCell>\n <TableCell align=\"right\">{'Requests'}</TableCell>\n <TableCell align=\"right\">{'Per request'}</TableCell>\n <TableCell align=\"right\">{'Sent'}</TableCell>\n <TableCell align=\"right\">{'From cache'}</TableCell>\n <TableCell align=\"right\">{'Generated'}</TableCell>\n <TableCell align=\"right\">{'Cache hit'}</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {tokens.kinds.map((row) => (\n <TableRow key={row.kind}>\n <TableCell>{row.kind}</TableCell>\n <TableCell align=\"right\">{row.requests.toLocaleString()}</TableCell>\n <TableCell align=\"right\">{usd(row.costPerRequestUsd)}</TableCell>\n <TableCell align=\"right\">{tokenCount(row.tokens.input)}</TableCell>\n <TableCell align=\"right\">{tokenCount(row.tokens.cached)}</TableCell>\n <TableCell align=\"right\">{tokenCount(row.tokens.output)}</TableCell>\n <TableCell align=\"right\">{rate(row.cacheHitRate)}</TableCell>\n </TableRow>\n ))}\n </TableBody>\n </ScrollTable>\n )}\n </Stack>\n )\n}\n\n/**\n * The month's top spenders, one row per person. The row opens the account;\n * the uid rides beneath the roster's name because two people can share one.\n */\nfunction TopUsersSection({ users }: { users: StaffOrgAiUser[] }) {\n const router = useRouter()\n const columns = useMemo<GridColDef<StaffOrgAiUser>[]>(\n () => [\n {\n field: 'name',\n headerName: 'Person',\n flex: 1,\n minWidth: 220,\n renderCell: ({ row }) => (\n <Stack sx={{ minWidth: 0 }}>\n <Typography variant=\"body2\" noWrap title={row.name}>\n {row.name}\n </Typography>\n {row.name !== row.uid ? (\n <Typography\n variant=\"caption\"\n color=\"text.secondary\"\n noWrap\n sx={{ fontFamily: 'monospace' }}\n >\n {row.uid}\n </Typography>\n ) : null}\n </Stack>\n ),\n },\n {\n field: 'credits',\n headerName: 'Credits',\n type: 'number',\n align: 'right',\n headerAlign: 'right',\n width: 110,\n valueFormatter: (value: number) => credits(value),\n },\n {\n field: 'share',\n headerName: 'Share',\n type: 'number',\n align: 'right',\n headerAlign: 'right',\n width: 90,\n valueFormatter: (value: number) => `${Math.round(value * 100)}%`,\n },\n {\n field: 'estCostUsd',\n headerName: 'Provider $',\n type: 'number',\n align: 'right',\n headerAlign: 'right',\n width: 120,\n valueFormatter: (value: number) => usd(value),\n },\n {\n field: 'requests',\n headerName: 'Requests',\n type: 'number',\n align: 'right',\n headerAlign: 'right',\n width: 110,\n valueFormatter: (value: number) => value.toLocaleString(),\n },\n {\n field: 'refusals',\n headerName: 'Refusals',\n type: 'number',\n align: 'right',\n headerAlign: 'right',\n width: 110,\n valueFormatter: (value: number) => value.toLocaleString(),\n },\n listActionsColumn((row: StaffOrgAiUser) => (\n <ListRowActions\n label={row.name}\n quick={{\n icon: mdiOpenInNew.path,\n label: 'View account',\n to: buildRoute(Route.ADMIN_USER_DETAIL, { uid: row.uid }),\n }}\n items={[]}\n />\n )),\n ],\n [],\n )\n return (\n <ListTable\n rows={users}\n columns={columns}\n getRowId={(row: StaffOrgAiUser) => row.uid}\n rowHeight={TABLE_ROW_HEIGHT}\n onOpen={(uid) => router.push(buildRoute(Route.ADMIN_USER_DETAIL, { uid }))}\n // The route's ten dearest members: a bounded readout, so no filter\n // over the rows it holds (AGL-3321).\n disableColumnFilter\n quickFilter={false}\n />\n )\n}\n\nconst StaffOrgAiCard = ({ orgId }: { orgId: string }) => {\n const { data: user } = useUser()\n // Keyed on who is signed in, not on the user object's identity.\n const signedInUid = user?.uid ?? null\n const userRef = useRef(user)\n userRef.current = user\n const [data, setData] = useState<StaffOrgAiResponse | null>(null)\n const [ready, setReady] = useState(false)\n const [error, setError] = useState<string | null>(null)\n // Bumped after a give-back, so the card re-reads the figures it changed.\n const [version, setVersion] = useState(0)\n const [notice, setNotice] = useState<string | null>(null)\n const [returning, setReturning] = useState<{\n mode: 'give' | 'reset'\n jobId?: string\n jobCredits?: number\n } | null>(null)\n const giveBackJob = useCallback(\n (job: StaffOrgAiJob) =>\n setReturning({ mode: 'give', jobId: job.id, jobCredits: job.creditsSpent }),\n [],\n )\n\n useEffect(() => {\n // Mounted only for a confirmed staff reader — the `staffOrg` zone sits\n // inside the page's `StaffOnly`, which renders nothing while the claim\n // loads — because the route records an access row on every successful\n // open, and an open the page did not mean to make would be an access\n // nobody made.\n const user = userRef.current\n if (!orgId || !signedInUid || !user) return undefined\n let active = true\n setReady(false)\n setError(null)\n void (async () => {\n try {\n const response = await authorizedFetch(\n user,\n `/api/ai/admin/org?orgId=${encodeURIComponent(orgId)}`,\n )\n const payload = await response.json().catch(() => null)\n if (!active) return\n if (!response.ok) {\n setError(payload?.error ?? 'AI lookup failed')\n setData(null)\n } else {\n setData(payload as StaffOrgAiResponse)\n }\n } catch {\n if (active) {\n setError('AI lookup failed')\n setData(null)\n }\n } finally {\n if (active) setReady(true)\n }\n })()\n return () => {\n active = false\n }\n }, [orgId, signedInUid, version])\n\n const name = aiAddonName()\n return (\n <CardDisplay\n header={name}\n help={pluginDocsHelp('aiMonitoring', {\n anchor: '#the-ai-card',\n excerpt:\n 'The add-on, the credit pool and its parts, this month’s overage and refusals, generation jobs, tokens and the cache hit rate by kind, the people spending the most, and the margin — for this organization.',\n })}\n HeaderProps={{\n action: (\n <StaffCreditReturnActions\n disabled={!data}\n onGive={() => setReturning({ mode: 'give' })}\n onReset={() => setReturning({ mode: 'reset' })}\n />\n ),\n }}\n contentGutterX\n contentGutterY\n >\n {data ? (\n <StaffCreditReturnDialog\n open={returning !== null}\n mode={returning?.mode ?? 'give'}\n target={{ orgId }}\n workspace={{ used: data.pool.usedCredits, limit: data.pool.totalCredits }}\n account={\n data.account\n ? { used: data.account.usedCredits, limit: data.account.limitCredits }\n : null\n }\n jobId={returning?.jobId ?? null}\n jobCredits={returning?.jobCredits ?? null}\n onClose={() => setReturning(null)}\n onReturned={(message) => {\n setReturning(null)\n setNotice(message)\n setVersion((current) => current + 1)\n }}\n />\n ) : null}\n {notice ? (\n <Alert severity=\"success\" onClose={() => setNotice(null)} sx={{ mb: 2 }}>\n {notice}\n </Alert>\n ) : null}\n {!ready ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Loading…'}\n </Typography>\n ) : error || !data ? (\n <Alert severity=\"warning\">\n {`Could not read this organization’s AI usage — ${error ?? 'a failed read'}, not zero usage.`}\n </Alert>\n ) : (\n <Stack spacing={2}>\n {/* Add-on */}\n <Stack spacing={0.5}>\n <Typography variant=\"overline\" color=\"text.secondary\">\n {'Add-on'}\n </Typography>\n <Stack useFlexGap direction=\"row\" spacing={1} sx={{ alignItems: 'center', flexWrap: 'wrap' }}>\n <Chip\n size=\"small\"\n color={data.addon.on ? 'primary' : 'default'}\n label={data.addon.on ? `${name} on` : `${name} off`}\n />\n {data.addon.priceUsd !== null ? (\n <Typography variant=\"body2\">\n {`${usd(data.addon.priceUsd)}/mo on this plan`}\n </Typography>\n ) : (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Not sold on this plan'}\n </Typography>\n )}\n {data.addon.on ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {data.addon.since\n ? `since ${when(data.addon.since)}`\n : data.addon.sinceSource === 'unavailable'\n ? 'since — (Stripe not reachable)'\n : 'since — (no subscription item)'}\n </Typography>\n ) : null}\n </Stack>\n </Stack>\n\n {/* Credit pool */}\n <Stack spacing={0.5}>\n <Typography variant=\"overline\" color=\"text.secondary\">\n {`Credit pool · ${data.month}`}\n </Typography>\n {data.pool.totalCredits === null && data.pool.uncapped ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Uncapped staff comp — no AI credit band. Bounded only by the message cap and an operator’s explicit spend ceiling.'}\n </Typography>\n ) : data.pool.totalCredits === null ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'No AI credit band on this plan — bounded by the message cap and the operator backstop.'}\n </Typography>\n ) : (\n <Typography variant=\"body2\">\n {`${credits(data.pool.totalCredits)} credits = ${poolPartsSentence(data.pool)}`}\n </Typography>\n )}\n <Typography variant=\"body2\">\n {`Used ${credits(data.pool.usedCredits)} credits (${usd(data.pool.providerUsd)} provider spend)`}\n {data.pool.remainingCredits !== null\n ? ` · ${credits(data.pool.remainingCredits)} remaining`\n : ''}\n </Typography>\n {data.pool.returnedCredits ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {`${credits(data.pool.returnedCredits)} credits given back this month — already taken off the figure above.`}\n </Typography>\n ) : null}\n {data.account ? (\n <Typography variant=\"body2\">\n {`Owner’s Free allowance: ${credits(data.account.usedCredits)} of ${credits(data.account.limitCredits)} used across their free workspaces` +\n (data.account.returnedCredits\n ? ` (${credits(data.account.returnedCredits)} given back)`\n : '')}\n </Typography>\n ) : null}\n <Typography variant=\"body2\" color=\"text.secondary\">\n {`Projected month-end at this pace: ${credits(data.pool.projectedCredits)} credits (${usd(data.pool.projectedUsd)}) · ${data.pool.messages.toLocaleString()} model turns, ${data.pool.deflected.toLocaleString()} answered from the docs`}\n </Typography>\n </Stack>\n\n {/* Overage */}\n <Stack spacing={0.5}>\n <Typography variant=\"overline\" color=\"text.secondary\">\n {'Overage'}\n </Typography>\n <Typography variant=\"body2\">\n {`${credits(data.overage.overageCredits)} credits over the band · ${usd(data.overage.accruedUsd)} accrued`}\n </Typography>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {overageStateSentence(data.overage, data.pool.uncapped === true)}\n </Typography>\n </Stack>\n\n {/* Refusals */}\n <Stack spacing={0.5}>\n <Typography variant=\"overline\" color=\"text.secondary\">\n {`Refusals this month · ${data.refusals.total.toLocaleString()}`}\n </Typography>\n <RefusalsRow refusals={data.refusals} />\n </Stack>\n\n {/* Jobs */}\n <Stack spacing={0.5}>\n <Typography variant=\"overline\" color=\"text.secondary\">\n {'Generation jobs'}\n </Typography>\n <JobsSection jobs={data.jobs} onGiveBack={giveBackJob} />\n </Stack>\n\n {/* Tokens — absent from a route older than the card */}\n {data.tokens ? (\n <Stack spacing={0.5}>\n <Typography variant=\"overline\" color=\"text.secondary\">\n {`Tokens · ${data.month}`}\n </Typography>\n <TokensSection tokens={data.tokens} />\n </Stack>\n ) : null}\n\n {/* Top users */}\n <Stack spacing={0.5}>\n <Typography variant=\"overline\" color=\"text.secondary\">\n {'Top users this month'}\n </Typography>\n {data.users.length === 0 ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'No AI usage attributed to a person this month.'}\n </Typography>\n ) : (\n <TopUsersSection users={data.users} />\n )}\n </Stack>\n\n {/* Margin */}\n <Stack spacing={0.5}>\n <Typography variant=\"overline\" color=\"text.secondary\">\n {'Margin'}\n </Typography>\n <Alert severity={marginTone(data.margin)}>\n {`Spend ${usd(data.margin.spendUsd)} against ${usd(data.margin.revenueUsd)} in — ` +\n `${usd(data.margin.addonRevenueUsd)} add-on, ${usd(data.margin.planAssistShareUsd)} plan assist share, ` +\n `${usd(data.margin.overageRevenueUsd)} overage.`}\n {data.margin.underwater\n ? ' Spend exceeds the add-on plus the plan’s assist share.'\n : ''}\n {data.margin.multiple >= 1\n ? ` ${data.margin.multiple}× the ${usd(data.margin.thresholdUsd)} staff review threshold.`\n : ''}\n </Alert>\n {data.margin.contribution.marginPct !== null ? (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {`Whole-org contribution margin ${Math.round(data.margin.contribution.marginPct * 100)}% on the ${data.margin.contribution.month} rollup with this month’s AI spend.`}\n </Typography>\n ) : null}\n </Stack>\n\n {/* Actions */}\n <Stack spacing={0.5}>\n <Typography variant=\"overline\" color=\"text.secondary\">\n {'Actions'}\n </Typography>\n <Typography variant=\"body2\">\n {'Credit override and feature toggles: '}\n <AppLink href={buildRoute(Route.ADMIN_ORGS)} underline=\"hover\">\n {'the entitlement override editor'}\n </AppLink>\n {' (also under Staff actions above). Pause AI for this org: '}\n <AppLink href={buildRoute(Route.ADMIN_LOCKDOWN)} underline=\"hover\">\n {'Lockdown'}\n </AppLink>\n {', feature keys ai-assist and ai-generate scoped to the org.'}\n </Typography>\n </Stack>\n </Stack>\n )}\n </CardDisplay>\n )\n}\nStaffOrgAiCard.displayName = 'StaffOrgAiCard'\n\nexport default StaffOrgAiCard\n"],"names":["aiAddonName","buildRoute","Route","pluginDocsHelp","mdiOpenInNew","AppLink","CardDisplay","ListRowActions","ListTable","listActionsColumn","ScrollTable","TABLE_ROW_HEIGHT","useUser","authorizedFetch","Alert","Chip","Stack","TableBody","TableCell","TableHead","TableRow","Typography","useRouter","useCallback","useEffect","useMemo","useRef","useState","StaffCreditReturnActions","StaffCreditReturnDialog","credits","value","Math","round","toLocaleString","usd","amount","Number","toFixed","abs","when","iso","Date","toLocaleDateString","poolPartsSentence","pool","parts","overrideCredits","push","planCredits","addonCredits","join","overageStateSentence","overage","uncapped","hardCap","sellsOverage","rate","rateUsdPer1k","capUsd","capReached","marginTone","margin","underwater","multiple","RefusalsRow","refusals","labels","band","cap","messages","budget","allotment","account","requests","platform","direction","spacing","useFlexGap","sx","flexWrap","Object","keys","map","reason","count","size","variant","color","label","JobsSection","jobs","onGiveBack","columns","jobColumns","severity","total","values","counts","reduce","sum","n","status","replace","done","truncated","rows","recent","getRowId","job","id","rowHeight","noRowsLabel","disableColumnFilter","quickFilter","field","headerName","flex","minWidth","renderCell","row","noWrap","title","fontFamily","width","valueFormatter","String","type","align","headerAlign","creditsReserved","createdBy","href","ADMIN_USER_DETAIL","uid","underline","items","key","disabled","creditsSpent","disabledReason","undefined","onClick","tokenCount","TokensSection","tokens","alignItems","input","cached","cacheWrite","output","cacheHitRate","kinds","length","kind","costPerRequestUsd","TopUsersSection","users","router","name","quick","icon","path","to","onOpen","StaffOrgAiCard","orgId","data","user","signedInUid","userRef","current","setData","ready","setReady","error","setError","version","setVersion","notice","setNotice","returning","setReturning","giveBackJob","mode","jobId","jobCredits","active","response","encodeURIComponent","payload","json","catch","ok","header","help","anchor","excerpt","HeaderProps","action","onGive","onReset","contentGutterX","contentGutterY","open","target","workspace","used","usedCredits","limit","totalCredits","limitCredits","onClose","onReturned","message","mb","addon","on","priceUsd","since","sinceSource","month","providerUsd","remainingCredits","returnedCredits","projectedCredits","projectedUsd","deflected","overageCredits","accruedUsd","spendUsd","revenueUsd","addonRevenueUsd","planAssistShareUsd","overageRevenueUsd","thresholdUsd","contribution","marginPct","ADMIN_ORGS","ADMIN_LOCKDOWN","displayName"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/staff-org-ai-card.component.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport { aiAddonName } from '@aglyn/aglyn'\nimport { buildRoute, Route } from '@aglyn/aglyn/app-utils/console-routes'\nimport { pluginDocsHelp } from '@aglyn/aglyn/app-utils/docs-help'\nimport { mdiOpenInNew } from '@aglyn/shared-data-mdi'\nimport { AppLink, CardDisplay } from '@aglyn/shared-ui-jsx'\nimport {\n ListRowActions,\n ListTable,\n listActionsColumn,\n} from '@aglyn/shared-ui-jsx/components/list-table.component'\nimport { ScrollTable } from '@aglyn/shared-ui-jsx/components/scroll-table.component'\nimport { TABLE_ROW_HEIGHT } from '@aglyn/shared-ui-jsx/const/table-pagination'\nimport { useUser } from '@aglyn/tenant-feature-instance'\nimport { authorizedFetch } from '@aglyn/shared-util-http/authorized-token'\nimport {\n Alert,\n Chip,\n Stack,\n TableBody,\n TableCell,\n TableHead,\n TableRow,\n Typography,\n} from '@mui/material'\nimport type { GridColDef } from '@mui/x-data-grid'\nimport { useRouter } from 'next/navigation'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport type {\n StaffOrgAiJob,\n StaffOrgAiJobs,\n StaffOrgAiMargin,\n StaffOrgAiOverage,\n StaffOrgAiPool,\n StaffOrgAiRefusals,\n StaffOrgAiResponse,\n StaffOrgAiTokens,\n StaffOrgAiUser,\n} from '../usage/staff-org-ai'\nimport {\n StaffCreditReturnActions,\n StaffCreditReturnDialog,\n} from './staff-ai-credit-return.component'\n\n/**\n * THE STAFF AI CARD (AGL-2930): everything about one org's AI usage on the\n * page staff already open to look at that org.\n *\n * Read through `/api/ai/admin/org`, one request on mount. Every figure on it\n * is the route's, and every figure the route serves is composed from the\n * same helpers the meter refuses with — see `usage/staff-org-ai.ts`. This\n * file only lays them out.\n *\n * ## What each section is for\n *\n * - **Add-on** — is the org paying for AI, at what, since when.\n * - **Credit pool** — the band as three NAMED parts, because \"why does\n * this org have 13,000 credits\" has three answers (the plan, an override,\n * the add-on) and a single total cannot say which.\n * - **Overage** — what is past the band, what it is sold at, and the two\n * controls the org itself holds over it.\n * - **Refusals** — how often, and why, the gate said no this month.\n * - **Jobs** and **Top users** — the generative and per-person halves,\n * each of which says plainly when its rollup has nothing yet.\n * - **Tokens** — what each kind of request costs per request, what it\n * sends and generates, and how much of its prompt the cache served.\n * - **Margin** — spend against what AI brings in, red when it is over.\n * - **Actions** — where the override editor and the AI pause live.\n *\n * The header carries the card's two acts (AGL-3595): give credits back to\n * the band (and, on a Free workspace, to the owner's allowance), or reset\n * the month — and each recent job offers the same give-back, prefilled with\n * that job's spend.\n */\n\nconst credits = (value: number | null | undefined): string =>\n value == null ? '—' : Math.round(value).toLocaleString()\n\n/**\n * Four decimals under a dollar, two above (the assist-signals page's rule):\n * a month that really cost eight cents must not read as `$0.00`.\n */\nconst usd = (value: number | null | undefined): string => {\n if (value == null) return '—'\n const amount = Number(value) || 0\n return `$${amount.toFixed(Math.abs(amount) < 1 ? 4 : 2)}`\n}\n\nconst when = (iso: string | null): string =>\n iso ? new Date(iso).toLocaleDateString() : '—'\n\n/** The pool as one sentence naming every part that is non-zero. */\nexport function poolPartsSentence(pool: StaffOrgAiPool): string {\n const parts: string[] = []\n if (pool.overrideCredits !== null) {\n parts.push(`${credits(pool.overrideCredits)} staff override`)\n } else {\n parts.push(`${credits(pool.planCredits)} plan band`)\n }\n if (pool.addonCredits > 0) {\n parts.push(`${credits(pool.addonCredits)} ${aiAddonName()} add-on`)\n }\n return parts.join(' + ')\n}\n\n/**\n * The overage's state as one line: sold, walled, or capped — or, for an\n * uncapped staff comp (AGL-3049), nothing to sell past at all.\n */\nexport function overageStateSentence(\n overage: StaffOrgAiOverage,\n uncapped = false,\n): string {\n if (uncapped) {\n return 'Nothing is sold past a band: an uncapped staff comp has none, and bills nothing.'\n }\n if (overage.hardCap) return 'Stopped at the band — the org’s band switch is on.'\n if (!overage.sellsOverage) return 'Not sold past the band on this plan.'\n const rate =\n overage.rateUsdPer1k === null ? '' : ` at ${usd(overage.rateUsdPer1k)} per 1,000`\n if (overage.capUsd !== null) {\n return overage.capReached\n ? `Stopped — the org’s ${usd(overage.capUsd)} overage ceiling is reached.`\n : `Sold${rate}, up to the org’s ${usd(overage.capUsd)} ceiling.`\n }\n return `Sold${rate}, no ceiling set.`\n}\n\n/** Whether the margin section renders red. */\nexport function marginTone(margin: StaffOrgAiMargin): 'error' | 'warning' | 'success' {\n if (margin.underwater) return 'error'\n if (margin.multiple >= 1) return 'warning'\n return 'success'\n}\n\nfunction RefusalsRow({ refusals }: { refusals: StaffOrgAiRefusals }) {\n const labels: Record<keyof Omit<StaffOrgAiRefusals, 'total'>, string> = {\n band: 'band',\n cap: 'ceiling',\n messages: 'messages',\n budget: 'operator backstop',\n // A hard allotment a manager set on a member, a collaborator or a site\n // (AGL-2942).\n allotment: 'allotments',\n // The Free taste's rungs (AGL-2925): only a Free workspace collects these.\n account: 'free account',\n requests: 'free requests/day',\n refusals: 'free refusals/day',\n platform: 'platform ceiling',\n }\n return (\n <Stack direction=\"row\" spacing={1} useFlexGap sx={{ flexWrap: 'wrap' }}>\n {(Object.keys(labels) as Array<keyof typeof labels>).map((reason) => {\n // A reason the answering server does not yet count reads as zero,\n // so a console newer than its route draws the row rather than\n // failing the card.\n const count = Number(refusals[reason] ?? 0)\n return (\n <Chip\n key={reason}\n size=\"small\"\n variant={count > 0 ? 'filled' : 'outlined'}\n color={count > 0 ? 'warning' : 'default'}\n label={`${labels[reason]} ${count.toLocaleString()}`}\n />\n )\n })}\n </Stack>\n )\n}\n\nfunction JobsSection({\n jobs,\n onGiveBack,\n}: {\n jobs: StaffOrgAiJobs | null\n onGiveBack: (job: StaffOrgAiJob) => void\n}) {\n const columns = useMemo(() => jobColumns(onGiveBack), [onGiveBack])\n if (jobs === null) {\n return (\n <Alert severity=\"warning\">\n {'Could not read the generation jobs — a failed read, not an idle org.'}\n </Alert>\n )\n }\n const total = Object.values(jobs.counts).reduce((sum, n) => sum + n, 0)\n if (total === 0) {\n return (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'No generation jobs yet.'}\n </Typography>\n )\n }\n return (\n <Stack spacing={1}>\n <Stack direction=\"row\" spacing={1} useFlexGap sx={{ flexWrap: 'wrap' }}>\n {(['queued', 'running', 'needs_input', 'needs_review', 'failed'] as const).map((status) => (\n <Chip\n key={status}\n size=\"small\"\n color={\n status === 'failed' && jobs.counts[status] > 0\n ? 'error'\n : (status === 'needs_input' || status === 'needs_review') &&\n jobs.counts[status] > 0\n ? 'warning'\n : 'default'\n }\n label={`${status.replace('_', ' ')} ${jobs.counts[status]}`}\n />\n ))}\n <Chip size=\"small\" variant=\"outlined\" label={`done ${jobs.counts.done}`} />\n </Stack>\n {jobs.truncated ? (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {'Counted from the newest jobs only — these counts are a floor.'}\n </Typography>\n ) : null}\n {/* A record list: the grid scrolls its own columns, so a job id and a\n starter's uid never push the card's content past its edge. */}\n <ListTable\n rows={jobs.recent}\n columns={columns}\n getRowId={(job: StaffOrgAiJob) => job.id}\n rowHeight={TABLE_ROW_HEIGHT}\n noRowsLabel=\"No recent jobs\"\n // The route's ten newest jobs: a bounded readout, so no filter over\n // the rows it holds (AGL-3321).\n disableColumnFilter\n quickFilter={false}\n />\n </Stack>\n )\n}\n\n/**\n * The recent jobs, one column per fact. Who started a job is a column of\n * its own rather than a link tucked beside the date, so it sorts like the\n * rest; the credits sort by what was SPENT, which is the figure the\n * pool was charged. The row's action gives that spend back (AGL-3595).\n */\nconst jobColumns = (\n onGiveBack: (job: StaffOrgAiJob) => void,\n): GridColDef<StaffOrgAiJob>[] => [\n {\n field: 'id',\n headerName: 'Job',\n flex: 1,\n minWidth: 200,\n renderCell: ({ row }) => (\n <Typography variant=\"body2\" noWrap title={row.id} sx={{ fontFamily: 'monospace' }}>\n {row.id}\n </Typography>\n ),\n },\n {\n field: 'kind',\n headerName: 'Kind',\n width: 120,\n valueFormatter: (value: string) => value || '—',\n },\n {\n field: 'status',\n headerName: 'Status',\n width: 130,\n valueFormatter: (value: string) => String(value ?? '').replace('_', ' '),\n },\n {\n field: 'creditsSpent',\n headerName: 'Credits',\n type: 'number',\n align: 'right',\n headerAlign: 'right',\n width: 140,\n valueFormatter: (value: number, row) =>\n `${credits(value)} / ${credits(row.creditsReserved)}`,\n },\n {\n field: 'createdAt',\n headerName: 'Started',\n width: 120,\n valueFormatter: (value: string | null) => when(value),\n },\n {\n field: 'createdBy',\n headerName: 'Started by',\n flex: 1,\n minWidth: 240,\n renderCell: ({ row }) =>\n row.createdBy ? (\n <AppLink\n href={buildRoute(Route.ADMIN_USER_DETAIL, { uid: row.createdBy })}\n variant=\"body2\"\n underline=\"hover\"\n noWrap\n sx={{ fontFamily: 'monospace' }}\n >\n {row.createdBy}\n </AppLink>\n ) : (\n '—'\n ),\n },\n listActionsColumn((row: StaffOrgAiJob) => (\n <ListRowActions\n label={row.id}\n items={[\n {\n key: 'give-back',\n label: 'Give back this job’s credits',\n disabled: row.creditsSpent <= 0,\n disabledReason: row.creditsSpent <= 0 ? 'This job spent no credits.' : undefined,\n onClick: () => onGiveBack(row),\n },\n ]}\n />\n )),\n]\n\nconst tokenCount = (value: number): string => Math.round(value).toLocaleString()\n\nconst rate = (value: number | null): string =>\n value == null ? '—' : `${Math.round(value * 100)}%`\n\n/** The month's tokens, and what each kind of request spends of them (AGL-2937). */\nfunction TokensSection({ tokens }: { tokens: StaffOrgAiTokens }) {\n const { total } = tokens\n return (\n <Stack spacing={1}>\n <Stack direction=\"row\" spacing={1} useFlexGap sx={{ alignItems: 'center', flexWrap: 'wrap' }}>\n <Typography variant=\"body2\">\n {`${tokenCount(total.input)} sent · ${tokenCount(total.cached)} read from cache · ${tokenCount(total.cacheWrite)} written to cache · ${tokenCount(total.output)} generated`}\n </Typography>\n <Chip\n size=\"small\"\n color={tokens.cacheHitRate != null && tokens.cacheHitRate >= 0.5 ? 'success' : 'default'}\n label={`cache hit rate ${rate(tokens.cacheHitRate)}`}\n />\n </Stack>\n {tokens.kinds.length === 0 ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'No model requests recorded by kind this month.'}\n </Typography>\n ) : (\n <ScrollTable size=\"small\">\n <TableHead>\n <TableRow>\n <TableCell>{'Kind'}</TableCell>\n <TableCell align=\"right\">{'Requests'}</TableCell>\n <TableCell align=\"right\">{'Per request'}</TableCell>\n <TableCell align=\"right\">{'Sent'}</TableCell>\n <TableCell align=\"right\">{'From cache'}</TableCell>\n <TableCell align=\"right\">{'Generated'}</TableCell>\n <TableCell align=\"right\">{'Cache hit'}</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {tokens.kinds.map((row) => (\n <TableRow key={row.kind}>\n <TableCell>{row.kind}</TableCell>\n <TableCell align=\"right\">{row.requests.toLocaleString()}</TableCell>\n <TableCell align=\"right\">{usd(row.costPerRequestUsd)}</TableCell>\n <TableCell align=\"right\">{tokenCount(row.tokens.input)}</TableCell>\n <TableCell align=\"right\">{tokenCount(row.tokens.cached)}</TableCell>\n <TableCell align=\"right\">{tokenCount(row.tokens.output)}</TableCell>\n <TableCell align=\"right\">{rate(row.cacheHitRate)}</TableCell>\n </TableRow>\n ))}\n </TableBody>\n </ScrollTable>\n )}\n </Stack>\n )\n}\n\n/**\n * The month's top spenders, one row per person. The row opens the account;\n * the uid rides beneath the roster's name because two people can share one.\n */\nfunction TopUsersSection({ users }: { users: StaffOrgAiUser[] }) {\n const router = useRouter()\n const columns = useMemo<GridColDef<StaffOrgAiUser>[]>(\n () => [\n {\n field: 'name',\n headerName: 'Person',\n flex: 1,\n minWidth: 220,\n renderCell: ({ row }) => (\n <Stack sx={{ minWidth: 0 }}>\n <Typography variant=\"body2\" noWrap title={row.name}>\n {row.name}\n </Typography>\n {row.name !== row.uid ? (\n <Typography\n variant=\"caption\"\n color=\"text.secondary\"\n noWrap\n sx={{ fontFamily: 'monospace' }}\n >\n {row.uid}\n </Typography>\n ) : null}\n </Stack>\n ),\n },\n {\n field: 'credits',\n headerName: 'Credits',\n type: 'number',\n align: 'right',\n headerAlign: 'right',\n width: 110,\n valueFormatter: (value: number) => credits(value),\n },\n {\n field: 'share',\n headerName: 'Share',\n type: 'number',\n align: 'right',\n headerAlign: 'right',\n width: 90,\n valueFormatter: (value: number) => `${Math.round(value * 100)}%`,\n },\n {\n field: 'estCostUsd',\n headerName: 'Provider $',\n type: 'number',\n align: 'right',\n headerAlign: 'right',\n width: 120,\n valueFormatter: (value: number) => usd(value),\n },\n {\n field: 'requests',\n headerName: 'Requests',\n type: 'number',\n align: 'right',\n headerAlign: 'right',\n width: 110,\n valueFormatter: (value: number) => value.toLocaleString(),\n },\n {\n field: 'refusals',\n headerName: 'Refusals',\n type: 'number',\n align: 'right',\n headerAlign: 'right',\n width: 110,\n valueFormatter: (value: number) => value.toLocaleString(),\n },\n listActionsColumn((row: StaffOrgAiUser) => (\n <ListRowActions\n label={row.name}\n quick={{\n icon: mdiOpenInNew.path,\n label: 'View account',\n newTab: true,\n to: buildRoute(Route.ADMIN_USER_DETAIL, { uid: row.uid }),\n }}\n items={[]}\n />\n )),\n ],\n [],\n )\n return (\n <ListTable\n rows={users}\n columns={columns}\n getRowId={(row: StaffOrgAiUser) => row.uid}\n rowHeight={TABLE_ROW_HEIGHT}\n onOpen={(uid) => router.push(buildRoute(Route.ADMIN_USER_DETAIL, { uid }))}\n // The route's ten dearest members: a bounded readout, so no filter\n // over the rows it holds (AGL-3321).\n disableColumnFilter\n quickFilter={false}\n />\n )\n}\n\nconst StaffOrgAiCard = ({ orgId }: { orgId: string }) => {\n const { data: user } = useUser()\n // Keyed on who is signed in, not on the user object's identity.\n const signedInUid = user?.uid ?? null\n const userRef = useRef(user)\n userRef.current = user\n const [data, setData] = useState<StaffOrgAiResponse | null>(null)\n const [ready, setReady] = useState(false)\n const [error, setError] = useState<string | null>(null)\n // Bumped after a give-back, so the card re-reads the figures it changed.\n const [version, setVersion] = useState(0)\n const [notice, setNotice] = useState<string | null>(null)\n const [returning, setReturning] = useState<{\n mode: 'give' | 'reset'\n jobId?: string\n jobCredits?: number\n } | null>(null)\n const giveBackJob = useCallback(\n (job: StaffOrgAiJob) =>\n setReturning({ mode: 'give', jobId: job.id, jobCredits: job.creditsSpent }),\n [],\n )\n\n useEffect(() => {\n // Mounted only for a confirmed staff reader — the `staffOrg` zone sits\n // inside the page's `StaffOnly`, which renders nothing while the claim\n // loads — because the route records an access row on every successful\n // open, and an open the page did not mean to make would be an access\n // nobody made.\n const user = userRef.current\n if (!orgId || !signedInUid || !user) return undefined\n let active = true\n setReady(false)\n setError(null)\n void (async () => {\n try {\n const response = await authorizedFetch(\n user,\n `/api/ai/admin/org?orgId=${encodeURIComponent(orgId)}`,\n )\n const payload = await response.json().catch(() => null)\n if (!active) return\n if (!response.ok) {\n setError(payload?.error ?? 'AI lookup failed')\n setData(null)\n } else {\n setData(payload as StaffOrgAiResponse)\n }\n } catch {\n if (active) {\n setError('AI lookup failed')\n setData(null)\n }\n } finally {\n if (active) setReady(true)\n }\n })()\n return () => {\n active = false\n }\n }, [orgId, signedInUid, version])\n\n const name = aiAddonName()\n return (\n <CardDisplay\n header={name}\n help={pluginDocsHelp('aiMonitoring', {\n anchor: '#the-ai-card',\n excerpt:\n 'The add-on, the credit pool and its parts, this month’s overage and refusals, generation jobs, tokens and the cache hit rate by kind, the people spending the most, and the margin — for this organization.',\n })}\n HeaderProps={{\n action: (\n <StaffCreditReturnActions\n disabled={!data}\n onGive={() => setReturning({ mode: 'give' })}\n onReset={() => setReturning({ mode: 'reset' })}\n />\n ),\n }}\n contentGutterX\n contentGutterY\n >\n {data ? (\n <StaffCreditReturnDialog\n open={returning !== null}\n mode={returning?.mode ?? 'give'}\n target={{ orgId }}\n workspace={{ used: data.pool.usedCredits, limit: data.pool.totalCredits }}\n account={\n data.account\n ? { used: data.account.usedCredits, limit: data.account.limitCredits }\n : null\n }\n jobId={returning?.jobId ?? null}\n jobCredits={returning?.jobCredits ?? null}\n onClose={() => setReturning(null)}\n onReturned={(message) => {\n setReturning(null)\n setNotice(message)\n setVersion((current) => current + 1)\n }}\n />\n ) : null}\n {notice ? (\n <Alert severity=\"success\" onClose={() => setNotice(null)} sx={{ mb: 2 }}>\n {notice}\n </Alert>\n ) : null}\n {!ready ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Loading…'}\n </Typography>\n ) : error || !data ? (\n <Alert severity=\"warning\">\n {`Could not read this organization’s AI usage — ${error ?? 'a failed read'}, not zero usage.`}\n </Alert>\n ) : (\n <Stack spacing={2}>\n {/* Add-on */}\n <Stack spacing={0.5}>\n <Typography variant=\"overline\" color=\"text.secondary\">\n {'Add-on'}\n </Typography>\n <Stack useFlexGap direction=\"row\" spacing={1} sx={{ alignItems: 'center', flexWrap: 'wrap' }}>\n <Chip\n size=\"small\"\n color={data.addon.on ? 'primary' : 'default'}\n label={data.addon.on ? `${name} on` : `${name} off`}\n />\n {data.addon.priceUsd !== null ? (\n <Typography variant=\"body2\">\n {`${usd(data.addon.priceUsd)}/mo on this plan`}\n </Typography>\n ) : (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Not sold on this plan'}\n </Typography>\n )}\n {data.addon.on ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {data.addon.since\n ? `since ${when(data.addon.since)}`\n : data.addon.sinceSource === 'unavailable'\n ? 'since — (Stripe not reachable)'\n : 'since — (no subscription item)'}\n </Typography>\n ) : null}\n </Stack>\n </Stack>\n\n {/* Credit pool */}\n <Stack spacing={0.5}>\n <Typography variant=\"overline\" color=\"text.secondary\">\n {`Credit pool · ${data.month}`}\n </Typography>\n {data.pool.totalCredits === null && data.pool.uncapped ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Uncapped staff comp — no AI credit band. Bounded only by the message cap and an operator’s explicit spend ceiling.'}\n </Typography>\n ) : data.pool.totalCredits === null ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'No AI credit band on this plan — bounded by the message cap and the operator backstop.'}\n </Typography>\n ) : (\n <Typography variant=\"body2\">\n {`${credits(data.pool.totalCredits)} credits = ${poolPartsSentence(data.pool)}`}\n </Typography>\n )}\n <Typography variant=\"body2\">\n {`Used ${credits(data.pool.usedCredits)} credits (${usd(data.pool.providerUsd)} provider spend)`}\n {data.pool.remainingCredits !== null\n ? ` · ${credits(data.pool.remainingCredits)} remaining`\n : ''}\n </Typography>\n {data.pool.returnedCredits ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {`${credits(data.pool.returnedCredits)} credits given back this month — already taken off the figure above.`}\n </Typography>\n ) : null}\n {data.account ? (\n <Typography variant=\"body2\">\n {`Owner’s Free allowance: ${credits(data.account.usedCredits)} of ${credits(data.account.limitCredits)} used across their free workspaces` +\n (data.account.returnedCredits\n ? ` (${credits(data.account.returnedCredits)} given back)`\n : '')}\n </Typography>\n ) : null}\n <Typography variant=\"body2\" color=\"text.secondary\">\n {`Projected month-end at this pace: ${credits(data.pool.projectedCredits)} credits (${usd(data.pool.projectedUsd)}) · ${data.pool.messages.toLocaleString()} model turns, ${data.pool.deflected.toLocaleString()} answered from the docs`}\n </Typography>\n </Stack>\n\n {/* Overage */}\n <Stack spacing={0.5}>\n <Typography variant=\"overline\" color=\"text.secondary\">\n {'Overage'}\n </Typography>\n <Typography variant=\"body2\">\n {`${credits(data.overage.overageCredits)} credits over the band · ${usd(data.overage.accruedUsd)} accrued`}\n </Typography>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {overageStateSentence(data.overage, data.pool.uncapped === true)}\n </Typography>\n </Stack>\n\n {/* Refusals */}\n <Stack spacing={0.5}>\n <Typography variant=\"overline\" color=\"text.secondary\">\n {`Refusals this month · ${data.refusals.total.toLocaleString()}`}\n </Typography>\n <RefusalsRow refusals={data.refusals} />\n </Stack>\n\n {/* Jobs */}\n <Stack spacing={0.5}>\n <Typography variant=\"overline\" color=\"text.secondary\">\n {'Generation jobs'}\n </Typography>\n <JobsSection jobs={data.jobs} onGiveBack={giveBackJob} />\n </Stack>\n\n {/* Tokens — absent from a route older than the card */}\n {data.tokens ? (\n <Stack spacing={0.5}>\n <Typography variant=\"overline\" color=\"text.secondary\">\n {`Tokens · ${data.month}`}\n </Typography>\n <TokensSection tokens={data.tokens} />\n </Stack>\n ) : null}\n\n {/* Top users */}\n <Stack spacing={0.5}>\n <Typography variant=\"overline\" color=\"text.secondary\">\n {'Top users this month'}\n </Typography>\n {data.users.length === 0 ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'No AI usage attributed to a person this month.'}\n </Typography>\n ) : (\n <TopUsersSection users={data.users} />\n )}\n </Stack>\n\n {/* Margin */}\n <Stack spacing={0.5}>\n <Typography variant=\"overline\" color=\"text.secondary\">\n {'Margin'}\n </Typography>\n <Alert severity={marginTone(data.margin)}>\n {`Spend ${usd(data.margin.spendUsd)} against ${usd(data.margin.revenueUsd)} in — ` +\n `${usd(data.margin.addonRevenueUsd)} add-on, ${usd(data.margin.planAssistShareUsd)} plan assist share, ` +\n `${usd(data.margin.overageRevenueUsd)} overage.`}\n {data.margin.underwater\n ? ' Spend exceeds the add-on plus the plan’s assist share.'\n : ''}\n {data.margin.multiple >= 1\n ? ` ${data.margin.multiple}× the ${usd(data.margin.thresholdUsd)} staff review threshold.`\n : ''}\n </Alert>\n {data.margin.contribution.marginPct !== null ? (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {`Whole-org contribution margin ${Math.round(data.margin.contribution.marginPct * 100)}% on the ${data.margin.contribution.month} rollup with this month’s AI spend.`}\n </Typography>\n ) : null}\n </Stack>\n\n {/* Actions */}\n <Stack spacing={0.5}>\n <Typography variant=\"overline\" color=\"text.secondary\">\n {'Actions'}\n </Typography>\n <Typography variant=\"body2\">\n {'Credit override and feature toggles: '}\n <AppLink href={buildRoute(Route.ADMIN_ORGS)} underline=\"hover\">\n {'the entitlement override editor'}\n </AppLink>\n {' (also under Staff actions above). Pause AI for this org: '}\n <AppLink href={buildRoute(Route.ADMIN_LOCKDOWN)} underline=\"hover\">\n {'Lockdown'}\n </AppLink>\n {', feature keys ai-assist and ai-generate scoped to the org.'}\n </Typography>\n </Stack>\n </Stack>\n )}\n </CardDisplay>\n )\n}\nStaffOrgAiCard.displayName = 'StaffOrgAiCard'\n\nexport default StaffOrgAiCard\n"],"names":["aiAddonName","buildRoute","Route","pluginDocsHelp","mdiOpenInNew","AppLink","CardDisplay","ListRowActions","ListTable","listActionsColumn","ScrollTable","TABLE_ROW_HEIGHT","useUser","authorizedFetch","Alert","Chip","Stack","TableBody","TableCell","TableHead","TableRow","Typography","useRouter","useCallback","useEffect","useMemo","useRef","useState","StaffCreditReturnActions","StaffCreditReturnDialog","credits","value","Math","round","toLocaleString","usd","amount","Number","toFixed","abs","when","iso","Date","toLocaleDateString","poolPartsSentence","pool","parts","overrideCredits","push","planCredits","addonCredits","join","overageStateSentence","overage","uncapped","hardCap","sellsOverage","rate","rateUsdPer1k","capUsd","capReached","marginTone","margin","underwater","multiple","RefusalsRow","refusals","labels","band","cap","messages","budget","allotment","account","requests","platform","direction","spacing","useFlexGap","sx","flexWrap","Object","keys","map","reason","count","size","variant","color","label","JobsSection","jobs","onGiveBack","columns","jobColumns","severity","total","values","counts","reduce","sum","n","status","replace","done","truncated","rows","recent","getRowId","job","id","rowHeight","noRowsLabel","disableColumnFilter","quickFilter","field","headerName","flex","minWidth","renderCell","row","noWrap","title","fontFamily","width","valueFormatter","String","type","align","headerAlign","creditsReserved","createdBy","href","ADMIN_USER_DETAIL","uid","underline","items","key","disabled","creditsSpent","disabledReason","undefined","onClick","tokenCount","TokensSection","tokens","alignItems","input","cached","cacheWrite","output","cacheHitRate","kinds","length","kind","costPerRequestUsd","TopUsersSection","users","router","name","quick","icon","path","newTab","to","onOpen","StaffOrgAiCard","orgId","data","user","signedInUid","userRef","current","setData","ready","setReady","error","setError","version","setVersion","notice","setNotice","returning","setReturning","giveBackJob","mode","jobId","jobCredits","active","response","encodeURIComponent","payload","json","catch","ok","header","help","anchor","excerpt","HeaderProps","action","onGive","onReset","contentGutterX","contentGutterY","open","target","workspace","used","usedCredits","limit","totalCredits","limitCredits","onClose","onReturned","message","mb","addon","on","priceUsd","since","sinceSource","month","providerUsd","remainingCredits","returnedCredits","projectedCredits","projectedUsd","deflected","overageCredits","accruedUsd","spendUsd","revenueUsd","addonRevenueUsd","planAssistShareUsd","overageRevenueUsd","thresholdUsd","contribution","marginPct","ADMIN_ORGS","ADMIN_LOCKDOWN","displayName"],"mappings":"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"}
@@ -14,10 +14,16 @@
14
14
  * See the License for the specific language governing permissions and
15
15
  * limitations under the License.
16
16
  */
17
+ /** The anchor an activity row's "Open the AI job" link lands on. */
18
+ export declare const STAFF_AI_REQUESTS_ANCHOR = "aglyn-ai-requests";
19
+ export interface StaffAiRequestsProps {
20
+ /** The staff org page: this organization's requests. */
21
+ orgId?: string;
22
+ /** The staff account page: this account's requests, in every org. */
23
+ uid?: string;
24
+ }
17
25
  declare const StaffOrgAiConversations: {
18
- ({ orgId }: {
19
- orgId: string;
20
- }): import("react").JSX.Element;
26
+ ({ orgId, uid }: StaffAiRequestsProps): import("react").JSX.Element;
21
27
  displayName: string;
22
28
  };
23
29
  export default StaffOrgAiConversations;