command-cmd 1.0.2 → 1.0.5

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 +2165 -16
  2. package/doc.md +292 -152
  3. package/docPTBR.md +299 -152
  4. package/map.md +244 -0
  5. package/mapPTBR.md +244 -0
  6. package/package.json +5 -2
package/doc.md CHANGED
@@ -1,19 +1,14 @@
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`
10
+ - `initMap`
11
+ - `initDoc`
17
12
 
18
13
  ## Installation
19
14
 
@@ -21,223 +16,368 @@ It **does not execute commands**. It only parses text.
21
16
  npm install command-cmd
22
17
  ```
23
18
 
24
- ## Quick start
19
+ ## Import
25
20
 
26
21
  ```js
27
- import { cmd, extractFirstCommand } from 'command-cmd';
22
+ import { cmd, extractFirstCommand, cursor, initMap, initDoc } from 'command-cmd';
23
+ ```
24
+
25
+ ## 1) `cmd(message)`
26
+
27
+ Extracts command blocks from text.
28
28
 
29
- const aiMessage = `
30
- Run this sequence:
31
- [type: shell, command: npm test, extra: run from project root, seq: 2]
32
- `;
29
+ Accepted format:
33
30
 
34
- const commandList = cmd(aiMessage);
35
- const firstCommand = extractFirstCommand(aiMessage);
31
+ ```txt
32
+ [type: open_app, command: tiktok, button: search_bar, seq: 1]
33
+ ```
34
+
35
+ For sequential movement:
36
36
 
37
- console.log(commandList);
38
- console.log(firstCommand);
37
+ ```txt
38
+ [move_sequence, points: 120x220|420x260|800x300, interval: 300, click: between, doubleClick: true]
39
39
  ```
40
40
 
41
- Expected output:
41
+ Short format is also supported:
42
42
 
43
- ```js
44
- [
45
- {
46
- type: 'shell',
47
- command: 'npm test',
48
- extra: 'run from project root',
49
- seq: 2
50
- }
51
- ]
43
+ ```txt
44
+ [open_app, command: tiktok, button: skip_ads]
45
+ ```
46
+
47
+ Returned object:
52
48
 
49
+ ```js
53
50
  {
54
- type: 'shell',
55
- command: 'npm test',
56
- extra: 'run from project root',
57
- seq: 2
51
+ type: 'open_app',
52
+ command: 'tiktok',
53
+ extra: undefined,
54
+ button: 'skip_ads',
55
+ seq: 1
58
56
  }
59
57
  ```
60
58
 
61
- ## Full API
59
+ ## 2) `extractFirstCommand(message)`
62
60
 
63
- ### `cmd(message)`
61
+ Returns only the first valid command.
64
62
 
65
- Extracts **all** valid commands from a string.
63
+ Output:
66
64
 
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 `[]`.
65
+ ```js
66
+ {
67
+ type,
68
+ command,
69
+ extra,
70
+ button,
71
+ key,
72
+ modifiers,
73
+ text,
74
+ typeDelay,
75
+ points,
76
+ path,
77
+ interval,
78
+ clickDelay,
79
+ click,
80
+ doubleClick,
81
+ seq
82
+ } | null
83
+ ```
71
84
 
72
- A block is returned only when it contains:
85
+ ## 3) `cursor(input, options?)`
73
86
 
74
- - `type` (or `tipo`)
75
- - `command` (or `comando`)
87
+ Runs mouse/keyboard actions.
76
88
 
77
- `seq` rules:
89
+ `input` can be:
78
90
 
79
- - Optional field.
80
- - Accepts only integer values greater than or equal to zero.
81
- - If invalid (for example `seq: many`), it remains `undefined`.
91
+ - string (internally parsed with `cmd`)
92
+ - one command object
93
+ - array of command objects
82
94
 
83
- ### `extractFirstCommand(message)`
95
+ Accepted object keys:
84
96
 
85
- Returns only the first valid command.
97
+ - `type` or `tipo`
98
+ - `command` or `comando`
99
+ - `button` or `botao`
100
+ - `key` or `tecla` (for `key_tap`)
101
+ - `modifiers` or `modificadores` (example: `command+shift`)
102
+ - `text` or `texto` (for `type_string_delayed`)
103
+ - `typeDelay` or `typingDelay` (ms per character while typing)
104
+ - `points` or `pontos` (coordinate sequence)
105
+ - `path` or `caminho` or `trajeto` (alias of `points`)
106
+ - `interval` or `intervalo` (ms between points)
107
+ - `clickDelay` or `delayClique` (ms between arriving and click)
108
+ - `click` or `clique` (`none`, `between`, `each`, `first`, `last`)
109
+ - `doubleClick` or `duplo` (true/false)
110
+ - `seq` or `sequencia`
111
+ - `extra`
86
112
 
87
- - Input: `message` (string).
88
- - Output: `{ type, command, extra, seq } | null`
89
- - If no valid command is found: returns `null`.
113
+ ## 4) `initMap(options?)`
90
114
 
91
- ## Expected command format
115
+ Creates (or loads/merges) `map.json` explicitly.
92
116
 
93
- Each command must be inside square brackets:
117
+ Example:
94
118
 
95
- ```txt
96
- [type: value, command: value, extra: value, seq: 3]
119
+ ```js
120
+ await initMap();
121
+ await initMap({ mapPath: './config/map.json' });
97
122
  ```
98
123
 
99
- Recognized keys:
124
+ Optional keys:
100
125
 
101
- - `type` or `tipo`
102
- - `command` or `comando`
103
- - `extra`
104
- - `seq`
126
+ - `mapPath`
127
+ - `createMapIfMissing`
128
+ - `persistMap`
129
+ - `apps`
130
+ - `defaultClosePoint`
131
+ - `skipAdsPoint`
132
+ - `persistMerged` (writes merged defaults even when map already exists)
105
133
 
106
- Key matching is case-insensitive.
134
+ ## 5) `initDoc(options?)`
107
135
 
108
- Valid examples:
136
+ Creates documentation files from package templates.
109
137
 
110
- ```txt
111
- [TYPE: shell, COMMAND: ls -la, SEQ: 1]
112
- [tipo: shell, comando: pwd, seq: 2]
138
+ By default it writes in current working directory:
139
+
140
+ - `doc.md`
141
+ - `docPTBR.md`
142
+ - `map.md`
143
+ - `mapPTBR.md`
144
+
145
+ Example:
146
+
147
+ ```js
148
+ await initDoc();
149
+ await initDoc({ outputDir: './docs', overwrite: true, includeMapDocs: false });
113
150
  ```
114
151
 
115
- ## Parsing rules
152
+ Optional keys:
116
153
 
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.
154
+ - `outputDir` (alias: `dir`, `path`)
155
+ - `overwrite`
156
+ - `includeMapDocs`
157
+ - `files` (e.g. `['doc', 'docPTBR', 'map', 'mapPTBR']`)
125
158
 
126
- ## Real AI response examples
159
+ ### App and button names (important)
127
160
 
128
- ### Example 1: single command
161
+ You can name apps and buttons however you want.
129
162
 
130
- AI text:
163
+ The library uses the name only to resolve keys in `map.json`, with normalization:
131
164
 
132
- ```txt
133
- To list files:
134
- [type: shell, command: ls -la, extra: linux or mac, seq: 1]
135
- ```
165
+ - case-insensitive;
166
+ - spaces/hyphens converted to `_`;
167
+ - accents removed.
168
+
169
+ Examples that resolve to the same logical key:
136
170
 
137
- Result:
171
+ - `Skip ADS`
172
+ - `skip-ads`
173
+ - `skip_ads`
174
+
175
+ Same idea for app names:
176
+
177
+ - `Tik Tok`
178
+ - `tik-tok`
179
+ - `tik_tok`
180
+
181
+ Example:
138
182
 
139
183
  ```js
140
- [
141
- {
142
- type: 'shell',
143
- command: 'ls -la',
144
- extra: 'linux or mac',
145
- seq: 1
146
- }
147
- ]
184
+ const commands = [
185
+ { type: 'open_app', command: 'youtube', button: 'search_bar', seq: 1 },
186
+ { type: 'open_app', command: 'youtube', button: 'skip_ads', seq: 1 }
187
+ ];
188
+
189
+ const runSummary = await cursor(commands);
190
+ console.log(runSummary);
148
191
  ```
149
192
 
150
- ### Example 2: multiple commands
193
+ ## App state flow (open/closed)
151
194
 
152
- AI text:
195
+ For app commands (`open_app`, `close_app`), the library uses `map.json`:
153
196
 
154
- ```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]
158
- ```
197
+ 1. Reads app state (`open` or `closed` / `aberto` or `fechado`).
198
+ 2. If already open, it does not open the app again.
199
+ 3. Executes mapped button click.
200
+ 4. If that button has `setState`, it updates app state in `map.json`.
159
201
 
160
- Result:
202
+ Note: `open_app/abrir_app` always triggers `robot.keyTap("command")` before app flow.
203
+
204
+ ### Automatic `map.json` creation
205
+
206
+ If `map.json` does not exist, the library creates it automatically in the project root (cwd) by default.
207
+
208
+ You can also create it explicitly before any automation:
161
209
 
162
210
  ```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
- ]
211
+ await initMap();
168
212
  ```
169
213
 
170
- ### Example 3: invalid `seq`
214
+ The generated file includes:
215
+
216
+ - `state` for each app;
217
+ - `buttons` for each app;
218
+ - a default `fechar/close` button for each app (`setState: "fechado"`).
219
+
220
+ This supports flows such as:
171
221
 
172
- AI text:
222
+ - "click TikTok search bar"
223
+ - "click YouTube skip ad button"
224
+
225
+ AI output example:
173
226
 
174
227
  ```txt
175
- [type: shell, command: npm test, seq: three]
228
+ [open_app, command: tiktok, button: search_bar]
229
+ [open_app, command: youtube, button: skip_ads]
176
230
  ```
177
231
 
178
- Result:
232
+ ## Supported `type` values
179
233
 
180
- ```js
181
- [
182
- {
183
- type: 'shell',
184
- command: 'npm test',
185
- extra: undefined,
186
- seq: undefined
187
- }
188
- ]
234
+ - `open_app` / `abrir_app`
235
+ - `close_app` / `fechar_app`
236
+ - `click` / `clicar`
237
+ - `double_click` / `clique_duplo`
238
+ - `scroll` / `rolar`
239
+ - `move_sequence` / `mover_sequencia`
240
+ - `skip_ads` / `pular_ads`
241
+ - `key_tap` / `tecla`
242
+ - `type_string_delayed` / `digitar`
243
+
244
+ ## Keyboard and typing
245
+
246
+ Single key:
247
+
248
+ ```txt
249
+ [key_tap, key: enter]
189
250
  ```
190
251
 
191
- ## How to build the AI system prompt
252
+ With modifier:
192
253
 
193
- Extraction quality depends on stable formatting. The best approach is to force the model to emit valid command blocks.
254
+ ```txt
255
+ [key_tap, key: v, modifiers: command]
256
+ ```
194
257
 
195
- ### Template 1: strict mode (blocks only)
258
+ Slow typing:
196
259
 
197
260
  ```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>]
261
+ [type_string_delayed, text: Typing slowly..., typeDelay: 100]
262
+ ```
201
263
 
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.
264
+ ## Sequential movement (new)
265
+
266
+ Use `move_sequence` to move mouse through 2+ points in order.
267
+
268
+ ### Coordinate format
269
+
270
+ Use `points` as:
271
+
272
+ ```txt
273
+ 100x200|300x260|640x420
208
274
  ```
209
275
 
210
- ### Template 2: explanation + blocks
276
+ `:` is also accepted:
211
277
 
212
278
  ```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>]
279
+ 100:200|300:260|640:420
280
+ ```
281
+
282
+ ### Click behavior between points
283
+
284
+ `click` field:
285
+
286
+ - `none`: no click
287
+ - `between`: click every point except the last
288
+ - `each`: click every point
289
+ - `first`: click only the first point
290
+ - `last`: click only the last point
291
+
292
+ `doubleClick` field:
293
+
294
+ - `true`: use double click when click is triggered
295
+ - `false`: single click
216
296
 
217
- If no command is needed, do not create a block.
218
- If a command must be repeated, set seq accordingly.
297
+ `clickDelay` field:
298
+
299
+ - delay (ms) between arriving at a point and clicking that point
300
+
301
+ ### AI text example
302
+
303
+ ```txt
304
+ [move_sequence, points: 140x260|520x280|980x300, interval: 250, click: between, doubleClick: true]
219
305
  ```
220
306
 
221
- ### Example of expected AI answer
307
+ With `clickDelay`:
222
308
 
223
309
  ```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]
310
+ [move_sequence, path: 140x260|520x280|980x300, interval: 250, clickDelay: 120, click: between, doubleClick: true]
311
+ ```
312
+
313
+ ### JS object example (recommended for devs)
314
+
315
+ ```js
316
+ await cursor({
317
+ type: 'move_sequence',
318
+ points: [
319
+ { x: 140, y: 260 },
320
+ { x: 520, y: 280 },
321
+ { x: 980, y: 300 }
322
+ ],
323
+ interval: 250,
324
+ clickDelay: 120,
325
+ click: 'between',
326
+ doubleClick: true
327
+ });
227
328
  ```
228
329
 
229
- ## Current limitations
330
+ ## `cursor` options
230
331
 
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.
332
+ ```js
333
+ {
334
+ mapPath: 'map.json',
335
+ createMapIfMissing: true,
336
+ persistMap: true,
337
+ launchKey: 'command', // used by close_app fallback shortcut (command+w)
338
+ moveSteps: 50,
339
+ moveDelay: 8,
340
+ scrollSteps: 10,
341
+ scrollDelay: 20,
342
+ typeDelay: 50,
343
+ sequenceInterval: 250,
344
+ sequenceClick: 'none',
345
+ sequenceDoubleClick: false,
346
+ defaultClosePoint: { x: 1888, y: 16 }
347
+ }
348
+ ```
234
349
 
235
- ## Security
350
+ ## Dedicated mapper docs
236
351
 
237
- This library does not execute commands.
352
+ Dedicated docs for creating and calibrating `map.json`:
353
+
354
+ - `mapPTBR.md` (PT-BR)
355
+ - `map.md` (English)
356
+
357
+ They explain:
358
+
359
+ - app mapping and coordinates;
360
+ - per-app button mapping;
361
+ - state management with `setState`.
362
+
363
+ ## Recommended system prompt (AI -> command)
364
+
365
+ ```txt
366
+ You are a technical assistant.
367
+ When you suggest executable actions, output only blocks:
368
+ [type: <type>, command: <app_or_value>, key: <optional_key>, modifiers: <optional_modifiers>, text: <optional_text>, typeDelay: <typing_ms>, 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>]
369
+
370
+ Rules:
371
+ 1. Always use square brackets.
372
+ 2. One command per block.
373
+ 3. seq must be an integer >= 0.
374
+ 4. For app interaction, use type open_app and command with app name.
375
+ 5. For UI clicks, fill button using a key that exists in map.json.
376
+ 6. For sequential movement, use type move_sequence and points in `xXy|xXy|xXy` format.
377
+ ```
238
378
 
239
- If you execute parsed output:
379
+ ## Important notes
240
380
 
241
- - Use an allowlist of allowed commands.
242
- - Block dangerous patterns.
243
- - Require confirmation for destructive operations.
381
+ - `cursor` requires a desktop environment where `robotjs` works.
382
+ - If `map.json` does not exist and `createMapIfMissing` is `false`, app commands fail.
383
+ - Avoid commas inside `[ ... ]` values because parser splitting uses commas.