@agentick/tui 0.2.1
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 +167 -0
- package/dist/bin.d.ts +12 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +199 -0
- package/dist/bin.js.map +1 -0
- package/dist/components/ErrorDisplay.d.ts +12 -0
- package/dist/components/ErrorDisplay.d.ts.map +1 -0
- package/dist/components/ErrorDisplay.js +17 -0
- package/dist/components/ErrorDisplay.js.map +1 -0
- package/dist/components/InputBar.d.ts +13 -0
- package/dist/components/InputBar.d.ts.map +1 -0
- package/dist/components/InputBar.js +20 -0
- package/dist/components/InputBar.js.map +1 -0
- package/dist/components/MessageList.d.ts +12 -0
- package/dist/components/MessageList.d.ts.map +1 -0
- package/dist/components/MessageList.js +81 -0
- package/dist/components/MessageList.js.map +1 -0
- package/dist/components/StreamingMessage.d.ts +7 -0
- package/dist/components/StreamingMessage.d.ts.map +1 -0
- package/dist/components/StreamingMessage.js +15 -0
- package/dist/components/StreamingMessage.js.map +1 -0
- package/dist/components/TUIApp.d.ts +18 -0
- package/dist/components/TUIApp.d.ts.map +1 -0
- package/dist/components/TUIApp.js +97 -0
- package/dist/components/TUIApp.js.map +1 -0
- package/dist/components/ToolCallIndicator.d.ts +12 -0
- package/dist/components/ToolCallIndicator.d.ts.map +1 -0
- package/dist/components/ToolCallIndicator.js +49 -0
- package/dist/components/ToolCallIndicator.js.map +1 -0
- package/dist/components/ToolConfirmationPrompt.d.ts +14 -0
- package/dist/components/ToolConfirmationPrompt.d.ts.map +1 -0
- package/dist/components/ToolConfirmationPrompt.js +33 -0
- package/dist/components/ToolConfirmationPrompt.js.map +1 -0
- package/dist/create-tui.d.ts +44 -0
- package/dist/create-tui.d.ts.map +1 -0
- package/dist/create-tui.js +29 -0
- package/dist/create-tui.js.map +1 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +43 -0
- package/dist/index.js.map +1 -0
- package/dist/testing.d.ts +31 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +31 -0
- package/dist/testing.js.map +1 -0
- package/dist/ui/chat.d.ts +18 -0
- package/dist/ui/chat.d.ts.map +1 -0
- package/dist/ui/chat.js +97 -0
- package/dist/ui/chat.js.map +1 -0
- package/dist/ui/index.d.ts +8 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +5 -0
- package/dist/ui/index.js.map +1 -0
- package/package.json +73 -0
- package/src/index.ts +45 -0
package/README.md
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# @agentick/tui
|
|
2
|
+
|
|
3
|
+
Terminal UI for Agentick agents. Uses [Ink](https://github.com/vadimdemedes/ink) (React for CLIs) with `@agentick/react` hooks — same hooks, same streaming, different renderer.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
pnpm add @agentick/tui
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
### Local Agent
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { createApp, Model, Timeline, Section } from "@agentick/core";
|
|
17
|
+
import { openai } from "@agentick/openai";
|
|
18
|
+
import { createTUI } from "@agentick/tui";
|
|
19
|
+
|
|
20
|
+
function MyAgent() {
|
|
21
|
+
return (
|
|
22
|
+
<>
|
|
23
|
+
<Model model={openai({ model: "gpt-4o-mini" })} />
|
|
24
|
+
<Section id="system" audience="model">
|
|
25
|
+
You are a helpful assistant.
|
|
26
|
+
</Section>
|
|
27
|
+
<Timeline />
|
|
28
|
+
</>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const app = createApp(MyAgent);
|
|
33
|
+
createTUI({ app }).start();
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Remote Agent
|
|
37
|
+
|
|
38
|
+
Connect to an Agentick gateway over HTTP/SSE:
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
import { createTUI } from "@agentick/tui";
|
|
42
|
+
|
|
43
|
+
createTUI({ url: "https://my-agent.fly.dev/api" }).start();
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Custom UI
|
|
47
|
+
|
|
48
|
+
Replace the default chat interface with your own Ink component:
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
import { createTUI } from "@agentick/tui";
|
|
52
|
+
import { MyDashboard } from "./dashboard.js";
|
|
53
|
+
|
|
54
|
+
createTUI({ app, ui: MyDashboard }).start();
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## CLI
|
|
58
|
+
|
|
59
|
+
The `agentick-tui` binary launches a TUI from the command line.
|
|
60
|
+
|
|
61
|
+
```sh
|
|
62
|
+
# Local app (file exporting an App instance)
|
|
63
|
+
agentick-tui --app ./my-app.ts
|
|
64
|
+
|
|
65
|
+
# Remote gateway
|
|
66
|
+
agentick-tui --url https://my-agent.fly.dev/api
|
|
67
|
+
|
|
68
|
+
# With session ID
|
|
69
|
+
agentick-tui --url https://my-agent.fly.dev/api --session my-session
|
|
70
|
+
|
|
71
|
+
# Custom terminal UI
|
|
72
|
+
agentick-tui --app ./my-app.ts --ui ./dashboard.tsx
|
|
73
|
+
agentick-tui --app ./my-app.ts --ui ./dashboard.tsx --ui-export MonitorDashboard
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**Dev (from repo root):**
|
|
77
|
+
|
|
78
|
+
```sh
|
|
79
|
+
pnpm tui -- --url http://localhost:3000/api --session default
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### CLI Options
|
|
83
|
+
|
|
84
|
+
| Flag | Description |
|
|
85
|
+
| -------------------- | -------------------------------------------------------- |
|
|
86
|
+
| `--app <path>` | Path to a file exporting an `App` instance |
|
|
87
|
+
| `--export <name>` | Named export to use (default: auto-detect) |
|
|
88
|
+
| `--url <url>` | Remote gateway URL (include the mount path, e.g. `/api`) |
|
|
89
|
+
| `--session <id>` | Session ID (default: `"main"`) |
|
|
90
|
+
| `--ui <name\|path>` | Built-in UI name or path to custom UI file |
|
|
91
|
+
| `--ui-export <name>` | Named export from custom UI file |
|
|
92
|
+
|
|
93
|
+
### Built-in UIs
|
|
94
|
+
|
|
95
|
+
| Name | Description |
|
|
96
|
+
| ------ | ------------------------------------------ |
|
|
97
|
+
| `chat` | Default conversational interface (default) |
|
|
98
|
+
|
|
99
|
+
## API
|
|
100
|
+
|
|
101
|
+
### createTUI(options)
|
|
102
|
+
|
|
103
|
+
Returns `{ start(): Promise<void> }`.
|
|
104
|
+
|
|
105
|
+
**Local options:**
|
|
106
|
+
|
|
107
|
+
| Option | Type | Description |
|
|
108
|
+
| ----------- | -------------- | ------------------------------------- |
|
|
109
|
+
| `app` | `App` | Agentick App instance |
|
|
110
|
+
| `sessionId` | `string` | Session ID (default: `"main"`) |
|
|
111
|
+
| `ui` | `TUIComponent` | Custom UI component (default: `Chat`) |
|
|
112
|
+
|
|
113
|
+
**Remote options:**
|
|
114
|
+
|
|
115
|
+
| Option | Type | Description |
|
|
116
|
+
| ----------- | -------------- | ------------------------------------- |
|
|
117
|
+
| `url` | `string` | Gateway URL |
|
|
118
|
+
| `token` | `string` | Auth token |
|
|
119
|
+
| `sessionId` | `string` | Session ID (default: `"main"`) |
|
|
120
|
+
| `ui` | `TUIComponent` | Custom UI component (default: `Chat`) |
|
|
121
|
+
|
|
122
|
+
### TUIComponent
|
|
123
|
+
|
|
124
|
+
Any React component that accepts `{ sessionId: string }`:
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
import type { TUIComponent } from "@agentick/tui";
|
|
128
|
+
|
|
129
|
+
const MyUI: TUIComponent = ({ sessionId }) => {
|
|
130
|
+
const { messages, status } = useSession(sessionId);
|
|
131
|
+
// ... Ink components
|
|
132
|
+
};
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Components
|
|
136
|
+
|
|
137
|
+
All components are exported for building custom UIs.
|
|
138
|
+
|
|
139
|
+
| Component | Purpose |
|
|
140
|
+
| ------------------------ | ------------------------------------------------- |
|
|
141
|
+
| `Chat` | Default chat UI (built-in) |
|
|
142
|
+
| `MessageList` | Completed messages (Ink `<Static>`) |
|
|
143
|
+
| `StreamingMessage` | Live streaming response with cursor |
|
|
144
|
+
| `ToolCallIndicator` | Spinner during tool execution |
|
|
145
|
+
| `ToolConfirmationPrompt` | Y/N/A prompt for tools with `requireConfirmation` |
|
|
146
|
+
| `ErrorDisplay` | Error box with optional dismiss |
|
|
147
|
+
| `InputBar` | Text input, disabled while streaming |
|
|
148
|
+
|
|
149
|
+
## Architecture
|
|
150
|
+
|
|
151
|
+
The TUI reuses `@agentick/react` hooks unchanged. Ink is React for terminals, so the same `useSession`, `useStreamingText`, and `useEvents` hooks work in both browser and terminal.
|
|
152
|
+
|
|
153
|
+
For local agents, `createLocalTransport` (from `@agentick/core`) bridges the in-process `App` to the `ClientTransport` interface. The TUI components don't know or care about local vs remote.
|
|
154
|
+
|
|
155
|
+
```
|
|
156
|
+
createTUI({ app })
|
|
157
|
+
→ createLocalTransport(app) → ClientTransport
|
|
158
|
+
→ createClient({ transport })
|
|
159
|
+
→ AgentickProvider + Ink components
|
|
160
|
+
→ useSession, useStreamingText, useEvents (same as web)
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
For remote agents, the client uses HTTP/SSE to connect to the gateway. An `eventsource` polyfill is included for Node.js environments where `globalThis.EventSource` is not available.
|
|
164
|
+
|
|
165
|
+
### Ink + React 19
|
|
166
|
+
|
|
167
|
+
Ink 5 bundles `react-reconciler@0.29`, which is incompatible with React 19. The monorepo applies a patch (`patches/ink@5.2.1.patch`) and overrides the reconciler to `0.31.0`. See `patches/README.md` for details.
|
package/dist/bin.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* CLI binary for launching the Agentick TUI.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* agentick-tui --app path/to/app.ts
|
|
7
|
+
* agentick-tui --app path/to/app.ts --export myApp
|
|
8
|
+
* agentick-tui --app path/to/app.ts --ui ./dashboard.tsx --ui-export MonitorDashboard
|
|
9
|
+
* agentick-tui --url https://my-app.fly.dev/api --session my-session
|
|
10
|
+
*/
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=bin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AAEA;;;;;;;;GAQG"}
|
package/dist/bin.js
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* CLI binary for launching the Agentick TUI.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* agentick-tui --app path/to/app.ts
|
|
7
|
+
* agentick-tui --app path/to/app.ts --export myApp
|
|
8
|
+
* agentick-tui --app path/to/app.ts --ui ./dashboard.tsx --ui-export MonitorDashboard
|
|
9
|
+
* agentick-tui --url https://my-app.fly.dev/api --session my-session
|
|
10
|
+
*/
|
|
11
|
+
import * as path from "node:path";
|
|
12
|
+
import { createTUI } from "./create-tui.js";
|
|
13
|
+
import { builtinUIs } from "./ui/index.js";
|
|
14
|
+
function parseArgs(argv) {
|
|
15
|
+
const args = {};
|
|
16
|
+
const positional = argv.slice(2);
|
|
17
|
+
for (let i = 0; i < positional.length; i++) {
|
|
18
|
+
const arg = positional[i];
|
|
19
|
+
const next = positional[i + 1];
|
|
20
|
+
switch (arg) {
|
|
21
|
+
case "--app":
|
|
22
|
+
args.app = next;
|
|
23
|
+
i++;
|
|
24
|
+
break;
|
|
25
|
+
case "--export":
|
|
26
|
+
args.export = next;
|
|
27
|
+
i++;
|
|
28
|
+
break;
|
|
29
|
+
case "--url":
|
|
30
|
+
args.url = next;
|
|
31
|
+
i++;
|
|
32
|
+
break;
|
|
33
|
+
case "--session":
|
|
34
|
+
args.session = next;
|
|
35
|
+
i++;
|
|
36
|
+
break;
|
|
37
|
+
case "--ui":
|
|
38
|
+
args.ui = next;
|
|
39
|
+
i++;
|
|
40
|
+
break;
|
|
41
|
+
case "--ui-export":
|
|
42
|
+
args.uiExport = next;
|
|
43
|
+
i++;
|
|
44
|
+
break;
|
|
45
|
+
case "--help":
|
|
46
|
+
case "-h":
|
|
47
|
+
args.help = true;
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return args;
|
|
52
|
+
}
|
|
53
|
+
function printUsage() {
|
|
54
|
+
console.log(`
|
|
55
|
+
agentick-tui — Launch an Agentick app in the terminal
|
|
56
|
+
|
|
57
|
+
Usage:
|
|
58
|
+
agentick-tui --app <path> Load app from a local file
|
|
59
|
+
agentick-tui --url <url> Connect to a remote app
|
|
60
|
+
|
|
61
|
+
Options:
|
|
62
|
+
--app <path> Path to a file exporting an App instance
|
|
63
|
+
--export <name> Named export to use (default: auto-detect)
|
|
64
|
+
--url <url> Remote gateway URL
|
|
65
|
+
--session <id> Session ID (default: "main")
|
|
66
|
+
--ui <name|path> Built-in UI name or path to custom UI file (default: "chat")
|
|
67
|
+
--ui-export <name> Named export from custom UI file (default: auto-detect)
|
|
68
|
+
--help, -h Show this help
|
|
69
|
+
|
|
70
|
+
Built-in UIs:
|
|
71
|
+
chat Default conversational interface
|
|
72
|
+
`.trim());
|
|
73
|
+
}
|
|
74
|
+
// ============================================================================
|
|
75
|
+
// Type guards
|
|
76
|
+
// ============================================================================
|
|
77
|
+
function isApp(value) {
|
|
78
|
+
return (typeof value === "object" &&
|
|
79
|
+
value !== null &&
|
|
80
|
+
"send" in value &&
|
|
81
|
+
typeof value.send === "function");
|
|
82
|
+
}
|
|
83
|
+
function isComponent(value) {
|
|
84
|
+
return typeof value === "function";
|
|
85
|
+
}
|
|
86
|
+
// ============================================================================
|
|
87
|
+
// Module helpers
|
|
88
|
+
// ============================================================================
|
|
89
|
+
/** Load a module by file path, exit on failure. */
|
|
90
|
+
async function loadModule(filePath) {
|
|
91
|
+
const resolved = path.resolve(process.cwd(), filePath);
|
|
92
|
+
try {
|
|
93
|
+
return await import(resolved);
|
|
94
|
+
}
|
|
95
|
+
catch (err) {
|
|
96
|
+
console.error(`Error loading module from ${resolved}:`);
|
|
97
|
+
console.error(err instanceof Error ? err.message : err);
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Scan a module for an export matching a predicate.
|
|
103
|
+
* Tries well-known names first, then scans all exports.
|
|
104
|
+
*/
|
|
105
|
+
function findExport(mod, check, wellKnownNames) {
|
|
106
|
+
for (const name of wellKnownNames) {
|
|
107
|
+
const exported = mod[name];
|
|
108
|
+
if (check(exported))
|
|
109
|
+
return exported;
|
|
110
|
+
}
|
|
111
|
+
for (const value of Object.values(mod)) {
|
|
112
|
+
if (check(value))
|
|
113
|
+
return value;
|
|
114
|
+
}
|
|
115
|
+
return undefined;
|
|
116
|
+
}
|
|
117
|
+
// ============================================================================
|
|
118
|
+
// App resolution
|
|
119
|
+
// ============================================================================
|
|
120
|
+
/** Find an App instance in a module. */
|
|
121
|
+
function findApp(mod, exportName) {
|
|
122
|
+
if (exportName) {
|
|
123
|
+
const exported = mod[exportName];
|
|
124
|
+
if (exported === undefined) {
|
|
125
|
+
throw new Error(`Export "${exportName}" not found in module`);
|
|
126
|
+
}
|
|
127
|
+
if (!isApp(exported)) {
|
|
128
|
+
throw new Error(`Export "${exportName}" does not appear to be an App (no .send method)`);
|
|
129
|
+
}
|
|
130
|
+
return exported;
|
|
131
|
+
}
|
|
132
|
+
const app = findExport(mod, isApp, ["app", "default"]);
|
|
133
|
+
if (app)
|
|
134
|
+
return app;
|
|
135
|
+
throw new Error("No App export found. Ensure your module exports an object with a .send() method, or use --export <name>.");
|
|
136
|
+
}
|
|
137
|
+
// ============================================================================
|
|
138
|
+
// UI resolution
|
|
139
|
+
// ============================================================================
|
|
140
|
+
/** Find a TUI component in a module. */
|
|
141
|
+
function findUIComponent(mod, exportName) {
|
|
142
|
+
if (exportName) {
|
|
143
|
+
const exported = mod[exportName];
|
|
144
|
+
if (exported === undefined) {
|
|
145
|
+
throw new Error(`Export "${exportName}" not found in UI module`);
|
|
146
|
+
}
|
|
147
|
+
if (!isComponent(exported)) {
|
|
148
|
+
throw new Error(`Export "${exportName}" is not a function component`);
|
|
149
|
+
}
|
|
150
|
+
return exported;
|
|
151
|
+
}
|
|
152
|
+
const component = findExport(mod, isComponent, ["default", "TUI", "UI"]);
|
|
153
|
+
if (component)
|
|
154
|
+
return component;
|
|
155
|
+
throw new Error("No component export found. Export a React component, or use --ui-export <name>.");
|
|
156
|
+
}
|
|
157
|
+
/** Resolve --ui flag: built-in name, file path, or undefined (use default). */
|
|
158
|
+
async function resolveUI(uiArg, uiExport) {
|
|
159
|
+
if (!uiArg)
|
|
160
|
+
return undefined;
|
|
161
|
+
if (uiArg in builtinUIs) {
|
|
162
|
+
return builtinUIs[uiArg];
|
|
163
|
+
}
|
|
164
|
+
const mod = await loadModule(uiArg);
|
|
165
|
+
return findUIComponent(mod, uiExport);
|
|
166
|
+
}
|
|
167
|
+
// ============================================================================
|
|
168
|
+
// Main
|
|
169
|
+
// ============================================================================
|
|
170
|
+
async function main() {
|
|
171
|
+
const args = parseArgs(process.argv);
|
|
172
|
+
if (args.help) {
|
|
173
|
+
printUsage();
|
|
174
|
+
process.exit(0);
|
|
175
|
+
}
|
|
176
|
+
if (!args.app && !args.url) {
|
|
177
|
+
console.error("Error: Provide --app <path> or --url <url>\n");
|
|
178
|
+
printUsage();
|
|
179
|
+
process.exit(1);
|
|
180
|
+
}
|
|
181
|
+
if (args.app && args.url) {
|
|
182
|
+
console.error("Error: --app and --url are mutually exclusive\n");
|
|
183
|
+
printUsage();
|
|
184
|
+
process.exit(1);
|
|
185
|
+
}
|
|
186
|
+
const ui = await resolveUI(args.ui, args.uiExport);
|
|
187
|
+
if (args.url) {
|
|
188
|
+
await createTUI({ url: args.url, sessionId: args.session, ui }).start();
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
const mod = await loadModule(args.app);
|
|
192
|
+
const app = findApp(mod, args.export);
|
|
193
|
+
await createTUI({ app: app, sessionId: args.session, ui }).start();
|
|
194
|
+
}
|
|
195
|
+
main().catch((err) => {
|
|
196
|
+
console.error("Fatal error:", err);
|
|
197
|
+
process.exit(1);
|
|
198
|
+
});
|
|
199
|
+
//# sourceMappingURL=bin.js.map
|
package/dist/bin.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ErrorDisplay — shows errors that occur during execution.
|
|
3
|
+
*
|
|
4
|
+
* Red bordered box with error message. Optional dismiss handler.
|
|
5
|
+
*/
|
|
6
|
+
interface ErrorDisplayProps {
|
|
7
|
+
error: Error | string | null;
|
|
8
|
+
onDismiss?: () => void;
|
|
9
|
+
}
|
|
10
|
+
export declare function ErrorDisplay({ error, onDismiss }: ErrorDisplayProps): import("react/jsx-runtime").JSX.Element | null;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=ErrorDisplay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ErrorDisplay.d.ts","sourceRoot":"","sources":["../../src/components/ErrorDisplay.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,UAAU,iBAAiB;IACzB,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,IAAI,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AAED,wBAAgB,YAAY,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,iBAAiB,kDAiCnE"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* ErrorDisplay — shows errors that occur during execution.
|
|
4
|
+
*
|
|
5
|
+
* Red bordered box with error message. Optional dismiss handler.
|
|
6
|
+
*/
|
|
7
|
+
import { Box, Text, useInput } from "ink";
|
|
8
|
+
export function ErrorDisplay({ error, onDismiss }) {
|
|
9
|
+
useInput(() => {
|
|
10
|
+
onDismiss?.();
|
|
11
|
+
}, { isActive: !!onDismiss && !!error });
|
|
12
|
+
if (!error)
|
|
13
|
+
return null;
|
|
14
|
+
const message = error instanceof Error ? error.message : error;
|
|
15
|
+
return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "red", paddingX: 1, marginTop: 1, children: [_jsx(Text, { color: "red", bold: true, children: "Error" }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { children: message }) }), onDismiss && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "gray", children: "Press any key to dismiss" }) }))] }));
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=ErrorDisplay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ErrorDisplay.js","sourceRoot":"","sources":["../../src/components/ErrorDisplay.tsx"],"names":[],"mappings":";AAAA;;;;GAIG;AAEH,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAO1C,MAAM,UAAU,YAAY,CAAC,EAAE,KAAK,EAAE,SAAS,EAAqB;IAClE,QAAQ,CACN,GAAG,EAAE;QACH,SAAS,EAAE,EAAE,CAAC;IAChB,CAAC,EACD,EAAE,QAAQ,EAAE,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,KAAK,EAAE,CACrC,CAAC;IAEF,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IAExB,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;IAE/D,OAAO,CACL,MAAC,GAAG,IACF,aAAa,EAAC,QAAQ,EACtB,WAAW,EAAC,OAAO,EACnB,WAAW,EAAC,KAAK,EACjB,QAAQ,EAAE,CAAC,EACX,SAAS,EAAE,CAAC,aAEZ,KAAC,IAAI,IAAC,KAAK,EAAC,KAAK,EAAC,IAAI,4BAEf,EACP,KAAC,GAAG,IAAC,SAAS,EAAE,CAAC,YACf,KAAC,IAAI,cAAE,OAAO,GAAQ,GAClB,EACL,SAAS,IAAI,CACZ,KAAC,GAAG,IAAC,SAAS,EAAE,CAAC,YACf,KAAC,IAAI,IAAC,KAAK,EAAC,MAAM,yCAAgC,GAC9C,CACP,IACG,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* InputBar — user text input for the TUI.
|
|
3
|
+
*
|
|
4
|
+
* Uses ink-text-input. Enter submits, disabled while streaming.
|
|
5
|
+
*/
|
|
6
|
+
interface InputBarProps {
|
|
7
|
+
onSubmit: (text: string) => void;
|
|
8
|
+
isDisabled?: boolean;
|
|
9
|
+
placeholder?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function InputBar({ onSubmit, isDisabled, placeholder }: InputBarProps): import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=InputBar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InputBar.d.ts","sourceRoot":"","sources":["../../src/components/InputBar.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,UAAU,aAAa;IACrB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,QAAQ,CAAC,EAAE,QAAQ,EAAE,UAAkB,EAAE,WAAW,EAAE,EAAE,aAAa,2CA0BpF"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* InputBar — user text input for the TUI.
|
|
4
|
+
*
|
|
5
|
+
* Uses ink-text-input. Enter submits, disabled while streaming.
|
|
6
|
+
*/
|
|
7
|
+
import { useState, useCallback } from "react";
|
|
8
|
+
import { Box, Text } from "ink";
|
|
9
|
+
import TextInput from "ink-text-input";
|
|
10
|
+
export function InputBar({ onSubmit, isDisabled = false, placeholder }) {
|
|
11
|
+
const [value, setValue] = useState("");
|
|
12
|
+
const handleSubmit = useCallback((text) => {
|
|
13
|
+
if (!text.trim() || isDisabled)
|
|
14
|
+
return;
|
|
15
|
+
onSubmit(text.trim());
|
|
16
|
+
setValue("");
|
|
17
|
+
}, [onSubmit, isDisabled]);
|
|
18
|
+
return (_jsxs(Box, { borderStyle: "single", borderColor: isDisabled ? "gray" : "cyan", paddingLeft: 1, children: [_jsx(Text, { color: isDisabled ? "gray" : "green", bold: true, children: "› " }), _jsx(TextInput, { value: value, onChange: setValue, onSubmit: handleSubmit, focus: !isDisabled, placeholder: placeholder ?? (isDisabled ? "Waiting for response..." : "Type a message...") })] }));
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=InputBar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InputBar.js","sourceRoot":"","sources":["../../src/components/InputBar.tsx"],"names":[],"mappings":";AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAC9C,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAChC,OAAO,SAAS,MAAM,gBAAgB,CAAC;AAQvC,MAAM,UAAU,QAAQ,CAAC,EAAE,QAAQ,EAAE,UAAU,GAAG,KAAK,EAAE,WAAW,EAAiB;IACnF,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IAEvC,MAAM,YAAY,GAAG,WAAW,CAC9B,CAAC,IAAY,EAAE,EAAE;QACf,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,UAAU;YAAE,OAAO;QACvC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACtB,QAAQ,CAAC,EAAE,CAAC,CAAC;IACf,CAAC,EACD,CAAC,QAAQ,EAAE,UAAU,CAAC,CACvB,CAAC;IAEF,OAAO,CACL,MAAC,GAAG,IAAC,WAAW,EAAC,QAAQ,EAAC,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,aACjF,KAAC,IAAI,IAAC,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,IAAI,kBAC7C,IAAI,GACA,EACP,KAAC,SAAS,IACR,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,YAAY,EACtB,KAAK,EAAE,CAAC,UAAU,EAClB,WAAW,EAAE,WAAW,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,mBAAmB,CAAC,GAC1F,IACE,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MessageList — displays completed conversation messages.
|
|
3
|
+
*
|
|
4
|
+
* Uses Ink's <Static> for messages that won't re-render (performance critical).
|
|
5
|
+
* Listens for execution_end events which contain `output.timeline` with all entries.
|
|
6
|
+
*/
|
|
7
|
+
interface MessageListProps {
|
|
8
|
+
sessionId?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function MessageList({ sessionId }: MessageListProps): import("react/jsx-runtime").JSX.Element | null;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=MessageList.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../src/components/MessageList.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AA6CH,UAAU,gBAAgB;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,WAAW,CAAC,EAAE,SAAS,EAAE,EAAE,gBAAgB,kDAwD1D"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* MessageList — displays completed conversation messages.
|
|
4
|
+
*
|
|
5
|
+
* Uses Ink's <Static> for messages that won't re-render (performance critical).
|
|
6
|
+
* Listens for execution_end events which contain `output.timeline` with all entries.
|
|
7
|
+
*/
|
|
8
|
+
import { useState, useEffect, useCallback } from "react";
|
|
9
|
+
import { Static, Box, Text } from "ink";
|
|
10
|
+
import { useEvents } from "@agentick/react";
|
|
11
|
+
function renderContent(content) {
|
|
12
|
+
if (typeof content === "string")
|
|
13
|
+
return content;
|
|
14
|
+
return content
|
|
15
|
+
.map((block) => {
|
|
16
|
+
if (block.type === "text")
|
|
17
|
+
return block.text;
|
|
18
|
+
if (block.type === "tool_use")
|
|
19
|
+
return `[tool: ${block.name}]`;
|
|
20
|
+
if (block.type === "tool_result") {
|
|
21
|
+
const resultContent = Array.isArray(block.content)
|
|
22
|
+
? block.content.map((c) => (c.type === "text" ? c.text : `[${c.type}]`)).join("")
|
|
23
|
+
: String(block.content ?? "");
|
|
24
|
+
return `[result: ${resultContent.slice(0, 100)}${resultContent.length > 100 ? "…" : ""}]`;
|
|
25
|
+
}
|
|
26
|
+
return `[${block.type}]`;
|
|
27
|
+
})
|
|
28
|
+
.join("");
|
|
29
|
+
}
|
|
30
|
+
function roleColor(role) {
|
|
31
|
+
switch (role) {
|
|
32
|
+
case "user":
|
|
33
|
+
return "blue";
|
|
34
|
+
case "assistant":
|
|
35
|
+
return "magenta";
|
|
36
|
+
case "system":
|
|
37
|
+
return "gray";
|
|
38
|
+
case "tool_result":
|
|
39
|
+
return "yellow";
|
|
40
|
+
default:
|
|
41
|
+
return "white";
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
export function MessageList({ sessionId }) {
|
|
45
|
+
const [messages, setMessages] = useState([]);
|
|
46
|
+
const { event } = useEvents({
|
|
47
|
+
sessionId,
|
|
48
|
+
filter: ["execution_end"],
|
|
49
|
+
});
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
if (!event || event.type !== "execution_end")
|
|
52
|
+
return;
|
|
53
|
+
// execution_end.output is the COMInput which has a timeline array
|
|
54
|
+
// Each entry has { kind: "message", message: Message } structure
|
|
55
|
+
const execEnd = event;
|
|
56
|
+
const timeline = execEnd.output?.timeline;
|
|
57
|
+
if (!Array.isArray(timeline))
|
|
58
|
+
return;
|
|
59
|
+
const newMessages = timeline
|
|
60
|
+
.filter((entry) => entry.kind === "message" && entry.message)
|
|
61
|
+
.map((entry, i) => {
|
|
62
|
+
const msg = entry.message;
|
|
63
|
+
return {
|
|
64
|
+
id: msg.id ?? `msg-${i}-${Date.now()}`,
|
|
65
|
+
role: msg.role,
|
|
66
|
+
text: renderContent(msg.content),
|
|
67
|
+
};
|
|
68
|
+
});
|
|
69
|
+
setMessages(newMessages);
|
|
70
|
+
}, [event]);
|
|
71
|
+
const renderMessage = useCallback((msg) => {
|
|
72
|
+
// Skip tool_result entries in the message list for cleaner output
|
|
73
|
+
if (msg.role === "tool_result")
|
|
74
|
+
return null;
|
|
75
|
+
return (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsxs(Text, { color: roleColor(msg.role), bold: true, children: [msg.role, ":"] }), _jsx(Box, { marginLeft: 2, children: _jsx(Text, { wrap: "wrap", children: msg.text }) })] }, msg.id));
|
|
76
|
+
}, []);
|
|
77
|
+
if (messages.length === 0)
|
|
78
|
+
return null;
|
|
79
|
+
return (_jsx(Static, { items: messages, children: renderMessage }));
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=MessageList.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MessageList.js","sourceRoot":"","sources":["../../src/components/MessageList.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StreamingMessage — shows the live model response while streaming.
|
|
3
|
+
*
|
|
4
|
+
* Uses useStreamingText() from @agentick/react.
|
|
5
|
+
*/
|
|
6
|
+
export declare function StreamingMessage(): import("react/jsx-runtime").JSX.Element | null;
|
|
7
|
+
//# sourceMappingURL=StreamingMessage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StreamingMessage.d.ts","sourceRoot":"","sources":["../../src/components/StreamingMessage.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,wBAAgB,gBAAgB,mDAkB/B"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* StreamingMessage — shows the live model response while streaming.
|
|
4
|
+
*
|
|
5
|
+
* Uses useStreamingText() from @agentick/react.
|
|
6
|
+
*/
|
|
7
|
+
import { Box, Text } from "ink";
|
|
8
|
+
import { useStreamingText } from "@agentick/react";
|
|
9
|
+
export function StreamingMessage() {
|
|
10
|
+
const { text, isStreaming } = useStreamingText();
|
|
11
|
+
if (!isStreaming && !text)
|
|
12
|
+
return null;
|
|
13
|
+
return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { color: "magenta", bold: true, children: "assistant:" }), _jsx(Box, { marginLeft: 2, children: _jsxs(Text, { children: [text, isStreaming ? _jsx(Text, { color: "cyan", children: "\u258A" }) : null] }) })] }));
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=StreamingMessage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StreamingMessage.js","sourceRoot":"","sources":["../../src/components/StreamingMessage.tsx"],"names":[],"mappings":";AAAA;;;;GAIG;AAEH,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAChC,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnD,MAAM,UAAU,gBAAgB;IAC9B,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,gBAAgB,EAAE,CAAC;IAEjD,IAAI,CAAC,WAAW,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IAEvC,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,SAAS,EAAE,CAAC,aACtC,KAAC,IAAI,IAAC,KAAK,EAAC,SAAS,EAAC,IAAI,iCAEnB,EACP,KAAC,GAAG,IAAC,UAAU,EAAE,CAAC,YAChB,MAAC,IAAI,eACF,IAAI,EACJ,WAAW,CAAC,CAAC,CAAC,KAAC,IAAI,IAAC,KAAK,EAAC,MAAM,uBAAS,CAAC,CAAC,CAAC,IAAI,IAC5C,GACH,IACF,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TUIApp — top-level TUI layout.
|
|
3
|
+
*
|
|
4
|
+
* Orchestrates the conversation: message history, streaming response,
|
|
5
|
+
* tool call indicators, tool confirmation prompts, error display, and user input.
|
|
6
|
+
*
|
|
7
|
+
* State machine: idle → streaming → (confirming_tool → streaming) → idle
|
|
8
|
+
* Ctrl+C behavior depends on state:
|
|
9
|
+
* - idle: exit the process
|
|
10
|
+
* - streaming: abort current execution
|
|
11
|
+
* - confirming_tool: reject tool, return to streaming
|
|
12
|
+
*/
|
|
13
|
+
interface TUIAppProps {
|
|
14
|
+
sessionId: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function TUIApp({ sessionId }: TUIAppProps): import("react/jsx-runtime").JSX.Element;
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=TUIApp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TUIApp.d.ts","sourceRoot":"","sources":["../../src/components/TUIApp.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAaH,UAAU,WAAW;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AASD,wBAAgB,MAAM,CAAC,EAAE,SAAS,EAAE,EAAE,WAAW,2CAkHhD"}
|