command-cmd 1.0.2 → 1.0.4

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 (6) hide show
  1. package/cmd.js +1640 -16
  2. package/doc.md +199 -157
  3. package/docPTBR.md +204 -157
  4. package/map.md +238 -0
  5. package/mapPTBR.md +238 -0
  6. package/package.json +5 -2
package/doc.md CHANGED
@@ -1,19 +1,12 @@
1
1
  # command-cmd (English Documentation)
2
2
 
3
- `command-cmd` is a lightweight parser for detecting and extracting structured commands from free-form text, especially AI output.
3
+ `command-cmd` parses AI text commands and runs cursor automation through `robotjs`.
4
4
 
5
- It is useful when a model returns natural language plus command blocks and you need clean structured data for automation.
5
+ Exported functions:
6
6
 
7
- ## What it is for
8
-
9
- Use this library to:
10
-
11
- - Extract commands embedded in AI responses.
12
- - Capture multiple commands from a single message.
13
- - Normalize output into a standard object: `type`, `command`, `extra`, and `seq`.
14
- - Accept both English and Portuguese keys (`type/tipo`, `command/comando`).
15
-
16
- It **does not execute commands**. It only parses text.
7
+ - `cmd`
8
+ - `extractFirstCommand`
9
+ - `cursor`
17
10
 
18
11
  ## Installation
19
12
 
@@ -21,223 +14,272 @@ It **does not execute commands**. It only parses text.
21
14
  npm install command-cmd
22
15
  ```
23
16
 
24
- ## Quick start
17
+ ## Import
25
18
 
26
19
  ```js
27
- import { cmd, extractFirstCommand } from 'command-cmd';
20
+ import { cmd, extractFirstCommand, cursor } from 'command-cmd';
21
+ ```
22
+
23
+ ## 1) `cmd(message)`
28
24
 
29
- const aiMessage = `
30
- Run this sequence:
31
- [type: shell, command: npm test, extra: run from project root, seq: 2]
32
- `;
25
+ Extracts command blocks from text.
33
26
 
34
- const commandList = cmd(aiMessage);
35
- const firstCommand = extractFirstCommand(aiMessage);
27
+ Accepted format:
36
28
 
37
- console.log(commandList);
38
- console.log(firstCommand);
29
+ ```txt
30
+ [type: open_app, command: tiktok, button: search_bar, seq: 1]
39
31
  ```
40
32
 
41
- Expected output:
33
+ For sequential movement:
42
34
 
43
- ```js
44
- [
45
- {
46
- type: 'shell',
47
- command: 'npm test',
48
- extra: 'run from project root',
49
- seq: 2
50
- }
51
- ]
35
+ ```txt
36
+ [move_sequence, points: 120x220|420x260|800x300, interval: 300, click: between, doubleClick: true]
37
+ ```
52
38
 
39
+ Short format is also supported:
40
+
41
+ ```txt
42
+ [open_app, command: tiktok, button: skip_ads]
43
+ ```
44
+
45
+ Returned object:
46
+
47
+ ```js
53
48
  {
54
- type: 'shell',
55
- command: 'npm test',
56
- extra: 'run from project root',
57
- seq: 2
49
+ type: 'open_app',
50
+ command: 'tiktok',
51
+ extra: undefined,
52
+ button: 'skip_ads',
53
+ seq: 1
58
54
  }
59
55
  ```
60
56
 
61
- ## Full API
57
+ ## 2) `extractFirstCommand(message)`
62
58
 
63
- ### `cmd(message)`
59
+ Returns only the first valid command.
64
60
 
65
- Extracts **all** valid commands from a string.
61
+ Output:
66
62
 
67
- - Input: `message` (string).
68
- - Output: `Array<{ type: string, command: string, extra?: string, seq?: number }>`
69
- - If `message` is not a string: returns `[]`.
70
- - If no valid command is found: returns `[]`.
63
+ ```js
64
+ { type, command, extra, button, points, path, interval, clickDelay, click, doubleClick, seq } | null
65
+ ```
71
66
 
72
- A block is returned only when it contains:
67
+ ## 3) `cursor(input, options?)`
73
68
 
74
- - `type` (or `tipo`)
75
- - `command` (or `comando`)
69
+ Runs mouse/keyboard actions.
76
70
 
77
- `seq` rules:
71
+ `input` can be:
78
72
 
79
- - Optional field.
80
- - Accepts only integer values greater than or equal to zero.
81
- - If invalid (for example `seq: many`), it remains `undefined`.
73
+ - string (internally parsed with `cmd`)
74
+ - one command object
75
+ - array of command objects
82
76
 
83
- ### `extractFirstCommand(message)`
77
+ Accepted object keys:
84
78
 
85
- Returns only the first valid command.
79
+ - `type` or `tipo`
80
+ - `command` or `comando`
81
+ - `button` or `botao`
82
+ - `points` or `pontos` (coordinate sequence)
83
+ - `path` or `caminho` or `trajeto` (alias of `points`)
84
+ - `interval` or `intervalo` (ms between points)
85
+ - `clickDelay` or `delayClique` (ms between arriving and click)
86
+ - `click` or `clique` (`none`, `between`, `each`, `first`, `last`)
87
+ - `doubleClick` or `duplo` (true/false)
88
+ - `seq` or `sequencia`
89
+ - `extra`
86
90
 
87
- - Input: `message` (string).
88
- - Output: `{ type, command, extra, seq } | null`
89
- - If no valid command is found: returns `null`.
91
+ ### App and button names (important)
90
92
 
91
- ## Expected command format
93
+ You can name apps and buttons however you want.
92
94
 
93
- Each command must be inside square brackets:
95
+ The library uses the name only to resolve keys in `map.json`, with normalization:
94
96
 
95
- ```txt
96
- [type: value, command: value, extra: value, seq: 3]
97
- ```
97
+ - case-insensitive;
98
+ - spaces/hyphens converted to `_`;
99
+ - accents removed.
98
100
 
99
- Recognized keys:
101
+ Examples that resolve to the same logical key:
100
102
 
101
- - `type` or `tipo`
102
- - `command` or `comando`
103
- - `extra`
104
- - `seq`
103
+ - `Skip ADS`
104
+ - `skip-ads`
105
+ - `skip_ads`
105
106
 
106
- Key matching is case-insensitive.
107
+ Same idea for app names:
107
108
 
108
- Valid examples:
109
+ - `Tik Tok`
110
+ - `tik-tok`
111
+ - `tik_tok`
109
112
 
110
- ```txt
111
- [TYPE: shell, COMMAND: ls -la, SEQ: 1]
112
- [tipo: shell, comando: pwd, seq: 2]
113
+ Example:
114
+
115
+ ```js
116
+ const commands = [
117
+ { type: 'open_app', command: 'youtube', button: 'search_bar', seq: 1 },
118
+ { type: 'open_app', command: 'youtube', button: 'skip_ads', seq: 1 }
119
+ ];
120
+
121
+ const runSummary = await cursor(commands);
122
+ console.log(runSummary);
113
123
  ```
114
124
 
115
- ## Parsing rules
125
+ ## App state flow (open/closed)
116
126
 
117
- - The parser searches for `[ ... ]` blocks.
118
- - Internal content is split by commas.
119
- - Each segment needs `:` to become `key: value`.
120
- - Blocks without `type/tipo` or `command/comando` are ignored.
121
- - `seq` is applied only when it is a non-negative integer.
122
- - Unknown keys use fallback behavior:
123
- - The first unknown key may become `type`, and its value becomes `command`.
124
- - Later unknown keys may fill `extra` if it is still empty.
127
+ For app commands (`open_app`, `close_app`), the library uses `map.json`:
125
128
 
126
- ## Real AI response examples
129
+ 1. Reads app state (`open` or `closed` / `aberto` or `fechado`).
130
+ 2. If already open, it does not open the app again.
131
+ 3. Executes mapped button click.
132
+ 4. If that button has `setState`, it updates app state in `map.json`.
127
133
 
128
- ### Example 1: single command
134
+ ### Automatic `map.json` creation
129
135
 
130
- AI text:
136
+ If `map.json` does not exist, the library creates it automatically in the project root (cwd) by default.
131
137
 
132
- ```txt
133
- To list files:
134
- [type: shell, command: ls -la, extra: linux or mac, seq: 1]
135
- ```
138
+ The generated file includes:
136
139
 
137
- Result:
140
+ - `state` for each app;
141
+ - `buttons` for each app;
142
+ - a default `fechar/close` button for each app (`setState: "fechado"`).
138
143
 
139
- ```js
140
- [
141
- {
142
- type: 'shell',
143
- command: 'ls -la',
144
- extra: 'linux or mac',
145
- seq: 1
146
- }
147
- ]
148
- ```
144
+ This supports flows such as:
149
145
 
150
- ### Example 2: multiple commands
146
+ - "click TikTok search bar"
147
+ - "click YouTube skip ad button"
151
148
 
152
- AI text:
149
+ AI output example:
153
150
 
154
151
  ```txt
155
- Step 1: [type: shell, command: npm install, seq: 1]
156
- Step 2: [type: shell, command: npm run dev, extra: default port 3000, seq: 1]
157
- Step 3: [type: shell, command: npm test, seq: 3]
152
+ [open_app, command: tiktok, button: search_bar]
153
+ [open_app, command: youtube, button: skip_ads]
158
154
  ```
159
155
 
160
- Result:
156
+ ## Supported `type` values
161
157
 
162
- ```js
163
- [
164
- { type: 'shell', command: 'npm install', extra: undefined, seq: 1 },
165
- { type: 'shell', command: 'npm run dev', extra: 'default port 3000', seq: 1 },
166
- { type: 'shell', command: 'npm test', extra: undefined, seq: 3 }
167
- ]
168
- ```
158
+ - `open_app` / `abrir_app`
159
+ - `close_app` / `fechar_app`
160
+ - `click` / `clicar`
161
+ - `double_click` / `clique_duplo`
162
+ - `scroll` / `rolar`
163
+ - `move_sequence` / `mover_sequencia`
164
+ - `skip_ads` / `pular_ads`
165
+
166
+ ## Sequential movement (new)
169
167
 
170
- ### Example 3: invalid `seq`
168
+ Use `move_sequence` to move mouse through 2+ points in order.
171
169
 
172
- AI text:
170
+ ### Coordinate format
171
+
172
+ Use `points` as:
173
173
 
174
174
  ```txt
175
- [type: shell, command: npm test, seq: three]
175
+ 100x200|300x260|640x420
176
176
  ```
177
177
 
178
- Result:
178
+ `:` is also accepted:
179
179
 
180
- ```js
181
- [
182
- {
183
- type: 'shell',
184
- command: 'npm test',
185
- extra: undefined,
186
- seq: undefined
187
- }
188
- ]
180
+ ```txt
181
+ 100:200|300:260|640:420
189
182
  ```
190
183
 
191
- ## How to build the AI system prompt
184
+ ### Click behavior between points
192
185
 
193
- Extraction quality depends on stable formatting. The best approach is to force the model to emit valid command blocks.
186
+ `click` field:
194
187
 
195
- ### Template 1: strict mode (blocks only)
188
+ - `none`: no click
189
+ - `between`: click every point except the last
190
+ - `each`: click every point
191
+ - `first`: click only the first point
192
+ - `last`: click only the last point
196
193
 
197
- ```txt
198
- You are a technical assistant.
199
- Whenever you suggest an executable action, output blocks in this format:
200
- [type: <category>, command: <command>, extra: <optional context>, seq: <optional integer>]
194
+ `doubleClick` field:
201
195
 
202
- Mandatory rules:
203
- 1. Always use square brackets.
204
- 2. Always use keys exactly as: type, command, extra, seq.
205
- 3. seq must be an integer >= 0.
206
- 4. Do not use commas inside values.
207
- 5. One command per block.
196
+ - `true`: use double click when click is triggered
197
+ - `false`: single click
198
+
199
+ `clickDelay` field:
200
+
201
+ - delay (ms) between arriving at a point and clicking that point
202
+
203
+ ### AI text example
204
+
205
+ ```txt
206
+ [move_sequence, points: 140x260|520x280|980x300, interval: 250, click: between, doubleClick: true]
208
207
  ```
209
208
 
210
- ### Template 2: explanation + blocks
209
+ With `clickDelay`:
211
210
 
212
211
  ```txt
213
- You can explain in natural language.
214
- Whenever a command is needed, include one block per command using:
215
- [type: <category>, command: <command>, extra: <optional context>, seq: <optional integer>]
212
+ [move_sequence, path: 140x260|520x280|980x300, interval: 250, clickDelay: 120, click: between, doubleClick: true]
213
+ ```
214
+
215
+ ### JS object example (recommended for devs)
216
216
 
217
- If no command is needed, do not create a block.
218
- If a command must be repeated, set seq accordingly.
217
+ ```js
218
+ await cursor({
219
+ type: 'move_sequence',
220
+ points: [
221
+ { x: 140, y: 260 },
222
+ { x: 520, y: 280 },
223
+ { x: 980, y: 300 }
224
+ ],
225
+ interval: 250,
226
+ clickDelay: 120,
227
+ click: 'between',
228
+ doubleClick: true
229
+ });
219
230
  ```
220
231
 
221
- ### Example of expected AI answer
232
+ ## `cursor` options
222
233
 
223
- ```txt
224
- To prepare the environment:
225
- [type: shell, command: npm install, extra: install dependencies, seq: 1]
226
- [type: shell, command: npm test, extra: repeat for stability check, seq: 3]
234
+ ```js
235
+ {
236
+ mapPath: 'map.json',
237
+ createMapIfMissing: true,
238
+ persistMap: true,
239
+ launchKey: 'command', // set false to disable launcher key tap
240
+ moveSteps: 50,
241
+ moveDelay: 8,
242
+ scrollSteps: 10,
243
+ scrollDelay: 20,
244
+ typeDelay: 50,
245
+ sequenceInterval: 250,
246
+ sequenceClick: 'none',
247
+ sequenceDoubleClick: false,
248
+ defaultClosePoint: { x: 1888, y: 16 }
249
+ }
227
250
  ```
228
251
 
229
- ## Current limitations
252
+ ## Dedicated mapper docs
253
+
254
+ Dedicated docs for creating and calibrating `map.json`:
230
255
 
231
- - Values containing commas may break parsing because splitting uses `,`.
232
- - Values containing `[` or `]` may interfere with block matching.
233
- - Only one `extra` field is returned per block.
256
+ - `mapPTBR.md` (PT-BR)
257
+ - `map.md` (English)
234
258
 
235
- ## Security
259
+ They explain:
236
260
 
237
- This library does not execute commands.
261
+ - app mapping and coordinates;
262
+ - per-app button mapping;
263
+ - state management with `setState`.
264
+
265
+ ## Recommended system prompt (AI -> command)
266
+
267
+ ```txt
268
+ You are a technical assistant.
269
+ When you suggest executable actions, output only blocks:
270
+ [type: <type>, command: <app_or_value>, points: <optional_points>, button: <optional_button>, interval: <optional_ms>, clickDelay: <optional_ms_before_click>, click: <optional_mode>, doubleClick: <optional_boolean>, extra: <optional_text>, seq: <optional_integer>]
271
+
272
+ Rules:
273
+ 1. Always use square brackets.
274
+ 2. One command per block.
275
+ 3. seq must be an integer >= 0.
276
+ 4. For app interaction, use type open_app and command with app name.
277
+ 5. For UI clicks, fill button using a key that exists in map.json.
278
+ 6. For sequential movement, use type move_sequence and points in `xXy|xXy|xXy` format.
279
+ ```
238
280
 
239
- If you execute parsed output:
281
+ ## Important notes
240
282
 
241
- - Use an allowlist of allowed commands.
242
- - Block dangerous patterns.
243
- - Require confirmation for destructive operations.
283
+ - `cursor` requires a desktop environment where `robotjs` works.
284
+ - If `map.json` does not exist and `createMapIfMissing` is `false`, app commands fail.
285
+ - Avoid commas inside `[ ... ]` values because parser splitting uses commas.