@burdenoff/microfe-subscriberbot 2026.1030.1 → 2026.1030.3

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 (49) hide show
  1. package/dist/subscriberbot/SubscriberBotRoutes.d.ts.map +1 -1
  2. package/dist/subscriberbot/SubscriberBotRoutes.js +16 -8
  3. package/dist/subscriberbot/SubscriberBotRoutes.js.map +1 -1
  4. package/dist/subscriberbot/components/StatusBadge.d.ts.map +1 -1
  5. package/dist/subscriberbot/components/StatusBadge.js +6 -1
  6. package/dist/subscriberbot/components/StatusBadge.js.map +1 -1
  7. package/dist/subscriberbot/components/decisions/DecisionBanners.d.ts +11 -0
  8. package/dist/subscriberbot/components/decisions/DecisionBanners.d.ts.map +1 -0
  9. package/dist/subscriberbot/components/decisions/DecisionBanners.js +62 -0
  10. package/dist/subscriberbot/components/decisions/DecisionBanners.js.map +1 -0
  11. package/dist/subscriberbot/components/decisions/DecisionCard.d.ts +22 -0
  12. package/dist/subscriberbot/components/decisions/DecisionCard.d.ts.map +1 -0
  13. package/dist/subscriberbot/components/decisions/DecisionCard.js +316 -0
  14. package/dist/subscriberbot/components/decisions/DecisionCard.js.map +1 -0
  15. package/dist/subscriberbot/components/decisions/decisionModel.d.ts +51 -0
  16. package/dist/subscriberbot/components/decisions/decisionModel.d.ts.map +1 -0
  17. package/dist/subscriberbot/components/decisions/decisionModel.js +139 -0
  18. package/dist/subscriberbot/components/decisions/decisionModel.js.map +1 -0
  19. package/dist/subscriberbot/components/decisions/index.d.ts +9 -0
  20. package/dist/subscriberbot/components/decisions/index.d.ts.map +1 -0
  21. package/dist/subscriberbot/components/decisions/index.js +3 -0
  22. package/dist/subscriberbot/hooks/index.d.ts +1 -1
  23. package/dist/subscriberbot/hooks/index.d.ts.map +1 -1
  24. package/dist/subscriberbot/hooks/useSubscriberBotApi.d.ts +19 -2
  25. package/dist/subscriberbot/hooks/useSubscriberBotApi.d.ts.map +1 -1
  26. package/dist/subscriberbot/hooks/useSubscriberBotApi.js +103 -38
  27. package/dist/subscriberbot/hooks/useSubscriberBotApi.js.map +1 -1
  28. package/dist/subscriberbot/pages/agents/AgentDetailPage.d.ts +7 -0
  29. package/dist/subscriberbot/pages/agents/AgentDetailPage.d.ts.map +1 -1
  30. package/dist/subscriberbot/pages/agents/AgentDetailPage.js +280 -175
  31. package/dist/subscriberbot/pages/agents/AgentDetailPage.js.map +1 -1
  32. package/dist/subscriberbot/pages/decisions/DecisionDetailPage.d.ts +12 -0
  33. package/dist/subscriberbot/pages/decisions/DecisionDetailPage.d.ts.map +1 -0
  34. package/dist/subscriberbot/pages/decisions/DecisionDetailPage.js +180 -0
  35. package/dist/subscriberbot/pages/decisions/DecisionDetailPage.js.map +1 -0
  36. package/dist/subscriberbot/pages/decisions/DecisionsPage.d.ts +13 -0
  37. package/dist/subscriberbot/pages/decisions/DecisionsPage.d.ts.map +1 -0
  38. package/dist/subscriberbot/pages/decisions/DecisionsPage.js +154 -0
  39. package/dist/subscriberbot/pages/decisions/DecisionsPage.js.map +1 -0
  40. package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.d.ts.map +1 -1
  41. package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.js +338 -316
  42. package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.js.map +1 -1
  43. package/dist/subscriberbot/types/index.d.ts +66 -1
  44. package/dist/subscriberbot/types/index.d.ts.map +1 -1
  45. package/dist/subscriberbot/utils/pageContext.d.ts +1 -0
  46. package/dist/subscriberbot/utils/pageContext.d.ts.map +1 -1
  47. package/dist/subscriberbot/utils/pageContext.js +2 -0
  48. package/dist/subscriberbot/utils/pageContext.js.map +1 -1
  49. package/package.json +1 -1
@@ -11,18 +11,36 @@ import { PostureOptions as d } from "../../components/PostureOptions.js";
11
11
  import { ErrorView as f, LoadingView as p, Section as m } from "../../components/StateViews.js";
12
12
  import { Timeline as h } from "../../components/viz.js";
13
13
  import "../../components/index.js";
14
- import { useAgent as g, useCreatePolicy as _, useSetAgentStatus as v } from "../../hooks/useSubscriberBotApi.js";
15
- import { useState as y } from "react";
16
- import { ArrowLeft as b, ArrowLeftRight as x, Bot as S, Building2 as C, Clock as w, ConciergeBell as T, DollarSign as E, Handshake as D, History as O, ListChecks as k, Mail as A, Plus as j, RefreshCw as M, Search as N, ShieldCheck as P, SlidersHorizontal as F, Zap as I } from "lucide-react";
17
- import { useParams as L } from "react-router";
18
- import { jsx as R, jsxs as z } from "react/jsx-runtime";
19
- import { GlassCard as B } from "@burdenoff/fe-libs/ui";
14
+ import { useAgent as g, useCreatePolicy as _, useDecisions as v, useRunAgent as y, useSetAgentStatus as ee } from "../../hooks/useSubscriberBotApi.js";
15
+ import { RUNNABLE_AGENT_KINDS as te } from "../../components/decisions/decisionModel.js";
16
+ import { DecisionCard as ne } from "../../components/decisions/DecisionCard.js";
17
+ import { AiDisclaimer as re, DecisionsUnavailableBanner as b } from "../../components/decisions/DecisionBanners.js";
18
+ import "../../components/decisions/index.js";
19
+ import { useState as x } from "react";
20
+ import { ArrowLeft as ie, ArrowLeftRight as S, ArrowRight as C, Bot as w, Building2 as T, Clock as E, ConciergeBell as D, DollarSign as O, Handshake as k, History as ae, ListChecks as oe, Mail as A, Play as se, Plus as ce, RefreshCw as j, Search as M, ShieldCheck as N, SlidersHorizontal as P, Zap as le } from "lucide-react";
21
+ import { useParams as ue } from "react-router";
22
+ import { jsx as F, jsxs as I } from "react/jsx-runtime";
23
+ import { GlassCard as L } from "@burdenoff/fe-libs/ui";
20
24
  //#region src/subscriberbot/pages/agents/AgentDetailPage.tsx
21
- var V = [
25
+ function de(e) {
26
+ let t = /* @__PURE__ */ new Map();
27
+ for (let n of e) {
28
+ let e = t.get(n.runId) ?? {
29
+ runId: n.runId,
30
+ ranAt: n.createdAt,
31
+ total: 0,
32
+ proposed: 0,
33
+ flagged: 0
34
+ };
35
+ e.total += 1, n.status === "PROPOSED" && (e.proposed += 1), n.status === "FLAGGED" && (e.flagged += 1), n.createdAt < e.ranAt && (e.ranAt = n.createdAt), t.set(n.runId, e);
36
+ }
37
+ return [...t.values()];
38
+ }
39
+ var R = [
22
40
  "DISABLED",
23
41
  "SUGGEST_ONLY",
24
42
  "AUTONOMOUS"
25
- ], H = {
43
+ ], z = {
26
44
  DISCOVERY: "agents.kinds.discovery",
27
45
  RENEWAL: "agents.kinds.renewal",
28
46
  COST: "agents.kinds.cost",
@@ -32,7 +50,7 @@ var V = [
32
50
  NEGOTIATION: "agents.kinds.negotiation",
33
51
  MIGRATION: "agents.kinds.migration",
34
52
  CONCIERGE: "agents.kinds.concierge"
35
- }, U = [
53
+ }, B = [
36
54
  "ALERT",
37
55
  "CREATE_TASK",
38
56
  "RENEW",
@@ -40,18 +58,18 @@ var V = [
40
58
  "PAUSE",
41
59
  "UPGRADE",
42
60
  "DOWNGRADE"
43
- ], W = {
44
- DISCOVERY: N,
45
- RENEWAL: M,
46
- COST: E,
61
+ ], V = {
62
+ DISCOVERY: M,
63
+ RENEWAL: j,
64
+ COST: O,
47
65
  NEWSLETTER: A,
48
- VENDOR: C,
49
- COMPLIANCE: P,
50
- NEGOTIATION: D,
51
- MIGRATION: x,
52
- CONCIERGE: T
66
+ VENDOR: T,
67
+ COMPLIANCE: N,
68
+ NEGOTIATION: k,
69
+ MIGRATION: S,
70
+ CONCIERGE: D
53
71
  };
54
- function G(e) {
72
+ function fe(e) {
55
73
  switch (e) {
56
74
  case "RENEW":
57
75
  case "UPGRADE": return "positive";
@@ -62,48 +80,48 @@ function G(e) {
62
80
  default: return "default";
63
81
  }
64
82
  }
65
- var K = "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)]", q = "mb-1 block text-xs font-medium text-text-secondary";
66
- function J(e) {
83
+ var H = "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)]", U = "mb-1 block text-xs font-medium text-text-secondary";
84
+ function W(e) {
67
85
  let t = e.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ").trim();
68
86
  return t.charAt(0).toUpperCase() + t.slice(1);
69
87
  }
70
- function Y(e) {
71
- return e == null ? "—" : typeof e == "string" ? e : typeof e == "number" ? i(e) : typeof e == "boolean" ? e ? "Yes" : "No" : Array.isArray(e) ? e.map(Y).join(", ") : JSON.stringify(e);
88
+ function G(e) {
89
+ return e == null ? "—" : typeof e == "string" ? e : typeof e == "number" ? i(e) : typeof e == "boolean" ? e ? "Yes" : "No" : Array.isArray(e) ? e.map(G).join(", ") : JSON.stringify(e);
72
90
  }
73
- function X(e) {
91
+ function K(e) {
74
92
  return !e || Array.isArray(e) ? [] : Object.entries(e).filter(([, e]) => e != null && e !== "").map(([e, t]) => ({
75
93
  key: e,
76
- value: Y(t)
94
+ value: G(t)
77
95
  }));
78
96
  }
79
- function Z({ enabled: e }) {
97
+ function q({ enabled: e }) {
80
98
  let t = u();
81
- return /* @__PURE__ */ z("span", {
99
+ return /* @__PURE__ */ I("span", {
82
100
  className: e ? "inline-flex items-center gap-1.5 rounded-full bg-status-success-bg-subtle px-2.5 py-0.5 text-xs font-medium text-status-success-text" : "inline-flex items-center gap-1.5 rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs font-medium text-text-secondary",
83
- children: [/* @__PURE__ */ R("span", {
101
+ children: [/* @__PURE__ */ F("span", {
84
102
  "aria-hidden": !0,
85
103
  className: "size-1.5 rounded-full bg-current",
86
104
  style: { opacity: e ? 1 : .6 }
87
105
  }), e ? t("agents.detail.enabled", "Enabled") : t("agents.detail.disabled", "Disabled")]
88
106
  });
89
107
  }
90
- function Q({ agentId: e, onClose: t }) {
91
- let n = u(), i = _(), [a, o] = y(""), [s, l] = y("ALERT"), [d, f] = y(""), [p, m] = y(""), [h, g] = y(!0), [v, b] = y(null);
92
- return /* @__PURE__ */ R(c, {
108
+ function pe({ agentId: e, onClose: t }) {
109
+ let n = u(), i = _(), [a, o] = x(""), [s, l] = x("ALERT"), [d, f] = x(""), [p, m] = x(""), [h, g] = x(!0), [v, y] = x(null);
110
+ return /* @__PURE__ */ F(c, {
93
111
  title: n("agents.policyModal.title", "Add policy"),
94
112
  onClose: t,
95
113
  maxWidthClassName: "max-w-xl",
96
- children: /* @__PURE__ */ z("form", {
114
+ children: /* @__PURE__ */ I("form", {
97
115
  onSubmit: (r) => {
98
- if (r.preventDefault(), b(null), !a.trim()) {
99
- b(n("agents.policyModal.nameRequired", "A policy name is required."));
116
+ if (r.preventDefault(), y(null), !a.trim()) {
117
+ y(n("agents.policyModal.nameRequired", "A policy name is required."));
100
118
  return;
101
119
  }
102
120
  let o;
103
121
  if (p.trim()) try {
104
122
  o = JSON.parse(p);
105
123
  } catch {
106
- b(n("agents.policyModal.conditionInvalid", "Condition must be valid JSON (e.g. {\"amountOver\": 100})."));
124
+ y(n("agents.policyModal.conditionInvalid", "Condition must be valid JSON (e.g. {\"amountOver\": 100})."));
107
125
  return;
108
126
  }
109
127
  i.mutate({
@@ -115,56 +133,56 @@ function Q({ agentId: e, onClose: t }) {
115
133
  ...o ? { condition: o } : {}
116
134
  }, {
117
135
  onSuccess: () => t(),
118
- onError: (e) => b(e instanceof Error ? e.message : n("agents.policyModal.error", "Could not add policy."))
136
+ onError: (e) => y(e instanceof Error ? e.message : n("agents.policyModal.error", "Could not add policy."))
119
137
  });
120
138
  },
121
139
  className: "space-y-4",
122
140
  children: [
123
- v && /* @__PURE__ */ R("div", {
141
+ v && /* @__PURE__ */ F("div", {
124
142
  className: "rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle px-4 py-2 text-sm text-status-error-text",
125
143
  children: v
126
144
  }),
127
- /* @__PURE__ */ z("div", { children: [/* @__PURE__ */ z("label", {
145
+ /* @__PURE__ */ I("div", { children: [/* @__PURE__ */ I("label", {
128
146
  htmlFor: "policy-name",
129
- className: q,
147
+ className: U,
130
148
  children: [
131
149
  n("agents.policyModal.nameLabel", "Name"),
132
150
  " ",
133
- /* @__PURE__ */ R("span", {
151
+ /* @__PURE__ */ F("span", {
134
152
  className: "text-status-error-text",
135
153
  children: "*"
136
154
  })
137
155
  ]
138
- }), /* @__PURE__ */ R("input", {
156
+ }), /* @__PURE__ */ F("input", {
139
157
  id: "policy-name",
140
158
  type: "text",
141
159
  value: a,
142
160
  onChange: (e) => o(e.target.value),
143
161
  placeholder: n("agents.policyModal.namePlaceholder", "e.g. Alert on price hike over 20%"),
144
- className: K,
162
+ className: H,
145
163
  required: !0
146
164
  })] }),
147
- /* @__PURE__ */ z("div", { children: [/* @__PURE__ */ R("label", {
165
+ /* @__PURE__ */ I("div", { children: [/* @__PURE__ */ F("label", {
148
166
  htmlFor: "policy-action",
149
- className: q,
167
+ className: U,
150
168
  children: n("agents.policyModal.actionLabel", "Action")
151
- }), /* @__PURE__ */ R("select", {
169
+ }), /* @__PURE__ */ F("select", {
152
170
  id: "policy-action",
153
171
  value: s,
154
172
  onChange: (e) => l(e.target.value),
155
- className: K,
156
- children: U.map((e) => /* @__PURE__ */ R("option", {
173
+ className: H,
174
+ children: B.map((e) => /* @__PURE__ */ F("option", {
157
175
  value: e,
158
176
  children: r(e)
159
177
  }, e))
160
178
  })] }),
161
- /* @__PURE__ */ z("div", { children: [/* @__PURE__ */ z("label", {
179
+ /* @__PURE__ */ I("div", { children: [/* @__PURE__ */ I("label", {
162
180
  htmlFor: "policy-condition",
163
- className: q,
181
+ className: U,
164
182
  children: [
165
183
  n("agents.policyModal.conditionLabel", "Condition"),
166
184
  " ",
167
- /* @__PURE__ */ z("span", {
185
+ /* @__PURE__ */ I("span", {
168
186
  className: "text-text-secondary",
169
187
  children: [
170
188
  "(",
@@ -173,42 +191,42 @@ function Q({ agentId: e, onClose: t }) {
173
191
  ]
174
192
  })
175
193
  ]
176
- }), /* @__PURE__ */ R("textarea", {
194
+ }), /* @__PURE__ */ F("textarea", {
177
195
  id: "policy-condition",
178
196
  value: p,
179
197
  onChange: (e) => m(e.target.value),
180
198
  rows: 3,
181
199
  placeholder: n("agents.policyModal.conditionPlaceholder", "{ \"priceIncreasePct\": 20 }"),
182
- className: `${K} font-mono`
200
+ className: `${H} font-mono`
183
201
  })] }),
184
- /* @__PURE__ */ z("div", { children: [/* @__PURE__ */ R("label", {
202
+ /* @__PURE__ */ I("div", { children: [/* @__PURE__ */ F("label", {
185
203
  htmlFor: "policy-desc",
186
- className: q,
204
+ className: U,
187
205
  children: n("agents.policyModal.descriptionLabel", "Description")
188
- }), /* @__PURE__ */ R("textarea", {
206
+ }), /* @__PURE__ */ F("textarea", {
189
207
  id: "policy-desc",
190
208
  value: d,
191
209
  onChange: (e) => f(e.target.value),
192
210
  rows: 2,
193
- className: K
211
+ className: H
194
212
  })] }),
195
- /* @__PURE__ */ z("label", {
213
+ /* @__PURE__ */ I("label", {
196
214
  className: "flex items-center gap-2 text-sm text-text-primary",
197
- children: [/* @__PURE__ */ R("input", {
215
+ children: [/* @__PURE__ */ F("input", {
198
216
  type: "checkbox",
199
217
  checked: h,
200
218
  onChange: (e) => g(e.target.checked),
201
219
  className: "size-4 rounded border-border-subtle"
202
220
  }), n("agents.policyModal.enabled", "Enabled")]
203
221
  }),
204
- /* @__PURE__ */ z("div", {
222
+ /* @__PURE__ */ I("div", {
205
223
  className: "flex justify-end gap-3",
206
- children: [/* @__PURE__ */ R("button", {
224
+ children: [/* @__PURE__ */ F("button", {
207
225
  type: "button",
208
226
  onClick: t,
209
227
  className: "rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken",
210
228
  children: n("agents.policyModal.cancel", "Cancel")
211
- }), /* @__PURE__ */ R("button", {
229
+ }), /* @__PURE__ */ F("button", {
212
230
  type: "submit",
213
231
  disabled: i.isPending,
214
232
  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",
@@ -219,69 +237,69 @@ function Q({ agentId: e, onClose: t }) {
219
237
  })
220
238
  });
221
239
  }
222
- function ee({ policy: e }) {
223
- let t = u(), n = X(e.condition);
224
- return /* @__PURE__ */ z(B, {
240
+ function me({ policy: e }) {
241
+ let t = u(), n = K(e.condition);
242
+ return /* @__PURE__ */ I(L, {
225
243
  treatment: "metric",
226
244
  className: "flex flex-col p-4",
227
245
  children: [
228
- /* @__PURE__ */ z("div", {
246
+ /* @__PURE__ */ I("div", {
229
247
  className: "flex items-start justify-between gap-2",
230
- children: [/* @__PURE__ */ R("p", {
248
+ children: [/* @__PURE__ */ F("p", {
231
249
  className: "text-sm font-semibold text-text-primary",
232
250
  children: e.name
233
- }), /* @__PURE__ */ R(Z, { enabled: e.isEnabled })]
251
+ }), /* @__PURE__ */ F(q, { enabled: e.isEnabled })]
234
252
  }),
235
- /* @__PURE__ */ z("div", {
253
+ /* @__PURE__ */ I("div", {
236
254
  className: "mt-2 flex flex-wrap items-center gap-2",
237
- children: [/* @__PURE__ */ z("span", {
255
+ children: [/* @__PURE__ */ I("span", {
238
256
  className: "inline-flex items-center gap-1.5 rounded-md bg-[var(--color-accent-soft)] px-2 py-0.5 text-[11px] font-medium text-text-primary",
239
257
  children: [
240
- /* @__PURE__ */ R(P, {
258
+ /* @__PURE__ */ F(N, {
241
259
  className: "h-3 w-3",
242
260
  "aria-hidden": !0
243
261
  }),
244
262
  " ",
245
263
  r(e.action)
246
264
  ]
247
- }), /* @__PURE__ */ R("span", {
265
+ }), /* @__PURE__ */ F("span", {
248
266
  className: "inline-flex items-center gap-1 rounded-md bg-bg-sunken px-2 py-0.5 text-[11px] font-medium text-text-secondary tabular-nums",
249
267
  children: t("agents.detail.triggered", "Triggered {{count}}×", { count: e.triggerCount })
250
268
  })]
251
269
  }),
252
- e.description && /* @__PURE__ */ R("p", {
270
+ e.description && /* @__PURE__ */ F("p", {
253
271
  className: "mt-2 line-clamp-2 text-xs text-text-secondary",
254
272
  children: e.description
255
273
  }),
256
- n.length > 0 && /* @__PURE__ */ z("div", {
274
+ n.length > 0 && /* @__PURE__ */ I("div", {
257
275
  className: "mt-3 border-t border-border-subtle pt-2.5",
258
- children: [/* @__PURE__ */ z("p", {
276
+ children: [/* @__PURE__ */ I("p", {
259
277
  className: "flex items-center gap-1.5 text-[10px] font-medium uppercase tracking-wide text-text-secondary",
260
278
  children: [
261
- /* @__PURE__ */ R(F, {
279
+ /* @__PURE__ */ F(P, {
262
280
  className: "h-3 w-3",
263
281
  "aria-hidden": !0
264
282
  }),
265
283
  " ",
266
284
  t("agents.detail.firesWhen", "Fires when")
267
285
  ]
268
- }), /* @__PURE__ */ R("div", {
286
+ }), /* @__PURE__ */ F("div", {
269
287
  className: "mt-1.5 flex flex-wrap gap-1.5",
270
- children: n.map((e) => /* @__PURE__ */ z("span", {
288
+ children: n.map((e) => /* @__PURE__ */ I("span", {
271
289
  className: "inline-flex items-center gap-1.5 rounded-md border border-border-subtle bg-bg-sunken px-2 py-0.5 text-[11px] text-text-secondary",
272
- children: [/* @__PURE__ */ R("span", {
290
+ children: [/* @__PURE__ */ F("span", {
273
291
  className: "font-medium text-text-primary",
274
- children: J(e.key)
275
- }), /* @__PURE__ */ R("span", {
292
+ children: W(e.key)
293
+ }), /* @__PURE__ */ F("span", {
276
294
  className: "font-mono tabular-nums",
277
295
  children: e.value
278
296
  })]
279
297
  }, e.key))
280
298
  })]
281
299
  }),
282
- /* @__PURE__ */ z("p", {
300
+ /* @__PURE__ */ I("p", {
283
301
  className: "mt-2 flex items-center gap-1.5 text-xs text-text-secondary",
284
- children: [/* @__PURE__ */ R(w, {
302
+ children: [/* @__PURE__ */ F(E, {
285
303
  className: "h-3.5 w-3.5",
286
304
  "aria-hidden": !0
287
305
  }), e.lastTriggeredAt ? t("agents.detail.triggered", "Triggered {{count}}×", { count: e.triggerCount }) : t("agents.detail.notYetTriggered", "Not yet triggered")]
@@ -289,26 +307,26 @@ function ee({ policy: e }) {
289
307
  ]
290
308
  });
291
309
  }
292
- function $() {
293
- let i = u(), { id: c } = L(), { navigateTo: _ } = e(), { data: x, isLoading: C, isError: T, refetch: E } = g(c), D = v(), A = l(), [M, N] = y(null), [F, U] = y(!1);
294
- if (C) return /* @__PURE__ */ R(t, {
310
+ function J() {
311
+ let i = u(), { id: c } = ue(), { navigateTo: _ } = e(), { data: S, isLoading: T, isError: D, refetch: O } = g(c), k = ee(), A = l(), [j, M] = x(null), [P, B] = x(!1), H = y(), [U, W] = x(null), [G, K] = x(null), q = v({ agentId: c }, { enabled: !!c });
312
+ if (T) return /* @__PURE__ */ F(t, {
295
313
  title: i("agents.detail.loading", "Loading agent…"),
296
- children: /* @__PURE__ */ R(p, { label: i("agents.detail.loading", "Loading agent…") })
314
+ children: /* @__PURE__ */ F(p, { label: i("agents.detail.loading", "Loading agent…") })
297
315
  });
298
- if (T) return /* @__PURE__ */ R(t, {
316
+ if (D) return /* @__PURE__ */ F(t, {
299
317
  title: i("agents.title", "AI Agents"),
300
- children: /* @__PURE__ */ R(f, {
318
+ children: /* @__PURE__ */ F(f, {
301
319
  message: i("agents.detail.error", "Could not load this agent."),
302
- onRetry: () => void E()
320
+ onRetry: () => void O()
303
321
  })
304
322
  });
305
- if (!x) return /* @__PURE__ */ R(t, {
323
+ if (!S) return /* @__PURE__ */ F(t, {
306
324
  title: i("agents.title", "AI Agents"),
307
- children: /* @__PURE__ */ R(s, {
325
+ children: /* @__PURE__ */ F(s, {
308
326
  illustration: "empty-data",
309
327
  title: i("agents.detail.notFoundTitle", "Agent not found"),
310
328
  description: i("agents.detail.notFoundDescription", "It may have been removed, or you may not have access to it."),
311
- action: /* @__PURE__ */ R("button", {
329
+ action: /* @__PURE__ */ F("button", {
312
330
  type: "button",
313
331
  onClick: () => _("/agents"),
314
332
  className: "rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90",
@@ -316,100 +334,133 @@ function $() {
316
334
  })
317
335
  })
318
336
  });
319
- let K = x, q = W[K.kind] ?? S, J = K.policies ?? [], Y = J.filter((e) => e.isEnabled).length, X = J.reduce((e, t) => e + (t.triggerCount || 0), 0), Z = [];
320
- K.lastRunAt && Z.push({
321
- ts: new Date(K.lastRunAt).getTime(),
337
+ let J = S, he = V[J.kind] ?? w, Y = J.policies ?? [], ge = Y.filter((e) => e.isEnabled).length, _e = Y.reduce((e, t) => e + (t.triggerCount || 0), 0), X = [];
338
+ J.lastRunAt && X.push({
339
+ ts: new Date(J.lastRunAt).getTime(),
322
340
  item: {
323
341
  title: i("agents.detail.agentRun", "Agent run"),
324
342
  sub: i("agents.detail.agentRunSub", "Latest autonomous cycle"),
325
- meta: a(K.lastRunAt),
343
+ meta: a(J.lastRunAt),
326
344
  tone: "positive"
327
345
  }
328
346
  });
329
- for (let e of J) e.lastTriggeredAt && Z.push({
347
+ for (let e of Y) e.lastTriggeredAt && X.push({
330
348
  ts: new Date(e.lastTriggeredAt).getTime(),
331
349
  item: {
332
350
  title: e.name,
333
351
  sub: `${r(e.action)} · ${i("agents.detail.triggered", "Triggered {{count}}×", { count: e.triggerCount })}`,
334
352
  meta: a(e.lastTriggeredAt),
335
- tone: G(e.action)
353
+ tone: fe(e.action)
336
354
  }
337
355
  });
338
- Z.sort((e, t) => t.ts - e.ts);
339
- let $ = Z.map((e) => e.item);
340
- return /* @__PURE__ */ z(t, {
341
- title: K.name,
342
- description: `${i(H[K.kind] ?? "", r(K.kind))} ${i("agents.card.kindSuffix", "agent")}`,
343
- actions: /* @__PURE__ */ z("button", {
344
- type: "button",
345
- onClick: () => _("/agents"),
346
- 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",
347
- children: [
348
- /* @__PURE__ */ R(b, { className: "h-4 w-4" }),
349
- " ",
350
- i("agents.new.back", "Back")
351
- ]
356
+ let Z = q.data?.items ?? [];
357
+ for (let e of de(Z)) X.push({
358
+ ts: new Date(e.ranAt).getTime(),
359
+ item: {
360
+ title: i("agents.detail.decisionRun", "Decision run"),
361
+ sub: i("agents.detail.decisionRunSub", "{{total}} recommendations · {{proposed}} open · {{flagged}} flagged", {
362
+ total: e.total,
363
+ proposed: e.proposed,
364
+ flagged: e.flagged
365
+ }),
366
+ meta: a(e.ranAt),
367
+ tone: e.flagged > 0 ? "warning" : "positive"
368
+ }
369
+ });
370
+ X.sort((e, t) => t.ts - e.ts);
371
+ let Q = te.has(J.kind) ? J.status === "DISABLED" ? i("agents.detail.runDisabled", "Set the posture to Suggest-only to run this agent.") : null : i("agents.detail.runUnsupported", "This agent kind does not make decisions yet. Cost, renewal, vendor and discovery agents do."), ve = () => {
372
+ K(null), W(null), H.mutate(J.id, {
373
+ onSuccess: (e) => W(e),
374
+ onError: (e) => K(e instanceof Error && e.message ? e.message : i("agents.detail.runError", "The agent run failed."))
375
+ });
376
+ }, $ = X.map((e) => e.item);
377
+ return /* @__PURE__ */ I(t, {
378
+ title: J.name,
379
+ description: `${i(z[J.kind] ?? "", r(J.kind))} ${i("agents.card.kindSuffix", "agent")}`,
380
+ actions: /* @__PURE__ */ I("div", {
381
+ className: "flex flex-wrap gap-2",
382
+ children: [/* @__PURE__ */ I("button", {
383
+ type: "button",
384
+ onClick: () => _("/agents"),
385
+ 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",
386
+ children: [
387
+ /* @__PURE__ */ F(ie, { className: "h-4 w-4" }),
388
+ " ",
389
+ i("agents.new.back", "Back")
390
+ ]
391
+ }), /* @__PURE__ */ I("button", {
392
+ type: "button",
393
+ onClick: ve,
394
+ disabled: H.isPending || Q !== null,
395
+ title: Q ?? void 0,
396
+ "data-testid": "run-agent",
397
+ className: "inline-flex items-center gap-2 rounded-lg bg-action-primary-bg px-3 py-2 text-sm font-medium text-action-primary-text hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-50",
398
+ children: [/* @__PURE__ */ F(se, {
399
+ className: "h-4 w-4",
400
+ "aria-hidden": !0
401
+ }), H.isPending ? i("agents.detail.running", "Running…") : i("agents.detail.run", "Run agent")]
402
+ })]
352
403
  }),
353
404
  children: [
354
- /* @__PURE__ */ R(B, {
405
+ /* @__PURE__ */ F(L, {
355
406
  treatment: "glass",
356
- glow: K.status === "AUTONOMOUS",
407
+ glow: J.status === "AUTONOMOUS",
357
408
  className: "p-5",
358
- children: /* @__PURE__ */ z("div", {
409
+ children: /* @__PURE__ */ I("div", {
359
410
  className: "flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between",
360
- children: [/* @__PURE__ */ z("div", {
411
+ children: [/* @__PURE__ */ I("div", {
361
412
  className: "flex items-start gap-4",
362
- children: [/* @__PURE__ */ R("span", {
413
+ children: [/* @__PURE__ */ F("span", {
363
414
  className: "flex size-12 shrink-0 items-center justify-center rounded-xl bg-[var(--color-accent-soft)] text-text-primary",
364
- children: /* @__PURE__ */ R(q, { className: "h-6 w-6" })
365
- }), /* @__PURE__ */ z("div", {
415
+ children: /* @__PURE__ */ F(he, { className: "h-6 w-6" })
416
+ }), /* @__PURE__ */ I("div", {
366
417
  className: "min-w-0",
367
418
  children: [
368
- /* @__PURE__ */ z("div", {
419
+ /* @__PURE__ */ I("div", {
369
420
  className: "flex flex-wrap items-center gap-2",
370
- children: [/* @__PURE__ */ R("p", {
421
+ children: [/* @__PURE__ */ F("p", {
371
422
  className: "text-lg font-semibold text-text-primary",
372
- children: K.name
373
- }), /* @__PURE__ */ R(o, { status: K.status })]
423
+ children: J.name
424
+ }), /* @__PURE__ */ F(o, { status: J.status })]
374
425
  }),
375
- /* @__PURE__ */ z("p", {
426
+ /* @__PURE__ */ I("p", {
376
427
  className: "mt-1 flex items-center gap-1.5 text-xs text-text-secondary",
377
- children: [/* @__PURE__ */ R(w, {
428
+ children: [/* @__PURE__ */ F(E, {
378
429
  className: "h-3.5 w-3.5",
379
430
  "aria-hidden": !0
380
- }), K.lastRunAt ? i("agents.card.lastRun", "Last run {{when}}", { when: a(K.lastRunAt) }) : i("agents.card.neverRun", "Never run")]
431
+ }), J.lastRunAt ? i("agents.card.lastRun", "Last run {{when}}", { when: a(J.lastRunAt) }) : i("agents.card.neverRun", "Never run")]
381
432
  }),
382
- K.description && /* @__PURE__ */ R("p", {
433
+ J.description && /* @__PURE__ */ F("p", {
383
434
  className: "mt-2 max-w-2xl text-sm text-text-secondary",
384
- children: K.description
435
+ children: J.description
385
436
  })
386
437
  ]
387
438
  })]
388
- }), /* @__PURE__ */ z("div", {
439
+ }), /* @__PURE__ */ I("div", {
389
440
  className: "w-full sm:w-56 sm:shrink-0",
390
441
  children: [
391
- /* @__PURE__ */ R("label", {
442
+ /* @__PURE__ */ F("label", {
392
443
  htmlFor: "agent-posture",
393
444
  className: "mb-1 block text-xs font-medium text-text-secondary",
394
445
  children: i("agents.detail.operatingPosture", "Operating posture")
395
446
  }),
396
- /* @__PURE__ */ R("select", {
447
+ /* @__PURE__ */ F("select", {
397
448
  id: "agent-posture",
398
- value: K.status,
399
- disabled: D.isPending,
449
+ value: J.status,
450
+ disabled: k.isPending,
400
451
  onChange: (e) => {
401
- N(null), D.mutate({
402
- id: K.id,
452
+ M(null), k.mutate({
453
+ id: J.id,
403
454
  status: e.target.value
404
- }, { onError: (e) => N(e instanceof Error ? e.message : i("agents.detail.error", "Could not load this agent.")) });
455
+ }, { onError: (e) => M(e instanceof Error ? e.message : i("agents.detail.error", "Could not load this agent.")) });
405
456
  },
406
457
  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",
407
- children: /* @__PURE__ */ R(d, {
408
- options: V,
409
- currentStatus: K.status
458
+ children: /* @__PURE__ */ F(d, {
459
+ options: R,
460
+ currentStatus: J.status
410
461
  })
411
462
  }),
412
- /* @__PURE__ */ R("p", {
463
+ /* @__PURE__ */ F("p", {
413
464
  className: "mt-1.5 text-[11px] leading-snug text-text-secondary",
414
465
  children: A ? i("agents.detail.postureHint", "Disabled never acts · Suggest-only proposes · Autonomous acts within its policies.") : i("agents.detail.postureHintGated", "Disabled never acts · Suggest-only proposes. Autonomous mode is not available yet — agents only suggest, they never act on their own.")
415
466
  })
@@ -417,99 +468,153 @@ function $() {
417
468
  })]
418
469
  })
419
470
  }),
420
- M && /* @__PURE__ */ R("div", {
471
+ j && /* @__PURE__ */ F("div", {
472
+ 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",
473
+ children: j
474
+ }),
475
+ H.isPending && /* @__PURE__ */ F("div", {
476
+ role: "status",
477
+ className: "mt-4 rounded-lg border border-border-subtle bg-bg-sunken px-4 py-2 text-sm text-text-secondary",
478
+ children: i("agents.detail.runProgress", "Evaluating your active and trial subscriptions. Nothing is changed by this run.")
479
+ }),
480
+ U && /* @__PURE__ */ I("div", {
481
+ role: "status",
482
+ "data-testid": "run-result",
483
+ className: "mt-4 rounded-lg border border-status-success-text/30 bg-status-success-bg-subtle px-4 py-2 text-sm text-status-success-text",
484
+ children: [i("agents.detail.runResult", "Run finished: {{evaluated}} subscriptions evaluated, {{proposed}} recommendations to review, {{flagged}} held back by validation.", {
485
+ evaluated: U.evaluated,
486
+ proposed: U.proposed,
487
+ flagged: U.flagged
488
+ }), U.truncated && ` ${i("agents.detail.runTruncated", "Only part of the portfolio was evaluated in this run.")}`]
489
+ }),
490
+ G && /* @__PURE__ */ F("div", {
421
491
  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",
422
- children: M
492
+ children: G
493
+ }),
494
+ Q && /* @__PURE__ */ F("p", {
495
+ className: "mt-3 text-xs text-text-secondary",
496
+ children: Q
423
497
  }),
424
- /* @__PURE__ */ z("div", {
498
+ /* @__PURE__ */ I("div", {
425
499
  className: "mt-6 grid grid-cols-1 gap-4 sm:grid-cols-3",
426
500
  children: [
427
- /* @__PURE__ */ R(n, {
428
- icon: /* @__PURE__ */ R(k, { className: "h-5 w-5" }),
429
- value: J.length,
501
+ /* @__PURE__ */ F(n, {
502
+ icon: /* @__PURE__ */ F(oe, { className: "h-5 w-5" }),
503
+ value: Y.length,
430
504
  label: i("agents.detail.policies", "Policies")
431
505
  }),
432
- /* @__PURE__ */ R(n, {
433
- icon: /* @__PURE__ */ R(P, { className: "h-5 w-5" }),
434
- value: Y,
506
+ /* @__PURE__ */ F(n, {
507
+ icon: /* @__PURE__ */ F(N, { className: "h-5 w-5" }),
508
+ value: ge,
435
509
  label: i("agents.detail.enabled", "Enabled")
436
510
  }),
437
- /* @__PURE__ */ R(n, {
438
- icon: /* @__PURE__ */ R(I, { className: "h-5 w-5" }),
439
- value: X,
511
+ /* @__PURE__ */ F(n, {
512
+ icon: /* @__PURE__ */ F(le, { className: "h-5 w-5" }),
513
+ value: _e,
440
514
  label: i("agents.detail.totalTriggers", "Total triggers")
441
515
  })
442
516
  ]
443
517
  }),
444
- /* @__PURE__ */ z("div", {
518
+ /* @__PURE__ */ I("div", {
445
519
  className: "mt-8 grid grid-cols-1 gap-6 lg:grid-cols-3",
446
- children: [/* @__PURE__ */ R("div", {
520
+ children: [/* @__PURE__ */ F("div", {
447
521
  className: "lg:col-span-2",
448
- children: /* @__PURE__ */ R(m, {
522
+ children: /* @__PURE__ */ F(m, {
449
523
  title: i("agents.detail.policies", "Policies"),
450
524
  description: i("agents.detail.policiesDescription", "The autonomous rules that bound this agent"),
451
- action: /* @__PURE__ */ z("button", {
525
+ action: /* @__PURE__ */ I("button", {
452
526
  type: "button",
453
- onClick: () => U(!0),
527
+ onClick: () => B(!0),
454
528
  className: "inline-flex items-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",
455
529
  children: [
456
- /* @__PURE__ */ R(j, { className: "h-3.5 w-3.5" }),
530
+ /* @__PURE__ */ F(ce, { className: "h-3.5 w-3.5" }),
457
531
  " ",
458
532
  i("agents.detail.addPolicy", "Add policy")
459
533
  ]
460
534
  }),
461
- children: J.length === 0 ? /* @__PURE__ */ R(s, {
535
+ children: Y.length === 0 ? /* @__PURE__ */ F(s, {
462
536
  illustration: "empty-data",
463
537
  title: i("agents.detail.noPoliciesTitle", "No policies"),
464
538
  description: i("agents.detail.noPoliciesDescription", "Policies define what this agent may do autonomously, and what it must alert on."),
465
- action: /* @__PURE__ */ R("button", {
539
+ action: /* @__PURE__ */ F("button", {
466
540
  type: "button",
467
- onClick: () => U(!0),
541
+ onClick: () => B(!0),
468
542
  className: "rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90",
469
543
  children: i("agents.detail.addPolicy", "Add policy")
470
544
  })
471
- }) : /* @__PURE__ */ R("div", {
545
+ }) : /* @__PURE__ */ F("div", {
472
546
  className: "grid grid-cols-1 gap-3 sm:grid-cols-2",
473
- children: J.map((e) => /* @__PURE__ */ R(ee, { policy: e }, e.id))
547
+ children: Y.map((e) => /* @__PURE__ */ F(me, { policy: e }, e.id))
474
548
  })
475
549
  })
476
- }), /* @__PURE__ */ R("div", {
550
+ }), /* @__PURE__ */ F("div", {
477
551
  className: "lg:col-span-1",
478
- children: /* @__PURE__ */ R(m, {
552
+ children: /* @__PURE__ */ F(m, {
479
553
  title: i("agents.detail.runHistory", "Run history"),
480
554
  description: i("agents.detail.runHistoryDescription", "Recent agent activity"),
481
- children: /* @__PURE__ */ R(B, {
555
+ children: /* @__PURE__ */ F(L, {
482
556
  treatment: "metric",
483
557
  className: "p-5",
484
- children: $.length === 0 ? /* @__PURE__ */ z("div", {
558
+ children: $.length === 0 ? /* @__PURE__ */ I("div", {
485
559
  className: "flex flex-col items-center justify-center gap-2 py-6 text-center",
486
560
  children: [
487
- /* @__PURE__ */ R(O, {
561
+ /* @__PURE__ */ F(ae, {
488
562
  className: "h-8 w-8 text-text-secondary",
489
563
  "aria-hidden": !0
490
564
  }),
491
- /* @__PURE__ */ R("p", {
565
+ /* @__PURE__ */ F("p", {
492
566
  className: "text-sm font-medium text-text-primary",
493
567
  children: i("agents.detail.noRunsTitle", "No runs yet")
494
568
  }),
495
- /* @__PURE__ */ R("p", {
569
+ /* @__PURE__ */ F("p", {
496
570
  className: "text-xs text-text-secondary",
497
571
  children: i("agents.detail.noRunsDescription", "Activity appears here once the agent runs or a policy fires.")
498
572
  })
499
573
  ]
500
- }) : /* @__PURE__ */ R(h, { items: $ })
574
+ }) : /* @__PURE__ */ F(h, { items: $ })
501
575
  })
502
576
  })
503
577
  })]
504
578
  }),
505
- F && /* @__PURE__ */ R(Q, {
506
- agentId: K.id,
507
- onClose: () => U(!1)
579
+ /* @__PURE__ */ I(m, {
580
+ title: i("agents.detail.decisions", "Decisions"),
581
+ description: i("agents.detail.decisionsDescription", "Recommendations from this agent. Review, apply or dismiss each one."),
582
+ action: /* @__PURE__ */ I("button", {
583
+ type: "button",
584
+ onClick: () => _("/decisions"),
585
+ className: "inline-flex items-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",
586
+ children: [i("agents.detail.allDecisions", "All decisions"), /* @__PURE__ */ F(C, {
587
+ className: "h-3.5 w-3.5",
588
+ "aria-hidden": !0
589
+ })]
590
+ }),
591
+ children: [/* @__PURE__ */ F(re, { className: "mb-3" }), q.isLoading ? /* @__PURE__ */ F(p, {
592
+ className: "min-h-[120px]",
593
+ label: i("decisions.loading", "Loading decisions…")
594
+ }) : q.isError ? /* @__PURE__ */ F(b, {
595
+ message: q.error instanceof Error ? q.error.message : void 0,
596
+ onRetry: () => void q.refetch()
597
+ }) : Z.length === 0 ? /* @__PURE__ */ F(s, {
598
+ illustration: "empty-data",
599
+ title: i("agents.detail.noDecisionsTitle", "No decisions yet"),
600
+ description: Q ?? i("agents.detail.noDecisionsDescription", "Run the agent to get recommendations. A run only proposes; nothing changes until you apply.")
601
+ }) : /* @__PURE__ */ F("div", {
602
+ className: "grid grid-cols-1 gap-3 lg:grid-cols-2",
603
+ "data-testid": "agent-decisions",
604
+ children: Z.slice(0, 6).map((e) => /* @__PURE__ */ F(ne, {
605
+ decision: e,
606
+ hideAgent: !0
607
+ }, e.id))
608
+ })]
609
+ }),
610
+ P && /* @__PURE__ */ F(pe, {
611
+ agentId: J.id,
612
+ onClose: () => B(!1)
508
613
  })
509
614
  ]
510
615
  });
511
616
  }
512
617
  //#endregion
513
- export { $ as AgentDetailPage };
618
+ export { J as AgentDetailPage };
514
619
 
515
620
  //# sourceMappingURL=AgentDetailPage.js.map