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.
- package/cmd.js +2165 -16
- package/doc.md +292 -152
- package/docPTBR.md +299 -152
- package/map.md +244 -0
- package/mapPTBR.md +244 -0
- package/package.json +5 -2
package/doc.md
CHANGED
|
@@ -1,19 +1,14 @@
|
|
|
1
1
|
# command-cmd (English Documentation)
|
|
2
2
|
|
|
3
|
-
`command-cmd`
|
|
3
|
+
`command-cmd` parses AI text commands and runs cursor automation through `robotjs`.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Exported functions:
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
-
|
|
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
|
-
##
|
|
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
|
-
|
|
30
|
-
Run this sequence:
|
|
31
|
-
[type: shell, command: npm test, extra: run from project root, seq: 2]
|
|
32
|
-
`;
|
|
29
|
+
Accepted format:
|
|
33
30
|
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
```txt
|
|
32
|
+
[type: open_app, command: tiktok, button: search_bar, seq: 1]
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
For sequential movement:
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
```txt
|
|
38
|
+
[move_sequence, points: 120x220|420x260|800x300, interval: 300, click: between, doubleClick: true]
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
Short format is also supported:
|
|
42
42
|
|
|
43
|
-
```
|
|
44
|
-
[
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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: '
|
|
55
|
-
command: '
|
|
56
|
-
extra:
|
|
57
|
-
|
|
51
|
+
type: 'open_app',
|
|
52
|
+
command: 'tiktok',
|
|
53
|
+
extra: undefined,
|
|
54
|
+
button: 'skip_ads',
|
|
55
|
+
seq: 1
|
|
58
56
|
}
|
|
59
57
|
```
|
|
60
58
|
|
|
61
|
-
##
|
|
59
|
+
## 2) `extractFirstCommand(message)`
|
|
62
60
|
|
|
63
|
-
|
|
61
|
+
Returns only the first valid command.
|
|
64
62
|
|
|
65
|
-
|
|
63
|
+
Output:
|
|
66
64
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
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
|
-
|
|
85
|
+
## 3) `cursor(input, options?)`
|
|
73
86
|
|
|
74
|
-
|
|
75
|
-
- `command` (or `comando`)
|
|
87
|
+
Runs mouse/keyboard actions.
|
|
76
88
|
|
|
77
|
-
`
|
|
89
|
+
`input` can be:
|
|
78
90
|
|
|
79
|
-
-
|
|
80
|
-
-
|
|
81
|
-
-
|
|
91
|
+
- string (internally parsed with `cmd`)
|
|
92
|
+
- one command object
|
|
93
|
+
- array of command objects
|
|
82
94
|
|
|
83
|
-
|
|
95
|
+
Accepted object keys:
|
|
84
96
|
|
|
85
|
-
|
|
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
|
-
|
|
88
|
-
- Output: `{ type, command, extra, seq } | null`
|
|
89
|
-
- If no valid command is found: returns `null`.
|
|
113
|
+
## 4) `initMap(options?)`
|
|
90
114
|
|
|
91
|
-
|
|
115
|
+
Creates (or loads/merges) `map.json` explicitly.
|
|
92
116
|
|
|
93
|
-
|
|
117
|
+
Example:
|
|
94
118
|
|
|
95
|
-
```
|
|
96
|
-
|
|
119
|
+
```js
|
|
120
|
+
await initMap();
|
|
121
|
+
await initMap({ mapPath: './config/map.json' });
|
|
97
122
|
```
|
|
98
123
|
|
|
99
|
-
|
|
124
|
+
Optional keys:
|
|
100
125
|
|
|
101
|
-
- `
|
|
102
|
-
- `
|
|
103
|
-
- `
|
|
104
|
-
- `
|
|
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
|
-
|
|
134
|
+
## 5) `initDoc(options?)`
|
|
107
135
|
|
|
108
|
-
|
|
136
|
+
Creates documentation files from package templates.
|
|
109
137
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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
|
-
|
|
152
|
+
Optional keys:
|
|
116
153
|
|
|
117
|
-
-
|
|
118
|
-
-
|
|
119
|
-
-
|
|
120
|
-
-
|
|
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
|
-
|
|
159
|
+
### App and button names (important)
|
|
127
160
|
|
|
128
|
-
|
|
161
|
+
You can name apps and buttons however you want.
|
|
129
162
|
|
|
130
|
-
|
|
163
|
+
The library uses the name only to resolve keys in `map.json`, with normalization:
|
|
131
164
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
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
|
-
|
|
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
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
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
|
-
|
|
193
|
+
## App state flow (open/closed)
|
|
151
194
|
|
|
152
|
-
|
|
195
|
+
For app commands (`open_app`, `close_app`), the library uses `map.json`:
|
|
153
196
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
222
|
+
- "click TikTok search bar"
|
|
223
|
+
- "click YouTube skip ad button"
|
|
224
|
+
|
|
225
|
+
AI output example:
|
|
173
226
|
|
|
174
227
|
```txt
|
|
175
|
-
[
|
|
228
|
+
[open_app, command: tiktok, button: search_bar]
|
|
229
|
+
[open_app, command: youtube, button: skip_ads]
|
|
176
230
|
```
|
|
177
231
|
|
|
178
|
-
|
|
232
|
+
## Supported `type` values
|
|
179
233
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
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
|
-
|
|
252
|
+
With modifier:
|
|
192
253
|
|
|
193
|
-
|
|
254
|
+
```txt
|
|
255
|
+
[key_tap, key: v, modifiers: command]
|
|
256
|
+
```
|
|
194
257
|
|
|
195
|
-
|
|
258
|
+
Slow typing:
|
|
196
259
|
|
|
197
260
|
```txt
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
[type: <category>, command: <command>, extra: <optional context>, seq: <optional integer>]
|
|
261
|
+
[type_string_delayed, text: Typing slowly..., typeDelay: 100]
|
|
262
|
+
```
|
|
201
263
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
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
|
-
|
|
276
|
+
`:` is also accepted:
|
|
211
277
|
|
|
212
278
|
```txt
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
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
|
-
|
|
218
|
-
|
|
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
|
-
|
|
307
|
+
With `clickDelay`:
|
|
222
308
|
|
|
223
309
|
```txt
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
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
|
-
##
|
|
330
|
+
## `cursor` options
|
|
230
331
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
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
|
-
##
|
|
350
|
+
## Dedicated mapper docs
|
|
236
351
|
|
|
237
|
-
|
|
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
|
-
|
|
379
|
+
## Important notes
|
|
240
380
|
|
|
241
|
-
-
|
|
242
|
-
-
|
|
243
|
-
-
|
|
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.
|