@robota-sdk/agent-transport 3.0.0-beta.75 → 3.0.0-beta.76

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 (187) hide show
  1. package/README.md +10 -10
  2. package/dist/node/headless/index.cjs +1 -1
  3. package/dist/node/{headless-CT2ibQnr.cjs → headless-OnpVk4-k.cjs} +7 -7
  4. package/dist/node/index.cjs +1 -1
  5. package/dist/node/index.d.ts +1 -6
  6. package/dist/node/index.d.ts.map +1 -1
  7. package/dist/node/index.js +1 -1
  8. package/dist/node/index.js.map +1 -1
  9. package/package.json +7 -75
  10. package/src/index.ts +1 -5
  11. package/src/transport-registry.ts +0 -9
  12. package/dist/node/http/index.cjs +0 -1
  13. package/dist/node/http/index.d.ts +0 -2
  14. package/dist/node/http/index.js +0 -1
  15. package/dist/node/http-2Jiuflc1.js +0 -2
  16. package/dist/node/http-2Jiuflc1.js.map +0 -1
  17. package/dist/node/http-CBAvefLw.cjs +0 -1
  18. package/dist/node/index-BNccqSpv.d.ts +0 -86
  19. package/dist/node/index-BNccqSpv.d.ts.map +0 -1
  20. package/dist/node/index-BUhHIf7X.d.ts +0 -86
  21. package/dist/node/index-BUhHIf7X.d.ts.map +0 -1
  22. package/dist/node/index-BnAGE-u9.d.ts +0 -33
  23. package/dist/node/index-BnAGE-u9.d.ts.map +0 -1
  24. package/dist/node/index-BrQ4gGw0.d.ts +0 -213
  25. package/dist/node/index-BrQ4gGw0.d.ts.map +0 -1
  26. package/dist/node/index-CoeBF21y.d.ts +0 -213
  27. package/dist/node/index-CoeBF21y.d.ts.map +0 -1
  28. package/dist/node/index-DHt-2VQ-.d.ts +0 -46
  29. package/dist/node/index-DHt-2VQ-.d.ts.map +0 -1
  30. package/dist/node/index-DMwKN5Le.d.ts +0 -33
  31. package/dist/node/index-DMwKN5Le.d.ts.map +0 -1
  32. package/dist/node/index-c0M42fsA.d.ts +0 -46
  33. package/dist/node/index-c0M42fsA.d.ts.map +0 -1
  34. package/dist/node/mcp/index.cjs +0 -1
  35. package/dist/node/mcp/index.d.ts +0 -2
  36. package/dist/node/mcp/index.js +0 -1
  37. package/dist/node/mcp-BOglBJNy.cjs +0 -1
  38. package/dist/node/mcp-D3BBVK7C.js +0 -2
  39. package/dist/node/mcp-D3BBVK7C.js.map +0 -1
  40. package/dist/node/rolldown-runtime-CMqjfN_6.cjs +0 -1
  41. package/dist/node/tui/index.cjs +0 -1
  42. package/dist/node/tui/index.d.ts +0 -2
  43. package/dist/node/tui/index.js +0 -1
  44. package/dist/node/tui-CcH5EsQh.js +0 -25
  45. package/dist/node/tui-CcH5EsQh.js.map +0 -1
  46. package/dist/node/tui-DznRbcku.cjs +0 -24
  47. package/dist/node/ws/index.cjs +0 -1
  48. package/dist/node/ws/index.d.ts +0 -2
  49. package/dist/node/ws/index.js +0 -1
  50. package/dist/node/ws-Dc2RUwVs.js +0 -2
  51. package/dist/node/ws-Dc2RUwVs.js.map +0 -1
  52. package/dist/node/ws-QNMQn5kg.cjs +0 -1
  53. package/src/http/__tests__/http-transport.test.ts +0 -55
  54. package/src/http/__tests__/routes.test.ts +0 -168
  55. package/src/http/http-transport.ts +0 -41
  56. package/src/http/index.ts +0 -4
  57. package/src/http/routes.ts +0 -152
  58. package/src/mcp/__tests__/mcp-server.test.ts +0 -66
  59. package/src/mcp/__tests__/mcp-transport.test.ts +0 -46
  60. package/src/mcp/index.ts +0 -4
  61. package/src/mcp/mcp-server.ts +0 -163
  62. package/src/mcp/mcp-transport.ts +0 -48
  63. package/src/tui/App.tsx +0 -491
  64. package/src/tui/BackgroundTaskPanel.tsx +0 -36
  65. package/src/tui/CjkTextInput.tsx +0 -199
  66. package/src/tui/ConfirmPrompt.tsx +0 -70
  67. package/src/tui/ContextWarningBanner.tsx +0 -34
  68. package/src/tui/ExecutionWorkspaceDetailPane.tsx +0 -64
  69. package/src/tui/ExecutionWorkspaceSwitcher.tsx +0 -187
  70. package/src/tui/InputArea.tsx +0 -310
  71. package/src/tui/InteractivePrompt.tsx +0 -59
  72. package/src/tui/ListPicker.tsx +0 -95
  73. package/src/tui/MenuSelect.tsx +0 -104
  74. package/src/tui/MessageList.tsx +0 -284
  75. package/src/tui/PermissionPrompt.tsx +0 -86
  76. package/src/tui/PluginTUI.tsx +0 -258
  77. package/src/tui/SessionPicker.tsx +0 -68
  78. package/src/tui/SessionStatusBar.tsx +0 -73
  79. package/src/tui/SlashAutocomplete.tsx +0 -110
  80. package/src/tui/StatusBar.tsx +0 -236
  81. package/src/tui/StreamingIndicator.tsx +0 -93
  82. package/src/tui/TextPrompt.tsx +0 -81
  83. package/src/tui/ToolCommandOutput.tsx +0 -39
  84. package/src/tui/ToolDiffBlock.tsx +0 -32
  85. package/src/tui/TransportTUI.tsx +0 -117
  86. package/src/tui/TuiInteractionChannel.ts +0 -495
  87. package/src/tui/UpdateNotice.tsx +0 -14
  88. package/src/tui/UsageSummaryEntry.tsx +0 -39
  89. package/src/tui/WaveText.tsx +0 -44
  90. package/src/tui/__tests__/InteractivePrompt.test.tsx +0 -82
  91. package/src/tui/__tests__/ListPicker.test.tsx +0 -159
  92. package/src/tui/__tests__/MenuSelect.test.tsx +0 -103
  93. package/src/tui/__tests__/PluginTUI.test.tsx +0 -167
  94. package/src/tui/__tests__/SlashAutocomplete.test.tsx +0 -140
  95. package/src/tui/__tests__/TextPrompt.test.tsx +0 -98
  96. package/src/tui/__tests__/TuiInteractionChannel.display-contract.test.ts +0 -239
  97. package/src/tui/__tests__/TuiInteractionChannel.lifecycle.test.ts +0 -297
  98. package/src/tui/__tests__/TuiInteractionChannel.requestAction.test.ts +0 -124
  99. package/src/tui/__tests__/UpdateNotice.test.tsx +0 -15
  100. package/src/tui/__tests__/abort-after-permission.test.tsx +0 -169
  101. package/src/tui/__tests__/abort-streaming-e2e.test.tsx +0 -183
  102. package/src/tui/__tests__/background-task-panel.test.tsx +0 -53
  103. package/src/tui/__tests__/background-task-row-format.test.ts +0 -59
  104. package/src/tui/__tests__/channel-factory-integration.test.ts +0 -138
  105. package/src/tui/__tests__/cjk-text-input-flow.test.ts +0 -109
  106. package/src/tui/__tests__/cjk-text-input.test.ts +0 -191
  107. package/src/tui/__tests__/command-effect-handler.test.ts +0 -127
  108. package/src/tui/__tests__/command-output-summary.test.ts +0 -95
  109. package/src/tui/__tests__/compact-event-bridge.test.ts +0 -20
  110. package/src/tui/__tests__/confirm-permission-flow.test.ts +0 -130
  111. package/src/tui/__tests__/confirm-prompt.test.tsx +0 -87
  112. package/src/tui/__tests__/execution-workspace-switcher.test.tsx +0 -110
  113. package/src/tui/__tests__/execution-workspace-view-model.test.ts +0 -93
  114. package/src/tui/__tests__/fixtures/provider-setup-prompt-driver.tsx +0 -125
  115. package/src/tui/__tests__/input-area-flow.test.ts +0 -164
  116. package/src/tui/__tests__/message-list-rendering.test.tsx +0 -353
  117. package/src/tui/__tests__/prompt-queue.test.tsx +0 -255
  118. package/src/tui/__tests__/provider-setup-pty-e2e.test.ts +0 -233
  119. package/src/tui/__tests__/pty/pty-driver.ts +0 -135
  120. package/src/tui/__tests__/pty/tui-pty.ptytest.ts +0 -61
  121. package/src/tui/__tests__/render-channel-options.test.ts +0 -32
  122. package/src/tui/__tests__/render-markdown.test.ts +0 -72
  123. package/src/tui/__tests__/selection-flow.test.ts +0 -61
  124. package/src/tui/__tests__/session-init-poller.test.ts +0 -102
  125. package/src/tui/__tests__/session-naming.test.ts +0 -64
  126. package/src/tui/__tests__/session-switch-channel.test.tsx +0 -307
  127. package/src/tui/__tests__/slash-routing-effects.test.ts +0 -228
  128. package/src/tui/__tests__/status-activity.test.ts +0 -71
  129. package/src/tui/__tests__/status-bar.test.tsx +0 -177
  130. package/src/tui/__tests__/streaming-indicator.test.tsx +0 -137
  131. package/src/tui/__tests__/text-prompt-flow.test.ts +0 -77
  132. package/src/tui/__tests__/tui-channel-init-failure.test.ts +0 -57
  133. package/src/tui/__tests__/tui-state-manager.test.ts +0 -401
  134. package/src/tui/background-task-row-format.ts +0 -53
  135. package/src/tui/command-interaction.ts +0 -9
  136. package/src/tui/command-output-summary.ts +0 -122
  137. package/src/tui/create-default-tui-cli-adapter.ts +0 -41
  138. package/src/tui/execution-workspace-view-model.ts +0 -123
  139. package/src/tui/flows/cjk-text-input-flow.ts +0 -285
  140. package/src/tui/flows/confirm-prompt-flow.ts +0 -45
  141. package/src/tui/flows/input-area-flow.ts +0 -189
  142. package/src/tui/flows/permission-prompt-flow.ts +0 -85
  143. package/src/tui/flows/selection-flow.ts +0 -126
  144. package/src/tui/flows/session-init-poller.ts +0 -77
  145. package/src/tui/flows/text-prompt-flow.ts +0 -98
  146. package/src/tui/hooks/command-effect-handler.ts +0 -97
  147. package/src/tui/hooks/command-effect-queue.ts +0 -39
  148. package/src/tui/hooks/side-effects-types.ts +0 -35
  149. package/src/tui/hooks/useAutocomplete.ts +0 -87
  150. package/src/tui/hooks/usePluginCallbacks.ts +0 -31
  151. package/src/tui/hooks/usePluginScreenData.ts +0 -85
  152. package/src/tui/hooks/useSideEffects.ts +0 -175
  153. package/src/tui/hooks/useSlashRouting.ts +0 -118
  154. package/src/tui/hooks/useStatusLineSettings.ts +0 -37
  155. package/src/tui/hooks/useTuiChannel.ts +0 -95
  156. package/src/tui/index.ts +0 -14
  157. package/src/tui/interactions/CommandConfirm.tsx +0 -36
  158. package/src/tui/interactions/CommandPicker.tsx +0 -77
  159. package/src/tui/interactions/__tests__/CommandConfirm.test.tsx +0 -124
  160. package/src/tui/interactions/__tests__/CommandPicker.test.tsx +0 -138
  161. package/src/tui/plugin-tui-handlers.ts +0 -163
  162. package/src/tui/render-markdown.ts +0 -130
  163. package/src/tui/render.tsx +0 -129
  164. package/src/tui/session-naming.ts +0 -33
  165. package/src/tui/status-activity.ts +0 -63
  166. package/src/tui/tui-cli-adapter-context.tsx +0 -13
  167. package/src/tui/tui-cli-adapter.ts +0 -25
  168. package/src/tui/tui-state-manager.ts +0 -226
  169. package/src/tui/tui-transport.ts +0 -35
  170. package/src/tui/types.ts +0 -15
  171. package/src/tui/utils/__tests__/edit-diff.test.ts +0 -426
  172. package/src/tui/utils/__tests__/paste-detection.test.ts +0 -116
  173. package/src/tui/utils/__tests__/paste-labels.test.ts +0 -46
  174. package/src/tui/utils/__tests__/tool-call-extractor.test.ts +0 -227
  175. package/src/tui/utils/__tests__/tool-diff-summary.test.ts +0 -104
  176. package/src/tui/utils/edit-diff.ts +0 -153
  177. package/src/tui/utils/paste-labels.ts +0 -9
  178. package/src/tui/utils/tool-call-extractor.ts +0 -92
  179. package/src/tui/utils/tool-diff-summary.ts +0 -75
  180. package/src/ws/__tests__/ws-handler.test.ts +0 -409
  181. package/src/ws/__tests__/ws-transport.test.ts +0 -53
  182. package/src/ws/index.ts +0 -13
  183. package/src/ws/ws-background-messages.ts +0 -170
  184. package/src/ws/ws-handler.ts +0 -280
  185. package/src/ws/ws-protocol.ts +0 -78
  186. package/src/ws/ws-transport-configurable.ts +0 -128
  187. package/src/ws/ws-transport.ts +0 -42
@@ -1,124 +0,0 @@
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
- });
@@ -1,138 +0,0 @@
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
- });
@@ -1,163 +0,0 @@
1
- /**
2
- * Screen-specific selection handlers for PluginTUI.
3
- * Extracted to keep PluginTUI.tsx under 300 lines.
4
- */
5
-
6
- import type { IMenuSelectItem } from './MenuSelect.js';
7
- import type { ICommandPluginAdapter } from '@robota-sdk/agent-interface-transport';
8
-
9
- interface IConfirmState {
10
- message: string;
11
- onConfirm: () => void;
12
- onCancel: () => void;
13
- }
14
-
15
- interface IMenuContext {
16
- marketplace?: string;
17
- pluginId?: string;
18
- }
19
-
20
- interface INavActions {
21
- push: (state: { screen: string; context?: IMenuContext }) => void;
22
- pop: () => void;
23
- popN: (n: number) => void;
24
- notify: (content: string) => void;
25
- setConfirm: (state: IConfirmState | undefined) => void;
26
- refresh: () => void;
27
- }
28
-
29
- export function handleMainSelect(value: string, nav: Pick<INavActions, 'push'>): void {
30
- if (value === 'marketplace') {
31
- nav.push({ screen: 'marketplace-list' });
32
- } else if (value === 'installed') {
33
- nav.push({ screen: 'installed-list' });
34
- }
35
- }
36
-
37
- export function handleMarketplaceListSelect(value: string, nav: Pick<INavActions, 'push'>): void {
38
- if (value === '__add__') {
39
- nav.push({ screen: 'marketplace-add' });
40
- } else {
41
- nav.push({ screen: 'marketplace-action', context: { marketplace: value } });
42
- }
43
- }
44
-
45
- export function handleMarketplaceActionSelect(
46
- value: string,
47
- marketplace: string,
48
- callbacks: ICommandPluginAdapter,
49
- nav: Pick<INavActions, 'push' | 'pop' | 'popN' | 'notify' | 'setConfirm'>,
50
- ): void {
51
- if (value === 'browse') {
52
- nav.push({ screen: 'marketplace-browse', context: { marketplace } });
53
- } else if (value === 'update') {
54
- callbacks
55
- .marketplaceUpdate(marketplace)
56
- .then(() => {
57
- nav.notify(`Updated marketplace "${marketplace}".`);
58
- nav.pop();
59
- })
60
- .catch((err) => {
61
- nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
62
- });
63
- } else if (value === 'remove') {
64
- nav.setConfirm({
65
- message: `Remove marketplace "${marketplace}" and all its plugins?`,
66
- onConfirm: () => {
67
- nav.setConfirm(undefined);
68
- callbacks
69
- .marketplaceRemove(marketplace)
70
- .then(() => {
71
- nav.notify(`Removed marketplace "${marketplace}".`);
72
- nav.popN(2);
73
- })
74
- .catch((err) => {
75
- nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
76
- });
77
- },
78
- onCancel: () => nav.setConfirm(undefined),
79
- });
80
- }
81
- }
82
-
83
- export function handleMarketplaceBrowseSelect(
84
- value: string,
85
- marketplace: string,
86
- items: IMenuSelectItem[],
87
- nav: Pick<INavActions, 'push'>,
88
- ): void {
89
- const fullId = `${value}@${marketplace}`;
90
- const item = items.find((i) => i.value === value);
91
- if (item?.hint === 'installed') {
92
- nav.push({ screen: 'installed-action', context: { pluginId: fullId } });
93
- } else {
94
- nav.push({ screen: 'marketplace-install-scope', context: { marketplace, pluginId: fullId } });
95
- }
96
- }
97
-
98
- export function handleInstallScopeSelect(
99
- value: string,
100
- pluginId: string,
101
- callbacks: ICommandPluginAdapter,
102
- nav: Pick<INavActions, 'popN' | 'notify'>,
103
- ): void {
104
- const scope = value as 'user' | 'project';
105
- callbacks
106
- .install(pluginId, scope)
107
- .then(() => {
108
- nav.notify(`Installed plugin "${pluginId}" (${scope} scope).`);
109
- nav.popN(2);
110
- })
111
- .catch((err) => {
112
- nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
113
- });
114
- }
115
-
116
- export function handleInstalledListSelect(
117
- value: string,
118
- callbacks: ICommandPluginAdapter,
119
- nav: Pick<INavActions, 'notify' | 'setConfirm' | 'refresh'>,
120
- ): void {
121
- nav.setConfirm({
122
- message: `Uninstall plugin "${value}"?`,
123
- onConfirm: () => {
124
- nav.setConfirm(undefined);
125
- callbacks
126
- .uninstall(value)
127
- .then(() => {
128
- nav.notify(`Uninstalled plugin "${value}".`);
129
- nav.refresh();
130
- })
131
- .catch((err) => {
132
- nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
133
- });
134
- },
135
- onCancel: () => nav.setConfirm(undefined),
136
- });
137
- }
138
-
139
- export function handleInstalledActionSelect(
140
- value: string,
141
- pluginId: string,
142
- callbacks: ICommandPluginAdapter,
143
- nav: Pick<INavActions, 'popN' | 'notify' | 'setConfirm'>,
144
- ): void {
145
- if (value === 'uninstall') {
146
- nav.setConfirm({
147
- message: `Uninstall plugin "${pluginId}"?`,
148
- onConfirm: () => {
149
- nav.setConfirm(undefined);
150
- callbacks
151
- .uninstall(pluginId)
152
- .then(() => {
153
- nav.notify(`Uninstalled plugin "${pluginId}".`);
154
- nav.popN(2);
155
- })
156
- .catch((err) => {
157
- nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
158
- });
159
- },
160
- onCancel: () => nav.setConfirm(undefined),
161
- });
162
- }
163
- }
@@ -1,130 +0,0 @@
1
- import { marked } from 'marked';
2
- // @ts-expect-error — marked-terminal has no type declarations
3
- import TerminalRenderer from 'marked-terminal';
4
-
5
- import type { Renderer } from 'marked';
6
-
7
- const ANSI_LIGHT_RED = '\u001b[38;5;210m';
8
- const ANSI_LIGHT_GREEN = '\u001b[38;5;120m';
9
- const ANSI_CYAN = '\u001b[36m';
10
- const ANSI_DIM = '\u001b[2m';
11
- const ANSI_DARK_RED_BACKGROUND = '\u001b[48;5;52m';
12
- const ANSI_DARK_GREEN_BACKGROUND = '\u001b[48;5;22m';
13
- const ANSI_RESET = '\u001b[0m';
14
- const CODE_BLOCK_INDENT = ' ';
15
- const ZERO_COLOR = '0';
16
-
17
- interface IRenderMarkdownOptions {
18
- color?: boolean;
19
- codeBlockWidth?: number;
20
- }
21
-
22
- interface ITerminalRendererOptions {
23
- code?: (text: string) => string;
24
- }
25
-
26
- interface IHighlightOptions {
27
- ignoreIllegals?: boolean;
28
- }
29
-
30
- type TTerminalRendererConstructor = new (
31
- options?: ITerminalRendererOptions,
32
- highlightOptions?: IHighlightOptions,
33
- ) => Renderer;
34
-
35
- const TerminalRendererConstructor = TerminalRenderer as TTerminalRendererConstructor;
36
-
37
- function shouldUseColor(option: boolean | undefined): boolean {
38
- if (option !== undefined) {
39
- return option;
40
- }
41
- if (process.env.NO_COLOR || process.env.FORCE_COLOR === ZERO_COLOR) {
42
- return false;
43
- }
44
- if (process.env.FORCE_COLOR) {
45
- return true;
46
- }
47
- return Boolean(process.stdout.isTTY);
48
- }
49
-
50
- function isDiffLanguage(language: string | undefined): boolean {
51
- return language?.trim().toLowerCase() === 'diff';
52
- }
53
-
54
- function styleAddedOrRemovedDiffRow(line: string, rowWidth: number, color: boolean): string {
55
- const row = `${CODE_BLOCK_INDENT}${line}`.padEnd(rowWidth);
56
- if (!color) {
57
- return row.trimEnd();
58
- }
59
- if (line.startsWith('+')) {
60
- return `${ANSI_DARK_GREEN_BACKGROUND}${ANSI_LIGHT_GREEN}${row}${ANSI_RESET}`;
61
- }
62
- if (line.startsWith('-')) {
63
- return `${ANSI_DARK_RED_BACKGROUND}${ANSI_LIGHT_RED}${row}${ANSI_RESET}`;
64
- }
65
- return row.trimEnd();
66
- }
67
-
68
- function colorizeDiffLine(line: string, color: boolean, rowWidth: number): string {
69
- if (line.startsWith('+') || line.startsWith('-')) {
70
- return styleAddedOrRemovedDiffRow(line, rowWidth, color);
71
- }
72
- const row = `${CODE_BLOCK_INDENT}${line}`;
73
- if (!color) {
74
- return row;
75
- }
76
- if (line.startsWith('@@')) {
77
- return `${ANSI_CYAN}${row}${ANSI_RESET}`;
78
- }
79
- if (line.startsWith('diff ') || line.startsWith('index ')) {
80
- return `${ANSI_DIM}${row}${ANSI_RESET}`;
81
- }
82
- return row;
83
- }
84
-
85
- function resolveDiffRowWidth(lines: readonly string[], requestedWidth: number | undefined): number {
86
- const minimumWidth = lines.reduce(
87
- (maxWidth, line) => Math.max(maxWidth, CODE_BLOCK_INDENT.length + line.length),
88
- 0,
89
- );
90
- if (requestedWidth === undefined) {
91
- return minimumWidth;
92
- }
93
- return Math.max(minimumWidth, requestedWidth);
94
- }
95
-
96
- function renderDiffCodeBlock(
97
- code: string,
98
- color: boolean,
99
- codeBlockWidth: number | undefined,
100
- ): string {
101
- const lines = code.split('\n');
102
- const rowWidth = resolveDiffRowWidth(lines, codeBlockWidth);
103
- const body = lines.map((line) => colorizeDiffLine(line, color, rowWidth)).join('\n');
104
- return `${body}\n\n`;
105
- }
106
-
107
- function createTerminalRenderer(color: boolean, codeBlockWidth: number | undefined): Renderer {
108
- const renderer = new TerminalRendererConstructor(undefined, { ignoreIllegals: true });
109
- const renderCode = renderer.code.bind(renderer);
110
-
111
- renderer.code = (code: string, language: string | undefined, escaped: boolean): string => {
112
- if (isDiffLanguage(language)) {
113
- return renderDiffCodeBlock(code, color, codeBlockWidth);
114
- }
115
- return renderCode(code, language, escaped);
116
- };
117
-
118
- return renderer;
119
- }
120
-
121
- /**
122
- * Render markdown to a terminal-formatted string with colors, bold, etc.
123
- * Returns the rendered string (may include ANSI escape codes).
124
- */
125
- export function renderMarkdown(md: string, options: IRenderMarkdownOptions = {}): string {
126
- const result = marked.parse(md, {
127
- renderer: createTerminalRenderer(shouldUseColor(options.color), options.codeBlockWidth),
128
- });
129
- return typeof result === 'string' ? result.trimEnd() : md;
130
- }
@@ -1,129 +0,0 @@
1
- /**
2
- * Ink render entry point.
3
- */
4
-
5
- import { render } from 'ink';
6
- import React from 'react';
7
-
8
- import App from './App.js';
9
- import { TuiInteractionChannel } from './TuiInteractionChannel.js';
10
-
11
- import type { ITuiCliAdapter } from './tui-cli-adapter.js';
12
- import type { IAIProvider } from '@robota-sdk/agent-core';
13
- import type { TPermissionMode } from '@robota-sdk/agent-core';
14
- import type {
15
- IBackgroundTaskRunner,
16
- ICommandHostAdapters,
17
- ICommandModule,
18
- TSubagentRunnerFactory,
19
- TShellExecFn,
20
- CommandRegistry,
21
- } from '@robota-sdk/agent-framework';
22
- import type {
23
- IInteractiveSession,
24
- IInteractiveSessionStore,
25
- ITransportRegistryView,
26
- } from '@robota-sdk/agent-interface-transport';
27
-
28
- export interface IRenderOptions {
29
- cwd: string;
30
- provider: IAIProvider;
31
- providerOverride?: string | undefined;
32
- providerType?: string | undefined;
33
- modelId?: string;
34
- language?: string;
35
- permissionMode?: TPermissionMode;
36
- maxTurns?: number;
37
- allowedTools?: string[];
38
- deniedTools?: string[];
39
- version?: string;
40
- sessionStore?: IInteractiveSessionStore;
41
- resumeSessionId?: string;
42
- showSessionPickerOnStart?: boolean;
43
- forkSession?: boolean;
44
- sessionName?: string;
45
- backgroundTaskRunners?: IBackgroundTaskRunner[];
46
- subagentRunnerFactory?: TSubagentRunnerFactory;
47
- commandModules?: readonly ICommandModule[];
48
- commandHostAdapters?: ICommandHostAdapters;
49
- shellExec?: TShellExecFn;
50
- startupUpdateNotice?: Promise<string | undefined>;
51
- transportRegistry?: ITransportRegistryView<IInteractiveSession>;
52
- cliAdapter: ITuiCliAdapter;
53
- reloadPluginCommandSource?: (registry: CommandRegistry) => void;
54
- agentName?: string;
55
- /** Active preset id selected at startup (PRESET-011 runtime state). Defaults to 'default'. */
56
- activePresetId?: string;
57
- /** Preset persona block composed as a `source: 'persona'` system-prompt section (priority 5). */
58
- persona?: string;
59
- /** Preset execution capability: activate agent runtime + subagent/background dispatch. */
60
- enableParallelSubagents?: boolean;
61
- /** Preset execution capability: run a post-task self-verification step. */
62
- selfVerification?: boolean;
63
- }
64
-
65
- /** Map render options to TuiInteractionChannel constructor options. */
66
- export function toChannelOptions(
67
- options: IRenderOptions,
68
- resumeSessionId?: string,
69
- ): ConstructorParameters<typeof TuiInteractionChannel>[0] {
70
- return {
71
- cwd: options.cwd,
72
- provider: options.provider,
73
- permissionMode: options.permissionMode,
74
- maxTurns: options.maxTurns,
75
- allowedTools: options.allowedTools,
76
- deniedTools: options.deniedTools,
77
- sessionStore: options.sessionStore,
78
- resumeSessionId,
79
- forkSession: options.forkSession,
80
- sessionName: options.sessionName,
81
- backgroundTaskRunners: options.backgroundTaskRunners,
82
- subagentRunnerFactory: options.subagentRunnerFactory,
83
- commandModules: options.commandModules,
84
- commandHostAdapters: options.commandHostAdapters,
85
- shellExec: options.shellExec,
86
- transportRegistry: options.transportRegistry,
87
- language: options.language,
88
- reloadPluginCommandSource: options.reloadPluginCommandSource,
89
- agentName: options.agentName,
90
- activePresetId: options.activePresetId,
91
- persona: options.persona,
92
- enableParallelSubagents: options.enableParallelSubagents,
93
- selfVerification: options.selfVerification,
94
- };
95
- }
96
-
97
- export async function renderApp(options: IRenderOptions): Promise<void> {
98
- process.on('unhandledRejection', (reason) => {
99
- process.stderr.write(`\n[UNHANDLED REJECTION] ${reason}\n`);
100
- if (reason instanceof Error) {
101
- process.stderr.write(`${reason.stack}\n`);
102
- }
103
- });
104
-
105
- // Single-owner lifecycle (CLI-B12): render.tsx supplies only the factory;
106
- // App creates, replaces, and stops channels exclusively through React state.
107
- const createChannel = (resumeSessionId?: string): TuiInteractionChannel =>
108
- new TuiInteractionChannel(toChannelOptions(options, resumeSessionId));
109
-
110
- const instance = render(
111
- <App
112
- cwd={options.cwd}
113
- createChannel={createChannel}
114
- providerOverride={options.providerOverride}
115
- providerType={options.providerType}
116
- modelId={options.modelId}
117
- permissionMode={options.permissionMode}
118
- version={options.version}
119
- sessionStore={options.sessionStore}
120
- resumeSessionId={options.resumeSessionId}
121
- showSessionPickerOnStart={options.showSessionPickerOnStart}
122
- startupUpdateNotice={options.startupUpdateNotice}
123
- transportRegistry={options.transportRegistry}
124
- cliAdapter={options.cliAdapter}
125
- />,
126
- { exitOnCtrlC: false },
127
- );
128
- await instance.waitUntilExit();
129
- }