@adoptai/genui-components 0.1.58 → 0.1.60

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 (54) hide show
  1. package/dist/builders/BlockForm.d.ts +5 -1
  2. package/dist/builders/BlockForm.d.ts.map +1 -1
  3. package/dist/builders/BuilderForm.d.ts +22 -1
  4. package/dist/builders/BuilderForm.d.ts.map +1 -1
  5. package/dist/builders/index.d.ts +1 -1
  6. package/dist/builders/index.d.ts.map +1 -1
  7. package/dist/composites/decision-card/resolver.cjs +289 -13
  8. package/dist/composites/decision-card/resolver.cjs.map +1 -1
  9. package/dist/composites/decision-card/resolver.d.ts +2 -1
  10. package/dist/composites/decision-card/resolver.d.ts.map +1 -1
  11. package/dist/composites/decision-card/resolver.js +289 -13
  12. package/dist/composites/decision-card/resolver.js.map +1 -1
  13. package/dist/composites/document-field-extraction/resolver.cjs +1920 -0
  14. package/dist/composites/document-field-extraction/resolver.cjs.map +1 -0
  15. package/dist/composites/document-field-extraction/resolver.js +1913 -0
  16. package/dist/composites/document-field-extraction/resolver.js.map +1 -0
  17. package/dist/composites/tabby-auth/resolver.cjs +597 -0
  18. package/dist/composites/tabby-auth/resolver.cjs.map +1 -0
  19. package/dist/composites/tabby-auth/resolver.d.ts +3 -0
  20. package/dist/composites/tabby-auth/resolver.d.ts.map +1 -0
  21. package/dist/composites/tabby-auth/resolver.js +595 -0
  22. package/dist/composites/tabby-auth/resolver.js.map +1 -0
  23. package/dist/composites/workflow-stepper/resolver.cjs +86 -18
  24. package/dist/composites/workflow-stepper/resolver.cjs.map +1 -1
  25. package/dist/composites/workflow-stepper/resolver.d.ts.map +1 -1
  26. package/dist/composites/workflow-stepper/resolver.js +86 -18
  27. package/dist/composites/workflow-stepper/resolver.js.map +1 -1
  28. package/dist/index.cjs +901 -63
  29. package/dist/index.cjs.map +1 -1
  30. package/dist/index.js +901 -63
  31. package/dist/index.js.map +1 -1
  32. package/dist/renderer.cjs +810 -45
  33. package/dist/renderer.cjs.map +1 -1
  34. package/dist/renderer.js +810 -45
  35. package/dist/renderer.js.map +1 -1
  36. package/dist/resolver.cjs +810 -45
  37. package/dist/resolver.cjs.map +1 -1
  38. package/dist/resolver.d.ts.map +1 -1
  39. package/dist/resolver.js +810 -45
  40. package/dist/resolver.js.map +1 -1
  41. package/dist/schemas/decision-card.d.ts +37 -0
  42. package/dist/schemas/decision-card.d.ts.map +1 -1
  43. package/dist/schemas/index.cjs +113 -8
  44. package/dist/schemas/index.cjs.map +1 -1
  45. package/dist/schemas/index.d.ts +155 -0
  46. package/dist/schemas/index.d.ts.map +1 -1
  47. package/dist/schemas/index.js +113 -8
  48. package/dist/schemas/index.js.map +1 -1
  49. package/dist/schemas/tabby-auth.d.ts +58 -0
  50. package/dist/schemas/tabby-auth.d.ts.map +1 -0
  51. package/dist/schemas/workflow-stepper.d.ts +60 -0
  52. package/dist/schemas/workflow-stepper.d.ts.map +1 -1
  53. package/dist/tool-definitions.json +135 -4
  54. package/package.json +1 -1
package/dist/renderer.js CHANGED
@@ -5217,7 +5217,32 @@ var workflowStepperSchema = z.object({
5217
5217
  n: z.number().int().positive().optional(),
5218
5218
  title: z.string(),
5219
5219
  sub: z.string().optional(),
5220
- status: z.enum(["done", "active", "review", "pending", "blocked", "failed"]),
5220
+ status: z.enum([
5221
+ "done",
5222
+ "active",
5223
+ "running",
5224
+ "review",
5225
+ "pending",
5226
+ "blocked",
5227
+ "failed"
5228
+ ]),
5229
+ // Optional quality-gate verdict for a step run by an executor (e.g. a
5230
+ // pipeline). Surfaces a subtle trust badge; flags hint at issues a human
5231
+ // should review (the full list lives in the escalation dock).
5232
+ eval: z.object({
5233
+ score: z.number().min(0).max(1).nullable().optional(),
5234
+ verdict: z.enum(["good", "bad"]).optional(),
5235
+ reasoning: z.string().optional(),
5236
+ judge_ok: z.boolean().optional(),
5237
+ data_quality_flags: z.array(
5238
+ z.object({
5239
+ field: z.string().optional(),
5240
+ issue: z.string().optional(),
5241
+ severity: z.enum(["low", "medium", "high"]).optional(),
5242
+ details: z.string().optional()
5243
+ })
5244
+ ).optional()
5245
+ }).optional(),
5221
5246
  assignees: z.array(
5222
5247
  z.object({
5223
5248
  name: z.string(),
@@ -5253,7 +5278,32 @@ var workflowStepperTool = {
5253
5278
  n: { type: "number", description: "Step number; defaults to index + 1" },
5254
5279
  title: { type: "string" },
5255
5280
  sub: { type: "string", description: "Short status caption, e.g. '7 accounts \xB7 2 exceptions'" },
5256
- status: { type: "string", enum: ["done", "active", "review", "pending", "blocked", "failed"] },
5281
+ status: {
5282
+ type: "string",
5283
+ enum: ["done", "active", "running", "review", "pending", "blocked", "failed"]
5284
+ },
5285
+ eval: {
5286
+ type: "object",
5287
+ description: "Optional quality-gate verdict for an executor-run step.",
5288
+ properties: {
5289
+ score: { type: "number" },
5290
+ verdict: { type: "string", enum: ["good", "bad"] },
5291
+ reasoning: { type: "string" },
5292
+ judge_ok: { type: "boolean" },
5293
+ data_quality_flags: {
5294
+ type: "array",
5295
+ items: {
5296
+ type: "object",
5297
+ properties: {
5298
+ field: { type: "string" },
5299
+ issue: { type: "string" },
5300
+ severity: { type: "string", enum: ["low", "medium", "high"] },
5301
+ details: { type: "string" }
5302
+ }
5303
+ }
5304
+ }
5305
+ }
5306
+ },
5257
5307
  assignees: {
5258
5308
  type: "array",
5259
5309
  maxItems: 6,
@@ -5475,7 +5525,14 @@ var decisionCardSchema = z.object({
5475
5525
  z.object({
5476
5526
  id: z.string().optional(),
5477
5527
  label: z.string(),
5478
- recommended: z.boolean().optional()
5528
+ recommended: z.boolean().optional(),
5529
+ value: z.number().optional(),
5530
+ adjust: z.object({
5531
+ min: z.number(),
5532
+ max: z.number(),
5533
+ step: z.number().optional(),
5534
+ unit: z.string().optional()
5535
+ }).optional()
5479
5536
  })
5480
5537
  ).min(1).max(5),
5481
5538
  source: z.object({
@@ -5483,7 +5540,8 @@ var decisionCardSchema = z.object({
5483
5540
  url: z.string().optional()
5484
5541
  }).optional(),
5485
5542
  resolved: z.object({
5486
- option: z.string()
5543
+ option: z.string(),
5544
+ value: z.number().optional()
5487
5545
  }).optional()
5488
5546
  });
5489
5547
  var decisionCardTool = {
@@ -5526,13 +5584,28 @@ var decisionCardTool = {
5526
5584
  type: "array",
5527
5585
  minItems: 1,
5528
5586
  maxItems: 5,
5529
- description: "Mutually-exclusive resolution choices; mark one `recommended` to make it primary",
5587
+ description: "Mutually-exclusive resolution choices; mark one `recommended` to make it primary. An option that carries a numeric figure the user may want to tune (e.g. 'Book reserve' at 50 units) should set `value` (your suggested figure) and `adjust` ({min,max[,step,unit]}) \u2014 the card then lets the user fine-tune the number within that range before confirming.",
5530
5588
  items: {
5531
5589
  type: "object",
5532
5590
  properties: {
5533
5591
  id: { type: "string" },
5534
5592
  label: { type: "string" },
5535
- recommended: { type: "boolean" }
5593
+ recommended: { type: "boolean" },
5594
+ value: {
5595
+ type: "number",
5596
+ description: "Suggested numeric figure for this option (the starting point of the adjuster)"
5597
+ },
5598
+ adjust: {
5599
+ type: "object",
5600
+ description: "Allow the user to tune `value` within this inclusive range before resolving",
5601
+ properties: {
5602
+ min: { type: "number" },
5603
+ max: { type: "number" },
5604
+ step: { type: "number", description: "Increment granularity; defaults to a sensible step for the range" },
5605
+ unit: { type: "string", description: "Short unit suffix shown after the number, e.g. 'units', '%', 'hrs'" }
5606
+ },
5607
+ required: ["min", "max"]
5608
+ }
5536
5609
  },
5537
5610
  required: ["label"]
5538
5611
  }
@@ -5549,7 +5622,8 @@ var decisionCardTool = {
5549
5622
  type: "object",
5550
5623
  description: "Pre-resolved state for transcript replay",
5551
5624
  properties: {
5552
- option: { type: "string" }
5625
+ option: { type: "string" },
5626
+ value: { type: "number", description: "Adjusted figure the user confirmed, when the option was adjustable" }
5553
5627
  },
5554
5628
  required: ["option"]
5555
5629
  }
@@ -5557,6 +5631,36 @@ var decisionCardTool = {
5557
5631
  required: ["type", "title", "question", "options"]
5558
5632
  }
5559
5633
  };
5634
+ var tabbyAuthSchema = z.object({
5635
+ type: z.literal("tabby-auth"),
5636
+ app: z.string(),
5637
+ url: z.string(),
5638
+ workspace: z.string().optional(),
5639
+ state: z.enum(["pending", "connected"]).optional(),
5640
+ ctaLabel: z.string().optional(),
5641
+ steps: z.array(z.string()).optional(),
5642
+ description: z.string().optional(),
5643
+ iconUrl: z.string().optional()
5644
+ });
5645
+ var tabbyAuthTool = {
5646
+ name: "render_tabby_auth",
5647
+ description: "Render a dedicated, trustworthy sign-in card when a harness skill needs the member to authenticate with a third-party app (e.g. Sage Intacct, Airbnb, an ERP) before a `call_web_api` request can proceed. Use this for the `login_required` path instead of a raw markdown link or a connect-integration card. `app` is the human display name (drives the title context, subtitle, and CTA). `url` is the login/short-link the prominent CTA opens in a new tab. `workspace` adds a subtitle suffix ('{app} \xB7 {workspace} workspace'). `state='pending'` (default) is the first-time connect; `state='connected'` is the verify/re-auth case (session already live) with a green badge and an Open deep-link. `steps` overrides the default numbered instructions; `description` is a one-line intro. The card title ('Authentication required') and the 'Credentials not stored by Adopt' trust footer are hardcoded brand constants \u2014 never supplied here.",
5648
+ input_schema: {
5649
+ type: "object",
5650
+ properties: {
5651
+ type: { type: "string", enum: ["tabby-auth"] },
5652
+ app: { type: "string" },
5653
+ url: { type: "string" },
5654
+ workspace: { type: "string" },
5655
+ state: { type: "string", enum: ["pending", "connected"] },
5656
+ ctaLabel: { type: "string" },
5657
+ steps: { type: "array", items: { type: "string" } },
5658
+ description: { type: "string" },
5659
+ iconUrl: { type: "string" }
5660
+ },
5661
+ required: ["type", "app", "url"]
5662
+ }
5663
+ };
5560
5664
 
5561
5665
  // src/schemas/index.ts
5562
5666
  var schemaRegistry = {
@@ -5618,7 +5722,8 @@ var schemaRegistry = {
5618
5722
  "pipeline-preview": { schema: pipelinePreviewSchema, tool: pipelinePreviewTool },
5619
5723
  "workflow-stepper": { schema: workflowStepperSchema, tool: workflowStepperTool },
5620
5724
  "document-field-extraction": { schema: documentFieldExtractionSchema, tool: documentFieldExtractionTool },
5621
- "decision-card": { schema: decisionCardSchema, tool: decisionCardTool }
5725
+ "decision-card": { schema: decisionCardSchema, tool: decisionCardTool },
5726
+ "tabby-auth": { schema: tabbyAuthSchema, tool: tabbyAuthTool }
5622
5727
  };
5623
5728
 
5624
5729
  // src/schemas/coercePayload.ts
@@ -6356,17 +6461,17 @@ function SparklineTableResolver(p) {
6356
6461
  // src/composites/heatmap-table/resolver.tsx
6357
6462
  init_theme();
6358
6463
  init_ThemeContext();
6359
- function heatColor(z60) {
6360
- const clamped = Math.max(-3, Math.min(3, z60));
6464
+ function heatColor(z61) {
6465
+ const clamped = Math.max(-3, Math.min(3, z61));
6361
6466
  const abs = Math.abs(clamped);
6362
6467
  const lightness = 95 - abs * 8;
6363
6468
  const hue = clamped >= 0 ? 142 : 0;
6364
6469
  return `hsl(${hue} 60% ${lightness}%)`;
6365
6470
  }
6366
- function heatTextColor(z60) {
6367
- const abs = Math.abs(z60);
6368
- if (abs > 2) return z60 >= 0 ? "#14532d" : "#7f1d1d";
6369
- if (abs > 1) return z60 >= 0 ? "#166534" : "#991b1b";
6471
+ function heatTextColor(z61) {
6472
+ const abs = Math.abs(z61);
6473
+ if (abs > 2) return z61 >= 0 ? "#14532d" : "#7f1d1d";
6474
+ if (abs > 1) return z61 >= 0 ? "#166534" : "#991b1b";
6370
6475
  return "var(--foreground)";
6371
6476
  }
6372
6477
  var th2 = {
@@ -17424,6 +17529,8 @@ var STATUS_COLORS3 = {
17424
17529
  done: "#15803d",
17425
17530
  active: "",
17426
17531
  // filled from theme ACCENT at render time
17532
+ running: "",
17533
+ // filled from theme ACCENT at render time (executor in flight)
17427
17534
  review: "#f59e0b",
17428
17535
  pending: "#9ca3af",
17429
17536
  blocked: "#b45309",
@@ -17432,6 +17539,7 @@ var STATUS_COLORS3 = {
17432
17539
  var STATUS_LABELS = {
17433
17540
  done: "Complete",
17434
17541
  active: "In progress",
17542
+ running: "Running",
17435
17543
  review: "In review",
17436
17544
  pending: "Pending",
17437
17545
  blocked: "Blocked",
@@ -17535,6 +17643,26 @@ function IndexDot({ step, index, accent }) {
17535
17643
  if (step.status === "failed") {
17536
17644
  return /* @__PURE__ */ jsx("div", { style: __spreadProps(__spreadValues({}, base), { background: "#dc2626", color: "white" }), children: /* @__PURE__ */ jsx("span", { style: { fontSize: 10 }, children: "!" }) });
17537
17645
  }
17646
+ if (step.status === "running") {
17647
+ return /* @__PURE__ */ jsxs("div", { style: __spreadProps(__spreadValues({}, base), { position: "relative", background: `${accent}1f`, color: accent }), children: [
17648
+ /* @__PURE__ */ jsx(
17649
+ "span",
17650
+ {
17651
+ className: "wfs-anim",
17652
+ "aria-hidden": "true",
17653
+ style: {
17654
+ position: "absolute",
17655
+ inset: 0,
17656
+ borderRadius: "50%",
17657
+ border: `1.5px solid ${accent}33`,
17658
+ borderTopColor: accent,
17659
+ animation: "wfsSpin 0.8s linear infinite"
17660
+ }
17661
+ }
17662
+ ),
17663
+ /* @__PURE__ */ jsx("span", { style: { fontSize: 9 }, children: n })
17664
+ ] });
17665
+ }
17538
17666
  if (step.status === "active") {
17539
17667
  return /* @__PURE__ */ jsx("div", { style: __spreadProps(__spreadValues({}, base), { background: accent, color: "white" }), children: n });
17540
17668
  }
@@ -17543,6 +17671,44 @@ function IndexDot({ step, index, accent }) {
17543
17671
  }
17544
17672
  return /* @__PURE__ */ jsx("div", { style: __spreadProps(__spreadValues({}, base), { background: "#f2f2f2", color: "#9ca3af" }), children: n });
17545
17673
  }
17674
+ function EvalBadge({ step }) {
17675
+ var _a;
17676
+ const ev = step.eval;
17677
+ if (!ev || ev.judge_ok === false) return null;
17678
+ const score = typeof ev.score === "number" ? ev.score : null;
17679
+ const flags = (_a = ev.data_quality_flags) != null ? _a : [];
17680
+ const bad = ev.verdict === "bad" || score !== null && score < 0.8;
17681
+ const tip = flags.length > 0 ? flags.map((f) => {
17682
+ var _a2;
17683
+ return `${(_a2 = f.severity) != null ? _a2 : "?"}: ${f.details || f.issue || f.field || "issue"}`;
17684
+ }).join("\n") : ev.reasoning || void 0;
17685
+ const label = score !== null ? score.toFixed(2) : bad ? "flagged" : "ok";
17686
+ return /* @__PURE__ */ jsxs(
17687
+ "span",
17688
+ {
17689
+ title: tip,
17690
+ "data-testid": `workflow-stepper-eval-${step.id}`,
17691
+ style: {
17692
+ display: "inline-flex",
17693
+ alignItems: "center",
17694
+ gap: 3,
17695
+ fontSize: 9,
17696
+ fontWeight: 700,
17697
+ padding: "1px 6px",
17698
+ borderRadius: 9999,
17699
+ background: bad ? "#fff7ed" : "#dcfce7",
17700
+ color: bad ? "#b45309" : "#15803d",
17701
+ whiteSpace: "nowrap",
17702
+ flexShrink: 0
17703
+ },
17704
+ children: [
17705
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: bad ? "\u26A0" : "\u2713" }),
17706
+ label,
17707
+ flags.length > 0 ? ` \xB7 ${flags.length}` : ""
17708
+ ]
17709
+ }
17710
+ );
17711
+ }
17546
17712
  var CARD_MIN = 132;
17547
17713
  var CARD_GAP = 16;
17548
17714
  var AUTO_COMPACT_BELOW = 360;
@@ -17567,6 +17733,7 @@ var KEYFRAMES = `
17567
17733
  @keyframes wfsLampPulse{0%,100%{box-shadow:0 0 0 0 var(--wfs-accent,#6366f1)73}50%{box-shadow:0 0 0 4px transparent}}
17568
17734
  @keyframes wfsRise{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
17569
17735
  @keyframes wfsShimmer{0%{background-position:-200px 0}100%{background-position:calc(200px + 100%) 0}}
17736
+ @keyframes wfsSpin{to{transform:rotate(360deg)}}
17570
17737
  .wfs-rise{animation:wfsRise 0.32s cubic-bezier(0.22,1,0.36,1) both}
17571
17738
  @media (prefers-reduced-motion: reduce){
17572
17739
  .wfs-anim,.wfs-rise,.wfs-shim{animation:none !important}
@@ -17647,7 +17814,7 @@ function WorkflowStepperRenderer({
17647
17814
  const steps = (_a = data.steps) != null ? _a : [];
17648
17815
  const activeStepId = (_d = (_c = data.active_step) != null ? _c : (_b = steps.find((s) => s.status === "active")) == null ? void 0 : _b.id) != null ? _d : null;
17649
17816
  const interactive = typeof onSelectStep === "function";
17650
- const statusColor3 = (s) => s === "active" ? ACCENT2 : STATUS_COLORS3[s];
17817
+ const statusColor3 = (s) => s === "active" || s === "running" ? ACCENT2 : STATUS_COLORS3[s];
17651
17818
  const doneCount = steps.filter((s) => s.status === "done").length;
17652
17819
  const rootRef = React45.useRef(null);
17653
17820
  const containerW = useContainerWidth(rootRef);
@@ -17875,6 +18042,7 @@ function WorkflowStepperRenderer({
17875
18042
  var _a2;
17876
18043
  const isSelected = selectedStep === step.id;
17877
18044
  const isActive = step.status === "active";
18045
+ const isRunning = step.status === "running";
17878
18046
  const reached = step.status !== "pending";
17879
18047
  const clickable = interactive && reached;
17880
18048
  const color = statusColor3(step.status);
@@ -17971,36 +18139,41 @@ function WorkflowStepperRenderer({
17971
18139
  }
17972
18140
  }
17973
18141
  ),
17974
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between" }, children: [
17975
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
18142
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 4 }, children: [
18143
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6, minWidth: 0 }, children: [
17976
18144
  /* @__PURE__ */ jsx(IndexDot, { step, index: i, accent: ACCENT2 }),
17977
18145
  /* @__PURE__ */ jsx(
17978
18146
  "span",
17979
18147
  {
17980
- className: isActive ? "wfs-anim" : void 0,
18148
+ className: isActive || isRunning ? "wfs-anim" : void 0,
17981
18149
  style: {
17982
18150
  width: 6,
17983
18151
  height: 6,
17984
18152
  borderRadius: "50%",
17985
18153
  background: color,
17986
- animation: isActive ? "wfsLampPulse 1.8s ease-in-out infinite" : "none"
18154
+ flexShrink: 0,
18155
+ animation: isActive || isRunning ? "wfsLampPulse 1.8s ease-in-out infinite" : "none"
17987
18156
  }
17988
18157
  }
17989
18158
  )
17990
18159
  ] }),
17991
- /* @__PURE__ */ jsx(
17992
- "span",
17993
- {
17994
- style: {
17995
- fontSize: 9,
17996
- fontWeight: 600,
17997
- letterSpacing: "0.05em",
17998
- textTransform: "uppercase",
17999
- color
18000
- },
18001
- children: STATUS_LABELS[step.status]
18002
- }
18003
- )
18160
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 4, minWidth: 0 }, children: [
18161
+ /* @__PURE__ */ jsx(EvalBadge, { step }),
18162
+ /* @__PURE__ */ jsx(
18163
+ "span",
18164
+ {
18165
+ style: {
18166
+ fontSize: 9,
18167
+ fontWeight: 600,
18168
+ letterSpacing: "0.05em",
18169
+ textTransform: "uppercase",
18170
+ color,
18171
+ whiteSpace: "nowrap"
18172
+ },
18173
+ children: STATUS_LABELS[step.status]
18174
+ }
18175
+ )
18176
+ ] })
18004
18177
  ] }),
18005
18178
  /* @__PURE__ */ jsxs("div", { style: { minWidth: 0 }, children: [
18006
18179
  /* @__PURE__ */ jsx(
@@ -18190,12 +18363,14 @@ var BADGE_TITLE = {
18190
18363
  var BADGE_STYLE = {
18191
18364
  SC: { bg: "#dcfce7", fg: "#15803d" },
18192
18365
  CN: { bg: "#eff6ff", fg: "#0364ff" },
18366
+ // theme-ok (SECONDARY)
18193
18367
  AB: { bg: "#fff7ed", fg: "#92400e" },
18194
18368
  SW: { bg: "#fef2f2", fg: "#dc2626" }
18195
18369
  };
18196
18370
  var STATE_DOT = {
18197
18371
  ok: "#15803d",
18198
18372
  corrected: "#0364ff",
18373
+ // theme-ok (SECONDARY)
18199
18374
  missing: "#dc2626",
18200
18375
  warn: "#f59e0b"
18201
18376
  };
@@ -18558,6 +18733,7 @@ var BADGE_DOT = {
18558
18733
  missing: "#dc2626",
18559
18734
  red: "#dc2626",
18560
18735
  corrected: "#0364ff"
18736
+ // theme-ok (SECONDARY)
18561
18737
  };
18562
18738
  function FieldDetails({
18563
18739
  summary,
@@ -19738,8 +19914,15 @@ function useContainerWidth2(ref) {
19738
19914
  var KEYFRAMES2 = `
19739
19915
  @keyframes dcRise{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
19740
19916
  .dc-rise{animation:dcRise 0.28s cubic-bezier(0.22,1,0.36,1) both}
19917
+ .dc-range{-webkit-appearance:none;appearance:none;width:100%;height:4px;border-radius:9999px;outline:none;cursor:pointer;background:transparent}
19918
+ .dc-range::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:16px;height:16px;border-radius:50%;background:white;border:2px solid var(--dc-thumb,#ff5000);box-shadow:0 1px 3px rgba(0,0,0,0.18);cursor:grab;transition:transform 0.12s}
19919
+ .dc-range::-webkit-slider-thumb:hover{transform:scale(1.12)}
19920
+ .dc-range:active::-webkit-slider-thumb{cursor:grabbing}
19921
+ .dc-range::-moz-range-thumb{width:12px;height:12px;border-radius:50%;background:white;border:2px solid var(--dc-thumb,#ff5000);box-shadow:0 1px 3px rgba(0,0,0,0.18);cursor:grab}
19922
+ .dc-range::-moz-range-track{height:4px;border-radius:9999px;background:transparent}
19741
19923
  @media (prefers-reduced-motion: reduce){
19742
19924
  .dc-rise{animation:none !important;opacity:1 !important;transform:none !important}
19925
+ .dc-range::-webkit-slider-thumb{transition:none}
19743
19926
  }`;
19744
19927
  function SparkCheck({ size, color }) {
19745
19928
  return /* @__PURE__ */ jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx(
@@ -19785,17 +19968,239 @@ function FlagPill({ flag }) {
19785
19968
  }
19786
19969
  );
19787
19970
  }
19971
+ function formatFigure(value, unit) {
19972
+ const body = Number.isInteger(value) ? `${value}` : `${Math.round(value * 100) / 100}`;
19973
+ if (!unit) return body;
19974
+ return unit === "%" ? `${body}%` : `${body} ${unit}`;
19975
+ }
19976
+ function clampToRange(raw, adjust) {
19977
+ var _a;
19978
+ const step = (_a = adjust.step) != null ? _a : Number.isInteger(adjust.min) && Number.isInteger(adjust.max) ? 1 : (adjust.max - adjust.min) / 100;
19979
+ const snapped = Math.round((raw - adjust.min) / step) * step + adjust.min;
19980
+ const fixed = Math.round(snapped * 1e6) / 1e6;
19981
+ return Math.min(adjust.max, Math.max(adjust.min, fixed));
19982
+ }
19983
+ function ValueAdjuster({
19984
+ option,
19985
+ accent,
19986
+ border,
19987
+ muted,
19988
+ onConfirm,
19989
+ onBack
19990
+ }) {
19991
+ var _a, _b;
19992
+ const adjust = option.adjust;
19993
+ const suggested = clampToRange((_a = option.value) != null ? _a : adjust.min, adjust);
19994
+ const [value, setValue] = React45.useState(suggested);
19995
+ const [text, setText] = React45.useState(String(suggested));
19996
+ const step = (_b = adjust.step) != null ? _b : Number.isInteger(adjust.min) && Number.isInteger(adjust.max) ? 1 : (adjust.max - adjust.min) / 100;
19997
+ const pct = adjust.max > adjust.min ? (value - adjust.min) / (adjust.max - adjust.min) * 100 : 0;
19998
+ const suggestedPct = adjust.max > adjust.min ? (suggested - adjust.min) / (adjust.max - adjust.min) * 100 : 0;
19999
+ const moved = value !== suggested;
20000
+ const commit = (raw) => {
20001
+ const v = clampToRange(raw, adjust);
20002
+ setValue(v);
20003
+ setText(String(v));
20004
+ };
20005
+ return /* @__PURE__ */ jsxs(
20006
+ "div",
20007
+ {
20008
+ className: "dc-rise",
20009
+ "data-testid": "decision-card-adjuster",
20010
+ style: {
20011
+ display: "flex",
20012
+ flexDirection: "column",
20013
+ gap: 12,
20014
+ border: `1px solid ${border}`,
20015
+ borderRadius: 10,
20016
+ padding: "12px 14px",
20017
+ background: "#fafafa"
20018
+ },
20019
+ children: [
20020
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "baseline", gap: 8 }, children: [
20021
+ /* @__PURE__ */ jsxs("span", { style: { fontSize: 11, fontWeight: 700, textTransform: "uppercase", letterSpacing: "0.06em", color: muted }, children: [
20022
+ "Adjust \xB7 ",
20023
+ option.label
20024
+ ] }),
20025
+ /* @__PURE__ */ jsx("span", { style: { flex: 1 } }),
20026
+ /* @__PURE__ */ jsx(
20027
+ "button",
20028
+ {
20029
+ type: "button",
20030
+ onClick: onBack,
20031
+ "data-testid": "decision-card-adjust-back",
20032
+ style: { border: "none", background: "none", padding: 0, cursor: "pointer", fontSize: 12, fontWeight: 600, color: muted },
20033
+ children: "Back"
20034
+ }
20035
+ )
20036
+ ] }),
20037
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "baseline", gap: 6 }, children: [
20038
+ /* @__PURE__ */ jsx(
20039
+ "input",
20040
+ {
20041
+ value: text,
20042
+ onChange: (e) => {
20043
+ setText(e.target.value);
20044
+ const n = Number(e.target.value);
20045
+ if (Number.isFinite(n)) setValue(clampToRange(n, adjust));
20046
+ },
20047
+ onBlur: () => commit(Number(text) || suggested),
20048
+ onKeyDown: (e) => {
20049
+ if (e.key === "Enter") {
20050
+ const v = clampToRange(Number(text) || suggested, adjust);
20051
+ commit(v);
20052
+ onConfirm(v);
20053
+ } else if (e.key === "ArrowUp") {
20054
+ e.preventDefault();
20055
+ commit(value + step);
20056
+ } else if (e.key === "ArrowDown") {
20057
+ e.preventDefault();
20058
+ commit(value - step);
20059
+ }
20060
+ },
20061
+ inputMode: "decimal",
20062
+ "aria-label": `${option.label} value`,
20063
+ "data-testid": "decision-card-adjust-input",
20064
+ style: {
20065
+ width: `${Math.max(3, String(text).length + 1)}ch`,
20066
+ fontSize: 26,
20067
+ fontWeight: 700,
20068
+ fontVariantNumeric: "tabular-nums",
20069
+ letterSpacing: "-0.02em",
20070
+ color: "var(--foreground)",
20071
+ border: "none",
20072
+ borderBottom: `2px solid ${accent}`,
20073
+ background: "transparent",
20074
+ outline: "none",
20075
+ padding: 0
20076
+ }
20077
+ }
20078
+ ),
20079
+ adjust.unit && /* @__PURE__ */ jsx("span", { style: { fontSize: 13, fontWeight: 600, color: muted }, children: adjust.unit }),
20080
+ moved && /* @__PURE__ */ jsxs(
20081
+ "button",
20082
+ {
20083
+ type: "button",
20084
+ onClick: () => commit(suggested),
20085
+ "data-testid": "decision-card-adjust-reset",
20086
+ style: {
20087
+ marginLeft: 8,
20088
+ border: "none",
20089
+ background: "none",
20090
+ padding: 0,
20091
+ cursor: "pointer",
20092
+ fontSize: 11.5,
20093
+ fontWeight: 600,
20094
+ color: muted,
20095
+ textDecoration: "underline",
20096
+ textUnderlineOffset: 2
20097
+ },
20098
+ children: [
20099
+ "Reset to suggested (",
20100
+ formatFigure(suggested, adjust.unit),
20101
+ ")"
20102
+ ]
20103
+ }
20104
+ )
20105
+ ] }),
20106
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
20107
+ /* @__PURE__ */ jsxs("div", { style: { position: "relative", height: 16, display: "flex", alignItems: "center" }, children: [
20108
+ /* @__PURE__ */ jsx(
20109
+ "div",
20110
+ {
20111
+ "aria-hidden": "true",
20112
+ style: {
20113
+ position: "absolute",
20114
+ left: 0,
20115
+ right: 0,
20116
+ height: 4,
20117
+ borderRadius: 9999,
20118
+ background: `linear-gradient(to right, ${accent} ${pct}%, #e8e8e8 ${pct}%)`
20119
+ }
20120
+ }
20121
+ ),
20122
+ moved && /* @__PURE__ */ jsx(
20123
+ "div",
20124
+ {
20125
+ "aria-hidden": "true",
20126
+ title: `Suggested: ${formatFigure(suggested, adjust.unit)}`,
20127
+ style: {
20128
+ position: "absolute",
20129
+ left: `${suggestedPct}%`,
20130
+ transform: "translateX(-50%)",
20131
+ width: 2,
20132
+ height: 10,
20133
+ borderRadius: 1,
20134
+ background: muted,
20135
+ opacity: 0.55
20136
+ }
20137
+ }
20138
+ ),
20139
+ /* @__PURE__ */ jsx(
20140
+ "input",
20141
+ {
20142
+ type: "range",
20143
+ className: "dc-range",
20144
+ min: adjust.min,
20145
+ max: adjust.max,
20146
+ step,
20147
+ value,
20148
+ onChange: (e) => commit(Number(e.target.value)),
20149
+ "aria-label": `${option.label} slider`,
20150
+ "data-testid": "decision-card-adjust-slider",
20151
+ style: { position: "relative", ["--dc-thumb"]: accent }
20152
+ }
20153
+ )
20154
+ ] }),
20155
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", fontSize: 10.5, fontWeight: 600, color: muted, fontVariantNumeric: "tabular-nums" }, children: [
20156
+ /* @__PURE__ */ jsx("span", { children: formatFigure(adjust.min, adjust.unit) }),
20157
+ /* @__PURE__ */ jsx("span", { children: formatFigure(adjust.max, adjust.unit) })
20158
+ ] })
20159
+ ] }),
20160
+ /* @__PURE__ */ jsxs(
20161
+ "button",
20162
+ {
20163
+ type: "button",
20164
+ onClick: () => onConfirm(value),
20165
+ "data-testid": "decision-card-adjust-confirm",
20166
+ style: {
20167
+ alignSelf: "flex-start",
20168
+ border: `1px solid ${accent}`,
20169
+ background: accent,
20170
+ color: "white",
20171
+ borderRadius: 8,
20172
+ fontSize: 13,
20173
+ fontWeight: 600,
20174
+ padding: "9px 16px",
20175
+ cursor: "pointer",
20176
+ fontVariantNumeric: "tabular-nums",
20177
+ transition: "opacity 0.15s"
20178
+ },
20179
+ onMouseEnter: (e) => e.currentTarget.style.opacity = "0.88",
20180
+ onMouseLeave: (e) => e.currentTarget.style.opacity = "1",
20181
+ children: [
20182
+ option.label,
20183
+ " \xB7 ",
20184
+ formatFigure(value, adjust.unit)
20185
+ ]
20186
+ }
20187
+ )
20188
+ ]
20189
+ }
20190
+ );
20191
+ }
19788
20192
  function DecisionCardRenderer({
19789
20193
  data,
19790
20194
  resolved = null,
19791
20195
  onResolve,
19792
20196
  onOpenSource
19793
20197
  }) {
19794
- var _a, _b;
20198
+ var _a, _b, _c;
19795
20199
  const { BORDER: BORDER4, MUTED: MUTED2, ACCENT: ACCENT2, ACCENT_SOFT: ACCENT_SOFT2 } = useTheme();
19796
20200
  const rootRef = React45.useRef(null);
19797
20201
  const width = useContainerWidth2(rootRef);
19798
20202
  const stacked = width > 0 && width < STACK_BELOW;
20203
+ const [adjustingIdx, setAdjustingIdx] = React45.useState(null);
19799
20204
  const options = (_a = data.options) != null ? _a : [];
19800
20205
  const recommendedIdx = Math.max(
19801
20206
  0,
@@ -19950,7 +20355,20 @@ function DecisionCardRenderer({
19950
20355
  ]
19951
20356
  }
19952
20357
  ) : /* @__PURE__ */ jsxs(Fragment, { children: [
19953
- /* @__PURE__ */ jsx(
20358
+ adjustingIdx != null && ((_b = options[adjustingIdx]) == null ? void 0 : _b.adjust) ? /* @__PURE__ */ jsx(
20359
+ ValueAdjuster,
20360
+ {
20361
+ option: options[adjustingIdx],
20362
+ accent: ACCENT2,
20363
+ border: BORDER4,
20364
+ muted: MUTED2,
20365
+ onBack: () => setAdjustingIdx(null),
20366
+ onConfirm: (value) => {
20367
+ setAdjustingIdx(null);
20368
+ onResolve == null ? void 0 : onResolve(options[adjustingIdx].label, value);
20369
+ }
20370
+ }
20371
+ ) : /* @__PURE__ */ jsx(
19954
20372
  "div",
19955
20373
  {
19956
20374
  style: {
@@ -19960,15 +20378,21 @@ function DecisionCardRenderer({
19960
20378
  gap: 8
19961
20379
  },
19962
20380
  children: options.map((opt, idx) => {
19963
- var _a2;
20381
+ var _a2, _b2;
19964
20382
  const primary = idx === recommendedIdx;
19965
- return /* @__PURE__ */ jsx(
20383
+ const adjustable = Boolean(opt.adjust);
20384
+ return /* @__PURE__ */ jsxs(
19966
20385
  "button",
19967
20386
  {
19968
20387
  type: "button",
19969
- onClick: () => onResolve == null ? void 0 : onResolve(opt.label),
20388
+ onClick: () => adjustable ? setAdjustingIdx(idx) : onResolve == null ? void 0 : onResolve(opt.label),
20389
+ "data-adjustable": adjustable || void 0,
19970
20390
  style: {
19971
20391
  width: stacked ? "100%" : "auto",
20392
+ display: "inline-flex",
20393
+ alignItems: "center",
20394
+ justifyContent: stacked ? "flex-start" : "center",
20395
+ gap: 7,
19972
20396
  textAlign: stacked ? "left" : "center",
19973
20397
  border: `1px solid ${primary ? ACCENT2 : BORDER4}`,
19974
20398
  background: primary ? ACCENT2 : "white",
@@ -19996,7 +20420,28 @@ function DecisionCardRenderer({
19996
20420
  e.currentTarget.style.background = "white";
19997
20421
  }
19998
20422
  },
19999
- children: opt.label
20423
+ children: [
20424
+ opt.label,
20425
+ adjustable && typeof opt.value === "number" && /* @__PURE__ */ jsxs(
20426
+ "span",
20427
+ {
20428
+ style: {
20429
+ fontSize: 11.5,
20430
+ fontWeight: 700,
20431
+ fontVariantNumeric: "tabular-nums",
20432
+ padding: "1px 7px",
20433
+ borderRadius: 9999,
20434
+ background: primary ? "rgba(255,255,255,0.22)" : "#f2f2f2",
20435
+ color: primary ? "white" : MUTED2,
20436
+ lineHeight: 1.5
20437
+ },
20438
+ children: [
20439
+ formatFigure(opt.value, (_b2 = opt.adjust) == null ? void 0 : _b2.unit),
20440
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", style: { marginLeft: 4, opacity: 0.8 }, children: "\u270E" })
20441
+ ]
20442
+ }
20443
+ )
20444
+ ]
20000
20445
  },
20001
20446
  (_a2 = opt.id) != null ? _a2 : opt.label
20002
20447
  );
@@ -20035,7 +20480,7 @@ function DecisionCardRenderer({
20035
20480
  strokeLinejoin: "round"
20036
20481
  }
20037
20482
  ) }),
20038
- (_b = data.source.label) != null ? _b : "View source for this figure"
20483
+ (_c = data.source.label) != null ? _c : "View source for this figure"
20039
20484
  ]
20040
20485
  }
20041
20486
  )
@@ -20044,20 +20489,27 @@ function DecisionCardRenderer({
20044
20489
  }
20045
20490
  );
20046
20491
  }
20492
+ function composeResolution(p, option, value) {
20493
+ var _a, _b, _c;
20494
+ if (value == null) return option;
20495
+ const unit = (_c = (_b = ((_a = p.options) != null ? _a : []).find((o) => o.label === option)) == null ? void 0 : _b.adjust) == null ? void 0 : _c.unit;
20496
+ return `${option} \xB7 ${formatFigure(value, unit)}`;
20497
+ }
20047
20498
  function DecisionCardResolver(p) {
20048
- var _a, _b, _c, _d;
20499
+ var _a, _b;
20049
20500
  const { resolvedDecisions, onDecisionResolve, onDecisionSource } = useGenUIInteraction();
20050
20501
  const decisionId = (_a = p.id) != null ? _a : p.title;
20051
20502
  const hostResolved = resolvedDecisions == null ? void 0 : resolvedDecisions[decisionId];
20052
- const initial = (_c = hostResolved != null ? hostResolved : (_b = p.resolved) == null ? void 0 : _b.option) != null ? _c : null;
20503
+ const initial = hostResolved != null ? hostResolved : p.resolved ? composeResolution(p, p.resolved.option, p.resolved.value) : null;
20053
20504
  const [localResolved, setLocalResolved] = React45.useState(initial);
20054
20505
  React45.useEffect(() => {
20055
20506
  if (hostResolved !== void 0) setLocalResolved(hostResolved);
20056
20507
  }, [hostResolved]);
20057
20508
  const resolved = hostResolved != null ? hostResolved : localResolved;
20058
- const handleResolve = (option) => {
20059
- setLocalResolved(option);
20060
- onDecisionResolve == null ? void 0 : onDecisionResolve(decisionId, option);
20509
+ const handleResolve = (option, value) => {
20510
+ const resolution = composeResolution(p, option, value);
20511
+ setLocalResolved(resolution);
20512
+ onDecisionResolve == null ? void 0 : onDecisionResolve(decisionId, resolution);
20061
20513
  };
20062
20514
  const handleSource = () => {
20063
20515
  var _a2;
@@ -20066,7 +20518,7 @@ function DecisionCardResolver(p) {
20066
20518
  window.open(p.source.url, "_blank", "noopener,noreferrer");
20067
20519
  }
20068
20520
  };
20069
- return /* @__PURE__ */ jsx(ComponentActions, { filename: (_d = p.title) != null ? _d : "decision-card", children: /* @__PURE__ */ jsx(
20521
+ return /* @__PURE__ */ jsx(ComponentActions, { filename: (_b = p.title) != null ? _b : "decision-card", children: /* @__PURE__ */ jsx(
20070
20522
  DecisionCardRenderer,
20071
20523
  {
20072
20524
  data: p,
@@ -20076,6 +20528,317 @@ function DecisionCardResolver(p) {
20076
20528
  }
20077
20529
  ) });
20078
20530
  }
20531
+ init_ThemeContext();
20532
+ var CONNECTED_GREEN3 = "#15803d";
20533
+ var CONNECTED_GREEN_BG = "#dcfce7";
20534
+ var PENDING_AMBER = "#92400e";
20535
+ var PENDING_AMBER_BG = "#fff7ed";
20536
+ var CARD_TITLE = "Authentication required";
20537
+ var TRUST_FOOTER = "Credentials not stored by Adopt";
20538
+ var DEFAULT_STEPS = (app, ctaLabel, connected) => connected ? [
20539
+ `Click ${ctaLabel} below to open ${app} in a new tab.`,
20540
+ "Confirm you are signed in \u2014 re-authenticate if prompted.",
20541
+ "Return here \u2014 the request continues automatically."
20542
+ ] : [
20543
+ `Click ${ctaLabel} below to open the sign-in page.`,
20544
+ `Sign in with your ${app} credentials \u2014 SSO is supported.`,
20545
+ "Return here \u2014 the request resumes automatically."
20546
+ ];
20547
+ function humanizeApp(raw) {
20548
+ const v = raw.trim();
20549
+ if (!v) return v;
20550
+ const looksLikeSlug = /^[a-z0-9]+([_-][a-z0-9]+)*$/.test(v);
20551
+ if (!looksLikeSlug) return v;
20552
+ return v.split(/[_-]+/).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
20553
+ }
20554
+ function ShieldIcon({ color }) {
20555
+ return /* @__PURE__ */ jsxs(
20556
+ "svg",
20557
+ {
20558
+ width: "13",
20559
+ height: "13",
20560
+ viewBox: "0 0 24 24",
20561
+ fill: "none",
20562
+ stroke: color,
20563
+ strokeWidth: "2",
20564
+ strokeLinecap: "round",
20565
+ strokeLinejoin: "round",
20566
+ "aria-hidden": "true",
20567
+ style: { flexShrink: 0 },
20568
+ children: [
20569
+ /* @__PURE__ */ jsx("path", { d: "M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" }),
20570
+ /* @__PURE__ */ jsx("path", { d: "m9 12 2 2 4-4" })
20571
+ ]
20572
+ }
20573
+ );
20574
+ }
20575
+ function ExternalIcon() {
20576
+ return /* @__PURE__ */ jsxs(
20577
+ "svg",
20578
+ {
20579
+ width: "13",
20580
+ height: "13",
20581
+ viewBox: "0 0 24 24",
20582
+ fill: "none",
20583
+ stroke: "currentColor",
20584
+ strokeWidth: "2",
20585
+ strokeLinecap: "round",
20586
+ strokeLinejoin: "round",
20587
+ "aria-hidden": "true",
20588
+ style: { flexShrink: 0 },
20589
+ children: [
20590
+ /* @__PURE__ */ jsx("path", { d: "M15 3h6v6" }),
20591
+ /* @__PURE__ */ jsx("path", { d: "M10 14 21 3" }),
20592
+ /* @__PURE__ */ jsx("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" })
20593
+ ]
20594
+ }
20595
+ );
20596
+ }
20597
+ function TabbyAuthResolver(p) {
20598
+ var _a, _b, _c;
20599
+ const { BORDER: BORDER4, MUTED: MUTED2, ACCENT: ACCENT2, ACCENT_SOFT: ACCENT_SOFT2 } = useTheme();
20600
+ const [cardHovered, setCardHovered] = useState(false);
20601
+ const [btnHovered, setBtnHovered] = useState(false);
20602
+ const [imgFailed, setImgFailed] = useState(false);
20603
+ const app = humanizeApp(p.app || "the app");
20604
+ const connected = p.state === "connected";
20605
+ const accent = connected ? CONNECTED_GREEN3 : ACCENT2;
20606
+ const ctaLabel = (_a = p.ctaLabel) != null ? _a : connected ? `Open ${app}` : `Connect ${app}`;
20607
+ const subtitle = p.workspace ? `${app} \xB7 ${p.workspace} workspace` : app;
20608
+ const steps = ((_b = p.steps) == null ? void 0 : _b.length) ? p.steps : DEFAULT_STEPS(app, ctaLabel, connected);
20609
+ const description = (_c = p.description) != null ? _c : connected ? `Your ${app} session is active. Open ${app} to continue, or re-authenticate if prompted.` : `Your ${app} account is not yet connected to this workspace. Complete sign-in once to enable automatic access.`;
20610
+ const iconSrc = p.iconUrl || brandIconUrl(app);
20611
+ const showImg = Boolean(iconSrc) && !imgFailed;
20612
+ const initial = app.charAt(0).toUpperCase();
20613
+ const badge = connected ? { label: "Connected", bg: CONNECTED_GREEN_BG, color: CONNECTED_GREEN3 } : { label: "Pending sign-in", bg: PENDING_AMBER_BG, color: PENDING_AMBER };
20614
+ const sectionPad = "13px 16px";
20615
+ return /* @__PURE__ */ jsx(ComponentActions, { filename: `${app} authentication`, children: /* @__PURE__ */ jsx("div", { style: { width: "100%", display: "flex", flexDirection: "column", gap: "10px" }, children: /* @__PURE__ */ jsxs(
20616
+ "div",
20617
+ {
20618
+ onMouseEnter: () => setCardHovered(true),
20619
+ onMouseLeave: () => setCardHovered(false),
20620
+ style: {
20621
+ display: "flex",
20622
+ flexDirection: "row",
20623
+ alignItems: "stretch",
20624
+ borderRadius: "0.75rem",
20625
+ border: `1px solid ${cardHovered ? "#d2d2d2" : BORDER4}`,
20626
+ background: "white",
20627
+ overflow: "hidden",
20628
+ boxShadow: cardHovered ? "0 1px 3px rgba(0,0,0,0.05), 0 6px 18px rgba(0,0,0,0.06)" : "0 1px 2px rgba(0,0,0,0.03)",
20629
+ transition: "box-shadow 0.18s ease, border-color 0.18s ease"
20630
+ },
20631
+ children: [
20632
+ /* @__PURE__ */ jsx("div", { style: { width: "3px", flexShrink: 0, background: accent } }),
20633
+ /* @__PURE__ */ jsxs("div", { style: { flex: 1, minWidth: 0, display: "flex", flexDirection: "column" }, children: [
20634
+ /* @__PURE__ */ jsxs(
20635
+ "div",
20636
+ {
20637
+ style: {
20638
+ display: "flex",
20639
+ alignItems: "flex-start",
20640
+ gap: "12px",
20641
+ padding: sectionPad
20642
+ },
20643
+ children: [
20644
+ /* @__PURE__ */ jsx(
20645
+ "div",
20646
+ {
20647
+ style: {
20648
+ position: "relative",
20649
+ width: "34px",
20650
+ height: "34px",
20651
+ borderRadius: "9px",
20652
+ flexShrink: 0,
20653
+ display: "flex",
20654
+ alignItems: "center",
20655
+ justifyContent: "center",
20656
+ background: showImg ? "white" : "#fff3ee",
20657
+ boxShadow: "inset 0 0 0 1px rgba(0,0,0,0.06)",
20658
+ overflow: "hidden"
20659
+ },
20660
+ children: showImg ? /* @__PURE__ */ jsx(
20661
+ "img",
20662
+ {
20663
+ src: iconSrc,
20664
+ alt: app,
20665
+ onError: () => setImgFailed(true),
20666
+ style: { width: "22px", height: "22px", objectFit: "contain" }
20667
+ }
20668
+ ) : /* @__PURE__ */ jsx(
20669
+ "span",
20670
+ {
20671
+ style: {
20672
+ fontFamily: "var(--font-serif)",
20673
+ fontSize: "17px",
20674
+ fontWeight: 400,
20675
+ color: ACCENT2,
20676
+ lineHeight: 1
20677
+ },
20678
+ children: initial
20679
+ }
20680
+ )
20681
+ }
20682
+ ),
20683
+ /* @__PURE__ */ jsxs("div", { style: { flex: 1, minWidth: 0, display: "flex", flexDirection: "column", gap: "2px" }, children: [
20684
+ /* @__PURE__ */ jsx(
20685
+ "span",
20686
+ {
20687
+ style: {
20688
+ fontFamily: "var(--font-serif)",
20689
+ fontSize: "15px",
20690
+ fontWeight: 400,
20691
+ color: "var(--foreground)",
20692
+ letterSpacing: "-0.01em",
20693
+ lineHeight: 1.2
20694
+ },
20695
+ children: CARD_TITLE
20696
+ }
20697
+ ),
20698
+ /* @__PURE__ */ jsx(
20699
+ "span",
20700
+ {
20701
+ style: {
20702
+ fontSize: "12px",
20703
+ color: MUTED2,
20704
+ whiteSpace: "nowrap",
20705
+ overflow: "hidden",
20706
+ textOverflow: "ellipsis"
20707
+ },
20708
+ children: subtitle
20709
+ }
20710
+ )
20711
+ ] }),
20712
+ /* @__PURE__ */ jsxs(
20713
+ "span",
20714
+ {
20715
+ style: {
20716
+ display: "inline-flex",
20717
+ alignItems: "center",
20718
+ gap: "5px",
20719
+ flexShrink: 0,
20720
+ fontSize: "10.5px",
20721
+ fontWeight: 600,
20722
+ padding: "3px 9px",
20723
+ borderRadius: "9999px",
20724
+ background: badge.bg,
20725
+ color: badge.color,
20726
+ whiteSpace: "nowrap"
20727
+ },
20728
+ children: [
20729
+ /* @__PURE__ */ jsx(
20730
+ "span",
20731
+ {
20732
+ style: {
20733
+ width: "6px",
20734
+ height: "6px",
20735
+ borderRadius: "9999px",
20736
+ background: badge.color
20737
+ }
20738
+ }
20739
+ ),
20740
+ badge.label
20741
+ ]
20742
+ }
20743
+ )
20744
+ ]
20745
+ }
20746
+ ),
20747
+ /* @__PURE__ */ jsxs(
20748
+ "div",
20749
+ {
20750
+ style: {
20751
+ borderTop: `1px solid ${BORDER4}`,
20752
+ padding: sectionPad,
20753
+ display: "flex",
20754
+ flexDirection: "column",
20755
+ gap: "12px"
20756
+ },
20757
+ children: [
20758
+ description && /* @__PURE__ */ jsx("p", { style: { margin: 0, fontSize: "12.5px", lineHeight: 1.5, color: "var(--foreground)" }, children: description }),
20759
+ /* @__PURE__ */ jsx("ol", { style: { margin: 0, padding: 0, listStyle: "none", display: "flex", flexDirection: "column", gap: "8px" }, children: steps.map((step, i) => /* @__PURE__ */ jsxs("li", { style: { display: "flex", alignItems: "flex-start", gap: "10px" }, children: [
20760
+ /* @__PURE__ */ jsx(
20761
+ "span",
20762
+ {
20763
+ style: {
20764
+ flexShrink: 0,
20765
+ width: "18px",
20766
+ height: "18px",
20767
+ borderRadius: "9999px",
20768
+ background: accent,
20769
+ color: "white",
20770
+ fontSize: "10.5px",
20771
+ fontWeight: 600,
20772
+ display: "flex",
20773
+ alignItems: "center",
20774
+ justifyContent: "center",
20775
+ marginTop: "1px"
20776
+ },
20777
+ children: i + 1
20778
+ }
20779
+ ),
20780
+ /* @__PURE__ */ jsx("span", { style: { fontSize: "12.5px", lineHeight: 1.45, color: "var(--foreground)" }, children: step })
20781
+ ] }, i)) })
20782
+ ]
20783
+ }
20784
+ ),
20785
+ /* @__PURE__ */ jsxs(
20786
+ "div",
20787
+ {
20788
+ style: {
20789
+ borderTop: `1px solid ${BORDER4}`,
20790
+ padding: sectionPad,
20791
+ background: "#fbfbfb",
20792
+ display: "flex",
20793
+ alignItems: "center",
20794
+ justifyContent: "space-between",
20795
+ gap: "12px",
20796
+ flexWrap: "wrap"
20797
+ },
20798
+ children: [
20799
+ /* @__PURE__ */ jsxs("span", { style: { display: "inline-flex", alignItems: "center", gap: "6px", color: MUTED2, fontSize: "11.5px" }, children: [
20800
+ /* @__PURE__ */ jsx(ShieldIcon, { color: CONNECTED_GREEN3 }),
20801
+ TRUST_FOOTER
20802
+ ] }),
20803
+ /* @__PURE__ */ jsxs(
20804
+ "a",
20805
+ {
20806
+ href: p.url,
20807
+ target: "_blank",
20808
+ rel: "noopener noreferrer",
20809
+ onMouseEnter: () => setBtnHovered(true),
20810
+ onMouseLeave: () => setBtnHovered(false),
20811
+ style: {
20812
+ display: "inline-flex",
20813
+ alignItems: "center",
20814
+ gap: "7px",
20815
+ flexShrink: 0,
20816
+ borderRadius: "8px",
20817
+ padding: "8px 15px",
20818
+ fontSize: "12.5px",
20819
+ fontWeight: 600,
20820
+ textDecoration: "none",
20821
+ whiteSpace: "nowrap",
20822
+ cursor: "pointer",
20823
+ color: "white",
20824
+ border: "1px solid transparent",
20825
+ background: btnHovered ? connected ? "#126a33" : ACCENT_SOFT2 : accent,
20826
+ transition: "background 0.15s ease"
20827
+ },
20828
+ children: [
20829
+ /* @__PURE__ */ jsx(ExternalIcon, {}),
20830
+ ctaLabel
20831
+ ]
20832
+ }
20833
+ )
20834
+ ]
20835
+ }
20836
+ )
20837
+ ] })
20838
+ ]
20839
+ }
20840
+ ) }) });
20841
+ }
20079
20842
  function resolveUI(rawPayload) {
20080
20843
  const payload = coercePayload(rawPayload);
20081
20844
  switch (payload.type) {
@@ -20197,6 +20960,8 @@ function resolveUI(rawPayload) {
20197
20960
  return /* @__PURE__ */ jsx(DocumentFieldExtractionResolver, __spreadValues({}, payload));
20198
20961
  case "decision-card":
20199
20962
  return /* @__PURE__ */ jsx(DecisionCardResolver, __spreadValues({}, payload));
20963
+ case "tabby-auth":
20964
+ return /* @__PURE__ */ jsx(TabbyAuthResolver, __spreadValues({}, payload));
20200
20965
  default: {
20201
20966
  return /* @__PURE__ */ jsx(
20202
20967
  "div",