@mast-ai/react-ui 0.1.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.
@@ -0,0 +1,162 @@
1
+ import type { ReactNode } from 'react';
2
+ /**
3
+ * The rendered state of a single tool invocation within an assistant turn.
4
+ *
5
+ * Created when a `tool_call_started` event is received and updated as the tool
6
+ * executes. For tools that run sub-agents, `subThinking` and `subText` accumulate
7
+ * live output streamed via {@link AgentRunner}'s `onToolEvent` callback.
8
+ */
9
+ /**
10
+ * Outcome of a completed tool call.
11
+ *
12
+ * - `success`: tool returned normally
13
+ * - `error`: tool threw an exception (or the tool was not found)
14
+ * - `cancelled`: the user rejected the call via the approval flow
15
+ */
16
+ export type ToolCallStatus = 'success' | 'error' | 'cancelled';
17
+ export interface ToolEventEntry {
18
+ /**
19
+ * Stable identifier for this tool invocation. Generated when the
20
+ * `tool_call_started` event is received and used as the React `key` in
21
+ * lists and to correlate `PendingApproval` handles back to the entry.
22
+ */
23
+ id: string;
24
+ /** Discriminates between a pending and a completed tool call. */
25
+ type: 'tool_call_started' | 'tool_call_completed';
26
+ /** The registered name of the tool. */
27
+ name: string;
28
+ /** The arguments passed to the tool, as parsed JSON. Present once the call has started. */
29
+ args?: unknown;
30
+ /**
31
+ * The value returned by the tool.
32
+ * Only present when `type` is `'tool_call_completed'`.
33
+ */
34
+ result?: unknown;
35
+ /**
36
+ * Accumulated thinking text streamed from a sub-agent running inside this tool.
37
+ * Populated incrementally via `onToolEvent` → `thinking` deltas.
38
+ * `undefined` for tools that are not sub-agents.
39
+ */
40
+ subThinking?: string;
41
+ /**
42
+ * Accumulated text streamed from a sub-agent running inside this tool.
43
+ * Populated incrementally via `onToolEvent` → `text_delta` deltas.
44
+ * `undefined` for tools that are not sub-agents.
45
+ */
46
+ subText?: string;
47
+ /**
48
+ * Tool calls fired by a sub-agent running inside this tool's execution.
49
+ * Populated incrementally via `onToolEvent` → `tool_call_started` /
50
+ * `tool_call_completed` events forwarded from the child runner.
51
+ * `undefined` when the tool is not a sub-agent or has not yet emitted
52
+ * any nested tool calls.
53
+ *
54
+ * Currently scoped to a single level of nesting. The state machine routes
55
+ * grandchild events back to the outermost matching parent; deeper
56
+ * disambiguation is a future extension.
57
+ */
58
+ nestedToolEvents?: ToolEventEntry[];
59
+ /**
60
+ * `true` while the tool is executing; `false` once `tool_call_completed` is received.
61
+ * Drives the spinner → check-mark transition in `<ToolCallBlock>`.
62
+ */
63
+ isStreaming: boolean;
64
+ /**
65
+ * `true` while the approval proxy is awaiting the user's decision via the
66
+ * `onApprovalRequired` callback or the inline approval queue. Set to `true`
67
+ * immediately before the callback is invoked and cleared once a decision
68
+ * is reached (approved, rejected, or replaced with a synthetic result).
69
+ * Always `false` for tools that do not require approval.
70
+ *
71
+ * Only meaningful while `isStreaming` is also `true`.
72
+ */
73
+ awaitingApproval?: boolean;
74
+ /**
75
+ * Final outcome of the tool call.
76
+ *
77
+ * Populated when `isStreaming` transitions to `false`:
78
+ * - `success`: tool returned normally
79
+ * - `error`: tool threw an exception (or was not registered)
80
+ * - `cancelled`: the user rejected the call via the approval flow
81
+ *
82
+ * `undefined` while the tool is still streaming.
83
+ */
84
+ status?: ToolCallStatus;
85
+ }
86
+ /**
87
+ * The rendered state of a single turn in the conversation.
88
+ *
89
+ * Each `sendMessage` call produces one user entry and one assistant entry.
90
+ * The assistant entry is updated in place as `AgentEvent`s stream in; it is
91
+ * never replaced — its `id` is stable for React reconciliation.
92
+ */
93
+ export interface ConversationEntry {
94
+ /** Stable identifier used as the React `key` for this entry. */
95
+ id: string;
96
+ /** Whether this entry was produced by the user or the assistant. */
97
+ role: 'user' | 'assistant';
98
+ /**
99
+ * The accumulated text content of this entry.
100
+ *
101
+ * For user entries this is the original message text.
102
+ * For assistant entries it grows with each `text_delta` event and is
103
+ * finalised to `event.output` when `done` is received.
104
+ */
105
+ text: string;
106
+ /**
107
+ * Accumulated thinking/reasoning trace for this assistant turn.
108
+ * Only present when the model emits `thinking` deltas.
109
+ */
110
+ thinking?: string;
111
+ /**
112
+ * Ordered list of tool invocations made during this assistant turn.
113
+ * Each element corresponds to one `tool_call_started` event and is updated
114
+ * in-place as the tool executes.
115
+ */
116
+ toolEvents: ToolEventEntry[];
117
+ /**
118
+ * `true` while the assistant is generating this entry; `false` once `done`,
119
+ * an error, or a cancellation is received.
120
+ * Drives streaming indicators across all child components.
121
+ */
122
+ isStreaming: boolean;
123
+ }
124
+ /**
125
+ * Allows consumers to replace any or all of the six built-in SVG icons with
126
+ * their own React nodes (e.g. from `lucide-react` or a custom design system).
127
+ *
128
+ * Pass an `IconMap` to the `icons` prop of `<AgentProvider>`. Unspecified keys
129
+ * fall back to the bundled inline SVG defaults.
130
+ *
131
+ * @example
132
+ * ```tsx
133
+ * import { Brain, Wrench, CircleCheck, LoaderCircle, Send, Square } from 'lucide-react';
134
+ *
135
+ * <AgentProvider icons={{
136
+ * brain: <Brain size={16} />,
137
+ * wrench: <Wrench size={16} />,
138
+ * check: <CircleCheck size={16} />,
139
+ * loader: <LoaderCircle size={16} className="mast-spin" />,
140
+ * send: <Send size={16} />,
141
+ * stop: <Square size={16} />,
142
+ * }}>
143
+ * ```
144
+ */
145
+ export interface IconMap {
146
+ /** Shown in the `<ThinkingBlock>` header. */
147
+ brain?: ReactNode;
148
+ /** Shown in the `<ToolCallBlock>` header while the tool is pending. */
149
+ wrench?: ReactNode;
150
+ /** Shown in the `<ToolCallBlock>` header when the tool succeeded. */
151
+ check?: ReactNode;
152
+ /** Shown in the `<ToolCallBlock>` header when the tool threw an error. */
153
+ error?: ReactNode;
154
+ /** Shown in the `<ToolCallBlock>` header when the user cancelled the tool call. */
155
+ cancelled?: ReactNode;
156
+ /** Animated spinner shown during streaming and pending tool calls. */
157
+ loader?: ReactNode;
158
+ /** Shown on the send button in `<ChatInput>`. */
159
+ send?: ReactNode;
160
+ /** Shown on the cancel button in `<ChatInput>` while `isRunning` is true. */
161
+ stop?: ReactNode;
162
+ }
package/package.json ADDED
@@ -0,0 +1,71 @@
1
+ {
2
+ "name": "@mast-ai/react-ui",
3
+ "version": "0.1.0",
4
+ "license": "Apache-2.0",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ },
13
+ "./styles.css": "./dist/styles.css"
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "git+https://github.com/andreban/mast-ai.git",
21
+ "directory": "packages/react-ui"
22
+ },
23
+ "publishConfig": {
24
+ "registry": "https://registry.npmjs.org",
25
+ "access": "public"
26
+ },
27
+ "scripts": {
28
+ "clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"",
29
+ "build": "npm run clean && vite build && tsc",
30
+ "prepublishOnly": "npm run build",
31
+ "dev": "vite build --watch",
32
+ "test": "vitest run --passWithNoTests",
33
+ "lint": "eslint src",
34
+ "format": "prettier --write src"
35
+ },
36
+ "peerDependencies": {
37
+ "@mast-ai/core": "^0.1.0",
38
+ "@tanstack/react-virtual": ">=3.0.0",
39
+ "react": ">=19.0.0",
40
+ "react-dom": ">=19.0.0"
41
+ },
42
+ "peerDependenciesMeta": {
43
+ "react-markdown": {
44
+ "optional": true
45
+ },
46
+ "remark-gfm": {
47
+ "optional": true
48
+ },
49
+ "rehype-sanitize": {
50
+ "optional": true
51
+ }
52
+ },
53
+ "devDependencies": {
54
+ "@mast-ai/core": "*",
55
+ "@tanstack/react-virtual": "^3.0.0",
56
+ "@testing-library/react": "^16.0.0",
57
+ "@testing-library/user-event": "^14.0.0",
58
+ "@types/react": "^19.0.0",
59
+ "@types/react-dom": "^19.0.0",
60
+ "@vitejs/plugin-react": "^4.0.0",
61
+ "jsdom": "^26.0.0",
62
+ "react": "^19.0.0",
63
+ "react-dom": "^19.0.0",
64
+ "react-markdown": "^9.0.0",
65
+ "rehype-sanitize": "^6.0.0",
66
+ "remark-gfm": "^4.0.0",
67
+ "typescript": "~6.0.2",
68
+ "vite": "^6.0.0",
69
+ "vitest": "^3.0.0"
70
+ }
71
+ }