@burdenoff/microfe-subscriberbot 2026.626.2 → 2026.629.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 (141) hide show
  1. package/dist/index.js +4 -4
  2. package/dist/subscriberbot/SubscriberBotRoot.js +61 -133
  3. package/dist/subscriberbot/SubscriberBotRoot.js.map +1 -1
  4. package/dist/subscriberbot/SubscriberBotRoutes.js +56 -187
  5. package/dist/subscriberbot/SubscriberBotRoutes.js.map +1 -1
  6. package/dist/subscriberbot/components/StateViews.js +49 -0
  7. package/dist/subscriberbot/components/StateViews.js.map +1 -0
  8. package/dist/subscriberbot/components/StatusBadge.js +45 -47
  9. package/dist/subscriberbot/components/StatusBadge.js.map +1 -1
  10. package/dist/subscriberbot/context/SubscriberBotContext.js +22 -30
  11. package/dist/subscriberbot/context/SubscriberBotContext.js.map +1 -1
  12. package/dist/subscriberbot/hooks/useSubscriberBotApi.js +342 -195
  13. package/dist/subscriberbot/hooks/useSubscriberBotApi.js.map +1 -1
  14. package/dist/subscriberbot/index.js +1 -1
  15. package/dist/subscriberbot/pages/DashboardPage.js +269 -0
  16. package/dist/subscriberbot/pages/DashboardPage.js.map +1 -0
  17. package/dist/subscriberbot/pages/InboxPage.js +186 -0
  18. package/dist/subscriberbot/pages/InboxPage.js.map +1 -0
  19. package/dist/subscriberbot/pages/InvoicesPage.js +211 -0
  20. package/dist/subscriberbot/pages/InvoicesPage.js.map +1 -0
  21. package/dist/subscriberbot/pages/WorkflowsPage.js +236 -0
  22. package/dist/subscriberbot/pages/WorkflowsPage.js.map +1 -0
  23. package/dist/subscriberbot/pages/agents/AgentDetailPage.js +160 -0
  24. package/dist/subscriberbot/pages/agents/AgentDetailPage.js.map +1 -0
  25. package/dist/subscriberbot/pages/agents/AgentNewPage.js +140 -0
  26. package/dist/subscriberbot/pages/agents/AgentNewPage.js.map +1 -0
  27. package/dist/subscriberbot/pages/agents/AgentsListPage.js +178 -0
  28. package/dist/subscriberbot/pages/agents/AgentsListPage.js.map +1 -0
  29. package/dist/subscriberbot/pages/providers/ProviderDetailPage.js +179 -0
  30. package/dist/subscriberbot/pages/providers/ProviderDetailPage.js.map +1 -0
  31. package/dist/subscriberbot/pages/providers/ProviderNewPage.js +185 -0
  32. package/dist/subscriberbot/pages/providers/ProviderNewPage.js.map +1 -0
  33. package/dist/subscriberbot/pages/providers/ProvidersListPage.js +254 -0
  34. package/dist/subscriberbot/pages/providers/ProvidersListPage.js.map +1 -0
  35. package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.js +306 -0
  36. package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.js.map +1 -0
  37. package/dist/subscriberbot/pages/relationships/RelationshipNewPage.js +253 -0
  38. package/dist/subscriberbot/pages/relationships/RelationshipNewPage.js.map +1 -0
  39. package/dist/subscriberbot/pages/relationships/RelationshipsListPage.js +248 -0
  40. package/dist/subscriberbot/pages/relationships/RelationshipsListPage.js.map +1 -0
  41. package/dist/subscriberbot/utils/formatters.js +50 -32
  42. package/dist/subscriberbot/utils/formatters.js.map +1 -1
  43. package/package.json +1 -1
  44. package/dist/subscriberbot/components/InvestmentCard.js +0 -97
  45. package/dist/subscriberbot/components/InvestmentCard.js.map +0 -1
  46. package/dist/subscriberbot/components/RatingDisplay.js +0 -35
  47. package/dist/subscriberbot/components/RatingDisplay.js.map +0 -1
  48. package/dist/subscriberbot/mocks/data.js +0 -1517
  49. package/dist/subscriberbot/mocks/data.js.map +0 -1
  50. package/dist/subscriberbot/mocks/users.js +0 -34
  51. package/dist/subscriberbot/mocks/users.js.map +0 -1
  52. package/dist/subscriberbot/pages/HomePage.js +0 -930
  53. package/dist/subscriberbot/pages/HomePage.js.map +0 -1
  54. package/dist/subscriberbot/pages/admin/AdminAnalyticsPage.js +0 -651
  55. package/dist/subscriberbot/pages/admin/AdminAnalyticsPage.js.map +0 -1
  56. package/dist/subscriberbot/pages/admin/AdminDashboard.js +0 -679
  57. package/dist/subscriberbot/pages/admin/AdminDashboard.js.map +0 -1
  58. package/dist/subscriberbot/pages/admin/AdminFinancialPage.js +0 -427
  59. package/dist/subscriberbot/pages/admin/AdminFinancialPage.js.map +0 -1
  60. package/dist/subscriberbot/pages/admin/AdminOrdersPage.js +0 -665
  61. package/dist/subscriberbot/pages/admin/AdminOrdersPage.js.map +0 -1
  62. package/dist/subscriberbot/pages/admin/AdminProfilePage.js +0 -261
  63. package/dist/subscriberbot/pages/admin/AdminProfilePage.js.map +0 -1
  64. package/dist/subscriberbot/pages/admin/AdminSettingsPage.js +0 -654
  65. package/dist/subscriberbot/pages/admin/AdminSettingsPage.js.map +0 -1
  66. package/dist/subscriberbot/pages/admin/CartManagementPage.js +0 -874
  67. package/dist/subscriberbot/pages/admin/CartManagementPage.js.map +0 -1
  68. package/dist/subscriberbot/pages/admin/UserManagementPage.js +0 -898
  69. package/dist/subscriberbot/pages/admin/UserManagementPage.js.map +0 -1
  70. package/dist/subscriberbot/pages/cart-owner/AnalyticsDashboard.js +0 -839
  71. package/dist/subscriberbot/pages/cart-owner/AnalyticsDashboard.js.map +0 -1
  72. package/dist/subscriberbot/pages/cart-owner/BusinessSettingsPage.js +0 -705
  73. package/dist/subscriberbot/pages/cart-owner/BusinessSettingsPage.js.map +0 -1
  74. package/dist/subscriberbot/pages/cart-owner/CartOwnerDashboard.js +0 -802
  75. package/dist/subscriberbot/pages/cart-owner/CartOwnerDashboard.js.map +0 -1
  76. package/dist/subscriberbot/pages/cart-owner/CartOwnerProfilePage.js +0 -891
  77. package/dist/subscriberbot/pages/cart-owner/CartOwnerProfilePage.js.map +0 -1
  78. package/dist/subscriberbot/pages/cart-owner/CartServiceConfigPage.js +0 -633
  79. package/dist/subscriberbot/pages/cart-owner/CartServiceConfigPage.js.map +0 -1
  80. package/dist/subscriberbot/pages/cart-owner/InventoryManagementPage.js +0 -910
  81. package/dist/subscriberbot/pages/cart-owner/InventoryManagementPage.js.map +0 -1
  82. package/dist/subscriberbot/pages/cart-owner/OrderManagementPage.js +0 -879
  83. package/dist/subscriberbot/pages/cart-owner/OrderManagementPage.js.map +0 -1
  84. package/dist/subscriberbot/pages/cart-owner/StaffManagementPage.js +0 -838
  85. package/dist/subscriberbot/pages/cart-owner/StaffManagementPage.js.map +0 -1
  86. package/dist/subscriberbot/pages/common/HelpSupportPage.js +0 -1323
  87. package/dist/subscriberbot/pages/common/HelpSupportPage.js.map +0 -1
  88. package/dist/subscriberbot/pages/common/NotificationCenterPage.js +0 -672
  89. package/dist/subscriberbot/pages/common/NotificationCenterPage.js.map +0 -1
  90. package/dist/subscriberbot/pages/common/SettingsPage.js +0 -973
  91. package/dist/subscriberbot/pages/common/SettingsPage.js.map +0 -1
  92. package/dist/subscriberbot/pages/customer/BookingDetailsPage.js +0 -626
  93. package/dist/subscriberbot/pages/customer/BookingDetailsPage.js.map +0 -1
  94. package/dist/subscriberbot/pages/customer/CartDetailPage.js +0 -654
  95. package/dist/subscriberbot/pages/customer/CartDetailPage.js.map +0 -1
  96. package/dist/subscriberbot/pages/customer/CartDiscoveryPage.js +0 -555
  97. package/dist/subscriberbot/pages/customer/CartDiscoveryPage.js.map +0 -1
  98. package/dist/subscriberbot/pages/customer/CheckoutPage.js +0 -529
  99. package/dist/subscriberbot/pages/customer/CheckoutPage.js.map +0 -1
  100. package/dist/subscriberbot/pages/customer/CustomerDashboard.js +0 -532
  101. package/dist/subscriberbot/pages/customer/CustomerDashboard.js.map +0 -1
  102. package/dist/subscriberbot/pages/customer/CustomerProfilePage.js +0 -630
  103. package/dist/subscriberbot/pages/customer/CustomerProfilePage.js.map +0 -1
  104. package/dist/subscriberbot/pages/customer/DirectServiceBookingPage.js +0 -633
  105. package/dist/subscriberbot/pages/customer/DirectServiceBookingPage.js.map +0 -1
  106. package/dist/subscriberbot/pages/customer/FavoritesPage.js +0 -484
  107. package/dist/subscriberbot/pages/customer/FavoritesPage.js.map +0 -1
  108. package/dist/subscriberbot/pages/customer/OrderHistoryPage.js +0 -446
  109. package/dist/subscriberbot/pages/customer/OrderHistoryPage.js.map +0 -1
  110. package/dist/subscriberbot/pages/customer/OrderTrackingPage.js +0 -394
  111. package/dist/subscriberbot/pages/customer/OrderTrackingPage.js.map +0 -1
  112. package/dist/subscriberbot/pages/customer/PaymentMethodsPage.js +0 -495
  113. package/dist/subscriberbot/pages/customer/PaymentMethodsPage.js.map +0 -1
  114. package/dist/subscriberbot/pages/customer/ReviewsPage.js +0 -613
  115. package/dist/subscriberbot/pages/customer/ReviewsPage.js.map +0 -1
  116. package/dist/subscriberbot/pages/customer/SavedAddressesPage.js +0 -450
  117. package/dist/subscriberbot/pages/customer/SavedAddressesPage.js.map +0 -1
  118. package/dist/subscriberbot/pages/investor/InvestmentDetailsPage.js +0 -886
  119. package/dist/subscriberbot/pages/investor/InvestmentDetailsPage.js.map +0 -1
  120. package/dist/subscriberbot/pages/investor/InvestmentOpportunitiesPage.js +0 -947
  121. package/dist/subscriberbot/pages/investor/InvestmentOpportunitiesPage.js.map +0 -1
  122. package/dist/subscriberbot/pages/investor/InvestorAnalyticsPage.js +0 -687
  123. package/dist/subscriberbot/pages/investor/InvestorAnalyticsPage.js.map +0 -1
  124. package/dist/subscriberbot/pages/investor/InvestorDashboard.js +0 -451
  125. package/dist/subscriberbot/pages/investor/InvestorDashboard.js.map +0 -1
  126. package/dist/subscriberbot/pages/investor/InvestorInvestmentsPage.js +0 -406
  127. package/dist/subscriberbot/pages/investor/InvestorInvestmentsPage.js.map +0 -1
  128. package/dist/subscriberbot/pages/investor/InvestorPortfolioPage.js +0 -575
  129. package/dist/subscriberbot/pages/investor/InvestorPortfolioPage.js.map +0 -1
  130. package/dist/subscriberbot/pages/investor/InvestorProfilePage.js +0 -1070
  131. package/dist/subscriberbot/pages/investor/InvestorProfilePage.js.map +0 -1
  132. package/dist/subscriberbot/pages/worker/TaskDetailsPage.js +0 -535
  133. package/dist/subscriberbot/pages/worker/TaskDetailsPage.js.map +0 -1
  134. package/dist/subscriberbot/pages/worker/WorkerDashboard.js +0 -666
  135. package/dist/subscriberbot/pages/worker/WorkerDashboard.js.map +0 -1
  136. package/dist/subscriberbot/pages/worker/WorkerOrdersPage.js +0 -681
  137. package/dist/subscriberbot/pages/worker/WorkerOrdersPage.js.map +0 -1
  138. package/dist/subscriberbot/pages/worker/WorkerProfilePage.js +0 -692
  139. package/dist/subscriberbot/pages/worker/WorkerProfilePage.js.map +0 -1
  140. package/dist/subscriberbot/pages/worker/WorkerSchedulePage.js +0 -588
  141. package/dist/subscriberbot/pages/worker/WorkerSchedulePage.js.map +0 -1
@@ -0,0 +1,160 @@
1
+ import { useSubscriberBot as e } from "../../context/SubscriberBotContext.js";
2
+ import { PageLayout as t } from "../../components/PageLayout.js";
3
+ import { formatEnumLabel as n, formatRelativeTime as r } from "../../utils/formatters.js";
4
+ import { StatusBadge as i } from "../../components/StatusBadge.js";
5
+ import { EmptyState as a } from "../../components/EmptyState.js";
6
+ import { ErrorView as o, LoadingView as s, Section as c } from "../../components/StateViews.js";
7
+ import { useAgent as l, useSetAgentStatus as u } from "../../hooks/useSubscriberBotApi.js";
8
+ import { useState as d } from "react";
9
+ import { ArrowLeft as f, Bot as p, ShieldCheck as m } from "lucide-react";
10
+ import { useParams as h } from "react-router-dom";
11
+ import { jsx as g, jsxs as _ } from "react/jsx-runtime";
12
+ import { GlassCard as v } from "@burdenoff/fe-libs/ui";
13
+ //#region src/subscriberbot/pages/agents/AgentDetailPage.tsx
14
+ var y = [
15
+ "DISABLED",
16
+ "SUGGEST_ONLY",
17
+ "AUTONOMOUS"
18
+ ];
19
+ function b() {
20
+ let { id: b } = h(), { navigateTo: x } = e(), { data: S, isLoading: C, isError: w, refetch: T } = l(b), E = u(), [D, O] = d(null);
21
+ if (C) return /* @__PURE__ */ g(t, {
22
+ title: "Agent",
23
+ children: /* @__PURE__ */ g(s, { label: "Loading agent…" })
24
+ });
25
+ if (w) return /* @__PURE__ */ g(t, {
26
+ title: "Agent",
27
+ children: /* @__PURE__ */ g(o, {
28
+ message: "Could not load this agent.",
29
+ onRetry: () => void T()
30
+ })
31
+ });
32
+ if (!S) return /* @__PURE__ */ g(t, {
33
+ title: "Agent",
34
+ children: /* @__PURE__ */ g(a, {
35
+ illustration: "empty-data",
36
+ title: "Agent not found",
37
+ description: "It may have been removed, or you may not have access to it.",
38
+ action: /* @__PURE__ */ g("button", {
39
+ type: "button",
40
+ onClick: () => x("/agents"),
41
+ className: "rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90",
42
+ children: "Back to agents"
43
+ })
44
+ })
45
+ });
46
+ let k = S;
47
+ return /* @__PURE__ */ _(t, {
48
+ title: k.name,
49
+ description: `${n(k.kind)} agent`,
50
+ actions: /* @__PURE__ */ _("button", {
51
+ type: "button",
52
+ onClick: () => x("/agents"),
53
+ className: "inline-flex items-center gap-2 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken",
54
+ children: [/* @__PURE__ */ g(f, { className: "h-4 w-4" }), " Back"]
55
+ }),
56
+ children: [
57
+ /* @__PURE__ */ _("div", {
58
+ className: "flex flex-wrap items-center gap-3",
59
+ children: [
60
+ /* @__PURE__ */ g("span", {
61
+ className: "flex size-10 items-center justify-center rounded-lg bg-[var(--color-accent-soft)] text-text-primary",
62
+ children: /* @__PURE__ */ g(p, { className: "h-5 w-5" })
63
+ }),
64
+ /* @__PURE__ */ g(i, { status: k.status }),
65
+ /* @__PURE__ */ g("span", {
66
+ className: "text-sm text-text-secondary",
67
+ children: k.lastRunAt ? `Last run ${r(k.lastRunAt)}` : "Never run"
68
+ })
69
+ ]
70
+ }),
71
+ k.description && /* @__PURE__ */ g("p", {
72
+ className: "mt-4 max-w-3xl text-sm text-text-secondary",
73
+ children: k.description
74
+ }),
75
+ D && /* @__PURE__ */ g("div", {
76
+ className: "mt-4 rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle px-4 py-2 text-sm text-status-error-text",
77
+ children: D
78
+ }),
79
+ /* @__PURE__ */ _("div", {
80
+ className: "mt-6 max-w-sm",
81
+ children: [
82
+ /* @__PURE__ */ g("label", {
83
+ htmlFor: "agent-posture",
84
+ className: "mb-1 block text-xs font-medium text-text-secondary",
85
+ children: "Operating posture"
86
+ }),
87
+ /* @__PURE__ */ g("select", {
88
+ id: "agent-posture",
89
+ value: k.status,
90
+ disabled: E.isPending,
91
+ onChange: (e) => {
92
+ O(null), E.mutate({
93
+ id: k.id,
94
+ status: e.target.value
95
+ }, { onError: (e) => O(e instanceof Error ? e.message : "Could not change posture.") });
96
+ },
97
+ className: "w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] disabled:opacity-50",
98
+ children: y.map((e) => /* @__PURE__ */ g("option", {
99
+ value: e,
100
+ children: n(e)
101
+ }, e))
102
+ }),
103
+ /* @__PURE__ */ g("p", {
104
+ className: "mt-1.5 text-xs text-text-secondary",
105
+ children: "Disabled never acts; Suggest-only proposes; Autonomous acts within its policies."
106
+ })
107
+ ]
108
+ }),
109
+ /* @__PURE__ */ g(c, {
110
+ title: "Policies",
111
+ description: "The autonomous rules that bound this agent",
112
+ children: !k.policies || k.policies.length === 0 ? /* @__PURE__ */ g(a, {
113
+ illustration: "empty-data",
114
+ title: "No policies",
115
+ description: "Policies define what this agent may do autonomously, and what it must alert on."
116
+ }) : /* @__PURE__ */ g("div", {
117
+ className: "grid grid-cols-1 gap-3 sm:grid-cols-2",
118
+ children: k.policies.map((e) => /* @__PURE__ */ _(v, {
119
+ treatment: "metric",
120
+ className: "p-4",
121
+ children: [
122
+ /* @__PURE__ */ _("div", {
123
+ className: "flex items-start justify-between gap-2",
124
+ children: [/* @__PURE__ */ g("p", {
125
+ className: "text-sm font-medium text-text-primary",
126
+ children: e.name
127
+ }), /* @__PURE__ */ g(i, { status: e.isEnabled ? "ACTIVE" : "DISABLED" })]
128
+ }),
129
+ /* @__PURE__ */ _("p", {
130
+ className: "mt-1 flex items-center gap-1.5 text-xs text-text-secondary",
131
+ children: [
132
+ /* @__PURE__ */ g(m, { className: "h-3.5 w-3.5" }),
133
+ " Action: ",
134
+ n(e.action)
135
+ ]
136
+ }),
137
+ e.description && /* @__PURE__ */ g("p", {
138
+ className: "mt-2 text-xs text-text-secondary",
139
+ children: e.description
140
+ }),
141
+ /* @__PURE__ */ _("p", {
142
+ className: "mt-2 text-xs text-text-secondary",
143
+ children: [
144
+ "Triggered ",
145
+ e.triggerCount,
146
+ "×",
147
+ e.lastTriggeredAt ? ` · last ${r(e.lastTriggeredAt)}` : ""
148
+ ]
149
+ })
150
+ ]
151
+ }, e.id))
152
+ })
153
+ })
154
+ ]
155
+ });
156
+ }
157
+ //#endregion
158
+ export { b as AgentDetailPage };
159
+
160
+ //# sourceMappingURL=AgentDetailPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AgentDetailPage.js","names":[],"sources":["../../../../src/subscriberbot/pages/agents/AgentDetailPage.tsx"],"sourcesContent":["/**\n * Agent detail\n * @module subscriberbot/pages/agents\n *\n * A single AI agent: its kind, posture, last run, and the autonomous policies\n * that bound it. Reads `subAgent(id)`; changes posture via `subSetAgentStatus`.\n */\n\nimport { useState } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { ArrowLeft, Bot, ShieldCheck } from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { EmptyState } from '../../components/EmptyState';\nimport { LoadingView, ErrorView, Section } from '../../components/StateViews';\nimport { useSubscriberBot } from '../../context/SubscriberBotContext';\nimport { useAgent, useSetAgentStatus } from '../../hooks/useSubscriberBotApi';\nimport { formatEnumLabel, formatRelativeTime } from '../../utils/formatters';\nimport type { SubAgentStatus } from '../../types';\n\nconst STATUS_OPTIONS: SubAgentStatus[] = ['DISABLED', 'SUGGEST_ONLY', 'AUTONOMOUS'];\n\nexport function AgentDetailPage() {\n const { id } = useParams<{ id: string }>();\n const { navigateTo } = useSubscriberBot();\n const { data: agent, isLoading, isError, refetch } = useAgent(id);\n const setAgentStatus = useSetAgentStatus();\n const [actionError, setActionError] = useState<string | null>(null);\n\n if (isLoading) {\n return (\n <PageLayout title=\"Agent\">\n <LoadingView label=\"Loading agent…\" />\n </PageLayout>\n );\n }\n\n if (isError) {\n return (\n <PageLayout title=\"Agent\">\n <ErrorView message=\"Could not load this agent.\" onRetry={() => void refetch()} />\n </PageLayout>\n );\n }\n\n if (!agent) {\n return (\n <PageLayout title=\"Agent\">\n <EmptyState\n illustration=\"empty-data\"\n title=\"Agent not found\"\n description=\"It may have been removed, or you may not have access to it.\"\n action={\n <button\n type=\"button\"\n onClick={() => navigateTo('/agents')}\n className=\"rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90\"\n >\n Back to agents\n </button>\n }\n />\n </PageLayout>\n );\n }\n\n const a = agent;\n\n return (\n <PageLayout\n title={a.name}\n description={`${formatEnumLabel(a.kind)} agent`}\n actions={\n <button\n type=\"button\"\n onClick={() => navigateTo('/agents')}\n className=\"inline-flex items-center gap-2 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken\"\n >\n <ArrowLeft className=\"h-4 w-4\" /> Back\n </button>\n }\n >\n <div className=\"flex flex-wrap items-center gap-3\">\n <span className=\"flex size-10 items-center justify-center rounded-lg bg-[var(--color-accent-soft)] text-text-primary\">\n <Bot className=\"h-5 w-5\" />\n </span>\n <StatusBadge status={a.status} />\n <span className=\"text-sm text-text-secondary\">\n {a.lastRunAt ? `Last run ${formatRelativeTime(a.lastRunAt)}` : 'Never run'}\n </span>\n </div>\n\n {a.description && (\n <p className=\"mt-4 max-w-3xl text-sm text-text-secondary\">{a.description}</p>\n )}\n\n {actionError && (\n <div className=\"mt-4 rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle px-4 py-2 text-sm text-status-error-text\">\n {actionError}\n </div>\n )}\n\n {/* Posture control */}\n <div className=\"mt-6 max-w-sm\">\n <label\n htmlFor=\"agent-posture\"\n className=\"mb-1 block text-xs font-medium text-text-secondary\"\n >\n Operating posture\n </label>\n <select\n id=\"agent-posture\"\n value={a.status}\n disabled={setAgentStatus.isPending}\n onChange={(e) => {\n setActionError(null);\n setAgentStatus.mutate(\n { id: a.id, status: e.target.value as SubAgentStatus },\n {\n onError: (err) =>\n setActionError(err instanceof Error ? err.message : 'Could not change posture.'),\n }\n );\n }}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] disabled:opacity-50\"\n >\n {STATUS_OPTIONS.map((s) => (\n <option key={s} value={s}>\n {formatEnumLabel(s)}\n </option>\n ))}\n </select>\n <p className=\"mt-1.5 text-xs text-text-secondary\">\n Disabled never acts; Suggest-only proposes; Autonomous acts within its policies.\n </p>\n </div>\n\n {/* Policies */}\n <Section title=\"Policies\" description=\"The autonomous rules that bound this agent\">\n {!a.policies || a.policies.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n title=\"No policies\"\n description=\"Policies define what this agent may do autonomously, and what it must alert on.\"\n />\n ) : (\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-2\">\n {a.policies.map((policy) => (\n <GlassCard key={policy.id} treatment=\"metric\" className=\"p-4\">\n <div className=\"flex items-start justify-between gap-2\">\n <p className=\"text-sm font-medium text-text-primary\">{policy.name}</p>\n <StatusBadge status={policy.isEnabled ? 'ACTIVE' : 'DISABLED'} />\n </div>\n <p className=\"mt-1 flex items-center gap-1.5 text-xs text-text-secondary\">\n <ShieldCheck className=\"h-3.5 w-3.5\" /> Action: {formatEnumLabel(policy.action)}\n </p>\n {policy.description && (\n <p className=\"mt-2 text-xs text-text-secondary\">{policy.description}</p>\n )}\n <p className=\"mt-2 text-xs text-text-secondary\">\n Triggered {policy.triggerCount}×\n {policy.lastTriggeredAt\n ? ` · last ${formatRelativeTime(policy.lastTriggeredAt)}`\n : ''}\n </p>\n </GlassCard>\n ))}\n </div>\n )}\n </Section>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,140 @@
1
+ import { useSubscriberBot as e } from "../../context/SubscriberBotContext.js";
2
+ import { PageLayout as t } from "../../components/PageLayout.js";
3
+ import { useCreateAgent as n } from "../../hooks/useSubscriberBotApi.js";
4
+ import { useState as r } from "react";
5
+ import { ArrowLeft as i } from "lucide-react";
6
+ import { jsx as a, jsxs as o } from "react/jsx-runtime";
7
+ import { PagePurpose as s } from "@burdenoff/fe-libs/ui";
8
+ //#region src/subscriberbot/pages/agents/AgentNewPage.tsx
9
+ var c = [
10
+ "DISCOVERY",
11
+ "RENEWAL",
12
+ "COST",
13
+ "NEWSLETTER",
14
+ "VENDOR",
15
+ "COMPLIANCE",
16
+ "NEGOTIATION",
17
+ "MIGRATION",
18
+ "CONCIERGE"
19
+ ], l = [
20
+ "SUGGEST_ONLY",
21
+ "DISABLED",
22
+ "AUTONOMOUS"
23
+ ], u = "w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]", d = "mb-1 block text-xs font-medium text-text-secondary";
24
+ function f() {
25
+ let { navigateTo: f } = e(), p = n(), [m, h] = r(""), [g, _] = r("DISCOVERY"), [v, y] = r("SUGGEST_ONLY"), [b, x] = r(""), [S, C] = r(null);
26
+ return /* @__PURE__ */ o(t, {
27
+ title: "New agent",
28
+ description: "Create an AI agent for your recurring portfolio",
29
+ actions: /* @__PURE__ */ o("button", {
30
+ type: "button",
31
+ onClick: () => f("/agents"),
32
+ className: "inline-flex items-center gap-2 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken",
33
+ children: [/* @__PURE__ */ a(i, { className: "h-4 w-4" }), " Back"]
34
+ }),
35
+ children: [/* @__PURE__ */ a(s, {
36
+ className: "mb-6",
37
+ children: "Each agent owns a slice of the recurring-relationship problem. Pick a kind, give it a name, and choose how much autonomy it starts with — you can adjust its posture and policies later."
38
+ }), /* @__PURE__ */ o("form", {
39
+ onSubmit: (e) => {
40
+ if (e.preventDefault(), C(null), !m.trim()) {
41
+ C("An agent name is required.");
42
+ return;
43
+ }
44
+ let t = {
45
+ name: m.trim(),
46
+ kind: g,
47
+ status: v,
48
+ ...b.trim() ? { description: b.trim() } : {}
49
+ };
50
+ p.mutate(t, {
51
+ onSuccess: (e) => f(`/agents/${e.id}`),
52
+ onError: (e) => C(e instanceof Error ? e.message : "Could not create agent.")
53
+ });
54
+ },
55
+ className: "max-w-2xl space-y-5",
56
+ children: [
57
+ S && /* @__PURE__ */ a("div", {
58
+ className: "rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle px-4 py-2 text-sm text-status-error-text",
59
+ children: S
60
+ }),
61
+ /* @__PURE__ */ o("div", { children: [/* @__PURE__ */ o("label", {
62
+ htmlFor: "agent-name",
63
+ className: d,
64
+ children: ["Name ", /* @__PURE__ */ a("span", {
65
+ className: "text-status-error-text",
66
+ children: "*"
67
+ })]
68
+ }), /* @__PURE__ */ a("input", {
69
+ id: "agent-name",
70
+ type: "text",
71
+ value: m,
72
+ onChange: (e) => h(e.target.value),
73
+ placeholder: "e.g. Renewal Watchdog",
74
+ className: u,
75
+ required: !0
76
+ })] }),
77
+ /* @__PURE__ */ o("div", {
78
+ className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
79
+ children: [/* @__PURE__ */ o("div", { children: [/* @__PURE__ */ a("label", {
80
+ htmlFor: "agent-kind",
81
+ className: d,
82
+ children: "Kind"
83
+ }), /* @__PURE__ */ a("select", {
84
+ id: "agent-kind",
85
+ value: g,
86
+ onChange: (e) => _(e.target.value),
87
+ className: u,
88
+ children: c.map((e) => /* @__PURE__ */ a("option", {
89
+ value: e,
90
+ children: e.replace(/_/g, " ")
91
+ }, e))
92
+ })] }), /* @__PURE__ */ o("div", { children: [/* @__PURE__ */ a("label", {
93
+ htmlFor: "agent-status",
94
+ className: d,
95
+ children: "Starting posture"
96
+ }), /* @__PURE__ */ a("select", {
97
+ id: "agent-status",
98
+ value: v,
99
+ onChange: (e) => y(e.target.value),
100
+ className: u,
101
+ children: l.map((e) => /* @__PURE__ */ a("option", {
102
+ value: e,
103
+ children: e.replace(/_/g, " ")
104
+ }, e))
105
+ })] })]
106
+ }),
107
+ /* @__PURE__ */ o("div", { children: [/* @__PURE__ */ a("label", {
108
+ htmlFor: "agent-desc",
109
+ className: d,
110
+ children: "Description"
111
+ }), /* @__PURE__ */ a("textarea", {
112
+ id: "agent-desc",
113
+ value: b,
114
+ onChange: (e) => x(e.target.value),
115
+ rows: 3,
116
+ placeholder: "What should this agent watch for and do?",
117
+ className: u
118
+ })] }),
119
+ /* @__PURE__ */ o("div", {
120
+ className: "flex gap-3",
121
+ children: [/* @__PURE__ */ a("button", {
122
+ type: "submit",
123
+ disabled: p.isPending,
124
+ className: "rounded-lg bg-action-primary-bg px-5 py-2.5 text-sm font-medium text-action-primary-text hover:opacity-90 disabled:opacity-50",
125
+ children: p.isPending ? "Creating…" : "Create agent"
126
+ }), /* @__PURE__ */ a("button", {
127
+ type: "button",
128
+ onClick: () => f("/agents"),
129
+ className: "rounded-lg border border-border-subtle px-5 py-2.5 text-sm font-medium text-text-primary hover:bg-bg-sunken",
130
+ children: "Cancel"
131
+ })]
132
+ })
133
+ ]
134
+ })]
135
+ });
136
+ }
137
+ //#endregion
138
+ export { f as AgentNewPage };
139
+
140
+ //# sourceMappingURL=AgentNewPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AgentNewPage.js","names":[],"sources":["../../../../src/subscriberbot/pages/agents/AgentNewPage.tsx"],"sourcesContent":["/**\n * Create agent\n * @module subscriberbot/pages/agents\n *\n * Spin up a new AI agent. Writes `subCreateAgent`.\n */\n\nimport { useState } from 'react';\nimport { ArrowLeft } from 'lucide-react';\nimport { PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { useSubscriberBot } from '../../context/SubscriberBotContext';\nimport { useCreateAgent } from '../../hooks/useSubscriberBotApi';\nimport type { SubAgentKind, SubAgentStatus, SubCreateAgentInput } from '../../types';\n\nconst KINDS: SubAgentKind[] = [\n 'DISCOVERY',\n 'RENEWAL',\n 'COST',\n 'NEWSLETTER',\n 'VENDOR',\n 'COMPLIANCE',\n 'NEGOTIATION',\n 'MIGRATION',\n 'CONCIERGE',\n];\n\nconst STATUSES: SubAgentStatus[] = ['SUGGEST_ONLY', 'DISABLED', 'AUTONOMOUS'];\n\nconst inputCls =\n 'w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]';\nconst labelCls = 'mb-1 block text-xs font-medium text-text-secondary';\n\nexport function AgentNewPage() {\n const { navigateTo } = useSubscriberBot();\n const create = useCreateAgent();\n\n const [name, setName] = useState('');\n const [kind, setKind] = useState<SubAgentKind>('DISCOVERY');\n const [status, setStatus] = useState<SubAgentStatus>('SUGGEST_ONLY');\n const [description, setDescription] = useState('');\n const [formError, setFormError] = useState<string | null>(null);\n\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n setFormError(null);\n if (!name.trim()) {\n setFormError('An agent name is required.');\n return;\n }\n const input: SubCreateAgentInput = {\n name: name.trim(),\n kind,\n status,\n ...(description.trim() ? { description: description.trim() } : {}),\n };\n create.mutate(input, {\n onSuccess: (agent) => navigateTo(`/agents/${agent.id}`),\n onError: (err) =>\n setFormError(err instanceof Error ? err.message : 'Could not create agent.'),\n });\n };\n\n return (\n <PageLayout\n title=\"New agent\"\n description=\"Create an AI agent for your recurring portfolio\"\n actions={\n <button\n type=\"button\"\n onClick={() => navigateTo('/agents')}\n className=\"inline-flex items-center gap-2 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken\"\n >\n <ArrowLeft className=\"h-4 w-4\" /> Back\n </button>\n }\n >\n <PagePurpose className=\"mb-6\">\n Each agent owns a slice of the recurring-relationship problem. Pick a kind, give it a name,\n and choose how much autonomy it starts with — you can adjust its posture and policies later.\n </PagePurpose>\n\n <form onSubmit={handleSubmit} className=\"max-w-2xl space-y-5\">\n {formError && (\n <div className=\"rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle px-4 py-2 text-sm text-status-error-text\">\n {formError}\n </div>\n )}\n\n <div>\n <label htmlFor=\"agent-name\" className={labelCls}>\n Name <span className=\"text-status-error-text\">*</span>\n </label>\n <input\n id=\"agent-name\"\n type=\"text\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n placeholder=\"e.g. Renewal Watchdog\"\n className={inputCls}\n required\n />\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label htmlFor=\"agent-kind\" className={labelCls}>\n Kind\n </label>\n <select\n id=\"agent-kind\"\n value={kind}\n onChange={(e) => setKind(e.target.value as SubAgentKind)}\n className={inputCls}\n >\n {KINDS.map((k) => (\n <option key={k} value={k}>\n {k.replace(/_/g, ' ')}\n </option>\n ))}\n </select>\n </div>\n <div>\n <label htmlFor=\"agent-status\" className={labelCls}>\n Starting posture\n </label>\n <select\n id=\"agent-status\"\n value={status}\n onChange={(e) => setStatus(e.target.value as SubAgentStatus)}\n className={inputCls}\n >\n {STATUSES.map((s) => (\n <option key={s} value={s}>\n {s.replace(/_/g, ' ')}\n </option>\n ))}\n </select>\n </div>\n </div>\n\n <div>\n <label htmlFor=\"agent-desc\" className={labelCls}>\n Description\n </label>\n <textarea\n id=\"agent-desc\"\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n rows={3}\n placeholder=\"What should this agent watch for and do?\"\n className={inputCls}\n />\n </div>\n\n <div className=\"flex gap-3\">\n <button\n type=\"submit\"\n disabled={create.isPending}\n className=\"rounded-lg bg-action-primary-bg px-5 py-2.5 text-sm font-medium text-action-primary-text hover:opacity-90 disabled:opacity-50\"\n >\n {create.isPending ? 'Creating…' : 'Create agent'}\n </button>\n <button\n type=\"button\"\n onClick={() => navigateTo('/agents')}\n className=\"rounded-lg border border-border-subtle px-5 py-2.5 text-sm font-medium text-text-primary hover:bg-bg-sunken\"\n >\n Cancel\n </button>\n </div>\n </form>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,178 @@
1
+ import { useSubscriberBot as e } from "../../context/SubscriberBotContext.js";
2
+ import { PageLayout as t } from "../../components/PageLayout.js";
3
+ import { formatEnumLabel as n, formatRelativeTime as r } from "../../utils/formatters.js";
4
+ import { StatusBadge as i } from "../../components/StatusBadge.js";
5
+ import { EmptyState as a } from "../../components/EmptyState.js";
6
+ import { ErrorView as o, LoadingView as s } from "../../components/StateViews.js";
7
+ import { useAgents as c, useSetAgentStatus as l } from "../../hooks/useSubscriberBotApi.js";
8
+ import { useState as u } from "react";
9
+ import { Bot as d, Plus as f } from "lucide-react";
10
+ import { jsx as p, jsxs as m } from "react/jsx-runtime";
11
+ import { PagePurpose as h } from "@burdenoff/fe-libs/ui";
12
+ //#region src/subscriberbot/pages/agents/AgentsListPage.tsx
13
+ var g = [
14
+ {
15
+ value: "",
16
+ label: "All kinds"
17
+ },
18
+ {
19
+ value: "DISCOVERY",
20
+ label: "Discovery"
21
+ },
22
+ {
23
+ value: "RENEWAL",
24
+ label: "Renewal"
25
+ },
26
+ {
27
+ value: "COST",
28
+ label: "Cost"
29
+ },
30
+ {
31
+ value: "NEWSLETTER",
32
+ label: "Newsletter"
33
+ },
34
+ {
35
+ value: "VENDOR",
36
+ label: "Vendor"
37
+ },
38
+ {
39
+ value: "COMPLIANCE",
40
+ label: "Compliance"
41
+ },
42
+ {
43
+ value: "NEGOTIATION",
44
+ label: "Negotiation"
45
+ },
46
+ {
47
+ value: "MIGRATION",
48
+ label: "Migration"
49
+ },
50
+ {
51
+ value: "CONCIERGE",
52
+ label: "Concierge"
53
+ }
54
+ ], _ = [
55
+ "DISABLED",
56
+ "SUGGEST_ONLY",
57
+ "AUTONOMOUS"
58
+ ];
59
+ function v() {
60
+ let { navigateTo: v } = e(), [y, b] = u(""), [x, S] = u(""), { data: C, isLoading: w, isError: T, refetch: E } = c({
61
+ kind: y || void 0,
62
+ status: x || void 0
63
+ }), D = l(), O = C ?? [];
64
+ return /* @__PURE__ */ m(t, {
65
+ title: "AI Agents",
66
+ description: "Specialized agents that automate your recurring portfolio",
67
+ actions: /* @__PURE__ */ m("button", {
68
+ type: "button",
69
+ onClick: () => v("/agents/new"),
70
+ className: "inline-flex items-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90",
71
+ children: [/* @__PURE__ */ p(f, { className: "h-4 w-4" }), " New agent"]
72
+ }),
73
+ children: [
74
+ /* @__PURE__ */ p(h, {
75
+ className: "mb-4",
76
+ children: "Agents propose; your policies decide what they may do autonomously. Set each agent's posture — Disabled, Suggest-only, or Autonomous — and open one to review its policies."
77
+ }),
78
+ /* @__PURE__ */ m("div", {
79
+ className: "flex flex-wrap items-center gap-3",
80
+ children: [/* @__PURE__ */ p("select", {
81
+ value: y,
82
+ onChange: (e) => b(e.target.value),
83
+ className: "rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-xs text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]",
84
+ children: g.map((e) => /* @__PURE__ */ p("option", {
85
+ value: e.value,
86
+ children: e.label
87
+ }, e.value))
88
+ }), /* @__PURE__ */ m("select", {
89
+ value: x,
90
+ onChange: (e) => S(e.target.value),
91
+ className: "rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-xs text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]",
92
+ children: [/* @__PURE__ */ p("option", {
93
+ value: "",
94
+ children: "Any posture"
95
+ }), _.map((e) => /* @__PURE__ */ p("option", {
96
+ value: e,
97
+ children: n(e)
98
+ }, e))]
99
+ })]
100
+ }),
101
+ w ? /* @__PURE__ */ p(s, { label: "Loading agents…" }) : T ? /* @__PURE__ */ p(o, {
102
+ message: "Could not load agents.",
103
+ onRetry: () => void E()
104
+ }) : O.length === 0 ? /* @__PURE__ */ p("div", {
105
+ className: "mt-6",
106
+ children: /* @__PURE__ */ p(a, {
107
+ illustration: "empty-data",
108
+ icon: /* @__PURE__ */ p(d, { className: "h-12 w-12" }),
109
+ title: "No agents yet",
110
+ description: "Create your first AI agent to start automating discovery, renewals, or cost optimization.",
111
+ action: /* @__PURE__ */ p("button", {
112
+ type: "button",
113
+ onClick: () => v("/agents/new"),
114
+ className: "rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90",
115
+ children: "New agent"
116
+ })
117
+ })
118
+ }) : /* @__PURE__ */ p("div", {
119
+ className: "mt-6 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3",
120
+ children: O.map((e) => /* @__PURE__ */ m("div", {
121
+ className: "flex flex-col rounded-lg border border-border-subtle bg-bg-surface p-4",
122
+ children: [/* @__PURE__ */ m("button", {
123
+ type: "button",
124
+ onClick: () => v(`/agents/${e.id}`),
125
+ className: "text-left",
126
+ children: [
127
+ /* @__PURE__ */ m("div", {
128
+ className: "flex items-start justify-between gap-2",
129
+ children: [/* @__PURE__ */ p("span", {
130
+ className: "flex size-9 items-center justify-center rounded-lg bg-[var(--color-accent-soft)] text-text-primary",
131
+ children: /* @__PURE__ */ p(d, { className: "h-4 w-4" })
132
+ }), /* @__PURE__ */ p(i, { status: e.status })]
133
+ }),
134
+ /* @__PURE__ */ p("p", {
135
+ className: "mt-3 truncate text-sm font-semibold text-text-primary",
136
+ children: e.name
137
+ }),
138
+ /* @__PURE__ */ m("p", {
139
+ className: "text-xs text-text-secondary",
140
+ children: [n(e.kind), " agent"]
141
+ }),
142
+ e.description && /* @__PURE__ */ p("p", {
143
+ className: "mt-2 line-clamp-2 text-xs text-text-secondary",
144
+ children: e.description
145
+ }),
146
+ /* @__PURE__ */ p("p", {
147
+ className: "mt-2 text-xs text-text-secondary",
148
+ children: e.lastRunAt ? `Last run ${r(e.lastRunAt)}` : "Never run"
149
+ })
150
+ ]
151
+ }), /* @__PURE__ */ m("div", {
152
+ className: "mt-3 border-t border-border-subtle pt-3",
153
+ children: [/* @__PURE__ */ p("label", {
154
+ className: "mb-1 block text-[10px] font-medium uppercase tracking-wide text-text-secondary",
155
+ children: "Posture"
156
+ }), /* @__PURE__ */ p("select", {
157
+ value: e.status,
158
+ disabled: D.isPending,
159
+ onChange: (t) => D.mutate({
160
+ id: e.id,
161
+ status: t.target.value
162
+ }),
163
+ className: "w-full rounded-lg border border-border-subtle bg-bg-surface px-2 py-1.5 text-xs text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] disabled:opacity-50",
164
+ children: _.map((e) => /* @__PURE__ */ p("option", {
165
+ value: e,
166
+ children: n(e)
167
+ }, e))
168
+ })]
169
+ })]
170
+ }, e.id))
171
+ })
172
+ ]
173
+ });
174
+ }
175
+ //#endregion
176
+ export { v as AgentsListPage };
177
+
178
+ //# sourceMappingURL=AgentsListPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AgentsListPage.js","names":[],"sources":["../../../../src/subscriberbot/pages/agents/AgentsListPage.tsx"],"sourcesContent":["/**\n * AI Agents list\n * @module subscriberbot/pages/agents\n *\n * The AI Agents Framework — specialized agents (Discovery, Renewal, Cost,\n * Newsletter, Vendor, Compliance, Negotiation, Migration, Concierge) that each\n * own a slice of the recurring-relationship problem. Filter by kind / posture.\n * Reads `subListAgents`; sets posture inline via `subSetAgentStatus`.\n */\n\nimport { useState } from 'react';\nimport { Plus, Bot } from 'lucide-react';\nimport { PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { EmptyState } from '../../components/EmptyState';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { useSubscriberBot } from '../../context/SubscriberBotContext';\nimport { useAgents, useSetAgentStatus } from '../../hooks/useSubscriberBotApi';\nimport { formatEnumLabel, formatRelativeTime } from '../../utils/formatters';\nimport type { SubAgentKind, SubAgentStatus } from '../../types';\n\nconst KIND_OPTIONS: Array<{ value: '' | SubAgentKind; label: string }> = [\n { value: '', label: 'All kinds' },\n { value: 'DISCOVERY', label: 'Discovery' },\n { value: 'RENEWAL', label: 'Renewal' },\n { value: 'COST', label: 'Cost' },\n { value: 'NEWSLETTER', label: 'Newsletter' },\n { value: 'VENDOR', label: 'Vendor' },\n { value: 'COMPLIANCE', label: 'Compliance' },\n { value: 'NEGOTIATION', label: 'Negotiation' },\n { value: 'MIGRATION', label: 'Migration' },\n { value: 'CONCIERGE', label: 'Concierge' },\n];\n\nconst STATUS_OPTIONS: SubAgentStatus[] = ['DISABLED', 'SUGGEST_ONLY', 'AUTONOMOUS'];\n\nexport function AgentsListPage() {\n const { navigateTo } = useSubscriberBot();\n const [kind, setKind] = useState<'' | SubAgentKind>('');\n const [status, setStatus] = useState<'' | SubAgentStatus>('');\n\n const { data, isLoading, isError, refetch } = useAgents({\n kind: kind || undefined,\n status: status || undefined,\n });\n const setAgentStatus = useSetAgentStatus();\n\n const agents = data ?? [];\n\n return (\n <PageLayout\n title=\"AI Agents\"\n description=\"Specialized agents that automate your recurring portfolio\"\n actions={\n <button\n type=\"button\"\n onClick={() => navigateTo('/agents/new')}\n className=\"inline-flex items-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90\"\n >\n <Plus className=\"h-4 w-4\" /> New agent\n </button>\n }\n >\n <PagePurpose className=\"mb-4\">\n Agents propose; your policies decide what they may do autonomously. Set each agent's posture\n — Disabled, Suggest-only, or Autonomous — and open one to review its policies.\n </PagePurpose>\n\n <div className=\"flex flex-wrap items-center gap-3\">\n <select\n value={kind}\n onChange={(e) => setKind(e.target.value as '' | SubAgentKind)}\n className=\"rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-xs text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n {KIND_OPTIONS.map((o) => (\n <option key={o.value} value={o.value}>\n {o.label}\n </option>\n ))}\n </select>\n <select\n value={status}\n onChange={(e) => setStatus(e.target.value as '' | SubAgentStatus)}\n className=\"rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-xs text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <option value=\"\">Any posture</option>\n {STATUS_OPTIONS.map((s) => (\n <option key={s} value={s}>\n {formatEnumLabel(s)}\n </option>\n ))}\n </select>\n </div>\n\n {isLoading ? (\n <LoadingView label=\"Loading agents…\" />\n ) : isError ? (\n <ErrorView message=\"Could not load agents.\" onRetry={() => void refetch()} />\n ) : agents.length === 0 ? (\n <div className=\"mt-6\">\n <EmptyState\n illustration=\"empty-data\"\n icon={<Bot className=\"h-12 w-12\" />}\n title=\"No agents yet\"\n description=\"Create your first AI agent to start automating discovery, renewals, or cost optimization.\"\n action={\n <button\n type=\"button\"\n onClick={() => navigateTo('/agents/new')}\n className=\"rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90\"\n >\n New agent\n </button>\n }\n />\n </div>\n ) : (\n <div className=\"mt-6 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {agents.map((a) => (\n <div\n key={a.id}\n className=\"flex flex-col rounded-lg border border-border-subtle bg-bg-surface p-4\"\n >\n <button\n type=\"button\"\n onClick={() => navigateTo(`/agents/${a.id}`)}\n className=\"text-left\"\n >\n <div className=\"flex items-start justify-between gap-2\">\n <span className=\"flex size-9 items-center justify-center rounded-lg bg-[var(--color-accent-soft)] text-text-primary\">\n <Bot className=\"h-4 w-4\" />\n </span>\n <StatusBadge status={a.status} />\n </div>\n <p className=\"mt-3 truncate text-sm font-semibold text-text-primary\">{a.name}</p>\n <p className=\"text-xs text-text-secondary\">{formatEnumLabel(a.kind)} agent</p>\n {a.description && (\n <p className=\"mt-2 line-clamp-2 text-xs text-text-secondary\">{a.description}</p>\n )}\n <p className=\"mt-2 text-xs text-text-secondary\">\n {a.lastRunAt ? `Last run ${formatRelativeTime(a.lastRunAt)}` : 'Never run'}\n </p>\n </button>\n <div className=\"mt-3 border-t border-border-subtle pt-3\">\n <label className=\"mb-1 block text-[10px] font-medium uppercase tracking-wide text-text-secondary\">\n Posture\n </label>\n <select\n value={a.status}\n disabled={setAgentStatus.isPending}\n onChange={(e) =>\n setAgentStatus.mutate({ id: a.id, status: e.target.value as SubAgentStatus })\n }\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface px-2 py-1.5 text-xs text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] disabled:opacity-50\"\n >\n {STATUS_OPTIONS.map((s) => (\n <option key={s} value={s}>\n {formatEnumLabel(s)}\n </option>\n ))}\n </select>\n </div>\n </div>\n ))}\n </div>\n )}\n </PageLayout>\n );\n}\n"],"mappings":"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"}