btcp-browser-agent 0.1.0 → 0.1.2

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 (136) hide show
  1. package/package.json +8 -9
  2. package/packages/core/dist/actions.d.ts +97 -0
  3. package/packages/core/dist/actions.js +940 -0
  4. package/packages/core/dist/errors.d.ts +138 -0
  5. package/packages/core/dist/errors.js +157 -0
  6. package/packages/core/dist/index.d.ts +120 -0
  7. package/packages/core/dist/index.js +134 -0
  8. package/packages/core/dist/ref-map.d.ts +16 -0
  9. package/packages/core/dist/ref-map.js +91 -0
  10. package/packages/core/dist/snapshot.d.ts +37 -0
  11. package/packages/core/dist/snapshot.js +751 -0
  12. package/packages/core/dist/types.d.ts +396 -0
  13. package/packages/core/dist/types.js +7 -0
  14. package/packages/extension/dist/background.d.ts +227 -0
  15. package/packages/extension/dist/background.js +737 -0
  16. package/packages/extension/dist/content.d.ts +18 -0
  17. package/packages/extension/dist/content.js +149 -0
  18. package/packages/extension/dist/index.d.ts +228 -0
  19. package/packages/extension/dist/index.js +350 -0
  20. package/packages/extension/dist/session-manager.d.ts +87 -0
  21. package/packages/extension/dist/session-manager.js +322 -0
  22. package/packages/extension/{src/session-types.ts → dist/session-types.d.ts} +113 -144
  23. package/packages/extension/dist/session-types.js +5 -0
  24. package/packages/extension/dist/types.d.ts +88 -0
  25. package/packages/extension/dist/types.js +7 -0
  26. package/CLAUDE.md +0 -230
  27. package/SKILL.md +0 -143
  28. package/SNAPSHOT_IMPROVEMENTS.md +0 -302
  29. package/USAGE.md +0 -146
  30. package/dist/index.d.ts.map +0 -1
  31. package/dist/index.js.map +0 -1
  32. package/docs/browser-cli-design.md +0 -500
  33. package/examples/chrome-extension/CHANGELOG.md +0 -210
  34. package/examples/chrome-extension/DEBUG.md +0 -231
  35. package/examples/chrome-extension/ERROR_FIXED.md +0 -147
  36. package/examples/chrome-extension/QUICK_TEST.md +0 -189
  37. package/examples/chrome-extension/README.md +0 -149
  38. package/examples/chrome-extension/SESSION_ONLY_MODE.md +0 -305
  39. package/examples/chrome-extension/TEST_WITH_YOUR_TABS.md +0 -97
  40. package/examples/chrome-extension/build.js +0 -43
  41. package/examples/chrome-extension/manifest.json +0 -37
  42. package/examples/chrome-extension/package-lock.json +0 -1063
  43. package/examples/chrome-extension/package.json +0 -21
  44. package/examples/chrome-extension/popup.html +0 -195
  45. package/examples/chrome-extension/src/background.ts +0 -12
  46. package/examples/chrome-extension/src/content.ts +0 -7
  47. package/examples/chrome-extension/src/popup.ts +0 -303
  48. package/examples/chrome-extension/src/scenario-google-github.ts +0 -389
  49. package/examples/chrome-extension/test-page.html +0 -127
  50. package/examples/chrome-extension/tests/README.md +0 -206
  51. package/examples/chrome-extension/tests/scenario-google-to-github-star.ts +0 -380
  52. package/examples/chrome-extension/tsconfig.json +0 -14
  53. package/examples/snapshots/README.md +0 -207
  54. package/examples/snapshots/amazon-com-detail.html +0 -9528
  55. package/examples/snapshots/amazon-com-detail.snapshot.txt +0 -997
  56. package/examples/snapshots/convert-snapshots.ts +0 -97
  57. package/examples/snapshots/edition-cnn-com.html +0 -13292
  58. package/examples/snapshots/edition-cnn-com.snapshot.txt +0 -562
  59. package/examples/snapshots/github-com-microsoft-vscode.html +0 -2916
  60. package/examples/snapshots/github-com-microsoft-vscode.snapshot.txt +0 -455
  61. package/examples/snapshots/google-search.html +0 -20012
  62. package/examples/snapshots/google-search.snapshot.txt +0 -195
  63. package/examples/snapshots/metadata.json +0 -86
  64. package/examples/snapshots/npr-org-templates.html +0 -2031
  65. package/examples/snapshots/npr-org-templates.snapshot.txt +0 -224
  66. package/examples/snapshots/stackoverflow-com.html +0 -5216
  67. package/examples/snapshots/stackoverflow-com.snapshot.txt +0 -2404
  68. package/examples/snapshots/test-all-mode.html +0 -46
  69. package/examples/snapshots/test-all-mode.snapshot.txt +0 -5
  70. package/examples/snapshots/validate.test.ts +0 -296
  71. package/packages/cli/package.json +0 -42
  72. package/packages/cli/src/__tests__/cli.test.ts +0 -434
  73. package/packages/cli/src/__tests__/errors.test.ts +0 -226
  74. package/packages/cli/src/__tests__/executor.test.ts +0 -275
  75. package/packages/cli/src/__tests__/formatter.test.ts +0 -260
  76. package/packages/cli/src/__tests__/parser.test.ts +0 -288
  77. package/packages/cli/src/__tests__/suggestions.test.ts +0 -255
  78. package/packages/cli/src/commands/back.ts +0 -22
  79. package/packages/cli/src/commands/check.ts +0 -33
  80. package/packages/cli/src/commands/clear.ts +0 -33
  81. package/packages/cli/src/commands/click.ts +0 -32
  82. package/packages/cli/src/commands/closetab.ts +0 -31
  83. package/packages/cli/src/commands/eval.ts +0 -41
  84. package/packages/cli/src/commands/fill.ts +0 -30
  85. package/packages/cli/src/commands/focus.ts +0 -33
  86. package/packages/cli/src/commands/forward.ts +0 -22
  87. package/packages/cli/src/commands/goto.ts +0 -34
  88. package/packages/cli/src/commands/help.ts +0 -162
  89. package/packages/cli/src/commands/hover.ts +0 -34
  90. package/packages/cli/src/commands/index.ts +0 -129
  91. package/packages/cli/src/commands/newtab.ts +0 -35
  92. package/packages/cli/src/commands/press.ts +0 -40
  93. package/packages/cli/src/commands/reload.ts +0 -25
  94. package/packages/cli/src/commands/screenshot.ts +0 -27
  95. package/packages/cli/src/commands/scroll.ts +0 -64
  96. package/packages/cli/src/commands/select.ts +0 -35
  97. package/packages/cli/src/commands/snapshot.ts +0 -21
  98. package/packages/cli/src/commands/tab.ts +0 -32
  99. package/packages/cli/src/commands/tabs.ts +0 -26
  100. package/packages/cli/src/commands/text.ts +0 -27
  101. package/packages/cli/src/commands/title.ts +0 -17
  102. package/packages/cli/src/commands/type.ts +0 -38
  103. package/packages/cli/src/commands/uncheck.ts +0 -33
  104. package/packages/cli/src/commands/url.ts +0 -17
  105. package/packages/cli/src/commands/wait.ts +0 -54
  106. package/packages/cli/src/errors.ts +0 -164
  107. package/packages/cli/src/executor.ts +0 -68
  108. package/packages/cli/src/formatter.ts +0 -215
  109. package/packages/cli/src/index.ts +0 -257
  110. package/packages/cli/src/parser.ts +0 -195
  111. package/packages/cli/src/suggestions.ts +0 -207
  112. package/packages/cli/src/terminal/Terminal.ts +0 -365
  113. package/packages/cli/src/terminal/index.ts +0 -5
  114. package/packages/cli/src/types.ts +0 -155
  115. package/packages/cli/tsconfig.json +0 -20
  116. package/packages/core/package.json +0 -35
  117. package/packages/core/src/actions.ts +0 -1210
  118. package/packages/core/src/errors.ts +0 -296
  119. package/packages/core/src/index.test.ts +0 -638
  120. package/packages/core/src/index.ts +0 -220
  121. package/packages/core/src/ref-map.ts +0 -107
  122. package/packages/core/src/snapshot.ts +0 -873
  123. package/packages/core/src/types.ts +0 -536
  124. package/packages/core/tsconfig.json +0 -23
  125. package/packages/extension/README.md +0 -129
  126. package/packages/extension/package.json +0 -43
  127. package/packages/extension/src/background.ts +0 -888
  128. package/packages/extension/src/content.ts +0 -172
  129. package/packages/extension/src/index.ts +0 -579
  130. package/packages/extension/src/session-manager.ts +0 -385
  131. package/packages/extension/src/types.ts +0 -162
  132. package/packages/extension/tsconfig.json +0 -28
  133. package/src/index.ts +0 -64
  134. package/tsconfig.build.json +0 -12
  135. package/tsconfig.json +0 -26
  136. package/vitest.config.ts +0 -13
@@ -1,207 +0,0 @@
1
- /**
2
- * @btcp/cli - Command suggestions and fuzzy matching
3
- *
4
- * Helps users self-correct typos and discover commands.
5
- */
6
-
7
- import { commands } from './commands/index.js';
8
-
9
- /**
10
- * Calculate Levenshtein distance between two strings
11
- */
12
- function levenshteinDistance(a: string, b: string): number {
13
- const matrix: number[][] = [];
14
-
15
- for (let i = 0; i <= b.length; i++) {
16
- matrix[i] = [i];
17
- }
18
- for (let j = 0; j <= a.length; j++) {
19
- matrix[0][j] = j;
20
- }
21
-
22
- for (let i = 1; i <= b.length; i++) {
23
- for (let j = 1; j <= a.length; j++) {
24
- if (b.charAt(i - 1) === a.charAt(j - 1)) {
25
- matrix[i][j] = matrix[i - 1][j - 1];
26
- } else {
27
- matrix[i][j] = Math.min(
28
- matrix[i - 1][j - 1] + 1, // substitution
29
- matrix[i][j - 1] + 1, // insertion
30
- matrix[i - 1][j] + 1 // deletion
31
- );
32
- }
33
- }
34
- }
35
-
36
- return matrix[b.length][a.length];
37
- }
38
-
39
- /**
40
- * Find similar commands to the given input
41
- */
42
- export function findSimilarCommands(input: string, maxSuggestions = 3): string[] {
43
- const inputLower = input.toLowerCase();
44
- const commandNames = Object.keys(commands);
45
-
46
- // Calculate distances and filter
47
- const scored = commandNames
48
- .map((name) => ({
49
- name,
50
- distance: levenshteinDistance(inputLower, name),
51
- startsWith: name.startsWith(inputLower),
52
- contains: name.includes(inputLower),
53
- }))
54
- .filter((item) => {
55
- // Only suggest if reasonably close
56
- const maxDistance = Math.max(2, Math.floor(input.length / 2));
57
- return item.distance <= maxDistance || item.startsWith || item.contains;
58
- })
59
- .sort((a, b) => {
60
- // Prioritize: startsWith > contains > distance
61
- if (a.startsWith && !b.startsWith) return -1;
62
- if (!a.startsWith && b.startsWith) return 1;
63
- if (a.contains && !b.contains) return -1;
64
- if (!a.contains && b.contains) return 1;
65
- return a.distance - b.distance;
66
- });
67
-
68
- return scored.slice(0, maxSuggestions).map((item) => item.name);
69
- }
70
-
71
- /**
72
- * Get contextual suggestions based on command and error
73
- */
74
- export function getContextualSuggestion(
75
- commandName: string,
76
- error: string,
77
- args: string[]
78
- ): string | null {
79
- const errorLower = error.toLowerCase();
80
-
81
- // Selector not found
82
- if (errorLower.includes('not found') || errorLower.includes('no element')) {
83
- return `Element not found. Try:\n 1. Run 'snapshot' to see available elements with @ref IDs\n 2. Use a different selector or wait for the element: 'wait ${args[0] || '<selector>'} --state visible'`;
84
- }
85
-
86
- // Invalid selector
87
- if (errorLower.includes('selector') || errorLower.includes('invalid')) {
88
- return `Invalid selector. Supported formats:\n - @ref:5 (from snapshot)\n - #id (CSS ID selector)\n - .class (CSS class selector)\n - button, input (tag names)`;
89
- }
90
-
91
- // Navigation errors
92
- if (errorLower.includes('navigate') || errorLower.includes('url')) {
93
- return `Navigation failed. Make sure:\n 1. URL includes protocol (https://)\n 2. The page is accessible\n 3. Try: 'goto https://example.com'`;
94
- }
95
-
96
- // Timeout
97
- if (errorLower.includes('timeout')) {
98
- return `Operation timed out. Try:\n 1. Increase wait time: 'wait 5000'\n 2. Check if element exists: 'snapshot'\n 3. Wait for specific state: 'wait ${args[0] || '<selector>'} --state visible'`;
99
- }
100
-
101
- // Permission/security
102
- if (errorLower.includes('permission') || errorLower.includes('security') || errorLower.includes('blocked')) {
103
- return `Action blocked. This may be due to:\n 1. Cross-origin restrictions\n 2. Browser security policies\n 3. The element may be in an iframe`;
104
- }
105
-
106
- return null;
107
- }
108
-
109
- /**
110
- * Command categories for organized help
111
- */
112
- export const commandCategories = {
113
- navigation: {
114
- name: 'Navigation',
115
- description: 'Navigate between pages and control browser history',
116
- commands: ['goto', 'back', 'forward', 'reload', 'url', 'title'],
117
- },
118
- inspection: {
119
- name: 'Page Inspection',
120
- description: 'Inspect page content and capture screenshots',
121
- commands: ['snapshot', 'screenshot', 'text'],
122
- },
123
- interaction: {
124
- name: 'Element Interaction',
125
- description: 'Click, type, and interact with page elements',
126
- commands: ['click', 'type', 'fill', 'clear', 'hover', 'focus', 'press'],
127
- },
128
- forms: {
129
- name: 'Form Controls',
130
- description: 'Work with form inputs like checkboxes and dropdowns',
131
- commands: ['check', 'uncheck', 'select'],
132
- },
133
- scrolling: {
134
- name: 'Scrolling',
135
- description: 'Scroll the page or scroll elements into view',
136
- commands: ['scroll'],
137
- },
138
- tabs: {
139
- name: 'Tab Management',
140
- description: 'Manage browser tabs',
141
- commands: ['tabs', 'tab', 'newtab', 'closetab'],
142
- },
143
- utility: {
144
- name: 'Utility',
145
- description: 'Wait, evaluate JavaScript, and get help',
146
- commands: ['wait', 'eval', 'help'],
147
- },
148
- };
149
-
150
- /**
151
- * Get category for a command
152
- */
153
- export function getCommandCategory(commandName: string): string | null {
154
- for (const [key, category] of Object.entries(commandCategories)) {
155
- if (category.commands.includes(commandName)) {
156
- return key;
157
- }
158
- }
159
- return null;
160
- }
161
-
162
- /**
163
- * Common workflow suggestions
164
- */
165
- export const workflowSuggestions = {
166
- afterNavigation: [
167
- 'snapshot # See page structure and get element refs',
168
- 'screenshot # Capture visual state',
169
- 'wait 1000 # Wait for page to settle',
170
- ],
171
- afterSnapshot: [
172
- 'click @ref:N # Click an element from snapshot',
173
- 'type @ref:N "..." # Type into an input',
174
- 'fill @ref:N "..." # Fill an input field',
175
- ],
176
- afterClick: [
177
- 'snapshot # See updated page state',
178
- 'wait 500 # Wait for animations/updates',
179
- ],
180
- afterError: [
181
- 'snapshot # Check current page state',
182
- 'url # Verify current URL',
183
- 'tabs # Check open tabs',
184
- ],
185
- };
186
-
187
- /**
188
- * Get next step suggestions based on last command
189
- */
190
- export function getNextStepSuggestions(lastCommand: string): string[] {
191
- switch (lastCommand) {
192
- case 'goto':
193
- case 'reload':
194
- case 'back':
195
- case 'forward':
196
- return workflowSuggestions.afterNavigation;
197
- case 'snapshot':
198
- return workflowSuggestions.afterSnapshot;
199
- case 'click':
200
- case 'type':
201
- case 'fill':
202
- case 'press':
203
- return workflowSuggestions.afterClick;
204
- default:
205
- return [];
206
- }
207
- }
@@ -1,365 +0,0 @@
1
- /**
2
- * Terminal UI Component
3
- *
4
- * An in-browser terminal interface for the CLI.
5
- */
6
-
7
- import type { HistoryEntry, TerminalConfig, CommandResult } from '../types.js';
8
- import { formatResult } from '../formatter.js';
9
-
10
- /**
11
- * Terminal options
12
- */
13
- export interface TerminalOptions {
14
- /** Execute a command and return the result */
15
- onExecute: (input: string) => Promise<CommandResult>;
16
- /** Optional configuration */
17
- config?: Partial<TerminalConfig>;
18
- }
19
-
20
- /**
21
- * Default terminal configuration
22
- */
23
- const defaultConfig: TerminalConfig = {
24
- theme: 'dark',
25
- fontSize: 14,
26
- historySize: 1000,
27
- prompt: '$ ',
28
- };
29
-
30
- /**
31
- * Terminal state
32
- */
33
- interface TerminalState {
34
- history: HistoryEntry[];
35
- commandHistory: string[];
36
- historyIndex: number;
37
- inputBuffer: string;
38
- isExecuting: boolean;
39
- }
40
-
41
- /**
42
- * Terminal UI class
43
- */
44
- export class Terminal {
45
- private container: HTMLElement;
46
- private config: TerminalConfig;
47
- private state: TerminalState;
48
- private onExecute: (input: string) => Promise<CommandResult>;
49
-
50
- // DOM elements
51
- private outputEl!: HTMLElement;
52
- private inputLineEl!: HTMLElement;
53
- private promptEl!: HTMLElement;
54
- private inputEl!: HTMLInputElement;
55
-
56
- constructor(container: HTMLElement, options: TerminalOptions) {
57
- this.container = container;
58
- this.config = { ...defaultConfig, ...options.config };
59
- this.onExecute = options.onExecute;
60
-
61
- this.state = {
62
- history: [],
63
- commandHistory: [],
64
- historyIndex: -1,
65
- inputBuffer: '',
66
- isExecuting: false,
67
- };
68
-
69
- this.render();
70
- this.bindEvents();
71
- this.focus();
72
- }
73
-
74
- /**
75
- * Render the terminal UI
76
- */
77
- private render(): void {
78
- const isDark = this.config.theme === 'dark';
79
-
80
- this.container.innerHTML = `
81
- <div class="btcp-terminal" style="
82
- font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', monospace;
83
- font-size: ${this.config.fontSize}px;
84
- line-height: 1.4;
85
- background: ${isDark ? '#1e1e1e' : '#ffffff'};
86
- color: ${isDark ? '#d4d4d4' : '#1e1e1e'};
87
- padding: 12px;
88
- height: 100%;
89
- overflow: hidden;
90
- display: flex;
91
- flex-direction: column;
92
- box-sizing: border-box;
93
- ">
94
- <div class="btcp-terminal-output" style="
95
- flex: 1;
96
- overflow-y: auto;
97
- white-space: pre-wrap;
98
- word-wrap: break-word;
99
- "></div>
100
- <div class="btcp-terminal-input-line" style="
101
- display: flex;
102
- align-items: center;
103
- margin-top: 8px;
104
- flex-shrink: 0;
105
- ">
106
- <span class="btcp-terminal-prompt" style="
107
- color: ${isDark ? '#6a9955' : '#008000'};
108
- margin-right: 8px;
109
- user-select: none;
110
- ">${this.config.prompt}</span>
111
- <input class="btcp-terminal-input" type="text" style="
112
- flex: 1;
113
- background: transparent;
114
- border: none;
115
- outline: none;
116
- font-family: inherit;
117
- font-size: inherit;
118
- color: inherit;
119
- padding: 0;
120
- margin: 0;
121
- " autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false">
122
- </div>
123
- </div>
124
- `;
125
-
126
- this.outputEl = this.container.querySelector('.btcp-terminal-output')!;
127
- this.inputLineEl = this.container.querySelector('.btcp-terminal-input-line')!;
128
- this.promptEl = this.container.querySelector('.btcp-terminal-prompt')!;
129
- this.inputEl = this.container.querySelector('.btcp-terminal-input')!;
130
- }
131
-
132
- /**
133
- * Bind event listeners
134
- */
135
- private bindEvents(): void {
136
- // Handle input
137
- this.inputEl.addEventListener('keydown', (e) => this.handleKeyDown(e));
138
-
139
- // Click to focus
140
- this.container.addEventListener('click', () => this.focus());
141
- }
142
-
143
- /**
144
- * Handle key down events
145
- */
146
- private async handleKeyDown(e: KeyboardEvent): Promise<void> {
147
- if (this.state.isExecuting) {
148
- e.preventDefault();
149
- return;
150
- }
151
-
152
- switch (e.key) {
153
- case 'Enter':
154
- e.preventDefault();
155
- await this.executeInput();
156
- break;
157
-
158
- case 'ArrowUp':
159
- e.preventDefault();
160
- this.navigateHistory(-1);
161
- break;
162
-
163
- case 'ArrowDown':
164
- e.preventDefault();
165
- this.navigateHistory(1);
166
- break;
167
-
168
- case 'c':
169
- if (e.ctrlKey) {
170
- e.preventDefault();
171
- this.cancel();
172
- }
173
- break;
174
-
175
- case 'l':
176
- if (e.ctrlKey) {
177
- e.preventDefault();
178
- this.clearScreen();
179
- }
180
- break;
181
- }
182
- }
183
-
184
- /**
185
- * Execute the current input
186
- */
187
- private async executeInput(): Promise<void> {
188
- const input = this.inputEl.value.trim();
189
-
190
- // Show the input in history
191
- this.appendOutput(`${this.config.prompt}${input}`, 'input');
192
-
193
- // Clear input
194
- this.inputEl.value = '';
195
-
196
- if (!input) {
197
- return;
198
- }
199
-
200
- // Add to command history
201
- this.state.commandHistory.push(input);
202
- this.state.historyIndex = this.state.commandHistory.length;
203
-
204
- // Handle built-in terminal commands
205
- if (input === 'clear') {
206
- this.clearScreen();
207
- return;
208
- }
209
-
210
- // Execute command
211
- this.state.isExecuting = true;
212
- this.setPrompt('...');
213
-
214
- try {
215
- const result = await this.onExecute(input);
216
- const formatted = formatResult(result);
217
-
218
- this.appendOutput(formatted.content, formatted.type === 'error' ? 'error' : 'output');
219
- } catch (error) {
220
- const message = error instanceof Error ? error.message : String(error);
221
- this.appendOutput(`Error: ${message}`, 'error');
222
- } finally {
223
- this.state.isExecuting = false;
224
- this.setPrompt(this.config.prompt);
225
- this.focus();
226
- }
227
- }
228
-
229
- /**
230
- * Navigate command history
231
- */
232
- private navigateHistory(direction: number): void {
233
- const newIndex = this.state.historyIndex + direction;
234
-
235
- if (newIndex < 0) {
236
- return;
237
- }
238
-
239
- if (newIndex >= this.state.commandHistory.length) {
240
- this.state.historyIndex = this.state.commandHistory.length;
241
- this.inputEl.value = this.state.inputBuffer;
242
- return;
243
- }
244
-
245
- // Save current input if navigating from end
246
- if (this.state.historyIndex === this.state.commandHistory.length) {
247
- this.state.inputBuffer = this.inputEl.value;
248
- }
249
-
250
- this.state.historyIndex = newIndex;
251
- this.inputEl.value = this.state.commandHistory[newIndex];
252
-
253
- // Move cursor to end
254
- this.inputEl.setSelectionRange(this.inputEl.value.length, this.inputEl.value.length);
255
- }
256
-
257
- /**
258
- * Append output to the terminal
259
- */
260
- private appendOutput(content: string, type: 'input' | 'output' | 'error' | 'info'): void {
261
- const isDark = this.config.theme === 'dark';
262
-
263
- let color = isDark ? '#d4d4d4' : '#1e1e1e';
264
- if (type === 'error') {
265
- color = isDark ? '#f14c4c' : '#cd3131';
266
- } else if (type === 'info') {
267
- color = isDark ? '#3794ff' : '#0066bf';
268
- } else if (type === 'input') {
269
- color = isDark ? '#9cdcfe' : '#0066bf';
270
- }
271
-
272
- const entry: HistoryEntry = {
273
- type,
274
- content,
275
- timestamp: Date.now(),
276
- };
277
-
278
- this.state.history.push(entry);
279
-
280
- // Trim history if needed
281
- while (this.state.history.length > this.config.historySize) {
282
- this.state.history.shift();
283
- }
284
-
285
- // Append to DOM
286
- const line = document.createElement('div');
287
- line.style.color = color;
288
- line.style.marginBottom = '2px';
289
- line.textContent = content;
290
- this.outputEl.appendChild(line);
291
-
292
- // Scroll to bottom
293
- this.outputEl.scrollTop = this.outputEl.scrollHeight;
294
- }
295
-
296
- /**
297
- * Set the prompt text
298
- */
299
- private setPrompt(prompt: string): void {
300
- this.promptEl.textContent = prompt;
301
- }
302
-
303
- /**
304
- * Cancel current operation
305
- */
306
- private cancel(): void {
307
- if (this.state.isExecuting) {
308
- this.appendOutput('^C', 'info');
309
- } else {
310
- this.inputEl.value = '';
311
- }
312
- }
313
-
314
- /**
315
- * Clear the screen
316
- */
317
- public clearScreen(): void {
318
- this.outputEl.innerHTML = '';
319
- this.state.history = [];
320
- }
321
-
322
- /**
323
- * Focus the input
324
- */
325
- public focus(): void {
326
- this.inputEl.focus();
327
- }
328
-
329
- /**
330
- * Write output programmatically
331
- */
332
- public write(content: string, type: 'output' | 'error' | 'info' = 'output'): void {
333
- this.appendOutput(content, type);
334
- }
335
-
336
- /**
337
- * Execute a command programmatically
338
- */
339
- public async run(command: string): Promise<CommandResult> {
340
- this.inputEl.value = command;
341
- await this.executeInput();
342
- return { success: true };
343
- }
344
-
345
- /**
346
- * Get the history
347
- */
348
- public getHistory(): HistoryEntry[] {
349
- return [...this.state.history];
350
- }
351
-
352
- /**
353
- * Get command history
354
- */
355
- public getCommandHistory(): string[] {
356
- return [...this.state.commandHistory];
357
- }
358
-
359
- /**
360
- * Destroy the terminal
361
- */
362
- public destroy(): void {
363
- this.container.innerHTML = '';
364
- }
365
- }
@@ -1,5 +0,0 @@
1
- /**
2
- * Terminal UI exports
3
- */
4
-
5
- export { Terminal, type TerminalOptions } from './Terminal.js';