@chances-ai/client 24.0.0

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 (121) hide show
  1. package/dist/client-core/client.d.ts +145 -0
  2. package/dist/client-core/client.d.ts.map +1 -0
  3. package/dist/client-core/client.js +533 -0
  4. package/dist/client-core/client.js.map +1 -0
  5. package/dist/client-core/index.d.ts +16 -0
  6. package/dist/client-core/index.d.ts.map +1 -0
  7. package/dist/client-core/index.js +15 -0
  8. package/dist/client-core/index.js.map +1 -0
  9. package/dist/client-core/reverse-map.d.ts +66 -0
  10. package/dist/client-core/reverse-map.d.ts.map +1 -0
  11. package/dist/client-core/reverse-map.js +86 -0
  12. package/dist/client-core/reverse-map.js.map +1 -0
  13. package/dist/client-core/store.d.ts +144 -0
  14. package/dist/client-core/store.d.ts.map +1 -0
  15. package/dist/client-core/store.js +36 -0
  16. package/dist/client-core/store.js.map +1 -0
  17. package/dist/client-core/transport.d.ts +53 -0
  18. package/dist/client-core/transport.d.ts.map +1 -0
  19. package/dist/client-core/transport.js +103 -0
  20. package/dist/client-core/transport.js.map +1 -0
  21. package/dist/web-ui/approval-badge.d.ts +17 -0
  22. package/dist/web-ui/approval-badge.d.ts.map +1 -0
  23. package/dist/web-ui/approval-badge.js +24 -0
  24. package/dist/web-ui/approval-badge.js.map +1 -0
  25. package/dist/web-ui/button.d.ts +10 -0
  26. package/dist/web-ui/button.d.ts.map +1 -0
  27. package/dist/web-ui/button.js +16 -0
  28. package/dist/web-ui/button.js.map +1 -0
  29. package/dist/web-ui/code-view.d.ts +6 -0
  30. package/dist/web-ui/code-view.d.ts.map +1 -0
  31. package/dist/web-ui/code-view.js +14 -0
  32. package/dist/web-ui/code-view.js.map +1 -0
  33. package/dist/web-ui/code-viewer.d.ts +11 -0
  34. package/dist/web-ui/code-viewer.d.ts.map +1 -0
  35. package/dist/web-ui/code-viewer.js +55 -0
  36. package/dist/web-ui/code-viewer.js.map +1 -0
  37. package/dist/web-ui/commands.d.ts +23 -0
  38. package/dist/web-ui/commands.d.ts.map +1 -0
  39. package/dist/web-ui/commands.js +26 -0
  40. package/dist/web-ui/commands.js.map +1 -0
  41. package/dist/web-ui/control-panel.d.ts +9 -0
  42. package/dist/web-ui/control-panel.d.ts.map +1 -0
  43. package/dist/web-ui/control-panel.js +70 -0
  44. package/dist/web-ui/control-panel.js.map +1 -0
  45. package/dist/web-ui/diff-view.d.ts +8 -0
  46. package/dist/web-ui/diff-view.d.ts.map +1 -0
  47. package/dist/web-ui/diff-view.js +28 -0
  48. package/dist/web-ui/diff-view.js.map +1 -0
  49. package/dist/web-ui/environment-panel.d.ts +9 -0
  50. package/dist/web-ui/environment-panel.d.ts.map +1 -0
  51. package/dist/web-ui/environment-panel.js +38 -0
  52. package/dist/web-ui/environment-panel.js.map +1 -0
  53. package/dist/web-ui/file-tree.d.ts +9 -0
  54. package/dist/web-ui/file-tree.d.ts.map +1 -0
  55. package/dist/web-ui/file-tree.js +77 -0
  56. package/dist/web-ui/file-tree.js.map +1 -0
  57. package/dist/web-ui/help-view.d.ts +13 -0
  58. package/dist/web-ui/help-view.d.ts.map +1 -0
  59. package/dist/web-ui/help-view.js +15 -0
  60. package/dist/web-ui/help-view.js.map +1 -0
  61. package/dist/web-ui/helpers.d.ts +77 -0
  62. package/dist/web-ui/helpers.d.ts.map +1 -0
  63. package/dist/web-ui/helpers.js +176 -0
  64. package/dist/web-ui/helpers.js.map +1 -0
  65. package/dist/web-ui/hooks.d.ts +7 -0
  66. package/dist/web-ui/hooks.d.ts.map +1 -0
  67. package/dist/web-ui/hooks.js +26 -0
  68. package/dist/web-ui/hooks.js.map +1 -0
  69. package/dist/web-ui/index.d.ts +32 -0
  70. package/dist/web-ui/index.d.ts.map +1 -0
  71. package/dist/web-ui/index.js +38 -0
  72. package/dist/web-ui/index.js.map +1 -0
  73. package/dist/web-ui/markdown.d.ts +12 -0
  74. package/dist/web-ui/markdown.d.ts.map +1 -0
  75. package/dist/web-ui/markdown.js +55 -0
  76. package/dist/web-ui/markdown.js.map +1 -0
  77. package/dist/web-ui/model-picker.d.ts +9 -0
  78. package/dist/web-ui/model-picker.d.ts.map +1 -0
  79. package/dist/web-ui/model-picker.js +119 -0
  80. package/dist/web-ui/model-picker.js.map +1 -0
  81. package/dist/web-ui/permission.d.ts +7 -0
  82. package/dist/web-ui/permission.d.ts.map +1 -0
  83. package/dist/web-ui/permission.js +25 -0
  84. package/dist/web-ui/permission.js.map +1 -0
  85. package/dist/web-ui/primitives.d.ts +59 -0
  86. package/dist/web-ui/primitives.d.ts.map +1 -0
  87. package/dist/web-ui/primitives.js +38 -0
  88. package/dist/web-ui/primitives.js.map +1 -0
  89. package/dist/web-ui/progress.d.ts +28 -0
  90. package/dist/web-ui/progress.d.ts.map +1 -0
  91. package/dist/web-ui/progress.js +45 -0
  92. package/dist/web-ui/progress.js.map +1 -0
  93. package/dist/web-ui/prompt-input.d.ts +15 -0
  94. package/dist/web-ui/prompt-input.d.ts.map +1 -0
  95. package/dist/web-ui/prompt-input.js +129 -0
  96. package/dist/web-ui/prompt-input.js.map +1 -0
  97. package/dist/web-ui/question-view.d.ts +7 -0
  98. package/dist/web-ui/question-view.d.ts.map +1 -0
  99. package/dist/web-ui/question-view.js +60 -0
  100. package/dist/web-ui/question-view.js.map +1 -0
  101. package/dist/web-ui/segments.d.ts +8 -0
  102. package/dist/web-ui/segments.d.ts.map +1 -0
  103. package/dist/web-ui/segments.js +19 -0
  104. package/dist/web-ui/segments.js.map +1 -0
  105. package/dist/web-ui/session-sidebar.d.ts +15 -0
  106. package/dist/web-ui/session-sidebar.d.ts.map +1 -0
  107. package/dist/web-ui/session-sidebar.js +10 -0
  108. package/dist/web-ui/session-sidebar.js.map +1 -0
  109. package/dist/web-ui/status-bar.d.ts +10 -0
  110. package/dist/web-ui/status-bar.d.ts.map +1 -0
  111. package/dist/web-ui/status-bar.js +10 -0
  112. package/dist/web-ui/status-bar.js.map +1 -0
  113. package/dist/web-ui/theme-context.d.ts +13 -0
  114. package/dist/web-ui/theme-context.d.ts.map +1 -0
  115. package/dist/web-ui/theme-context.js +31 -0
  116. package/dist/web-ui/theme-context.js.map +1 -0
  117. package/dist/web-ui/transcript.d.ts +27 -0
  118. package/dist/web-ui/transcript.d.ts.map +1 -0
  119. package/dist/web-ui/transcript.js +56 -0
  120. package/dist/web-ui/transcript.js.map +1 -0
  121. package/package.json +56 -0
@@ -0,0 +1,59 @@
1
+ /**
2
+ * (v22 / docs/6.5b §C1) Minimal DOM layout primitives — the replacement for the
3
+ * `@tamagui/core` `View`/`Text` the web panel used before v22 retired Tamagui.
4
+ *
5
+ * `Box` is a flexbox `<div>` and `Txt` a `<span>`, both accepting the small set
6
+ * of style props the panel actually uses, mapped 1:1 onto inline `style`. Keeping
7
+ * the SAME prop names as the old Tamagui primitives makes the component port a
8
+ * mechanical import-swap with no layout drift (Tamagui `View` also defaulted to
9
+ * `flex-direction: column`, preserved here). Chrome colors are passed as
10
+ * `var(--ch-*)` custom properties (set on the panel root from ui-core's
11
+ * `themeCssVars`); content colors come straight from the ui-core `Theme`.
12
+ *
13
+ * This is deliberately NOT a styling system — HeroUI v3 owns the interactive
14
+ * components (modals, pickers, tabs); these two primitives only lay out the
15
+ * bespoke panel chrome + transcript rows.
16
+ */
17
+ import type { CSSProperties, ReactNode } from "react";
18
+ export interface BoxProps {
19
+ children?: ReactNode;
20
+ flexDirection?: "row" | "column";
21
+ gap?: number;
22
+ padding?: number;
23
+ paddingHorizontal?: number;
24
+ paddingVertical?: number;
25
+ paddingLeft?: number;
26
+ alignItems?: CSSProperties["alignItems"];
27
+ alignSelf?: CSSProperties["alignSelf"];
28
+ justifyContent?: CSSProperties["justifyContent"];
29
+ flex?: number;
30
+ flexWrap?: CSSProperties["flexWrap"];
31
+ maxWidth?: number | string;
32
+ backgroundColor?: string;
33
+ borderWidth?: number;
34
+ borderTopWidth?: number;
35
+ borderBottomWidth?: number;
36
+ borderColor?: string;
37
+ borderRadius?: number;
38
+ marginTop?: number;
39
+ opacity?: number;
40
+ overflow?: CSSProperties["overflow"];
41
+ /** Escape hatch for one-off CSS (merged last). */
42
+ style?: CSSProperties;
43
+ className?: string;
44
+ }
45
+ /** A flexbox `<div>` (defaults to a column, matching the old Tamagui `View`). */
46
+ export declare function Box({ children, flexDirection, gap, padding, paddingHorizontal, paddingVertical, paddingLeft, alignItems, alignSelf, justifyContent, flex, flexWrap, maxWidth, backgroundColor, borderWidth, borderTopWidth, borderBottomWidth, borderColor, borderRadius, marginTop, opacity, overflow, style, className, }: BoxProps): import("react/jsx-runtime").JSX.Element;
47
+ export interface TxtProps {
48
+ children?: ReactNode;
49
+ color?: string;
50
+ backgroundColor?: string;
51
+ fontWeight?: CSSProperties["fontWeight"];
52
+ fontSize?: number;
53
+ flex?: number;
54
+ style?: CSSProperties;
55
+ className?: string;
56
+ }
57
+ /** An inline `<span>` carrying text color/weight/size. */
58
+ export declare function Txt({ children, color, backgroundColor, fontWeight, fontSize, flex, style, className }: TxtProps): import("react/jsx-runtime").JSX.Element;
59
+ //# sourceMappingURL=primitives.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"primitives.d.ts","sourceRoot":"","sources":["../../src/web-ui/primitives.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEtD,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,aAAa,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC;IACjC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACzC,SAAS,CAAC,EAAE,aAAa,CAAC,WAAW,CAAC,CAAC;IACvC,cAAc,CAAC,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC;IACjD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IACrC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IACrC,kDAAkD;IAClD,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,iFAAiF;AACjF,wBAAgB,GAAG,CAAC,EAClB,QAAQ,EACR,aAAwB,EACxB,GAAG,EACH,OAAO,EACP,iBAAiB,EACjB,eAAe,EACf,WAAW,EACX,UAAU,EACV,SAAS,EACT,cAAc,EACd,IAAI,EACJ,QAAQ,EACR,QAAQ,EACR,eAAe,EACf,WAAW,EACX,cAAc,EACd,iBAAiB,EACjB,WAAW,EACX,YAAY,EACZ,SAAS,EACT,OAAO,EACP,QAAQ,EACR,KAAK,EACL,SAAS,GACV,EAAE,QAAQ,2CAiCV;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,0DAA0D;AAC1D,wBAAgB,GAAG,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,QAAQ,2CAO/G"}
@@ -0,0 +1,38 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /** A flexbox `<div>` (defaults to a column, matching the old Tamagui `View`). */
3
+ export function Box({ children, flexDirection = "column", gap, padding, paddingHorizontal, paddingVertical, paddingLeft, alignItems, alignSelf, justifyContent, flex, flexWrap, maxWidth, backgroundColor, borderWidth, borderTopWidth, borderBottomWidth, borderColor, borderRadius, marginTop, opacity, overflow, style, className, }) {
4
+ const css = {
5
+ display: "flex",
6
+ flexDirection,
7
+ gap,
8
+ padding,
9
+ paddingLeft: paddingHorizontal ?? paddingLeft,
10
+ paddingRight: paddingHorizontal,
11
+ paddingTop: paddingVertical,
12
+ paddingBottom: paddingVertical,
13
+ alignItems,
14
+ alignSelf,
15
+ justifyContent,
16
+ flex,
17
+ flexWrap,
18
+ maxWidth,
19
+ backgroundColor,
20
+ borderStyle: borderWidth || borderTopWidth || borderBottomWidth ? "solid" : undefined,
21
+ borderWidth,
22
+ borderTopWidth,
23
+ borderBottomWidth,
24
+ borderColor,
25
+ borderRadius,
26
+ marginTop,
27
+ opacity,
28
+ overflow,
29
+ ...style,
30
+ };
31
+ return (_jsx("div", { className: className, style: css, children: children }));
32
+ }
33
+ /** An inline `<span>` carrying text color/weight/size. */
34
+ export function Txt({ children, color, backgroundColor, fontWeight, fontSize, flex, style, className }) {
35
+ const css = { color, backgroundColor, fontWeight, fontSize, flex, ...style };
36
+ return (_jsx("span", { className: className, style: css, children: children }));
37
+ }
38
+ //# sourceMappingURL=primitives.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"primitives.js","sourceRoot":"","sources":["../../src/web-ui/primitives.tsx"],"names":[],"mappings":";AA8CA,iFAAiF;AACjF,MAAM,UAAU,GAAG,CAAC,EAClB,QAAQ,EACR,aAAa,GAAG,QAAQ,EACxB,GAAG,EACH,OAAO,EACP,iBAAiB,EACjB,eAAe,EACf,WAAW,EACX,UAAU,EACV,SAAS,EACT,cAAc,EACd,IAAI,EACJ,QAAQ,EACR,QAAQ,EACR,eAAe,EACf,WAAW,EACX,cAAc,EACd,iBAAiB,EACjB,WAAW,EACX,YAAY,EACZ,SAAS,EACT,OAAO,EACP,QAAQ,EACR,KAAK,EACL,SAAS,GACA;IACT,MAAM,GAAG,GAAkB;QACzB,OAAO,EAAE,MAAM;QACf,aAAa;QACb,GAAG;QACH,OAAO;QACP,WAAW,EAAE,iBAAiB,IAAI,WAAW;QAC7C,YAAY,EAAE,iBAAiB;QAC/B,UAAU,EAAE,eAAe;QAC3B,aAAa,EAAE,eAAe;QAC9B,UAAU;QACV,SAAS;QACT,cAAc;QACd,IAAI;QACJ,QAAQ;QACR,QAAQ;QACR,eAAe;QACf,WAAW,EAAE,WAAW,IAAI,cAAc,IAAI,iBAAiB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;QACrF,WAAW;QACX,cAAc;QACd,iBAAiB;QACjB,WAAW;QACX,YAAY;QACZ,SAAS;QACT,OAAO;QACP,QAAQ;QACR,GAAG,KAAK;KACT,CAAC;IACF,OAAO,CACL,cAAK,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,YAClC,QAAQ,GACL,CACP,CAAC;AACJ,CAAC;AAaD,0DAA0D;AAC1D,MAAM,UAAU,GAAG,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAY;IAC9G,MAAM,GAAG,GAAkB,EAAE,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,KAAK,EAAE,CAAC;IAC5F,OAAO,CACL,eAAM,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,YACnC,QAAQ,GACJ,CACR,CAAC;AACJ,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * (v22 / docs/6.5b §C6) The "thinking" progress line shown above the composer
3
+ * while a turn streams — the web twin of the TUI `Progress`:
4
+ * `✻ Crunching… (esc to interrupt · 8s)`. The animated glyph cycles the shared
5
+ * `SPINNER_FRAMES` on a single interval (cleared on unmount/inactive); the verb +
6
+ * elapsed come from the shared ui-core formatters. The web store carries no live
7
+ * streaming token count, so (unlike the terminal) tokens aren't shown here — the
8
+ * status bar surfaces the final usage.
9
+ *
10
+ * Reliability: `frameOverride` / `elapsedMsOverride` / `now` are injected test
11
+ * seams, so tests render a deterministic frame with NO interval + NO `Date.now()`.
12
+ * Under `reducedMotion` the glyph is static (no interval at all).
13
+ */
14
+ import { type JSX } from "react";
15
+ export interface ProgressProps {
16
+ active: boolean;
17
+ /** Verb to display. Omitted ⇒ a verb is picked once on mount. */
18
+ verb?: string;
19
+ reducedMotion?: boolean;
20
+ /** Test seam: fixed elapsed ms (skips the wall clock). */
21
+ elapsedMsOverride?: number;
22
+ /** Test seam: fixed frame index (skips the interval). */
23
+ frameOverride?: number;
24
+ /** Test seam: injected clock (defaults to `Date.now`). */
25
+ now?: () => number;
26
+ }
27
+ export declare function Progress({ active, verb, reducedMotion, elapsedMsOverride, frameOverride, now }: ProgressProps): JSX.Element | null;
28
+ //# sourceMappingURL=progress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress.d.ts","sourceRoot":"","sources":["../../src/web-ui/progress.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,KAAK,GAAG,EAA+B,MAAM,OAAO,CAAC;AAO9D,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,OAAO,CAAC;IAChB,iEAAiE;IACjE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,0DAA0D;IAC1D,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,yDAAyD;IACzD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,0DAA0D;IAC1D,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,wBAAgB,QAAQ,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,aAAqB,EAAE,iBAAiB,EAAE,aAAa,EAAE,GAAc,EAAE,EAAE,aAAa,GAAG,GAAG,CAAC,OAAO,GAAG,IAAI,CAiCrJ"}
@@ -0,0 +1,45 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * (v22 / docs/6.5b §C6) The "thinking" progress line shown above the composer
4
+ * while a turn streams — the web twin of the TUI `Progress`:
5
+ * `✻ Crunching… (esc to interrupt · 8s)`. The animated glyph cycles the shared
6
+ * `SPINNER_FRAMES` on a single interval (cleared on unmount/inactive); the verb +
7
+ * elapsed come from the shared ui-core formatters. The web store carries no live
8
+ * streaming token count, so (unlike the terminal) tokens aren't shown here — the
9
+ * status bar surfaces the final usage.
10
+ *
11
+ * Reliability: `frameOverride` / `elapsedMsOverride` / `now` are injected test
12
+ * seams, so tests render a deterministic frame with NO interval + NO `Date.now()`.
13
+ * Under `reducedMotion` the glyph is static (no interval at all).
14
+ */
15
+ import { useEffect, useRef, useState } from "react";
16
+ import { formatElapsed, pickVerb, SPINNER_FRAMES, SPINNER_STATIC } from "@chances-ai/ui-core";
17
+ import { Box, Txt } from "./primitives.js";
18
+ import { useUiTheme } from "./theme-context.js";
19
+ const TICK_MS = 120;
20
+ export function Progress({ active, verb, reducedMotion = false, elapsedMsOverride, frameOverride, now = Date.now }) {
21
+ const theme = useUiTheme();
22
+ const [frame, setFrame] = useState(0);
23
+ const [autoVerb] = useState(() => pickVerb(Math.floor(now() / 1000)));
24
+ const startRef = useRef(now());
25
+ // Reset the turn clock when the turn (re)starts.
26
+ useEffect(() => {
27
+ if (active)
28
+ startRef.current = now();
29
+ }, [active]); // eslint-disable-line react-hooks/exhaustive-deps
30
+ // Single pulse interval, cleared on unmount / when inactive / under a test seam.
31
+ useEffect(() => {
32
+ if (!active || reducedMotion || frameOverride !== undefined)
33
+ return;
34
+ const id = setInterval(() => setFrame((f) => (f + 1) % SPINNER_FRAMES.length), TICK_MS);
35
+ return () => clearInterval(id);
36
+ }, [active, reducedMotion, frameOverride]);
37
+ if (!active)
38
+ return null;
39
+ const elapsedMs = elapsedMsOverride ?? now() - startRef.current;
40
+ const glyphIndex = frameOverride ?? frame;
41
+ const glyph = reducedMotion ? SPINNER_STATIC : (SPINNER_FRAMES[glyphIndex % SPINNER_FRAMES.length] ?? "✻");
42
+ const text = `${verb ?? autoVerb}… (esc to interrupt · ${formatElapsed(elapsedMs)})`;
43
+ return (_jsxs(Box, { flexDirection: "row", gap: 6, alignItems: "baseline", children: [_jsx(Txt, { color: theme.accent, children: glyph }), _jsx(Txt, { color: theme.synComment, fontSize: 13, children: text })] }));
44
+ }
45
+ //# sourceMappingURL=progress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress.js","sourceRoot":"","sources":["../../src/web-ui/progress.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAY,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC9F,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhD,MAAM,OAAO,GAAG,GAAG,CAAC;AAepB,MAAM,UAAU,QAAQ,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,GAAG,GAAG,IAAI,CAAC,GAAG,EAAiB;IAC/H,MAAM,KAAK,GAAG,UAAU,EAAE,CAAC;IAC3B,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IACtC,MAAM,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACtE,MAAM,QAAQ,GAAG,MAAM,CAAS,GAAG,EAAE,CAAC,CAAC;IAEvC,iDAAiD;IACjD,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,MAAM;YAAE,QAAQ,CAAC,OAAO,GAAG,GAAG,EAAE,CAAC;IACvC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,kDAAkD;IAEhE,iFAAiF;IACjF,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,MAAM,IAAI,aAAa,IAAI,aAAa,KAAK,SAAS;YAAE,OAAO;QACpE,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,cAAc,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC;QACxF,OAAO,GAAG,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;IACjC,CAAC,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,aAAa,CAAC,CAAC,CAAC;IAE3C,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAEzB,MAAM,SAAS,GAAG,iBAAiB,IAAI,GAAG,EAAE,GAAG,QAAQ,CAAC,OAAO,CAAC;IAChE,MAAM,UAAU,GAAG,aAAa,IAAI,KAAK,CAAC;IAC1C,MAAM,KAAK,GAAG,aAAa,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,UAAU,GAAG,cAAc,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC;IAC3G,MAAM,IAAI,GAAG,GAAG,IAAI,IAAI,QAAQ,0BAA0B,aAAa,CAAC,SAAS,CAAC,GAAG,CAAC;IAEtF,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,KAAK,EAAC,GAAG,EAAE,CAAC,EAAE,UAAU,EAAC,UAAU,aACpD,KAAC,GAAG,IAAC,KAAK,EAAE,KAAK,CAAC,MAAM,YAAG,KAAK,GAAO,EACvC,KAAC,GAAG,IAAC,KAAK,EAAE,KAAK,CAAC,UAAU,EAAE,QAAQ,EAAE,EAAE,YACvC,IAAI,GACD,IACF,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { type WebCommand } from "./commands.js";
2
+ export interface PromptInputProps {
3
+ /** A turn is running ⇒ show Stop (abort) instead of Send, and block submit. */
4
+ busy: boolean;
5
+ /** No live connection ⇒ disable the box entirely. */
6
+ disabled: boolean;
7
+ onSubmit: (text: string) => void;
8
+ onAbort: () => void;
9
+ /** (v22) Client-side slash commands; enables the typeahead + slash dispatch. */
10
+ commands?: WebCommand[];
11
+ /** (v22) Run a slash command by name (the registry lives in the parent). */
12
+ onCommand?: (name: string) => void;
13
+ }
14
+ export declare function PromptInput({ busy, disabled, onSubmit, onAbort, commands, onCommand }: PromptInputProps): import("react/jsx-runtime").JSX.Element;
15
+ //# sourceMappingURL=prompt-input.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt-input.d.ts","sourceRoot":"","sources":["../../src/web-ui/prompt-input.tsx"],"names":[],"mappings":"AAYA,OAAO,EAAwC,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAMtF,MAAM,WAAW,gBAAgB;IAC/B,+EAA+E;IAC/E,IAAI,EAAE,OAAO,CAAC;IACd,qDAAqD;IACrD,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,gFAAgF;IAChF,QAAQ,CAAC,EAAE,UAAU,EAAE,CAAC;IACxB,4EAA4E;IAC5E,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC;AAED,wBAAgB,WAAW,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,gBAAgB,2CAuJvG"}
@@ -0,0 +1,129 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ /**
3
+ * (v17 M1 B3; v22) The prompt composer. A native `<textarea>` (inline-styled from
4
+ * the ui-core palette) + a Send / Stop affordance. Enter submits, Shift+Enter
5
+ * inserts a newline, IME composition is respected (the pure `shouldSubmit`).
6
+ *
7
+ * (v22) When `commands` is supplied, typing a leading `/<word>` opens a slash
8
+ * typeahead (↑↓ move, Tab completes, Enter runs the highlighted command, Esc
9
+ * dismisses); submitting a `/command` runs it via `onCommand` instead of sending
10
+ * it as a prompt. Esc while a turn streams interrupts it (the web twin of the TUI
11
+ * chat:cancel) — but the typeahead owns Esc first when it's open.
12
+ */
13
+ import { useState } from "react";
14
+ import { parseCommandName, suggestWebCommands } from "./commands.js";
15
+ import { Button } from "./button.js";
16
+ import { MONO, shouldSubmit } from "./helpers.js";
17
+ import { Box } from "./primitives.js";
18
+ import { useUiTheme } from "./theme-context.js";
19
+ export function PromptInput({ busy, disabled, onSubmit, onAbort, commands, onCommand }) {
20
+ const theme = useUiTheme();
21
+ const [text, setText] = useState("");
22
+ const [cursor, setCursor] = useState(0);
23
+ const suggestions = commands ? suggestWebCommands(text, commands) : [];
24
+ const typeaheadOpen = suggestions.length > 0;
25
+ const border = theme.synComment ?? "#555";
26
+ const runCommand = (name) => {
27
+ onCommand?.(name);
28
+ setText("");
29
+ setCursor(0);
30
+ };
31
+ const submit = () => {
32
+ const trimmed = text.trim();
33
+ if (!trimmed || busy || disabled)
34
+ return;
35
+ // A KNOWN `/command` runs client-side; anything else (incl. an unknown slash)
36
+ // is sent as a prompt — never a silent no-op (codex v22 SHOULD).
37
+ if (trimmed.startsWith("/") && onCommand && commands?.some((c) => c.name === parseCommandName(trimmed))) {
38
+ runCommand(parseCommandName(trimmed));
39
+ return;
40
+ }
41
+ onSubmit(trimmed);
42
+ setText("");
43
+ };
44
+ const onKeyDown = (e) => {
45
+ if (typeaheadOpen) {
46
+ if (e.key === "ArrowDown") {
47
+ e.preventDefault();
48
+ setCursor((c) => Math.min(suggestions.length - 1, c + 1));
49
+ return;
50
+ }
51
+ if (e.key === "ArrowUp") {
52
+ e.preventDefault();
53
+ setCursor((c) => Math.max(0, c - 1));
54
+ return;
55
+ }
56
+ if (e.key === "Tab") {
57
+ e.preventDefault();
58
+ const pick = suggestions[Math.min(cursor, suggestions.length - 1)];
59
+ if (pick)
60
+ setText(`/${pick.name} `);
61
+ return;
62
+ }
63
+ if (e.key === "Enter" && !e.shiftKey) {
64
+ e.preventDefault();
65
+ const pick = suggestions[Math.min(cursor, suggestions.length - 1)];
66
+ if (pick)
67
+ runCommand(pick.name);
68
+ return;
69
+ }
70
+ if (e.key === "Escape") {
71
+ e.preventDefault();
72
+ setText(""); // dismiss the typeahead
73
+ return;
74
+ }
75
+ }
76
+ // (v22) Esc while a turn streams interrupts it (no typeahead open).
77
+ if (e.key === "Escape" && busy) {
78
+ e.preventDefault();
79
+ onAbort();
80
+ return;
81
+ }
82
+ if (shouldSubmit(e)) {
83
+ e.preventDefault();
84
+ submit();
85
+ }
86
+ };
87
+ return (_jsxs(Box, { style: { position: "relative" }, children: [typeaheadOpen ? (_jsx("div", { role: "listbox", "aria-label": "slash commands", style: {
88
+ position: "absolute",
89
+ bottom: "calc(100% + 4px)",
90
+ left: 0,
91
+ right: 0,
92
+ zIndex: 10,
93
+ maxHeight: 240,
94
+ overflowY: "auto",
95
+ background: "var(--ch-bg)",
96
+ border: `1px solid ${border}`,
97
+ borderRadius: 8,
98
+ padding: 6,
99
+ display: "flex",
100
+ flexDirection: "column",
101
+ gap: 2,
102
+ }, children: suggestions.map((c, i) => (_jsxs("div", { role: "option", "aria-selected": i === cursor, onMouseEnter: () => setCursor(i), onMouseDown: (e) => {
103
+ e.preventDefault(); // keep textarea focus
104
+ runCommand(c.name);
105
+ }, style: {
106
+ fontFamily: MONO,
107
+ fontSize: 13,
108
+ padding: "4px 6px",
109
+ borderRadius: 6,
110
+ cursor: "pointer",
111
+ background: i === cursor ? theme.userMessageBg : "transparent",
112
+ color: "var(--ch-fg)",
113
+ }, children: [_jsxs("span", { style: { color: theme.accent }, children: ["/", c.name] }), _jsxs("span", { style: { color: theme.synComment }, children: [" \u2014 ", c.description] })] }, c.name))) })) : null, _jsxs(Box, { flexDirection: "row", gap: 8, alignItems: "flex-end", children: [_jsx("textarea", { value: text, rows: 2, disabled: disabled, onChange: (e) => {
114
+ setText(e.target.value);
115
+ setCursor(0);
116
+ }, onKeyDown: onKeyDown, placeholder: disabled ? "connecting…" : "Message the agent — Enter to send, Shift+Enter for newline, / for commands", style: {
117
+ flex: 1,
118
+ resize: "vertical",
119
+ fontFamily: MONO,
120
+ fontSize: 14,
121
+ padding: 8,
122
+ borderRadius: 8,
123
+ background: "transparent",
124
+ color: "inherit",
125
+ border: `1px solid ${border}`,
126
+ outline: "none",
127
+ } }), busy ? (_jsx(Button, { label: "Stop", color: theme.error, onPress: onAbort })) : (_jsx(Button, { label: "Send", color: theme.accent, onPress: submit, disabled: disabled }))] })] }));
128
+ }
129
+ //# sourceMappingURL=prompt-input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt-input.js","sourceRoot":"","sources":["../../src/web-ui/prompt-input.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { PendingQuestion, QuestionAnswer } from "../client-core/index.js";
2
+ export interface QuestionViewProps {
3
+ pending: PendingQuestion;
4
+ onAnswer: (answer: QuestionAnswer) => void;
5
+ }
6
+ export declare function QuestionView({ pending, onAnswer }: QuestionViewProps): import("react/jsx-runtime").JSX.Element;
7
+ //# sourceMappingURL=question-view.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"question-view.d.ts","sourceRoot":"","sources":["../../src/web-ui/question-view.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAQ/E,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,eAAe,CAAC;IACzB,QAAQ,EAAE,CAAC,MAAM,EAAE,cAAc,KAAK,IAAI,CAAC;CAC5C;AAED,wBAAgB,YAAY,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,iBAAiB,2CAqFpE"}
@@ -0,0 +1,60 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ /**
3
+ * (v22 / docs/6.5b §C7) The `ask_user_question` UI — the web answer to the TUI's
4
+ * tabbed QuestionView. On the web a STACKED form reads more naturally than tabs:
5
+ * each question renders its prompt + options (radio for single-select, checkbox
6
+ * for multi) + an optional "Other" free-text row; Submit sends the answers map,
7
+ * Cancel declines. Native inputs (real radio/checkbox roles) keep it accessible +
8
+ * reliably testable. Answers map each question's text → the chosen option labels
9
+ * (plus any typed "Other" text), matching the engine's QuestionDecision.
10
+ */
11
+ import { useState } from "react";
12
+ import { Button } from "./button.js";
13
+ import { Box, Txt } from "./primitives.js";
14
+ import { useUiTheme } from "./theme-context.js";
15
+ /** Sentinel label for the free-text "Other" row (never sent verbatim). */
16
+ const OTHER = "__other__";
17
+ export function QuestionView({ pending, onAnswer }) {
18
+ const theme = useUiTheme();
19
+ const [selections, setSelections] = useState({});
20
+ const [other, setOther] = useState({});
21
+ const toggle = (qi, label, multi) => {
22
+ setSelections((s) => {
23
+ const cur = s[qi] ?? [];
24
+ if (!multi)
25
+ return { ...s, [qi]: [label] };
26
+ return { ...s, [qi]: cur.includes(label) ? cur.filter((x) => x !== label) : [...cur, label] };
27
+ });
28
+ };
29
+ // (codex v22 SHOULD) A question counts as answered with ≥1 real selection OR a
30
+ // non-empty "Other". Submit stays disabled until EVERY question is answered, so
31
+ // an empty form can't be submitted as a non-declined "no answers" (use Cancel).
32
+ const answered = (qi) => {
33
+ const chosen = selections[qi] ?? [];
34
+ if (chosen.some((l) => l !== OTHER))
35
+ return true;
36
+ return chosen.includes(OTHER) && (other[qi] ?? "").trim().length > 0;
37
+ };
38
+ const allAnswered = pending.questions.every((_, qi) => answered(qi));
39
+ const submit = () => {
40
+ const answers = {};
41
+ pending.questions.forEach((q, qi) => {
42
+ const chosen = (selections[qi] ?? []).filter((l) => l !== OTHER);
43
+ const otherText = (other[qi] ?? "").trim();
44
+ const wantsOther = (selections[qi] ?? []).includes(OTHER) && otherText.length > 0;
45
+ answers[q.question] = wantsOther ? [...chosen, otherText] : chosen;
46
+ });
47
+ onAnswer({ answers });
48
+ };
49
+ const border = theme.permission ?? "#888";
50
+ return (_jsxs(Box, { borderWidth: 1, borderColor: border, borderRadius: 8, padding: 12, gap: 12, backgroundColor: "var(--ch-bg)", children: [_jsxs(Txt, { color: border, fontWeight: 700, children: ["The agent is asking", pending.questions.length > 1 ? ` ${pending.questions.length} questions` : "", "\u2026"] }), pending.questions.map((q, qi) => {
51
+ const multi = q.multiSelect === true;
52
+ const chosen = selections[qi] ?? [];
53
+ const otherChecked = chosen.includes(OTHER);
54
+ return (_jsxs(Box, { gap: 4, children: [_jsx(Txt, { color: "var(--ch-fg)", fontWeight: 600, children: q.question }), q.options.map((opt) => (_jsxs("label", { style: { display: "flex", gap: 8, alignItems: "baseline", cursor: "pointer" }, children: [_jsx("input", { type: multi ? "checkbox" : "radio", name: `q-${qi}`, checked: chosen.includes(opt.label), onChange: () => toggle(qi, opt.label, multi) }), _jsxs(Txt, { color: "var(--ch-fg)", children: [opt.label, opt.description ? _jsxs(Txt, { color: theme.synComment, children: [" \u2014 ", opt.description] }) : null] })] }, opt.label))), _jsxs("label", { style: { display: "flex", gap: 8, alignItems: "baseline", cursor: "pointer" }, children: [_jsx("input", { type: multi ? "checkbox" : "radio", name: `q-${qi}`, checked: otherChecked, onChange: () => toggle(qi, OTHER, multi) }), _jsx(Txt, { color: theme.synComment, children: "Other:" }), _jsx("input", { "aria-label": `other answer for question ${qi + 1}`, value: other[qi] ?? "", onChange: (e) => setOther((o) => ({ ...o, [qi]: e.target.value })), onFocus: () => {
55
+ if (!otherChecked)
56
+ toggle(qi, OTHER, multi);
57
+ }, style: { flex: 1, background: "transparent", color: "inherit", border: `1px solid ${theme.synComment ?? "#555"}`, borderRadius: 4, padding: "2px 6px", outline: "none" } })] })] }, qi));
58
+ }), _jsxs(Box, { flexDirection: "row", gap: 8, flexWrap: "wrap", children: [_jsx(Button, { label: "Submit", color: theme.accent, onPress: submit, disabled: !allAnswered }), _jsx(Button, { label: "Cancel", color: theme.synComment, onPress: () => onAnswer({ answers: {}, declined: true }) })] })] }));
59
+ }
60
+ //# sourceMappingURL=question-view.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"question-view.js","sourceRoot":"","sources":["../../src/web-ui/question-view.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export interface CodeSegmentsProps {
2
+ code: string;
3
+ lang?: string;
4
+ fontSize?: number;
5
+ }
6
+ /** A monospace run of themed syntax segments (one inline span per scope). */
7
+ export declare function CodeSegments({ code, lang, fontSize }: CodeSegmentsProps): import("react/jsx-runtime").JSX.Element;
8
+ //# sourceMappingURL=segments.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"segments.d.ts","sourceRoot":"","sources":["../../src/web-ui/segments.tsx"],"names":[],"mappings":"AAYA,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,6EAA6E;AAC7E,wBAAgB,YAAY,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,QAAa,EAAE,EAAE,iBAAiB,2CAY5E"}
@@ -0,0 +1,19 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /**
3
+ * (v17 M1 B3; v22) Server-/TUI-shared syntax highlighting on the web: ui-core's
4
+ * `highlightToSegments` (highlight.js, NO shiki — docs/6.1 res #2) yields flat
5
+ * `{text, scope}` segments; each renders as an inline span tinted by the scope's
6
+ * theme colour. Same palette + same segmenter as the terminal, so a snippet
7
+ * highlights byte-identically across surfaces.
8
+ */
9
+ import { highlightToSegments } from "@chances-ai/ui-core";
10
+ import { MONO, segmentColor } from "./helpers.js";
11
+ import { Txt } from "./primitives.js";
12
+ import { useUiTheme } from "./theme-context.js";
13
+ /** A monospace run of themed syntax segments (one inline span per scope). */
14
+ export function CodeSegments({ code, lang, fontSize = 13 }) {
15
+ const theme = useUiTheme();
16
+ const segments = highlightToSegments(code, lang);
17
+ return (_jsx(Txt, { fontSize: fontSize, style: { fontFamily: MONO, whiteSpace: "pre-wrap", overflowWrap: "anywhere" }, children: segments.map((seg, i) => (_jsx(Txt, { color: segmentColor(seg.scope, theme), children: seg.text }, i))) }));
18
+ }
19
+ //# sourceMappingURL=segments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"segments.js","sourceRoot":"","sources":["../../src/web-ui/segments.tsx"],"names":[],"mappings":";AAAA;;;;;;GAMG;AACH,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAQhD,6EAA6E;AAC7E,MAAM,UAAU,YAAY,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,GAAG,EAAE,EAAqB;IAC3E,MAAM,KAAK,GAAG,UAAU,EAAE,CAAC;IAC3B,MAAM,QAAQ,GAAG,mBAAmB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACjD,OAAO,CACL,KAAC,GAAG,IAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,YACnG,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,CACxB,KAAC,GAAG,IAAS,KAAK,EAAE,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,YAC/C,GAAG,CAAC,IAAI,IADD,CAAC,CAEL,CACP,CAAC,GACE,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * (v23 M5 / docs/6.6 §3) The left rail. The web relay holds ONE engine session
3
+ * per process (no multi-session backend — that's a CLI-management concern that
4
+ * stays out, see docs/STATUS), so this is an honest, lean rail: brand, a
5
+ * "New chat" action (clears the transcript), the active session, and a
6
+ * connection-status footer. Browser-safe, pure over the injected client/state.
7
+ */
8
+ import type { ClientState } from "../client-core/index.js";
9
+ export interface SessionSidebarProps {
10
+ state: ClientState;
11
+ /** Clear the transcript ("New chat"). */
12
+ onNewChat: () => void;
13
+ }
14
+ export declare function SessionSidebar({ state, onNewChat }: SessionSidebarProps): import("react/jsx-runtime").JSX.Element;
15
+ //# sourceMappingURL=session-sidebar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-sidebar.d.ts","sourceRoot":"","sources":["../../src/web-ui/session-sidebar.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAM3D,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,WAAW,CAAC;IACnB,yCAAyC;IACzC,SAAS,EAAE,MAAM,IAAI,CAAC;CACvB;AAED,wBAAgB,cAAc,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,mBAAmB,2CAoCvE"}
@@ -0,0 +1,10 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Button } from "./button.js";
3
+ import { statusColor, statusText } from "./helpers.js";
4
+ import { Box, Txt } from "./primitives.js";
5
+ import { useUiTheme } from "./theme-context.js";
6
+ export function SessionSidebar({ state, onNewChat }) {
7
+ const theme = useUiTheme();
8
+ return (_jsxs(Box, { style: { height: "100%" }, paddingVertical: 10, paddingHorizontal: 10, gap: 10, children: [_jsx(Txt, { color: theme.accent, fontWeight: 700, fontSize: 15, children: "chances" }), _jsx(Button, { label: "\uFF0B New chat", color: theme.accent, onPress: onNewChat }), _jsxs(Box, { marginTop: 8, gap: 4, children: [_jsx(Txt, { color: theme.synComment, fontSize: 11, style: { textTransform: "uppercase", letterSpacing: 0.5 }, children: "Session" }), _jsx(Txt, { color: state.sessionId ? "var(--ch-fg)" : theme.synComment, fontSize: 12, style: { fontFamily: "ui-monospace, monospace", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }, children: state.sessionId ?? "—" })] }), _jsx(Box, { flex: 1 }), _jsxs(Box, { flexDirection: "row", alignItems: "center", gap: 6, children: [_jsx(Txt, { color: statusColor(state.status, theme), fontSize: 12, children: "\u25CF" }), _jsx(Txt, { color: theme.synComment, fontSize: 12, children: statusText(state.status) })] })] }));
9
+ }
10
+ //# sourceMappingURL=session-sidebar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-sidebar.js","sourceRoot":"","sources":["../../src/web-ui/session-sidebar.tsx"],"names":[],"mappings":";AAQA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAQhD,MAAM,UAAU,cAAc,CAAC,EAAE,KAAK,EAAE,SAAS,EAAuB;IACtE,MAAM,KAAK,GAAG,UAAU,EAAE,CAAC;IAC3B,OAAO,CACL,MAAC,GAAG,IAAC,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,eAAe,EAAE,EAAE,EAAE,iBAAiB,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,aACjF,KAAC,GAAG,IAAC,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,QAAQ,EAAE,EAAE,wBAEjD,EACN,KAAC,MAAM,IAAC,KAAK,EAAC,iBAAY,EAAC,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,GAAI,EAEtE,MAAC,GAAG,IAAC,SAAS,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,aACvB,KAAC,GAAG,IAAC,KAAK,EAAE,KAAK,CAAC,UAAU,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,EAAE,GAAG,EAAE,wBAE/F,EACN,KAAC,GAAG,IACF,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,EAC1D,QAAQ,EAAE,EAAE,EACZ,KAAK,EAAE,EAAE,UAAU,EAAE,yBAAyB,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,UAAU,EAAE,YAEnH,KAAK,CAAC,SAAS,IAAI,GAAG,GACnB,IACF,EAGN,KAAC,GAAG,IAAC,IAAI,EAAE,CAAC,GAAI,EAGhB,MAAC,GAAG,IAAC,aAAa,EAAC,KAAK,EAAC,UAAU,EAAC,QAAQ,EAAC,GAAG,EAAE,CAAC,aACjD,KAAC,GAAG,IAAC,KAAK,EAAE,WAAW,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,QAAQ,EAAE,EAAE,uBAEpD,EACN,KAAC,GAAG,IAAC,KAAK,EAAE,KAAK,CAAC,UAAU,EAAE,QAAQ,EAAE,EAAE,YACvC,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,GACrB,IACF,IACF,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * (v17 M1 B3; v22) The footer status line — connection state dot + label, a
3
+ * working indicator while a turn streams, the latest token usage, and the last
4
+ * error. All pure reads off the client-core store snapshot.
5
+ */
6
+ import type { ClientState } from "../client-core/index.js";
7
+ export declare function StatusBar({ state }: {
8
+ state: ClientState;
9
+ }): import("react/jsx-runtime").JSX.Element;
10
+ //# sourceMappingURL=status-bar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status-bar.d.ts","sourceRoot":"","sources":["../../src/web-ui/status-bar.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAK3D,wBAAgB,SAAS,CAAC,EAAE,KAAK,EAAE,EAAE;IAAE,KAAK,EAAE,WAAW,CAAA;CAAE,2CA8B1D"}
@@ -0,0 +1,10 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { formatUsage, statusColor, statusText } from "./helpers.js";
3
+ import { Box, Txt } from "./primitives.js";
4
+ import { GLYPHS, useUiTheme } from "./theme-context.js";
5
+ export function StatusBar({ state }) {
6
+ const theme = useUiTheme();
7
+ const sc = statusColor(state.status, theme);
8
+ return (_jsxs(Box, { flexDirection: "row", gap: 12, alignItems: "center", flexWrap: "wrap", children: [_jsxs(Box, { flexDirection: "row", gap: 4, alignItems: "center", children: [_jsx(Txt, { color: sc, fontSize: 12, children: GLYPHS.dot }), _jsx(Txt, { color: sc, fontSize: 12, children: statusText(state.status) })] }), state.busy ? (_jsxs(Txt, { color: theme.accent, fontSize: 12, children: [GLYPHS.thinking, " working\u2026"] })) : null, state.lastUsage ? (_jsx(Txt, { color: theme.synComment, fontSize: 12, children: formatUsage(state.lastUsage) })) : null, state.lastError ? (_jsxs(Txt, { color: theme.error, fontSize: 12, children: ["\u26A0 ", state.lastError] })) : null] }));
9
+ }
10
+ //# sourceMappingURL=status-bar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status-bar.js","sourceRoot":"","sources":["../../src/web-ui/status-bar.tsx"],"names":[],"mappings":";AAMA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AACpE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAExD,MAAM,UAAU,SAAS,CAAC,EAAE,KAAK,EAA0B;IACzD,MAAM,KAAK,GAAG,UAAU,EAAE,CAAC;IAC3B,MAAM,EAAE,GAAG,WAAW,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC5C,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,KAAK,EAAC,GAAG,EAAE,EAAE,EAAE,UAAU,EAAC,QAAQ,EAAC,QAAQ,EAAC,MAAM,aACnE,MAAC,GAAG,IAAC,aAAa,EAAC,KAAK,EAAC,GAAG,EAAE,CAAC,EAAE,UAAU,EAAC,QAAQ,aAClD,KAAC,GAAG,IAAC,KAAK,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,YACzB,MAAM,CAAC,GAAG,GACP,EACN,KAAC,GAAG,IAAC,KAAK,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,YACzB,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,GACrB,IACF,EACL,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CACZ,MAAC,GAAG,IAAC,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE,aACnC,MAAM,CAAC,QAAQ,sBACZ,CACP,CAAC,CAAC,CAAC,IAAI,EACP,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CACjB,KAAC,GAAG,IAAC,KAAK,EAAE,KAAK,CAAC,UAAU,EAAE,QAAQ,EAAE,EAAE,YACvC,WAAW,CAAC,KAAK,CAAC,SAAS,CAAC,GACzB,CACP,CAAC,CAAC,CAAC,IAAI,EACP,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CACjB,MAAC,GAAG,IAAC,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE,wBAChC,KAAK,CAAC,SAAS,IACd,CACP,CAAC,CAAC,CAAC,IAAI,IACJ,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { type Glyphs, type Theme } from "@chances-ai/ui-core";
2
+ export type Mode = "dark" | "light";
3
+ /** Glyphs for the web surface — the non-darwin `●` dot renders consistently in
4
+ * browser fonts (the `⏺` variant aligns only in some macOS terminals). */
5
+ export declare const GLYPHS: Glyphs;
6
+ /** Resolve the ui-core palette for a mode (NO_COLOR is a terminal-only concern
7
+ * on the web; the panel always has a palette). */
8
+ export declare function themeFor(mode: Mode): Theme;
9
+ /** Provides the ui-core palette to the transcript tree. */
10
+ export declare const UiThemeProvider: import("react").Provider<Theme>;
11
+ /** The active ui-core palette (dark by default, see module doc). */
12
+ export declare function useUiTheme(): Theme;
13
+ //# sourceMappingURL=theme-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme-context.d.ts","sourceRoot":"","sources":["../../src/web-ui/theme-context.tsx"],"names":[],"mappings":"AAcA,OAAO,EAA4B,KAAK,MAAM,EAAE,KAAK,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAExF,MAAM,MAAM,IAAI,GAAG,MAAM,GAAG,OAAO,CAAC;AAEpC;2EAC2E;AAC3E,eAAO,MAAM,MAAM,EAAE,MAA0B,CAAC;AAEhD;mDACmD;AACnD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,IAAI,GAAG,KAAK,CAE1C;AAID,2DAA2D;AAC3D,eAAO,MAAM,eAAe,iCAA0B,CAAC;AAEvD,oEAAoE;AACpE,wBAAgB,UAAU,IAAI,KAAK,CAElC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * (v17 M1 B3; v22) Theme plumbing for the web panel. Transcript CONTENT colours
3
+ * (syntax, diff backgrounds, tool dot, error/info) come from the ui-core
4
+ * `Theme` — the single palette shared with the TUI, carrying the full role set
5
+ * incl. `syn*`. Layout CHROME (background / border) comes from the same ui-core
6
+ * source as `--ch-*` CSS custom properties (`themeCssVars`, set on the panel
7
+ * root), so content + chrome agree by construction — no second palette.
8
+ *
9
+ * The ui-core `Theme` is provided through React context so the deep transcript
10
+ * tree doesn't prop-drill it. The default is the dark palette, so a component
11
+ * rendered WITHOUT a provider (e.g. a `renderToStaticMarkup` smoke) still has
12
+ * sensible colours.
13
+ */
14
+ import { createContext, useContext } from "react";
15
+ import { makeGlyphs, resolveTheme } from "@chances-ai/ui-core";
16
+ /** Glyphs for the web surface — the non-darwin `●` dot renders consistently in
17
+ * browser fonts (the `⏺` variant aligns only in some macOS terminals). */
18
+ export const GLYPHS = makeGlyphs("web");
19
+ /** Resolve the ui-core palette for a mode (NO_COLOR is a terminal-only concern
20
+ * on the web; the panel always has a palette). */
21
+ export function themeFor(mode) {
22
+ return resolveTheme(mode, {});
23
+ }
24
+ const UiThemeContext = createContext(themeFor("dark"));
25
+ /** Provides the ui-core palette to the transcript tree. */
26
+ export const UiThemeProvider = UiThemeContext.Provider;
27
+ /** The active ui-core palette (dark by default, see module doc). */
28
+ export function useUiTheme() {
29
+ return useContext(UiThemeContext);
30
+ }
31
+ //# sourceMappingURL=theme-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme-context.js","sourceRoot":"","sources":["../../src/web-ui/theme-context.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,YAAY,EAA2B,MAAM,qBAAqB,CAAC;AAIxF;2EAC2E;AAC3E,MAAM,CAAC,MAAM,MAAM,GAAW,UAAU,CAAC,KAAK,CAAC,CAAC;AAEhD;mDACmD;AACnD,MAAM,UAAU,QAAQ,CAAC,IAAU;IACjC,OAAO,YAAY,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,cAAc,GAAG,aAAa,CAAQ,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;AAE9D,2DAA2D;AAC3D,MAAM,CAAC,MAAM,eAAe,GAAG,cAAc,CAAC,QAAQ,CAAC;AAEvD,oEAAoE;AACpE,MAAM,UAAU,UAAU;IACxB,OAAO,UAAU,CAAC,cAAc,CAAC,CAAC;AACpC,CAAC"}