@tangle-network/agent-app 0.45.47 → 0.45.49

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 (94) hide show
  1. package/dist/{DesignCanvas-P2ZVK6FM.js → DesignCanvas-JRBCAWHW.js} +2 -2
  2. package/dist/{DesignCanvasEditor-DGNCA54P.js → DesignCanvasEditor-J2OLS22G.js} +4 -4
  3. package/dist/{IntakeInterview-3ZIQMZS6.js → IntakeInterview-OKT6DCBN.js} +2 -2
  4. package/dist/InvitationsPanel-OFCYVSAE.js +9 -0
  5. package/dist/InviteAcceptPage-BDOO4JSE.js +7 -0
  6. package/dist/MembersPanel-3ZK2GCMC.js +9 -0
  7. package/dist/{TimelineEditor-OTNPJ3SN.js → TimelineEditor-52YEPDX5.js} +2 -2
  8. package/dist/VaultPane-IGJKB6CX.js +7 -0
  9. package/dist/assistant/index.d.ts +36 -11
  10. package/dist/assistant/index.js +235 -90
  11. package/dist/assistant/index.js.map +1 -1
  12. package/dist/{billing-BibxgALe.d.ts → billing-BuNlaKlE.d.ts} +15 -23
  13. package/dist/chat-react/index.js +2 -1
  14. package/dist/chat-react/index.js.map +1 -1
  15. package/dist/{chunk-TL37E5YY.js → chunk-33BN7P57.js} +6 -6
  16. package/dist/chunk-33BN7P57.js.map +1 -0
  17. package/dist/{chunk-IUSO2XRE.js → chunk-5MI2SKQH.js} +14 -15
  18. package/dist/chunk-5MI2SKQH.js.map +1 -0
  19. package/dist/{chunk-65OZT566.js → chunk-7LJYCHXK.js} +29 -27
  20. package/dist/chunk-7LJYCHXK.js.map +1 -0
  21. package/dist/chunk-AULM4X7U.js +77 -0
  22. package/dist/chunk-AULM4X7U.js.map +1 -0
  23. package/dist/{chunk-GNPN6ED4.js → chunk-CJHIAZKK.js} +128 -166
  24. package/dist/chunk-CJHIAZKK.js.map +1 -0
  25. package/dist/{chunk-54FYYXAX.js → chunk-ENLRJYVW.js} +21 -18
  26. package/dist/chunk-ENLRJYVW.js.map +1 -0
  27. package/dist/{chunk-F4XLTVQ3.js → chunk-GRDLGQ6A.js} +19 -18
  28. package/dist/chunk-GRDLGQ6A.js.map +1 -0
  29. package/dist/{chunk-BT4QFCTB.js → chunk-HSBJB46C.js} +13 -1
  30. package/dist/chunk-HSBJB46C.js.map +1 -0
  31. package/dist/{chunk-VOJB7MVG.js → chunk-I2CA5N7V.js} +70 -28
  32. package/dist/chunk-I2CA5N7V.js.map +1 -0
  33. package/dist/chunk-MLG6XKPV.js +44 -0
  34. package/dist/chunk-MLG6XKPV.js.map +1 -0
  35. package/dist/{chunk-IN6LNZ7O.js → chunk-Q2QKEV6J.js} +7 -7
  36. package/dist/{chunk-IN6LNZ7O.js.map → chunk-Q2QKEV6J.js.map} +1 -1
  37. package/dist/{chunk-B62EZF52.js → chunk-UMV45ZDF.js} +3 -3
  38. package/dist/{chunk-JJJEO4ND.js → chunk-VWTODXRW.js} +2 -2
  39. package/dist/{chunk-JJJEO4ND.js.map → chunk-VWTODXRW.js.map} +1 -1
  40. package/dist/{chunk-VCPZ3HTN.js → chunk-W7P5KV6O.js} +51 -27
  41. package/dist/chunk-W7P5KV6O.js.map +1 -0
  42. package/dist/{chunk-ZX5UT4HF.js → chunk-ZAKKG6WI.js} +354 -273
  43. package/dist/chunk-ZAKKG6WI.js.map +1 -0
  44. package/dist/{chunk-PE67O2LH.js → chunk-ZGY6QB4F.js} +21 -16
  45. package/dist/chunk-ZGY6QB4F.js.map +1 -0
  46. package/dist/design-canvas-react/index.js +18 -16
  47. package/dist/design-canvas-react/index.js.map +1 -1
  48. package/dist/design-canvas-react/lazy.js +1 -1
  49. package/dist/intakes-react/index.js +1 -1
  50. package/dist/intakes-react/lazy.js +1 -1
  51. package/dist/platform/index.d.ts +1 -1
  52. package/dist/platform/index.js +16 -16
  53. package/dist/platform/index.js.map +1 -1
  54. package/dist/sequences-react/index.js +2 -2
  55. package/dist/studio/index.d.ts +13 -1
  56. package/dist/studio/index.js +13 -1
  57. package/dist/studio-react/index.js +115 -78
  58. package/dist/studio-react/index.js.map +1 -1
  59. package/dist/studio-react/studio.css +0 -56
  60. package/dist/teams-react/index.js +4 -3
  61. package/dist/teams-react/lazy.js +3 -3
  62. package/dist/theme/index.js +1 -1
  63. package/dist/theme/tokens.css +15 -13
  64. package/dist/vault/index.js +1 -1
  65. package/dist/vault/lazy.js +1 -1
  66. package/dist/web-react/index.d.ts +16 -12
  67. package/dist/web-react/index.js +6 -4
  68. package/dist/work-product-react/index.js +9 -27
  69. package/dist/work-product-react/index.js.map +1 -1
  70. package/package.json +3 -3
  71. package/dist/InvitationsPanel-F56UOQXA.js +0 -8
  72. package/dist/InviteAcceptPage-P3QJC3C6.js +0 -7
  73. package/dist/MembersPanel-XNLF3SA4.js +0 -8
  74. package/dist/VaultPane-MUWGYVJ7.js +0 -7
  75. package/dist/chunk-54FYYXAX.js.map +0 -1
  76. package/dist/chunk-65OZT566.js.map +0 -1
  77. package/dist/chunk-BT4QFCTB.js.map +0 -1
  78. package/dist/chunk-F4XLTVQ3.js.map +0 -1
  79. package/dist/chunk-GNPN6ED4.js.map +0 -1
  80. package/dist/chunk-IUSO2XRE.js.map +0 -1
  81. package/dist/chunk-PE67O2LH.js.map +0 -1
  82. package/dist/chunk-TL37E5YY.js.map +0 -1
  83. package/dist/chunk-VCPZ3HTN.js.map +0 -1
  84. package/dist/chunk-VOJB7MVG.js.map +0 -1
  85. package/dist/chunk-ZX5UT4HF.js.map +0 -1
  86. /package/dist/{DesignCanvas-P2ZVK6FM.js.map → DesignCanvas-JRBCAWHW.js.map} +0 -0
  87. /package/dist/{DesignCanvasEditor-DGNCA54P.js.map → DesignCanvasEditor-J2OLS22G.js.map} +0 -0
  88. /package/dist/{IntakeInterview-3ZIQMZS6.js.map → IntakeInterview-OKT6DCBN.js.map} +0 -0
  89. /package/dist/{InvitationsPanel-F56UOQXA.js.map → InvitationsPanel-OFCYVSAE.js.map} +0 -0
  90. /package/dist/{InviteAcceptPage-P3QJC3C6.js.map → InviteAcceptPage-BDOO4JSE.js.map} +0 -0
  91. /package/dist/{MembersPanel-XNLF3SA4.js.map → MembersPanel-3ZK2GCMC.js.map} +0 -0
  92. /package/dist/{TimelineEditor-OTNPJ3SN.js.map → TimelineEditor-52YEPDX5.js.map} +0 -0
  93. /package/dist/{VaultPane-MUWGYVJ7.js.map → VaultPane-IGJKB6CX.js.map} +0 -0
  94. /package/dist/{chunk-B62EZF52.js.map → chunk-UMV45ZDF.js.map} +0 -0
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  ChatComposer,
3
+ ChatEmptyState,
3
4
  ChatMessages
4
- } from "../chunk-ZX5UT4HF.js";
5
+ } from "../chunk-ZAKKG6WI.js";
5
6
  import "../chunk-FBVLEGEG.js";
6
- import "../chunk-54FYYXAX.js";
7
+ import "../chunk-ENLRJYVW.js";
7
8
  import "../chunk-GEYACSFW.js";
8
9
  import {
9
- ModelPicker,
10
- OVERLAY_SHADOW,
11
- ProviderLogo
12
- } from "../chunk-GNPN6ED4.js";
10
+ ModelPicker
11
+ } from "../chunk-CJHIAZKK.js";
12
+ import "../chunk-MLG6XKPV.js";
13
13
  import "../chunk-BATKJP3P.js";
14
14
  import {
15
15
  AsyncView
@@ -703,7 +703,7 @@ function describeProposal(proposal) {
703
703
  if (args.product != null)
704
704
  fields.push({ label: "Product", value: str(args.product) });
705
705
  if (args.budgetUsd != null)
706
- fields.push({ label: "Budget (USD)", value: str(args.budgetUsd) });
706
+ fields.push({ label: "Budget", value: `$${str(args.budgetUsd)}` });
707
707
  return { title: "Create API key", preview: null, fields };
708
708
  }
709
709
  case "revoke_api_key":
@@ -960,7 +960,7 @@ function applyStreamEvent(state, event) {
960
960
  {
961
961
  id: `cap-${event.data.turnId}`,
962
962
  role: "status",
963
- text: "Paused after a lot of steps \u2014 continue when you're ready and I'll pick up where I left off."
963
+ text: "Paused at the step limit \u2014 continue when you're ready and I'll pick up where I left off."
964
964
  }
965
965
  ]);
966
966
  }
@@ -1691,7 +1691,7 @@ import {
1691
1691
 
1692
1692
  // src/assistant/AssistantPanel.tsx
1693
1693
  import { History, MessageSquarePlus, Minus, Plus, X } from "lucide-react";
1694
- import { useEffect as useEffect6, useMemo as useMemo3, useRef as useRef6, useState as useState6 } from "react";
1694
+ import { useEffect as useEffect6, useLayoutEffect as useLayoutEffect2, useMemo as useMemo3, useRef as useRef6, useState as useState6 } from "react";
1695
1695
 
1696
1696
  // src/assistant/AssistantHistory.tsx
1697
1697
  import { Search, Trash2 } from "lucide-react";
@@ -1705,7 +1705,18 @@ function timeAgo(ts) {
1705
1705
  const mins = Math.floor(secs / 60);
1706
1706
  if (mins < 60) return `${mins}m ago`;
1707
1707
  const hrs = Math.floor(mins / 60);
1708
- return `${hrs}h ago`;
1708
+ if (hrs < 24) return `${hrs}h ago`;
1709
+ const days = Math.floor(hrs / 24);
1710
+ if (days < 7) return `${days}d ago`;
1711
+ const weeks = Math.floor(days / 7);
1712
+ if (weeks < 5) return `${weeks}w ago`;
1713
+ const date = new Date(ts);
1714
+ const sameYear = date.getFullYear() === (/* @__PURE__ */ new Date()).getFullYear();
1715
+ return date.toLocaleDateString(void 0, {
1716
+ month: "short",
1717
+ day: "numeric",
1718
+ ...sameYear ? {} : { year: "numeric" }
1719
+ });
1709
1720
  }
1710
1721
 
1711
1722
  // src/assistant/AssistantHistory.tsx
@@ -1770,6 +1781,42 @@ function AssistantHistory({
1770
1781
  {
1771
1782
  state,
1772
1783
  loadingLabel: "Loading\u2026",
1784
+ renderError: ({ message, retry }) => /* @__PURE__ */ jsxs(
1785
+ "div",
1786
+ {
1787
+ role: "alert",
1788
+ className: "flex flex-col items-center justify-center gap-2 px-4 py-10 text-center",
1789
+ children: [
1790
+ /* @__PURE__ */ jsxs(
1791
+ "svg",
1792
+ {
1793
+ className: "h-4 w-4 text-destructive",
1794
+ viewBox: "0 0 24 24",
1795
+ fill: "none",
1796
+ stroke: "currentColor",
1797
+ strokeWidth: "2",
1798
+ strokeLinecap: "round",
1799
+ strokeLinejoin: "round",
1800
+ "aria-hidden": "true",
1801
+ children: [
1802
+ /* @__PURE__ */ jsx2("circle", { cx: "12", cy: "12", r: "9" }),
1803
+ /* @__PURE__ */ jsx2("path", { d: "M12 8v4m0 4h.01" })
1804
+ ]
1805
+ }
1806
+ ),
1807
+ /* @__PURE__ */ jsx2("p", { className: "max-w-md text-destructive text-sm", children: message }),
1808
+ /* @__PURE__ */ jsx2(
1809
+ "button",
1810
+ {
1811
+ type: "button",
1812
+ onClick: retry,
1813
+ className: "rounded border border-destructive/40 bg-card px-2 py-0.5 font-medium text-xs text-destructive transition hover:bg-destructive/10",
1814
+ children: "Retry"
1815
+ }
1816
+ )
1817
+ ]
1818
+ }
1819
+ ),
1773
1820
  empty: {
1774
1821
  title: trimmed ? "No conversations match your search." : "No past conversations yet.",
1775
1822
  description: trimmed ? void 0 : "Your chats with the assistant will appear here."
@@ -1798,7 +1845,7 @@ function AssistantHistory({
1798
1845
  children: title
1799
1846
  }
1800
1847
  ),
1801
- ms != null && /* @__PURE__ */ jsx2("span", { className: "text-[11px] text-muted-foreground", children: timeAgo(ms) })
1848
+ ms != null && /* @__PURE__ */ jsx2("span", { className: "text-xs text-muted-foreground", children: timeAgo(ms) })
1802
1849
  ]
1803
1850
  }
1804
1851
  ),
@@ -1826,6 +1873,7 @@ function AssistantHistory({
1826
1873
 
1827
1874
  // src/assistant/ProposalCard.tsx
1828
1875
  import { useEffect as useEffect4, useRef as useRef3, useState as useState4 } from "react";
1876
+ import { ProviderIcon } from "@tangle-network/sandbox-ui/integrations";
1829
1877
 
1830
1878
  // src/assistant/provider-label.ts
1831
1879
  var PROVIDER_LABELS = {
@@ -1844,6 +1892,7 @@ function providerLabel(provider) {
1844
1892
 
1845
1893
  // src/assistant/ProposalCard.tsx
1846
1894
  import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
1895
+ var EYEBROW_CLASS = "text-xs font-semibold uppercase tracking-[0.05em] text-muted-foreground";
1847
1896
  function ProposalCard({
1848
1897
  proposal,
1849
1898
  confirming,
@@ -1859,14 +1908,13 @@ function ProposalCard({
1859
1908
  const isWorkflow = view.preview?.kind === "workflow";
1860
1909
  const showGraph = isWorkflow && !!renderGraph;
1861
1910
  return /* @__PURE__ */ jsxs2("div", { className: "rounded-lg border border-primary/40 bg-card p-3 text-sm", children: [
1862
- /* @__PURE__ */ jsx3("p", { className: "font-medium text-foreground", children: view.title }),
1863
- /* @__PURE__ */ jsx3("p", { className: "text-muted-foreground text-xs", children: "Confirm to run this action on your account." }),
1864
- view.fields.length > 0 && /* @__PURE__ */ jsx3("dl", { className: "mt-2 space-y-1", children: view.fields.map((f) => /* @__PURE__ */ jsxs2("div", { className: "flex gap-2 text-xs", children: [
1865
- /* @__PURE__ */ jsx3("dt", { className: "shrink-0 text-muted-foreground", children: f.label }),
1911
+ /* @__PURE__ */ jsx3("p", { className: "font-semibold text-[15px] text-foreground", children: view.title }),
1912
+ view.fields.length > 0 && /* @__PURE__ */ jsx3("dl", { className: "mt-2 space-y-1", children: view.fields.map((f) => /* @__PURE__ */ jsxs2("div", { className: "grid grid-cols-[auto_1fr] gap-x-3 text-xs", children: [
1913
+ /* @__PURE__ */ jsx3("dt", { className: "text-muted-foreground", children: f.label }),
1866
1914
  /* @__PURE__ */ jsx3("dd", { className: "truncate text-foreground", title: f.value, children: f.value })
1867
1915
  ] }, f.label)) }),
1868
1916
  view.skills && view.skills.length > 0 && /* @__PURE__ */ jsxs2("div", { className: "mt-2", children: [
1869
- /* @__PURE__ */ jsx3("p", { className: "text-muted-foreground text-xs", children: "New skills" }),
1917
+ /* @__PURE__ */ jsx3("p", { className: EYEBROW_CLASS, children: "New skills" }),
1870
1918
  /* @__PURE__ */ jsx3("ul", { className: "mt-1 space-y-0.5", children: view.skills.map((s) => /* @__PURE__ */ jsxs2("li", { className: "text-foreground text-xs", children: [
1871
1919
  /* @__PURE__ */ jsx3("span", { className: "font-medium", children: s.name }),
1872
1920
  s.description ? /* @__PURE__ */ jsxs2("span", { className: "text-muted-foreground", children: [
@@ -1877,14 +1925,15 @@ function ProposalCard({
1877
1925
  ] }),
1878
1926
  view.preview && /* @__PURE__ */ jsxs2("div", { className: "mt-2", children: [
1879
1927
  /* @__PURE__ */ jsxs2("div", { className: "flex items-center justify-between", children: [
1880
- /* @__PURE__ */ jsx3("p", { className: "text-muted-foreground text-xs", children: view.preview.label }),
1928
+ /* @__PURE__ */ jsx3("p", { className: EYEBROW_CLASS, children: view.preview.label }),
1881
1929
  showGraph && /* @__PURE__ */ jsxs2("div", { className: "flex gap-2 text-xs", children: [
1882
1930
  /* @__PURE__ */ jsx3(
1883
1931
  "button",
1884
1932
  {
1885
1933
  type: "button",
1886
1934
  onClick: () => setTab("graph"),
1887
- className: tab === "graph" ? "text-foreground" : "text-muted-foreground",
1935
+ "aria-pressed": tab === "graph",
1936
+ className: tab === "graph" ? "font-medium text-foreground underline decoration-primary underline-offset-4" : "text-muted-foreground hover:text-foreground",
1888
1937
  children: "Graph"
1889
1938
  }
1890
1939
  ),
@@ -1893,16 +1942,22 @@ function ProposalCard({
1893
1942
  {
1894
1943
  type: "button",
1895
1944
  onClick: () => setTab("yaml"),
1896
- className: tab === "yaml" ? "text-foreground" : "text-muted-foreground",
1945
+ "aria-pressed": tab === "yaml",
1946
+ className: tab === "yaml" ? "font-medium text-foreground underline decoration-primary underline-offset-4" : "text-muted-foreground hover:text-foreground",
1897
1947
  children: "YAML"
1898
1948
  }
1899
1949
  )
1900
1950
  ] })
1901
1951
  ] }),
1902
- showGraph && tab === "graph" ? /* @__PURE__ */ jsx3("div", { className: "mt-1 h-64 overflow-hidden rounded border border-border", children: renderGraph?.(view.preview.content) }) : /* @__PURE__ */ jsx3("pre", { className: "mt-1 max-h-48 overflow-auto rounded border border-border bg-secondary p-2 text-xs", children: /* @__PURE__ */ jsx3("code", { children: view.preview.content }) })
1952
+ showGraph && tab === "graph" ? /* @__PURE__ */ jsx3("div", { className: "mt-1 h-64 overflow-hidden rounded border border-border", children: renderGraph?.(view.preview.content) }) : (
1953
+ // max-h fits a whole number of lines at text-xs' 16px leading —
1954
+ // 1px border + 8px top padding, 12 lines = 202px — so the scroll
1955
+ // cut lands on a line boundary, never mid-glyph.
1956
+ /* @__PURE__ */ jsx3("pre", { className: "mt-1 max-h-[202px] overflow-auto rounded border border-border bg-secondary p-2 font-mono text-xs tabular-nums", children: /* @__PURE__ */ jsx3("code", { children: view.preview.content }) })
1957
+ )
1903
1958
  ] }),
1904
1959
  proposal.requirements && proposal.requirements.length > 0 && /* @__PURE__ */ jsxs2("div", { className: "mt-3 rounded border border-border p-2", children: [
1905
- /* @__PURE__ */ jsx3("p", { className: "text-muted-foreground text-xs", children: "Integrations" }),
1960
+ /* @__PURE__ */ jsx3("p", { className: EYEBROW_CLASS, children: "Integrations" }),
1906
1961
  /* @__PURE__ */ jsx3("ul", { className: "mt-1 space-y-1", children: proposal.requirements.map((r) => /* @__PURE__ */ jsx3(
1907
1962
  RequirementRow,
1908
1963
  {
@@ -1913,7 +1968,7 @@ function ProposalCard({
1913
1968
  },
1914
1969
  `${r.provider}-${r.kind ?? "integration"}`
1915
1970
  )) }),
1916
- /* @__PURE__ */ jsx3("p", { className: "mt-1 text-muted-foreground text-xs", children: "Connect the items above, then confirm \u2014 your proposal stays here until you do." })
1971
+ /* @__PURE__ */ jsx3("p", { className: "mt-1 text-muted-foreground text-xs", children: "Connect the items above, then confirm." })
1917
1972
  ] }),
1918
1973
  proposal.retryError && /* @__PURE__ */ jsx3("p", { role: "alert", className: "mt-2 text-destructive text-xs", children: proposal.retryError }),
1919
1974
  /* @__PURE__ */ jsxs2("div", { className: "mt-3 flex gap-2", children: [
@@ -1923,7 +1978,7 @@ function ProposalCard({
1923
1978
  type: "button",
1924
1979
  onClick: onConfirm,
1925
1980
  disabled: confirming || !proposal.proposalId,
1926
- className: "rounded bg-primary px-3 py-1.5 text-primary-foreground text-sm disabled:opacity-50",
1981
+ className: "rounded-md bg-primary px-3 py-1.5 font-medium text-primary-foreground text-sm disabled:opacity-50",
1927
1982
  children: confirming ? "Confirming\u2026" : "Confirm"
1928
1983
  }
1929
1984
  ),
@@ -1933,7 +1988,7 @@ function ProposalCard({
1933
1988
  type: "button",
1934
1989
  onClick: onCancel,
1935
1990
  disabled: confirming,
1936
- className: "rounded border border-border px-3 py-1.5 text-foreground text-sm disabled:opacity-50",
1991
+ className: "rounded-md border border-border px-3 py-1.5 font-medium text-foreground text-sm disabled:opacity-50",
1937
1992
  children: "Cancel"
1938
1993
  }
1939
1994
  )
@@ -2001,10 +2056,17 @@ function RequirementRow({
2001
2056
  } catch {
2002
2057
  providerIcon = null;
2003
2058
  }
2004
- return /* @__PURE__ */ jsxs2("li", { className: "flex items-center justify-between gap-2 text-xs", children: [
2059
+ return /* @__PURE__ */ jsxs2("li", { className: "flex items-center justify-between gap-2 text-sm", children: [
2005
2060
  /* @__PURE__ */ jsxs2("span", { className: "flex min-w-0 items-center gap-2", children: [
2006
- providerIcon ?? /* @__PURE__ */ jsx3(ProviderLogo, { provider: req.provider, size: 16 }),
2007
- /* @__PURE__ */ jsx3("span", { className: "truncate text-foreground", children: kindLabel }),
2061
+ providerIcon ?? /* @__PURE__ */ jsx3(
2062
+ ProviderIcon,
2063
+ {
2064
+ id: req.provider,
2065
+ size: 16,
2066
+ className: "rounded-[4px]"
2067
+ }
2068
+ ),
2069
+ /* @__PURE__ */ jsx3("span", { className: "truncate font-medium text-foreground", children: kindLabel }),
2008
2070
  /* @__PURE__ */ jsxs2("span", { className: "flex shrink-0 items-center gap-1", children: [
2009
2071
  /* @__PURE__ */ jsx3(
2010
2072
  "span",
@@ -2028,7 +2090,7 @@ function RequirementRow({
2028
2090
  type: "button",
2029
2091
  onClick: handleConnect,
2030
2092
  disabled: connecting,
2031
- className: "shrink-0 rounded border border-primary px-2 py-0.5 font-medium text-primary transition-colors hover:bg-primary/10 disabled:opacity-50",
2093
+ className: "shrink-0 rounded border border-primary px-2 py-0.5 font-medium text-primary text-sm transition-colors hover:bg-primary/10 disabled:opacity-50",
2032
2094
  children: connecting ? isApp ? "Installing\u2026" : "Connecting\u2026" : isApp ? "Install" : "Connect"
2033
2095
  }
2034
2096
  )
@@ -2036,6 +2098,7 @@ function RequirementRow({
2036
2098
  }
2037
2099
 
2038
2100
  // src/assistant/transcript.tsx
2101
+ import { Check } from "lucide-react";
2039
2102
  import { useCallback as useCallback3, useMemo as useMemo2 } from "react";
2040
2103
  import { Fragment, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
2041
2104
  function assistantIsThinking(state) {
@@ -2053,13 +2116,18 @@ function adaptToolResult(outcome) {
2053
2116
  return { ok: false, message: outcome.error?.message, code: outcome.error?.code };
2054
2117
  }
2055
2118
  function adaptTranscript(view) {
2056
- const messages = [];
2119
+ const blocks = [];
2057
2120
  const confirmedResults = /* @__PURE__ */ new Map();
2121
+ let run = [];
2122
+ const flushRun = () => {
2123
+ if (run.length > 0) blocks.push({ kind: "run", messages: run });
2124
+ run = [];
2125
+ };
2058
2126
  let turn = null;
2059
2127
  let currentTurnAssistant = null;
2060
2128
  const openTurn = (id) => {
2061
2129
  const message = { id, role: "assistant", content: "", segments: [] };
2062
- messages.push(message);
2130
+ run.push(message);
2063
2131
  turn = message;
2064
2132
  currentTurnAssistant = message;
2065
2133
  return message;
@@ -2073,7 +2141,7 @@ ${text}` : text;
2073
2141
  };
2074
2142
  for (const msg of view.messages) {
2075
2143
  if (msg.role === "user") {
2076
- messages.push({ id: msg.id, role: "user", content: msg.text });
2144
+ run.push({ id: msg.id, role: "user", content: msg.text });
2077
2145
  turn = null;
2078
2146
  currentTurnAssistant = null;
2079
2147
  } else if (msg.role === "assistant") {
@@ -2097,7 +2165,8 @@ ${text}` : text;
2097
2165
  }
2098
2166
  });
2099
2167
  } else {
2100
- messages.push({ id: msg.id, role: "system", content: msg.text });
2168
+ flushRun();
2169
+ blocks.push({ kind: "status", id: msg.id, text: msg.text });
2101
2170
  if (msg.result) confirmedResults.set(msg.id, msg.result);
2102
2171
  turn = null;
2103
2172
  }
@@ -2123,9 +2192,24 @@ ${text}` : text;
2123
2192
  currentTurnAssistant.durationMs = view.usage.durationMs;
2124
2193
  }
2125
2194
  }
2195
+ flushRun();
2126
2196
  const isEmptyShell = (m) => m.role === "assistant" && m.content === "" && (m.segments?.length ?? 0) === 0 && m.reasoning == null && m.modelUsed == null && m.completionTokens == null && m.promptTokens == null && m.durationMs == null && m.id !== proposalHostId;
2197
+ const kept = [];
2198
+ const messages = [];
2199
+ for (const block of blocks) {
2200
+ if (block.kind === "status") {
2201
+ kept.push(block);
2202
+ continue;
2203
+ }
2204
+ const visible = block.messages.filter((m) => !isEmptyShell(m));
2205
+ if (visible.length > 0) {
2206
+ kept.push({ kind: "run", messages: visible });
2207
+ messages.push(...visible);
2208
+ }
2209
+ }
2127
2210
  return {
2128
- messages: messages.filter((m) => !isEmptyShell(m)),
2211
+ blocks: kept,
2212
+ messages,
2129
2213
  proposalHostId,
2130
2214
  metricsHostId: currentTurnAssistant && !isEmptyShell(currentTurnAssistant) ? currentTurnAssistant.id : null,
2131
2215
  confirmedResults
@@ -2140,6 +2224,20 @@ function ProposalSlot({
2140
2224
  }) {
2141
2225
  return /* @__PURE__ */ jsx4(Fragment, { children: render(proposal) });
2142
2226
  }
2227
+ function StatusRow({
2228
+ text,
2229
+ result,
2230
+ renderConfirmedResult
2231
+ }) {
2232
+ const confirmed = result && renderConfirmedResult ? renderConfirmedResult(result) : null;
2233
+ return /* @__PURE__ */ jsxs3("div", { className: "mx-auto w-full max-w-3xl px-6 py-1", children: [
2234
+ /* @__PURE__ */ jsxs3("p", { className: "flex items-center justify-center gap-1.5 text-center text-muted-foreground text-xs", children: [
2235
+ /* @__PURE__ */ jsx4(Check, { "aria-hidden": "true", className: "h-3.5 w-3.5 shrink-0" }),
2236
+ text
2237
+ ] }),
2238
+ confirmed ? /* @__PURE__ */ jsx4("div", { className: "mt-3", children: confirmed }) : null
2239
+ ] });
2240
+ }
2143
2241
  function AssistantTranscript({
2144
2242
  view,
2145
2243
  renderMarkdown,
@@ -2147,7 +2245,7 @@ function AssistantTranscript({
2147
2245
  renderConfirmedResult,
2148
2246
  emptyState
2149
2247
  }) {
2150
- const { messages, proposalHostId, metricsHostId, confirmedResults } = useMemo2(
2248
+ const { blocks, proposalHostId, metricsHostId, confirmedResults } = useMemo2(
2151
2249
  () => adaptTranscript(view),
2152
2250
  [view]
2153
2251
  );
@@ -2155,43 +2253,51 @@ function AssistantTranscript({
2155
2253
  (content) => renderMarkdown ? renderMarkdown(content) : content,
2156
2254
  [renderMarkdown]
2157
2255
  );
2158
- if (messages.length === 0 && !view.isStreaming) {
2256
+ if (blocks.length === 0 && !view.isStreaming) {
2159
2257
  return /* @__PURE__ */ jsx4(Fragment, { children: emptyState });
2160
2258
  }
2161
- return /* @__PURE__ */ jsx4(
2162
- ChatMessages,
2163
- {
2164
- messages,
2165
- loading: view.isStreaming,
2166
- agentLabel: "Assistant",
2167
- renderMarkdown: markdown,
2168
- toolRenderers,
2169
- renderEmpty: () => /* @__PURE__ */ jsx4(Fragment, { children: emptyState }),
2170
- renderExtras: (message) => {
2171
- const proposals = message.id === proposalHostId && view.pendingProposals.length > 0 ? /* @__PURE__ */ jsx4("div", { className: "mt-3 flex flex-col gap-3", children: view.pendingProposals.map((proposal) => /* @__PURE__ */ jsx4(
2172
- ProposalSlot,
2173
- {
2174
- proposal,
2175
- render: view.renderProposal
2176
- },
2177
- proposal.callId
2178
- )) }) : null;
2179
- const confirmed = confirmedResults.get(message.id);
2180
- const confirmedNode = confirmed && renderConfirmedResult ? renderConfirmedResult(confirmed) : null;
2181
- const confirmedCard = confirmedNode ? /* @__PURE__ */ jsx4("div", { className: "mt-3", children: confirmedNode }) : null;
2182
- const cost = message.id === metricsHostId && !view.isStreaming && view.usage?.costUsd != null && !view.usage.replayed ? /* @__PURE__ */ jsxs3("p", { className: "mt-1 text-[11px] text-muted-foreground", children: [
2183
- formatTurnCost(view.usage.costUsd),
2184
- " this turn"
2185
- ] }) : null;
2186
- if (!proposals && !cost && !confirmedCard) return null;
2187
- return /* @__PURE__ */ jsxs3(Fragment, { children: [
2188
- confirmedCard,
2189
- proposals,
2190
- cost
2191
- ] });
2192
- }
2193
- }
2194
- );
2259
+ const extras = (message) => {
2260
+ const proposals = message.id === proposalHostId && view.pendingProposals.length > 0 ? /* @__PURE__ */ jsx4("div", { className: "mt-3 flex flex-col gap-3", children: view.pendingProposals.map((proposal) => /* @__PURE__ */ jsx4(
2261
+ ProposalSlot,
2262
+ {
2263
+ proposal,
2264
+ render: view.renderProposal
2265
+ },
2266
+ proposal.callId
2267
+ )) }) : null;
2268
+ const cost = message.id === metricsHostId && !view.isStreaming && view.usage?.costUsd != null && !view.usage.replayed ? /* @__PURE__ */ jsxs3("p", { className: "mt-1 text-xs text-muted-foreground", children: [
2269
+ formatTurnCost(view.usage.costUsd),
2270
+ " this turn"
2271
+ ] }) : null;
2272
+ if (!proposals && !cost) return null;
2273
+ return /* @__PURE__ */ jsxs3(Fragment, { children: [
2274
+ proposals,
2275
+ cost
2276
+ ] });
2277
+ };
2278
+ return /* @__PURE__ */ jsx4(Fragment, { children: blocks.map(
2279
+ (block, i) => block.kind === "status" ? /* @__PURE__ */ jsx4(
2280
+ StatusRow,
2281
+ {
2282
+ text: block.text,
2283
+ result: confirmedResults.get(block.id),
2284
+ renderConfirmedResult
2285
+ },
2286
+ block.id
2287
+ ) : /* @__PURE__ */ jsx4(
2288
+ ChatMessages,
2289
+ {
2290
+ messages: block.messages,
2291
+ loading: view.isStreaming && i === blocks.length - 1,
2292
+ agentLabel: "Assistant",
2293
+ chrome: "quiet",
2294
+ renderMarkdown: markdown,
2295
+ toolRenderers,
2296
+ renderExtras: extras
2297
+ },
2298
+ i
2299
+ )
2300
+ ) });
2195
2301
  }
2196
2302
 
2197
2303
  // src/assistant/usePanelPrefs.ts
@@ -2338,7 +2444,11 @@ function useStickToBottom(ref, { enabled, contentSignature, streamingId, threadI
2338
2444
 
2339
2445
  // src/assistant/AssistantPanel.tsx
2340
2446
  import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
2341
- var EMPTY_STATE = "Ask me to create a workflow, check your usage, or manage your API keys.";
2447
+ var EMPTY_DOORS = [
2448
+ { label: "Create a workflow", seed: "Create a workflow that " },
2449
+ { label: "Check usage", seed: "What did my workflows cost this week?" },
2450
+ { label: "Manage API keys", seed: "Create an API key named " }
2451
+ ];
2342
2452
  function defaultFormatMoney(usd) {
2343
2453
  if (usd == null) return "\u2014";
2344
2454
  return new Intl.NumberFormat("en-US", {
@@ -2400,6 +2510,7 @@ function AssistantPanel({
2400
2510
  const models = useAssistantModels();
2401
2511
  const threads = useAssistantThreads(userId);
2402
2512
  const font = useFontScale();
2513
+ const [doorSeed, setDoorSeed] = useState6(null);
2403
2514
  const [view, setView] = useState6("chat");
2404
2515
  const historyButtonRef = useRef6(null);
2405
2516
  const logRef = useRef6(null);
@@ -2447,12 +2558,16 @@ function AssistantPanel({
2447
2558
  state.status,
2448
2559
  state.pendingProposals
2449
2560
  ]);
2561
+ const emptyThread = state.messages.length === 0 && state.status !== "streaming";
2450
2562
  const { onScroll: handleConversationScroll } = useStickToBottom(logRef, {
2451
- enabled: view === "chat",
2563
+ enabled: view === "chat" && !emptyThread,
2452
2564
  contentSignature,
2453
2565
  streamingId: state.streamingId,
2454
2566
  threadId: state.threadId
2455
2567
  });
2568
+ useLayoutEffect2(() => {
2569
+ if (emptyThread && logRef.current) logRef.current.scrollTop = 0;
2570
+ }, [emptyThread]);
2456
2571
  const effectiveBalance = state.usage?.balanceUsd ?? balanceUsd;
2457
2572
  const errorView = state.error ? presentError(state.error.code, state.error.message) : null;
2458
2573
  const low = isLowBalance(effectiveBalance) && !errorView;
@@ -2509,8 +2624,8 @@ function AssistantPanel({
2509
2624
  /* @__PURE__ */ jsx5("div", { className: "border-border border-b", children: /* @__PURE__ */ jsxs4("div", { className: "flex items-center justify-between gap-2 px-4 pt-3 pb-2.5", children: [
2510
2625
  /* @__PURE__ */ jsxs4("div", { className: "flex min-w-0 flex-col", children: [
2511
2626
  /* @__PURE__ */ jsxs4("div", { className: "flex items-baseline gap-2", children: [
2512
- /* @__PURE__ */ jsx5("span", { className: "font-medium text-foreground text-sm", children: "Assistant" }),
2513
- /* @__PURE__ */ jsx5(
2627
+ /* @__PURE__ */ jsx5("span", { className: "font-semibold text-[15px] text-foreground", children: "Assistant" }),
2628
+ effectiveBalance != null && /* @__PURE__ */ jsx5(
2514
2629
  "span",
2515
2630
  {
2516
2631
  "aria-label": "Your credit balance",
@@ -2639,7 +2754,18 @@ function AssistantPanel({
2639
2754
  renderMarkdown,
2640
2755
  toolRenderers,
2641
2756
  renderConfirmedResult,
2642
- emptyState: /* @__PURE__ */ jsx5("p", { className: "px-4 py-8 text-center text-muted-foreground text-sm", children: EMPTY_STATE })
2757
+ emptyState: /* @__PURE__ */ jsx5(
2758
+ ChatEmptyState,
2759
+ {
2760
+ productName: "Assistant",
2761
+ headline: "Ask the assistant to do something",
2762
+ subline: "Create workflows, check usage, or manage API keys \u2014 I'll pause for approval before anything changes.",
2763
+ doors: EMPTY_DOORS.map((door) => ({
2764
+ label: door.label,
2765
+ onSelect: () => setDoorSeed(door.seed)
2766
+ }))
2767
+ }
2768
+ )
2643
2769
  }
2644
2770
  ) })
2645
2771
  )
@@ -2649,21 +2775,37 @@ function AssistantPanel({
2649
2775
  "div",
2650
2776
  {
2651
2777
  role: "alert",
2652
- className: "mx-4 mb-2 rounded-lg border border-destructive/40 bg-destructive/5 px-3 py-2 text-sm",
2778
+ className: "mx-4 mb-2 flex items-start gap-2.5 rounded-lg border border-destructive/40 bg-destructive/5 px-3 py-2.5 text-destructive text-sm",
2653
2779
  children: [
2654
- /* @__PURE__ */ jsx5("p", { className: "text-foreground", children: errorView.message }),
2655
- errorView.cta && /* @__PURE__ */ jsxs4(
2656
- "button",
2780
+ /* @__PURE__ */ jsxs4(
2781
+ "svg",
2657
2782
  {
2658
- type: "button",
2659
- onClick: () => navigate?.(errorView.cta?.to ?? ""),
2660
- className: "mt-1 text-primary text-xs",
2783
+ className: "mt-0.5 h-4 w-4 shrink-0",
2784
+ viewBox: "0 0 24 24",
2785
+ fill: "none",
2786
+ stroke: "currentColor",
2787
+ strokeWidth: "2",
2788
+ strokeLinecap: "round",
2789
+ strokeLinejoin: "round",
2790
+ "aria-hidden": "true",
2661
2791
  children: [
2662
- errorView.cta.label,
2663
- " \u2192"
2792
+ /* @__PURE__ */ jsx5("circle", { cx: "12", cy: "12", r: "9" }),
2793
+ /* @__PURE__ */ jsx5("path", { d: "M12 8v4m0 4h.01" })
2664
2794
  ]
2665
2795
  }
2666
- )
2796
+ ),
2797
+ /* @__PURE__ */ jsxs4("div", { className: "min-w-0 flex-1", children: [
2798
+ /* @__PURE__ */ jsx5("p", { children: errorView.message }),
2799
+ errorView.cta && /* @__PURE__ */ jsx5(
2800
+ "button",
2801
+ {
2802
+ type: "button",
2803
+ onClick: () => navigate?.(errorView.cta?.to ?? ""),
2804
+ className: "mt-1.5 rounded border border-destructive/40 bg-card px-2 py-0.5 font-medium text-xs text-destructive transition hover:bg-destructive/10",
2805
+ children: errorView.cta.label
2806
+ }
2807
+ )
2808
+ ] })
2667
2809
  ]
2668
2810
  }
2669
2811
  ),
@@ -2692,7 +2834,7 @@ function AssistantPanel({
2692
2834
  role: "status",
2693
2835
  className: "mx-4 mb-2 flex items-center gap-3 rounded-lg border border-border bg-secondary px-3 py-2 text-sm",
2694
2836
  children: [
2695
- /* @__PURE__ */ jsx5("p", { className: "min-w-0 flex-1 text-foreground", children: "Paused after a lot of steps." }),
2837
+ /* @__PURE__ */ jsx5("p", { className: "min-w-0 flex-1 text-foreground", children: "Paused at the step limit." }),
2696
2838
  /* @__PURE__ */ jsx5(
2697
2839
  "button",
2698
2840
  {
@@ -2721,9 +2863,12 @@ function AssistantPanel({
2721
2863
  onCancel: chat.stop,
2722
2864
  isStreaming: streaming,
2723
2865
  disabled: chat.restoring || state.status === "awaiting_confirm",
2724
- placeholder: "Message the assistant\u2026",
2725
- seed: composerSeed,
2726
- onSeedApplied: onComposerSeedApplied,
2866
+ placeholder: state.status === "awaiting_confirm" ? "Confirm or cancel the proposal above to continue" : "Message the assistant\u2026",
2867
+ seed: doorSeed ?? composerSeed,
2868
+ onSeedApplied: () => {
2869
+ setDoorSeed(null);
2870
+ onComposerSeedApplied?.();
2871
+ },
2727
2872
  onAttach: composerAttachments?.onAttach,
2728
2873
  onAttachFolder: composerAttachments?.onAttachFolder,
2729
2874
  pendingFiles: composerAttachments?.pendingFiles,
@@ -2934,7 +3079,7 @@ function AssistantDock({
2934
3079
  type: "button",
2935
3080
  onClick: openDialog,
2936
3081
  "aria-label": "Open assistant",
2937
- className: "fixed right-4 bottom-4 z-40 flex h-12 w-12 items-center justify-center rounded-full bg-primary text-primary-foreground shadow-raised transition-colors hover:opacity-90 focus:outline-none focus:ring-2 focus:ring-ring",
3082
+ className: "fixed right-4 bottom-4 z-40 flex h-12 w-12 items-center justify-center rounded-full bg-primary text-primary-foreground shadow-[var(--shadow-overlay)] transition-colors hover:bg-primary/90 focus:outline-none focus:ring-2 focus:ring-ring",
2938
3083
  children: /* @__PURE__ */ jsx8(MessageSquare, { className: "h-6 w-6" })
2939
3084
  }
2940
3085
  );
@@ -2982,7 +3127,7 @@ function AssistantDock({
2982
3127
  tabIndex: -1,
2983
3128
  onKeyDown: trapTab,
2984
3129
  style: isDesktop ? { width: `${width}px` } : void 0,
2985
- className: `fixed inset-y-0 right-0 z-50 flex w-full flex-col border-card-edge border-l ${OVERLAY_SHADOW} focus:outline-none`,
3130
+ className: "fixed inset-y-0 right-0 z-50 flex w-full flex-col border-card-edge border-l shadow-[var(--shadow-overlay)] focus:outline-none",
2986
3131
  children: [
2987
3132
  /* @__PURE__ */ jsx8(
2988
3133
  AssistantPanel,