@agentick/tui 0.4.0 → 0.6.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.
- package/README.md +202 -20
- package/dist/commands-context.d.ts +10 -0
- package/dist/commands-context.d.ts.map +1 -0
- package/dist/commands-context.js +10 -0
- package/dist/commands-context.js.map +1 -0
- package/dist/commands.d.ts +30 -0
- package/dist/commands.d.ts.map +1 -0
- package/dist/commands.js +163 -0
- package/dist/commands.js.map +1 -0
- package/dist/components/CompletionPicker.d.ts +12 -0
- package/dist/components/CompletionPicker.d.ts.map +1 -0
- package/dist/components/CompletionPicker.js +41 -0
- package/dist/components/CompletionPicker.js.map +1 -0
- package/dist/components/DiffView.d.ts +21 -0
- package/dist/components/DiffView.d.ts.map +1 -0
- package/dist/components/DiffView.js +94 -0
- package/dist/components/DiffView.js.map +1 -0
- package/dist/components/ErrorDisplay.d.ts +6 -6
- package/dist/components/ErrorDisplay.d.ts.map +1 -1
- package/dist/components/ErrorDisplay.js +6 -8
- package/dist/components/ErrorDisplay.js.map +1 -1
- package/dist/components/InputBar.d.ts +8 -7
- package/dist/components/InputBar.d.ts.map +1 -1
- package/dist/components/InputBar.js +7 -13
- package/dist/components/InputBar.js.map +1 -1
- package/dist/components/MessageList.d.ts +11 -5
- package/dist/components/MessageList.d.ts.map +1 -1
- package/dist/components/MessageList.js +37 -44
- package/dist/components/MessageList.js.map +1 -1
- package/dist/components/RichTextInput.d.ts +14 -0
- package/dist/components/RichTextInput.d.ts.map +1 -0
- package/dist/components/RichTextInput.js +24 -0
- package/dist/components/RichTextInput.js.map +1 -0
- package/dist/components/ToolCallIndicator.d.ts.map +1 -1
- package/dist/components/ToolCallIndicator.js +12 -5
- package/dist/components/ToolCallIndicator.js.map +1 -1
- package/dist/components/ToolConfirmationPrompt.d.ts +9 -6
- package/dist/components/ToolConfirmationPrompt.d.ts.map +1 -1
- package/dist/components/ToolConfirmationPrompt.js +18 -19
- package/dist/components/ToolConfirmationPrompt.js.map +1 -1
- package/dist/components/status-bar/DefaultStatusBar.d.ts +20 -0
- package/dist/components/status-bar/DefaultStatusBar.d.ts.map +1 -0
- package/dist/components/status-bar/DefaultStatusBar.js +11 -0
- package/dist/components/status-bar/DefaultStatusBar.js.map +1 -0
- package/dist/components/status-bar/StatusBar.d.ts +22 -0
- package/dist/components/status-bar/StatusBar.d.ts.map +1 -0
- package/dist/components/status-bar/StatusBar.js +16 -0
- package/dist/components/status-bar/StatusBar.js.map +1 -0
- package/dist/components/status-bar/StatusBarRight.d.ts +12 -0
- package/dist/components/status-bar/StatusBarRight.d.ts.map +1 -0
- package/dist/components/status-bar/StatusBarRight.js +29 -0
- package/dist/components/status-bar/StatusBarRight.js.map +1 -0
- package/dist/components/status-bar/context.d.ts +27 -0
- package/dist/components/status-bar/context.d.ts.map +1 -0
- package/dist/components/status-bar/context.js +18 -0
- package/dist/components/status-bar/context.js.map +1 -0
- package/dist/components/status-bar/index.d.ts +5 -0
- package/dist/components/status-bar/index.d.ts.map +1 -0
- package/dist/components/status-bar/index.js +5 -0
- package/dist/components/status-bar/index.js.map +1 -0
- package/dist/components/status-bar/widgets/BrandLabel.d.ts +8 -0
- package/dist/components/status-bar/widgets/BrandLabel.d.ts.map +1 -0
- package/dist/components/status-bar/widgets/BrandLabel.js +6 -0
- package/dist/components/status-bar/widgets/BrandLabel.js.map +1 -0
- package/dist/components/status-bar/widgets/ContextUtilization.d.ts +11 -0
- package/dist/components/status-bar/widgets/ContextUtilization.d.ts.map +1 -0
- package/dist/components/status-bar/widgets/ContextUtilization.js +12 -0
- package/dist/components/status-bar/widgets/ContextUtilization.js.map +1 -0
- package/dist/components/status-bar/widgets/KeyboardHints.d.ts +16 -0
- package/dist/components/status-bar/widgets/KeyboardHints.d.ts.map +1 -0
- package/dist/components/status-bar/widgets/KeyboardHints.js +25 -0
- package/dist/components/status-bar/widgets/KeyboardHints.js.map +1 -0
- package/dist/components/status-bar/widgets/ModelInfo.d.ts +7 -0
- package/dist/components/status-bar/widgets/ModelInfo.d.ts.map +1 -0
- package/dist/components/status-bar/widgets/ModelInfo.js +10 -0
- package/dist/components/status-bar/widgets/ModelInfo.js.map +1 -0
- package/dist/components/status-bar/widgets/Separator.d.ts +7 -0
- package/dist/components/status-bar/widgets/Separator.d.ts.map +1 -0
- package/dist/components/status-bar/widgets/Separator.js +6 -0
- package/dist/components/status-bar/widgets/Separator.js.map +1 -0
- package/dist/components/status-bar/widgets/StateIndicator.d.ts +12 -0
- package/dist/components/status-bar/widgets/StateIndicator.d.ts.map +1 -0
- package/dist/components/status-bar/widgets/StateIndicator.js +21 -0
- package/dist/components/status-bar/widgets/StateIndicator.js.map +1 -0
- package/dist/components/status-bar/widgets/TickCount.d.ts +9 -0
- package/dist/components/status-bar/widgets/TickCount.d.ts.map +1 -0
- package/dist/components/status-bar/widgets/TickCount.js +11 -0
- package/dist/components/status-bar/widgets/TickCount.js.map +1 -0
- package/dist/components/status-bar/widgets/TokenCount.d.ts +12 -0
- package/dist/components/status-bar/widgets/TokenCount.d.ts.map +1 -0
- package/dist/components/status-bar/widgets/TokenCount.js +28 -0
- package/dist/components/status-bar/widgets/TokenCount.js.map +1 -0
- package/dist/components/status-bar/widgets/index.d.ts +9 -0
- package/dist/components/status-bar/widgets/index.d.ts.map +1 -0
- package/dist/components/status-bar/widgets/index.js +9 -0
- package/dist/components/status-bar/widgets/index.js.map +1 -0
- package/dist/create-tui.d.ts +17 -6
- package/dist/create-tui.d.ts.map +1 -1
- package/dist/create-tui.js +14 -3
- package/dist/create-tui.js.map +1 -1
- package/dist/hooks/use-double-ctrl-c.d.ts +5 -0
- package/dist/hooks/use-double-ctrl-c.d.ts.map +1 -0
- package/dist/hooks/use-double-ctrl-c.js +32 -0
- package/dist/hooks/use-double-ctrl-c.js.map +1 -0
- package/dist/hooks/use-line-editor.d.ts +26 -0
- package/dist/hooks/use-line-editor.d.ts.map +1 -0
- package/dist/hooks/use-line-editor.js +63 -0
- package/dist/hooks/use-line-editor.js.map +1 -0
- package/dist/index.d.ts +14 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -1
- package/dist/input-utils.d.ts +15 -0
- package/dist/input-utils.d.ts.map +1 -0
- package/dist/input-utils.js +29 -0
- package/dist/input-utils.js.map +1 -0
- package/dist/rendering/content-block.d.ts +12 -0
- package/dist/rendering/content-block.d.ts.map +1 -0
- package/dist/rendering/content-block.js +82 -0
- package/dist/rendering/content-block.js.map +1 -0
- package/dist/rendering/index.d.ts +5 -0
- package/dist/rendering/index.d.ts.map +1 -0
- package/dist/rendering/index.js +5 -0
- package/dist/rendering/index.js.map +1 -0
- package/dist/rendering/markdown.d.ts +14 -0
- package/dist/rendering/markdown.d.ts.map +1 -0
- package/dist/rendering/markdown.js +61 -0
- package/dist/rendering/markdown.js.map +1 -0
- package/dist/rendering/message.d.ts +25 -0
- package/dist/rendering/message.d.ts.map +1 -0
- package/dist/rendering/message.js +54 -0
- package/dist/rendering/message.js.map +1 -0
- package/dist/rendering/theme.d.ts +37 -0
- package/dist/rendering/theme.d.ts.map +1 -0
- package/dist/rendering/theme.js +49 -0
- package/dist/rendering/theme.js.map +1 -0
- package/dist/ui/chat.d.ts +26 -4
- package/dist/ui/chat.d.ts.map +1 -1
- package/dist/ui/chat.js +91 -68
- package/dist/ui/chat.js.map +1 -1
- package/package.json +11 -6
package/README.md
CHANGED
|
@@ -54,6 +54,16 @@ import { MyDashboard } from "./dashboard.js";
|
|
|
54
54
|
createTUI({ app, ui: MyDashboard }).start();
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
+
### Alternate Screen
|
|
58
|
+
|
|
59
|
+
Use the terminal's alternate screen buffer to avoid polluting scrollback:
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
createTUI({ app, alternateScreen: true }).start();
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
When enabled, the TUI takes over the alternate screen on start and restores the normal screen on exit. This prevents terminal scrollbar confusion where native scrollback doesn't interact with Ink's rendering.
|
|
66
|
+
|
|
57
67
|
## CLI
|
|
58
68
|
|
|
59
69
|
The `agentick-tui` binary launches a TUI from the command line.
|
|
@@ -104,20 +114,22 @@ Returns `{ start(): Promise<void> }`.
|
|
|
104
114
|
|
|
105
115
|
**Local options:**
|
|
106
116
|
|
|
107
|
-
| Option
|
|
108
|
-
|
|
|
109
|
-
| `app`
|
|
110
|
-
| `sessionId`
|
|
111
|
-
| `ui`
|
|
117
|
+
| Option | Type | Description |
|
|
118
|
+
| ----------------- | -------------- | -------------------------------------------- |
|
|
119
|
+
| `app` | `App` | Agentick App instance |
|
|
120
|
+
| `sessionId` | `string` | Session ID (default: `"main"`) |
|
|
121
|
+
| `ui` | `TUIComponent` | Custom UI component (default: `Chat`) |
|
|
122
|
+
| `alternateScreen` | `boolean` | Use alternate screen buffer (default: false) |
|
|
112
123
|
|
|
113
124
|
**Remote options:**
|
|
114
125
|
|
|
115
|
-
| Option
|
|
116
|
-
|
|
|
117
|
-
| `url`
|
|
118
|
-
| `token`
|
|
119
|
-
| `sessionId`
|
|
120
|
-
| `ui`
|
|
126
|
+
| Option | Type | Description |
|
|
127
|
+
| ----------------- | -------------- | -------------------------------------------- |
|
|
128
|
+
| `url` | `string` | Gateway URL |
|
|
129
|
+
| `token` | `string` | Auth token |
|
|
130
|
+
| `sessionId` | `string` | Session ID (default: `"main"`) |
|
|
131
|
+
| `ui` | `TUIComponent` | Custom UI component (default: `Chat`) |
|
|
132
|
+
| `alternateScreen` | `boolean` | Use alternate screen buffer (default: false) |
|
|
121
133
|
|
|
122
134
|
### TUIComponent
|
|
123
135
|
|
|
@@ -136,15 +148,185 @@ const MyUI: TUIComponent = ({ sessionId }) => {
|
|
|
136
148
|
|
|
137
149
|
All components are exported for building custom UIs.
|
|
138
150
|
|
|
139
|
-
| Component | Purpose
|
|
140
|
-
| ------------------------ |
|
|
141
|
-
| `Chat` | Default
|
|
142
|
-
| `MessageList` |
|
|
143
|
-
| `StreamingMessage` | Live streaming response with cursor
|
|
144
|
-
| `ToolCallIndicator` | Spinner during tool execution
|
|
145
|
-
| `ToolConfirmationPrompt` | Y/N/A prompt for tools with `requireConfirmation`
|
|
146
|
-
| `
|
|
147
|
-
| `
|
|
151
|
+
| Component | Purpose |
|
|
152
|
+
| ------------------------ | --------------------------------------------------- |
|
|
153
|
+
| `Chat` | Default conversational interface (block rendering) |
|
|
154
|
+
| `MessageList` | Prop-driven message display (Static + in-progress) |
|
|
155
|
+
| `StreamingMessage` | Live streaming response with cursor |
|
|
156
|
+
| `ToolCallIndicator` | Spinner during tool execution |
|
|
157
|
+
| `ToolConfirmationPrompt` | Y/N/A prompt for tools with `requireConfirmation` |
|
|
158
|
+
| `DiffView` | Side-by-side diff display for file changes |
|
|
159
|
+
| `ErrorDisplay` | Error box with optional dismiss |
|
|
160
|
+
| `InputBar` | Visual-only text input (value + cursor from parent) |
|
|
161
|
+
| `CompletionPicker` | Windowed completion list (emerald-themed) |
|
|
162
|
+
| `StatusBar` | Container with context provider and layout |
|
|
163
|
+
| `DefaultStatusBar` | Pre-composed status bar with responsive layout |
|
|
164
|
+
|
|
165
|
+
**Status bar widgets** (use standalone or inside `<StatusBar>`):
|
|
166
|
+
|
|
167
|
+
| Widget | Purpose |
|
|
168
|
+
| -------------------- | ------------------------------------------- |
|
|
169
|
+
| `ModelInfo` | Model name/id display |
|
|
170
|
+
| `TokenCount` | Formatted token count (cumulative or tick) |
|
|
171
|
+
| `TickCount` | Current execution tick number |
|
|
172
|
+
| `ContextUtilization` | Utilization % with color thresholds |
|
|
173
|
+
| `StateIndicator` | Mode label with color (idle/streaming/etc.) |
|
|
174
|
+
| `KeyboardHints` | Contextual keyboard shortcut hints |
|
|
175
|
+
| `BrandLabel` | Styled app name |
|
|
176
|
+
| `Separator` | Visual divider between segments |
|
|
177
|
+
|
|
178
|
+
### InputBar
|
|
179
|
+
|
|
180
|
+
Visual-only input display. Renders the current value and cursor position — all keystroke handling lives in the parent via `useLineEditor`.
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
import { InputBar, useLineEditor } from "@agentick/tui";
|
|
184
|
+
|
|
185
|
+
const editor = useLineEditor({ onSubmit: handleSubmit });
|
|
186
|
+
|
|
187
|
+
<InputBar
|
|
188
|
+
value={editor.value}
|
|
189
|
+
cursor={editor.cursor}
|
|
190
|
+
isActive={chatMode === "idle"}
|
|
191
|
+
placeholder="Type a message..."
|
|
192
|
+
/>
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### useLineEditor
|
|
196
|
+
|
|
197
|
+
Ink-specific wrapper around `@agentick/client`'s `LineEditor` class. Provides
|
|
198
|
+
readline-quality editing with cursor movement, history, kill/yank, and word
|
|
199
|
+
navigation.
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
const editor = useLineEditor({
|
|
203
|
+
onSubmit: (text) => send(text),
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
// In your centralized useInput handler:
|
|
207
|
+
if (chatMode === "idle") {
|
|
208
|
+
editor.handleInput(input, key);
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Returns `{ value, cursor, completion, completedRanges, handleInput, setValue, clear, editor }`. Does not call `useInput` internally — the parent routes keystrokes to `editor.handleInput` when appropriate.
|
|
213
|
+
|
|
214
|
+
The `editor` property exposes the raw `LineEditor` instance for registering completion sources. The `completion` property is the current `CompletionState | null` — pass it to `CompletionPicker` to render the autocomplete picker.
|
|
215
|
+
|
|
216
|
+
For framework-agnostic usage (web, Angular), use `LineEditor` from `@agentick/client` directly, or `useLineEditor` from `@agentick/react`.
|
|
217
|
+
|
|
218
|
+
### CompletionPicker
|
|
219
|
+
|
|
220
|
+
Renders a windowed completion list from `CompletionState`. Emerald-themed border, inverse highlight for the selected item, loading spinner, and "No matches" empty state.
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
import { CompletionPicker } from "@agentick/tui";
|
|
224
|
+
|
|
225
|
+
{editor.completion && <CompletionPicker completion={editor.completion} />}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Slash Commands
|
|
229
|
+
|
|
230
|
+
`useSlashCommands` provides a command registry with dispatch, dynamic add/remove, and completion integration.
|
|
231
|
+
|
|
232
|
+
```typescript
|
|
233
|
+
import {
|
|
234
|
+
useSlashCommands,
|
|
235
|
+
helpCommand,
|
|
236
|
+
exitCommand,
|
|
237
|
+
createCommandCompletionSource,
|
|
238
|
+
} from "@agentick/tui";
|
|
239
|
+
|
|
240
|
+
const { dispatch, commands } = useSlashCommands([helpCommand(), exitCommand(exit)], {
|
|
241
|
+
sessionId,
|
|
242
|
+
send,
|
|
243
|
+
abort,
|
|
244
|
+
output: console.log,
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
// Wire into completion
|
|
248
|
+
useEffect(() => {
|
|
249
|
+
return editor.editor.registerCompletion(createCommandCompletionSource(commands));
|
|
250
|
+
}, [editor.editor, commands]);
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
See [`COMPLETION.md`](../client/COMPLETION.md) for the full completion system reference.
|
|
254
|
+
|
|
255
|
+
### handleConfirmationKey
|
|
256
|
+
|
|
257
|
+
Input routing utility for tool confirmation prompts. Maps `y`/`n`/`a` keys to confirmation responses.
|
|
258
|
+
|
|
259
|
+
```typescript
|
|
260
|
+
import { handleConfirmationKey } from "@agentick/tui";
|
|
261
|
+
|
|
262
|
+
if (chatMode === "confirming_tool") {
|
|
263
|
+
handleConfirmationKey(input, respondToConfirmation);
|
|
264
|
+
}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### MessageList
|
|
268
|
+
|
|
269
|
+
Prop-driven message display. Accepts `messages` from `useChat` and splits them into committed (Ink `<Static>`) and in-progress (regular render) based on `isExecuting`.
|
|
270
|
+
|
|
271
|
+
```typescript
|
|
272
|
+
<MessageList messages={messages} isExecuting={isExecuting} />
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
`Chat` uses `useChat({ renderMode: "block" })` so messages appear block-at-a-time as content completes, rather than waiting for the entire execution to finish.
|
|
276
|
+
|
|
277
|
+
### StatusBar
|
|
278
|
+
|
|
279
|
+
`<StatusBar>` is a container that calls `useContextInfo` and `useStreamingText` once, provides the data via React context, and renders a left/right flexbox layout with a top border.
|
|
280
|
+
|
|
281
|
+
Widgets read from context automatically when inside a `<StatusBar>`, or accept explicit props when used standalone.
|
|
282
|
+
|
|
283
|
+
**Default** — `Chat` renders `<DefaultStatusBar>` automatically:
|
|
284
|
+
|
|
285
|
+
```
|
|
286
|
+
Enter send | Ctrl+C exit GPT-4o | 6.2K 35% | idle
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
The default is responsive — hides token/utilization info in narrow terminals.
|
|
290
|
+
|
|
291
|
+
**Custom** — compose your own from widgets:
|
|
292
|
+
|
|
293
|
+
```typescript
|
|
294
|
+
import { StatusBar, BrandLabel, ModelInfo, TokenCount,
|
|
295
|
+
ContextUtilization, StateIndicator, Separator, KeyboardHints } from "@agentick/tui";
|
|
296
|
+
|
|
297
|
+
<StatusBar sessionId={sessionId} mode={chatMode}
|
|
298
|
+
left={<KeyboardHints hints={{ idle: [{ key: "Tab", action: "complete" }] }} />}
|
|
299
|
+
right={<>
|
|
300
|
+
<BrandLabel name="myapp" />
|
|
301
|
+
<Separator />
|
|
302
|
+
<ModelInfo />
|
|
303
|
+
<Separator />
|
|
304
|
+
<TokenCount cumulative />
|
|
305
|
+
<Separator />
|
|
306
|
+
<ContextUtilization />
|
|
307
|
+
<Separator />
|
|
308
|
+
<StateIndicator labels={{ streaming: "active" }} />
|
|
309
|
+
</>}
|
|
310
|
+
/>
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
**Chat integration** — control the status bar via the `statusBar` prop:
|
|
314
|
+
|
|
315
|
+
```typescript
|
|
316
|
+
// Default (renders DefaultStatusBar)
|
|
317
|
+
<Chat sessionId="main" />
|
|
318
|
+
|
|
319
|
+
// Disabled
|
|
320
|
+
<Chat sessionId="main" statusBar={false} />
|
|
321
|
+
|
|
322
|
+
// Render prop — receives chat state
|
|
323
|
+
<Chat sessionId="main" statusBar={({ mode, sessionId }) => (
|
|
324
|
+
<StatusBar sessionId={sessionId} mode={mode}
|
|
325
|
+
left={<KeyboardHints />}
|
|
326
|
+
right={<StateIndicator />}
|
|
327
|
+
/>
|
|
328
|
+
)} />
|
|
329
|
+
```
|
|
148
330
|
|
|
149
331
|
## Architecture
|
|
150
332
|
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import type { SlashCommand } from "./commands.js";
|
|
3
|
+
interface CommandsProviderProps {
|
|
4
|
+
commands: (SlashCommand | SlashCommand[])[];
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
}
|
|
7
|
+
export declare function CommandsProvider({ commands, children }: CommandsProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export declare function useCommandsConfig(): (SlashCommand | SlashCommand[])[];
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=commands-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands-context.d.ts","sourceRoot":"","sources":["../src/commands-context.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAIlD,UAAU,qBAAqB;IAC7B,QAAQ,EAAE,CAAC,YAAY,GAAG,YAAY,EAAE,CAAC,EAAE,CAAC;IAC5C,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,wBAAgB,gBAAgB,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,qBAAqB,2CAI7E;AAED,wBAAgB,iBAAiB,IAAI,CAAC,YAAY,GAAG,YAAY,EAAE,CAAC,EAAE,CAErE"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useContext } from "react";
|
|
3
|
+
const CommandsConfigContext = createContext([]);
|
|
4
|
+
export function CommandsProvider({ commands, children }) {
|
|
5
|
+
return (_jsx(CommandsConfigContext.Provider, { value: commands, children: children }));
|
|
6
|
+
}
|
|
7
|
+
export function useCommandsConfig() {
|
|
8
|
+
return useContext(CommandsConfigContext);
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=commands-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands-context.js","sourceRoot":"","sources":["../src/commands-context.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAIlD,MAAM,qBAAqB,GAAG,aAAa,CAAoC,EAAE,CAAC,CAAC;AAOnF,MAAM,UAAU,gBAAgB,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAyB;IAC5E,OAAO,CACL,KAAC,qBAAqB,CAAC,QAAQ,IAAC,KAAK,EAAE,QAAQ,YAAG,QAAQ,GAAkC,CAC7F,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,OAAO,UAAU,CAAC,qBAAqB,CAAC,CAAC;AAC3C,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { CompletionSource } from "@agentick/client";
|
|
2
|
+
export interface SlashCommand {
|
|
3
|
+
name: string;
|
|
4
|
+
description: string;
|
|
5
|
+
aliases?: string[];
|
|
6
|
+
args?: string;
|
|
7
|
+
handler: (args: string, ctx: CommandContext) => void | Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
export interface CommandContext {
|
|
10
|
+
sessionId: string;
|
|
11
|
+
send: (...args: any[]) => any;
|
|
12
|
+
abort: () => void;
|
|
13
|
+
output: (text: string) => void;
|
|
14
|
+
addCommand: (cmd: SlashCommand) => void;
|
|
15
|
+
removeCommand: (name: string) => void;
|
|
16
|
+
}
|
|
17
|
+
export declare function helpCommand(): SlashCommand;
|
|
18
|
+
export declare function clearCommand(onClear: () => void): SlashCommand;
|
|
19
|
+
export declare function exitCommand(onExit: () => void): SlashCommand;
|
|
20
|
+
export declare function loadCommand(): SlashCommand;
|
|
21
|
+
export declare function createCommandCompletionSource(commands: SlashCommand[]): CompletionSource;
|
|
22
|
+
interface UseSlashCommandsResult {
|
|
23
|
+
dispatch: (input: string) => boolean;
|
|
24
|
+
commands: SlashCommand[];
|
|
25
|
+
addCommand: (cmd: SlashCommand) => void;
|
|
26
|
+
removeCommand: (name: string) => void;
|
|
27
|
+
}
|
|
28
|
+
export declare function useSlashCommands(initial: (SlashCommand | SlashCommand[])[], ctx: Omit<CommandContext, "addCommand" | "removeCommand">): UseSlashCommandsResult;
|
|
29
|
+
export {};
|
|
30
|
+
//# sourceMappingURL=commands.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAkB,MAAM,kBAAkB,CAAC;AAIzE,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,cAAc,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACtE;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAElB,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC;IAC9B,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,UAAU,EAAE,CAAC,GAAG,EAAE,YAAY,KAAK,IAAI,CAAC;IACxC,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACvC;AAID,wBAAgB,WAAW,IAAI,YAAY,CAS1C;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,IAAI,GAAG,YAAY,CAQ9D;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,IAAI,GAAG,YAAY,CAS5D;AAED,wBAAgB,WAAW,IAAI,YAAY,CAkC1C;AAuBD,wBAAgB,6BAA6B,CAAC,QAAQ,EAAE,YAAY,EAAE,GAAG,gBAAgB,CAmBxF;AAID,UAAU,sBAAsB;IAC9B,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;IACrC,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,UAAU,EAAE,CAAC,GAAG,EAAE,YAAY,KAAK,IAAI,CAAC;IACxC,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACvC;AAED,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,CAAC,YAAY,GAAG,YAAY,EAAE,CAAC,EAAE,EAC1C,GAAG,EAAE,IAAI,CAAC,cAAc,EAAE,YAAY,GAAG,eAAe,CAAC,GACxD,sBAAsB,CAmFxB"}
|
package/dist/commands.js
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { useState, useCallback, useMemo, useRef } from "react";
|
|
2
|
+
// --- Built-in command factories ---
|
|
3
|
+
export function helpCommand() {
|
|
4
|
+
return {
|
|
5
|
+
name: "help",
|
|
6
|
+
description: "Show available commands",
|
|
7
|
+
handler: (_args, ctx) => {
|
|
8
|
+
// Access commands via closure — the registry ref is captured in useSlashCommands
|
|
9
|
+
ctx.output("Unknown command registry — /help is wired internally");
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export function clearCommand(onClear) {
|
|
14
|
+
return {
|
|
15
|
+
name: "clear",
|
|
16
|
+
description: "Clear message history",
|
|
17
|
+
handler: () => {
|
|
18
|
+
onClear();
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export function exitCommand(onExit) {
|
|
23
|
+
return {
|
|
24
|
+
name: "exit",
|
|
25
|
+
description: "Exit",
|
|
26
|
+
aliases: ["quit"],
|
|
27
|
+
handler: () => {
|
|
28
|
+
onExit();
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export function loadCommand() {
|
|
33
|
+
return {
|
|
34
|
+
name: "load",
|
|
35
|
+
description: "Load a command from a file",
|
|
36
|
+
args: "<path>",
|
|
37
|
+
handler: async (args, ctx) => {
|
|
38
|
+
const filePath = args.trim();
|
|
39
|
+
if (!filePath) {
|
|
40
|
+
ctx.output("Usage: /load <path>");
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const resolved = filePath.startsWith("/") ? filePath : `${process.cwd()}/${filePath}`;
|
|
44
|
+
try {
|
|
45
|
+
const mod = await import(resolved);
|
|
46
|
+
const cmd = mod.command ?? mod.default;
|
|
47
|
+
if (!cmd || !cmd.name || !cmd.description || !cmd.handler) {
|
|
48
|
+
ctx.output(`Invalid command file: expected export const command: SlashCommand or export default`);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
ctx.addCommand(cmd);
|
|
52
|
+
ctx.output(`Loaded /${cmd.name} — ${cmd.description}`);
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
ctx.output(`Failed to load ${resolved}: ${err instanceof Error ? err.message : String(err)}`);
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
// --- Help formatting ---
|
|
61
|
+
function formatHelp(commands) {
|
|
62
|
+
const sorted = [...commands].sort((a, b) => a.name.localeCompare(b.name));
|
|
63
|
+
const lines = [];
|
|
64
|
+
for (const cmd of sorted) {
|
|
65
|
+
const nameWithArgs = cmd.args ? `/${cmd.name} ${cmd.args}` : `/${cmd.name}`;
|
|
66
|
+
const aliasStr = cmd.aliases && cmd.aliases.length > 0
|
|
67
|
+
? ` (aliases: ${cmd.aliases.map((a) => `/${a}`).join(", ")})`
|
|
68
|
+
: "";
|
|
69
|
+
const padded = nameWithArgs.padEnd(20);
|
|
70
|
+
lines.push(` ${padded}${cmd.description}${aliasStr}`);
|
|
71
|
+
}
|
|
72
|
+
return lines.join("\n");
|
|
73
|
+
}
|
|
74
|
+
// --- Completion source factory ---
|
|
75
|
+
export function createCommandCompletionSource(commands) {
|
|
76
|
+
return {
|
|
77
|
+
id: "command",
|
|
78
|
+
trigger: { type: "char", char: "/" },
|
|
79
|
+
shouldActivate: (_value, anchor) => anchor === 0,
|
|
80
|
+
resolve: (query) => {
|
|
81
|
+
const items = [];
|
|
82
|
+
for (const cmd of commands) {
|
|
83
|
+
if (!query || cmd.name.startsWith(query)) {
|
|
84
|
+
items.push({
|
|
85
|
+
label: cmd.name,
|
|
86
|
+
value: `/${cmd.name}`,
|
|
87
|
+
description: cmd.description,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return items;
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
export function useSlashCommands(initial, ctx) {
|
|
96
|
+
const [registry, setRegistry] = useState(() => {
|
|
97
|
+
const map = new Map();
|
|
98
|
+
for (const item of initial.flat()) {
|
|
99
|
+
map.set(item.name, item);
|
|
100
|
+
}
|
|
101
|
+
return map;
|
|
102
|
+
});
|
|
103
|
+
// Keep a ref so dispatch always sees current registry without re-creating the callback
|
|
104
|
+
const registryRef = useRef(registry);
|
|
105
|
+
registryRef.current = registry;
|
|
106
|
+
const addCommand = useCallback((cmd) => {
|
|
107
|
+
setRegistry((prev) => {
|
|
108
|
+
const next = new Map(prev);
|
|
109
|
+
next.set(cmd.name, cmd);
|
|
110
|
+
return next;
|
|
111
|
+
});
|
|
112
|
+
}, []);
|
|
113
|
+
const removeCommand = useCallback((name) => {
|
|
114
|
+
setRegistry((prev) => {
|
|
115
|
+
const next = new Map(prev);
|
|
116
|
+
next.delete(name);
|
|
117
|
+
return next;
|
|
118
|
+
});
|
|
119
|
+
}, []);
|
|
120
|
+
const dispatch = useCallback((input) => {
|
|
121
|
+
if (!input.startsWith("/"))
|
|
122
|
+
return false;
|
|
123
|
+
const spaceIdx = input.indexOf(" ");
|
|
124
|
+
const name = spaceIdx === -1 ? input.slice(1) : input.slice(1, spaceIdx);
|
|
125
|
+
const args = spaceIdx === -1 ? "" : input.slice(spaceIdx + 1);
|
|
126
|
+
const reg = registryRef.current;
|
|
127
|
+
// Direct name match
|
|
128
|
+
let cmd = reg.get(name);
|
|
129
|
+
// Alias match
|
|
130
|
+
if (!cmd) {
|
|
131
|
+
for (const candidate of reg.values()) {
|
|
132
|
+
if (candidate.aliases?.includes(name)) {
|
|
133
|
+
cmd = candidate;
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (!cmd) {
|
|
139
|
+
ctx.output(`Unknown command: /${name}. Type /help for available commands.`);
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
// Special-case /help: format with current registry
|
|
143
|
+
if (cmd.name === "help") {
|
|
144
|
+
ctx.output(formatHelp([...reg.values()]));
|
|
145
|
+
return true;
|
|
146
|
+
}
|
|
147
|
+
const fullCtx = {
|
|
148
|
+
...ctx,
|
|
149
|
+
addCommand,
|
|
150
|
+
removeCommand,
|
|
151
|
+
};
|
|
152
|
+
cmd.handler(args, fullCtx);
|
|
153
|
+
return true;
|
|
154
|
+
}, [ctx, addCommand, removeCommand]);
|
|
155
|
+
const commands = useMemo(() => [...registry.values()], [registry]);
|
|
156
|
+
return {
|
|
157
|
+
dispatch,
|
|
158
|
+
commands,
|
|
159
|
+
addCommand,
|
|
160
|
+
removeCommand,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=commands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands.js","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAuB/D,qCAAqC;AAErC,MAAM,UAAU,WAAW;IACzB,OAAO;QACL,IAAI,EAAE,MAAM;QACZ,WAAW,EAAE,yBAAyB;QACtC,OAAO,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;YACtB,iFAAiF;YACjF,GAAG,CAAC,MAAM,CAAC,sDAAsD,CAAC,CAAC;QACrE,CAAC;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,OAAmB;IAC9C,OAAO;QACL,IAAI,EAAE,OAAO;QACb,WAAW,EAAE,uBAAuB;QACpC,OAAO,EAAE,GAAG,EAAE;YACZ,OAAO,EAAE,CAAC;QACZ,CAAC;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAkB;IAC5C,OAAO;QACL,IAAI,EAAE,MAAM;QACZ,WAAW,EAAE,MAAM;QACnB,OAAO,EAAE,CAAC,MAAM,CAAC;QACjB,OAAO,EAAE,GAAG,EAAE;YACZ,MAAM,EAAE,CAAC;QACX,CAAC;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,OAAO;QACL,IAAI,EAAE,MAAM;QACZ,WAAW,EAAE,4BAA4B;QACzC,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE;YAC3B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YAC7B,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,GAAG,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC;gBAClC,OAAO;YACT,CAAC;YAED,MAAM,QAAQ,GAAG,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,GAAG,EAAE,IAAI,QAAQ,EAAE,CAAC;YAEtF,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;gBACnC,MAAM,GAAG,GAA6B,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC;gBAEjE,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,WAAW,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;oBAC1D,GAAG,CAAC,MAAM,CACR,qFAAqF,CACtF,CAAC;oBACF,OAAO;gBACT,CAAC;gBAED,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;gBACpB,GAAG,CAAC,MAAM,CAAC,WAAW,GAAG,CAAC,IAAI,MAAM,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC;YACzD,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,GAAG,CAAC,MAAM,CACR,kBAAkB,QAAQ,KAAK,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAClF,CAAC;YACJ,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AAED,0BAA0B;AAE1B,SAAS,UAAU,CAAC,QAAwB;IAC1C,MAAM,MAAM,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1E,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;QACzB,MAAM,YAAY,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;QAC5E,MAAM,QAAQ,GACZ,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;YACnC,CAAC,CAAC,cAAc,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;YAC7D,CAAC,CAAC,EAAE,CAAC;QACT,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACvC,KAAK,CAAC,IAAI,CAAC,KAAK,MAAM,GAAG,GAAG,CAAC,WAAW,GAAG,QAAQ,EAAE,CAAC,CAAC;IACzD,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,oCAAoC;AAEpC,MAAM,UAAU,6BAA6B,CAAC,QAAwB;IACpE,OAAO;QACL,EAAE,EAAE,SAAS;QACb,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE;QACpC,cAAc,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,KAAK,CAAC;QAChD,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YACjB,MAAM,KAAK,GAAqB,EAAE,CAAC;YACnC,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;gBAC3B,IAAI,CAAC,KAAK,IAAI,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;oBACzC,KAAK,CAAC,IAAI,CAAC;wBACT,KAAK,EAAE,GAAG,CAAC,IAAI;wBACf,KAAK,EAAE,IAAI,GAAG,CAAC,IAAI,EAAE;wBACrB,WAAW,EAAE,GAAG,CAAC,WAAW;qBAC7B,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;KACF,CAAC;AACJ,CAAC;AAWD,MAAM,UAAU,gBAAgB,CAC9B,OAA0C,EAC1C,GAAyD;IAEzD,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAA4B,GAAG,EAAE;QACvE,MAAM,GAAG,GAAG,IAAI,GAAG,EAAwB,CAAC;QAC5C,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;YAClC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAC3B,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC,CAAC,CAAC;IAEH,uFAAuF;IACvF,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;IACrC,WAAW,CAAC,OAAO,GAAG,QAAQ,CAAC;IAE/B,MAAM,UAAU,GAAG,WAAW,CAAC,CAAC,GAAiB,EAAE,EAAE;QACnD,WAAW,CAAC,CAAC,IAAI,EAAE,EAAE;YACnB,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC;YAC3B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YACxB,OAAO,IAAI,CAAC;QACd,CAAC,CAAC,CAAC;IACL,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,aAAa,GAAG,WAAW,CAAC,CAAC,IAAY,EAAE,EAAE;QACjD,WAAW,CAAC,CAAC,IAAI,EAAE,EAAE;YACnB,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC;YAC3B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAClB,OAAO,IAAI,CAAC;QACd,CAAC,CAAC,CAAC;IACL,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,QAAQ,GAAG,WAAW,CAC1B,CAAC,KAAa,EAAW,EAAE;QACzB,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC;QAEzC,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACpC,MAAM,IAAI,GAAG,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;QACzE,MAAM,IAAI,GAAG,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC;QAE9D,MAAM,GAAG,GAAG,WAAW,CAAC,OAAO,CAAC;QAEhC,oBAAoB;QACpB,IAAI,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAExB,cAAc;QACd,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,KAAK,MAAM,SAAS,IAAI,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC;gBACrC,IAAI,SAAS,CAAC,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;oBACtC,GAAG,GAAG,SAAS,CAAC;oBAChB,MAAM;gBACR,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,GAAG,CAAC,MAAM,CAAC,qBAAqB,IAAI,sCAAsC,CAAC,CAAC;YAC5E,OAAO,IAAI,CAAC;QACd,CAAC;QAED,mDAAmD;QACnD,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACxB,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;YAC1C,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,OAAO,GAAmB;YAC9B,GAAG,GAAG;YACN,UAAU;YACV,aAAa;SACd,CAAC;QAEF,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC3B,OAAO,IAAI,CAAC;IACd,CAAC,EACD,CAAC,GAAG,EAAE,UAAU,EAAE,aAAa,CAAC,CACjC,CAAC;IAEF,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEnE,OAAO;QACL,QAAQ;QACR,QAAQ;QACR,UAAU;QACV,aAAa;KACd,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CompletionPicker — renders a completion dropdown for the TUI.
|
|
3
|
+
*
|
|
4
|
+
* Pure rendering component. Takes CompletionState, renders items in an
|
|
5
|
+
* emerald-themed bordered box with windowed scrolling.
|
|
6
|
+
*/
|
|
7
|
+
import type { CompletionState } from "@agentick/client";
|
|
8
|
+
export interface CompletionPickerProps {
|
|
9
|
+
completion: CompletionState;
|
|
10
|
+
}
|
|
11
|
+
export declare function CompletionPicker({ completion }: CompletionPickerProps): import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
//# sourceMappingURL=CompletionPicker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CompletionPicker.d.ts","sourceRoot":"","sources":["../../src/components/CompletionPicker.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAKxD,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,eAAe,CAAC;CAC7B;AAED,wBAAgB,gBAAgB,CAAC,EAAE,UAAU,EAAE,EAAE,qBAAqB,2CA+DrE"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* CompletionPicker — renders a completion dropdown for the TUI.
|
|
4
|
+
*
|
|
5
|
+
* Pure rendering component. Takes CompletionState, renders items in an
|
|
6
|
+
* emerald-themed bordered box with windowed scrolling.
|
|
7
|
+
*/
|
|
8
|
+
import { Box, Text } from "ink";
|
|
9
|
+
const MAX_VISIBLE = 8;
|
|
10
|
+
const BORDER_COLOR = "#34d399";
|
|
11
|
+
export function CompletionPicker({ completion }) {
|
|
12
|
+
const { items, selectedIndex, loading } = completion;
|
|
13
|
+
if (loading && items.length === 0) {
|
|
14
|
+
return (_jsx(Box, { borderStyle: "single", borderColor: BORDER_COLOR, paddingLeft: 1, paddingRight: 1, children: _jsx(Text, { dimColor: true, children: "Loading..." }) }));
|
|
15
|
+
}
|
|
16
|
+
if (items.length === 0) {
|
|
17
|
+
return (_jsx(Box, { borderStyle: "single", borderColor: BORDER_COLOR, paddingLeft: 1, paddingRight: 1, children: _jsx(Text, { dimColor: true, children: "No matches" }) }));
|
|
18
|
+
}
|
|
19
|
+
// Windowed scrolling — keep selected item visible
|
|
20
|
+
const total = items.length;
|
|
21
|
+
const windowSize = Math.min(total, MAX_VISIBLE);
|
|
22
|
+
let windowStart;
|
|
23
|
+
if (total <= MAX_VISIBLE) {
|
|
24
|
+
windowStart = 0;
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
// Center the selected item in the window
|
|
28
|
+
const half = Math.floor(windowSize / 2);
|
|
29
|
+
windowStart = Math.max(0, Math.min(selectedIndex - half, total - windowSize));
|
|
30
|
+
}
|
|
31
|
+
const windowEnd = windowStart + windowSize;
|
|
32
|
+
const visibleItems = items.slice(windowStart, windowEnd);
|
|
33
|
+
const hasItemsAbove = windowStart > 0;
|
|
34
|
+
const hasItemsBelow = windowEnd < total;
|
|
35
|
+
return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: BORDER_COLOR, paddingLeft: 1, paddingRight: 1, children: [hasItemsAbove && _jsx(Text, { dimColor: true, children: " ..." }), visibleItems.map((item, i) => {
|
|
36
|
+
const actualIndex = windowStart + i;
|
|
37
|
+
const isSelected = actualIndex === selectedIndex;
|
|
38
|
+
return (_jsxs(Box, { flexDirection: "row", gap: 1, children: [_jsx(Text, { inverse: isSelected, bold: isSelected, children: item.label }), item.description && _jsx(Text, { dimColor: true, children: item.description })] }, actualIndex));
|
|
39
|
+
}), hasItemsBelow && _jsx(Text, { dimColor: true, children: " ..." }), loading && _jsx(Text, { dimColor: true, children: " Loading..." })] }));
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=CompletionPicker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CompletionPicker.js","sourceRoot":"","sources":["../../src/components/CompletionPicker.tsx"],"names":[],"mappings":";AAAA;;;;;GAKG;AAEH,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAGhC,MAAM,WAAW,GAAG,CAAC,CAAC;AACtB,MAAM,YAAY,GAAG,SAAS,CAAC;AAM/B,MAAM,UAAU,gBAAgB,CAAC,EAAE,UAAU,EAAyB;IACpE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC;IAErD,IAAI,OAAO,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,OAAO,CACL,KAAC,GAAG,IAAC,WAAW,EAAC,QAAQ,EAAC,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,YAClF,KAAC,IAAI,IAAC,QAAQ,iCAAkB,GAC5B,CACP,CAAC;IACJ,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,CACL,KAAC,GAAG,IAAC,WAAW,EAAC,QAAQ,EAAC,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,YAClF,KAAC,IAAI,IAAC,QAAQ,iCAAkB,GAC5B,CACP,CAAC;IACJ,CAAC;IAED,kDAAkD;IAClD,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC;IAC3B,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;IAChD,IAAI,WAAmB,CAAC;IAExB,IAAI,KAAK,IAAI,WAAW,EAAE,CAAC;QACzB,WAAW,GAAG,CAAC,CAAC;IAClB,CAAC;SAAM,CAAC;QACN,yCAAyC;QACzC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;QACxC,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,aAAa,GAAG,IAAI,EAAE,KAAK,GAAG,UAAU,CAAC,CAAC,CAAC;IAChF,CAAC;IAED,MAAM,SAAS,GAAG,WAAW,GAAG,UAAU,CAAC;IAC3C,MAAM,YAAY,GAAG,KAAK,CAAC,KAAK,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IACzD,MAAM,aAAa,GAAG,WAAW,GAAG,CAAC,CAAC;IACtC,MAAM,aAAa,GAAG,SAAS,GAAG,KAAK,CAAC;IAExC,OAAO,CACL,MAAC,GAAG,IACF,aAAa,EAAC,QAAQ,EACtB,WAAW,EAAC,QAAQ,EACpB,WAAW,EAAE,YAAY,EACzB,WAAW,EAAE,CAAC,EACd,YAAY,EAAE,CAAC,aAEd,aAAa,IAAI,KAAC,IAAI,IAAC,QAAQ,2BAAY,EAC3C,YAAY,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;gBAC5B,MAAM,WAAW,GAAG,WAAW,GAAG,CAAC,CAAC;gBACpC,MAAM,UAAU,GAAG,WAAW,KAAK,aAAa,CAAC;gBAEjD,OAAO,CACL,MAAC,GAAG,IAAmB,aAAa,EAAC,KAAK,EAAC,GAAG,EAAE,CAAC,aAC/C,KAAC,IAAI,IAAC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,YACxC,IAAI,CAAC,KAAK,GACN,EACN,IAAI,CAAC,WAAW,IAAI,KAAC,IAAI,IAAC,QAAQ,kBAAE,IAAI,CAAC,WAAW,GAAQ,KAJrD,WAAW,CAKf,CACP,CAAC;YACJ,CAAC,CAAC,EACD,aAAa,IAAI,KAAC,IAAI,IAAC,QAAQ,2BAAY,EAC3C,OAAO,IAAI,KAAC,IAAI,IAAC,QAAQ,kCAAmB,IACzC,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DiffView — colored diff rendering with line numbers and gutter markers.
|
|
3
|
+
*
|
|
4
|
+
* Parses unified diff output (from jsdiff's createTwoFilesPatch) and renders:
|
|
5
|
+
* - Summary header with add/remove counts
|
|
6
|
+
* - Line numbers in a left gutter
|
|
7
|
+
* - Colored text (green additions, red removals, dim context)
|
|
8
|
+
* - Hunk headers in cyan
|
|
9
|
+
*
|
|
10
|
+
* Uses chalk for ANSI coloring without background colors — background colors
|
|
11
|
+
* create visible gaps between lines in most terminals due to inter-line
|
|
12
|
+
* pixel spacing from the font engine.
|
|
13
|
+
*/
|
|
14
|
+
interface DiffViewProps {
|
|
15
|
+
patch: string;
|
|
16
|
+
filePath?: string;
|
|
17
|
+
maxLines?: number;
|
|
18
|
+
}
|
|
19
|
+
export declare function DiffView({ patch, filePath, maxLines }: DiffViewProps): import("react/jsx-runtime").JSX.Element;
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=DiffView.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DiffView.d.ts","sourceRoot":"","sources":["../../src/components/DiffView.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,UAAU,aAAa;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AA2FD,wBAAgB,QAAQ,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAa,EAAE,EAAE,aAAa,2CAmCzE"}
|