btcp-browser-agent 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,35 +0,0 @@
1
- /**
2
- * select command - Select dropdown option
3
- */
4
-
5
- import type { CommandHandler } from '../types.js';
6
- import { InvalidArgumentsError } from '../errors.js';
7
-
8
- export const selectCommand: CommandHandler = {
9
- name: 'select',
10
- description: 'Select a dropdown option',
11
- usage: 'select <selector> <value>',
12
- examples: ['select @ref:5 "Option 1"', 'select #country US'],
13
-
14
- async execute(client, args) {
15
- if (args.length < 2) {
16
- throw new InvalidArgumentsError('Selector and value required', 'select <selector> <value>');
17
- }
18
-
19
- const selector = args[0];
20
- const value = args.slice(1).join(' ');
21
-
22
- const response = await client.execute({
23
- id: `cmd_${Date.now()}`,
24
- action: 'select',
25
- selector,
26
- values: value,
27
- } as any);
28
-
29
- if (response.success) {
30
- return { success: true, message: `Selected "${value}" in: ${selector}` };
31
- }
32
-
33
- return { success: false, error: response.error };
34
- },
35
- };
@@ -1,21 +0,0 @@
1
- /**
2
- * snapshot command - Get page accessibility tree
3
- */
4
-
5
- import type { CommandHandler } from '../types.js';
6
- import { getFlagString, getFlagNumber } from '../parser.js';
7
-
8
- export const snapshotCommand: CommandHandler = {
9
- name: 'snapshot',
10
- description: 'Get page accessibility tree',
11
- usage: 'snapshot [--selector <css>] [--depth <n>]',
12
- examples: ['snapshot', 'snapshot --selector main', 'snapshot --depth 5'],
13
-
14
- async execute(client, _args, flags) {
15
- const selector = getFlagString(flags, 'selector');
16
- const maxDepth = getFlagNumber(flags, 'depth');
17
-
18
- const result = await client.snapshot({ selector, maxDepth });
19
- return { success: true, data: result };
20
- },
21
- };
@@ -1,32 +0,0 @@
1
- /**
2
- * tab command - Switch to a tab
3
- */
4
-
5
- import type { CommandHandler } from '../types.js';
6
- import { InvalidArgumentsError } from '../errors.js';
7
-
8
- export const tabCommand: CommandHandler = {
9
- name: 'tab',
10
- description: 'Switch to a tab by ID',
11
- usage: 'tab <id>',
12
- examples: ['tab 123'],
13
-
14
- async execute(client, args) {
15
- if (args.length === 0) {
16
- throw new InvalidArgumentsError('Tab ID required', 'tab <id>');
17
- }
18
-
19
- const tabId = parseInt(args[0], 10);
20
- if (isNaN(tabId)) {
21
- throw new InvalidArgumentsError('Invalid tab ID', 'tab <id>');
22
- }
23
-
24
- const response = await client.tabSwitch(tabId);
25
-
26
- if (response.success) {
27
- return { success: true, message: `Switched to tab ${tabId}` };
28
- }
29
-
30
- return { success: false, error: response.error };
31
- },
32
- };
@@ -1,26 +0,0 @@
1
- /**
2
- * tabs command - List all tabs
3
- */
4
-
5
- import type { CommandHandler } from '../types.js';
6
-
7
- export const tabsCommand: CommandHandler = {
8
- name: 'tabs',
9
- description: 'List all open tabs',
10
- usage: 'tabs',
11
- examples: ['tabs'],
12
-
13
- async execute(client) {
14
- const tabs = await client.tabList();
15
-
16
- const formatted = tabs
17
- .map((tab) => {
18
- const marker = tab.active ? '*' : ' ';
19
- const title = tab.title || '(untitled)';
20
- return `${marker} [${tab.id}] ${title}\n ${tab.url || ''}`;
21
- })
22
- .join('\n');
23
-
24
- return { success: true, data: formatted || 'No tabs' };
25
- },
26
- };
@@ -1,27 +0,0 @@
1
- /**
2
- * text command - Get text content of an element
3
- */
4
-
5
- import type { CommandHandler } from '../types.js';
6
- import { InvalidArgumentsError } from '../errors.js';
7
-
8
- export const textCommand: CommandHandler = {
9
- name: 'text',
10
- description: 'Get text content of an element',
11
- usage: 'text <selector>',
12
- examples: ['text @ref:5', 'text #heading', 'text .message'],
13
-
14
- async execute(client, args) {
15
- if (args.length === 0) {
16
- throw new InvalidArgumentsError('Selector required', 'text <selector>');
17
- }
18
-
19
- const selector = args[0];
20
- const text = await client.getText(selector);
21
-
22
- return {
23
- success: true,
24
- data: text !== null ? text : '(element not found)',
25
- };
26
- },
27
- };
@@ -1,17 +0,0 @@
1
- /**
2
- * title command - Get current page title
3
- */
4
-
5
- import type { CommandHandler } from '../types.js';
6
-
7
- export const titleCommand: CommandHandler = {
8
- name: 'title',
9
- description: 'Get the current page title',
10
- usage: 'title',
11
- examples: ['title'],
12
-
13
- async execute(client) {
14
- const title = await client.getTitle();
15
- return { success: true, data: title };
16
- },
17
- };
@@ -1,38 +0,0 @@
1
- /**
2
- * type command - Type text into an element
3
- */
4
-
5
- import type { CommandHandler } from '../types.js';
6
- import { InvalidArgumentsError } from '../errors.js';
7
- import { getFlagNumber, getFlagBool } from '../parser.js';
8
-
9
- export const typeCommand: CommandHandler = {
10
- name: 'type',
11
- description: 'Type text into an element (character by character)',
12
- usage: 'type <selector> <text> [--delay <ms>] [--clear]',
13
- examples: [
14
- 'type @ref:1 "hello world"',
15
- 'type #search hello',
16
- 'type @ref:2 "test" --delay 50',
17
- 'type @ref:3 "new text" --clear',
18
- ],
19
-
20
- async execute(client, args, flags) {
21
- if (args.length < 2) {
22
- throw new InvalidArgumentsError('Selector and text required', 'type <selector> <text>');
23
- }
24
-
25
- const selector = args[0];
26
- const text = args.slice(1).join(' ');
27
- const delay = getFlagNumber(flags, 'delay');
28
- const clear = getFlagBool(flags, 'clear');
29
-
30
- const response = await client.type(selector, text, { delay, clear });
31
-
32
- if (response.success) {
33
- return { success: true, message: `Typed "${text}" into: ${selector}` };
34
- }
35
-
36
- return { success: false, error: response.error };
37
- },
38
- };
@@ -1,33 +0,0 @@
1
- /**
2
- * uncheck command - Uncheck a checkbox
3
- */
4
-
5
- import type { CommandHandler } from '../types.js';
6
- import { InvalidArgumentsError } from '../errors.js';
7
-
8
- export const uncheckCommand: CommandHandler = {
9
- name: 'uncheck',
10
- description: 'Uncheck a checkbox',
11
- usage: 'uncheck <selector>',
12
- examples: ['uncheck @ref:5', 'uncheck #newsletter'],
13
-
14
- async execute(client, args) {
15
- if (args.length === 0) {
16
- throw new InvalidArgumentsError('Selector required', 'uncheck <selector>');
17
- }
18
-
19
- const selector = args[0];
20
-
21
- const response = await client.execute({
22
- id: `cmd_${Date.now()}`,
23
- action: 'uncheck',
24
- selector,
25
- } as any);
26
-
27
- if (response.success) {
28
- return { success: true, message: `Unchecked: ${selector}` };
29
- }
30
-
31
- return { success: false, error: response.error };
32
- },
33
- };
@@ -1,17 +0,0 @@
1
- /**
2
- * url command - Get current page URL
3
- */
4
-
5
- import type { CommandHandler } from '../types.js';
6
-
7
- export const urlCommand: CommandHandler = {
8
- name: 'url',
9
- description: 'Get the current page URL',
10
- usage: 'url',
11
- examples: ['url'],
12
-
13
- async execute(client) {
14
- const url = await client.getUrl();
15
- return { success: true, data: url };
16
- },
17
- };
@@ -1,54 +0,0 @@
1
- /**
2
- * wait command - Wait for duration or element
3
- */
4
-
5
- import type { CommandHandler } from '../types.js';
6
- import { getFlagString, getFlagNumber } from '../parser.js';
7
-
8
- export const waitCommand: CommandHandler = {
9
- name: 'wait',
10
- description: 'Wait for duration (ms) or element state',
11
- usage: 'wait <ms> | wait <selector> [--state visible|hidden]',
12
- examples: [
13
- 'wait 1000',
14
- 'wait @ref:5',
15
- 'wait @ref:5 --state visible',
16
- 'wait #loading --state hidden',
17
- ],
18
-
19
- async execute(client, args, flags) {
20
- if (args.length === 0) {
21
- // Default wait
22
- await new Promise((resolve) => setTimeout(resolve, 1000));
23
- return { success: true, message: 'Waited 1000ms' };
24
- }
25
-
26
- const first = args[0];
27
-
28
- // Check if it's a number (duration)
29
- const duration = parseInt(first, 10);
30
- if (!isNaN(duration) && String(duration) === first) {
31
- await new Promise((resolve) => setTimeout(resolve, duration));
32
- return { success: true, message: `Waited ${duration}ms` };
33
- }
34
-
35
- // It's a selector - wait for element
36
- const selector = first;
37
- const state = getFlagString(flags, 'state') as 'visible' | 'hidden' | undefined;
38
- const timeout = getFlagNumber(flags, 'timeout', 30000);
39
-
40
- const response = await client.execute({
41
- id: `cmd_${Date.now()}`,
42
- action: 'wait',
43
- selector,
44
- state: state || 'visible',
45
- timeout,
46
- } as any);
47
-
48
- if (response.success) {
49
- return { success: true, message: `Element ready: ${selector}` };
50
- }
51
-
52
- return { success: false, error: response.error };
53
- },
54
- };
@@ -1,164 +0,0 @@
1
- /**
2
- * @btcp/cli - Error classes with contextual feedback
3
- */
4
-
5
- /**
6
- * Base CLI error with optional suggestions
7
- */
8
- export class CLIError extends Error {
9
- /** Suggestions for fixing the error */
10
- public suggestions?: string[];
11
- /** Usage hint */
12
- public usage?: string;
13
- /** Related command */
14
- public command?: string;
15
-
16
- constructor(
17
- message: string,
18
- options?: {
19
- suggestions?: string[];
20
- usage?: string;
21
- command?: string;
22
- }
23
- ) {
24
- super(message);
25
- this.name = 'CLIError';
26
- this.suggestions = options?.suggestions;
27
- this.usage = options?.usage;
28
- this.command = options?.command;
29
- }
30
-
31
- /**
32
- * Format error with suggestions for display
33
- */
34
- toFormattedString(): string {
35
- let output = this.message;
36
-
37
- if (this.usage) {
38
- output += `\n\nUsage: ${this.usage}`;
39
- }
40
-
41
- if (this.suggestions && this.suggestions.length > 0) {
42
- output += '\n\nSuggestions:';
43
- for (const suggestion of this.suggestions) {
44
- output += `\n - ${suggestion}`;
45
- }
46
- }
47
-
48
- return output;
49
- }
50
- }
51
-
52
- /**
53
- * Command not found error with similar command suggestions
54
- */
55
- export class CommandNotFoundError extends CLIError {
56
- constructor(
57
- public readonly commandName: string,
58
- similarCommands?: string[]
59
- ) {
60
- const suggestions = similarCommands?.length
61
- ? similarCommands.map((cmd) => `Did you mean '${cmd}'?`)
62
- : ['Type "help" to see available commands'];
63
-
64
- super(`Unknown command: ${commandName}`, {
65
- suggestions,
66
- command: commandName,
67
- });
68
- this.name = 'CommandNotFoundError';
69
- }
70
- }
71
-
72
- /**
73
- * Invalid arguments error with usage hint
74
- */
75
- export class InvalidArgumentsError extends CLIError {
76
- constructor(
77
- message: string,
78
- usage?: string,
79
- examples?: string[]
80
- ) {
81
- const suggestions = examples?.map((ex) => `Example: ${ex}`);
82
- super(message, { usage, suggestions });
83
- this.name = 'InvalidArgumentsError';
84
- }
85
- }
86
-
87
- /**
88
- * Parse error with syntax help
89
- */
90
- export class ParseError extends CLIError {
91
- constructor(message: string, hint?: string) {
92
- const suggestions = hint ? [hint] : [
93
- 'Commands should be: <command> [args] [--flags]',
94
- 'Use quotes for text with spaces: type @ref:1 "hello world"',
95
- ];
96
- super(message, { suggestions });
97
- this.name = 'ParseError';
98
- }
99
- }
100
-
101
- /**
102
- * Execution error with recovery suggestions
103
- */
104
- export class ExecutionError extends CLIError {
105
- constructor(
106
- message: string,
107
- options?: {
108
- suggestions?: string[];
109
- command?: string;
110
- }
111
- ) {
112
- super(message, options);
113
- this.name = 'ExecutionError';
114
- }
115
- }
116
-
117
- /**
118
- * Element not found error
119
- */
120
- export class ElementNotFoundError extends CLIError {
121
- constructor(selector: string) {
122
- super(`Element not found: ${selector}`, {
123
- suggestions: [
124
- 'Run "snapshot" to see available elements with @ref IDs',
125
- `Wait for element: wait ${selector} --state visible`,
126
- 'Check if the element is inside an iframe',
127
- ],
128
- });
129
- this.name = 'ElementNotFoundError';
130
- }
131
- }
132
-
133
- /**
134
- * Navigation error
135
- */
136
- export class NavigationError extends CLIError {
137
- constructor(url: string, reason?: string) {
138
- super(`Navigation failed: ${reason || url}`, {
139
- suggestions: [
140
- 'Ensure URL includes protocol (https://)',
141
- 'Check if the URL is accessible',
142
- 'Try: goto https://example.com',
143
- ],
144
- });
145
- this.name = 'NavigationError';
146
- }
147
- }
148
-
149
- /**
150
- * Timeout error
151
- */
152
- export class TimeoutError extends CLIError {
153
- constructor(operation: string, selector?: string) {
154
- const suggestions = [
155
- 'Increase wait time: wait 5000',
156
- 'Check if element exists: snapshot',
157
- ];
158
- if (selector) {
159
- suggestions.push(`Wait for element: wait ${selector} --state visible`);
160
- }
161
- super(`Timeout: ${operation}`, { suggestions });
162
- this.name = 'TimeoutError';
163
- }
164
- }
@@ -1,68 +0,0 @@
1
- /**
2
- * @btcp/cli - Command executor
3
- *
4
- * Executes parsed commands using the client.
5
- */
6
-
7
- import type { ParsedCommand, CommandResult, CommandClient } from './types.js';
8
- import { getCommand } from './commands/index.js';
9
- import { CommandNotFoundError, ExecutionError, CLIError } from './errors.js';
10
- import { findSimilarCommands, getContextualSuggestion } from './suggestions.js';
11
-
12
- /**
13
- * Execute a parsed command
14
- */
15
- export async function executeCommand(
16
- client: CommandClient,
17
- command: ParsedCommand
18
- ): Promise<CommandResult> {
19
- const handler = getCommand(command.name);
20
-
21
- if (!handler) {
22
- // Find similar commands for suggestion
23
- const similar = findSimilarCommands(command.name);
24
- throw new CommandNotFoundError(command.name, similar);
25
- }
26
-
27
- try {
28
- const result = await handler.execute(client, command.args, command.flags);
29
-
30
- // Add contextual suggestions on error
31
- if (!result.success && result.error) {
32
- const suggestion = getContextualSuggestion(command.name, result.error, command.args);
33
- if (suggestion) {
34
- return {
35
- ...result,
36
- error: `${result.error}\n\n${suggestion}`,
37
- };
38
- }
39
- }
40
-
41
- return result;
42
- } catch (error) {
43
- if (error instanceof CLIError) {
44
- throw error;
45
- }
46
-
47
- // Wrap unexpected errors with contextual suggestions
48
- const message = error instanceof Error ? error.message : String(error);
49
- const suggestion = getContextualSuggestion(command.name, message, command.args);
50
-
51
- throw new ExecutionError(message, {
52
- suggestions: suggestion ? [suggestion] : undefined,
53
- command: command.name,
54
- });
55
- }
56
- }
57
-
58
- /**
59
- * Execute a raw command string
60
- */
61
- export async function executeCommandString(
62
- client: CommandClient,
63
- input: string,
64
- parse: (input: string) => ParsedCommand
65
- ): Promise<CommandResult> {
66
- const command = parse(input);
67
- return executeCommand(client, command);
68
- }