@burdenoff/microfe-subscriberbot 2026.1023.1 → 2026.1029.1

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 (46) hide show
  1. package/dist/subscriberbot/admin/AdminDashboardPage.js +5 -5
  2. package/dist/subscriberbot/admin/AdminDashboardPage.js.map +1 -1
  3. package/dist/subscriberbot/components/PostureOptions.d.ts +10 -0
  4. package/dist/subscriberbot/components/PostureOptions.d.ts.map +1 -0
  5. package/dist/subscriberbot/components/PostureOptions.js +20 -0
  6. package/dist/subscriberbot/components/PostureOptions.js.map +1 -0
  7. package/dist/subscriberbot/components/index.d.ts +2 -0
  8. package/dist/subscriberbot/components/index.d.ts.map +1 -1
  9. package/dist/subscriberbot/components/index.js +1 -0
  10. package/dist/subscriberbot/hooks/index.d.ts +1 -0
  11. package/dist/subscriberbot/hooks/index.d.ts.map +1 -1
  12. package/dist/subscriberbot/hooks/index.js +2 -1
  13. package/dist/subscriberbot/hooks/useAutonomousAgentMode.d.ts +15 -0
  14. package/dist/subscriberbot/hooks/useAutonomousAgentMode.d.ts.map +1 -0
  15. package/dist/subscriberbot/hooks/useAutonomousAgentMode.js +13 -0
  16. package/dist/subscriberbot/hooks/useAutonomousAgentMode.js.map +1 -0
  17. package/dist/subscriberbot/hooks/useSubscriberBotApi.d.ts.map +1 -1
  18. package/dist/subscriberbot/hooks/useSubscriberBotApi.js +9 -0
  19. package/dist/subscriberbot/hooks/useSubscriberBotApi.js.map +1 -1
  20. package/dist/subscriberbot/pages/AssetVaultPage.js +16 -16
  21. package/dist/subscriberbot/pages/DashboardPage.js +23 -23
  22. package/dist/subscriberbot/pages/DashboardPage.js.map +1 -1
  23. package/dist/subscriberbot/pages/InboxPage.js +62 -62
  24. package/dist/subscriberbot/pages/InsightsPage.js +14 -14
  25. package/dist/subscriberbot/pages/InvoicesPage.js +66 -66
  26. package/dist/subscriberbot/pages/WorkflowsPage.js +20 -20
  27. package/dist/subscriberbot/pages/agents/AgentDetailPage.d.ts.map +1 -1
  28. package/dist/subscriberbot/pages/agents/AgentDetailPage.js +184 -182
  29. package/dist/subscriberbot/pages/agents/AgentDetailPage.js.map +1 -1
  30. package/dist/subscriberbot/pages/agents/AgentNewPage.d.ts.map +1 -1
  31. package/dist/subscriberbot/pages/agents/AgentNewPage.js +77 -79
  32. package/dist/subscriberbot/pages/agents/AgentNewPage.js.map +1 -1
  33. package/dist/subscriberbot/pages/agents/AgentsListPage.d.ts.map +1 -1
  34. package/dist/subscriberbot/pages/agents/AgentsListPage.js +134 -133
  35. package/dist/subscriberbot/pages/agents/AgentsListPage.js.map +1 -1
  36. package/dist/subscriberbot/pages/providers/ProviderDetailPage.js +64 -64
  37. package/dist/subscriberbot/pages/providers/ProviderNewPage.js +3 -3
  38. package/dist/subscriberbot/pages/providers/ProvidersListPage.js +18 -18
  39. package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.d.ts.map +1 -1
  40. package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.js +122 -89
  41. package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.js.map +1 -1
  42. package/dist/subscriberbot/pages/relationships/RelationshipNewPage.js +6 -6
  43. package/dist/subscriberbot/pages/relationships/RelationshipsListPage.js +7 -7
  44. package/dist/subscriberbot/types/index.d.ts +1 -0
  45. package/dist/subscriberbot/types/index.d.ts.map +1 -1
  46. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"useSubscriberBotApi.js","names":[],"sources":["../../../src/subscriberbot/hooks/useSubscriberBotApi.ts"],"sourcesContent":["/**\n * SubscriberBot API hooks\n * @module subscriberbot/hooks\n *\n * React-Query hooks wired DIRECTLY to the real `wspace-subscriberbot-svc`\n * federated GraphQL contract (the `Sub*` operations). Every query/mutation\n * below uses an inline gql string whose fields match the svc\n * `.hive-schema.graphql` exactly. No mock data.\n *\n * Transport: `graphqlFetch({ gateway: 'workspace', workspaceToken: true })`\n * — the same pattern the workspace MFEs use; the host shell supplies the\n * gateway base URL + a workspace-scoped token.\n */\n\nimport { useCallback, useState } from 'react';\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';\nimport { graphqlFetch } from '@burdenoff/fe-libs/shared/graphql';\n// clearGraphqlFetchResponseCache is re-exported from the barrel only in newer\n// fe-libs; import it from its defining module so this works on the pinned\n// 2026.625.5 without forcing a risky fe-libs major bump.\nimport { clearGraphqlFetchResponseCache } from '@burdenoff/fe-libs/shared/graphql/fetch';\n\nimport { useSubscriberBot } from '../context';\nimport type {\n PaginationInput,\n SubAdapterSubmission,\n SubAgentKind,\n SubAgentStatus,\n SubAiAgent,\n SubAsset,\n SubBenchmarkDataPoint,\n SubBenchmarkFilterInput,\n SubCommunicationChannel,\n SubConnection,\n SubCreateAgentInput,\n SubCreateAssetInput,\n SubCreateChannelInput,\n SubCreateEntitlementInput,\n SubCreateInvoiceInput,\n SubCreatePaymentInstrumentInput,\n SubCreatePlanInput,\n SubCreatePolicyInput,\n SubCreateProviderInput,\n SubCreateRelationshipInput,\n SubCreateWorkflowInput,\n SubEntitlement,\n SubInboxMessage,\n SubIngestMessageInput,\n SubInvoice,\n SubInvoiceStatus,\n SubMarketplaceReport,\n SubMessageCategory,\n SubModerationAction,\n SubPaymentInstrument,\n SubPlan,\n SubPolicy,\n SubProvider,\n SubProviderCategory,\n SubProviderStatus,\n SubRelationship,\n SubRelationshipKind,\n SubRelationshipStatus,\n SubRenewalEvent,\n SubReportStatus,\n SubSubmissionStatus,\n SubUpdateProviderInput,\n SubUpdateRelationshipInput,\n SubWorkflow,\n SubWorkflowStatus,\n} from '../types';\n\n// ============================================================================\n// Transport\n// ============================================================================\n\nconst subQuery = async <TData>(\n query: string,\n variables: Record<string, unknown>,\n baseUrl?: string\n): Promise<TData> => {\n const response = await graphqlFetch<TData>({\n gateway: 'workspace',\n baseUrl,\n query,\n variables,\n workspaceToken: true,\n });\n\n if (response.errors?.length) {\n throw new Error(response.errors[0]?.message ?? 'GraphQL request failed');\n }\n if (!response.data) {\n throw new Error('GraphQL response did not include data');\n }\n // A mutation just changed server state. fe-libs' graphqlFetch keeps a ~15s\n // global response micro-cache keyed by query+vars, so the react-query refetch\n // that an onSuccess triggers would otherwise be served the STALE pre-write\n // response (a newly created provider/relationship/agent wouldn't appear, a\n // just-marked-read message would still show unread) until the TTL expires.\n // Drop that cache here — centralized so no mutation call site can forget it.\n if (/^\\s*mutation\\b/.test(query)) {\n clearGraphqlFetchResponseCache();\n }\n return response.data;\n};\n\n// React-Query key roots (one namespace per domain entity).\nconst KEY = {\n relationships: ['subscriberbot', 'relationships'] as const,\n relationship: (id: string) => ['subscriberbot', 'relationship', id] as const,\n providers: ['subscriberbot', 'providers'] as const,\n provider: (id: string) => ['subscriberbot', 'provider', id] as const,\n plans: ['subscriberbot', 'plans'] as const,\n benchmarks: (providerSlug: string) => ['subscriberbot', 'benchmarks', providerSlug] as const,\n inbox: ['subscriberbot', 'inbox'] as const,\n invoices: ['subscriberbot', 'invoices'] as const,\n paymentInstruments: ['subscriberbot', 'payment-instruments'] as const,\n channels: ['subscriberbot', 'channels'] as const,\n agents: ['subscriberbot', 'agents'] as const,\n agent: (id: string) => ['subscriberbot', 'agent', id] as const,\n workflows: ['subscriberbot', 'workflows'] as const,\n renewals: ['subscriberbot', 'renewals'] as const,\n assets: ['subscriberbot', 'assets'] as const,\n entitlements: ['subscriberbot', 'entitlements'] as const,\n adapterSubmissions: ['subscriberbot', 'admin', 'adapter-submissions'] as const,\n marketplaceReports: ['subscriberbot', 'admin', 'marketplace-reports'] as const,\n} as const;\n\n// ============================================================================\n// Reusable gql field selections (kept inline-string for codegen-free strictness)\n// ============================================================================\n\nconst PROVIDER_FIELDS = `\n id name slug category status description industry region language websiteUrl\n logoFileId tags churnRiskScore vendorHealthScore workspaceId createdAt updatedAt\n`;\n\nconst PLAN_FIELDS = `\n id name description providerId amount currency interval features isActive\n workspaceId createdAt updatedAt\n`;\n\nconst RELATIONSHIP_FIELDS = `\n id label kind status amount currency interval autoRenew discoverySource notes\n tags healthScore ownerId providerId planId startedAt renewsAt trialEndsAt\n cancelledAt workspaceId createdAt updatedAt\n`;\n\nconst INBOX_FIELDS = `\n id subject preview category categoryConfidence channelId relationshipId\n externalId actionRequired isRead receivedAt workspaceId createdAt updatedAt\n`;\n\nconst INVOICE_FIELDS = `\n id number relationshipId status currency subtotal taxAmount total issueDate\n dueDate paidAt paymentInstrumentId workspaceId createdAt updatedAt\n`;\n\nconst AGENT_FIELDS = `\n id name description kind status ownerId lastRunAt workspaceId createdAt updatedAt\n`;\n\nconst WORKFLOW_FIELDS = `\n id name description triggerEvent status runCount lastRunAt workspaceId\n createdAt updatedAt\n`;\n\nconst ENTITLEMENT_FIELDS = `\n id name description type relationshipId quota used unit isActive\n workspaceId createdAt updatedAt\n`;\n\nconst ASSET_FIELDS = `\n id name type relationshipId secretRef expiresAt workspaceId createdAt\n updatedAt file { id }\n`;\n\nconst PAYMENT_INSTRUMENT_FIELDS = `\n id label type status brand last4 expiryMonth expiryYear isDefault ownerId\n workspaceId createdAt updatedAt\n`;\n\nconst CHANNEL_FIELDS = `\n id label type status address ingestEnabled ownerId verifiedAt workspaceId\n createdAt updatedAt\n`;\n\nconst POLICY_FIELDS = `\n id name description action agentId condition isEnabled triggerCount\n lastTriggeredAt workspaceId createdAt updatedAt\n`;\n\nconst BENCHMARK_DATA_POINT_FIELDS = `\n id providerSlug providerName planName region currency interval amount\n contractSizeSeats sourceKind sourceLabel notes observedAt createdAt\n`;\n\nconst ADAPTER_SUBMISSION_FIELDS = `\n id workspaceId adapterId submitterWorkspaceId status notes createdAt updatedAt\n`;\n\nconst MARKETPLACE_REPORT_FIELDS = `\n id workspaceId listingId reporterWorkspaceId reason status resolutionReason\n createdAt updatedAt\n`;\n\n// ============================================================================\n// Relationships (the core domain object)\n// ============================================================================\n\nexport interface RelationshipListFilters {\n kind?: SubRelationshipKind;\n status?: SubRelationshipStatus;\n providerId?: string;\n ownerId?: string;\n /** Case-insensitive substring match on the relationship label (server-side). */\n search?: string;\n pagination?: PaginationInput;\n}\n\nexport const useRelationships = (filters: RelationshipListFilters = {}) => {\n const { apiGatewayUrl } = useSubscriberBot();\n return useQuery({\n queryKey: [...KEY.relationships, filters],\n queryFn: async () => {\n const result = await subQuery<{\n subListRelationships: SubConnection<SubRelationship>;\n }>(\n `query SubRelationships(\n $kind: SubRelationshipKind\n $status: SubRelationshipStatus\n $providerId: ID\n $ownerId: ID\n $search: String\n $pagination: PaginationInput\n ) {\n subListRelationships(\n kind: $kind\n status: $status\n providerId: $providerId\n ownerId: $ownerId\n search: $search\n pagination: $pagination\n ) {\n items {\n ${RELATIONSHIP_FIELDS}\n provider { id name category status logoFileId }\n plan { id name amount currency interval }\n }\n pageInfo { cursor hasMore }\n }\n }`,\n {\n kind: filters.kind,\n status: filters.status,\n providerId: filters.providerId,\n ownerId: filters.ownerId,\n search: filters.search,\n pagination: filters.pagination ?? { limit: 50, offset: 0 },\n },\n apiGatewayUrl\n );\n return result.subListRelationships;\n },\n });\n};\n\nexport const useRelationship = (id: string | undefined) => {\n const { apiGatewayUrl } = useSubscriberBot();\n return useQuery({\n queryKey: KEY.relationship(id ?? ''),\n enabled: Boolean(id),\n queryFn: async () => {\n const result = await subQuery<{ subRelationship: SubRelationship | null }>(\n `query SubRelationship($id: ID!) {\n subRelationship(id: $id) {\n ${RELATIONSHIP_FIELDS}\n provider { ${PROVIDER_FIELDS} }\n plan { ${PLAN_FIELDS} }\n entitlements {\n id name description type relationshipId quota used unit isActive\n workspaceId createdAt updatedAt\n }\n assets {\n id name type relationshipId secretRef expiresAt workspaceId\n createdAt updatedAt file { id }\n }\n renewalEvents {\n id relationshipId eventType occursAt amount currency detail\n notified workspaceId createdAt updatedAt\n }\n }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.subRelationship;\n },\n });\n};\n\nexport const useCreateRelationship = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async (input: SubCreateRelationshipInput) => {\n const result = await subQuery<{ subCreateRelationship: SubRelationship }>(\n `mutation SubCreateRelationship($input: SubCreateRelationshipInput!) {\n subCreateRelationship(input: $input) { ${RELATIONSHIP_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.subCreateRelationship;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: KEY.relationships });\n },\n });\n};\n\nexport const useTransitionRelationship = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async ({ id, status }: { id: string; status: SubRelationshipStatus }) => {\n const result = await subQuery<{ subTransitionRelationship: SubRelationship }>(\n `mutation SubTransitionRelationship($id: ID!, $status: SubRelationshipStatus!) {\n subTransitionRelationship(id: $id, status: $status) { ${RELATIONSHIP_FIELDS} }\n }`,\n { id, status },\n apiGatewayUrl\n );\n return result.subTransitionRelationship;\n },\n onSuccess: (data) => {\n void queryClient.invalidateQueries({ queryKey: KEY.relationships });\n void queryClient.invalidateQueries({ queryKey: KEY.relationship(data.id) });\n },\n });\n};\n\nexport const useCancelRelationship = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await subQuery<{ subCancelRelationship: SubRelationship }>(\n `mutation SubCancelRelationship($id: ID!) {\n subCancelRelationship(id: $id) { ${RELATIONSHIP_FIELDS} }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.subCancelRelationship;\n },\n onSuccess: (data) => {\n void queryClient.invalidateQueries({ queryKey: KEY.relationships });\n void queryClient.invalidateQueries({ queryKey: KEY.relationship(data.id) });\n },\n });\n};\n\nexport const useUpdateRelationship = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async ({ id, input }: { id: string; input: SubUpdateRelationshipInput }) => {\n const result = await subQuery<{ subUpdateRelationship: SubRelationship }>(\n `mutation SubUpdateRelationship($id: ID!, $input: SubUpdateRelationshipInput!) {\n subUpdateRelationship(id: $id, input: $input) { ${RELATIONSHIP_FIELDS} }\n }`,\n { id, input },\n apiGatewayUrl\n );\n return result.subUpdateRelationship;\n },\n onSuccess: (data) => {\n void queryClient.invalidateQueries({ queryKey: KEY.relationships });\n void queryClient.invalidateQueries({ queryKey: KEY.relationship(data.id) });\n },\n });\n};\n\nexport const useRenewalEvents = (\n args: { relationshipId?: string; upcomingOnly?: boolean } = {}\n) => {\n const { apiGatewayUrl } = useSubscriberBot();\n return useQuery({\n queryKey: [...KEY.renewals, args],\n queryFn: async () => {\n // subListRenewalEvents returns SubRenewalEventConnection (items/pageInfo),\n // not a bare list — matching every other subList* root field in this\n // schema (see useRelationships above). Selecting event fields directly\n // fails GraphQL validation server-side (`Cannot query field \"id\" on type\n // \"SubRenewalEventConnection\"`).\n const result = await subQuery<{\n subListRenewalEvents: SubConnection<SubRenewalEvent>;\n }>(\n `query SubRenewalEvents($relationshipId: ID, $upcomingOnly: Boolean) {\n subListRenewalEvents(relationshipId: $relationshipId, upcomingOnly: $upcomingOnly) {\n items {\n id relationshipId eventType occursAt amount currency detail notified\n workspaceId createdAt updatedAt\n }\n pageInfo { cursor hasMore }\n }\n }`,\n { relationshipId: args.relationshipId, upcomingOnly: args.upcomingOnly },\n apiGatewayUrl\n );\n return result.subListRenewalEvents.items;\n },\n });\n};\n\nexport const useEntitlements = (relationshipId: string | undefined) => {\n const { apiGatewayUrl } = useSubscriberBot();\n return useQuery({\n queryKey: [...KEY.entitlements, relationshipId],\n enabled: Boolean(relationshipId),\n queryFn: async () => {\n const result = await subQuery<{\n subListEntitlements: SubConnection<SubEntitlement>;\n }>(\n `query SubEntitlements($relationshipId: ID!) {\n subListEntitlements(relationshipId: $relationshipId) {\n items {\n id name description type relationshipId quota used unit isActive\n workspaceId createdAt updatedAt\n }\n pageInfo { cursor hasMore }\n }\n }`,\n { relationshipId },\n apiGatewayUrl\n );\n return result.subListEntitlements.items;\n },\n });\n};\n\nexport const useCreateEntitlement = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async (input: SubCreateEntitlementInput) => {\n const result = await subQuery<{ subCreateEntitlement: SubEntitlement }>(\n `mutation SubCreateEntitlement($input: SubCreateEntitlementInput!) {\n subCreateEntitlement(input: $input) { ${ENTITLEMENT_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.subCreateEntitlement;\n },\n onSuccess: (data) => {\n void queryClient.invalidateQueries({ queryKey: KEY.entitlements });\n void queryClient.invalidateQueries({ queryKey: KEY.relationship(data.relationshipId) });\n },\n });\n};\n\nexport const useAssets = (relationshipId: string | undefined) => {\n const { apiGatewayUrl } = useSubscriberBot();\n return useQuery({\n queryKey: [...KEY.assets, relationshipId],\n enabled: Boolean(relationshipId),\n queryFn: async () => {\n const result = await subQuery<{ subListAssets: SubConnection<SubAsset> }>(\n `query SubAssets($relationshipId: ID!) {\n subListAssets(relationshipId: $relationshipId) {\n items {\n id name type relationshipId secretRef expiresAt workspaceId\n createdAt updatedAt file { id }\n }\n pageInfo { cursor hasMore }\n }\n }`,\n { relationshipId },\n apiGatewayUrl\n );\n return result.subListAssets.items;\n },\n });\n};\n\n/** Every asset in the workspace (Digital Asset Vault) — omits relationshipId. */\nexport const useAllAssets = () => {\n const { apiGatewayUrl } = useSubscriberBot();\n return useQuery({\n queryKey: [...KEY.assets, 'all'],\n queryFn: async () => {\n const result = await subQuery<{ subListAssets: SubConnection<SubAsset> }>(\n `query SubAllAssets {\n subListAssets { items { ${ASSET_FIELDS} } pageInfo { cursor hasMore } }\n }`,\n {},\n apiGatewayUrl\n );\n return result.subListAssets.items;\n },\n });\n};\n\nexport const useCreateAsset = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async (input: SubCreateAssetInput) => {\n const result = await subQuery<{ subCreateAsset: SubAsset }>(\n `mutation SubCreateAsset($input: SubCreateAssetInput!) {\n subCreateAsset(input: $input) { ${ASSET_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.subCreateAsset;\n },\n onSuccess: (data) => {\n void queryClient.invalidateQueries({ queryKey: KEY.assets });\n void queryClient.invalidateQueries({ queryKey: KEY.relationship(data.relationshipId) });\n },\n });\n};\n\n/**\n * Upload a file to `wspace-files-svc` and return its File id, using the\n * platform-standard 3-step flow (initiateUpload → presigned PUT → completeUpload)\n * over the same `graphqlFetch` transport the rest of this MFE uses. Assets store\n * only the returned `fileId` on `SubCreateAssetInput`; blobs live in files-svc.\n *\n * `CompleteUploadInput.fileSize` is a REQUIRED BigInt (quota tracking) and must\n * match the value given to `initiateUpload` — we pass `String(file.size)` to both.\n */\nconst ASSET_FOLDER_PATH = '/SubscriberBot/Assets';\n\nexport const useUploadFile = () => {\n const { apiGatewayUrl } = useSubscriberBot();\n const [progress, setProgress] = useState(0);\n const [isUploading, setIsUploading] = useState(false);\n\n const uploadFile = useCallback(\n async (file: File): Promise<{ fileId: string; fileName: string }> => {\n setIsUploading(true);\n setProgress(0);\n try {\n // 1. Resolve (or create) the destination folder — File.folderId is a real FK.\n const folderRes = await subQuery<{ ensureFolderByPath: { id: string } | null }>(\n `mutation SubEnsureFolder($path: String!) {\n ensureFolderByPath(path: $path) { id }\n }`,\n { path: ASSET_FOLDER_PATH },\n apiGatewayUrl\n );\n const folderId = folderRes.ensureFolderByPath?.id;\n if (!folderId) throw new Error('Could not resolve the upload folder.');\n\n const mimeType = file.type || 'application/octet-stream';\n const dotIndex = file.name.lastIndexOf('.');\n const extension = dotIndex > -1 ? file.name.slice(dotIndex + 1) : 'bin';\n\n // 2. Open a presigned upload session.\n const initiated = await subQuery<{\n initiateUpload: { uploadUrl: string | null; session: { id: string } } | null;\n }>(\n `mutation SubInitiateUpload($input: InitiateUploadInput!) {\n initiateUpload(input: $input) {\n uploadUrl\n session { id }\n }\n }`,\n {\n input: {\n fileName: file.name,\n extension,\n mimeType,\n fileSize: String(file.size),\n folderId,\n },\n },\n apiGatewayUrl\n );\n const uploadUrl = initiated.initiateUpload?.uploadUrl;\n const sessionId = initiated.initiateUpload?.session.id;\n if (!uploadUrl || !sessionId) {\n throw new Error('The files service did not return an upload URL.');\n }\n\n // 3. PUT the raw bytes to storage. Content-Type must match what was signed.\n await new Promise<void>((resolve, reject) => {\n const xhr = new XMLHttpRequest();\n xhr.open('PUT', uploadUrl);\n xhr.setRequestHeader('Content-Type', mimeType);\n xhr.upload.onprogress = (event) => {\n if (event.lengthComputable) {\n setProgress(Math.round((event.loaded / event.total) * 100));\n }\n };\n xhr.onload = () => {\n if (xhr.status >= 200 && xhr.status < 300) resolve();\n else reject(new Error(`Upload to storage failed (${xhr.status}).`));\n };\n xhr.onerror = () => reject(new Error('Upload to storage failed.'));\n xhr.send(file);\n });\n\n // 4. Finalize — creates the File record. fileSize must match initiateUpload.\n const completed = await subQuery<{\n completeUpload: { fileId: string; file: { id: string; name: string } | null } | null;\n }>(\n `mutation SubCompleteUpload($input: CompleteUploadInput!) {\n completeUpload(input: $input) {\n fileId\n file { id name }\n }\n }`,\n { input: { sessionId, fileSize: String(file.size), folderId } },\n apiGatewayUrl\n );\n const fileId = completed.completeUpload?.file?.id ?? completed.completeUpload?.fileId;\n if (!fileId) throw new Error('The upload could not be finalized.');\n return { fileId, fileName: completed.completeUpload?.file?.name ?? file.name };\n } finally {\n setIsUploading(false);\n }\n },\n [apiGatewayUrl]\n );\n\n return { uploadFile, progress, isUploading };\n};\n\n/**\n * Resolve a short-lived presigned download URL for a `wspace-files-svc` File id.\n * Never select the federated arg-less `File.downloadUrl` (it mints a URL beyond\n * S3's 7-day cap and 500s the response) — use the root `getFileDownloadUrl`\n * query with a TTL under 604800s instead.\n */\nexport const useFileDownloadUrl = () => {\n const { apiGatewayUrl } = useSubscriberBot();\n return useCallback(\n async (fileId: string): Promise<string> => {\n const result = await subQuery<{ getFileDownloadUrl: string }>(\n `query SubFileDownloadUrl($id: ID!, $expiresIn: Int) {\n getFileDownloadUrl(id: $id, expiresIn: $expiresIn)\n }`,\n { id: fileId, expiresIn: 21600 },\n apiGatewayUrl\n );\n return result.getFileDownloadUrl;\n },\n [apiGatewayUrl]\n );\n};\n\n// ============================================================================\n// Providers (the global discovery registry)\n// ============================================================================\n\nexport interface ProviderListFilters {\n category?: SubProviderCategory;\n status?: SubProviderStatus;\n search?: string;\n pagination?: PaginationInput;\n}\n\nexport const useProviders = (filters: ProviderListFilters = {}) => {\n const { apiGatewayUrl } = useSubscriberBot();\n return useQuery({\n queryKey: [...KEY.providers, filters],\n queryFn: async () => {\n const result = await subQuery<{ subListProviders: SubConnection<SubProvider> }>(\n `query SubProviders(\n $category: SubProviderCategory\n $status: SubProviderStatus\n $search: String\n $pagination: PaginationInput\n ) {\n subListProviders(\n category: $category\n status: $status\n search: $search\n pagination: $pagination\n ) {\n items { ${PROVIDER_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n {\n category: filters.category,\n status: filters.status,\n search: filters.search,\n pagination: filters.pagination ?? { limit: 50, offset: 0 },\n },\n apiGatewayUrl\n );\n return result.subListProviders;\n },\n });\n};\n\nexport const useProvider = (id: string | undefined) => {\n const { apiGatewayUrl } = useSubscriberBot();\n return useQuery({\n queryKey: KEY.provider(id ?? ''),\n enabled: Boolean(id),\n queryFn: async () => {\n const result = await subQuery<{ subProvider: SubProvider | null }>(\n `query SubProvider($id: ID!) {\n subProvider(id: $id) {\n ${PROVIDER_FIELDS}\n plans { ${PLAN_FIELDS} }\n }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.subProvider;\n },\n });\n};\n\nexport const useCreateProvider = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async (input: SubCreateProviderInput) => {\n const result = await subQuery<{ subCreateProvider: SubProvider }>(\n `mutation SubCreateProvider($input: SubCreateProviderInput!) {\n subCreateProvider(input: $input) { ${PROVIDER_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.subCreateProvider;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: KEY.providers });\n },\n });\n};\n\nexport const useUpdateProvider = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async ({ id, input }: { id: string; input: SubUpdateProviderInput }) => {\n const result = await subQuery<{ subUpdateProvider: SubProvider }>(\n `mutation SubUpdateProvider($id: ID!, $input: SubUpdateProviderInput!) {\n subUpdateProvider(id: $id, input: $input) { ${PROVIDER_FIELDS} }\n }`,\n { id, input },\n apiGatewayUrl\n );\n return result.subUpdateProvider;\n },\n onSuccess: (data) => {\n void queryClient.invalidateQueries({ queryKey: KEY.providers });\n void queryClient.invalidateQueries({ queryKey: KEY.provider(data.id) });\n },\n });\n};\n\nexport const useArchiveProvider = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await subQuery<{ subArchiveProvider: boolean }>(\n `mutation SubArchiveProvider($id: ID!) {\n subArchiveProvider(id: $id)\n }`,\n { id },\n apiGatewayUrl\n );\n return result.subArchiveProvider;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: KEY.providers });\n },\n });\n};\n\nexport const usePlans = (providerId: string | undefined) => {\n const { apiGatewayUrl } = useSubscriberBot();\n return useQuery({\n queryKey: [...KEY.plans, providerId],\n enabled: Boolean(providerId),\n queryFn: async () => {\n const result = await subQuery<{ subListPlans: SubConnection<SubPlan> }>(\n `query SubPlans($providerId: ID) {\n subListPlans(providerId: $providerId) { items { ${PLAN_FIELDS} } pageInfo { cursor hasMore } }\n }`,\n { providerId },\n apiGatewayUrl\n );\n return result.subListPlans.items;\n },\n });\n};\n\nexport const useCreatePlan = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async (input: SubCreatePlanInput) => {\n const result = await subQuery<{ subCreatePlan: SubPlan }>(\n `mutation SubCreatePlan($input: SubCreatePlanInput!) {\n subCreatePlan(input: $input) { ${PLAN_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.subCreatePlan;\n },\n onSuccess: (data) => {\n void queryClient.invalidateQueries({ queryKey: KEY.plans });\n void queryClient.invalidateQueries({ queryKey: KEY.provider(data.providerId) });\n },\n });\n};\n\n/**\n * Observed price points for one provider, newest first from the server.\n *\n * Backs the provider \"Price history\" card. The benchmark dataset is read\n * GLOBALLY (`@rbac(..., public: true)` on the svc) — it is the same for every\n * workspace — so nothing here is workspace scoped. Matching is by\n * `providerSlug`, which is an exact match server-side; `providerName` is a\n * fuzzy `contains` match and would risk attributing another vendor's prices to\n * this provider, so the query stays disabled until a slug exists.\n */\nexport const useBenchmarkDataPoints = (providerSlug: string | null | undefined) => {\n const { apiGatewayUrl } = useSubscriberBot();\n return useQuery({\n queryKey: KEY.benchmarks(providerSlug ?? ''),\n enabled: Boolean(providerSlug),\n queryFn: async () => {\n const filter: SubBenchmarkFilterInput = { providerSlug: providerSlug ?? undefined };\n const result = await subQuery<{\n subListBenchmarkDataPoints: SubConnection<SubBenchmarkDataPoint>;\n }>(\n `query SubBenchmarkDataPoints(\n $filter: SubBenchmarkFilterInput\n $pagination: PaginationInput\n ) {\n subListBenchmarkDataPoints(filter: $filter, pagination: $pagination) {\n items { ${BENCHMARK_DATA_POINT_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n { filter, pagination: { limit: 100, offset: 0 } },\n apiGatewayUrl\n );\n return result.subListBenchmarkDataPoints.items;\n },\n });\n};\n\n// ============================================================================\n// Universal Inbox\n// ============================================================================\n\nexport interface InboxListFilters {\n category?: SubMessageCategory;\n channelId?: string;\n relationshipId?: string;\n unreadOnly?: boolean;\n pagination?: PaginationInput;\n}\n\nexport const useInboxMessages = (filters: InboxListFilters = {}) => {\n const { apiGatewayUrl } = useSubscriberBot();\n return useQuery({\n queryKey: [...KEY.inbox, filters],\n queryFn: async () => {\n const result = await subQuery<{\n subListInboxMessages: SubConnection<SubInboxMessage>;\n }>(\n `query SubInboxMessages(\n $category: SubMessageCategory\n $channelId: ID\n $relationshipId: ID\n $unreadOnly: Boolean\n $pagination: PaginationInput\n ) {\n subListInboxMessages(\n category: $category\n channelId: $channelId\n relationshipId: $relationshipId\n unreadOnly: $unreadOnly\n pagination: $pagination\n ) {\n items { ${INBOX_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n {\n category: filters.category,\n channelId: filters.channelId,\n relationshipId: filters.relationshipId,\n unreadOnly: filters.unreadOnly,\n pagination: filters.pagination ?? { limit: 50, offset: 0 },\n },\n apiGatewayUrl\n );\n return result.subListInboxMessages;\n },\n });\n};\n\nexport const useMarkMessageRead = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await subQuery<{ subMarkMessageRead: SubInboxMessage }>(\n `mutation SubMarkMessageRead($id: ID!) {\n subMarkMessageRead(id: $id) { ${INBOX_FIELDS} }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.subMarkMessageRead;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: KEY.inbox });\n },\n });\n};\n\nexport const useIngestMessage = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async (input: SubIngestMessageInput) => {\n const result = await subQuery<{ subIngestMessage: SubInboxMessage }>(\n `mutation SubIngestMessage($input: SubIngestMessageInput!) {\n subIngestMessage(input: $input) { ${INBOX_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.subIngestMessage;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: KEY.inbox });\n },\n });\n};\n\n// ============================================================================\n// Invoices (Universal Billing Layer)\n// ============================================================================\n\nexport interface InvoiceListFilters {\n status?: SubInvoiceStatus;\n relationshipId?: string;\n pagination?: PaginationInput;\n}\n\nexport const useInvoices = (filters: InvoiceListFilters = {}) => {\n const { apiGatewayUrl } = useSubscriberBot();\n return useQuery({\n queryKey: [...KEY.invoices, filters],\n queryFn: async () => {\n const result = await subQuery<{ subListInvoices: SubConnection<SubInvoice> }>(\n `query SubInvoices(\n $status: SubInvoiceStatus\n $relationshipId: ID\n $pagination: PaginationInput\n ) {\n subListInvoices(\n status: $status\n relationshipId: $relationshipId\n pagination: $pagination\n ) {\n items { ${INVOICE_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n {\n status: filters.status,\n relationshipId: filters.relationshipId,\n pagination: filters.pagination ?? { limit: 50, offset: 0 },\n },\n apiGatewayUrl\n );\n return result.subListInvoices;\n },\n });\n};\n\nexport const useMarkInvoicePaid = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await subQuery<{ subMarkInvoicePaid: SubInvoice }>(\n `mutation SubMarkInvoicePaid($id: ID!) {\n subMarkInvoicePaid(id: $id) { ${INVOICE_FIELDS} }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.subMarkInvoicePaid;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: KEY.invoices });\n },\n });\n};\n\nexport const useCreateInvoice = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async (input: SubCreateInvoiceInput) => {\n const result = await subQuery<{ subCreateInvoice: SubInvoice }>(\n `mutation SubCreateInvoice($input: SubCreateInvoiceInput!) {\n subCreateInvoice(input: $input) { ${INVOICE_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.subCreateInvoice;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: KEY.invoices });\n },\n });\n};\n\n// ============================================================================\n// Payment instruments & communication channels\n// ============================================================================\n\nexport const usePaymentInstruments = (ownerId?: string) => {\n const { apiGatewayUrl } = useSubscriberBot();\n return useQuery({\n queryKey: [...KEY.paymentInstruments, ownerId],\n queryFn: async () => {\n const result = await subQuery<{\n subListPaymentInstruments: SubConnection<SubPaymentInstrument>;\n }>(\n `query SubPaymentInstruments($ownerId: ID) {\n subListPaymentInstruments(ownerId: $ownerId) {\n items {\n id label type status brand last4 expiryMonth expiryYear isDefault\n ownerId workspaceId createdAt updatedAt\n }\n pageInfo { cursor hasMore }\n }\n }`,\n { ownerId },\n apiGatewayUrl\n );\n return result.subListPaymentInstruments.items;\n },\n });\n};\n\nexport const useCreatePaymentInstrument = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async (input: SubCreatePaymentInstrumentInput) => {\n const result = await subQuery<{ subCreatePaymentInstrument: SubPaymentInstrument }>(\n `mutation SubCreatePaymentInstrument($input: SubCreatePaymentInstrumentInput!) {\n subCreatePaymentInstrument(input: $input) { ${PAYMENT_INSTRUMENT_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.subCreatePaymentInstrument;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: KEY.paymentInstruments });\n },\n });\n};\n\nexport const useRemovePaymentInstrument = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await subQuery<{ subRemovePaymentInstrument: boolean }>(\n `mutation SubRemovePaymentInstrument($id: ID!) {\n subRemovePaymentInstrument(id: $id)\n }`,\n { id },\n apiGatewayUrl\n );\n return result.subRemovePaymentInstrument;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: KEY.paymentInstruments });\n },\n });\n};\n\nexport const useChannels = (ownerId?: string) => {\n const { apiGatewayUrl } = useSubscriberBot();\n return useQuery({\n queryKey: [...KEY.channels, ownerId],\n queryFn: async () => {\n const result = await subQuery<{\n subListChannels: SubConnection<SubCommunicationChannel>;\n }>(\n `query SubChannels($ownerId: ID) {\n subListChannels(ownerId: $ownerId) {\n items {\n id label type status address ingestEnabled ownerId verifiedAt\n workspaceId createdAt updatedAt\n }\n pageInfo { cursor hasMore }\n }\n }`,\n { ownerId },\n apiGatewayUrl\n );\n return result.subListChannels.items;\n },\n });\n};\n\nexport const useCreateChannel = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async (input: SubCreateChannelInput) => {\n const result = await subQuery<{ subCreateChannel: SubCommunicationChannel }>(\n `mutation SubCreateChannel($input: SubCreateChannelInput!) {\n subCreateChannel(input: $input) { ${CHANNEL_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.subCreateChannel;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: KEY.channels });\n },\n });\n};\n\nexport const useVerifyChannel = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await subQuery<{ subVerifyChannel: SubCommunicationChannel }>(\n `mutation SubVerifyChannel($id: ID!) {\n subVerifyChannel(id: $id) { ${CHANNEL_FIELDS} }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.subVerifyChannel;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: KEY.channels });\n },\n });\n};\n\n// ============================================================================\n// AI Agents & workflows (automation)\n// ============================================================================\n\nexport interface AgentListFilters {\n kind?: SubAgentKind;\n status?: SubAgentStatus;\n ownerId?: string;\n}\n\nexport const useAgents = (filters: AgentListFilters = {}) => {\n const { apiGatewayUrl } = useSubscriberBot();\n return useQuery({\n queryKey: [...KEY.agents, filters],\n queryFn: async () => {\n const result = await subQuery<{ subListAgents: SubConnection<SubAiAgent> }>(\n `query SubAgents($kind: SubAgentKind, $status: SubAgentStatus, $ownerId: ID) {\n subListAgents(kind: $kind, status: $status, ownerId: $ownerId) {\n items { ${AGENT_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n { kind: filters.kind, status: filters.status, ownerId: filters.ownerId },\n apiGatewayUrl\n );\n return result.subListAgents.items;\n },\n });\n};\n\nexport const useAgent = (id: string | undefined) => {\n const { apiGatewayUrl } = useSubscriberBot();\n return useQuery({\n queryKey: KEY.agent(id ?? ''),\n enabled: Boolean(id),\n queryFn: async () => {\n const result = await subQuery<{ subAgent: SubAiAgent | null }>(\n `query SubAgent($id: ID!) {\n subAgent(id: $id) {\n ${AGENT_FIELDS}\n policies { ${POLICY_FIELDS} }\n }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.subAgent;\n },\n });\n};\n\nexport const useCreateAgent = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async (input: SubCreateAgentInput) => {\n const result = await subQuery<{ subCreateAgent: SubAiAgent }>(\n `mutation SubCreateAgent($input: SubCreateAgentInput!) {\n subCreateAgent(input: $input) { ${AGENT_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.subCreateAgent;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: KEY.agents });\n },\n });\n};\n\nexport const useSetAgentStatus = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async ({ id, status }: { id: string; status: SubAgentStatus }) => {\n const result = await subQuery<{ subSetAgentStatus: SubAiAgent }>(\n `mutation SubSetAgentStatus($id: ID!, $status: SubAgentStatus!) {\n subSetAgentStatus(id: $id, status: $status) { ${AGENT_FIELDS} }\n }`,\n { id, status },\n apiGatewayUrl\n );\n return result.subSetAgentStatus;\n },\n onSuccess: (data) => {\n void queryClient.invalidateQueries({ queryKey: KEY.agents });\n void queryClient.invalidateQueries({ queryKey: KEY.agent(data.id) });\n },\n });\n};\n\nexport const useCreatePolicy = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async (input: SubCreatePolicyInput) => {\n const result = await subQuery<{ subCreatePolicy: SubPolicy }>(\n `mutation SubCreatePolicy($input: SubCreatePolicyInput!) {\n subCreatePolicy(input: $input) { ${POLICY_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.subCreatePolicy;\n },\n onSuccess: (data) => {\n void queryClient.invalidateQueries({ queryKey: KEY.agents });\n void queryClient.invalidateQueries({ queryKey: KEY.agent(data.agentId) });\n },\n });\n};\n\nexport const useWorkflows = (status?: SubWorkflowStatus) => {\n const { apiGatewayUrl } = useSubscriberBot();\n return useQuery({\n queryKey: [...KEY.workflows, status],\n queryFn: async () => {\n const result = await subQuery<{ subListWorkflows: SubConnection<SubWorkflow> }>(\n `query SubWorkflows($status: SubWorkflowStatus) {\n subListWorkflows(status: $status) { items { ${WORKFLOW_FIELDS} } pageInfo { cursor hasMore } }\n }`,\n { status },\n apiGatewayUrl\n );\n return result.subListWorkflows.items;\n },\n });\n};\n\nexport const useCreateWorkflow = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async (input: SubCreateWorkflowInput) => {\n const result = await subQuery<{ subCreateWorkflow: SubWorkflow }>(\n `mutation SubCreateWorkflow($input: SubCreateWorkflowInput!) {\n subCreateWorkflow(input: $input) { ${WORKFLOW_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.subCreateWorkflow;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: KEY.workflows });\n },\n });\n};\n\nexport const useActivateWorkflow = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await subQuery<{ subActivateWorkflow: SubWorkflow }>(\n `mutation SubActivateWorkflow($id: ID!) {\n subActivateWorkflow(id: $id) { ${WORKFLOW_FIELDS} }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.subActivateWorkflow;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: KEY.workflows });\n },\n });\n};\n\n// ============================================================================\n// Admin governance (adapter approvals + marketplace moderation)\n// ============================================================================\n\nexport interface AdapterSubmissionListFilters {\n status?: SubSubmissionStatus;\n pagination?: PaginationInput;\n}\n\nexport const useAdapterSubmissions = (filters: AdapterSubmissionListFilters = {}) => {\n const { apiGatewayUrl } = useSubscriberBot();\n return useQuery({\n queryKey: [...KEY.adapterSubmissions, filters],\n queryFn: async () => {\n const result = await subQuery<{\n subListAdapterSubmissions: SubConnection<SubAdapterSubmission>;\n }>(\n `query SubAdapterSubmissions($status: SubSubmissionStatus, $pagination: PaginationInput) {\n subListAdapterSubmissions(status: $status, pagination: $pagination) {\n items { ${ADAPTER_SUBMISSION_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n {\n status: filters.status,\n pagination: filters.pagination ?? { limit: 50, offset: 0 },\n },\n apiGatewayUrl\n );\n return result.subListAdapterSubmissions;\n },\n });\n};\n\nexport const useApproveAdapter = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async ({ id, notes }: { id: string; notes?: string }) => {\n const result = await subQuery<{ subApproveAdapter: SubAdapterSubmission }>(\n `mutation SubApproveAdapter($id: ID!, $notes: String) {\n subApproveAdapter(id: $id, notes: $notes) { ${ADAPTER_SUBMISSION_FIELDS} }\n }`,\n { id, notes },\n apiGatewayUrl\n );\n return result.subApproveAdapter;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: KEY.adapterSubmissions });\n },\n });\n};\n\nexport const useRejectAdapter = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async ({ id, reason }: { id: string; reason: string }) => {\n const result = await subQuery<{ subRejectAdapter: SubAdapterSubmission }>(\n `mutation SubRejectAdapter($id: ID!, $reason: String!) {\n subRejectAdapter(id: $id, reason: $reason) { ${ADAPTER_SUBMISSION_FIELDS} }\n }`,\n { id, reason },\n apiGatewayUrl\n );\n return result.subRejectAdapter;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: KEY.adapterSubmissions });\n },\n });\n};\n\nexport interface MarketplaceReportListFilters {\n status?: SubReportStatus;\n pagination?: PaginationInput;\n}\n\nexport const useMarketplaceReports = (filters: MarketplaceReportListFilters = {}) => {\n const { apiGatewayUrl } = useSubscriberBot();\n return useQuery({\n queryKey: [...KEY.marketplaceReports, filters],\n queryFn: async () => {\n const result = await subQuery<{\n subListMarketplaceReports: SubConnection<SubMarketplaceReport>;\n }>(\n `query SubMarketplaceReports($status: SubReportStatus, $pagination: PaginationInput) {\n subListMarketplaceReports(status: $status, pagination: $pagination) {\n items { ${MARKETPLACE_REPORT_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n {\n status: filters.status,\n pagination: filters.pagination ?? { limit: 50, offset: 0 },\n },\n apiGatewayUrl\n );\n return result.subListMarketplaceReports;\n },\n });\n};\n\nexport const useModerateListing = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async ({\n id,\n action,\n reason,\n }: {\n id: string;\n action: SubModerationAction;\n reason: string;\n }) => {\n const result = await subQuery<{ subModerateListing: SubMarketplaceReport }>(\n `mutation SubModerateListing($id: ID!, $action: SubModerationAction!, $reason: String!) {\n subModerateListing(id: $id, action: $action, reason: $reason) { ${MARKETPLACE_REPORT_FIELDS} }\n }`,\n { id, action, reason },\n apiGatewayUrl\n );\n return result.subModerateListing;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: KEY.marketplaceReports });\n },\n });\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"useSubscriberBotApi.js","names":[],"sources":["../../../src/subscriberbot/hooks/useSubscriberBotApi.ts"],"sourcesContent":["/**\n * SubscriberBot API hooks\n * @module subscriberbot/hooks\n *\n * React-Query hooks wired DIRECTLY to the real `wspace-subscriberbot-svc`\n * federated GraphQL contract (the `Sub*` operations). Every query/mutation\n * below uses an inline gql string whose fields match the svc\n * `.hive-schema.graphql` exactly. No mock data.\n *\n * Transport: `graphqlFetch({ gateway: 'workspace', workspaceToken: true })`\n * — the same pattern the workspace MFEs use; the host shell supplies the\n * gateway base URL + a workspace-scoped token.\n */\n\nimport { useCallback, useState } from 'react';\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';\nimport { graphqlFetch } from '@burdenoff/fe-libs/shared/graphql';\n// clearGraphqlFetchResponseCache is re-exported from the barrel only in newer\n// fe-libs; import it from its defining module so this works on the pinned\n// 2026.625.5 without forcing a risky fe-libs major bump.\nimport { clearGraphqlFetchResponseCache } from '@burdenoff/fe-libs/shared/graphql/fetch';\n\nimport { useSubscriberBot } from '../context';\nimport type {\n PaginationInput,\n SubAdapterSubmission,\n SubAgentKind,\n SubAgentStatus,\n SubAiAgent,\n SubAsset,\n SubBenchmarkDataPoint,\n SubBenchmarkFilterInput,\n SubCommunicationChannel,\n SubConnection,\n SubCreateAgentInput,\n SubCreateAssetInput,\n SubCreateChannelInput,\n SubCreateEntitlementInput,\n SubCreateInvoiceInput,\n SubCreatePaymentInstrumentInput,\n SubCreatePlanInput,\n SubCreatePolicyInput,\n SubCreateProviderInput,\n SubCreateRelationshipInput,\n SubCreateWorkflowInput,\n SubEntitlement,\n SubInboxMessage,\n SubIngestMessageInput,\n SubInvoice,\n SubInvoiceStatus,\n SubMarketplaceReport,\n SubMessageCategory,\n SubModerationAction,\n SubPaymentInstrument,\n SubPlan,\n SubPolicy,\n SubProvider,\n SubProviderCategory,\n SubProviderStatus,\n SubRelationship,\n SubRelationshipKind,\n SubRelationshipStatus,\n SubRenewalEvent,\n SubReportStatus,\n SubSubmissionStatus,\n SubUpdateProviderInput,\n SubUpdateRelationshipInput,\n SubWorkflow,\n SubWorkflowStatus,\n} from '../types';\n\n// ============================================================================\n// Transport\n// ============================================================================\n\nconst subQuery = async <TData>(\n query: string,\n variables: Record<string, unknown>,\n baseUrl?: string\n): Promise<TData> => {\n const response = await graphqlFetch<TData>({\n gateway: 'workspace',\n baseUrl,\n query,\n variables,\n workspaceToken: true,\n });\n\n if (response.errors?.length) {\n throw new Error(response.errors[0]?.message ?? 'GraphQL request failed');\n }\n if (!response.data) {\n throw new Error('GraphQL response did not include data');\n }\n // A mutation just changed server state. fe-libs' graphqlFetch keeps a ~15s\n // global response micro-cache keyed by query+vars, so the react-query refetch\n // that an onSuccess triggers would otherwise be served the STALE pre-write\n // response (a newly created provider/relationship/agent wouldn't appear, a\n // just-marked-read message would still show unread) until the TTL expires.\n // Drop that cache here — centralized so no mutation call site can forget it.\n if (/^\\s*mutation\\b/.test(query)) {\n clearGraphqlFetchResponseCache();\n }\n return response.data;\n};\n\n// React-Query key roots (one namespace per domain entity).\nconst KEY = {\n relationships: ['subscriberbot', 'relationships'] as const,\n relationship: (id: string) => ['subscriberbot', 'relationship', id] as const,\n providers: ['subscriberbot', 'providers'] as const,\n provider: (id: string) => ['subscriberbot', 'provider', id] as const,\n plans: ['subscriberbot', 'plans'] as const,\n benchmarks: (providerSlug: string) => ['subscriberbot', 'benchmarks', providerSlug] as const,\n inbox: ['subscriberbot', 'inbox'] as const,\n invoices: ['subscriberbot', 'invoices'] as const,\n paymentInstruments: ['subscriberbot', 'payment-instruments'] as const,\n channels: ['subscriberbot', 'channels'] as const,\n agents: ['subscriberbot', 'agents'] as const,\n agent: (id: string) => ['subscriberbot', 'agent', id] as const,\n workflows: ['subscriberbot', 'workflows'] as const,\n renewals: ['subscriberbot', 'renewals'] as const,\n assets: ['subscriberbot', 'assets'] as const,\n entitlements: ['subscriberbot', 'entitlements'] as const,\n adapterSubmissions: ['subscriberbot', 'admin', 'adapter-submissions'] as const,\n marketplaceReports: ['subscriberbot', 'admin', 'marketplace-reports'] as const,\n} as const;\n\n// ============================================================================\n// Reusable gql field selections (kept inline-string for codegen-free strictness)\n// ============================================================================\n\nconst PROVIDER_FIELDS = `\n id name slug category status description industry region language websiteUrl\n logoFileId tags churnRiskScore vendorHealthScore workspaceId createdAt updatedAt\n`;\n\nconst PLAN_FIELDS = `\n id name description providerId amount currency interval features isActive\n workspaceId createdAt updatedAt\n`;\n\nconst RELATIONSHIP_FIELDS = `\n id label kind status amount currency interval autoRenew discoverySource notes\n tags healthScore ownerId providerId planId startedAt renewsAt trialEndsAt\n cancelledAt workspaceId createdAt updatedAt\n`;\n\nconst INBOX_FIELDS = `\n id subject preview category categoryConfidence channelId relationshipId\n externalId actionRequired isRead receivedAt workspaceId createdAt updatedAt\n`;\n\nconst INVOICE_FIELDS = `\n id number relationshipId status currency subtotal taxAmount total issueDate\n dueDate paidAt paymentInstrumentId workspaceId createdAt updatedAt\n`;\n\nconst AGENT_FIELDS = `\n id name description kind status ownerId lastRunAt workspaceId createdAt updatedAt\n`;\n\nconst WORKFLOW_FIELDS = `\n id name description triggerEvent status runCount lastRunAt workspaceId\n createdAt updatedAt\n`;\n\nconst ENTITLEMENT_FIELDS = `\n id name description type relationshipId quota used unit isActive\n workspaceId createdAt updatedAt\n`;\n\nconst ASSET_FIELDS = `\n id name type relationshipId secretRef expiresAt workspaceId createdAt\n updatedAt file { id }\n`;\n\nconst PAYMENT_INSTRUMENT_FIELDS = `\n id label type status brand last4 expiryMonth expiryYear isDefault ownerId\n workspaceId createdAt updatedAt\n`;\n\nconst CHANNEL_FIELDS = `\n id label type status address ingestEnabled ownerId verifiedAt workspaceId\n createdAt updatedAt\n`;\n\nconst POLICY_FIELDS = `\n id name description action agentId condition isEnabled triggerCount\n lastTriggeredAt workspaceId createdAt updatedAt\n`;\n\nconst BENCHMARK_DATA_POINT_FIELDS = `\n id providerSlug providerName planName region currency interval amount\n contractSizeSeats sourceKind sourceLabel notes observedAt createdAt\n`;\n\nconst ADAPTER_SUBMISSION_FIELDS = `\n id workspaceId adapterId submitterWorkspaceId status notes createdAt updatedAt\n`;\n\nconst MARKETPLACE_REPORT_FIELDS = `\n id workspaceId listingId reporterWorkspaceId reason status resolutionReason\n createdAt updatedAt\n`;\n\n// ============================================================================\n// Relationships (the core domain object)\n// ============================================================================\n\nexport interface RelationshipListFilters {\n kind?: SubRelationshipKind;\n status?: SubRelationshipStatus;\n providerId?: string;\n ownerId?: string;\n /** Case-insensitive substring match on the relationship label (server-side). */\n search?: string;\n pagination?: PaginationInput;\n}\n\nexport const useRelationships = (filters: RelationshipListFilters = {}) => {\n const { apiGatewayUrl } = useSubscriberBot();\n return useQuery({\n queryKey: [...KEY.relationships, filters],\n queryFn: async () => {\n const result = await subQuery<{\n subListRelationships: SubConnection<SubRelationship>;\n }>(\n `query SubRelationships(\n $kind: SubRelationshipKind\n $status: SubRelationshipStatus\n $providerId: ID\n $ownerId: ID\n $search: String\n $pagination: PaginationInput\n ) {\n subListRelationships(\n kind: $kind\n status: $status\n providerId: $providerId\n ownerId: $ownerId\n search: $search\n pagination: $pagination\n ) {\n items {\n ${RELATIONSHIP_FIELDS}\n provider { id name category status logoFileId }\n plan { id name amount currency interval }\n }\n pageInfo { cursor hasMore }\n }\n }`,\n {\n kind: filters.kind,\n status: filters.status,\n providerId: filters.providerId,\n ownerId: filters.ownerId,\n search: filters.search,\n pagination: filters.pagination ?? { limit: 50, offset: 0 },\n },\n apiGatewayUrl\n );\n return result.subListRelationships;\n },\n });\n};\n\nexport const useRelationship = (id: string | undefined) => {\n const { apiGatewayUrl } = useSubscriberBot();\n return useQuery({\n queryKey: KEY.relationship(id ?? ''),\n enabled: Boolean(id),\n queryFn: async () => {\n const result = await subQuery<{ subRelationship: SubRelationship | null }>(\n `query SubRelationship($id: ID!) {\n subRelationship(id: $id) {\n ${RELATIONSHIP_FIELDS}\n provider { ${PROVIDER_FIELDS} }\n plan { ${PLAN_FIELDS} }\n entitlements {\n id name description type relationshipId quota used unit isActive\n workspaceId createdAt updatedAt\n }\n assets {\n id name type relationshipId secretRef expiresAt workspaceId\n createdAt updatedAt file { id }\n }\n # BOFF-8659 - invoices linked via SubInvoice.relationshipId,\n # shown in the Assets section alongside file-based assets so\n # users don't have to leave the relationship page to discover\n # they have an outstanding invoice tied to it.\n invoices {\n id number relationshipId status currency subtotal taxAmount\n total issueDate dueDate paidAt paymentInstrumentId workspaceId\n createdAt updatedAt\n }\n renewalEvents {\n id relationshipId eventType occursAt amount currency detail\n notified workspaceId createdAt updatedAt\n }\n }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.subRelationship;\n },\n });\n};\n\nexport const useCreateRelationship = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async (input: SubCreateRelationshipInput) => {\n const result = await subQuery<{ subCreateRelationship: SubRelationship }>(\n `mutation SubCreateRelationship($input: SubCreateRelationshipInput!) {\n subCreateRelationship(input: $input) { ${RELATIONSHIP_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.subCreateRelationship;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: KEY.relationships });\n },\n });\n};\n\nexport const useTransitionRelationship = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async ({ id, status }: { id: string; status: SubRelationshipStatus }) => {\n const result = await subQuery<{ subTransitionRelationship: SubRelationship }>(\n `mutation SubTransitionRelationship($id: ID!, $status: SubRelationshipStatus!) {\n subTransitionRelationship(id: $id, status: $status) { ${RELATIONSHIP_FIELDS} }\n }`,\n { id, status },\n apiGatewayUrl\n );\n return result.subTransitionRelationship;\n },\n onSuccess: (data) => {\n void queryClient.invalidateQueries({ queryKey: KEY.relationships });\n void queryClient.invalidateQueries({ queryKey: KEY.relationship(data.id) });\n },\n });\n};\n\nexport const useCancelRelationship = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await subQuery<{ subCancelRelationship: SubRelationship }>(\n `mutation SubCancelRelationship($id: ID!) {\n subCancelRelationship(id: $id) { ${RELATIONSHIP_FIELDS} }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.subCancelRelationship;\n },\n onSuccess: (data) => {\n void queryClient.invalidateQueries({ queryKey: KEY.relationships });\n void queryClient.invalidateQueries({ queryKey: KEY.relationship(data.id) });\n },\n });\n};\n\nexport const useUpdateRelationship = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async ({ id, input }: { id: string; input: SubUpdateRelationshipInput }) => {\n const result = await subQuery<{ subUpdateRelationship: SubRelationship }>(\n `mutation SubUpdateRelationship($id: ID!, $input: SubUpdateRelationshipInput!) {\n subUpdateRelationship(id: $id, input: $input) { ${RELATIONSHIP_FIELDS} }\n }`,\n { id, input },\n apiGatewayUrl\n );\n return result.subUpdateRelationship;\n },\n onSuccess: (data) => {\n void queryClient.invalidateQueries({ queryKey: KEY.relationships });\n void queryClient.invalidateQueries({ queryKey: KEY.relationship(data.id) });\n },\n });\n};\n\nexport const useRenewalEvents = (\n args: { relationshipId?: string; upcomingOnly?: boolean } = {}\n) => {\n const { apiGatewayUrl } = useSubscriberBot();\n return useQuery({\n queryKey: [...KEY.renewals, args],\n queryFn: async () => {\n // subListRenewalEvents returns SubRenewalEventConnection (items/pageInfo),\n // not a bare list — matching every other subList* root field in this\n // schema (see useRelationships above). Selecting event fields directly\n // fails GraphQL validation server-side (`Cannot query field \"id\" on type\n // \"SubRenewalEventConnection\"`).\n const result = await subQuery<{\n subListRenewalEvents: SubConnection<SubRenewalEvent>;\n }>(\n `query SubRenewalEvents($relationshipId: ID, $upcomingOnly: Boolean) {\n subListRenewalEvents(relationshipId: $relationshipId, upcomingOnly: $upcomingOnly) {\n items {\n id relationshipId eventType occursAt amount currency detail notified\n workspaceId createdAt updatedAt\n }\n pageInfo { cursor hasMore }\n }\n }`,\n { relationshipId: args.relationshipId, upcomingOnly: args.upcomingOnly },\n apiGatewayUrl\n );\n return result.subListRenewalEvents.items;\n },\n });\n};\n\nexport const useEntitlements = (relationshipId: string | undefined) => {\n const { apiGatewayUrl } = useSubscriberBot();\n return useQuery({\n queryKey: [...KEY.entitlements, relationshipId],\n enabled: Boolean(relationshipId),\n queryFn: async () => {\n const result = await subQuery<{\n subListEntitlements: SubConnection<SubEntitlement>;\n }>(\n `query SubEntitlements($relationshipId: ID!) {\n subListEntitlements(relationshipId: $relationshipId) {\n items {\n id name description type relationshipId quota used unit isActive\n workspaceId createdAt updatedAt\n }\n pageInfo { cursor hasMore }\n }\n }`,\n { relationshipId },\n apiGatewayUrl\n );\n return result.subListEntitlements.items;\n },\n });\n};\n\nexport const useCreateEntitlement = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async (input: SubCreateEntitlementInput) => {\n const result = await subQuery<{ subCreateEntitlement: SubEntitlement }>(\n `mutation SubCreateEntitlement($input: SubCreateEntitlementInput!) {\n subCreateEntitlement(input: $input) { ${ENTITLEMENT_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.subCreateEntitlement;\n },\n onSuccess: (data) => {\n void queryClient.invalidateQueries({ queryKey: KEY.entitlements });\n void queryClient.invalidateQueries({ queryKey: KEY.relationship(data.relationshipId) });\n },\n });\n};\n\nexport const useAssets = (relationshipId: string | undefined) => {\n const { apiGatewayUrl } = useSubscriberBot();\n return useQuery({\n queryKey: [...KEY.assets, relationshipId],\n enabled: Boolean(relationshipId),\n queryFn: async () => {\n const result = await subQuery<{ subListAssets: SubConnection<SubAsset> }>(\n `query SubAssets($relationshipId: ID!) {\n subListAssets(relationshipId: $relationshipId) {\n items {\n id name type relationshipId secretRef expiresAt workspaceId\n createdAt updatedAt file { id }\n }\n pageInfo { cursor hasMore }\n }\n }`,\n { relationshipId },\n apiGatewayUrl\n );\n return result.subListAssets.items;\n },\n });\n};\n\n/** Every asset in the workspace (Digital Asset Vault) — omits relationshipId. */\nexport const useAllAssets = () => {\n const { apiGatewayUrl } = useSubscriberBot();\n return useQuery({\n queryKey: [...KEY.assets, 'all'],\n queryFn: async () => {\n const result = await subQuery<{ subListAssets: SubConnection<SubAsset> }>(\n `query SubAllAssets {\n subListAssets { items { ${ASSET_FIELDS} } pageInfo { cursor hasMore } }\n }`,\n {},\n apiGatewayUrl\n );\n return result.subListAssets.items;\n },\n });\n};\n\nexport const useCreateAsset = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async (input: SubCreateAssetInput) => {\n const result = await subQuery<{ subCreateAsset: SubAsset }>(\n `mutation SubCreateAsset($input: SubCreateAssetInput!) {\n subCreateAsset(input: $input) { ${ASSET_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.subCreateAsset;\n },\n onSuccess: (data) => {\n void queryClient.invalidateQueries({ queryKey: KEY.assets });\n void queryClient.invalidateQueries({ queryKey: KEY.relationship(data.relationshipId) });\n },\n });\n};\n\n/**\n * Upload a file to `wspace-files-svc` and return its File id, using the\n * platform-standard 3-step flow (initiateUpload → presigned PUT → completeUpload)\n * over the same `graphqlFetch` transport the rest of this MFE uses. Assets store\n * only the returned `fileId` on `SubCreateAssetInput`; blobs live in files-svc.\n *\n * `CompleteUploadInput.fileSize` is a REQUIRED BigInt (quota tracking) and must\n * match the value given to `initiateUpload` — we pass `String(file.size)` to both.\n */\nconst ASSET_FOLDER_PATH = '/SubscriberBot/Assets';\n\nexport const useUploadFile = () => {\n const { apiGatewayUrl } = useSubscriberBot();\n const [progress, setProgress] = useState(0);\n const [isUploading, setIsUploading] = useState(false);\n\n const uploadFile = useCallback(\n async (file: File): Promise<{ fileId: string; fileName: string }> => {\n setIsUploading(true);\n setProgress(0);\n try {\n // 1. Resolve (or create) the destination folder — File.folderId is a real FK.\n const folderRes = await subQuery<{ ensureFolderByPath: { id: string } | null }>(\n `mutation SubEnsureFolder($path: String!) {\n ensureFolderByPath(path: $path) { id }\n }`,\n { path: ASSET_FOLDER_PATH },\n apiGatewayUrl\n );\n const folderId = folderRes.ensureFolderByPath?.id;\n if (!folderId) throw new Error('Could not resolve the upload folder.');\n\n const mimeType = file.type || 'application/octet-stream';\n const dotIndex = file.name.lastIndexOf('.');\n const extension = dotIndex > -1 ? file.name.slice(dotIndex + 1) : 'bin';\n\n // 2. Open a presigned upload session.\n const initiated = await subQuery<{\n initiateUpload: { uploadUrl: string | null; session: { id: string } } | null;\n }>(\n `mutation SubInitiateUpload($input: InitiateUploadInput!) {\n initiateUpload(input: $input) {\n uploadUrl\n session { id }\n }\n }`,\n {\n input: {\n fileName: file.name,\n extension,\n mimeType,\n fileSize: String(file.size),\n folderId,\n },\n },\n apiGatewayUrl\n );\n const uploadUrl = initiated.initiateUpload?.uploadUrl;\n const sessionId = initiated.initiateUpload?.session.id;\n if (!uploadUrl || !sessionId) {\n throw new Error('The files service did not return an upload URL.');\n }\n\n // 3. PUT the raw bytes to storage. Content-Type must match what was signed.\n await new Promise<void>((resolve, reject) => {\n const xhr = new XMLHttpRequest();\n xhr.open('PUT', uploadUrl);\n xhr.setRequestHeader('Content-Type', mimeType);\n xhr.upload.onprogress = (event) => {\n if (event.lengthComputable) {\n setProgress(Math.round((event.loaded / event.total) * 100));\n }\n };\n xhr.onload = () => {\n if (xhr.status >= 200 && xhr.status < 300) resolve();\n else reject(new Error(`Upload to storage failed (${xhr.status}).`));\n };\n xhr.onerror = () => reject(new Error('Upload to storage failed.'));\n xhr.send(file);\n });\n\n // 4. Finalize — creates the File record. fileSize must match initiateUpload.\n const completed = await subQuery<{\n completeUpload: { fileId: string; file: { id: string; name: string } | null } | null;\n }>(\n `mutation SubCompleteUpload($input: CompleteUploadInput!) {\n completeUpload(input: $input) {\n fileId\n file { id name }\n }\n }`,\n { input: { sessionId, fileSize: String(file.size), folderId } },\n apiGatewayUrl\n );\n const fileId = completed.completeUpload?.file?.id ?? completed.completeUpload?.fileId;\n if (!fileId) throw new Error('The upload could not be finalized.');\n return { fileId, fileName: completed.completeUpload?.file?.name ?? file.name };\n } finally {\n setIsUploading(false);\n }\n },\n [apiGatewayUrl]\n );\n\n return { uploadFile, progress, isUploading };\n};\n\n/**\n * Resolve a short-lived presigned download URL for a `wspace-files-svc` File id.\n * Never select the federated arg-less `File.downloadUrl` (it mints a URL beyond\n * S3's 7-day cap and 500s the response) — use the root `getFileDownloadUrl`\n * query with a TTL under 604800s instead.\n */\nexport const useFileDownloadUrl = () => {\n const { apiGatewayUrl } = useSubscriberBot();\n return useCallback(\n async (fileId: string): Promise<string> => {\n const result = await subQuery<{ getFileDownloadUrl: string }>(\n `query SubFileDownloadUrl($id: ID!, $expiresIn: Int) {\n getFileDownloadUrl(id: $id, expiresIn: $expiresIn)\n }`,\n { id: fileId, expiresIn: 21600 },\n apiGatewayUrl\n );\n return result.getFileDownloadUrl;\n },\n [apiGatewayUrl]\n );\n};\n\n// ============================================================================\n// Providers (the global discovery registry)\n// ============================================================================\n\nexport interface ProviderListFilters {\n category?: SubProviderCategory;\n status?: SubProviderStatus;\n search?: string;\n pagination?: PaginationInput;\n}\n\nexport const useProviders = (filters: ProviderListFilters = {}) => {\n const { apiGatewayUrl } = useSubscriberBot();\n return useQuery({\n queryKey: [...KEY.providers, filters],\n queryFn: async () => {\n const result = await subQuery<{ subListProviders: SubConnection<SubProvider> }>(\n `query SubProviders(\n $category: SubProviderCategory\n $status: SubProviderStatus\n $search: String\n $pagination: PaginationInput\n ) {\n subListProviders(\n category: $category\n status: $status\n search: $search\n pagination: $pagination\n ) {\n items { ${PROVIDER_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n {\n category: filters.category,\n status: filters.status,\n search: filters.search,\n pagination: filters.pagination ?? { limit: 50, offset: 0 },\n },\n apiGatewayUrl\n );\n return result.subListProviders;\n },\n });\n};\n\nexport const useProvider = (id: string | undefined) => {\n const { apiGatewayUrl } = useSubscriberBot();\n return useQuery({\n queryKey: KEY.provider(id ?? ''),\n enabled: Boolean(id),\n queryFn: async () => {\n const result = await subQuery<{ subProvider: SubProvider | null }>(\n `query SubProvider($id: ID!) {\n subProvider(id: $id) {\n ${PROVIDER_FIELDS}\n plans { ${PLAN_FIELDS} }\n }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.subProvider;\n },\n });\n};\n\nexport const useCreateProvider = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async (input: SubCreateProviderInput) => {\n const result = await subQuery<{ subCreateProvider: SubProvider }>(\n `mutation SubCreateProvider($input: SubCreateProviderInput!) {\n subCreateProvider(input: $input) { ${PROVIDER_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.subCreateProvider;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: KEY.providers });\n },\n });\n};\n\nexport const useUpdateProvider = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async ({ id, input }: { id: string; input: SubUpdateProviderInput }) => {\n const result = await subQuery<{ subUpdateProvider: SubProvider }>(\n `mutation SubUpdateProvider($id: ID!, $input: SubUpdateProviderInput!) {\n subUpdateProvider(id: $id, input: $input) { ${PROVIDER_FIELDS} }\n }`,\n { id, input },\n apiGatewayUrl\n );\n return result.subUpdateProvider;\n },\n onSuccess: (data) => {\n void queryClient.invalidateQueries({ queryKey: KEY.providers });\n void queryClient.invalidateQueries({ queryKey: KEY.provider(data.id) });\n },\n });\n};\n\nexport const useArchiveProvider = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await subQuery<{ subArchiveProvider: boolean }>(\n `mutation SubArchiveProvider($id: ID!) {\n subArchiveProvider(id: $id)\n }`,\n { id },\n apiGatewayUrl\n );\n return result.subArchiveProvider;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: KEY.providers });\n },\n });\n};\n\nexport const usePlans = (providerId: string | undefined) => {\n const { apiGatewayUrl } = useSubscriberBot();\n return useQuery({\n queryKey: [...KEY.plans, providerId],\n enabled: Boolean(providerId),\n queryFn: async () => {\n const result = await subQuery<{ subListPlans: SubConnection<SubPlan> }>(\n `query SubPlans($providerId: ID) {\n subListPlans(providerId: $providerId) { items { ${PLAN_FIELDS} } pageInfo { cursor hasMore } }\n }`,\n { providerId },\n apiGatewayUrl\n );\n return result.subListPlans.items;\n },\n });\n};\n\nexport const useCreatePlan = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async (input: SubCreatePlanInput) => {\n const result = await subQuery<{ subCreatePlan: SubPlan }>(\n `mutation SubCreatePlan($input: SubCreatePlanInput!) {\n subCreatePlan(input: $input) { ${PLAN_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.subCreatePlan;\n },\n onSuccess: (data) => {\n void queryClient.invalidateQueries({ queryKey: KEY.plans });\n void queryClient.invalidateQueries({ queryKey: KEY.provider(data.providerId) });\n },\n });\n};\n\n/**\n * Observed price points for one provider, newest first from the server.\n *\n * Backs the provider \"Price history\" card. The benchmark dataset is read\n * GLOBALLY (`@rbac(..., public: true)` on the svc) — it is the same for every\n * workspace — so nothing here is workspace scoped. Matching is by\n * `providerSlug`, which is an exact match server-side; `providerName` is a\n * fuzzy `contains` match and would risk attributing another vendor's prices to\n * this provider, so the query stays disabled until a slug exists.\n */\nexport const useBenchmarkDataPoints = (providerSlug: string | null | undefined) => {\n const { apiGatewayUrl } = useSubscriberBot();\n return useQuery({\n queryKey: KEY.benchmarks(providerSlug ?? ''),\n enabled: Boolean(providerSlug),\n queryFn: async () => {\n const filter: SubBenchmarkFilterInput = { providerSlug: providerSlug ?? undefined };\n const result = await subQuery<{\n subListBenchmarkDataPoints: SubConnection<SubBenchmarkDataPoint>;\n }>(\n `query SubBenchmarkDataPoints(\n $filter: SubBenchmarkFilterInput\n $pagination: PaginationInput\n ) {\n subListBenchmarkDataPoints(filter: $filter, pagination: $pagination) {\n items { ${BENCHMARK_DATA_POINT_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n { filter, pagination: { limit: 100, offset: 0 } },\n apiGatewayUrl\n );\n return result.subListBenchmarkDataPoints.items;\n },\n });\n};\n\n// ============================================================================\n// Universal Inbox\n// ============================================================================\n\nexport interface InboxListFilters {\n category?: SubMessageCategory;\n channelId?: string;\n relationshipId?: string;\n unreadOnly?: boolean;\n pagination?: PaginationInput;\n}\n\nexport const useInboxMessages = (filters: InboxListFilters = {}) => {\n const { apiGatewayUrl } = useSubscriberBot();\n return useQuery({\n queryKey: [...KEY.inbox, filters],\n queryFn: async () => {\n const result = await subQuery<{\n subListInboxMessages: SubConnection<SubInboxMessage>;\n }>(\n `query SubInboxMessages(\n $category: SubMessageCategory\n $channelId: ID\n $relationshipId: ID\n $unreadOnly: Boolean\n $pagination: PaginationInput\n ) {\n subListInboxMessages(\n category: $category\n channelId: $channelId\n relationshipId: $relationshipId\n unreadOnly: $unreadOnly\n pagination: $pagination\n ) {\n items { ${INBOX_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n {\n category: filters.category,\n channelId: filters.channelId,\n relationshipId: filters.relationshipId,\n unreadOnly: filters.unreadOnly,\n pagination: filters.pagination ?? { limit: 50, offset: 0 },\n },\n apiGatewayUrl\n );\n return result.subListInboxMessages;\n },\n });\n};\n\nexport const useMarkMessageRead = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await subQuery<{ subMarkMessageRead: SubInboxMessage }>(\n `mutation SubMarkMessageRead($id: ID!) {\n subMarkMessageRead(id: $id) { ${INBOX_FIELDS} }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.subMarkMessageRead;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: KEY.inbox });\n },\n });\n};\n\nexport const useIngestMessage = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async (input: SubIngestMessageInput) => {\n const result = await subQuery<{ subIngestMessage: SubInboxMessage }>(\n `mutation SubIngestMessage($input: SubIngestMessageInput!) {\n subIngestMessage(input: $input) { ${INBOX_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.subIngestMessage;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: KEY.inbox });\n },\n });\n};\n\n// ============================================================================\n// Invoices (Universal Billing Layer)\n// ============================================================================\n\nexport interface InvoiceListFilters {\n status?: SubInvoiceStatus;\n relationshipId?: string;\n pagination?: PaginationInput;\n}\n\nexport const useInvoices = (filters: InvoiceListFilters = {}) => {\n const { apiGatewayUrl } = useSubscriberBot();\n return useQuery({\n queryKey: [...KEY.invoices, filters],\n queryFn: async () => {\n const result = await subQuery<{ subListInvoices: SubConnection<SubInvoice> }>(\n `query SubInvoices(\n $status: SubInvoiceStatus\n $relationshipId: ID\n $pagination: PaginationInput\n ) {\n subListInvoices(\n status: $status\n relationshipId: $relationshipId\n pagination: $pagination\n ) {\n items { ${INVOICE_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n {\n status: filters.status,\n relationshipId: filters.relationshipId,\n pagination: filters.pagination ?? { limit: 50, offset: 0 },\n },\n apiGatewayUrl\n );\n return result.subListInvoices;\n },\n });\n};\n\nexport const useMarkInvoicePaid = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await subQuery<{ subMarkInvoicePaid: SubInvoice }>(\n `mutation SubMarkInvoicePaid($id: ID!) {\n subMarkInvoicePaid(id: $id) { ${INVOICE_FIELDS} }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.subMarkInvoicePaid;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: KEY.invoices });\n },\n });\n};\n\nexport const useCreateInvoice = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async (input: SubCreateInvoiceInput) => {\n const result = await subQuery<{ subCreateInvoice: SubInvoice }>(\n `mutation SubCreateInvoice($input: SubCreateInvoiceInput!) {\n subCreateInvoice(input: $input) { ${INVOICE_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.subCreateInvoice;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: KEY.invoices });\n },\n });\n};\n\n// ============================================================================\n// Payment instruments & communication channels\n// ============================================================================\n\nexport const usePaymentInstruments = (ownerId?: string) => {\n const { apiGatewayUrl } = useSubscriberBot();\n return useQuery({\n queryKey: [...KEY.paymentInstruments, ownerId],\n queryFn: async () => {\n const result = await subQuery<{\n subListPaymentInstruments: SubConnection<SubPaymentInstrument>;\n }>(\n `query SubPaymentInstruments($ownerId: ID) {\n subListPaymentInstruments(ownerId: $ownerId) {\n items {\n id label type status brand last4 expiryMonth expiryYear isDefault\n ownerId workspaceId createdAt updatedAt\n }\n pageInfo { cursor hasMore }\n }\n }`,\n { ownerId },\n apiGatewayUrl\n );\n return result.subListPaymentInstruments.items;\n },\n });\n};\n\nexport const useCreatePaymentInstrument = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async (input: SubCreatePaymentInstrumentInput) => {\n const result = await subQuery<{ subCreatePaymentInstrument: SubPaymentInstrument }>(\n `mutation SubCreatePaymentInstrument($input: SubCreatePaymentInstrumentInput!) {\n subCreatePaymentInstrument(input: $input) { ${PAYMENT_INSTRUMENT_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.subCreatePaymentInstrument;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: KEY.paymentInstruments });\n },\n });\n};\n\nexport const useRemovePaymentInstrument = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await subQuery<{ subRemovePaymentInstrument: boolean }>(\n `mutation SubRemovePaymentInstrument($id: ID!) {\n subRemovePaymentInstrument(id: $id)\n }`,\n { id },\n apiGatewayUrl\n );\n return result.subRemovePaymentInstrument;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: KEY.paymentInstruments });\n },\n });\n};\n\nexport const useChannels = (ownerId?: string) => {\n const { apiGatewayUrl } = useSubscriberBot();\n return useQuery({\n queryKey: [...KEY.channels, ownerId],\n queryFn: async () => {\n const result = await subQuery<{\n subListChannels: SubConnection<SubCommunicationChannel>;\n }>(\n `query SubChannels($ownerId: ID) {\n subListChannels(ownerId: $ownerId) {\n items {\n id label type status address ingestEnabled ownerId verifiedAt\n workspaceId createdAt updatedAt\n }\n pageInfo { cursor hasMore }\n }\n }`,\n { ownerId },\n apiGatewayUrl\n );\n return result.subListChannels.items;\n },\n });\n};\n\nexport const useCreateChannel = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async (input: SubCreateChannelInput) => {\n const result = await subQuery<{ subCreateChannel: SubCommunicationChannel }>(\n `mutation SubCreateChannel($input: SubCreateChannelInput!) {\n subCreateChannel(input: $input) { ${CHANNEL_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.subCreateChannel;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: KEY.channels });\n },\n });\n};\n\nexport const useVerifyChannel = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await subQuery<{ subVerifyChannel: SubCommunicationChannel }>(\n `mutation SubVerifyChannel($id: ID!) {\n subVerifyChannel(id: $id) { ${CHANNEL_FIELDS} }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.subVerifyChannel;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: KEY.channels });\n },\n });\n};\n\n// ============================================================================\n// AI Agents & workflows (automation)\n// ============================================================================\n\nexport interface AgentListFilters {\n kind?: SubAgentKind;\n status?: SubAgentStatus;\n ownerId?: string;\n}\n\nexport const useAgents = (filters: AgentListFilters = {}) => {\n const { apiGatewayUrl } = useSubscriberBot();\n return useQuery({\n queryKey: [...KEY.agents, filters],\n queryFn: async () => {\n const result = await subQuery<{ subListAgents: SubConnection<SubAiAgent> }>(\n `query SubAgents($kind: SubAgentKind, $status: SubAgentStatus, $ownerId: ID) {\n subListAgents(kind: $kind, status: $status, ownerId: $ownerId) {\n items { ${AGENT_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n { kind: filters.kind, status: filters.status, ownerId: filters.ownerId },\n apiGatewayUrl\n );\n return result.subListAgents.items;\n },\n });\n};\n\nexport const useAgent = (id: string | undefined) => {\n const { apiGatewayUrl } = useSubscriberBot();\n return useQuery({\n queryKey: KEY.agent(id ?? ''),\n enabled: Boolean(id),\n queryFn: async () => {\n const result = await subQuery<{ subAgent: SubAiAgent | null }>(\n `query SubAgent($id: ID!) {\n subAgent(id: $id) {\n ${AGENT_FIELDS}\n policies { ${POLICY_FIELDS} }\n }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.subAgent;\n },\n });\n};\n\nexport const useCreateAgent = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async (input: SubCreateAgentInput) => {\n const result = await subQuery<{ subCreateAgent: SubAiAgent }>(\n `mutation SubCreateAgent($input: SubCreateAgentInput!) {\n subCreateAgent(input: $input) { ${AGENT_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.subCreateAgent;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: KEY.agents });\n },\n });\n};\n\nexport const useSetAgentStatus = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async ({ id, status }: { id: string; status: SubAgentStatus }) => {\n const result = await subQuery<{ subSetAgentStatus: SubAiAgent }>(\n `mutation SubSetAgentStatus($id: ID!, $status: SubAgentStatus!) {\n subSetAgentStatus(id: $id, status: $status) { ${AGENT_FIELDS} }\n }`,\n { id, status },\n apiGatewayUrl\n );\n return result.subSetAgentStatus;\n },\n onSuccess: (data) => {\n void queryClient.invalidateQueries({ queryKey: KEY.agents });\n void queryClient.invalidateQueries({ queryKey: KEY.agent(data.id) });\n },\n });\n};\n\nexport const useCreatePolicy = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async (input: SubCreatePolicyInput) => {\n const result = await subQuery<{ subCreatePolicy: SubPolicy }>(\n `mutation SubCreatePolicy($input: SubCreatePolicyInput!) {\n subCreatePolicy(input: $input) { ${POLICY_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.subCreatePolicy;\n },\n onSuccess: (data) => {\n void queryClient.invalidateQueries({ queryKey: KEY.agents });\n void queryClient.invalidateQueries({ queryKey: KEY.agent(data.agentId) });\n },\n });\n};\n\nexport const useWorkflows = (status?: SubWorkflowStatus) => {\n const { apiGatewayUrl } = useSubscriberBot();\n return useQuery({\n queryKey: [...KEY.workflows, status],\n queryFn: async () => {\n const result = await subQuery<{ subListWorkflows: SubConnection<SubWorkflow> }>(\n `query SubWorkflows($status: SubWorkflowStatus) {\n subListWorkflows(status: $status) { items { ${WORKFLOW_FIELDS} } pageInfo { cursor hasMore } }\n }`,\n { status },\n apiGatewayUrl\n );\n return result.subListWorkflows.items;\n },\n });\n};\n\nexport const useCreateWorkflow = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async (input: SubCreateWorkflowInput) => {\n const result = await subQuery<{ subCreateWorkflow: SubWorkflow }>(\n `mutation SubCreateWorkflow($input: SubCreateWorkflowInput!) {\n subCreateWorkflow(input: $input) { ${WORKFLOW_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.subCreateWorkflow;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: KEY.workflows });\n },\n });\n};\n\nexport const useActivateWorkflow = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await subQuery<{ subActivateWorkflow: SubWorkflow }>(\n `mutation SubActivateWorkflow($id: ID!) {\n subActivateWorkflow(id: $id) { ${WORKFLOW_FIELDS} }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.subActivateWorkflow;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: KEY.workflows });\n },\n });\n};\n\n// ============================================================================\n// Admin governance (adapter approvals + marketplace moderation)\n// ============================================================================\n\nexport interface AdapterSubmissionListFilters {\n status?: SubSubmissionStatus;\n pagination?: PaginationInput;\n}\n\nexport const useAdapterSubmissions = (filters: AdapterSubmissionListFilters = {}) => {\n const { apiGatewayUrl } = useSubscriberBot();\n return useQuery({\n queryKey: [...KEY.adapterSubmissions, filters],\n queryFn: async () => {\n const result = await subQuery<{\n subListAdapterSubmissions: SubConnection<SubAdapterSubmission>;\n }>(\n `query SubAdapterSubmissions($status: SubSubmissionStatus, $pagination: PaginationInput) {\n subListAdapterSubmissions(status: $status, pagination: $pagination) {\n items { ${ADAPTER_SUBMISSION_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n {\n status: filters.status,\n pagination: filters.pagination ?? { limit: 50, offset: 0 },\n },\n apiGatewayUrl\n );\n return result.subListAdapterSubmissions;\n },\n });\n};\n\nexport const useApproveAdapter = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async ({ id, notes }: { id: string; notes?: string }) => {\n const result = await subQuery<{ subApproveAdapter: SubAdapterSubmission }>(\n `mutation SubApproveAdapter($id: ID!, $notes: String) {\n subApproveAdapter(id: $id, notes: $notes) { ${ADAPTER_SUBMISSION_FIELDS} }\n }`,\n { id, notes },\n apiGatewayUrl\n );\n return result.subApproveAdapter;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: KEY.adapterSubmissions });\n },\n });\n};\n\nexport const useRejectAdapter = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async ({ id, reason }: { id: string; reason: string }) => {\n const result = await subQuery<{ subRejectAdapter: SubAdapterSubmission }>(\n `mutation SubRejectAdapter($id: ID!, $reason: String!) {\n subRejectAdapter(id: $id, reason: $reason) { ${ADAPTER_SUBMISSION_FIELDS} }\n }`,\n { id, reason },\n apiGatewayUrl\n );\n return result.subRejectAdapter;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: KEY.adapterSubmissions });\n },\n });\n};\n\nexport interface MarketplaceReportListFilters {\n status?: SubReportStatus;\n pagination?: PaginationInput;\n}\n\nexport const useMarketplaceReports = (filters: MarketplaceReportListFilters = {}) => {\n const { apiGatewayUrl } = useSubscriberBot();\n return useQuery({\n queryKey: [...KEY.marketplaceReports, filters],\n queryFn: async () => {\n const result = await subQuery<{\n subListMarketplaceReports: SubConnection<SubMarketplaceReport>;\n }>(\n `query SubMarketplaceReports($status: SubReportStatus, $pagination: PaginationInput) {\n subListMarketplaceReports(status: $status, pagination: $pagination) {\n items { ${MARKETPLACE_REPORT_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n {\n status: filters.status,\n pagination: filters.pagination ?? { limit: 50, offset: 0 },\n },\n apiGatewayUrl\n );\n return result.subListMarketplaceReports;\n },\n });\n};\n\nexport const useModerateListing = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useSubscriberBot();\n return useMutation({\n mutationFn: async ({\n id,\n action,\n reason,\n }: {\n id: string;\n action: SubModerationAction;\n reason: string;\n }) => {\n const result = await subQuery<{ subModerateListing: SubMarketplaceReport }>(\n `mutation SubModerateListing($id: ID!, $action: SubModerationAction!, $reason: String!) {\n subModerateListing(id: $id, action: $action, reason: $reason) { ${MARKETPLACE_REPORT_FIELDS} }\n }`,\n { id, action, reason },\n apiGatewayUrl\n );\n return result.subModerateListing;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: KEY.marketplaceReports });\n },\n });\n};\n"],"mappings":"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"}
@@ -3,10 +3,10 @@ import { PageLayout as t } from "../components/PageLayout.js";
3
3
  import { MetricsCard as n } from "../components/MetricsCard.js";
4
4
  import { formatDate as r, formatEnumLabel as i } from "../utils/formatters.js";
5
5
  import { EmptyState as a } from "../components/EmptyState.js";
6
- import { ErrorView as o, LoadingView as s, Section as c } from "../components/StateViews.js";
6
+ import { useTr as o } from "../hooks/useTr.js";
7
+ import { ErrorView as s, LoadingView as c, Section as l } from "../components/StateViews.js";
7
8
  import "../components/index.js";
8
- import { useAllAssets as l, useFileDownloadUrl as u, useRelationships as d } from "../hooks/useSubscriberBotApi.js";
9
- import { useTr as f } from "../hooks/useTr.js";
9
+ import { useAllAssets as u, useFileDownloadUrl as d, useRelationships as f } from "../hooks/useSubscriberBotApi.js";
10
10
  import { useMemo as p, useState as m } from "react";
11
11
  import { AlarmClock as h, Award as g, Download as _, File as v, FileKey as y, FileText as b, Globe as x, Receipt as S, Search as C, ShieldCheck as w, Vault as T } from "lucide-react";
12
12
  import { jsx as E, jsxs as D } from "react/jsx-runtime";
@@ -42,14 +42,14 @@ var A = {
42
42
  return Number.isNaN(t) ? Infinity : t;
43
43
  };
44
44
  function P({ asset: t, subscription: n }) {
45
- let a = f(), o = u(), [s, c] = m(!1), l = A[t.type] ?? v, d = M(t.expiresAt);
45
+ let a = o(), s = d(), [c, l] = m(!1), u = A[t.type] ?? v, f = M(t.expiresAt);
46
46
  return /* @__PURE__ */ D(O, {
47
47
  treatment: "metric",
48
48
  className: "flex items-start gap-3 p-4",
49
49
  children: [
50
50
  /* @__PURE__ */ E("span", {
51
51
  className: "grid h-10 w-10 shrink-0 place-items-center rounded-lg bg-accent-wash text-text-link",
52
- children: /* @__PURE__ */ E(l, { className: "h-5 w-5" })
52
+ children: /* @__PURE__ */ E(u, { className: "h-5 w-5" })
53
53
  }),
54
54
  /* @__PURE__ */ D("div", {
55
55
  className: "min-w-0 flex-1",
@@ -68,7 +68,7 @@ function P({ asset: t, subscription: n }) {
68
68
  className: "rounded bg-bg-sunken px-1.5 py-0.5 text-text-secondary",
69
69
  children: i(t.type)
70
70
  }), t.expiresAt && /* @__PURE__ */ E("span", {
71
- className: e(d ? "text-status-warning-text" : "text-text-secondary"),
71
+ className: e(f ? "text-status-warning-text" : "text-text-secondary"),
72
72
  children: a("assetVault.expires", "Expires {{date}}", { date: r(t.expiresAt) })
73
73
  })]
74
74
  })
@@ -77,17 +77,17 @@ function P({ asset: t, subscription: n }) {
77
77
  t.file?.id && /* @__PURE__ */ E("button", {
78
78
  type: "button",
79
79
  onClick: async () => {
80
- if (!(!t.file?.id || s)) {
81
- c(!0);
80
+ if (!(!t.file?.id || c)) {
81
+ l(!0);
82
82
  try {
83
- let e = await o(t.file.id);
83
+ let e = await s(t.file.id);
84
84
  window.open(e, "_blank", "noopener,noreferrer");
85
85
  } finally {
86
- c(!1);
86
+ l(!1);
87
87
  }
88
88
  }
89
89
  },
90
- disabled: s,
90
+ disabled: c,
91
91
  "aria-label": a("assetVault.downloadAriaLabel", "Download {{name}}", { name: t.name }),
92
92
  className: "shrink-0 rounded-lg border border-border-subtle p-2 text-text-secondary hover:text-text-primary disabled:opacity-50",
93
93
  children: /* @__PURE__ */ E(_, { className: "h-4 w-4" })
@@ -96,11 +96,11 @@ function P({ asset: t, subscription: n }) {
96
96
  });
97
97
  }
98
98
  var F = () => {
99
- let u = l(), g = d({ pagination: { limit: 100 } }), _ = f(), [y, x] = m(""), [S, A] = m("ALL"), F = p(() => {
99
+ let d = u(), g = f({ pagination: { limit: 100 } }), _ = o(), [y, x] = m(""), [S, A] = m("ALL"), F = p(() => {
100
100
  let e = /* @__PURE__ */ new Map();
101
101
  for (let t of g.data?.items ?? []) e.set(t.id, t.label);
102
102
  return e;
103
- }, [g.data]), I = p(() => u.data ?? [], [u.data]), L = p(() => I.filter((e) => (S === "ALL" || e.type === S) && (!y || e.name.toLowerCase().includes(y.toLowerCase()))), [
103
+ }, [g.data]), I = p(() => d.data ?? [], [d.data]), L = p(() => I.filter((e) => (S === "ALL" || e.type === S) && (!y || e.name.toLowerCase().includes(y.toLowerCase()))), [
104
104
  I,
105
105
  S,
106
106
  y
@@ -109,9 +109,9 @@ var F = () => {
109
109
  for (let t of L) e.set(t.type, [...e.get(t.type) ?? [], t]);
110
110
  return j.filter((t) => e.has(t)).map((t) => [t, e.get(t)]);
111
111
  }, [L]), z = p(() => I.filter((e) => M(e.expiresAt)).sort((e, t) => N(e.expiresAt) - N(t.expiresAt)), [I]);
112
- return u.isLoading ? /* @__PURE__ */ E(s, { label: _("assetVault.loading", "Loading your asset vault…") }) : u.isError ? /* @__PURE__ */ E(o, {
112
+ return d.isLoading ? /* @__PURE__ */ E(c, { label: _("assetVault.loading", "Loading your asset vault…") }) : d.isError ? /* @__PURE__ */ E(s, {
113
113
  message: _("assetVault.error", "Could not load the asset vault."),
114
- onRetry: () => void u.refetch()
114
+ onRetry: () => void d.refetch()
115
115
  }) : /* @__PURE__ */ D(t, {
116
116
  title: _("assetVault.title", "Asset vault"),
117
117
  description: _("assetVault.description", "Every contract, receipt, license key and document attached to your subscriptions — in one secure place."),
@@ -172,7 +172,7 @@ var F = () => {
172
172
  icon: /* @__PURE__ */ E(T, { className: "h-8 w-8" }),
173
173
  title: I.length === 0 ? _("assetVault.empty.noDocumentsTitle", "No documents yet") : _("assetVault.empty.noMatchesTitle", "No matching documents"),
174
174
  description: I.length === 0 ? _("assetVault.empty.noDocumentsDescription", "Attach a contract, receipt or license key from any subscription’s detail page and it will appear here.") : _("assetVault.empty.noMatchesDescription", "Try a different search or type filter.")
175
- }) : R.map(([e, t]) => /* @__PURE__ */ E(c, {
175
+ }) : R.map(([e, t]) => /* @__PURE__ */ E(l, {
176
176
  title: `${i(e)} · ${t.length}`,
177
177
  children: /* @__PURE__ */ E("div", {
178
178
  className: "grid grid-cols-1 gap-3 md:grid-cols-2 xl:grid-cols-3",
@@ -4,13 +4,13 @@ import { MetricsCard as n } from "../components/MetricsCard.js";
4
4
  import { formatCurrency as r, formatEnumLabel as i, formatRelativeTime as a } from "../utils/formatters.js";
5
5
  import { StatusBadge as o } from "../components/StatusBadge.js";
6
6
  import { EmptyState as s } from "../components/EmptyState.js";
7
- import { ErrorView as c, LoadingView as l, Section as u } from "../components/StateViews.js";
7
+ import { useTr as c } from "../hooks/useTr.js";
8
+ import { ErrorView as ee, LoadingView as l, Section as u } from "../components/StateViews.js";
8
9
  import { Donut as d, Legend as f, Timeline as p } from "../components/viz.js";
9
10
  import "../components/index.js";
10
11
  import { useInboxMessages as m, useInvoices as h, useRelationships as g, useRenewalEvents as _ } from "../hooks/useSubscriberBotApi.js";
11
- import { useTr as v } from "../hooks/useTr.js";
12
- import { useMemo as y } from "react";
13
- import { AlertTriangle as b, ArrowRight as x, ArrowUpRight as S, Bot as C, CalendarClock as w, Inbox as T, Repeat2 as E, ShieldCheck as ee, Sparkles as D, Wallet as O } from "lucide-react";
12
+ import { useMemo as v } from "react";
13
+ import { AlertTriangle as y, ArrowRight as b, ArrowUpRight as x, Bot as S, CalendarClock as C, Inbox as w, Repeat2 as T, ShieldCheck as E, Sparkles as D, Wallet as O } from "lucide-react";
14
14
  import { jsx as k, jsxs as A } from "react/jsx-runtime";
15
15
  import { GlassCard as j, PagePurpose as M } from "@burdenoff/fe-libs/ui";
16
16
  //#region src/subscriberbot/pages/DashboardPage.tsx
@@ -25,7 +25,7 @@ var N = {
25
25
  USAGE_BASED: 1
26
26
  }, P = 1e3 * 60 * 60 * 24;
27
27
  function F() {
28
- let { navigateTo: F, currentUser: I } = e(), L = v(), R = g({ pagination: {
28
+ let { navigateTo: F, currentUser: I } = e(), L = c(), R = g({ pagination: {
29
29
  limit: 100,
30
30
  offset: 0
31
31
  } }), z = h({ pagination: {
@@ -34,10 +34,10 @@ function F() {
34
34
  } }), B = m({ pagination: {
35
35
  limit: 50,
36
36
  offset: 0
37
- } }), V = _({ upcomingOnly: !0 }), H = y(() => R.data?.items ?? [], [R.data]), U = y(() => z.data?.items ?? [], [z.data]), W = y(() => B.data?.items ?? [], [B.data]), G = y(() => V.data ?? [], [V.data]), K = y(() => {
37
+ } }), V = _({ upcomingOnly: !0 }), H = v(() => R.data?.items ?? [], [R.data]), U = v(() => z.data?.items ?? [], [z.data]), W = v(() => B.data?.items ?? [], [B.data]), G = v(() => V.data ?? [], [V.data]), K = v(() => {
38
38
  let e = /* @__PURE__ */ new Map();
39
39
  return H.forEach((t) => e.set(t.id, t)), e;
40
- }, [H]), q = y(() => {
40
+ }, [H]), q = v(() => {
41
41
  let e = H.filter((e) => e.status === "ACTIVE" || e.status === "TRIAL"), t = e.reduce((e, t) => e + t.amount * (N[t.interval] ?? 1), 0), n = e[0]?.currency ?? H[0]?.currency ?? "USD", r = W.filter((e) => e.actionRequired).length, i = U.filter((e) => e.status === "ISSUED" || e.status === "OVERDUE" || e.status === "FAILED"), a = i.reduce((e, t) => e + t.total, 0), o = H.filter((e) => e.status === "PAST_DUE" || e.status === "LAPSED").length;
42
42
  return {
43
43
  activeCount: e.length,
@@ -53,13 +53,13 @@ function F() {
53
53
  H,
54
54
  W,
55
55
  U
56
- ]), J = y(() => {
56
+ ]), J = v(() => {
57
57
  let e = /* @__PURE__ */ new Map();
58
58
  return H.forEach((t) => e.set(t.status, (e.get(t.status) ?? 0) + 1)), Array.from(e.entries()).sort((e, t) => t[1] - e[1]).map(([e, t]) => ({
59
59
  label: i(e),
60
60
  value: t
61
61
  }));
62
- }, [H]), Y = y(() => {
62
+ }, [H]), Y = v(() => {
63
63
  let e = Date.now(), t = G.map((t) => {
64
64
  let n = K.get(t.relationshipId), r = new Date(t.occursAt).getTime();
65
65
  return {
@@ -92,12 +92,12 @@ function F() {
92
92
  G,
93
93
  H,
94
94
  K
95
- ]), X = y(() => Y.slice(0, 6).map((e) => ({
95
+ ]), X = v(() => Y.slice(0, 6).map((e) => ({
96
96
  title: e.title,
97
97
  sub: a(e.when),
98
98
  tone: e.soon ? "warning" : "default",
99
99
  meta: e.amount == null ? void 0 : r(e.amount, e.currency ?? q.primaryCurrency, { maximumFractionDigits: 0 })
100
- })), [Y, q.primaryCurrency]), Z = y(() => W.filter((e) => e.actionRequired), [W]), Q = R.isLoading || z.isLoading || B.isLoading || V.isLoading, te = R.isError && z.isError && B.isError && V.isError;
100
+ })), [Y, q.primaryCurrency]), Z = v(() => W.filter((e) => e.actionRequired), [W]), Q = R.isLoading || z.isLoading || B.isLoading || V.isLoading, te = R.isError && z.isError && B.isError && V.isError;
101
101
  if (Q) return /* @__PURE__ */ k(t, {
102
102
  title: L("dashboard.title", "Overview"),
103
103
  description: L("dashboard.description", "Your recurring digital relationships at a glance"),
@@ -106,7 +106,7 @@ function F() {
106
106
  if (te) return /* @__PURE__ */ k(t, {
107
107
  title: L("dashboard.title", "Overview"),
108
108
  description: L("dashboard.description", "Your recurring digital relationships at a glance"),
109
- children: /* @__PURE__ */ k(c, {
109
+ children: /* @__PURE__ */ k(ee, {
110
110
  message: L("dashboard.error", "We couldn't reach the Subscriber Bot service. Please try again."),
111
111
  onRetry: () => {
112
112
  R.refetch(), z.refetch(), B.refetch(), V.refetch();
@@ -119,7 +119,7 @@ function F() {
119
119
  descriptionKey: "dashboard.quickActions.addRelationship.description",
120
120
  fallbackLabel: "Add a relationship",
121
121
  fallbackDescription: "Track a new subscription",
122
- icon: /* @__PURE__ */ k(E, { className: "h-5 w-5" }),
122
+ icon: /* @__PURE__ */ k(T, { className: "h-5 w-5" }),
123
123
  path: "/relationships/new"
124
124
  },
125
125
  {
@@ -135,7 +135,7 @@ function F() {
135
135
  descriptionKey: "dashboard.quickActions.openInbox.description",
136
136
  fallbackLabel: "Open inbox",
137
137
  fallbackDescription: "Merged communications",
138
- icon: /* @__PURE__ */ k(T, { className: "h-5 w-5" }),
138
+ icon: /* @__PURE__ */ k(w, { className: "h-5 w-5" }),
139
139
  path: "/inbox"
140
140
  },
141
141
  {
@@ -143,7 +143,7 @@ function F() {
143
143
  descriptionKey: "dashboard.quickActions.configureAgents.description",
144
144
  fallbackLabel: "Configure agents",
145
145
  fallbackDescription: "Automate your portfolio",
146
- icon: /* @__PURE__ */ k(C, { className: "h-5 w-5" }),
146
+ icon: /* @__PURE__ */ k(S, { className: "h-5 w-5" }),
147
147
  path: "/agents"
148
148
  }
149
149
  ];
@@ -165,17 +165,17 @@ function F() {
165
165
  label: L("dashboard.metrics.recurringSpend", "Recurring spend / month")
166
166
  }),
167
167
  /* @__PURE__ */ k(n, {
168
- icon: /* @__PURE__ */ k(E, {}),
168
+ icon: /* @__PURE__ */ k(T, {}),
169
169
  value: q.activeCount,
170
170
  label: L("dashboard.metrics.activeRelationships", "Active relationships")
171
171
  }),
172
172
  /* @__PURE__ */ k(n, {
173
- icon: /* @__PURE__ */ k(w, {}),
173
+ icon: /* @__PURE__ */ k(C, {}),
174
174
  value: Y.length,
175
175
  label: L("dashboard.metrics.upcomingRenewals", "Upcoming renewals")
176
176
  }),
177
177
  /* @__PURE__ */ k(n, {
178
- icon: /* @__PURE__ */ k(b, {}),
178
+ icon: /* @__PURE__ */ k(y, {}),
179
179
  value: q.actionRequired,
180
180
  label: L("dashboard.metrics.needsAction", "Need your action"),
181
181
  trend: q.actionRequired > 0 ? "down" : void 0
@@ -197,7 +197,7 @@ function F() {
197
197
  children: [
198
198
  L("common.viewAll", "View all"),
199
199
  " ",
200
- /* @__PURE__ */ k(S, { className: "h-3.5 w-3.5" })
200
+ /* @__PURE__ */ k(x, { className: "h-3.5 w-3.5" })
201
201
  ]
202
202
  }),
203
203
  children: /* @__PURE__ */ k(j, {
@@ -261,7 +261,7 @@ function F() {
261
261
  className: "flex items-center gap-3 px-2 py-4",
262
262
  children: [/* @__PURE__ */ k("span", {
263
263
  className: "flex size-10 shrink-0 items-center justify-center rounded-lg bg-status-success-bg-subtle text-status-success-text",
264
- children: /* @__PURE__ */ k(ee, { className: "h-5 w-5" })
264
+ children: /* @__PURE__ */ k(E, { className: "h-5 w-5" })
265
265
  }), /* @__PURE__ */ A("div", {
266
266
  className: "min-w-0",
267
267
  children: [/* @__PURE__ */ k("p", {
@@ -303,14 +303,14 @@ function F() {
303
303
  className: "mt-6 flex w-full items-center justify-between gap-3 rounded-xl border border-status-warning-text/30 bg-status-warning-bg-subtle px-5 py-4 text-left transition-shadow hover:shadow-md",
304
304
  children: [/* @__PURE__ */ A("div", {
305
305
  className: "flex items-center gap-3",
306
- children: [/* @__PURE__ */ k(b, { className: "h-5 w-5 shrink-0 text-status-warning-text" }), /* @__PURE__ */ k("span", {
306
+ children: [/* @__PURE__ */ k(y, { className: "h-5 w-5 shrink-0 text-status-warning-text" }), /* @__PURE__ */ k("span", {
307
307
  className: "text-sm font-medium text-status-warning-text",
308
308
  children: L("dashboard.openInvoices.label", "{{count}} open invoice · {{amount}} outstanding", {
309
309
  count: q.openInvoiceCount,
310
310
  amount: r(q.openInvoiceTotal, q.primaryCurrency)
311
311
  })
312
312
  })]
313
- }), /* @__PURE__ */ k(x, { className: "h-4 w-4 shrink-0 text-status-warning-text" })]
313
+ }), /* @__PURE__ */ k(b, { className: "h-4 w-4 shrink-0 text-status-warning-text" })]
314
314
  }),
315
315
  /* @__PURE__ */ k(u, {
316
316
  title: L("dashboard.quickActions.title", "Quick actions"),
@@ -336,7 +336,7 @@ function F() {
336
336
  children: L(e.descriptionKey, e.fallbackDescription)
337
337
  })]
338
338
  }),
339
- /* @__PURE__ */ k(x, { className: "h-4 w-4 shrink-0 text-text-secondary transition-transform group-hover:translate-x-0.5" })
339
+ /* @__PURE__ */ k(b, { className: "h-4 w-4 shrink-0 text-text-secondary transition-transform group-hover:translate-x-0.5" })
340
340
  ]
341
341
  }, e.path))
342
342
  })