@a5c-ai/agent-mux-tui 0.3.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 (58) hide show
  1. package/README.md +71 -0
  2. package/dist/app.d.ts +9 -0
  3. package/dist/app.d.ts.map +1 -0
  4. package/dist/app.js +97 -0
  5. package/dist/app.js.map +1 -0
  6. package/dist/bin/amux-tui.d.ts +3 -0
  7. package/dist/bin/amux-tui.d.ts.map +1 -0
  8. package/dist/bin/amux-tui.js +8 -0
  9. package/dist/bin/amux-tui.js.map +1 -0
  10. package/dist/event-stream.d.ts +14 -0
  11. package/dist/event-stream.d.ts.map +1 -0
  12. package/dist/event-stream.js +34 -0
  13. package/dist/event-stream.js.map +1 -0
  14. package/dist/index.d.ts +10 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +24 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/plugin.d.ts +57 -0
  19. package/dist/plugin.d.ts.map +1 -0
  20. package/dist/plugin.js +4 -0
  21. package/dist/plugin.js.map +1 -0
  22. package/dist/plugins/chat-view.d.ts +9 -0
  23. package/dist/plugins/chat-view.d.ts.map +1 -0
  24. package/dist/plugins/chat-view.js +35 -0
  25. package/dist/plugins/chat-view.js.map +1 -0
  26. package/dist/plugins/cost.d.ts +3 -0
  27. package/dist/plugins/cost.d.ts.map +1 -0
  28. package/dist/plugins/cost.js +16 -0
  29. package/dist/plugins/cost.js.map +1 -0
  30. package/dist/plugins/diff.d.ts +7 -0
  31. package/dist/plugins/diff.d.ts.map +1 -0
  32. package/dist/plugins/diff.js +42 -0
  33. package/dist/plugins/diff.js.map +1 -0
  34. package/dist/plugins/fallback.d.ts +7 -0
  35. package/dist/plugins/fallback.d.ts.map +1 -0
  36. package/dist/plugins/fallback.js +17 -0
  37. package/dist/plugins/fallback.js.map +1 -0
  38. package/dist/plugins/sessions-view.d.ts +3 -0
  39. package/dist/plugins/sessions-view.d.ts.map +1 -0
  40. package/dist/plugins/sessions-view.js +49 -0
  41. package/dist/plugins/sessions-view.js.map +1 -0
  42. package/dist/plugins/text-delta.d.ts +3 -0
  43. package/dist/plugins/text-delta.d.ts.map +1 -0
  44. package/dist/plugins/text-delta.js +19 -0
  45. package/dist/plugins/text-delta.js.map +1 -0
  46. package/dist/plugins/tool-call.d.ts +3 -0
  47. package/dist/plugins/tool-call.d.ts.map +1 -0
  48. package/dist/plugins/tool-call.js +24 -0
  49. package/dist/plugins/tool-call.js.map +1 -0
  50. package/dist/prompt-input.d.ts +7 -0
  51. package/dist/prompt-input.d.ts.map +1 -0
  52. package/dist/prompt-input.js +25 -0
  53. package/dist/prompt-input.js.map +1 -0
  54. package/dist/registry.d.ts +13 -0
  55. package/dist/registry.d.ts.map +1 -0
  56. package/dist/registry.js +26 -0
  57. package/dist/registry.js.map +1 -0
  58. package/package.json +71 -0
package/README.md ADDED
@@ -0,0 +1,71 @@
1
+ # @a5c-ai/agent-mux-tui
2
+
3
+ Ink-based TUI for agent-mux with a plugin-first architecture. Almost everything
4
+ (message renderers, tool-call cards, diff views, session manager, chat) ships
5
+ as a plugin. The host package only provides the Ink process, view router, and
6
+ the SDK-injected `TuiContext`.
7
+
8
+ ## Install
9
+
10
+ ```bash
11
+ npm i -g @a5c-ai/agent-mux-tui
12
+ amux-tui
13
+ ```
14
+
15
+ ## Writing a plugin
16
+
17
+ ```ts
18
+ import { definePlugin } from '@a5c-ai/agent-mux-tui/plugin';
19
+ import { Text } from 'ink';
20
+ import React from 'react';
21
+
22
+ export default definePlugin({
23
+ name: 'my-error-renderer',
24
+ register(ctx) {
25
+ ctx.registerEventRenderer({
26
+ id: 'error',
27
+ match: (ev) => ev.type === 'error',
28
+ component: ({ event }) =>
29
+ event.type === 'error' ? <Text color="red">{event.message}</Text> : null,
30
+ });
31
+ },
32
+ });
33
+ ```
34
+
35
+ Pass your plugins to `App`:
36
+
37
+ ```tsx
38
+ import { render } from 'ink';
39
+ import { App, builtinPlugins } from '@a5c-ai/agent-mux-tui';
40
+ import myPlugin from './my-plugin.js';
41
+
42
+ render(<App client={client} plugins={[...builtinPlugins, myPlugin]} />);
43
+ ```
44
+
45
+ ## Extension points
46
+
47
+ - `registerView` — top-level tab in the TUI (chat, sessions, config, …)
48
+ - `registerEventRenderer` — per-`AgentEvent` display component. The renderer
49
+ with `id: 'fallback'` is reserved for the built-in dim one-liner that
50
+ handles any unrecognized event type; other renderers take priority.
51
+ - `registerCommand` — global hotkey command
52
+ - `registerPromptHandler` — overrides the default `p` prompt dispatch. If any
53
+ plugin registers a prompt handler, it receives the prompt instead of
54
+ `client.run({ agent: defaultAgent, prompt })`.
55
+
56
+ All extension points get an injected `TuiContext` with:
57
+ - `client: AgentMuxClient` — the SDK client instance
58
+ - `eventStream: EventStream` — shared pub/sub of `AgentEvent`s. Views
59
+ subscribe to render streaming output; commands can push synthetic events
60
+ via `ctx.emit({ type: 'event', event })`.
61
+
62
+ ## Running a prompt
63
+
64
+ Press `p` to open the prompt input, type your message, and press Enter.
65
+ Events from the resulting `client.run()` are pushed into the shared
66
+ `EventStream` and rendered by `chat-view` in registration-priority order
67
+ (specific renderers before the fallback).
68
+
69
+ The built-in plugins (`text-delta`, `thinking-delta`, `tool-call`,
70
+ `tool-error`, `cost`, `chat-view`, `sessions-view`, `fallback`) are all
71
+ implemented through these same extension points — use them as references.
package/dist/app.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ import type { AgentMuxClient } from '@a5c-ai/agent-mux';
2
+ import type { TuiPlugin } from './plugin.js';
3
+ export interface AppProps {
4
+ client: AgentMuxClient;
5
+ plugins: TuiPlugin[];
6
+ defaultAgent?: string;
7
+ }
8
+ export declare function App({ client, plugins, defaultAgent }: AppProps): import("react/jsx-runtime").JSX.Element;
9
+ //# sourceMappingURL=app.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAc,MAAM,mBAAmB,CAAC;AAEpE,OAAO,KAAK,EAAE,SAAS,EAA+B,MAAM,aAAa,CAAC;AAI1E,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,cAAc,CAAC;IACvB,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAQD,wBAAgB,GAAG,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,YAA4B,EAAE,EAAE,QAAQ,2CAkH9E"}
package/dist/app.js ADDED
@@ -0,0 +1,97 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useMemo, useState } from 'react';
3
+ import { Box, Text, useInput, useApp } from 'ink';
4
+ import { createRegistry, createContext, loadPlugins } from './registry.js';
5
+ import { EventStream } from './event-stream.js';
6
+ import { PromptInput } from './prompt-input.js';
7
+ function pickRenderers(renderers, ev) {
8
+ const specific = renderers.find((r) => r.id !== 'fallback' && r.match(ev));
9
+ if (specific)
10
+ return specific;
11
+ return renderers.find((r) => r.id === 'fallback');
12
+ }
13
+ export function App({ client, plugins, defaultAgent = 'claude-code' }) {
14
+ const { exit } = useApp();
15
+ const [status, setStatus] = useState('');
16
+ const [activeId, setActiveId] = useState('chat');
17
+ const [promptMode, setPromptMode] = useState(false);
18
+ const { registry, stream } = useMemo(() => {
19
+ const r = createRegistry();
20
+ const s = new EventStream();
21
+ const ctx = createContext(client, r, (ev) => {
22
+ if (ev.type === 'status')
23
+ setStatus(ev.message);
24
+ if (ev.type === 'view:switch')
25
+ setActiveId(ev.id);
26
+ }, s);
27
+ void loadPlugins(plugins, ctx);
28
+ return { registry: r, stream: s };
29
+ }, [client, plugins]);
30
+ useInput((input, key) => {
31
+ if (promptMode)
32
+ return; // PromptInput owns keys while open
33
+ if (input === 'q' || (key.ctrl && input === 'c')) {
34
+ exit();
35
+ return;
36
+ }
37
+ if (input === 'p') {
38
+ setPromptMode(true);
39
+ return;
40
+ }
41
+ for (const v of registry.views) {
42
+ if (v.hotkey && input === v.hotkey)
43
+ setActiveId(v.id);
44
+ }
45
+ for (const c of registry.commands) {
46
+ if (input === c.hotkey) {
47
+ void c.run({
48
+ client,
49
+ eventStream: stream,
50
+ registerView: () => { },
51
+ registerEventRenderer: () => { },
52
+ registerCommand: () => { },
53
+ registerPromptHandler: () => { },
54
+ emit: (e) => {
55
+ if (e.type === 'status')
56
+ setStatus(e.message);
57
+ if (e.type === 'event')
58
+ stream.push(e.event);
59
+ },
60
+ });
61
+ }
62
+ }
63
+ });
64
+ const active = registry.views.find((v) => v.id === activeId) ?? registry.views[0];
65
+ const ActiveView = active?.component;
66
+ // Inject renderers+stream into whichever view is active by using a thin wrapper.
67
+ const ViewWithRenderers = ActiveView
68
+ ? (props) => {
69
+ const Wrapped = ActiveView;
70
+ return _jsx(Wrapped, { ...props, renderers: registry.renderers });
71
+ }
72
+ : undefined;
73
+ async function handlePromptSubmit(prompt) {
74
+ setPromptMode(false);
75
+ if (!prompt.trim())
76
+ return;
77
+ setStatus(`Dispatching to ${defaultAgent}…`);
78
+ // If a plugin registered a prompt handler, it wins.
79
+ if (registry.promptHandlers.length > 0) {
80
+ for (const h of registry.promptHandlers)
81
+ await h(prompt);
82
+ return;
83
+ }
84
+ try {
85
+ const handle = client.run({ agent: defaultAgent, prompt });
86
+ for await (const ev of handle) {
87
+ stream.push(ev);
88
+ }
89
+ setStatus('Run complete.');
90
+ }
91
+ catch (e) {
92
+ setStatus(`Error: ${e.message}`);
93
+ }
94
+ }
95
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { children: registry.views.map((v) => (_jsxs(Text, { color: v.id === active?.id ? 'green' : 'gray', children: ["[", v.hotkey ?? '?', "] ", v.title, ' '] }, v.id))) }), _jsx(Box, { borderStyle: "single", flexDirection: "column", paddingX: 1, children: ViewWithRenderers ? (_jsx(ViewWithRenderers, { client: client, active: true, eventStream: stream })) : (_jsx(Text, { dimColor: true, children: "No views registered." })) }), promptMode ? (_jsx(PromptInput, { onSubmit: handlePromptSubmit, onCancel: () => setPromptMode(false) })) : (_jsx(Box, { children: _jsx(Text, { dimColor: true, children: status || 'p: prompt · q: quit' }) }))] }));
96
+ }
97
+ //# sourceMappingURL=app.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=amux-tui.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"amux-tui.d.ts","sourceRoot":"","sources":["../../src/bin/amux-tui.tsx"],"names":[],"mappings":""}
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { render } from 'ink';
4
+ import { createClient } from '@a5c-ai/agent-mux';
5
+ import { App, builtinPlugins } from '../index.js';
6
+ const client = createClient();
7
+ render(_jsx(App, { client: client, plugins: builtinPlugins }));
8
+ //# sourceMappingURL=amux-tui.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"amux-tui.js","sourceRoot":"","sources":["../../src/bin/amux-tui.tsx"],"names":[],"mappings":";;AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,GAAG,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;AAC9B,MAAM,CAAC,KAAC,GAAG,IAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAI,CAAC,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { AgentEvent } from '@a5c-ai/agent-mux';
2
+ export type EventSubscriber = (event: AgentEvent) => void;
3
+ export type Unsubscribe = () => void;
4
+ export declare class EventStream {
5
+ private subscribers;
6
+ private buffer;
7
+ private maxBuffer;
8
+ constructor(maxBuffer?: number);
9
+ subscribe(fn: EventSubscriber): Unsubscribe;
10
+ push(event: AgentEvent): void;
11
+ snapshot(): readonly AgentEvent[];
12
+ clear(): void;
13
+ }
14
+ //# sourceMappingURL=event-stream.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-stream.d.ts","sourceRoot":"","sources":["../src/event-stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;AAC1D,MAAM,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC;AAErC,qBAAa,WAAW;IACtB,OAAO,CAAC,WAAW,CAAmC;IACtD,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,SAAS,CAAS;gBAEd,SAAS,SAAO;IAI5B,SAAS,CAAC,EAAE,EAAE,eAAe,GAAG,WAAW;IAO3C,IAAI,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAY7B,QAAQ,IAAI,SAAS,UAAU,EAAE;IAIjC,KAAK,IAAI,IAAI;CAGd"}
@@ -0,0 +1,34 @@
1
+ export class EventStream {
2
+ subscribers = new Set();
3
+ buffer = [];
4
+ maxBuffer;
5
+ constructor(maxBuffer = 1000) {
6
+ this.maxBuffer = maxBuffer;
7
+ }
8
+ subscribe(fn) {
9
+ this.subscribers.add(fn);
10
+ return () => {
11
+ this.subscribers.delete(fn);
12
+ };
13
+ }
14
+ push(event) {
15
+ this.buffer.push(event);
16
+ if (this.buffer.length > this.maxBuffer)
17
+ this.buffer.shift();
18
+ for (const fn of this.subscribers) {
19
+ try {
20
+ fn(event);
21
+ }
22
+ catch {
23
+ // subscriber errors must not break the stream
24
+ }
25
+ }
26
+ }
27
+ snapshot() {
28
+ return this.buffer.slice();
29
+ }
30
+ clear() {
31
+ this.buffer = [];
32
+ }
33
+ }
34
+ //# sourceMappingURL=event-stream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-stream.js","sourceRoot":"","sources":["../src/event-stream.ts"],"names":[],"mappings":"AAKA,MAAM,OAAO,WAAW;IACd,WAAW,GAAyB,IAAI,GAAG,EAAE,CAAC;IAC9C,MAAM,GAAiB,EAAE,CAAC;IAC1B,SAAS,CAAS;IAE1B,YAAY,SAAS,GAAG,IAAI;QAC1B,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;IAED,SAAS,CAAC,EAAmB;QAC3B,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACzB,OAAO,GAAG,EAAE;YACV,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC9B,CAAC,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,KAAiB;QACpB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACxB,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,SAAS;YAAE,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAC7D,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YAClC,IAAI,CAAC;gBACH,EAAE,CAAC,KAAK,CAAC,CAAC;YACZ,CAAC;YAAC,MAAM,CAAC;gBACP,8CAA8C;YAChD,CAAC;QACH,CAAC;IACH,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IAC7B,CAAC;IAED,KAAK;QACH,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;IACnB,CAAC;CACF"}
@@ -0,0 +1,10 @@
1
+ export { App } from './app.js';
2
+ export { createRegistry, createContext, loadPlugins } from './registry.js';
3
+ export type { Registry } from './registry.js';
4
+ export { EventStream } from './event-stream.js';
5
+ export type { EventSubscriber, Unsubscribe } from './event-stream.js';
6
+ export { PromptInput } from './prompt-input.js';
7
+ export * from './plugin.js';
8
+ import type { TuiPlugin } from './plugin.js';
9
+ export declare const builtinPlugins: TuiPlugin[];
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC3E,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,YAAY,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,cAAc,aAAa,CAAC;AAS5B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAI7C,eAAO,MAAM,cAAc,EAAE,SAAS,EAQrC,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,24 @@
1
+ export { App } from './app.js';
2
+ export { createRegistry, createContext, loadPlugins } from './registry.js';
3
+ export { EventStream } from './event-stream.js';
4
+ export { PromptInput } from './prompt-input.js';
5
+ export * from './plugin.js';
6
+ import textDelta from './plugins/text-delta.js';
7
+ import toolCall from './plugins/tool-call.js';
8
+ import cost from './plugins/cost.js';
9
+ import chatView from './plugins/chat-view.js';
10
+ import sessionsView from './plugins/sessions-view.js';
11
+ import fallback from './plugins/fallback.js';
12
+ import diff from './plugins/diff.js';
13
+ // Order matters: specific renderers first, fallback LAST so it only matches
14
+ // when nothing else did (chat-view's pickRenderers enforces this).
15
+ export const builtinPlugins = [
16
+ textDelta,
17
+ toolCall,
18
+ diff,
19
+ cost,
20
+ chatView,
21
+ sessionsView,
22
+ fallback,
23
+ ];
24
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE3E,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,cAAc,aAAa,CAAC;AAE5B,OAAO,SAAS,MAAM,yBAAyB,CAAC;AAChD,OAAO,QAAQ,MAAM,wBAAwB,CAAC;AAC9C,OAAO,IAAI,MAAM,mBAAmB,CAAC;AACrC,OAAO,QAAQ,MAAM,wBAAwB,CAAC;AAC9C,OAAO,YAAY,MAAM,4BAA4B,CAAC;AACtD,OAAO,QAAQ,MAAM,uBAAuB,CAAC;AAC7C,OAAO,IAAI,MAAM,mBAAmB,CAAC;AAGrC,4EAA4E;AAC5E,mEAAmE;AACnE,MAAM,CAAC,MAAM,cAAc,GAAgB;IACzC,SAAS;IACT,QAAQ;IACR,IAAI;IACJ,IAAI;IACJ,QAAQ;IACR,YAAY;IACZ,QAAQ;CACT,CAAC"}
@@ -0,0 +1,57 @@
1
+ import type { ComponentType } from 'react';
2
+ import type { AgentMuxClient, AgentEvent, RunHandle } from '@a5c-ai/agent-mux';
3
+ import type { EventStream } from './event-stream.js';
4
+ export type PromptHandler = (prompt: string) => void | Promise<void>;
5
+ export interface TuiContext {
6
+ client: AgentMuxClient;
7
+ eventStream: EventStream;
8
+ registerView(view: TuiView): void;
9
+ registerEventRenderer(renderer: EventRenderer): void;
10
+ registerCommand(cmd: TuiCommand): void;
11
+ registerPromptHandler(handler: PromptHandler): void;
12
+ emit(event: TuiInternalEvent): void;
13
+ }
14
+ export interface TuiView {
15
+ id: string;
16
+ title: string;
17
+ hotkey?: string;
18
+ component: ComponentType<TuiViewProps>;
19
+ }
20
+ export interface TuiViewProps {
21
+ client: AgentMuxClient;
22
+ active: boolean;
23
+ eventStream: EventStream;
24
+ }
25
+ export interface EventRenderer {
26
+ id: string;
27
+ match(ev: AgentEvent): boolean;
28
+ component: ComponentType<{
29
+ event: AgentEvent;
30
+ }>;
31
+ }
32
+ export interface TuiCommand {
33
+ id: string;
34
+ hotkey: string;
35
+ label: string;
36
+ run(ctx: TuiContext): void | Promise<void>;
37
+ }
38
+ export type TuiInternalEvent = {
39
+ type: 'view:switch';
40
+ id: string;
41
+ } | {
42
+ type: 'run:attach';
43
+ handle: RunHandle;
44
+ } | {
45
+ type: 'status';
46
+ message: string;
47
+ } | {
48
+ type: 'event';
49
+ event: AgentEvent;
50
+ };
51
+ export interface TuiPlugin {
52
+ name: string;
53
+ version?: string;
54
+ register(ctx: TuiContext): void | Promise<void>;
55
+ }
56
+ export declare function definePlugin(plugin: TuiPlugin): TuiPlugin;
57
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC/E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,MAAM,MAAM,aAAa,GAAG,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAErE,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,cAAc,CAAC;IACvB,WAAW,EAAE,WAAW,CAAC;IACzB,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;IAClC,qBAAqB,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI,CAAC;IACrD,eAAe,CAAC,GAAG,EAAE,UAAU,GAAG,IAAI,CAAC;IACvC,qBAAqB,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,CAAC;IACpD,IAAI,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAAC;CACrC;AAED,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;CACxC;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,cAAc,CAAC;IACvB,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,EAAE,WAAW,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,EAAE,UAAU,GAAG,OAAO,CAAC;IAC/B,SAAS,EAAE,aAAa,CAAC;QAAE,KAAK,EAAE,UAAU,CAAA;KAAE,CAAC,CAAC;CACjD;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,GAAG,EAAE,UAAU,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5C;AAED,MAAM,MAAM,gBAAgB,GACxB;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,SAAS,CAAA;CAAE,GACzC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,UAAU,CAAA;CAAE,CAAC;AAEzC,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,GAAG,EAAE,UAAU,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACjD;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,CAEzD"}
package/dist/plugin.js ADDED
@@ -0,0 +1,4 @@
1
+ export function definePlugin(plugin) {
2
+ return plugin;
3
+ }
4
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAsDA,MAAM,UAAU,YAAY,CAAC,MAAiB;IAC5C,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { type EventRenderer, type TuiViewProps } from '../plugin.js';
2
+ interface ChatViewInnerProps extends TuiViewProps {
3
+ renderers: EventRenderer[];
4
+ }
5
+ declare function ChatViewInner({ eventStream, renderers }: ChatViewInnerProps): import("react/jsx-runtime").JSX.Element;
6
+ declare const _default: import("../plugin.js").TuiPlugin;
7
+ export default _default;
8
+ export { ChatViewInner };
9
+ //# sourceMappingURL=chat-view.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-view.d.ts","sourceRoot":"","sources":["../../src/plugins/chat-view.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAgB,KAAK,aAAa,EAAE,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAEnF,UAAU,kBAAmB,SAAQ,YAAY;IAC/C,SAAS,EAAE,aAAa,EAAE,CAAC;CAC5B;AAED,iBAAS,aAAa,CAAC,EAAE,WAAW,EAAE,SAAS,EAAE,EAAE,kBAAkB,2CA4BpE;;AAED,wBAYG;AAEH,OAAO,EAAE,aAAa,EAAE,CAAC"}
@@ -0,0 +1,35 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useEffect, useState } from 'react';
3
+ import { Box, Text } from 'ink';
4
+ import { definePlugin } from '../plugin.js';
5
+ function ChatViewInner({ eventStream, renderers }) {
6
+ const [events, setEvents] = useState(() => [...eventStream.snapshot()]);
7
+ useEffect(() => {
8
+ return eventStream.subscribe((ev) => {
9
+ setEvents((prev) => [...prev, ev]);
10
+ });
11
+ }, [eventStream]);
12
+ if (events.length === 0) {
13
+ return (_jsx(Box, { flexDirection: "column", children: _jsx(Text, { dimColor: true, children: "No messages yet. Press `p` to run a prompt." }) }));
14
+ }
15
+ const specific = renderers.filter((r) => r.id !== 'fallback');
16
+ const fallback = renderers.find((r) => r.id === 'fallback');
17
+ return (_jsx(Box, { flexDirection: "column", children: events.slice(-200).map((ev, i) => {
18
+ const r = specific.find((x) => x.match(ev)) ?? fallback;
19
+ const Comp = r?.component;
20
+ return Comp ? _jsx(Comp, { event: ev }, i) : null;
21
+ }) }));
22
+ }
23
+ export default definePlugin({
24
+ name: 'builtin:chat-view',
25
+ register(ctx) {
26
+ ctx.registerView({
27
+ id: 'chat',
28
+ title: 'Chat',
29
+ hotkey: '1',
30
+ component: (props) => (_jsx(ChatViewInner, { ...props, renderers: [] })),
31
+ });
32
+ },
33
+ });
34
+ export { ChatViewInner };
35
+ //# sourceMappingURL=chat-view.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-view.js","sourceRoot":"","sources":["../../src/plugins/chat-view.tsx"],"names":[],"mappings":";AAAA,OAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACnD,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAEhC,OAAO,EAAE,YAAY,EAAyC,MAAM,cAAc,CAAC;AAMnF,SAAS,aAAa,CAAC,EAAE,WAAW,EAAE,SAAS,EAAsB;IACnE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAe,GAAG,EAAE,CAAC,CAAC,GAAG,WAAW,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;IACtF,SAAS,CAAC,GAAG,EAAE;QACb,OAAO,WAAW,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,EAAE;YAClC,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC;IACL,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;IAElB,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,CACL,KAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,YACzB,KAAC,IAAI,IAAC,QAAQ,kEAAmD,GAC7D,CACP,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,UAAU,CAAC,CAAC;IAC9D,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,UAAU,CAAC,CAAC;IAE5D,OAAO,CACL,KAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,YACxB,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE;YAChC,MAAM,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,QAAQ,CAAC;YACxD,MAAM,IAAI,GAAG,CAAC,EAAE,SAAS,CAAC;YAC1B,OAAO,IAAI,CAAC,CAAC,CAAC,KAAC,IAAI,IAAS,KAAK,EAAE,EAAE,IAAZ,CAAC,CAAe,CAAC,CAAC,CAAC,IAAI,CAAC;QACnD,CAAC,CAAC,GACE,CACP,CAAC;AACJ,CAAC;AAED,eAAe,YAAY,CAAC;IAC1B,IAAI,EAAE,mBAAmB;IACzB,QAAQ,CAAC,GAAG;QACV,GAAG,CAAC,YAAY,CAAC;YACf,EAAE,EAAE,MAAM;YACV,KAAK,EAAE,MAAM;YACb,MAAM,EAAE,GAAG;YACX,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CACpB,KAAC,aAAa,OAAK,KAAK,EAAE,SAAS,EAAE,EAAE,GAAI,CAC5C;SACF,CAAC,CAAC;IACL,CAAC;CACF,CAAC,CAAC;AAEH,OAAO,EAAE,aAAa,EAAE,CAAC"}
@@ -0,0 +1,3 @@
1
+ declare const _default: import("../plugin.js").TuiPlugin;
2
+ export default _default;
3
+ //# sourceMappingURL=cost.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost.d.ts","sourceRoot":"","sources":["../../src/plugins/cost.tsx"],"names":[],"mappings":";AAIA,wBAiBG"}
@@ -0,0 +1,16 @@
1
+ import { jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Text } from 'ink';
3
+ import { definePlugin } from '../plugin.js';
4
+ export default definePlugin({
5
+ name: 'builtin:cost',
6
+ register(ctx) {
7
+ ctx.registerEventRenderer({
8
+ id: 'cost',
9
+ match: (ev) => ev.type === 'cost',
10
+ component: ({ event }) => event.type === 'cost' ? (_jsxs(Text, { color: "yellow", children: ["$", event.cost.totalUsd !== undefined
11
+ ? event.cost.totalUsd.toFixed(4)
12
+ : '?'] })) : null,
13
+ });
14
+ },
15
+ });
16
+ //# sourceMappingURL=cost.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost.js","sourceRoot":"","sources":["../../src/plugins/cost.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,eAAe,YAAY,CAAC;IAC1B,IAAI,EAAE,cAAc;IACpB,QAAQ,CAAC,GAAG;QACV,GAAG,CAAC,qBAAqB,CAAC;YACxB,EAAE,EAAE,MAAM;YACV,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,KAAK,MAAM;YACjC,SAAS,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CACvB,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,CACtB,MAAC,IAAI,IAAC,KAAK,EAAC,QAAQ,kBAEjB,KAAK,CAAC,IAAI,CAAC,QAAQ,KAAK,SAAS;wBAChC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;wBAChC,CAAC,CAAC,GAAG,IACF,CACR,CAAC,CAAC,CAAC,IAAI;SACX,CAAC,CAAC;IACL,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { AgentEvent } from '@a5c-ai/agent-mux';
2
+ export declare function DiffRenderer({ event }: {
3
+ event: AgentEvent;
4
+ }): import("react/jsx-runtime").JSX.Element | null;
5
+ declare const _default: import("../plugin.js").TuiPlugin;
6
+ export default _default;
7
+ //# sourceMappingURL=diff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/plugins/diff.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAGpD,wBAAgB,YAAY,CAAC,EAAE,KAAK,EAAE,EAAE;IAAE,KAAK,EAAE,UAAU,CAAA;CAAE,kDAiC5D;;AAED,wBASG"}
@@ -0,0 +1,42 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import { Box, Text } from 'ink';
3
+ import { definePlugin } from '../plugin.js';
4
+ export function DiffRenderer({ event }) {
5
+ if (event.type !== 'file_patch')
6
+ return null;
7
+ const lines = event.diff.split('\n');
8
+ let adds = 0;
9
+ let dels = 0;
10
+ for (const line of lines) {
11
+ if (line.startsWith('+') && !line.startsWith('+++'))
12
+ adds++;
13
+ else if (line.startsWith('-') && !line.startsWith('---'))
14
+ dels++;
15
+ }
16
+ return (_jsxs(Box, { flexDirection: "column", marginY: 0, children: [_jsxs(Text, { children: [_jsxs(Text, { color: "magenta", children: ["\u25C6 ", event.path] }), ' ', _jsxs(Text, { color: "green", children: ["+", adds] }), ' ', _jsxs(Text, { color: "red", children: ["-", dels] })] }), lines.map((line, i) => {
17
+ if (line.startsWith('+++') || line.startsWith('---')) {
18
+ return _jsx(Text, { dimColor: true, children: line }, i);
19
+ }
20
+ if (line.startsWith('@@')) {
21
+ return _jsx(Text, { color: "cyan", children: line }, i);
22
+ }
23
+ if (line.startsWith('+')) {
24
+ return _jsx(Text, { color: "green", children: line }, i);
25
+ }
26
+ if (line.startsWith('-')) {
27
+ return _jsx(Text, { color: "red", children: line }, i);
28
+ }
29
+ return _jsx(Text, { children: line }, i);
30
+ })] }));
31
+ }
32
+ export default definePlugin({
33
+ name: 'builtin:diff',
34
+ register(ctx) {
35
+ ctx.registerEventRenderer({
36
+ id: 'file-patch',
37
+ match: (ev) => ev.type === 'file_patch',
38
+ component: DiffRenderer,
39
+ });
40
+ },
41
+ });
42
+ //# sourceMappingURL=diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/plugins/diff.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAEhC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,MAAM,UAAU,YAAY,CAAC,EAAE,KAAK,EAAyB;IAC3D,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY;QAAE,OAAO,IAAI,CAAC;IAC7C,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACrC,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;YAAE,IAAI,EAAE,CAAC;aACvD,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;YAAE,IAAI,EAAE,CAAC;IACnE,CAAC;IACD,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,OAAO,EAAE,CAAC,aACpC,MAAC,IAAI,eACH,MAAC,IAAI,IAAC,KAAK,EAAC,SAAS,wBAAI,KAAK,CAAC,IAAI,IAAQ,EAAC,GAAG,EAC/C,MAAC,IAAI,IAAC,KAAK,EAAC,OAAO,kBAAG,IAAI,IAAQ,EAAC,GAAG,EACtC,MAAC,IAAI,IAAC,KAAK,EAAC,KAAK,kBAAG,IAAI,IAAQ,IAC3B,EACN,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;gBACrB,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;oBACrD,OAAO,KAAC,IAAI,IAAS,QAAQ,kBAAE,IAAI,IAAjB,CAAC,CAAwB,CAAC;gBAC9C,CAAC;gBACD,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC1B,OAAO,KAAC,IAAI,IAAS,KAAK,EAAC,MAAM,YAAE,IAAI,IAArB,CAAC,CAA4B,CAAC;gBAClD,CAAC;gBACD,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;oBACzB,OAAO,KAAC,IAAI,IAAS,KAAK,EAAC,OAAO,YAAE,IAAI,IAAtB,CAAC,CAA6B,CAAC;gBACnD,CAAC;gBACD,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;oBACzB,OAAO,KAAC,IAAI,IAAS,KAAK,EAAC,KAAK,YAAE,IAAI,IAApB,CAAC,CAA2B,CAAC;gBACjD,CAAC;gBACD,OAAO,KAAC,IAAI,cAAU,IAAI,IAAR,CAAC,CAAe,CAAC;YACrC,CAAC,CAAC,IACE,CACP,CAAC;AACJ,CAAC;AAED,eAAe,YAAY,CAAC;IAC1B,IAAI,EAAE,cAAc;IACpB,QAAQ,CAAC,GAAG;QACV,GAAG,CAAC,qBAAqB,CAAC;YACxB,EAAE,EAAE,YAAY;YAChB,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,KAAK,YAAY;YACvC,SAAS,EAAE,YAAY;SACxB,CAAC,CAAC;IACL,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { AgentEvent } from '@a5c-ai/agent-mux';
2
+ export declare function FallbackRenderer({ event }: {
3
+ event: AgentEvent;
4
+ }): import("react/jsx-runtime").JSX.Element;
5
+ declare const _default: import("../plugin.js").TuiPlugin;
6
+ export default _default;
7
+ //# sourceMappingURL=fallback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fallback.d.ts","sourceRoot":"","sources":["../../src/plugins/fallback.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAGpD,wBAAgB,gBAAgB,CAAC,EAAE,KAAK,EAAE,EAAE;IAAE,KAAK,EAAE,UAAU,CAAA;CAAE,2CAMhE;;AAED,wBASG"}
@@ -0,0 +1,17 @@
1
+ import { jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Text } from 'ink';
3
+ import { definePlugin } from '../plugin.js';
4
+ export function FallbackRenderer({ event }) {
5
+ return (_jsxs(Text, { dimColor: true, children: ["\u00B7 ", event.type] }));
6
+ }
7
+ export default definePlugin({
8
+ name: 'builtin:fallback',
9
+ register(ctx) {
10
+ ctx.registerEventRenderer({
11
+ id: 'fallback',
12
+ match: () => true,
13
+ component: FallbackRenderer,
14
+ });
15
+ },
16
+ });
17
+ //# sourceMappingURL=fallback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fallback.js","sourceRoot":"","sources":["../../src/plugins/fallback.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAE3B,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,MAAM,UAAU,gBAAgB,CAAC,EAAE,KAAK,EAAyB;IAC/D,OAAO,CACL,MAAC,IAAI,IAAC,QAAQ,8BACT,KAAK,CAAC,IAAI,IACR,CACR,CAAC;AACJ,CAAC;AAED,eAAe,YAAY,CAAC;IAC1B,IAAI,EAAE,kBAAkB;IACxB,QAAQ,CAAC,GAAG;QACV,GAAG,CAAC,qBAAqB,CAAC;YACxB,EAAE,EAAE,UAAU;YACd,KAAK,EAAE,GAAG,EAAE,CAAC,IAAI;YACjB,SAAS,EAAE,gBAAgB;SAC5B,CAAC,CAAC;IACL,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ declare const _default: import("../plugin.js").TuiPlugin;
2
+ export default _default;
3
+ //# sourceMappingURL=sessions-view.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions-view.d.ts","sourceRoot":"","sources":["../../src/plugins/sessions-view.tsx"],"names":[],"mappings":";AAwCA,wBAUG"}
@@ -0,0 +1,49 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useState } from 'react';
3
+ import { Box, Text } from 'ink';
4
+ import { definePlugin } from '../plugin.js';
5
+ function SessionsView({ client, active }) {
6
+ const [sessions, setSessions] = useState([]);
7
+ const [error, setError] = useState(null);
8
+ useEffect(() => {
9
+ if (!active)
10
+ return;
11
+ (async () => {
12
+ try {
13
+ const agents = ['claude-code', 'codex', 'gemini'];
14
+ const all = [];
15
+ for (const a of agents) {
16
+ try {
17
+ const list = await client.sessions.list(a);
18
+ for (const s of list)
19
+ all.push({ sessionId: s.sessionId, agent: a });
20
+ }
21
+ catch {
22
+ // ignore per-agent listing errors
23
+ }
24
+ }
25
+ setSessions(all.slice(0, 20));
26
+ }
27
+ catch (e) {
28
+ setError(String(e));
29
+ }
30
+ })();
31
+ }, [active, client]);
32
+ if (error)
33
+ return _jsx(Text, { color: "red", children: error });
34
+ if (sessions.length === 0)
35
+ return _jsx(Text, { dimColor: true, children: "No sessions found." });
36
+ return (_jsx(Box, { flexDirection: "column", children: sessions.map((s) => (_jsxs(Text, { children: [_jsx(Text, { color: "cyan", children: s.agent }), " ", s.sessionId] }, s.agent + ':' + s.sessionId))) }));
37
+ }
38
+ export default definePlugin({
39
+ name: 'builtin:sessions-view',
40
+ register(ctx) {
41
+ ctx.registerView({
42
+ id: 'sessions',
43
+ title: 'Sessions',
44
+ hotkey: '2',
45
+ component: SessionsView,
46
+ });
47
+ },
48
+ });
49
+ //# sourceMappingURL=sessions-view.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions-view.js","sourceRoot":"","sources":["../../src/plugins/sessions-view.tsx"],"names":[],"mappings":";AAAA,OAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACnD,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAChC,OAAO,EAAE,YAAY,EAAqB,MAAM,cAAc,CAAC;AAE/D,SAAS,YAAY,CAAC,EAAE,MAAM,EAAE,MAAM,EAAgB;IACpD,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAyC,EAAE,CAAC,CAAC;IACrF,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IACxD,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,MAAM;YAAE,OAAO;QACpB,CAAC,KAAK,IAAI,EAAE;YACV,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,CAAC,aAAa,EAAE,OAAO,EAAE,QAAQ,CAAU,CAAC;gBAC3D,MAAM,GAAG,GAA2C,EAAE,CAAC;gBACvD,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;oBACvB,IAAI,CAAC;wBACH,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;wBAC3C,KAAK,MAAM,CAAC,IAAI,IAAI;4BAAE,GAAG,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;oBACvE,CAAC;oBAAC,MAAM,CAAC;wBACP,kCAAkC;oBACpC,CAAC;gBACH,CAAC;gBACD,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;YAChC,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;YACtB,CAAC;QACH,CAAC,CAAC,EAAE,CAAC;IACP,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACrB,IAAI,KAAK;QAAE,OAAO,KAAC,IAAI,IAAC,KAAK,EAAC,KAAK,YAAE,KAAK,GAAQ,CAAC;IACnD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAC,IAAI,IAAC,QAAQ,yCAA0B,CAAC;IAC3E,OAAO,CACL,KAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,YACxB,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CACnB,MAAC,IAAI,eACH,KAAC,IAAI,IAAC,KAAK,EAAC,MAAM,YAAE,CAAC,CAAC,KAAK,GAAQ,OAAE,CAAC,CAAC,SAAS,KADvC,CAAC,CAAC,KAAK,GAAG,GAAG,GAAG,CAAC,CAAC,SAAS,CAE/B,CACR,CAAC,GACE,CACP,CAAC;AACJ,CAAC;AAED,eAAe,YAAY,CAAC;IAC1B,IAAI,EAAE,uBAAuB;IAC7B,QAAQ,CAAC,GAAG;QACV,GAAG,CAAC,YAAY,CAAC;YACf,EAAE,EAAE,UAAU;YACd,KAAK,EAAE,UAAU;YACjB,MAAM,EAAE,GAAG;YACX,SAAS,EAAE,YAAY;SACxB,CAAC,CAAC;IACL,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ declare const _default: import("../plugin.js").TuiPlugin;
2
+ export default _default;
3
+ //# sourceMappingURL=text-delta.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-delta.d.ts","sourceRoot":"","sources":["../../src/plugins/text-delta.tsx"],"names":[],"mappings":";AAIA,wBAoBG"}
@@ -0,0 +1,19 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Text } from 'ink';
3
+ import { definePlugin } from '../plugin.js';
4
+ export default definePlugin({
5
+ name: 'builtin:text-delta',
6
+ register(ctx) {
7
+ ctx.registerEventRenderer({
8
+ id: 'text-delta',
9
+ match: (ev) => ev.type === 'text_delta',
10
+ component: ({ event }) => event.type === 'text_delta' ? _jsx(Text, { children: event.delta }) : null,
11
+ });
12
+ ctx.registerEventRenderer({
13
+ id: 'thinking-delta',
14
+ match: (ev) => ev.type === 'thinking_delta',
15
+ component: ({ event }) => event.type === 'thinking_delta' ? (_jsx(Text, { dimColor: true, italic: true, children: event.delta })) : null,
16
+ });
17
+ },
18
+ });
19
+ //# sourceMappingURL=text-delta.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-delta.js","sourceRoot":"","sources":["../../src/plugins/text-delta.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,eAAe,YAAY,CAAC;IAC1B,IAAI,EAAE,oBAAoB;IAC1B,QAAQ,CAAC,GAAG;QACV,GAAG,CAAC,qBAAqB,CAAC;YACxB,EAAE,EAAE,YAAY;YAChB,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,KAAK,YAAY;YACvC,SAAS,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CACvB,KAAK,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,KAAC,IAAI,cAAE,KAAK,CAAC,KAAK,GAAQ,CAAC,CAAC,CAAC,IAAI;SAClE,CAAC,CAAC;QACH,GAAG,CAAC,qBAAqB,CAAC;YACxB,EAAE,EAAE,gBAAgB;YACpB,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,KAAK,gBAAgB;YAC3C,SAAS,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CACvB,KAAK,CAAC,IAAI,KAAK,gBAAgB,CAAC,CAAC,CAAC,CAChC,KAAC,IAAI,IAAC,QAAQ,QAAC,MAAM,kBAClB,KAAK,CAAC,KAAK,GACP,CACR,CAAC,CAAC,CAAC,IAAI;SACX,CAAC,CAAC;IACL,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ declare const _default: import("../plugin.js").TuiPlugin;
2
+ export default _default;
3
+ //# sourceMappingURL=tool-call.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-call.d.ts","sourceRoot":"","sources":["../../src/plugins/tool-call.tsx"],"names":[],"mappings":";AAIA,wBAoCG"}
@@ -0,0 +1,24 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import { Box, Text } from 'ink';
3
+ import { definePlugin } from '../plugin.js';
4
+ export default definePlugin({
5
+ name: 'builtin:tool-call',
6
+ register(ctx) {
7
+ ctx.registerEventRenderer({
8
+ id: 'tool-call-start',
9
+ match: (ev) => ev.type === 'tool_call_start',
10
+ component: ({ event }) => event.type === 'tool_call_start' ? (_jsx(Box, { children: _jsxs(Text, { color: "cyan", children: ["\u25B6 ", event.toolName] }) })) : null,
11
+ });
12
+ ctx.registerEventRenderer({
13
+ id: 'tool-result',
14
+ match: (ev) => ev.type === 'tool_result',
15
+ component: ({ event }) => event.type === 'tool_result' ? (_jsx(Box, { children: _jsxs(Text, { color: "green", children: ["\u2713 ", event.toolName, " (", event.durationMs, "ms)"] }) })) : null,
16
+ });
17
+ ctx.registerEventRenderer({
18
+ id: 'tool-error',
19
+ match: (ev) => ev.type === 'tool_error',
20
+ component: ({ event }) => event.type === 'tool_error' ? (_jsx(Box, { children: _jsxs(Text, { color: "red", children: ["\u2717 ", event.toolName, ": ", event.error] }) })) : null,
21
+ });
22
+ },
23
+ });
24
+ //# sourceMappingURL=tool-call.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-call.js","sourceRoot":"","sources":["../../src/plugins/tool-call.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAChC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,eAAe,YAAY,CAAC;IAC1B,IAAI,EAAE,mBAAmB;IACzB,QAAQ,CAAC,GAAG;QACV,GAAG,CAAC,qBAAqB,CAAC;YACxB,EAAE,EAAE,iBAAiB;YACrB,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,KAAK,iBAAiB;YAC5C,SAAS,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CACvB,KAAK,CAAC,IAAI,KAAK,iBAAiB,CAAC,CAAC,CAAC,CACjC,KAAC,GAAG,cACF,MAAC,IAAI,IAAC,KAAK,EAAC,MAAM,wBAAI,KAAK,CAAC,QAAQ,IAAQ,GACxC,CACP,CAAC,CAAC,CAAC,IAAI;SACX,CAAC,CAAC;QACH,GAAG,CAAC,qBAAqB,CAAC;YACxB,EAAE,EAAE,aAAa;YACjB,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,KAAK,aAAa;YACxC,SAAS,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CACvB,KAAK,CAAC,IAAI,KAAK,aAAa,CAAC,CAAC,CAAC,CAC7B,KAAC,GAAG,cACF,MAAC,IAAI,IAAC,KAAK,EAAC,OAAO,wBACd,KAAK,CAAC,QAAQ,QAAI,KAAK,CAAC,UAAU,WAChC,GACH,CACP,CAAC,CAAC,CAAC,IAAI;SACX,CAAC,CAAC;QACH,GAAG,CAAC,qBAAqB,CAAC;YACxB,EAAE,EAAE,YAAY;YAChB,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,KAAK,YAAY;YACvC,SAAS,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CACvB,KAAK,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,CAC5B,KAAC,GAAG,cACF,MAAC,IAAI,IAAC,KAAK,EAAC,KAAK,wBAAI,KAAK,CAAC,QAAQ,QAAI,KAAK,CAAC,KAAK,IAAQ,GACtD,CACP,CAAC,CAAC,CAAC,IAAI;SACX,CAAC,CAAC;IACL,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,7 @@
1
+ export interface PromptInputProps {
2
+ onSubmit: (value: string) => void;
3
+ onCancel: () => void;
4
+ label?: string;
5
+ }
6
+ export declare function PromptInput({ onSubmit, onCancel, label }: PromptInputProps): import("react/jsx-runtime").JSX.Element;
7
+ //# sourceMappingURL=prompt-input.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt-input.d.ts","sourceRoot":"","sources":["../src/prompt-input.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,WAAW,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAkB,EAAE,EAAE,gBAAgB,2CA0BvF"}
@@ -0,0 +1,25 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from 'react';
3
+ import { Box, Text, useInput } from 'ink';
4
+ export function PromptInput({ onSubmit, onCancel, label = 'prompt> ' }) {
5
+ const [value, setValue] = useState('');
6
+ useInput((input, key) => {
7
+ if (key.escape) {
8
+ onCancel();
9
+ return;
10
+ }
11
+ if (key.return) {
12
+ onSubmit(value);
13
+ return;
14
+ }
15
+ if (key.backspace || key.delete) {
16
+ setValue((v) => v.slice(0, -1));
17
+ return;
18
+ }
19
+ if (input && !key.ctrl && !key.meta) {
20
+ setValue((v) => v + input);
21
+ }
22
+ });
23
+ return (_jsxs(Box, { children: [_jsx(Text, { color: "cyan", children: label }), _jsx(Text, { children: value }), _jsx(Text, { color: "cyan", children: "\u258C" })] }));
24
+ }
25
+ //# sourceMappingURL=prompt-input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt-input.js","sourceRoot":"","sources":["../src/prompt-input.tsx"],"names":[],"mappings":";AAAA,OAAc,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACxC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAQ1C,MAAM,UAAU,WAAW,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,GAAG,UAAU,EAAoB;IACtF,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACvC,QAAQ,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QACtB,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;YACf,QAAQ,EAAE,CAAC;YACX,OAAO;QACT,CAAC;QACD,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;YACf,QAAQ,CAAC,KAAK,CAAC,CAAC;YAChB,OAAO;QACT,CAAC;QACD,IAAI,GAAG,CAAC,SAAS,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;YAChC,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAChC,OAAO;QACT,CAAC;QACD,IAAI,KAAK,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;YACpC,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC,CAAC,CAAC;IACH,OAAO,CACL,MAAC,GAAG,eACF,KAAC,IAAI,IAAC,KAAK,EAAC,MAAM,YAAE,KAAK,GAAQ,EACjC,KAAC,IAAI,cAAE,KAAK,GAAQ,EACpB,KAAC,IAAI,IAAC,KAAK,EAAC,MAAM,uBAAS,IACvB,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { AgentMuxClient } from '@a5c-ai/agent-mux';
2
+ import type { EventStream } from './event-stream.js';
3
+ import type { EventRenderer, PromptHandler, TuiCommand, TuiContext, TuiInternalEvent, TuiPlugin, TuiView } from './plugin.js';
4
+ export interface Registry {
5
+ views: TuiView[];
6
+ renderers: EventRenderer[];
7
+ commands: TuiCommand[];
8
+ promptHandlers: PromptHandler[];
9
+ }
10
+ export declare function createRegistry(): Registry;
11
+ export declare function createContext(client: AgentMuxClient, registry: Registry, emit: (e: TuiInternalEvent) => void, eventStream: EventStream): TuiContext;
12
+ export declare function loadPlugins(plugins: TuiPlugin[], ctx: TuiContext): Promise<void>;
13
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EACV,aAAa,EACb,aAAa,EACb,UAAU,EACV,UAAU,EACV,gBAAgB,EAChB,SAAS,EACT,OAAO,EACR,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB,SAAS,EAAE,aAAa,EAAE,CAAC;IAC3B,QAAQ,EAAE,UAAU,EAAE,CAAC;IACvB,cAAc,EAAE,aAAa,EAAE,CAAC;CACjC;AAED,wBAAgB,cAAc,IAAI,QAAQ,CAEzC;AAED,wBAAgB,aAAa,CAC3B,MAAM,EAAE,cAAc,EACtB,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE,CAAC,CAAC,EAAE,gBAAgB,KAAK,IAAI,EACnC,WAAW,EAAE,WAAW,GACvB,UAAU,CAgBZ;AAED,wBAAsB,WAAW,CAC/B,OAAO,EAAE,SAAS,EAAE,EACpB,GAAG,EAAE,UAAU,GACd,OAAO,CAAC,IAAI,CAAC,CAIf"}
@@ -0,0 +1,26 @@
1
+ export function createRegistry() {
2
+ return { views: [], renderers: [], commands: [], promptHandlers: [] };
3
+ }
4
+ export function createContext(client, registry, emit, eventStream) {
5
+ return {
6
+ client,
7
+ eventStream,
8
+ registerView: (v) => registry.views.push(v),
9
+ registerEventRenderer: (r) => registry.renderers.push(r),
10
+ registerCommand: (c) => registry.commands.push(c),
11
+ registerPromptHandler: (h) => registry.promptHandlers.push(h),
12
+ emit: (e) => {
13
+ if (e.type === 'event') {
14
+ eventStream.push(e.event);
15
+ return;
16
+ }
17
+ emit(e);
18
+ },
19
+ };
20
+ }
21
+ export async function loadPlugins(plugins, ctx) {
22
+ for (const p of plugins) {
23
+ await p.register(ctx);
24
+ }
25
+ }
26
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAmBA,MAAM,UAAU,cAAc;IAC5B,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE,CAAC;AACxE,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,MAAsB,EACtB,QAAkB,EAClB,IAAmC,EACnC,WAAwB;IAExB,OAAO;QACL,MAAM;QACN,WAAW;QACX,YAAY,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QAC3C,qBAAqB,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;QACxD,eAAe,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;QACjD,qBAAqB,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC;QAC7D,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE;YACV,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBACvB,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;gBAC1B,OAAO;YACT,CAAC;YACD,IAAI,CAAC,CAAC,CAAC,CAAC;QACV,CAAC;KACF,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,OAAoB,EACpB,GAAe;IAEf,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IACxB,CAAC;AACH,CAAC"}
package/package.json ADDED
@@ -0,0 +1,71 @@
1
+ {
2
+ "name": "@a5c-ai/agent-mux-tui",
3
+ "version": "0.3.0",
4
+ "type": "module",
5
+ "license": "MIT",
6
+ "description": "Extensible Ink-based TUI for agent-mux, with a plugin-first architecture",
7
+ "author": "a5c-ai",
8
+ "homepage": "https://github.com/a5c-ai/agent-mux#readme",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/a5c-ai/agent-mux.git",
12
+ "directory": "packages/tui"
13
+ },
14
+ "bugs": {
15
+ "url": "https://github.com/a5c-ai/agent-mux/issues"
16
+ },
17
+ "keywords": [
18
+ "agent-mux",
19
+ "tui",
20
+ "ink",
21
+ "react",
22
+ "plugins"
23
+ ],
24
+ "engines": {
25
+ "node": ">=20.9.0"
26
+ },
27
+ "bin": {
28
+ "amux-tui": "./dist/bin/amux-tui.js"
29
+ },
30
+ "main": "./dist/index.js",
31
+ "module": "./dist/index.js",
32
+ "types": "./dist/index.d.ts",
33
+ "exports": {
34
+ ".": {
35
+ "import": {
36
+ "types": "./dist/index.d.ts",
37
+ "default": "./dist/index.js"
38
+ }
39
+ },
40
+ "./plugin": {
41
+ "import": {
42
+ "types": "./dist/plugin.d.ts",
43
+ "default": "./dist/plugin.js"
44
+ }
45
+ }
46
+ },
47
+ "files": [
48
+ "dist",
49
+ "README.md",
50
+ "LICENSE"
51
+ ],
52
+ "publishConfig": {
53
+ "access": "public"
54
+ },
55
+ "scripts": {
56
+ "build": "tsc --build",
57
+ "start": "node ./dist/bin/amux-tui.js",
58
+ "dev": "npm run build && npm start",
59
+ "prepublishOnly": "npm run build",
60
+ "test": "vitest run --config ../../vitest.config.ts"
61
+ },
62
+ "dependencies": {
63
+ "@a5c-ai/agent-mux": "0.2.0",
64
+ "ink": "^5.0.1",
65
+ "react": "^18.3.1"
66
+ },
67
+ "devDependencies": {
68
+ "@types/react": "^18.3.3",
69
+ "ink-testing-library": "^4.0.0"
70
+ }
71
+ }