@robota-sdk/agent-transport 3.0.0-beta.69 → 3.0.0-beta.70

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 (67) hide show
  1. package/dist/node/headless/index.cjs +1 -1
  2. package/dist/node/headless/index.d.ts +2 -2
  3. package/dist/node/headless/index.js +1 -1
  4. package/dist/node/headless-C6tj35h3.js +15 -0
  5. package/dist/node/headless-C6tj35h3.js.map +1 -0
  6. package/dist/node/headless-DCtHvyVf.cjs +14 -0
  7. package/dist/node/http/index.d.ts +1 -1
  8. package/dist/node/index-27HV5PJB.d.ts +68 -0
  9. package/dist/node/index-27HV5PJB.d.ts.map +1 -0
  10. package/dist/node/index-BRchlFBE.d.ts +68 -0
  11. package/dist/node/index-BRchlFBE.d.ts.map +1 -0
  12. package/dist/node/{index-C7DvsmEg.d.ts → index-BRgV_MPB.d.ts} +2 -2
  13. package/dist/node/{index-C7DvsmEg.d.ts.map → index-BRgV_MPB.d.ts.map} +1 -1
  14. package/dist/node/{index-D-aT_t_N.d.ts → index-BVNhOeeU.d.ts} +3 -2
  15. package/dist/node/{index-D-aT_t_N.d.ts.map → index-BVNhOeeU.d.ts.map} +1 -1
  16. package/dist/node/{index-yvGShbDx.d.ts → index-COWvtBa2.d.ts} +2 -2
  17. package/dist/node/{index-yvGShbDx.d.ts.map → index-COWvtBa2.d.ts.map} +1 -1
  18. package/dist/node/{index-ioN9mYAD.d.ts → index-TMAlNHuM.d.ts} +5 -4
  19. package/dist/node/{index-ioN9mYAD.d.ts.map → index-TMAlNHuM.d.ts.map} +1 -1
  20. package/dist/node/{index-DOA2KIYt.d.ts → index-nBlMTFkZ.d.ts} +2 -2
  21. package/dist/node/{index-DOA2KIYt.d.ts.map → index-nBlMTFkZ.d.ts.map} +1 -1
  22. package/dist/node/index.cjs +1 -1
  23. package/dist/node/index.d.ts +7 -7
  24. package/dist/node/index.js +1 -1
  25. package/dist/node/index.js.map +1 -1
  26. package/dist/node/mcp/index.d.ts +1 -1
  27. package/dist/node/tui/index.cjs +1 -1
  28. package/dist/node/tui/index.d.ts +2 -2
  29. package/dist/node/tui/index.js +1 -1
  30. package/dist/node/tui-Cf1-zocr.js +25 -0
  31. package/dist/node/tui-Cf1-zocr.js.map +1 -0
  32. package/dist/node/tui-re-S-CGS.cjs +24 -0
  33. package/dist/node/ws/index.d.ts +1 -1
  34. package/package.json +6 -6
  35. package/src/headless/HeadlessInteractionChannel.ts +84 -0
  36. package/src/headless/index.ts +2 -0
  37. package/src/tui/App.tsx +26 -56
  38. package/src/tui/InputArea.tsx +3 -59
  39. package/src/tui/StatusBar.tsx +1 -1
  40. package/src/tui/TuiInteractionChannel.ts +461 -0
  41. package/src/tui/__tests__/TuiInteractionChannel.display-contract.test.ts +239 -0
  42. package/src/tui/__tests__/TuiInteractionChannel.lifecycle.test.ts +294 -0
  43. package/src/tui/__tests__/TuiInteractionChannel.requestAction.test.ts +124 -0
  44. package/src/tui/__tests__/compact-event-bridge.test.ts +1 -1
  45. package/src/tui/__tests__/input-area-flow.test.ts +5 -12
  46. package/src/tui/flows/input-area-flow.ts +10 -15
  47. package/src/tui/hooks/use-interactive-session-init.ts +37 -2
  48. package/src/tui/hooks/useSlashRouting.ts +1 -1
  49. package/src/tui/hooks/useTuiChannel.ts +95 -0
  50. package/src/tui/index.ts +2 -1
  51. package/src/tui/interactions/__tests__/CommandConfirm.test.tsx +124 -0
  52. package/src/tui/interactions/__tests__/CommandPicker.test.tsx +138 -0
  53. package/src/tui/render.tsx +39 -1
  54. package/src/tui/tui-state-manager.ts +2 -1
  55. package/src/tui/tui-transport.ts +1 -1
  56. package/dist/node/headless-C-Ezlo9U.js +0 -15
  57. package/dist/node/headless-C-Ezlo9U.js.map +0 -1
  58. package/dist/node/headless-Cv-igy49.cjs +0 -14
  59. package/dist/node/index-CP7kaYMg.d.ts +0 -41
  60. package/dist/node/index-CP7kaYMg.d.ts.map +0 -1
  61. package/dist/node/index-Gby9H4q2.d.ts +0 -41
  62. package/dist/node/index-Gby9H4q2.d.ts.map +0 -1
  63. package/dist/node/tui-87G6pg3z.js +0 -25
  64. package/dist/node/tui-87G6pg3z.js.map +0 -1
  65. package/dist/node/tui-BAtwGilM.cjs +0 -24
  66. package/src/tui/command-interaction-registry.ts +0 -66
  67. package/src/tui/hooks/useInteractiveSession.ts +0 -299
@@ -0,0 +1,124 @@
1
+ import React from 'react';
2
+ import { render } from 'ink-testing-library';
3
+ import { describe, it, expect } from 'vitest';
4
+
5
+ import CommandConfirm from '../CommandConfirm.js';
6
+
7
+ import type { ITuiConfirmInteraction } from '../../command-interaction.js';
8
+
9
+ const delay = (ms: number): Promise<void> => new Promise((r) => setTimeout(r, ms));
10
+
11
+ function makeInteraction(message: string): ITuiConfirmInteraction {
12
+ return { onMissingArgs: 'confirm', message };
13
+ }
14
+
15
+ describe('CommandConfirm', () => {
16
+ it('renders the message text', () => {
17
+ const { lastFrame } = render(
18
+ <CommandConfirm
19
+ commandName="exit"
20
+ interaction={makeInteraction('Exit the session?')}
21
+ onConfirm={() => {}}
22
+ onCancel={() => {}}
23
+ />,
24
+ );
25
+ expect(lastFrame()).toContain('Exit the session?');
26
+ });
27
+
28
+ it('calls onConfirm when y is pressed', () => {
29
+ let confirmed = false;
30
+ const { stdin } = render(
31
+ <CommandConfirm
32
+ commandName="exit"
33
+ interaction={makeInteraction('Exit?')}
34
+ onConfirm={() => {
35
+ confirmed = true;
36
+ }}
37
+ onCancel={() => {}}
38
+ />,
39
+ );
40
+ stdin.write('y');
41
+ expect(confirmed).toBe(true);
42
+ });
43
+
44
+ it('calls onConfirm when Y is pressed', () => {
45
+ let confirmed = false;
46
+ const { stdin } = render(
47
+ <CommandConfirm
48
+ commandName="exit"
49
+ interaction={makeInteraction('Exit?')}
50
+ onConfirm={() => {
51
+ confirmed = true;
52
+ }}
53
+ onCancel={() => {}}
54
+ />,
55
+ );
56
+ stdin.write('Y');
57
+ expect(confirmed).toBe(true);
58
+ });
59
+
60
+ it('calls onConfirm on Enter', () => {
61
+ let confirmed = false;
62
+ const { stdin } = render(
63
+ <CommandConfirm
64
+ commandName="exit"
65
+ interaction={makeInteraction('Exit?')}
66
+ onConfirm={() => {
67
+ confirmed = true;
68
+ }}
69
+ onCancel={() => {}}
70
+ />,
71
+ );
72
+ stdin.write('\r');
73
+ expect(confirmed).toBe(true);
74
+ });
75
+
76
+ it('calls onCancel when n is pressed', () => {
77
+ let cancelled = false;
78
+ const { stdin } = render(
79
+ <CommandConfirm
80
+ commandName="exit"
81
+ interaction={makeInteraction('Exit?')}
82
+ onConfirm={() => {}}
83
+ onCancel={() => {
84
+ cancelled = true;
85
+ }}
86
+ />,
87
+ );
88
+ stdin.write('n');
89
+ expect(cancelled).toBe(true);
90
+ });
91
+
92
+ it('calls onCancel when N is pressed', () => {
93
+ let cancelled = false;
94
+ const { stdin } = render(
95
+ <CommandConfirm
96
+ commandName="exit"
97
+ interaction={makeInteraction('Exit?')}
98
+ onConfirm={() => {}}
99
+ onCancel={() => {
100
+ cancelled = true;
101
+ }}
102
+ />,
103
+ );
104
+ stdin.write('N');
105
+ expect(cancelled).toBe(true);
106
+ });
107
+
108
+ it('calls onCancel on Escape', async () => {
109
+ let cancelled = false;
110
+ const { stdin } = render(
111
+ <CommandConfirm
112
+ commandName="exit"
113
+ interaction={makeInteraction('Exit?')}
114
+ onConfirm={() => {}}
115
+ onCancel={() => {
116
+ cancelled = true;
117
+ }}
118
+ />,
119
+ );
120
+ stdin.write('\x1b');
121
+ await delay(50);
122
+ expect(cancelled).toBe(true);
123
+ });
124
+ });
@@ -0,0 +1,138 @@
1
+ import React from 'react';
2
+ import { render } from 'ink-testing-library';
3
+ import { describe, it, expect, vi } from 'vitest';
4
+
5
+ import CommandPicker from '../CommandPicker.js';
6
+
7
+ import type { ITuiPickerInteraction, ITuiPickerItem } from '../../command-interaction.js';
8
+
9
+ const delay = (ms: number): Promise<void> => new Promise((r) => setTimeout(r, ms));
10
+
11
+ function makeInteraction(items: ITuiPickerItem[]): ITuiPickerInteraction {
12
+ return {
13
+ onMissingArgs: 'picker',
14
+ getItems: () => items,
15
+ };
16
+ }
17
+
18
+ const ITEMS: ITuiPickerItem[] = [
19
+ { label: 'plan', value: 'plan', description: 'Plan mode' },
20
+ { label: 'default', value: 'default', description: 'Default mode' },
21
+ { label: 'auto', value: 'auto' },
22
+ ];
23
+
24
+ describe('CommandPicker', () => {
25
+ it('renders all item labels', () => {
26
+ const { lastFrame } = render(
27
+ <CommandPicker
28
+ commandName="mode"
29
+ interaction={makeInteraction(ITEMS)}
30
+ onSelect={() => {}}
31
+ onCancel={() => {}}
32
+ />,
33
+ );
34
+ const frame = lastFrame()!;
35
+ expect(frame).toContain('plan');
36
+ expect(frame).toContain('default');
37
+ expect(frame).toContain('auto');
38
+ });
39
+
40
+ it('highlights first item by default', () => {
41
+ const { lastFrame } = render(
42
+ <CommandPicker
43
+ commandName="mode"
44
+ interaction={makeInteraction(ITEMS)}
45
+ onSelect={() => {}}
46
+ onCancel={() => {}}
47
+ />,
48
+ );
49
+ const frame = lastFrame()!;
50
+ expect(frame).toContain('▸ plan');
51
+ });
52
+
53
+ it('calls onSelect with first item on Enter', () => {
54
+ const onSelect = vi.fn();
55
+ const { stdin } = render(
56
+ <CommandPicker
57
+ commandName="mode"
58
+ interaction={makeInteraction(ITEMS)}
59
+ onSelect={onSelect}
60
+ onCancel={() => {}}
61
+ />,
62
+ );
63
+ stdin.write('\r');
64
+ expect(onSelect).toHaveBeenCalledWith(ITEMS[0]);
65
+ });
66
+
67
+ it('moves highlight down on arrow-down then selects on Enter', async () => {
68
+ let selected: ITuiPickerItem | undefined;
69
+ const { stdin } = render(
70
+ <CommandPicker
71
+ commandName="mode"
72
+ interaction={makeInteraction(ITEMS)}
73
+ onSelect={(item) => {
74
+ selected = item;
75
+ }}
76
+ onCancel={() => {}}
77
+ />,
78
+ );
79
+ stdin.write('\x1B[B'); // ↓
80
+ await delay(50);
81
+ stdin.write('\r');
82
+ expect(selected).toEqual(ITEMS[1]);
83
+ });
84
+
85
+ it('calls onCancel on Escape', async () => {
86
+ let cancelled = false;
87
+ const { stdin } = render(
88
+ <CommandPicker
89
+ commandName="mode"
90
+ interaction={makeInteraction(ITEMS)}
91
+ onSelect={() => {}}
92
+ onCancel={() => {
93
+ cancelled = true;
94
+ }}
95
+ />,
96
+ );
97
+ stdin.write('\x1b');
98
+ await delay(50);
99
+ expect(cancelled).toBe(true);
100
+ });
101
+
102
+ it('calls onCancel on q', () => {
103
+ const onCancel = vi.fn();
104
+ const { stdin } = render(
105
+ <CommandPicker
106
+ commandName="mode"
107
+ interaction={makeInteraction(ITEMS)}
108
+ onSelect={() => {}}
109
+ onCancel={onCancel}
110
+ />,
111
+ );
112
+ stdin.write('q');
113
+ expect(onCancel).toHaveBeenCalled();
114
+ });
115
+
116
+ it('wraps highlight from last to first on arrow-down at bottom', async () => {
117
+ let selected: ITuiPickerItem | undefined;
118
+ const { stdin } = render(
119
+ <CommandPicker
120
+ commandName="mode"
121
+ interaction={makeInteraction(ITEMS)}
122
+ onSelect={(item) => {
123
+ selected = item;
124
+ }}
125
+ onCancel={() => {}}
126
+ />,
127
+ );
128
+ // Navigate to last item (index 2)
129
+ stdin.write('\x1B[B'); // ↓ to index 1
130
+ await delay(50);
131
+ stdin.write('\x1B[B'); // ↓ to index 2
132
+ await delay(50);
133
+ stdin.write('\x1B[B'); // ↓ wraps to index 0
134
+ await delay(50);
135
+ stdin.write('\r');
136
+ expect(selected).toEqual(ITEMS[0]);
137
+ });
138
+ });
@@ -6,6 +6,7 @@ import { render } from 'ink';
6
6
  import React from 'react';
7
7
 
8
8
  import App from './App.js';
9
+ import { TuiInteractionChannel } from './TuiInteractionChannel.js';
9
10
 
10
11
  import type { ITuiCliAdapter } from './tui-cli-adapter.js';
11
12
  import type { IAIProvider } from '@robota-sdk/agent-core';
@@ -57,6 +58,43 @@ export async function renderApp(options: IRenderOptions): Promise<void> {
57
58
  }
58
59
  });
59
60
 
60
- const instance = render(<App {...options} />, { exitOnCtrlC: false });
61
+ const channel = new TuiInteractionChannel({
62
+ cwd: options.cwd,
63
+ provider: options.provider,
64
+ permissionMode: options.permissionMode,
65
+ maxTurns: options.maxTurns,
66
+ sessionStore: options.sessionStore,
67
+ resumeSessionId: options.resumeSessionId,
68
+ forkSession: options.forkSession,
69
+ sessionName: options.sessionName,
70
+ backgroundTaskRunners: options.backgroundTaskRunners,
71
+ subagentRunnerFactory: options.subagentRunnerFactory,
72
+ commandModules: options.commandModules,
73
+ commandHostAdapters: options.commandHostAdapters,
74
+ shellExec: options.shellExec,
75
+ transportRegistry: options.transportRegistry,
76
+ language: options.language,
77
+ reloadPluginCommandSource: options.reloadPluginCommandSource,
78
+ agentName: options.agentName,
79
+ });
80
+
81
+ const instance = render(
82
+ <App
83
+ cwd={options.cwd}
84
+ channel={channel}
85
+ providerOverride={options.providerOverride}
86
+ providerType={options.providerType}
87
+ modelId={options.modelId}
88
+ permissionMode={options.permissionMode}
89
+ version={options.version}
90
+ sessionStore={options.sessionStore}
91
+ resumeSessionId={options.resumeSessionId}
92
+ showSessionPickerOnStart={options.showSessionPickerOnStart}
93
+ startupUpdateNotice={options.startupUpdateNotice}
94
+ transportRegistry={options.transportRegistry}
95
+ cliAdapter={options.cliAdapter}
96
+ />,
97
+ { exitOnCtrlC: false },
98
+ );
61
99
  await instance.waitUntilExit();
62
100
  }
@@ -4,7 +4,7 @@
4
4
  * Converts InteractiveSession events into rendering state.
5
5
  * No React dependency. Fully unit-testable.
6
6
  *
7
- * React hook (useInteractiveSession) subscribes to onChange
7
+ * React hook (useTuiChannel) subscribes to onChange
8
8
  * and reads state for rendering.
9
9
  */
10
10
 
@@ -107,6 +107,7 @@ export class TuiStateManager {
107
107
  this.activeTools = [];
108
108
  } else {
109
109
  this.isAborting = false;
110
+ this.activeTools = [];
110
111
  }
111
112
  this.notify();
112
113
  };
@@ -16,7 +16,7 @@ export class TuiTransport implements IConfigurableTransport<IInteractiveSession>
16
16
  }
17
17
 
18
18
  attach(_session: IInteractiveSession): void {
19
- // TuiTransport creates its own InteractiveSession internally via useInteractiveSession.
19
+ // TuiTransport creates its own InteractiveSession internally via TuiInteractionChannel.
20
20
  }
21
21
 
22
22
  async start(): Promise<void> {
@@ -1,15 +0,0 @@
1
- import*as e from"node:readline";import{randomUUID as t}from"node:crypto";var n=class{write(e){process.stdout.write(e)}writeLine(e){process.stdout.write(e+`
2
- `)}writeMarkdown(e){process.stdout.write(e)}writeError(e){process.stderr.write(e+`
3
- `)}prompt(t){return new Promise(n=>{let r=e.createInterface({input:process.stdin,output:process.stdout,terminal:!1,historySize:0});r.question(t,e=>{r.close(),n(e)})})}async select(e,t=0){for(let n=0;n<e.length;n++){let r=n===t?`>`:` `;process.stdout.write(` ${r} ${n+1}) ${e[n]}\n`)}let n=(await this.prompt(` Choose [1-${e.length}] (default: ${e[t]}): `)).trim().toLowerCase();if(n===``)return t;let r=parseInt(n,10);return!isNaN(r)&&r>=1&&r<=e.length?r-1:t}spinner(e){return{stop(){},update(){}}}};const r=(e,t=!1)=>new Promise((n,r)=>{process.stdout.write(e);let i=``,a=process.stdin,o=a.isRaw;if(!a.isTTY){r(Error(`Cannot prompt for input: stdin is not a TTY.
4
- Set your API key via environment variable instead:
5
- ANTHROPIC_API_KEY=<key> robota
6
- OPENAI_API_KEY=<key> robota`));return}a.setRawMode(!0),a.resume(),a.setEncoding(`utf8`);let s=e=>{for(let r of e)if(r===`\r`||r===`
7
- `){a.removeListener(`data`,s),a.setRawMode(o??!1),a.pause(),process.stdout.write(`
8
- `),n(i.trim());return}else r===``||r===`\b`?i.length>0&&(i=i.slice(0,-1),process.stdout.write(`\b \b`)):r===``?(a.removeListener(`data`,s),a.setRawMode(o??!1),a.pause(),process.stdout.write(`
9
- `),process.exit(0)):r.charCodeAt(0)>=32&&(i+=r,process.stdout.write(t?`*`:r))};a.on(`data`,s)});function i(e){let t=e.trimStart();if(!t.startsWith(`/`))return null;let[n=``,...r]=t.slice(1).split(/\s+/);return n.length===0?null:{name:n,args:r.join(` `)}}async function a(e,t){let n=i(t);if(!n)return{kind:`not-slash`};let r=await e.executeCommand(n.name,n.args);return r?r.effects?.some(e=>e.type===`session-execution-started`)?{kind:`session-execution`}:{kind:`command-result`,result:r}:{kind:`command-result`,result:{message:`Unknown command "/${n.name}".`,success:!1}}}function o(e,n,r){let i=JSON.stringify({type:`stream_event`,event:r,session_id:n(e),uuid:t()});process.stdout.write(i+`
10
- `)}function s(e,t,n,r){let i=n=>o(e,t,n),a=e=>i({type:`content_block_delta`,delta:{type:`text_delta`,text:e}}),s=e=>i({type:`background_task_event`,background_task_event:e}),l=e=>i({type:`background_job_group_event`,background_job_group_event:e}),u=()=>c(e,{onTextDelta:a,onBackgroundTaskEvent:s,onBackgroundJobGroupEvent:l,onComplete:d,onInterrupted:f,onError:p}),d=i=>{u(),n(t(e),i.response,`success`),r(0)},f=i=>{u(),n(t(e),i.response,`success`),r(0)},p=i=>{u(),n(t(e),``,`error`,i),r(1)};return e.on(`text_delta`,a),e.on(`background_task_event`,s),e.on(`background_job_group_event`,l),e.on(`complete`,d),e.on(`interrupted`,f),e.on(`error`,p),u}function c(e,t){e.off(`text_delta`,t.onTextDelta),e.off(`background_task_event`,t.onBackgroundTaskEvent),e.off(`background_job_group_event`,t.onBackgroundJobGroupEvent),e.off(`complete`,t.onComplete),e.off(`interrupted`,t.onInterrupted),e.off(`error`,t.onError)}function l(e){let{session:t,outputFormat:n}=e;return{run:e=>n===`text`?p(t,e):n===`json`?m(t,e):h(t,e)}}function u(e){let t=e.message.toLowerCase();return t.includes(`api key`)||t.includes(`no provider`)||t.includes(`provider`)?`config_error`:t.includes(`tool`)||t.includes(`execution`)?`tool_error`:`api_error`}function d(e,t,n,r){let i={type:`result`,result:t,session_id:e,subtype:n};n===`error`&&r!==void 0&&(i.error_code=u(r));let a=JSON.stringify(i);process.stdout.write(a+`
11
- `)}function f(e){try{return e.getSession().getSessionId()}catch{return``}}function p(e,t){return new Promise(n=>{let r=()=>{e.off(`complete`,i),e.off(`interrupted`,o),e.off(`error`,s)},i=e=>{r(),process.stdout.write(e.response+`
12
- `),n(0)},o=e=>{r(),e.response&&process.stdout.write(e.response+`
13
- `),n(0)},s=e=>{r(),n(1)};e.on(`complete`,i),e.on(`interrupted`,o),e.on(`error`,s),a(e,t).then(i=>{if(i.kind===`command-result`){r(),process.stdout.write(i.result.message+`
14
- `),n(+!i.result.success);return}i.kind!==`session-execution`&&e.submit(t)})})}function m(e,t){return new Promise(n=>{let r=()=>{e.off(`complete`,i),e.off(`interrupted`,o),e.off(`error`,s)},i=t=>{r(),d(f(e),t.response,`success`),n(0)},o=t=>{r(),d(f(e),t.response,`success`),n(0)},s=t=>{r(),d(f(e),``,`error`,t),n(1)};e.on(`complete`,i),e.on(`interrupted`,o),e.on(`error`,s),a(e,t).then(i=>{if(i.kind===`command-result`){r(),d(f(e),i.result.message,i.result.success?`success`:`error`),n(+!i.result.success);return}i.kind!==`session-execution`&&e.submit(t)})})}function h(e,t){return new Promise(n=>{let r=s(e,f,d,n);a(e,t).then(i=>{if(i.kind===`command-result`){r(),d(f(e),i.result.message,i.result.success?`success`:`error`),n(+!i.result.success);return}i.kind!==`session-execution`&&e.submit(t)})})}function g(e){let t=null,n=0;return{name:`headless`,attach(e){t=e},async start(){if(!t)throw Error(`No session attached. Call attach() first.`);n=await l({session:t,outputFormat:e.outputFormat}).run(e.prompt)},async stop(){},getExitCode(){return n}}}export{n as i,l as n,r,g as t};
15
- //# sourceMappingURL=headless-C-Ezlo9U.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"headless-C-Ezlo9U.js","names":[],"sources":["../../src/headless/print-terminal.ts","../../src/headless/cli-input.ts","../../src/headless/headless-stream-json.ts","../../src/headless/headless-runner.ts","../../src/headless/headless-transport.ts"],"sourcesContent":["/**\n * ITerminalOutput implementation for print mode (-p).\n *\n * Writes to stdout/stderr directly. The readline-based prompt and select are\n * only invoked if the agent triggers a permission-gated tool, which is rare in\n * one-shot print mode but must still work correctly.\n */\n\nimport * as readline from 'node:readline';\nimport type { ITerminalOutput, ISpinner } from '@robota-sdk/agent-core';\n\nexport class PrintTerminal implements ITerminalOutput {\n write(text: string): void {\n process.stdout.write(text);\n }\n writeLine(text: string): void {\n process.stdout.write(text + '\\n');\n }\n writeMarkdown(md: string): void {\n process.stdout.write(md);\n }\n writeError(text: string): void {\n process.stderr.write(text + '\\n');\n }\n prompt(question: string): Promise<string> {\n return new Promise<string>((resolve) => {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n terminal: false,\n historySize: 0,\n });\n rl.question(question, (answer) => {\n rl.close();\n resolve(answer);\n });\n });\n }\n async select(options: string[], initialIndex = 0): Promise<number> {\n for (let i = 0; i < options.length; i++) {\n const marker = i === initialIndex ? '>' : ' ';\n process.stdout.write(` ${marker} ${i + 1}) ${options[i]}\\n`);\n }\n const answer = await this.prompt(\n ` Choose [1-${options.length}] (default: ${options[initialIndex]}): `,\n );\n const trimmed = answer.trim().toLowerCase();\n if (trimmed === '') return initialIndex;\n const num = parseInt(trimmed, 10);\n if (!isNaN(num) && num >= 1 && num <= options.length) return num - 1;\n return initialIndex;\n }\n spinner(_message: string): ISpinner {\n return { stop(): void {}, update(): void {} };\n }\n}\n","const PRINTABLE_ASCII_START = 32;\n\nexport const promptInput = (label: string, masked = false): Promise<string> =>\n new Promise<string>((resolve, reject) => {\n process.stdout.write(label);\n let input = '';\n const stdin = process.stdin;\n const wasRaw = stdin.isRaw;\n if (!stdin.isTTY) {\n reject(\n new Error(\n 'Cannot prompt for input: stdin is not a TTY.\\n' +\n 'Set your API key via environment variable instead:\\n' +\n ' ANTHROPIC_API_KEY=<key> robota\\n' +\n ' OPENAI_API_KEY=<key> robota',\n ),\n );\n return;\n }\n stdin.setRawMode(true);\n stdin.resume();\n stdin.setEncoding('utf8');\n const onData = (data: string): void => {\n for (const ch of data) {\n if (ch === '\\r' || ch === '\\n') {\n stdin.removeListener('data', onData);\n stdin.setRawMode(wasRaw ?? false);\n stdin.pause();\n process.stdout.write('\\n');\n resolve(input.trim());\n return;\n } else if (ch === '\\x7f' || ch === '\\b') {\n if (input.length > 0) {\n input = input.slice(0, -1);\n process.stdout.write('\\b \\b');\n }\n } else if (ch === '\\x03') {\n stdin.removeListener('data', onData);\n stdin.setRawMode(wasRaw ?? false);\n stdin.pause();\n process.stdout.write('\\n');\n process.exit(0);\n } else if (ch.charCodeAt(0) >= PRINTABLE_ASCII_START) {\n input += ch;\n process.stdout.write(masked ? '*' : ch);\n }\n }\n };\n stdin.on('data', onData);\n });\n","import { randomUUID } from 'node:crypto';\n\nimport type {\n IInteractiveSession,\n IExecutionResult,\n ICommandResult,\n TBackgroundJobGroupEvent,\n TBackgroundTaskEvent,\n} from '@robota-sdk/agent-framework';\n\ntype TSlashCommandExecution =\n | { readonly kind: 'not-slash' }\n | { readonly kind: 'command-result'; readonly result: ICommandResult }\n | { readonly kind: 'session-execution' };\n\nfunction parseSlashCommand(prompt: string): { name: string; args: string } | null {\n const trimmed = prompt.trimStart();\n if (!trimmed.startsWith('/')) return null;\n const withoutSlash = trimmed.slice(1);\n const [name = '', ...args] = withoutSlash.split(/\\s+/);\n if (name.length === 0) return null;\n return { name, args: args.join(' ') };\n}\n\nexport async function executeSlashCommandIfPresent(\n session: IInteractiveSession,\n prompt: string,\n): Promise<TSlashCommandExecution> {\n const command = parseSlashCommand(prompt);\n if (!command) return { kind: 'not-slash' };\n\n const result = await session.executeCommand(command.name, command.args);\n if (result) {\n if (result.effects?.some((effect) => effect.type === 'session-execution-started')) {\n return { kind: 'session-execution' };\n }\n return { kind: 'command-result', result };\n }\n return {\n kind: 'command-result',\n result: { message: `Unknown command \"/${command.name}\".`, success: false },\n };\n}\n\ntype TStreamJsonEvent =\n | {\n type: 'content_block_delta';\n delta: { type: 'text_delta'; text: string };\n }\n | {\n type: 'background_task_event';\n background_task_event: TBackgroundTaskEvent;\n }\n | {\n type: 'background_job_group_event';\n background_job_group_event: TBackgroundJobGroupEvent;\n };\n\ninterface IStreamJsonHandlers {\n onTextDelta: (text: string) => void;\n onBackgroundTaskEvent: (event: TBackgroundTaskEvent) => void;\n onBackgroundJobGroupEvent: (event: TBackgroundJobGroupEvent) => void;\n onComplete: (result: IExecutionResult) => void;\n onInterrupted: (result: IExecutionResult) => void;\n onError: (error: Error) => void;\n}\n\nexport function writeStreamJsonEvent(\n session: IInteractiveSession,\n getSessionId: (s: IInteractiveSession) => string,\n event: TStreamJsonEvent,\n): void {\n const output = JSON.stringify({\n type: 'stream_event',\n event,\n session_id: getSessionId(session),\n uuid: randomUUID(),\n });\n process.stdout.write(output + '\\n');\n}\n\nexport function subscribeStreamJsonEvents(\n session: IInteractiveSession,\n getSessionId: (s: IInteractiveSession) => string,\n writeJsonResult: (\n sessionId: string,\n result: string,\n subtype: 'success' | 'error',\n error?: Error,\n ) => void,\n resolve: (exitCode: number) => void,\n): () => void {\n const emit = (event: TStreamJsonEvent): void =>\n writeStreamJsonEvent(session, getSessionId, event);\n\n const onTextDelta = (text: string): void =>\n emit({ type: 'content_block_delta', delta: { type: 'text_delta', text } });\n const onBackgroundTaskEvent = (event: TBackgroundTaskEvent): void =>\n emit({ type: 'background_task_event', background_task_event: event });\n const onBackgroundJobGroupEvent = (event: TBackgroundJobGroupEvent): void =>\n emit({ type: 'background_job_group_event', background_job_group_event: event });\n\n const cleanup = (): void =>\n unsubscribeStreamJsonEvents(session, {\n onTextDelta,\n onBackgroundTaskEvent,\n onBackgroundJobGroupEvent,\n onComplete,\n onInterrupted,\n onError,\n });\n\n const onComplete = (result: IExecutionResult): void => {\n cleanup();\n writeJsonResult(getSessionId(session), result.response, 'success');\n resolve(0);\n };\n const onInterrupted = (result: IExecutionResult): void => {\n cleanup();\n writeJsonResult(getSessionId(session), result.response, 'success');\n resolve(0);\n };\n const onError = (error: Error): void => {\n cleanup();\n writeJsonResult(getSessionId(session), '', 'error', error);\n resolve(1);\n };\n\n session.on('text_delta', onTextDelta);\n session.on('background_task_event', onBackgroundTaskEvent);\n session.on('background_job_group_event', onBackgroundJobGroupEvent);\n session.on('complete', onComplete);\n session.on('interrupted', onInterrupted);\n session.on('error', onError);\n return cleanup;\n}\n\nfunction unsubscribeStreamJsonEvents(\n session: IInteractiveSession,\n handlers: IStreamJsonHandlers,\n): void {\n session.off('text_delta', handlers.onTextDelta);\n session.off('background_task_event', handlers.onBackgroundTaskEvent);\n session.off('background_job_group_event', handlers.onBackgroundJobGroupEvent);\n session.off('complete', handlers.onComplete);\n session.off('interrupted', handlers.onInterrupted);\n session.off('error', handlers.onError);\n}\n","import { executeSlashCommandIfPresent, subscribeStreamJsonEvents } from './headless-stream-json.js';\n\nimport type { IInteractiveSession, IExecutionResult } from '@robota-sdk/agent-framework';\n\nexport type TOutputFormat = 'text' | 'json' | 'stream-json';\n\nexport interface IHeadlessRunnerOptions {\n session: IInteractiveSession;\n outputFormat: TOutputFormat;\n}\n\nexport function createHeadlessRunner(options: IHeadlessRunnerOptions): {\n run: (prompt: string) => Promise<number>;\n} {\n const { session, outputFormat } = options;\n return {\n run: (prompt: string): Promise<number> => {\n if (outputFormat === 'text') return runTextFormat(session, prompt);\n if (outputFormat === 'json') return runJsonFormat(session, prompt);\n return runStreamJsonFormat(session, prompt);\n },\n };\n}\n\nexport function resolveErrorCode(error: Error): string {\n const msg = error.message.toLowerCase();\n if (msg.includes('api key') || msg.includes('no provider') || msg.includes('provider')) {\n return 'config_error';\n }\n if (msg.includes('tool') || msg.includes('execution')) {\n return 'tool_error';\n }\n return 'api_error';\n}\n\nexport function writeJsonResult(\n sessionId: string,\n result: string,\n subtype: 'success' | 'error',\n error?: Error,\n): void {\n const payload: Record<string, unknown> = {\n type: 'result',\n result,\n session_id: sessionId,\n subtype,\n };\n if (subtype === 'error' && error !== undefined) {\n payload['error_code'] = resolveErrorCode(error);\n }\n const output = JSON.stringify(payload);\n process.stdout.write(output + '\\n');\n}\n\nexport function getSessionId(session: IInteractiveSession): string {\n try {\n return session.getSession().getSessionId();\n } catch {\n // allow-fallback: session may not be initialized yet\n return '';\n }\n}\n\nfunction runTextFormat(session: IInteractiveSession, prompt: string): Promise<number> {\n return new Promise<number>((resolve) => {\n const cleanup = (): void => {\n session.off('complete', onComplete);\n session.off('interrupted', onInterrupted);\n session.off('error', onError);\n };\n const onComplete = (result: IExecutionResult): void => {\n cleanup();\n process.stdout.write(result.response + '\\n');\n resolve(0);\n };\n const onInterrupted = (result: IExecutionResult): void => {\n cleanup();\n if (result.response) process.stdout.write(result.response + '\\n');\n resolve(0);\n };\n const onError = (_error: Error): void => {\n cleanup();\n resolve(1);\n };\n\n session.on('complete', onComplete);\n session.on('interrupted', onInterrupted);\n session.on('error', onError);\n\n void executeSlashCommandIfPresent(session, prompt).then((cmd) => {\n if (cmd.kind === 'command-result') {\n cleanup();\n process.stdout.write(cmd.result.message + '\\n');\n resolve(cmd.result.success ? 0 : 1);\n return;\n }\n if (cmd.kind !== 'session-execution') void session.submit(prompt);\n });\n });\n}\n\nfunction runJsonFormat(session: IInteractiveSession, prompt: string): Promise<number> {\n return new Promise<number>((resolve) => {\n const cleanup = (): void => {\n session.off('complete', onComplete);\n session.off('interrupted', onInterrupted);\n session.off('error', onError);\n };\n const onComplete = (result: IExecutionResult): void => {\n cleanup();\n writeJsonResult(getSessionId(session), result.response, 'success');\n resolve(0);\n };\n const onInterrupted = (result: IExecutionResult): void => {\n cleanup();\n writeJsonResult(getSessionId(session), result.response, 'success');\n resolve(0);\n };\n const onError = (error: Error): void => {\n cleanup();\n writeJsonResult(getSessionId(session), '', 'error', error);\n resolve(1);\n };\n\n session.on('complete', onComplete);\n session.on('interrupted', onInterrupted);\n session.on('error', onError);\n\n void executeSlashCommandIfPresent(session, prompt).then((cmd) => {\n if (cmd.kind === 'command-result') {\n cleanup();\n writeJsonResult(\n getSessionId(session),\n cmd.result.message,\n cmd.result.success ? 'success' : 'error',\n );\n resolve(cmd.result.success ? 0 : 1);\n return;\n }\n if (cmd.kind !== 'session-execution') void session.submit(prompt);\n });\n });\n}\n\nfunction runStreamJsonFormat(session: IInteractiveSession, prompt: string): Promise<number> {\n return new Promise<number>((resolve) => {\n const cleanup = subscribeStreamJsonEvents(session, getSessionId, writeJsonResult, resolve);\n\n void executeSlashCommandIfPresent(session, prompt).then((cmd) => {\n if (cmd.kind === 'command-result') {\n cleanup();\n writeJsonResult(\n getSessionId(session),\n cmd.result.message,\n cmd.result.success ? 'success' : 'error',\n );\n resolve(cmd.result.success ? 0 : 1);\n return;\n }\n if (cmd.kind !== 'session-execution') void session.submit(prompt);\n });\n });\n}\n","/**\n * ITransportAdapter implementation for headless transport.\n *\n * Wraps createHeadlessRunner into the unified ITransportAdapter interface.\n * After start() completes, getExitCode() returns the runner's exit code.\n */\n\nimport { createHeadlessRunner } from './headless-runner.js';\n\nimport type { TOutputFormat } from './headless-runner.js';\nimport type { IInteractiveSession } from '@robota-sdk/agent-framework';\nimport type { ITransportAdapter } from '@robota-sdk/agent-interface-transport';\n\nexport interface IHeadlessTransportOptions {\n /** Output format: 'text', 'json', or 'stream-json'. */\n outputFormat: TOutputFormat;\n /** The prompt to execute. */\n prompt: string;\n}\n\nexport function createHeadlessTransport(\n options: IHeadlessTransportOptions,\n): ITransportAdapter<IInteractiveSession> & { getExitCode(): number } {\n let session: IInteractiveSession | null = null;\n let exitCode = 0;\n\n return {\n name: 'headless',\n attach(s: IInteractiveSession) {\n session = s;\n },\n async start() {\n if (!session) throw new Error('No session attached. Call attach() first.');\n const runner = createHeadlessRunner({ session, outputFormat: options.outputFormat });\n exitCode = await runner.run(options.prompt);\n },\n async stop() {\n /* no-op: headless runner completes in start() */\n },\n getExitCode() {\n return exitCode;\n },\n };\n}\n"],"mappings":"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"}
@@ -1,14 +0,0 @@
1
- const e=require(`./chunk-Bmb41Sf3.cjs`);let t=require(`node:readline`);t=e.t(t,1);let n=require(`node:crypto`);var r=class{write(e){process.stdout.write(e)}writeLine(e){process.stdout.write(e+`
2
- `)}writeMarkdown(e){process.stdout.write(e)}writeError(e){process.stderr.write(e+`
3
- `)}prompt(e){return new Promise(n=>{let r=t.createInterface({input:process.stdin,output:process.stdout,terminal:!1,historySize:0});r.question(e,e=>{r.close(),n(e)})})}async select(e,t=0){for(let n=0;n<e.length;n++){let r=n===t?`>`:` `;process.stdout.write(` ${r} ${n+1}) ${e[n]}\n`)}let n=(await this.prompt(` Choose [1-${e.length}] (default: ${e[t]}): `)).trim().toLowerCase();if(n===``)return t;let r=parseInt(n,10);return!isNaN(r)&&r>=1&&r<=e.length?r-1:t}spinner(e){return{stop(){},update(){}}}};const i=(e,t=!1)=>new Promise((n,r)=>{process.stdout.write(e);let i=``,a=process.stdin,o=a.isRaw;if(!a.isTTY){r(Error(`Cannot prompt for input: stdin is not a TTY.
4
- Set your API key via environment variable instead:
5
- ANTHROPIC_API_KEY=<key> robota
6
- OPENAI_API_KEY=<key> robota`));return}a.setRawMode(!0),a.resume(),a.setEncoding(`utf8`);let s=e=>{for(let r of e)if(r===`\r`||r===`
7
- `){a.removeListener(`data`,s),a.setRawMode(o??!1),a.pause(),process.stdout.write(`
8
- `),n(i.trim());return}else r===``||r===`\b`?i.length>0&&(i=i.slice(0,-1),process.stdout.write(`\b \b`)):r===``?(a.removeListener(`data`,s),a.setRawMode(o??!1),a.pause(),process.stdout.write(`
9
- `),process.exit(0)):r.charCodeAt(0)>=32&&(i+=r,process.stdout.write(t?`*`:r))};a.on(`data`,s)});function a(e){let t=e.trimStart();if(!t.startsWith(`/`))return null;let[n=``,...r]=t.slice(1).split(/\s+/);return n.length===0?null:{name:n,args:r.join(` `)}}async function o(e,t){let n=a(t);if(!n)return{kind:`not-slash`};let r=await e.executeCommand(n.name,n.args);return r?r.effects?.some(e=>e.type===`session-execution-started`)?{kind:`session-execution`}:{kind:`command-result`,result:r}:{kind:`command-result`,result:{message:`Unknown command "/${n.name}".`,success:!1}}}function s(e,t,r){let i=JSON.stringify({type:`stream_event`,event:r,session_id:t(e),uuid:(0,n.randomUUID)()});process.stdout.write(i+`
10
- `)}function c(e,t,n,r){let i=n=>s(e,t,n),a=e=>i({type:`content_block_delta`,delta:{type:`text_delta`,text:e}}),o=e=>i({type:`background_task_event`,background_task_event:e}),c=e=>i({type:`background_job_group_event`,background_job_group_event:e}),u=()=>l(e,{onTextDelta:a,onBackgroundTaskEvent:o,onBackgroundJobGroupEvent:c,onComplete:d,onInterrupted:f,onError:p}),d=i=>{u(),n(t(e),i.response,`success`),r(0)},f=i=>{u(),n(t(e),i.response,`success`),r(0)},p=i=>{u(),n(t(e),``,`error`,i),r(1)};return e.on(`text_delta`,a),e.on(`background_task_event`,o),e.on(`background_job_group_event`,c),e.on(`complete`,d),e.on(`interrupted`,f),e.on(`error`,p),u}function l(e,t){e.off(`text_delta`,t.onTextDelta),e.off(`background_task_event`,t.onBackgroundTaskEvent),e.off(`background_job_group_event`,t.onBackgroundJobGroupEvent),e.off(`complete`,t.onComplete),e.off(`interrupted`,t.onInterrupted),e.off(`error`,t.onError)}function u(e){let{session:t,outputFormat:n}=e;return{run:e=>n===`text`?m(t,e):n===`json`?h(t,e):g(t,e)}}function d(e){let t=e.message.toLowerCase();return t.includes(`api key`)||t.includes(`no provider`)||t.includes(`provider`)?`config_error`:t.includes(`tool`)||t.includes(`execution`)?`tool_error`:`api_error`}function f(e,t,n,r){let i={type:`result`,result:t,session_id:e,subtype:n};n===`error`&&r!==void 0&&(i.error_code=d(r));let a=JSON.stringify(i);process.stdout.write(a+`
11
- `)}function p(e){try{return e.getSession().getSessionId()}catch{return``}}function m(e,t){return new Promise(n=>{let r=()=>{e.off(`complete`,i),e.off(`interrupted`,a),e.off(`error`,s)},i=e=>{r(),process.stdout.write(e.response+`
12
- `),n(0)},a=e=>{r(),e.response&&process.stdout.write(e.response+`
13
- `),n(0)},s=e=>{r(),n(1)};e.on(`complete`,i),e.on(`interrupted`,a),e.on(`error`,s),o(e,t).then(i=>{if(i.kind===`command-result`){r(),process.stdout.write(i.result.message+`
14
- `),n(+!i.result.success);return}i.kind!==`session-execution`&&e.submit(t)})})}function h(e,t){return new Promise(n=>{let r=()=>{e.off(`complete`,i),e.off(`interrupted`,a),e.off(`error`,s)},i=t=>{r(),f(p(e),t.response,`success`),n(0)},a=t=>{r(),f(p(e),t.response,`success`),n(0)},s=t=>{r(),f(p(e),``,`error`,t),n(1)};e.on(`complete`,i),e.on(`interrupted`,a),e.on(`error`,s),o(e,t).then(i=>{if(i.kind===`command-result`){r(),f(p(e),i.result.message,i.result.success?`success`:`error`),n(+!i.result.success);return}i.kind!==`session-execution`&&e.submit(t)})})}function g(e,t){return new Promise(n=>{let r=c(e,p,f,n);o(e,t).then(i=>{if(i.kind===`command-result`){r(),f(p(e),i.result.message,i.result.success?`success`:`error`),n(+!i.result.success);return}i.kind!==`session-execution`&&e.submit(t)})})}function _(e){let t=null,n=0;return{name:`headless`,attach(e){t=e},async start(){if(!t)throw Error(`No session attached. Call attach() first.`);n=await u({session:t,outputFormat:e.outputFormat}).run(e.prompt)},async stop(){},getExitCode(){return n}}}Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return r}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return u}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return i}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return _}});
@@ -1,41 +0,0 @@
1
- import { ISpinner, ITerminalOutput } from "@robota-sdk/agent-core";
2
- import { IInteractiveSession } from "@robota-sdk/agent-framework";
3
- import { ITransportAdapter } from "@robota-sdk/agent-interface-transport";
4
-
5
- //#region src/headless/print-terminal.d.ts
6
- declare class PrintTerminal implements ITerminalOutput {
7
- write(text: string): void;
8
- writeLine(text: string): void;
9
- writeMarkdown(md: string): void;
10
- writeError(text: string): void;
11
- prompt(question: string): Promise<string>;
12
- select(options: string[], initialIndex?: number): Promise<number>;
13
- spinner(_message: string): ISpinner;
14
- }
15
- //#endregion
16
- //#region src/headless/cli-input.d.ts
17
- declare const promptInput: (label: string, masked?: boolean) => Promise<string>;
18
- //#endregion
19
- //#region src/headless/headless-runner.d.ts
20
- type TOutputFormat = 'text' | 'json' | 'stream-json';
21
- interface IHeadlessRunnerOptions {
22
- session: IInteractiveSession;
23
- outputFormat: TOutputFormat;
24
- }
25
- declare function createHeadlessRunner(options: IHeadlessRunnerOptions): {
26
- run: (prompt: string) => Promise<number>;
27
- };
28
- //#endregion
29
- //#region src/headless/headless-transport.d.ts
30
- interface IHeadlessTransportOptions {
31
- /** Output format: 'text', 'json', or 'stream-json'. */
32
- outputFormat: TOutputFormat;
33
- /** The prompt to execute. */
34
- prompt: string;
35
- }
36
- declare function createHeadlessTransport(options: IHeadlessTransportOptions): ITransportAdapter<IInteractiveSession> & {
37
- getExitCode(): number;
38
- };
39
- //#endregion
40
- export { createHeadlessRunner as a, TOutputFormat as i, createHeadlessTransport as n, promptInput as o, IHeadlessRunnerOptions as r, PrintTerminal as s, IHeadlessTransportOptions as t };
41
- //# sourceMappingURL=index-CP7kaYMg.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-CP7kaYMg.d.ts","names":[],"sources":["../../src/headless/print-terminal.ts","../../src/headless/cli-input.ts","../../src/headless/headless-runner.ts","../../src/headless/headless-transport.ts"],"mappings":";;;;;cAWa,aAAA,YAAyB,eAAA;EACpC,KAAA,CAAM,IAAA;EAGN,SAAA,CAAU,IAAA;EAGV,aAAA,CAAc,EAAA;EAGd,UAAA,CAAW,IAAA;EAGX,MAAA,CAAO,QAAA,WAAmB,OAAA;EAcpB,MAAA,CAAO,OAAA,YAAmB,YAAA,YAAmB,OAAA;EAcnD,OAAA,CAAQ,QAAA,WAAmB,QAAA;AAAA;;;cClDhB,WAAA,GAAe,KAAA,UAAe,MAAA,eAAiB,OAAO;;;KCEvD,aAAA;AAAA,UAEK,sBAAA;EACf,OAAA,EAAS,mBAAA;EACT,YAAA,EAAc,aAAa;AAAA;AAAA,iBAGb,oBAAA,CAAqB,OAAA,EAAS,sBAAA;EAC5C,GAAA,GAAM,MAAA,aAAmB,OAAO;AAAA;;;UCCjB,yBAAA;EHuCY;EGrC3B,YAAA,EAAc,aAAa;EHJwB;EGMnD,MAAA;AAAA;AAAA,iBAGc,uBAAA,CACd,OAAA,EAAS,yBAAA,GACR,iBAAA,CAAkB,mBAAA;EAAyB,WAAA;AAAA"}
@@ -1,41 +0,0 @@
1
- import { ISpinner, ITerminalOutput } from "@robota-sdk/agent-core";
2
- import { IInteractiveSession } from "@robota-sdk/agent-framework";
3
- import { ITransportAdapter } from "@robota-sdk/agent-interface-transport";
4
-
5
- //#region src/headless/print-terminal.d.ts
6
- declare class PrintTerminal implements ITerminalOutput {
7
- write(text: string): void;
8
- writeLine(text: string): void;
9
- writeMarkdown(md: string): void;
10
- writeError(text: string): void;
11
- prompt(question: string): Promise<string>;
12
- select(options: string[], initialIndex?: number): Promise<number>;
13
- spinner(_message: string): ISpinner;
14
- }
15
- //#endregion
16
- //#region src/headless/cli-input.d.ts
17
- declare const promptInput: (label: string, masked?: boolean) => Promise<string>;
18
- //#endregion
19
- //#region src/headless/headless-runner.d.ts
20
- type TOutputFormat = 'text' | 'json' | 'stream-json';
21
- interface IHeadlessRunnerOptions {
22
- session: IInteractiveSession;
23
- outputFormat: TOutputFormat;
24
- }
25
- declare function createHeadlessRunner(options: IHeadlessRunnerOptions): {
26
- run: (prompt: string) => Promise<number>;
27
- };
28
- //#endregion
29
- //#region src/headless/headless-transport.d.ts
30
- interface IHeadlessTransportOptions {
31
- /** Output format: 'text', 'json', or 'stream-json'. */
32
- outputFormat: TOutputFormat;
33
- /** The prompt to execute. */
34
- prompt: string;
35
- }
36
- declare function createHeadlessTransport(options: IHeadlessTransportOptions): ITransportAdapter<IInteractiveSession> & {
37
- getExitCode(): number;
38
- };
39
- //#endregion
40
- export { createHeadlessRunner as a, TOutputFormat as i, createHeadlessTransport as n, promptInput as o, IHeadlessRunnerOptions as r, PrintTerminal as s, IHeadlessTransportOptions as t };
41
- //# sourceMappingURL=index-Gby9H4q2.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-Gby9H4q2.d.ts","names":[],"sources":["../../src/headless/print-terminal.ts","../../src/headless/cli-input.ts","../../src/headless/headless-runner.ts","../../src/headless/headless-transport.ts"],"mappings":";;;;;cAWa,aAAA,YAAyB,eAAA;EACpC,KAAA,CAAM,IAAA;EAGN,SAAA,CAAU,IAAA;EAGV,aAAA,CAAc,EAAA;EAGd,UAAA,CAAW,IAAA;EAGX,MAAA,CAAO,QAAA,WAAmB,OAAA;EAcpB,MAAA,CAAO,OAAA,YAAmB,YAAA,YAAmB,OAAA;EAcnD,OAAA,CAAQ,QAAA,WAAmB,QAAA;AAAA;;;cClDhB,WAAA,GAAe,KAAA,UAAe,MAAA,eAAiB,OAAO;;;KCEvD,aAAA;AAAA,UAEK,sBAAA;EACf,OAAA,EAAS,mBAAA;EACT,YAAA,EAAc,aAAa;AAAA;AAAA,iBAGb,oBAAA,CAAqB,OAAA,EAAS,sBAAA;EAC5C,GAAA,GAAM,MAAA,aAAmB,OAAO;AAAA;;;UCCjB,yBAAA;EHuCY;EGrC3B,YAAA,EAAc,aAAa;EHJwB;EGMnD,MAAA;AAAA;AAAA,iBAGc,uBAAA,CACd,OAAA,EAAS,yBAAA,GACR,iBAAA,CAAkB,mBAAA;EAAyB,WAAA;AAAA"}