@burdenoff/microfe-subscriberbot 2026.706.2 → 2026.710.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 (140) hide show
  1. package/dist/generated/global-operations.d.ts +2 -0
  2. package/dist/generated/global-operations.d.ts.map +1 -0
  3. package/dist/generated/global-types.d.ts +23527 -0
  4. package/dist/generated/global-types.d.ts.map +1 -0
  5. package/dist/generated/wspace-operations.d.ts +2 -0
  6. package/dist/generated/wspace-operations.d.ts.map +1 -0
  7. package/dist/generated/wspace-types.d.ts +57851 -0
  8. package/dist/generated/wspace-types.d.ts.map +1 -0
  9. package/dist/index.d.ts +6 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +2 -1
  12. package/dist/subscriberbot/SubscriberBotRoot.d.ts +5 -0
  13. package/dist/subscriberbot/SubscriberBotRoot.d.ts.map +1 -0
  14. package/dist/subscriberbot/SubscriberBotRoot.js +56 -40
  15. package/dist/subscriberbot/SubscriberBotRoot.js.map +1 -1
  16. package/dist/subscriberbot/SubscriberBotRoutes.d.ts +4 -0
  17. package/dist/subscriberbot/SubscriberBotRoutes.d.ts.map +1 -0
  18. package/dist/subscriberbot/SubscriberBotRoutes.js +14 -6
  19. package/dist/subscriberbot/SubscriberBotRoutes.js.map +1 -1
  20. package/dist/subscriberbot/components/EmptyState.d.ts +18 -0
  21. package/dist/subscriberbot/components/EmptyState.d.ts.map +1 -0
  22. package/dist/subscriberbot/components/MetricsCard.d.ts +16 -0
  23. package/dist/subscriberbot/components/MetricsCard.d.ts.map +1 -0
  24. package/dist/subscriberbot/components/Modal.d.ts +13 -0
  25. package/dist/subscriberbot/components/Modal.d.ts.map +1 -0
  26. package/dist/subscriberbot/components/PageLayout.d.ts +23 -0
  27. package/dist/subscriberbot/components/PageLayout.d.ts.map +1 -0
  28. package/dist/subscriberbot/components/StateViews.d.ts +24 -0
  29. package/dist/subscriberbot/components/StateViews.d.ts.map +1 -0
  30. package/dist/subscriberbot/components/StatusBadge.d.ts +9 -0
  31. package/dist/subscriberbot/components/StatusBadge.d.ts.map +1 -0
  32. package/dist/subscriberbot/components/index.d.ts +13 -0
  33. package/dist/subscriberbot/components/index.d.ts.map +1 -0
  34. package/dist/subscriberbot/components/index.js +7 -0
  35. package/dist/subscriberbot/components/viz.d.ts +58 -0
  36. package/dist/subscriberbot/components/viz.d.ts.map +1 -0
  37. package/dist/subscriberbot/components/viz.js +196 -0
  38. package/dist/subscriberbot/components/viz.js.map +1 -0
  39. package/dist/subscriberbot/config/assistantUsecases.d.ts +13 -0
  40. package/dist/subscriberbot/config/assistantUsecases.d.ts.map +1 -0
  41. package/dist/subscriberbot/context/SubscriberBotContext.d.ts +16 -0
  42. package/dist/subscriberbot/context/SubscriberBotContext.d.ts.map +1 -0
  43. package/dist/subscriberbot/context/index.d.ts +6 -0
  44. package/dist/subscriberbot/context/index.d.ts.map +1 -0
  45. package/dist/subscriberbot/hooks/index.d.ts +7 -0
  46. package/dist/subscriberbot/hooks/index.d.ts.map +1 -0
  47. package/dist/subscriberbot/hooks/useSubscriberBotApi.d.ts +105 -0
  48. package/dist/subscriberbot/hooks/useSubscriberBotApi.d.ts.map +1 -0
  49. package/dist/subscriberbot/hooks/useSubscriberBotApi.js +38 -30
  50. package/dist/subscriberbot/hooks/useSubscriberBotApi.js.map +1 -1
  51. package/dist/subscriberbot/index.d.ts +12 -0
  52. package/dist/subscriberbot/index.d.ts.map +1 -0
  53. package/dist/subscriberbot/index.js +1 -0
  54. package/dist/subscriberbot/pages/AssetVaultPage.d.ts +4 -0
  55. package/dist/subscriberbot/pages/AssetVaultPage.d.ts.map +1 -0
  56. package/dist/subscriberbot/pages/AssetVaultPage.js +182 -0
  57. package/dist/subscriberbot/pages/AssetVaultPage.js.map +1 -0
  58. package/dist/subscriberbot/pages/DashboardPage.d.ts +12 -0
  59. package/dist/subscriberbot/pages/DashboardPage.d.ts.map +1 -0
  60. package/dist/subscriberbot/pages/DashboardPage.js +272 -199
  61. package/dist/subscriberbot/pages/DashboardPage.js.map +1 -1
  62. package/dist/subscriberbot/pages/InboxPage.d.ts +12 -0
  63. package/dist/subscriberbot/pages/InboxPage.d.ts.map +1 -0
  64. package/dist/subscriberbot/pages/InboxPage.js +517 -234
  65. package/dist/subscriberbot/pages/InboxPage.js.map +1 -1
  66. package/dist/subscriberbot/pages/InsightsPage.d.ts +4 -0
  67. package/dist/subscriberbot/pages/InsightsPage.d.ts.map +1 -0
  68. package/dist/subscriberbot/pages/InsightsPage.js +220 -0
  69. package/dist/subscriberbot/pages/InsightsPage.js.map +1 -0
  70. package/dist/subscriberbot/pages/InvoicesPage.d.ts +13 -0
  71. package/dist/subscriberbot/pages/InvoicesPage.d.ts.map +1 -0
  72. package/dist/subscriberbot/pages/InvoicesPage.js +325 -237
  73. package/dist/subscriberbot/pages/InvoicesPage.js.map +1 -1
  74. package/dist/subscriberbot/pages/WorkflowsPage.d.ts +15 -0
  75. package/dist/subscriberbot/pages/WorkflowsPage.d.ts.map +1 -0
  76. package/dist/subscriberbot/pages/WorkflowsPage.js +301 -112
  77. package/dist/subscriberbot/pages/WorkflowsPage.js.map +1 -1
  78. package/dist/subscriberbot/pages/agents/AgentDetailPage.d.ts +11 -0
  79. package/dist/subscriberbot/pages/agents/AgentDetailPage.d.ts.map +1 -0
  80. package/dist/subscriberbot/pages/agents/AgentDetailPage.js +311 -165
  81. package/dist/subscriberbot/pages/agents/AgentDetailPage.js.map +1 -1
  82. package/dist/subscriberbot/pages/agents/AgentNewPage.d.ts +8 -0
  83. package/dist/subscriberbot/pages/agents/AgentNewPage.d.ts.map +1 -0
  84. package/dist/subscriberbot/pages/agents/AgentsListPage.d.ts +11 -0
  85. package/dist/subscriberbot/pages/agents/AgentsListPage.d.ts.map +1 -0
  86. package/dist/subscriberbot/pages/agents/AgentsListPage.js +183 -93
  87. package/dist/subscriberbot/pages/agents/AgentsListPage.js.map +1 -1
  88. package/dist/subscriberbot/pages/providers/ProviderDetailPage.d.ts +10 -0
  89. package/dist/subscriberbot/pages/providers/ProviderDetailPage.d.ts.map +1 -0
  90. package/dist/subscriberbot/pages/providers/ProviderDetailPage.js +426 -293
  91. package/dist/subscriberbot/pages/providers/ProviderDetailPage.js.map +1 -1
  92. package/dist/subscriberbot/pages/providers/ProviderNewPage.d.ts +10 -0
  93. package/dist/subscriberbot/pages/providers/ProviderNewPage.d.ts.map +1 -0
  94. package/dist/subscriberbot/pages/providers/ProviderNewPage.js +217 -153
  95. package/dist/subscriberbot/pages/providers/ProviderNewPage.js.map +1 -1
  96. package/dist/subscriberbot/pages/providers/ProvidersListPage.d.ts +12 -0
  97. package/dist/subscriberbot/pages/providers/ProvidersListPage.d.ts.map +1 -0
  98. package/dist/subscriberbot/pages/providers/ProvidersListPage.js +215 -112
  99. package/dist/subscriberbot/pages/providers/ProvidersListPage.js.map +1 -1
  100. package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.d.ts +13 -0
  101. package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.d.ts.map +1 -0
  102. package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.js +542 -428
  103. package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.js.map +1 -1
  104. package/dist/subscriberbot/pages/relationships/RelationshipNewPage.d.ts +10 -0
  105. package/dist/subscriberbot/pages/relationships/RelationshipNewPage.d.ts.map +1 -0
  106. package/dist/subscriberbot/pages/relationships/RelationshipNewPage.js +242 -192
  107. package/dist/subscriberbot/pages/relationships/RelationshipNewPage.js.map +1 -1
  108. package/dist/subscriberbot/pages/relationships/RelationshipsListPage.d.ts +10 -0
  109. package/dist/subscriberbot/pages/relationships/RelationshipsListPage.d.ts.map +1 -0
  110. package/dist/subscriberbot/pages/relationships/RelationshipsListPage.js +174 -133
  111. package/dist/subscriberbot/pages/relationships/RelationshipsListPage.js.map +1 -1
  112. package/dist/subscriberbot/services/assistantApi.d.ts +66 -0
  113. package/dist/subscriberbot/services/assistantApi.d.ts.map +1 -0
  114. package/dist/subscriberbot/services/assistantApi.js +260 -0
  115. package/dist/subscriberbot/services/assistantApi.js.map +1 -0
  116. package/dist/subscriberbot/services/createSandboxAssistantTransport.d.ts +13 -0
  117. package/dist/subscriberbot/services/createSandboxAssistantTransport.d.ts.map +1 -0
  118. package/dist/subscriberbot/services/createSandboxAssistantTransport.js +120 -0
  119. package/dist/subscriberbot/services/createSandboxAssistantTransport.js.map +1 -0
  120. package/dist/subscriberbot/store/index.d.ts +6 -0
  121. package/dist/subscriberbot/store/index.d.ts.map +1 -0
  122. package/dist/subscriberbot/store/subscriberbotStore.d.ts +60 -0
  123. package/dist/subscriberbot/store/subscriberbotStore.d.ts.map +1 -0
  124. package/dist/subscriberbot/types/assistant.d.ts +57 -0
  125. package/dist/subscriberbot/types/assistant.d.ts.map +1 -0
  126. package/dist/subscriberbot/types/index.d.ts +465 -0
  127. package/dist/subscriberbot/types/index.d.ts.map +1 -0
  128. package/dist/subscriberbot/utils/cn.d.ts +4 -0
  129. package/dist/subscriberbot/utils/cn.d.ts.map +1 -0
  130. package/dist/subscriberbot/utils/formatters.d.ts +53 -0
  131. package/dist/subscriberbot/utils/formatters.d.ts.map +1 -0
  132. package/dist/subscriberbot/utils/index.d.ts +8 -0
  133. package/dist/subscriberbot/utils/index.d.ts.map +1 -0
  134. package/dist/subscriberbot/utils/navigation.d.ts +20 -0
  135. package/dist/subscriberbot/utils/navigation.d.ts.map +1 -0
  136. package/dist/subscriberbot/utils/pageContext.d.ts +21 -0
  137. package/dist/subscriberbot/utils/pageContext.d.ts.map +1 -0
  138. package/dist/subscriberbot/utils/pageContext.js +47 -0
  139. package/dist/subscriberbot/utils/pageContext.js.map +1 -0
  140. package/package.json +5 -1
@@ -1,16 +1,18 @@
1
1
  import { PageLayout as e } from "../components/PageLayout.js";
2
- import { formatRelativeTime as t } from "../utils/formatters.js";
3
- import { StatusBadge as n } from "../components/StatusBadge.js";
4
- import { EmptyState as r } from "../components/EmptyState.js";
5
- import { ErrorView as i, LoadingView as a } from "../components/StateViews.js";
6
- import { useActivateWorkflow as o, useCreateWorkflow as s, useWorkflows as c } from "../hooks/useSubscriberBotApi.js";
7
- import { Modal as l } from "../components/Modal.js";
8
- import { useState as u } from "react";
9
- import { Play as d, Plus as f, Workflow as p } from "lucide-react";
10
- import { jsx as m, jsxs as h } from "react/jsx-runtime";
11
- import { PagePurpose as g } from "@burdenoff/fe-libs/ui";
2
+ import { MetricsCard as t } from "../components/MetricsCard.js";
3
+ import { formatRelativeTime as n } from "../utils/formatters.js";
4
+ import { StatusBadge as r } from "../components/StatusBadge.js";
5
+ import { EmptyState as i } from "../components/EmptyState.js";
6
+ import { Modal as a } from "../components/Modal.js";
7
+ import { ErrorView as o, LoadingView as s } from "../components/StateViews.js";
8
+ import "../components/index.js";
9
+ import { useActivateWorkflow as c, useCreateWorkflow as l, useWorkflows as u } from "../hooks/useSubscriberBotApi.js";
10
+ import { useState as d } from "react";
11
+ import { ArrowRight as f, CheckCircle2 as p, Clock as m, Play as h, Plus as g, Sparkles as _, Workflow as v, X as y, Zap as b } from "lucide-react";
12
+ import { Fragment as x, jsx as S, jsxs as C } from "react/jsx-runtime";
13
+ import { GlassCard as w, PagePurpose as T } from "@burdenoff/fe-libs/ui";
12
14
  //#region src/subscriberbot/pages/WorkflowsPage.tsx
13
- var _ = [
15
+ var E = [
14
16
  {
15
17
  value: "",
16
18
  label: "All statuses"
@@ -31,183 +33,370 @@ var _ = [
31
33
  value: "ARCHIVED",
32
34
  label: "Archived"
33
35
  }
34
- ], v = "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)]", y = "mb-1 block text-xs font-medium text-text-secondary";
35
- function b() {
36
- let [b, x] = u(""), [S, C] = u(!1), { data: w, isLoading: T, isError: E, refetch: D } = c(b || void 0), O = s(), k = o(), [A, j] = u(""), [M, N] = u(""), [P, F] = u(""), [I, L] = u(null), R = w ?? [], z = () => {
37
- j(""), N(""), F(""), L(null);
38
- }, B = () => {
39
- C(!1), z();
36
+ ], D = "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)]", O = "mb-1 block text-xs font-medium text-text-secondary";
37
+ function k({ icon: e, kicker: t, title: n, sub: r, accent: i }) {
38
+ return /* @__PURE__ */ C("div", {
39
+ className: "w-48 shrink-0 overflow-hidden rounded-xl border border-border-subtle bg-bg-surface shadow-sm",
40
+ children: [/* @__PURE__ */ S("div", {
41
+ className: `h-1 w-full ${i === "done" ? "bg-status-success-text" : i === "run" ? "bg-status-warning-text" : "bg-[var(--color-accent-indigo)]"}`,
42
+ "aria-hidden": !0
43
+ }), /* @__PURE__ */ C("div", {
44
+ className: "p-3",
45
+ children: [
46
+ /* @__PURE__ */ S("span", {
47
+ className: "flex size-8 items-center justify-center rounded-lg bg-[var(--color-accent-soft)] text-text-primary",
48
+ children: e
49
+ }),
50
+ /* @__PURE__ */ S("p", {
51
+ className: "mt-2 text-[10px] font-medium uppercase tracking-wide text-text-secondary",
52
+ children: t
53
+ }),
54
+ /* @__PURE__ */ S("p", {
55
+ className: "truncate text-sm font-semibold text-text-primary",
56
+ title: n,
57
+ children: n
58
+ }),
59
+ r && /* @__PURE__ */ S("p", {
60
+ className: "mt-0.5 truncate text-xs text-text-secondary",
61
+ children: r
62
+ })
63
+ ]
64
+ })]
65
+ });
66
+ }
67
+ function A({ workflow: e, onClose: t, onActivate: i, activating: a }) {
68
+ let o = /* @__PURE__ */ C("div", {
69
+ className: "flex shrink-0 items-center px-1 text-text-secondary",
70
+ "aria-hidden": !0,
71
+ children: [/* @__PURE__ */ S("span", { className: "h-px w-4 bg-border-seam sm:w-6" }), /* @__PURE__ */ S(f, { className: "h-4 w-4" })]
72
+ });
73
+ return /* @__PURE__ */ C(w, {
74
+ treatment: "glass",
75
+ glow: !0,
76
+ className: "mt-6 p-5",
77
+ children: [
78
+ /* @__PURE__ */ C("div", {
79
+ className: "flex flex-wrap items-start justify-between gap-3",
80
+ children: [/* @__PURE__ */ C("div", {
81
+ className: "min-w-0",
82
+ children: [/* @__PURE__ */ C("div", {
83
+ className: "flex flex-wrap items-center gap-2",
84
+ children: [/* @__PURE__ */ S("p", {
85
+ className: "text-base font-semibold text-text-primary",
86
+ children: e.name
87
+ }), /* @__PURE__ */ S(r, { status: e.status })]
88
+ }), /* @__PURE__ */ C("p", {
89
+ className: "mt-1 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-text-secondary",
90
+ children: [/* @__PURE__ */ C("span", {
91
+ className: "tabular-nums",
92
+ children: [
93
+ "Ran ",
94
+ e.runCount,
95
+ "×"
96
+ ]
97
+ }), e.lastRunAt && /* @__PURE__ */ C("span", {
98
+ className: "inline-flex items-center gap-1",
99
+ children: [
100
+ /* @__PURE__ */ S(m, {
101
+ className: "h-3 w-3",
102
+ "aria-hidden": !0
103
+ }),
104
+ " last",
105
+ " ",
106
+ n(e.lastRunAt)
107
+ ]
108
+ })]
109
+ })]
110
+ }), /* @__PURE__ */ S("button", {
111
+ type: "button",
112
+ onClick: t,
113
+ "aria-label": "Close flow",
114
+ className: "rounded-lg border border-border-subtle p-1.5 text-text-secondary hover:bg-bg-sunken hover:text-text-primary",
115
+ children: /* @__PURE__ */ S(y, { className: "h-4 w-4" })
116
+ })]
117
+ }),
118
+ e.description && /* @__PURE__ */ S("p", {
119
+ className: "mt-2 max-w-3xl text-sm text-text-secondary",
120
+ children: e.description
121
+ }),
122
+ /* @__PURE__ */ S("div", {
123
+ className: "mt-4 overflow-x-auto pb-2",
124
+ children: /* @__PURE__ */ C("div", {
125
+ className: "flex min-w-max items-stretch",
126
+ children: [
127
+ /* @__PURE__ */ S(k, {
128
+ accent: "trigger",
129
+ kicker: "When",
130
+ icon: /* @__PURE__ */ S(b, { className: "h-4 w-4" }),
131
+ title: e.triggerEvent,
132
+ sub: "Trigger event"
133
+ }),
134
+ o,
135
+ /* @__PURE__ */ S(k, {
136
+ accent: "run",
137
+ kicker: "Run",
138
+ icon: /* @__PURE__ */ S(_, { className: "h-4 w-4" }),
139
+ title: e.name,
140
+ sub: "Automation"
141
+ }),
142
+ o,
143
+ /* @__PURE__ */ S(k, {
144
+ accent: "done",
145
+ kicker: "Then",
146
+ icon: /* @__PURE__ */ S(p, { className: "h-4 w-4" }),
147
+ title: e.status === "ACTIVE" ? "Live" : "Awaiting activation",
148
+ sub: `Status: ${e.status.charAt(0) + e.status.slice(1).toLowerCase()}`
149
+ })
150
+ ]
151
+ })
152
+ }),
153
+ e.status !== "ACTIVE" && /* @__PURE__ */ S("div", {
154
+ className: "mt-3 flex justify-end",
155
+ children: /* @__PURE__ */ C("button", {
156
+ type: "button",
157
+ disabled: a,
158
+ onClick: i,
159
+ className: "inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90 disabled:opacity-50",
160
+ children: [
161
+ /* @__PURE__ */ S(h, { className: "h-4 w-4" }),
162
+ " ",
163
+ a ? "Activating…" : "Activate workflow"
164
+ ]
165
+ })
166
+ })
167
+ ]
168
+ });
169
+ }
170
+ function j() {
171
+ let [f, p] = d(""), [m, _] = d(!1), [y, k] = d(null), { data: j, isLoading: M, isError: N, refetch: P } = u(f || void 0), F = l(), I = c(), [L, R] = d(""), [z, B] = d(""), [V, H] = d(""), [U, W] = d(null), G = j ?? [], K = G.find((e) => e.id === y) ?? null, q = G.filter((e) => e.status === "ACTIVE").length, J = G.reduce((e, t) => e + (t.runCount || 0), 0), Y = () => {
172
+ R(""), B(""), H(""), W(null);
173
+ }, X = () => {
174
+ _(!1), Y();
40
175
  };
41
- return /* @__PURE__ */ h(e, {
176
+ return /* @__PURE__ */ C(e, {
42
177
  title: "Workflows",
43
178
  description: "Event-driven automation across your portfolio",
44
- actions: /* @__PURE__ */ h("button", {
179
+ actions: /* @__PURE__ */ C("button", {
45
180
  type: "button",
46
- onClick: () => C(!0),
181
+ onClick: () => _(!0),
47
182
  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",
48
- children: [/* @__PURE__ */ m(f, { className: "h-4 w-4" }), " New workflow"]
183
+ children: [/* @__PURE__ */ S(g, { className: "h-4 w-4" }), " New workflow"]
49
184
  }),
50
185
  children: [
51
- /* @__PURE__ */ m(g, {
186
+ /* @__PURE__ */ S(T, {
52
187
  className: "mb-4",
53
188
  children: "Workflows react to domain events — a new invoice, a detected renewal, a cancelled relationship — and run multi-step automations. Draft a workflow, then activate it when you're ready."
54
189
  }),
55
- /* @__PURE__ */ m("div", {
190
+ /* @__PURE__ */ S("div", {
56
191
  className: "flex flex-wrap items-center gap-3",
57
- children: /* @__PURE__ */ m("select", {
192
+ children: /* @__PURE__ */ S("select", {
58
193
  "aria-label": "Filter by status",
59
- value: b,
60
- onChange: (e) => x(e.target.value),
194
+ value: f,
195
+ onChange: (e) => p(e.target.value),
61
196
  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)]",
62
- children: _.map((e) => /* @__PURE__ */ m("option", {
197
+ children: E.map((e) => /* @__PURE__ */ S("option", {
63
198
  value: e.value,
64
199
  children: e.label
65
200
  }, e.value))
66
201
  })
67
202
  }),
68
- T ? /* @__PURE__ */ m(a, { label: "Loading workflows…" }) : E ? /* @__PURE__ */ m(i, {
203
+ M ? /* @__PURE__ */ S(s, { label: "Loading workflows…" }) : N ? /* @__PURE__ */ S(o, {
69
204
  message: "Could not load workflows.",
70
- onRetry: () => void D()
71
- }) : R.length === 0 ? /* @__PURE__ */ m("div", {
205
+ onRetry: () => void P()
206
+ }) : G.length === 0 ? /* @__PURE__ */ S("div", {
72
207
  className: "mt-6",
73
- children: /* @__PURE__ */ m(r, {
208
+ children: /* @__PURE__ */ S(i, {
74
209
  illustration: "empty-data",
75
- icon: /* @__PURE__ */ m(p, { className: "h-12 w-12" }),
210
+ icon: /* @__PURE__ */ S(v, { className: "h-12 w-12" }),
76
211
  title: "No workflows yet",
77
212
  description: "Create your first event-driven workflow to automate your recurring portfolio.",
78
- action: /* @__PURE__ */ m("button", {
213
+ action: /* @__PURE__ */ S("button", {
79
214
  type: "button",
80
- onClick: () => C(!0),
215
+ onClick: () => _(!0),
81
216
  className: "rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90",
82
217
  children: "New workflow"
83
218
  })
84
219
  })
85
- }) : /* @__PURE__ */ m("div", {
86
- className: "mt-6 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3",
87
- children: R.map((e) => /* @__PURE__ */ h("div", {
88
- className: "flex flex-col rounded-lg border border-border-subtle bg-bg-surface p-4",
220
+ }) : /* @__PURE__ */ C(x, { children: [
221
+ /* @__PURE__ */ C("div", {
222
+ className: "mt-6 grid grid-cols-1 gap-4 sm:grid-cols-3",
89
223
  children: [
90
- /* @__PURE__ */ h("div", {
91
- className: "flex items-start justify-between gap-2",
92
- children: [/* @__PURE__ */ m("span", {
93
- className: "flex size-9 items-center justify-center rounded-lg bg-[var(--color-accent-soft)] text-text-primary",
94
- children: /* @__PURE__ */ m(p, { className: "h-4 w-4" })
95
- }), /* @__PURE__ */ m(n, { status: e.status })]
96
- }),
97
- /* @__PURE__ */ m("p", {
98
- className: "mt-3 truncate text-sm font-semibold text-text-primary",
99
- children: e.name
224
+ /* @__PURE__ */ S(t, {
225
+ icon: /* @__PURE__ */ S(v, { className: "h-5 w-5" }),
226
+ value: G.length,
227
+ label: "Workflows"
100
228
  }),
101
- /* @__PURE__ */ h("p", {
102
- className: "truncate text-xs text-text-secondary",
103
- children: ["on ", e.triggerEvent]
229
+ /* @__PURE__ */ S(t, {
230
+ icon: /* @__PURE__ */ S(b, { className: "h-5 w-5" }),
231
+ value: q,
232
+ label: "Active"
104
233
  }),
105
- e.description && /* @__PURE__ */ m("p", {
106
- className: "mt-2 line-clamp-2 text-xs text-text-secondary",
107
- children: e.description
108
- }),
109
- /* @__PURE__ */ h("p", {
110
- className: "mt-2 text-xs text-text-secondary",
111
- children: [
112
- "Ran ",
113
- e.runCount,
114
- "×",
115
- e.lastRunAt ? ` · last ${t(e.lastRunAt)}` : ""
116
- ]
117
- }),
118
- e.status !== "ACTIVE" && /* @__PURE__ */ h("button", {
119
- type: "button",
120
- disabled: k.isPending,
121
- onClick: () => k.mutate(e.id),
122
- className: "mt-3 inline-flex items-center justify-center gap-1.5 rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-text-primary hover:bg-bg-sunken disabled:opacity-50",
123
- children: [/* @__PURE__ */ m(d, { className: "h-3.5 w-3.5" }), " Activate"]
234
+ /* @__PURE__ */ S(t, {
235
+ icon: /* @__PURE__ */ S(h, { className: "h-5 w-5" }),
236
+ value: J,
237
+ label: "Total runs"
124
238
  })
125
239
  ]
126
- }, e.id))
127
- }),
128
- S && /* @__PURE__ */ m(l, {
240
+ }),
241
+ K && /* @__PURE__ */ S(A, {
242
+ workflow: K,
243
+ onClose: () => k(null),
244
+ onActivate: () => I.mutate(K.id),
245
+ activating: I.isPending
246
+ }),
247
+ /* @__PURE__ */ S("div", {
248
+ className: "mt-6 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3",
249
+ children: G.map((e) => {
250
+ let t = e.id === y;
251
+ return /* @__PURE__ */ C(w, {
252
+ treatment: "metric",
253
+ glow: t || e.status === "ACTIVE",
254
+ role: "button",
255
+ tabIndex: 0,
256
+ "aria-pressed": t,
257
+ "aria-label": `View flow for ${e.name}`,
258
+ onClick: () => k(t ? null : e.id),
259
+ onKeyDown: (n) => {
260
+ (n.key === "Enter" || n.key === " ") && (n.preventDefault(), k(t ? null : e.id));
261
+ },
262
+ className: "flex cursor-pointer flex-col p-5 focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]",
263
+ children: [
264
+ /* @__PURE__ */ C("div", {
265
+ className: "flex items-start justify-between gap-2",
266
+ children: [/* @__PURE__ */ S("span", {
267
+ className: "flex size-10 items-center justify-center rounded-xl bg-[var(--color-accent-soft)] text-text-primary",
268
+ children: /* @__PURE__ */ S(v, { className: "h-5 w-5" })
269
+ }), /* @__PURE__ */ S(r, { status: e.status })]
270
+ }),
271
+ /* @__PURE__ */ S("p", {
272
+ className: "mt-3 truncate text-sm font-semibold text-text-primary",
273
+ children: e.name
274
+ }),
275
+ /* @__PURE__ */ C("p", {
276
+ className: "flex items-center gap-1 truncate text-xs text-text-secondary",
277
+ children: [
278
+ /* @__PURE__ */ S(b, {
279
+ className: "h-3 w-3 shrink-0",
280
+ "aria-hidden": !0
281
+ }),
282
+ " on ",
283
+ e.triggerEvent
284
+ ]
285
+ }),
286
+ e.description && /* @__PURE__ */ S("p", {
287
+ className: "mt-2 line-clamp-2 min-h-[2rem] text-xs text-text-secondary",
288
+ children: e.description
289
+ }),
290
+ /* @__PURE__ */ C("p", {
291
+ className: "mt-3 flex items-center gap-1.5 text-xs text-text-secondary tabular-nums",
292
+ children: [
293
+ /* @__PURE__ */ S(h, {
294
+ className: "h-3.5 w-3.5",
295
+ "aria-hidden": !0
296
+ }),
297
+ " Ran ",
298
+ e.runCount,
299
+ "×",
300
+ e.lastRunAt ? ` · last ${n(e.lastRunAt)}` : ""
301
+ ]
302
+ }),
303
+ e.status !== "ACTIVE" && /* @__PURE__ */ C("button", {
304
+ type: "button",
305
+ disabled: I.isPending,
306
+ onClick: (t) => {
307
+ t.stopPropagation(), I.mutate(e.id);
308
+ },
309
+ className: "mt-4 inline-flex items-center justify-center gap-1.5 rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-text-primary hover:bg-bg-sunken disabled:opacity-50",
310
+ children: [/* @__PURE__ */ S(h, { className: "h-3.5 w-3.5" }), " Activate"]
311
+ })
312
+ ]
313
+ }, e.id);
314
+ })
315
+ })
316
+ ] }),
317
+ m && /* @__PURE__ */ S(a, {
129
318
  title: "New workflow",
130
- onClose: B,
131
- children: /* @__PURE__ */ h("form", {
319
+ onClose: X,
320
+ children: /* @__PURE__ */ C("form", {
132
321
  onSubmit: (e) => {
133
- if (e.preventDefault(), L(null), !A.trim() || !M.trim()) {
134
- L("Name and trigger event are required.");
322
+ if (e.preventDefault(), W(null), !L.trim() || !z.trim()) {
323
+ W("Name and trigger event are required.");
135
324
  return;
136
325
  }
137
326
  let t = {
138
- name: A.trim(),
139
- triggerEvent: M.trim(),
140
- ...P.trim() ? { description: P.trim() } : {}
327
+ name: L.trim(),
328
+ triggerEvent: z.trim(),
329
+ ...V.trim() ? { description: V.trim() } : {}
141
330
  };
142
- O.mutate(t, {
331
+ F.mutate(t, {
143
332
  onSuccess: () => {
144
- z(), C(!1);
333
+ Y(), _(!1);
145
334
  },
146
- onError: (e) => L(e instanceof Error ? e.message : "Could not create workflow.")
335
+ onError: (e) => W(e instanceof Error ? e.message : "Could not create workflow.")
147
336
  });
148
337
  },
149
338
  className: "space-y-4",
150
339
  children: [
151
- I && /* @__PURE__ */ m("div", {
340
+ U && /* @__PURE__ */ S("div", {
152
341
  className: "rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle px-4 py-2 text-sm text-status-error-text",
153
- children: I
342
+ children: U
154
343
  }),
155
- /* @__PURE__ */ h("div", { children: [/* @__PURE__ */ h("label", {
344
+ /* @__PURE__ */ C("div", { children: [/* @__PURE__ */ C("label", {
156
345
  htmlFor: "wf-name",
157
- className: y,
158
- children: ["Name ", /* @__PURE__ */ m("span", {
346
+ className: O,
347
+ children: ["Name ", /* @__PURE__ */ S("span", {
159
348
  className: "text-status-error-text",
160
349
  children: "*"
161
350
  })]
162
- }), /* @__PURE__ */ m("input", {
351
+ }), /* @__PURE__ */ S("input", {
163
352
  id: "wf-name",
164
353
  type: "text",
165
- value: A,
166
- onChange: (e) => j(e.target.value),
354
+ value: L,
355
+ onChange: (e) => R(e.target.value),
167
356
  placeholder: "e.g. Invoice → notify finance",
168
- className: v,
357
+ className: D,
169
358
  required: !0
170
359
  })] }),
171
- /* @__PURE__ */ h("div", { children: [/* @__PURE__ */ h("label", {
360
+ /* @__PURE__ */ C("div", { children: [/* @__PURE__ */ C("label", {
172
361
  htmlFor: "wf-trigger",
173
- className: y,
174
- children: ["Trigger event ", /* @__PURE__ */ m("span", {
362
+ className: O,
363
+ children: ["Trigger event ", /* @__PURE__ */ S("span", {
175
364
  className: "text-status-error-text",
176
365
  children: "*"
177
366
  })]
178
- }), /* @__PURE__ */ m("input", {
367
+ }), /* @__PURE__ */ S("input", {
179
368
  id: "wf-trigger",
180
369
  type: "text",
181
- value: M,
182
- onChange: (e) => N(e.target.value),
370
+ value: z,
371
+ onChange: (e) => B(e.target.value),
183
372
  placeholder: "e.g. InvoiceReceived, RenewalDetected",
184
- className: v,
373
+ className: D,
185
374
  required: !0
186
375
  })] }),
187
- /* @__PURE__ */ h("div", { children: [/* @__PURE__ */ m("label", {
376
+ /* @__PURE__ */ C("div", { children: [/* @__PURE__ */ S("label", {
188
377
  htmlFor: "wf-desc",
189
- className: y,
378
+ className: O,
190
379
  children: "Description"
191
- }), /* @__PURE__ */ m("textarea", {
380
+ }), /* @__PURE__ */ S("textarea", {
192
381
  id: "wf-desc",
193
- value: P,
194
- onChange: (e) => F(e.target.value),
382
+ value: V,
383
+ onChange: (e) => H(e.target.value),
195
384
  rows: 3,
196
385
  placeholder: "What should this workflow do when the event fires?",
197
- className: v
386
+ className: D
198
387
  })] }),
199
- /* @__PURE__ */ h("div", {
388
+ /* @__PURE__ */ C("div", {
200
389
  className: "flex justify-end gap-3",
201
- children: [/* @__PURE__ */ m("button", {
390
+ children: [/* @__PURE__ */ S("button", {
202
391
  type: "button",
203
- onClick: B,
392
+ onClick: X,
204
393
  className: "rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken",
205
394
  children: "Cancel"
206
- }), /* @__PURE__ */ m("button", {
395
+ }), /* @__PURE__ */ S("button", {
207
396
  type: "submit",
208
- disabled: O.isPending,
397
+ disabled: F.isPending,
209
398
  className: "rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90 disabled:opacity-50",
210
- children: O.isPending ? "Creating…" : "Create workflow"
399
+ children: F.isPending ? "Creating…" : "Create workflow"
211
400
  })]
212
401
  })
213
402
  ]
@@ -217,6 +406,6 @@ function b() {
217
406
  });
218
407
  }
219
408
  //#endregion
220
- export { b as WorkflowsPage };
409
+ export { j as WorkflowsPage };
221
410
 
222
411
  //# sourceMappingURL=WorkflowsPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"WorkflowsPage.js","names":[],"sources":["../../../src/subscriberbot/pages/WorkflowsPage.tsx"],"sourcesContent":["/**\n * Workflows (Automation)\n * @module subscriberbot/pages\n *\n * The Workflow Engine — event-driven automation (\"when invoice arrives →\n * classify → update relationship → notify finance\"). List + create + activate.\n * Reads `subListWorkflows`; writes `subCreateWorkflow` / `subActivateWorkflow`.\n */\n\nimport { useState } from 'react';\nimport { Plus, Workflow as WorkflowIcon, Play } 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 { Modal } from '../components/Modal';\nimport { LoadingView, ErrorView } from '../components/StateViews';\nimport { useWorkflows, useCreateWorkflow, useActivateWorkflow } from '../hooks/useSubscriberBotApi';\nimport { formatRelativeTime } from '../utils/formatters';\nimport type { SubCreateWorkflowInput, SubWorkflowStatus } from '../types';\n\nconst STATUS_OPTIONS: Array<{ value: '' | SubWorkflowStatus; label: string }> = [\n { value: '', label: 'All statuses' },\n { value: 'ACTIVE', label: 'Active' },\n { value: 'DRAFT', label: 'Draft' },\n { value: 'PAUSED', label: 'Paused' },\n { value: 'ARCHIVED', label: 'Archived' },\n];\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 WorkflowsPage() {\n const [statusFilter, setStatusFilter] = useState<'' | SubWorkflowStatus>('');\n const [showCreate, setShowCreate] = useState(false);\n\n const { data, isLoading, isError, refetch } = useWorkflows(statusFilter || undefined);\n const create = useCreateWorkflow();\n const activate = useActivateWorkflow();\n\n const [name, setName] = useState('');\n const [triggerEvent, setTriggerEvent] = useState('');\n const [description, setDescription] = useState('');\n const [formError, setFormError] = useState<string | null>(null);\n\n const workflows = data ?? [];\n\n const resetForm = () => {\n setName('');\n setTriggerEvent('');\n setDescription('');\n setFormError(null);\n };\n\n const closeCreate = () => {\n setShowCreate(false);\n resetForm();\n };\n\n const handleCreate = (e: React.FormEvent) => {\n e.preventDefault();\n setFormError(null);\n if (!name.trim() || !triggerEvent.trim()) {\n setFormError('Name and trigger event are required.');\n return;\n }\n const input: SubCreateWorkflowInput = {\n name: name.trim(),\n triggerEvent: triggerEvent.trim(),\n ...(description.trim() ? { description: description.trim() } : {}),\n };\n create.mutate(input, {\n onSuccess: () => {\n resetForm();\n setShowCreate(false);\n },\n onError: (err) =>\n setFormError(err instanceof Error ? err.message : 'Could not create workflow.'),\n });\n };\n\n return (\n <PageLayout\n title=\"Workflows\"\n description=\"Event-driven automation across your portfolio\"\n actions={\n <button\n type=\"button\"\n onClick={() => setShowCreate(true)}\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 workflow\n </button>\n }\n >\n <PagePurpose className=\"mb-4\">\n Workflows react to domain events — a new invoice, a detected renewal, a cancelled\n relationship — and run multi-step automations. Draft a workflow, then activate it when\n you're ready.\n </PagePurpose>\n\n <div className=\"flex flex-wrap items-center gap-3\">\n <select\n aria-label=\"Filter by status\"\n value={statusFilter}\n onChange={(e) => setStatusFilter(e.target.value as '' | SubWorkflowStatus)}\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 {STATUS_OPTIONS.map((o) => (\n <option key={o.value} value={o.value}>\n {o.label}\n </option>\n ))}\n </select>\n </div>\n\n {isLoading ? (\n <LoadingView label=\"Loading workflows…\" />\n ) : isError ? (\n <ErrorView message=\"Could not load workflows.\" onRetry={() => void refetch()} />\n ) : workflows.length === 0 ? (\n <div className=\"mt-6\">\n <EmptyState\n illustration=\"empty-data\"\n icon={<WorkflowIcon className=\"h-12 w-12\" />}\n title=\"No workflows yet\"\n description=\"Create your first event-driven workflow to automate your recurring portfolio.\"\n action={\n <button\n type=\"button\"\n onClick={() => setShowCreate(true)}\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 workflow\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 {workflows.map((wf) => (\n <div\n key={wf.id}\n className=\"flex flex-col rounded-lg border border-border-subtle bg-bg-surface p-4\"\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 <WorkflowIcon className=\"h-4 w-4\" />\n </span>\n <StatusBadge status={wf.status} />\n </div>\n <p className=\"mt-3 truncate text-sm font-semibold text-text-primary\">{wf.name}</p>\n <p className=\"truncate text-xs text-text-secondary\">on {wf.triggerEvent}</p>\n {wf.description && (\n <p className=\"mt-2 line-clamp-2 text-xs text-text-secondary\">{wf.description}</p>\n )}\n <p className=\"mt-2 text-xs text-text-secondary\">\n Ran {wf.runCount}×\n {wf.lastRunAt ? ` · last ${formatRelativeTime(wf.lastRunAt)}` : ''}\n </p>\n {wf.status !== 'ACTIVE' && (\n <button\n type=\"button\"\n disabled={activate.isPending}\n onClick={() => activate.mutate(wf.id)}\n className=\"mt-3 inline-flex items-center justify-center gap-1.5 rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-text-primary hover:bg-bg-sunken disabled:opacity-50\"\n >\n <Play className=\"h-3.5 w-3.5\" /> Activate\n </button>\n )}\n </div>\n ))}\n </div>\n )}\n\n {/* Create modal */}\n {showCreate && (\n <Modal title=\"New workflow\" onClose={closeCreate}>\n <form onSubmit={handleCreate} className=\"space-y-4\">\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 <div>\n <label htmlFor=\"wf-name\" className={labelCls}>\n Name <span className=\"text-status-error-text\">*</span>\n </label>\n <input\n id=\"wf-name\"\n type=\"text\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n placeholder=\"e.g. Invoice → notify finance\"\n className={inputCls}\n required\n />\n </div>\n <div>\n <label htmlFor=\"wf-trigger\" className={labelCls}>\n Trigger event <span className=\"text-status-error-text\">*</span>\n </label>\n <input\n id=\"wf-trigger\"\n type=\"text\"\n value={triggerEvent}\n onChange={(e) => setTriggerEvent(e.target.value)}\n placeholder=\"e.g. InvoiceReceived, RenewalDetected\"\n className={inputCls}\n required\n />\n </div>\n <div>\n <label htmlFor=\"wf-desc\" className={labelCls}>\n Description\n </label>\n <textarea\n id=\"wf-desc\"\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n rows={3}\n placeholder=\"What should this workflow do when the event fires?\"\n className={inputCls}\n />\n </div>\n <div className=\"flex justify-end gap-3\">\n <button\n type=\"button\"\n onClick={closeCreate}\n className=\"rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken\"\n >\n Cancel\n </button>\n <button\n type=\"submit\"\n disabled={create.isPending}\n className=\"rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90 disabled:opacity-50\"\n >\n {create.isPending ? 'Creating…' : 'Create workflow'}\n </button>\n </div>\n </form>\n </Modal>\n )}\n </PageLayout>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"WorkflowsPage.js","names":[],"sources":["../../../src/subscriberbot/pages/WorkflowsPage.tsx"],"sourcesContent":["/**\n * Workflows (Automation)\n * @module subscriberbot/pages\n *\n * The Workflow Engine — event-driven automation (\"when invoice arrives →\n * classify → update relationship → notify finance\"). List + create + activate.\n * Reads `subListWorkflows`; writes `subCreateWorkflow` / `subActivateWorkflow`.\n *\n * Opening a workflow renders a READ-ONLY horizontal step-flow derived from the\n * workflow's real `triggerEvent`, `name` and `status` (the svc contract does\n * not expose an editable step array — this is a truthful visualisation, not a\n * builder).\n */\n\nimport { useState } from 'react';\nimport {\n Plus,\n Workflow as WorkflowIcon,\n Play,\n Zap,\n Sparkles,\n CheckCircle2,\n ArrowRight,\n Clock,\n X,\n} from 'lucide-react';\nimport { PagePurpose, GlassCard } from '@burdenoff/fe-libs/ui';\nimport {\n PageLayout,\n StatusBadge,\n EmptyState,\n Modal,\n MetricsCard,\n LoadingView,\n ErrorView,\n} from '../components';\nimport { useWorkflows, useCreateWorkflow, useActivateWorkflow } from '../hooks/useSubscriberBotApi';\nimport { formatRelativeTime } from '../utils/formatters';\nimport type { SubCreateWorkflowInput, SubWorkflow, SubWorkflowStatus } from '../types';\n\nconst STATUS_OPTIONS: Array<{ value: '' | SubWorkflowStatus; label: string }> = [\n { value: '', label: 'All statuses' },\n { value: 'ACTIVE', label: 'Active' },\n { value: 'DRAFT', label: 'Draft' },\n { value: 'PAUSED', label: 'Paused' },\n { value: 'ARCHIVED', label: 'Archived' },\n];\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\n// ---------------------------------------------------------------------------\n// A single node in the read-only step flow.\n// ---------------------------------------------------------------------------\nfunction FlowNode({\n icon,\n kicker,\n title,\n sub,\n accent,\n}: {\n icon: React.ReactNode;\n kicker: string;\n title: string;\n sub?: string;\n /** Top accent bar tone. */\n accent: 'trigger' | 'run' | 'done';\n}) {\n const bar =\n accent === 'done'\n ? 'bg-status-success-text'\n : accent === 'run'\n ? 'bg-status-warning-text'\n : 'bg-[var(--color-accent-indigo)]';\n return (\n <div className=\"w-48 shrink-0 overflow-hidden rounded-xl border border-border-subtle bg-bg-surface shadow-sm\">\n <div className={`h-1 w-full ${bar}`} aria-hidden />\n <div className=\"p-3\">\n <span className=\"flex size-8 items-center justify-center rounded-lg bg-[var(--color-accent-soft)] text-text-primary\">\n {icon}\n </span>\n <p className=\"mt-2 text-[10px] font-medium uppercase tracking-wide text-text-secondary\">\n {kicker}\n </p>\n <p className=\"truncate text-sm font-semibold text-text-primary\" title={title}>\n {title}\n </p>\n {sub && <p className=\"mt-0.5 truncate text-xs text-text-secondary\">{sub}</p>}\n </div>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Read-only flow panel for the selected workflow.\n// ---------------------------------------------------------------------------\nfunction WorkflowFlowPanel({\n workflow,\n onClose,\n onActivate,\n activating,\n}: {\n workflow: SubWorkflow;\n onClose: () => void;\n onActivate: () => void;\n activating: boolean;\n}) {\n const connector = (\n <div className=\"flex shrink-0 items-center px-1 text-text-secondary\" aria-hidden>\n <span className=\"h-px w-4 bg-border-seam sm:w-6\" />\n <ArrowRight className=\"h-4 w-4\" />\n </div>\n );\n\n return (\n <GlassCard treatment=\"glass\" glow className=\"mt-6 p-5\">\n <div className=\"flex flex-wrap items-start justify-between gap-3\">\n <div className=\"min-w-0\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <p className=\"text-base font-semibold text-text-primary\">{workflow.name}</p>\n <StatusBadge status={workflow.status} />\n </div>\n <p className=\"mt-1 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-text-secondary\">\n <span className=\"tabular-nums\">Ran {workflow.runCount}×</span>\n {workflow.lastRunAt && (\n <span className=\"inline-flex items-center gap-1\">\n <Clock className=\"h-3 w-3\" aria-hidden /> last{' '}\n {formatRelativeTime(workflow.lastRunAt)}\n </span>\n )}\n </p>\n </div>\n <button\n type=\"button\"\n onClick={onClose}\n aria-label=\"Close flow\"\n className=\"rounded-lg border border-border-subtle p-1.5 text-text-secondary hover:bg-bg-sunken hover:text-text-primary\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n </div>\n\n {workflow.description && (\n <p className=\"mt-2 max-w-3xl text-sm text-text-secondary\">{workflow.description}</p>\n )}\n\n {/* Horizontal read-only step flow (scrolls on small screens) */}\n <div className=\"mt-4 overflow-x-auto pb-2\">\n <div className=\"flex min-w-max items-stretch\">\n <FlowNode\n accent=\"trigger\"\n kicker=\"When\"\n icon={<Zap className=\"h-4 w-4\" />}\n title={workflow.triggerEvent}\n sub=\"Trigger event\"\n />\n {connector}\n <FlowNode\n accent=\"run\"\n kicker=\"Run\"\n icon={<Sparkles className=\"h-4 w-4\" />}\n title={workflow.name}\n sub=\"Automation\"\n />\n {connector}\n <FlowNode\n accent=\"done\"\n kicker=\"Then\"\n icon={<CheckCircle2 className=\"h-4 w-4\" />}\n title={workflow.status === 'ACTIVE' ? 'Live' : 'Awaiting activation'}\n sub={`Status: ${workflow.status.charAt(0) + workflow.status.slice(1).toLowerCase()}`}\n />\n </div>\n </div>\n\n {workflow.status !== 'ACTIVE' && (\n <div className=\"mt-3 flex justify-end\">\n <button\n type=\"button\"\n disabled={activating}\n onClick={onActivate}\n className=\"inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90 disabled:opacity-50\"\n >\n <Play className=\"h-4 w-4\" /> {activating ? 'Activating…' : 'Activate workflow'}\n </button>\n </div>\n )}\n </GlassCard>\n );\n}\n\nexport function WorkflowsPage() {\n const [statusFilter, setStatusFilter] = useState<'' | SubWorkflowStatus>('');\n const [showCreate, setShowCreate] = useState(false);\n const [selectedId, setSelectedId] = useState<string | null>(null);\n\n const { data, isLoading, isError, refetch } = useWorkflows(statusFilter || undefined);\n const create = useCreateWorkflow();\n const activate = useActivateWorkflow();\n\n const [name, setName] = useState('');\n const [triggerEvent, setTriggerEvent] = useState('');\n const [description, setDescription] = useState('');\n const [formError, setFormError] = useState<string | null>(null);\n\n const workflows = data ?? [];\n const selected = workflows.find((w) => w.id === selectedId) ?? null;\n\n // --- Real, computed aggregates -------------------------------------------\n const activeCount = workflows.filter((w) => w.status === 'ACTIVE').length;\n const totalRuns = workflows.reduce((s, w) => s + (w.runCount || 0), 0);\n\n const resetForm = () => {\n setName('');\n setTriggerEvent('');\n setDescription('');\n setFormError(null);\n };\n\n const closeCreate = () => {\n setShowCreate(false);\n resetForm();\n };\n\n const handleCreate = (e: React.FormEvent) => {\n e.preventDefault();\n setFormError(null);\n if (!name.trim() || !triggerEvent.trim()) {\n setFormError('Name and trigger event are required.');\n return;\n }\n const input: SubCreateWorkflowInput = {\n name: name.trim(),\n triggerEvent: triggerEvent.trim(),\n ...(description.trim() ? { description: description.trim() } : {}),\n };\n create.mutate(input, {\n onSuccess: () => {\n resetForm();\n setShowCreate(false);\n },\n onError: (err) =>\n setFormError(err instanceof Error ? err.message : 'Could not create workflow.'),\n });\n };\n\n return (\n <PageLayout\n title=\"Workflows\"\n description=\"Event-driven automation across your portfolio\"\n actions={\n <button\n type=\"button\"\n onClick={() => setShowCreate(true)}\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 workflow\n </button>\n }\n >\n <PagePurpose className=\"mb-4\">\n Workflows react to domain events — a new invoice, a detected renewal, a cancelled\n relationship — and run multi-step automations. Draft a workflow, then activate it when\n you're ready.\n </PagePurpose>\n\n <div className=\"flex flex-wrap items-center gap-3\">\n <select\n aria-label=\"Filter by status\"\n value={statusFilter}\n onChange={(e) => setStatusFilter(e.target.value as '' | SubWorkflowStatus)}\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 {STATUS_OPTIONS.map((o) => (\n <option key={o.value} value={o.value}>\n {o.label}\n </option>\n ))}\n </select>\n </div>\n\n {isLoading ? (\n <LoadingView label=\"Loading workflows…\" />\n ) : isError ? (\n <ErrorView message=\"Could not load workflows.\" onRetry={() => void refetch()} />\n ) : workflows.length === 0 ? (\n <div className=\"mt-6\">\n <EmptyState\n illustration=\"empty-data\"\n icon={<WorkflowIcon className=\"h-12 w-12\" />}\n title=\"No workflows yet\"\n description=\"Create your first event-driven workflow to automate your recurring portfolio.\"\n action={\n <button\n type=\"button\"\n onClick={() => setShowCreate(true)}\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 workflow\n </button>\n }\n />\n </div>\n ) : (\n <>\n {/* Overview (computed) */}\n <div className=\"mt-6 grid grid-cols-1 gap-4 sm:grid-cols-3\">\n <MetricsCard\n icon={<WorkflowIcon className=\"h-5 w-5\" />}\n value={workflows.length}\n label=\"Workflows\"\n />\n <MetricsCard icon={<Zap className=\"h-5 w-5\" />} value={activeCount} label=\"Active\" />\n <MetricsCard icon={<Play className=\"h-5 w-5\" />} value={totalRuns} label=\"Total runs\" />\n </div>\n\n {/* Selected workflow flow */}\n {selected && (\n <WorkflowFlowPanel\n workflow={selected}\n onClose={() => setSelectedId(null)}\n onActivate={() => activate.mutate(selected.id)}\n activating={activate.isPending}\n />\n )}\n\n {/* Workflow cards */}\n <div className=\"mt-6 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {workflows.map((wf) => {\n const isSelected = wf.id === selectedId;\n return (\n <GlassCard\n key={wf.id}\n treatment=\"metric\"\n glow={isSelected || wf.status === 'ACTIVE'}\n role=\"button\"\n tabIndex={0}\n aria-pressed={isSelected}\n aria-label={`View flow for ${wf.name}`}\n onClick={() => setSelectedId(isSelected ? null : wf.id)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n setSelectedId(isSelected ? null : wf.id);\n }\n }}\n className=\"flex cursor-pointer flex-col p-5 focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]\"\n >\n <div className=\"flex items-start justify-between gap-2\">\n <span className=\"flex size-10 items-center justify-center rounded-xl bg-[var(--color-accent-soft)] text-text-primary\">\n <WorkflowIcon className=\"h-5 w-5\" />\n </span>\n <StatusBadge status={wf.status} />\n </div>\n <p className=\"mt-3 truncate text-sm font-semibold text-text-primary\">{wf.name}</p>\n <p className=\"flex items-center gap-1 truncate text-xs text-text-secondary\">\n <Zap className=\"h-3 w-3 shrink-0\" aria-hidden /> on {wf.triggerEvent}\n </p>\n {wf.description && (\n <p className=\"mt-2 line-clamp-2 min-h-[2rem] text-xs text-text-secondary\">\n {wf.description}\n </p>\n )}\n <p className=\"mt-3 flex items-center gap-1.5 text-xs text-text-secondary tabular-nums\">\n <Play className=\"h-3.5 w-3.5\" aria-hidden /> Ran {wf.runCount}×\n {wf.lastRunAt ? ` · last ${formatRelativeTime(wf.lastRunAt)}` : ''}\n </p>\n {wf.status !== 'ACTIVE' && (\n <button\n type=\"button\"\n disabled={activate.isPending}\n onClick={(e) => {\n e.stopPropagation();\n activate.mutate(wf.id);\n }}\n className=\"mt-4 inline-flex items-center justify-center gap-1.5 rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-text-primary hover:bg-bg-sunken disabled:opacity-50\"\n >\n <Play className=\"h-3.5 w-3.5\" /> Activate\n </button>\n )}\n </GlassCard>\n );\n })}\n </div>\n </>\n )}\n\n {/* Create modal */}\n {showCreate && (\n <Modal title=\"New workflow\" onClose={closeCreate}>\n <form onSubmit={handleCreate} className=\"space-y-4\">\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 <div>\n <label htmlFor=\"wf-name\" className={labelCls}>\n Name <span className=\"text-status-error-text\">*</span>\n </label>\n <input\n id=\"wf-name\"\n type=\"text\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n placeholder=\"e.g. Invoice → notify finance\"\n className={inputCls}\n required\n />\n </div>\n <div>\n <label htmlFor=\"wf-trigger\" className={labelCls}>\n Trigger event <span className=\"text-status-error-text\">*</span>\n </label>\n <input\n id=\"wf-trigger\"\n type=\"text\"\n value={triggerEvent}\n onChange={(e) => setTriggerEvent(e.target.value)}\n placeholder=\"e.g. InvoiceReceived, RenewalDetected\"\n className={inputCls}\n required\n />\n </div>\n <div>\n <label htmlFor=\"wf-desc\" className={labelCls}>\n Description\n </label>\n <textarea\n id=\"wf-desc\"\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n rows={3}\n placeholder=\"What should this workflow do when the event fires?\"\n className={inputCls}\n />\n </div>\n <div className=\"flex justify-end gap-3\">\n <button\n type=\"button\"\n onClick={closeCreate}\n className=\"rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken\"\n >\n Cancel\n </button>\n <button\n type=\"submit\"\n disabled={create.isPending}\n className=\"rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90 disabled:opacity-50\"\n >\n {create.isPending ? 'Creating…' : 'Create workflow'}\n </button>\n </div>\n </form>\n </Modal>\n )}\n </PageLayout>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Agent detail
3
+ * @module subscriberbot/pages/agents
4
+ *
5
+ * A single AI agent: its kind, posture, last run, and the autonomous policies
6
+ * that bound it. Reads `subAgent(id)`; changes posture via `subSetAgentStatus`.
7
+ * The "Run history" timeline is derived from the agent's real `lastRunAt` and
8
+ * each policy's real `lastTriggeredAt` — never mocked.
9
+ */
10
+ export declare function AgentDetailPage(): import("react").JSX.Element;
11
+ //# sourceMappingURL=AgentDetailPage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AgentDetailPage.d.ts","sourceRoot":"","sources":["../../../../src/subscriberbot/pages/agents/AgentDetailPage.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAwRH,wBAAgB,eAAe,gCAmP9B"}