@steerable/agent-ui 0.2.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 (104) hide show
  1. package/LICENSE +91 -0
  2. package/README.md +118 -0
  3. package/dist/components/ChatPanel.d.ts +42 -0
  4. package/dist/components/ChatPanel.d.ts.map +1 -0
  5. package/dist/components/ChatPanel.js +46 -0
  6. package/dist/components/ChatPanel.js.map +1 -0
  7. package/dist/components/ChatPanel.stories.d.ts +17 -0
  8. package/dist/components/ChatPanel.stories.d.ts.map +1 -0
  9. package/dist/components/ChatPanel.stories.js +143 -0
  10. package/dist/components/ChatPanel.stories.js.map +1 -0
  11. package/dist/components/MessageList.d.ts +44 -0
  12. package/dist/components/MessageList.d.ts.map +1 -0
  13. package/dist/components/MessageList.js +43 -0
  14. package/dist/components/MessageList.js.map +1 -0
  15. package/dist/components/MessageList.stories.d.ts +12 -0
  16. package/dist/components/MessageList.stories.d.ts.map +1 -0
  17. package/dist/components/MessageList.stories.js +88 -0
  18. package/dist/components/MessageList.stories.js.map +1 -0
  19. package/dist/components/OrchestrationPlanCard.d.ts +32 -0
  20. package/dist/components/OrchestrationPlanCard.d.ts.map +1 -0
  21. package/dist/components/OrchestrationPlanCard.js +48 -0
  22. package/dist/components/OrchestrationPlanCard.js.map +1 -0
  23. package/dist/components/OrchestrationPlanCard.stories.d.ts +12 -0
  24. package/dist/components/OrchestrationPlanCard.stories.d.ts.map +1 -0
  25. package/dist/components/OrchestrationPlanCard.stories.js +84 -0
  26. package/dist/components/OrchestrationPlanCard.stories.js.map +1 -0
  27. package/dist/components/SSEStreamView.d.ts +29 -0
  28. package/dist/components/SSEStreamView.d.ts.map +1 -0
  29. package/dist/components/SSEStreamView.js +78 -0
  30. package/dist/components/SSEStreamView.js.map +1 -0
  31. package/dist/components/SSEStreamView.stories.d.ts +12 -0
  32. package/dist/components/SSEStreamView.stories.d.ts.map +1 -0
  33. package/dist/components/SSEStreamView.stories.js +86 -0
  34. package/dist/components/SSEStreamView.stories.js.map +1 -0
  35. package/dist/components/ToolCallRenderer.d.ts +42 -0
  36. package/dist/components/ToolCallRenderer.d.ts.map +1 -0
  37. package/dist/components/ToolCallRenderer.js +70 -0
  38. package/dist/components/ToolCallRenderer.js.map +1 -0
  39. package/dist/components/ToolCallRenderer.stories.d.ts +13 -0
  40. package/dist/components/ToolCallRenderer.stories.d.ts.map +1 -0
  41. package/dist/components/ToolCallRenderer.stories.js +112 -0
  42. package/dist/components/ToolCallRenderer.stories.js.map +1 -0
  43. package/dist/components/cn.d.ts +7 -0
  44. package/dist/components/cn.d.ts.map +1 -0
  45. package/dist/components/cn.js +9 -0
  46. package/dist/components/cn.js.map +1 -0
  47. package/dist/components/index.d.ts +11 -0
  48. package/dist/components/index.d.ts.map +1 -0
  49. package/dist/components/index.js +6 -0
  50. package/dist/components/index.js.map +1 -0
  51. package/dist/hooks/index.d.ts +7 -0
  52. package/dist/hooks/index.d.ts.map +1 -0
  53. package/dist/hooks/index.js +4 -0
  54. package/dist/hooks/index.js.map +1 -0
  55. package/dist/hooks/useAgentSession.d.ts +56 -0
  56. package/dist/hooks/useAgentSession.d.ts.map +1 -0
  57. package/dist/hooks/useAgentSession.js +128 -0
  58. package/dist/hooks/useAgentSession.js.map +1 -0
  59. package/dist/hooks/useChatStream.d.ts +59 -0
  60. package/dist/hooks/useChatStream.d.ts.map +1 -0
  61. package/dist/hooks/useChatStream.js +251 -0
  62. package/dist/hooks/useChatStream.js.map +1 -0
  63. package/dist/hooks/useToolCallStatus.d.ts +47 -0
  64. package/dist/hooks/useToolCallStatus.d.ts.map +1 -0
  65. package/dist/hooks/useToolCallStatus.js +57 -0
  66. package/dist/hooks/useToolCallStatus.js.map +1 -0
  67. package/dist/index.d.ts +12 -0
  68. package/dist/index.d.ts.map +1 -0
  69. package/dist/index.js +12 -0
  70. package/dist/index.js.map +1 -0
  71. package/dist/tailwind-preset.d.ts +76 -0
  72. package/dist/tailwind-preset.d.ts.map +1 -0
  73. package/dist/tailwind-preset.js +104 -0
  74. package/dist/tailwind-preset.js.map +1 -0
  75. package/package.json +97 -0
  76. package/src/Introduction.mdx +71 -0
  77. package/src/components/ChatPanel.stories.tsx +173 -0
  78. package/src/components/ChatPanel.tsx +188 -0
  79. package/src/components/MessageList.stories.tsx +112 -0
  80. package/src/components/MessageList.test.tsx +57 -0
  81. package/src/components/MessageList.tsx +144 -0
  82. package/src/components/OrchestrationPlanCard.stories.tsx +98 -0
  83. package/src/components/OrchestrationPlanCard.test.tsx +34 -0
  84. package/src/components/OrchestrationPlanCard.tsx +159 -0
  85. package/src/components/SSEStreamView.stories.tsx +99 -0
  86. package/src/components/SSEStreamView.test.tsx +42 -0
  87. package/src/components/SSEStreamView.tsx +155 -0
  88. package/src/components/ToolCallRenderer.stories.tsx +152 -0
  89. package/src/components/ToolCallRenderer.test.tsx +93 -0
  90. package/src/components/ToolCallRenderer.tsx +213 -0
  91. package/src/components/cn.ts +10 -0
  92. package/src/components/index.ts +18 -0
  93. package/src/hooks/index.ts +21 -0
  94. package/src/hooks/useAgentSession.mdx +115 -0
  95. package/src/hooks/useAgentSession.test.ts +127 -0
  96. package/src/hooks/useAgentSession.ts +181 -0
  97. package/src/hooks/useChatStream.mdx +129 -0
  98. package/src/hooks/useChatStream.test.ts +233 -0
  99. package/src/hooks/useChatStream.ts +341 -0
  100. package/src/hooks/useToolCallStatus.mdx +102 -0
  101. package/src/hooks/useToolCallStatus.test.ts +99 -0
  102. package/src/hooks/useToolCallStatus.ts +99 -0
  103. package/src/index.ts +12 -0
  104. package/src/tailwind-preset.ts +109 -0
@@ -0,0 +1,70 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * `ToolCallRenderer` — display a single tool call + (optional) tool result.
4
+ *
5
+ * Renders three visual rows depending on lifecycle / mode:
6
+ *
7
+ * ┌──────────────────────────────────────────────────┐
8
+ * │ [icon] tool_name [mode-pill] [time] │
9
+ * │ args (collapsed by default) │
10
+ * │ ── result ── │
11
+ * │ message + data (collapsed by default) │
12
+ * └──────────────────────────────────────────────────┘
13
+ *
14
+ * Headless body: callers can override the args / result subtree with
15
+ * `renderArgs` / `renderResult` if they need richer formatting (diffs, code
16
+ * blocks, structured cards). Default body uses pretty-printed JSON.
17
+ */
18
+ import { useState } from 'react';
19
+ import { useToolCallStatus } from '../hooks/useToolCallStatus.js';
20
+ import { cn } from './cn.js';
21
+ const modeBadgeClass = {
22
+ read: 'bg-agent-tool-read/15 text-agent-tool-read border-agent-tool-read/40',
23
+ safe_write: 'bg-agent-tool-write/15 text-agent-tool-write border-agent-tool-write/40',
24
+ destructive: 'bg-agent-tool-destructive/15 text-agent-tool-destructive border-agent-tool-destructive/40',
25
+ local: 'bg-agent-accent/15 text-agent-accent border-agent-accent/40',
26
+ external: 'bg-agent-muted text-agent-muted-foreground border-agent-border',
27
+ ui: 'bg-agent-muted text-agent-muted-foreground border-agent-border',
28
+ synthetic: 'bg-agent-muted text-agent-muted-foreground border-agent-border',
29
+ unknown: 'bg-agent-muted text-agent-muted-foreground border-agent-border',
30
+ };
31
+ const statusDotClass = {
32
+ pending: 'bg-agent-muted-foreground animate-pulse',
33
+ running: 'bg-agent-accent animate-pulse',
34
+ done: 'bg-agent-tool-read',
35
+ error: 'bg-agent-destructive',
36
+ };
37
+ function defaultArgsRenderer(call) {
38
+ return (_jsx("pre", { className: "whitespace-pre-wrap break-words text-xs leading-relaxed text-agent-muted-foreground", children: safeStringify(call.arguments) }));
39
+ }
40
+ function defaultResultRenderer(result) {
41
+ const lines = [];
42
+ if (result.message) {
43
+ lines.push(_jsx("div", { className: "text-xs text-agent-foreground", children: result.message }, "msg"));
44
+ }
45
+ if (result.error) {
46
+ lines.push(_jsx("div", { className: "text-xs text-agent-destructive", children: result.error }, "err"));
47
+ }
48
+ if (result.data) {
49
+ lines.push(_jsx("pre", { className: "mt-1 whitespace-pre-wrap break-words text-xs leading-relaxed text-agent-muted-foreground", children: safeStringify(result.data) }, "data"));
50
+ }
51
+ if (lines.length === 0) {
52
+ lines.push(_jsx("div", { className: "text-xs text-agent-muted-foreground", children: "ok" }, "ok"));
53
+ }
54
+ return _jsx("div", { className: "space-y-1", children: lines });
55
+ }
56
+ function safeStringify(value) {
57
+ try {
58
+ return JSON.stringify(value, null, 2);
59
+ }
60
+ catch {
61
+ return String(value);
62
+ }
63
+ }
64
+ export function ToolCallRenderer(props) {
65
+ const { call, result, mode, runningHint, onApprove, onReject, className, renderArgs = defaultArgsRenderer, renderResult = defaultResultRenderer, defaultExpanded = false, } = props;
66
+ const [expanded, setExpanded] = useState(defaultExpanded);
67
+ const status = useToolCallStatus({ call, result, mode, runningHint });
68
+ return (_jsxs("div", { "data-status": status.status, "data-mode": status.mode, className: cn('rounded-agent-md border bg-agent-canvas px-3 py-2 text-agent-foreground', status.isDestructive ? 'border-agent-destructive/40' : 'border-agent-border', className), children: [_jsxs("button", { type: "button", className: "flex w-full items-center justify-between gap-2 text-left", onClick: () => setExpanded((v) => !v), "aria-expanded": expanded, children: [_jsxs("span", { className: "flex min-w-0 items-center gap-2", children: [_jsx("span", { className: cn('h-2 w-2 rounded-full', statusDotClass[status.status]), "aria-hidden": true }), _jsx("span", { className: "truncate font-mono text-xs font-medium", children: call.name }), _jsx("span", { className: cn('shrink-0 rounded-full border px-1.5 py-0.5 text-[10px] font-semibold uppercase tracking-wide', modeBadgeClass[status.mode]), children: status.mode })] }), _jsx("span", { className: "shrink-0 text-[10px] uppercase tracking-wide text-agent-muted-foreground", children: status.status })] }), status.requiresApproval && !result ? (_jsxs("div", { className: "mt-2 flex items-center gap-2", children: [_jsx("span", { className: "text-xs text-agent-muted-foreground", children: "Local execution requires approval." }), onApprove ? (_jsx("button", { type: "button", className: "rounded-agent-sm bg-agent-accent px-2 py-1 text-xs font-medium text-agent-accent-foreground", onClick: () => onApprove(call), children: "Approve" })) : null, onReject ? (_jsx("button", { type: "button", className: "rounded-agent-sm border border-agent-border px-2 py-1 text-xs font-medium text-agent-foreground", onClick: () => onReject(call), children: "Reject" })) : null] })) : null, expanded ? (_jsxs("div", { className: "mt-2 space-y-2 border-t border-agent-border pt-2", children: [renderArgs(call), result ? (_jsx("div", { className: "border-t border-dashed border-agent-border pt-2", children: renderResult(result) })) : null] })) : null] }));
69
+ }
70
+ //# sourceMappingURL=ToolCallRenderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ToolCallRenderer.js","sourceRoot":"","sources":["../../src/components/ToolCallRenderer.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { ToolCallRenderer } from './ToolCallRenderer.js';
3
+ declare const meta: Meta<typeof ToolCallRenderer>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof ToolCallRenderer>;
6
+ export declare const ReadModePending: Story;
7
+ export declare const ReadModeSuccess: Story;
8
+ export declare const SafeWriteRunning: Story;
9
+ export declare const SafeWriteError: Story;
10
+ export declare const DestructivePending: Story;
11
+ export declare const LocalAwaitingApproval: Story;
12
+ export declare const CustomRenderers: Story;
13
+ //# sourceMappingURL=ToolCallRenderer.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ToolCallRenderer.stories.d.ts","sourceRoot":"","sources":["../../src/components/ToolCallRenderer.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,gBAAgB,CAoBvC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,gBAAgB,CAAC,CAAC;AA8C/C,eAAO,MAAM,eAAe,EAAE,KAK7B,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,KAO7B,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,KAM9B,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,KAO5B,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,KAMhC,CAAC;AAEF,eAAO,MAAM,qBAAqB,EAAE,KAOnC,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,KA4B7B,CAAC"}
@@ -0,0 +1,112 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { ToolCallRenderer } from './ToolCallRenderer.js';
3
+ const meta = {
4
+ title: 'Components/ToolCallRenderer',
5
+ component: ToolCallRenderer,
6
+ parameters: {
7
+ layout: 'centered',
8
+ actions: { argTypesRegex: '^on[A-Z].*' },
9
+ docs: {
10
+ description: {
11
+ component: 'Single tool-call card. Computes its display state from `useToolCallStatus` (call + optional result + mode hint). Pass `mode="local"` and `onApprove` / `onReject` to render an approval prompt for local-execution tools.',
12
+ },
13
+ },
14
+ },
15
+ decorators: [
16
+ (Story) => (_jsx("div", { className: "w-[520px]", children: _jsx(Story, {}) })),
17
+ ],
18
+ };
19
+ export default meta;
20
+ const readCall = {
21
+ id: 'call_read_1',
22
+ name: 'web_search',
23
+ arguments: { query: 'tokyo vegetarian restaurants 2026' },
24
+ };
25
+ const writeCall = {
26
+ id: 'call_write_1',
27
+ name: 'create_calendar_event',
28
+ arguments: {
29
+ title: 'Team retro',
30
+ startTime: '2026-05-20T14:00:00Z',
31
+ durationMinutes: 60,
32
+ },
33
+ };
34
+ const destructiveCall = {
35
+ id: 'call_destructive_1',
36
+ name: 'shell_exec',
37
+ arguments: { command: 'rm -rf /tmp/build-cache' },
38
+ };
39
+ const localCall = {
40
+ id: 'call_local_1',
41
+ name: 'cflog_open_workspace',
42
+ arguments: { path: '/Users/me/projects/cflog/case-2024-001' },
43
+ };
44
+ const successResult = {
45
+ success: true,
46
+ message: 'Found 12 results.',
47
+ data: {
48
+ hits: [
49
+ { title: 'T\u2019s Tantan', url: 'https://example.com/1' },
50
+ { title: 'AIN SOPH. Soar', url: 'https://example.com/2' },
51
+ ],
52
+ },
53
+ };
54
+ const errorResult = {
55
+ success: false,
56
+ error: 'TimeRangeConflict: another event already occupies 14:00–15:00 on 2026-05-20',
57
+ };
58
+ export const ReadModePending = {
59
+ args: {
60
+ call: readCall,
61
+ mode: 'read',
62
+ },
63
+ };
64
+ export const ReadModeSuccess = {
65
+ args: {
66
+ call: readCall,
67
+ result: successResult,
68
+ mode: 'read',
69
+ defaultExpanded: true,
70
+ },
71
+ };
72
+ export const SafeWriteRunning = {
73
+ args: {
74
+ call: writeCall,
75
+ mode: 'safe_write',
76
+ runningHint: true,
77
+ },
78
+ };
79
+ export const SafeWriteError = {
80
+ args: {
81
+ call: writeCall,
82
+ result: errorResult,
83
+ mode: 'safe_write',
84
+ defaultExpanded: true,
85
+ },
86
+ };
87
+ export const DestructivePending = {
88
+ args: {
89
+ call: destructiveCall,
90
+ mode: 'destructive',
91
+ defaultExpanded: true,
92
+ },
93
+ };
94
+ export const LocalAwaitingApproval = {
95
+ args: {
96
+ call: localCall,
97
+ mode: 'local',
98
+ onApprove: () => { },
99
+ onReject: () => { },
100
+ },
101
+ };
102
+ export const CustomRenderers = {
103
+ args: {
104
+ call: readCall,
105
+ result: successResult,
106
+ mode: 'read',
107
+ defaultExpanded: true,
108
+ renderArgs: (call) => (_jsxs("div", { className: "text-xs", children: [_jsx("span", { className: "font-medium text-agent-foreground", children: "Query:" }), ' ', _jsx("span", { className: "text-agent-muted-foreground", children: String(call.arguments.query ?? '') })] })),
109
+ renderResult: (result) => (_jsx("ul", { className: "space-y-1 text-xs text-agent-muted-foreground", children: (result.data?.hits ?? []).map((hit) => (_jsx("li", { children: _jsx("a", { className: "text-agent-accent underline", href: hit.url, children: hit.title }) }, hit.url))) })),
110
+ },
111
+ };
112
+ //# sourceMappingURL=ToolCallRenderer.stories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ToolCallRenderer.stories.js","sourceRoot":"","sources":["../../src/components/ToolCallRenderer.stories.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Tiny class-name combiner. We intentionally don't depend on `clsx` /
3
+ * `tailwind-merge` to keep the package's runtime footprint near zero — those
4
+ * niceties belong in the consumer app.
5
+ */
6
+ export declare function cn(...values: Array<string | false | null | undefined>): string;
7
+ //# sourceMappingURL=cn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cn.d.ts","sourceRoot":"","sources":["../../src/components/cn.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,wBAAgB,EAAE,CAChB,GAAG,MAAM,EAAE,KAAK,CAAC,MAAM,GAAG,KAAK,GAAG,IAAI,GAAG,SAAS,CAAC,GAClD,MAAM,CAER"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Tiny class-name combiner. We intentionally don't depend on `clsx` /
3
+ * `tailwind-merge` to keep the package's runtime footprint near zero — those
4
+ * niceties belong in the consumer app.
5
+ */
6
+ export function cn(...values) {
7
+ return values.filter(Boolean).join(' ');
8
+ }
9
+ //# sourceMappingURL=cn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cn.js","sourceRoot":"","sources":["../../src/components/cn.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,UAAU,EAAE,CAChB,GAAG,MAAgD;IAEnD,OAAO,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC1C,CAAC"}
@@ -0,0 +1,11 @@
1
+ export { MessageList } from './MessageList.js';
2
+ export type { MessageListProps, MessageRendererProps } from './MessageList.js';
3
+ export { ChatPanel } from './ChatPanel.js';
4
+ export type { ChatPanelProps } from './ChatPanel.js';
5
+ export { OrchestrationPlanCard } from './OrchestrationPlanCard.js';
6
+ export type { OrchestrationPlanCardProps, OrchestrationStep, OrchestrationStepStatus, } from './OrchestrationPlanCard.js';
7
+ export { ToolCallRenderer } from './ToolCallRenderer.js';
8
+ export type { ToolCallRendererProps } from './ToolCallRenderer.js';
9
+ export { SSEStreamView } from './SSEStreamView.js';
10
+ export type { SSEStreamViewProps } from './SSEStreamView.js';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,YAAY,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAE/E,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,YAAY,EACV,0BAA0B,EAC1B,iBAAiB,EACjB,uBAAuB,GACxB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,YAAY,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAEnE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,6 @@
1
+ export { MessageList } from './MessageList.js';
2
+ export { ChatPanel } from './ChatPanel.js';
3
+ export { OrchestrationPlanCard } from './OrchestrationPlanCard.js';
4
+ export { ToolCallRenderer } from './ToolCallRenderer.js';
5
+ export { SSEStreamView } from './SSEStreamView.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAG/C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAG3C,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAOnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAGzD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,7 @@
1
+ export { useChatStream } from './useChatStream.js';
2
+ export type { UseChatStreamOptions, UseChatStreamReturn, ChatStreamTransport, ChatStreamSendInput, } from './useChatStream.js';
3
+ export { useToolCallStatus } from './useToolCallStatus.js';
4
+ export type { ToolCallStatus, UseToolCallStatusOptions, UseToolCallStatusReturn, } from './useToolCallStatus.js';
5
+ export { useAgentSession } from './useAgentSession.js';
6
+ export type { UseAgentSessionOptions, UseAgentSessionReturn, AgentSessionTransport, } from './useAgentSession.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,YAAY,EACV,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,YAAY,EACV,cAAc,EACd,wBAAwB,EACxB,uBAAuB,GACxB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,YAAY,EACV,sBAAsB,EACtB,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { useChatStream } from './useChatStream.js';
2
+ export { useToolCallStatus } from './useToolCallStatus.js';
3
+ export { useAgentSession } from './useAgentSession.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAQnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAO3D,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * `useAgentSession` — light-weight wrapper around the session lifecycle.
3
+ *
4
+ * Sessions are created lazily on first message in most production setups, but
5
+ * the desktop / web clients still need a deterministic handle to fetch /
6
+ * resume / list. The hook exposes a transport-agnostic API matching the
7
+ * methods on the framework's storage adapter (`InMemoryStorage`,
8
+ * `SqlAlchemyStorage`) so consumers can wire any backend.
9
+ *
10
+ * Stability contract:
11
+ * The hook tolerates inline-object literals for `autoLoad`. We re-run the
12
+ * `list` effect only when the **values** in `autoLoad` change, not when the
13
+ * object identity changes (otherwise an unmemoised consumer would loop).
14
+ * `transport` is held by ref so swapping the implementation mid-session
15
+ * doesn't trigger a refetch — call `refresh()` explicitly if you need that.
16
+ */
17
+ import type { AgentSession } from '@steerable/agent-protocol';
18
+ export interface AgentSessionTransport {
19
+ create: (input: {
20
+ chatId: string;
21
+ userId: string;
22
+ projectId?: string | null;
23
+ scenario?: string;
24
+ stageData?: Record<string, unknown> | null;
25
+ }) => Promise<AgentSession>;
26
+ resume: (sessionId: string) => Promise<AgentSession>;
27
+ list: (filter: {
28
+ userId?: string;
29
+ chatId?: string;
30
+ activeOnly?: boolean;
31
+ }) => Promise<AgentSession[]>;
32
+ }
33
+ export interface UseAgentSessionOptions {
34
+ transport: AgentSessionTransport;
35
+ /** Optional auto-load filter; when set the hook calls `list` on mount. */
36
+ autoLoad?: {
37
+ userId?: string;
38
+ chatId?: string;
39
+ activeOnly?: boolean;
40
+ };
41
+ }
42
+ export interface UseAgentSessionReturn {
43
+ /** Active sessions for the current filter. */
44
+ sessions: AgentSession[];
45
+ /** The session created/resumed most recently via this hook. */
46
+ current: AgentSession | null;
47
+ isLoading: boolean;
48
+ error: Error | null;
49
+ create: AgentSessionTransport['create'];
50
+ resume: AgentSessionTransport['resume'];
51
+ refresh: () => Promise<void>;
52
+ /** Set the current session pointer without re-fetching. */
53
+ setCurrent: (session: AgentSession | null) => void;
54
+ }
55
+ export declare function useAgentSession(options: UseAgentSessionOptions): UseAgentSessionReturn;
56
+ //# sourceMappingURL=useAgentSession.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAgentSession.d.ts","sourceRoot":"","sources":["../../src/hooks/useAgentSession.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AASH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAE9D,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,CAAC,KAAK,EAAE;QACd,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;KAC5C,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;IAC5B,MAAM,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;IACrD,IAAI,EAAE,CAAC,MAAM,EAAE;QACb,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,UAAU,CAAC,EAAE,OAAO,CAAC;KACtB,KAAK,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,qBAAqB,CAAC;IACjC,0EAA0E;IAC1E,QAAQ,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CACvE;AAED,MAAM,WAAW,qBAAqB;IACpC,8CAA8C;IAC9C,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,+DAA+D;IAC/D,OAAO,EAAE,YAAY,GAAG,IAAI,CAAC;IAC7B,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IACxC,MAAM,EAAE,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IACxC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,2DAA2D;IAC3D,UAAU,EAAE,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,KAAK,IAAI,CAAC;CACpD;AAcD,wBAAgB,eAAe,CAC7B,OAAO,EAAE,sBAAsB,GAC9B,qBAAqB,CAwGvB"}
@@ -0,0 +1,128 @@
1
+ /**
2
+ * `useAgentSession` — light-weight wrapper around the session lifecycle.
3
+ *
4
+ * Sessions are created lazily on first message in most production setups, but
5
+ * the desktop / web clients still need a deterministic handle to fetch /
6
+ * resume / list. The hook exposes a transport-agnostic API matching the
7
+ * methods on the framework's storage adapter (`InMemoryStorage`,
8
+ * `SqlAlchemyStorage`) so consumers can wire any backend.
9
+ *
10
+ * Stability contract:
11
+ * The hook tolerates inline-object literals for `autoLoad`. We re-run the
12
+ * `list` effect only when the **values** in `autoLoad` change, not when the
13
+ * object identity changes (otherwise an unmemoised consumer would loop).
14
+ * `transport` is held by ref so swapping the implementation mid-session
15
+ * doesn't trigger a refetch — call `refresh()` explicitly if you need that.
16
+ */
17
+ import { useCallback, useEffect, useMemo, useRef, useState, } from 'react';
18
+ function autoLoadKey(autoLoad) {
19
+ if (!autoLoad)
20
+ return null;
21
+ // Stable, deterministic key — values are primitives so JSON.stringify is fine.
22
+ return JSON.stringify({
23
+ userId: autoLoad.userId ?? null,
24
+ chatId: autoLoad.chatId ?? null,
25
+ activeOnly: autoLoad.activeOnly ?? null,
26
+ });
27
+ }
28
+ export function useAgentSession(options) {
29
+ const [sessions, setSessions] = useState([]);
30
+ const [current, setCurrent] = useState(null);
31
+ const [isLoading, setLoading] = useState(false);
32
+ const [error, setError] = useState(null);
33
+ const mountedRef = useRef(true);
34
+ const transportRef = useRef(options.transport);
35
+ transportRef.current = options.transport;
36
+ useEffect(() => {
37
+ mountedRef.current = true;
38
+ return () => {
39
+ mountedRef.current = false;
40
+ };
41
+ }, []);
42
+ const autoLoadKeyVal = autoLoadKey(options.autoLoad);
43
+ const refresh = useCallback(async () => {
44
+ if (!options.autoLoad)
45
+ return;
46
+ setLoading(true);
47
+ try {
48
+ const list = await transportRef.current.list(options.autoLoad);
49
+ if (mountedRef.current) {
50
+ setSessions(list);
51
+ setError(null);
52
+ }
53
+ }
54
+ catch (err) {
55
+ if (mountedRef.current) {
56
+ setError(err instanceof Error ? err : new Error(String(err)));
57
+ }
58
+ }
59
+ finally {
60
+ if (mountedRef.current)
61
+ setLoading(false);
62
+ }
63
+ // We intentionally key on the serialised filter, not the object identity.
64
+ // eslint-disable-next-line react-hooks/exhaustive-deps
65
+ }, [autoLoadKeyVal]);
66
+ useEffect(() => {
67
+ if (autoLoadKeyVal === null)
68
+ return;
69
+ void refresh();
70
+ }, [autoLoadKeyVal, refresh]);
71
+ const create = useCallback(async (input) => {
72
+ setLoading(true);
73
+ try {
74
+ const session = await transportRef.current.create(input);
75
+ if (mountedRef.current) {
76
+ setCurrent(session);
77
+ setSessions((prev) => [
78
+ session,
79
+ ...prev.filter((s) => s.sessionId !== session.sessionId),
80
+ ]);
81
+ setError(null);
82
+ }
83
+ return session;
84
+ }
85
+ catch (err) {
86
+ if (mountedRef.current) {
87
+ setError(err instanceof Error ? err : new Error(String(err)));
88
+ }
89
+ throw err;
90
+ }
91
+ finally {
92
+ if (mountedRef.current)
93
+ setLoading(false);
94
+ }
95
+ }, []);
96
+ const resume = useCallback(async (sessionId) => {
97
+ setLoading(true);
98
+ try {
99
+ const session = await transportRef.current.resume(sessionId);
100
+ if (mountedRef.current) {
101
+ setCurrent(session);
102
+ setError(null);
103
+ }
104
+ return session;
105
+ }
106
+ catch (err) {
107
+ if (mountedRef.current) {
108
+ setError(err instanceof Error ? err : new Error(String(err)));
109
+ }
110
+ throw err;
111
+ }
112
+ finally {
113
+ if (mountedRef.current)
114
+ setLoading(false);
115
+ }
116
+ }, []);
117
+ return useMemo(() => ({
118
+ sessions,
119
+ current,
120
+ isLoading,
121
+ error,
122
+ create,
123
+ resume,
124
+ refresh,
125
+ setCurrent,
126
+ }), [sessions, current, isLoading, error, create, resume, refresh]);
127
+ }
128
+ //# sourceMappingURL=useAgentSession.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAgentSession.js","sourceRoot":"","sources":["../../src/hooks/useAgentSession.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * `useChatStream` — own the in-flight chat lifecycle.
3
+ *
4
+ * Caller plugs in a transport (fetch+SSE, IPC bridge, sidecar, …) that yields
5
+ * `SSEEvent` instances; the hook turns those into the local `ChatMessage[]`
6
+ * that `<MessageList>` and `<ChatPanel>` render. The hook is intentionally
7
+ * unaware of HTTP, of which provider serves the events, and of any specific
8
+ * sequencing rules — those live in the framework spec and the caller's
9
+ * transport.
10
+ */
11
+ import type { ChatMessage, SSEEvent, ToolResult } from '@steerable/agent-protocol';
12
+ export interface ChatStreamSendInput {
13
+ /** The user's free-text message. */
14
+ content: string;
15
+ /** Optional structured metadata (mention list, tools requested, etc.). */
16
+ metadata?: Record<string, unknown>;
17
+ }
18
+ export interface ChatStreamTransport {
19
+ /**
20
+ * Called when the user submits a message. The transport is expected to:
21
+ * 1. POST/IPC the message to the backend,
22
+ * 2. consume the SSE stream and call `onEvent` for each parsed event,
23
+ * 3. resolve when the stream terminates (or reject on error).
24
+ *
25
+ * Returning a function from the promise is a `cancel` handle the hook will
26
+ * call on unmount or when the user clicks "stop".
27
+ */
28
+ stream: (input: ChatStreamSendInput, onEvent: (event: SSEEvent) => void) => Promise<void | (() => void)>;
29
+ }
30
+ export interface UseChatStreamOptions {
31
+ /** Required transport handle; see `ChatStreamTransport`. */
32
+ transport: ChatStreamTransport;
33
+ /** Initial message history (persisted from previous turns). */
34
+ initialMessages?: ChatMessage[];
35
+ /**
36
+ * Map a tool-result event to a standalone `tool` ChatMessage. Default
37
+ * returns null, which keeps tool results inline on the assistant message
38
+ * that owns the corresponding call.
39
+ */
40
+ toolResultToMessage?: (result: ToolResult) => ChatMessage | null;
41
+ /**
42
+ * Called for every event that doesn't have a built-in handler — useful for
43
+ * `loader-hint`, `agent`, `orchestration`, automation, search-source, etc.
44
+ * Receivers can stash these into their own state.
45
+ */
46
+ onUnknownEvent?: (event: SSEEvent) => void;
47
+ }
48
+ export interface UseChatStreamReturn {
49
+ messages: ChatMessage[];
50
+ isStreaming: boolean;
51
+ sendUserMessage: (input: ChatStreamSendInput) => Promise<void>;
52
+ cancel: () => void;
53
+ /** Replace the message buffer (e.g. when switching chat). */
54
+ setMessages: (messages: ChatMessage[]) => void;
55
+ /** Append a single message without going through the transport. */
56
+ appendMessage: (message: ChatMessage) => void;
57
+ }
58
+ export declare function useChatStream(options: UseChatStreamOptions): UseChatStreamReturn;
59
+ //# sourceMappingURL=useChatStream.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useChatStream.d.ts","sourceRoot":"","sources":["../../src/hooks/useChatStream.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EACV,WAAW,EACX,QAAQ,EAER,UAAU,EACX,MAAM,2BAA2B,CAAC;AAEnC,MAAM,WAAW,mBAAmB;IAClC,oCAAoC;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,mBAAmB;IAClC;;;;;;;;OAQG;IACH,MAAM,EAAE,CACN,KAAK,EAAE,mBAAmB,EAC1B,OAAO,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,KAC/B,OAAO,CAAC,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,oBAAoB;IACnC,4DAA4D;IAC5D,SAAS,EAAE,mBAAmB,CAAC;IAC/B,+DAA+D;IAC/D,eAAe,CAAC,EAAE,WAAW,EAAE,CAAC;IAChC;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,WAAW,GAAG,IAAI,CAAC;IACjE;;;;OAIG;IACH,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAC;CAC5C;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,WAAW,EAAE,OAAO,CAAC;IACrB,eAAe,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/D,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,6DAA6D;IAC7D,WAAW,EAAE,CAAC,QAAQ,EAAE,WAAW,EAAE,KAAK,IAAI,CAAC;IAC/C,mEAAmE;IACnE,aAAa,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;CAC/C;AAsID,wBAAgB,aAAa,CAC3B,OAAO,EAAE,oBAAoB,GAC5B,mBAAmB,CAsIrB"}