flow-frame-core 0.1.6 → 0.1.7

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 (3) hide show
  1. package/README.md +32 -0
  2. package/TOOLS.md +1080 -0
  3. package/package.json +2 -1
package/README.md CHANGED
@@ -43,6 +43,38 @@ Detailed documentation is available in the `docs/` folder:
43
43
  - **[Email Automation](docs/email_automation.md)**: Gmail polling and filtering.
44
44
  - **[Workflows](docs/workflows.md)**: How to build and run workflows.
45
45
 
46
+ ## 🔧 Tool Reference (for Agent Integration)
47
+
48
+ `flow-frame-core` is designed to be used as a tool library by AI agents. The complete tool glossary is in **[TOOLS.md](./TOOLS.md)**, covering every function and REST endpoint organized by capability:
49
+
50
+ | Category | Tools | Integration |
51
+ |----------|-------|-------------|
52
+ | **LLM / AI** | `runPrompt`, `runPromptGrok`, `runImagePromptGrok` | Import or `POST /api/prompts/chat` |
53
+ | **Prompt Chains** | `executeChain` — serial/parallel steps with auto-repair | Import |
54
+ | **Workflow Engine** | `executeFlow` — 25+ node types in a DAG | Import or REST |
55
+ | **JSON Utilities** | `extractJSON`, `cleanJSONString`, `containsJSON` | Import |
56
+ | **Schema & Code Gen** | `inferSchema`, `generateJsTransformFromPrompt` | Import |
57
+ | **Prompt Optimization** | `runAutoPromptSearch` — iterative prompt refinement | Import |
58
+ | **Image Analysis** | `classifyImageQuery`, `findImageInImage` | Import or REST |
59
+ | **Audio / TTS** | `processAudio` — ElevenLabs TTS | Import or `POST /generateAudio` |
60
+ | **PDF Processing** | `extractPdf` — text, images, page renders | Import or `GET /pdf/extract` |
61
+ | **Email** | `extractGmailBodyText`, polling endpoints | Import or REST |
62
+ | **Web Scraping** | `crawl` — full-site depth-first crawl | Import or `POST /scrape` |
63
+ | **Storage** | `getItem`, `setItem`, profile management | Import or REST |
64
+ | **Queue** | `queueManager` — serial job queue with events | Import or REST |
65
+ | **File System** | 30+ file utilities (read, write, download, zip) | Import or REST |
66
+ | **Templates** | `generateTextFromTemplate` — LLM variable generation | Import or REST |
67
+ | **Browser / Desktop** | Chrome control, mouse, keyboard, app management | Import or REST |
68
+ | **Screenshots** | `captureScreenshotBase64`, `captureFullScreenshot` | Import or REST |
69
+ | **Self-Learning Vision** | Ingest, recognize, discover screens, transition graphs | Import or REST |
70
+ | **UI Planning** | `UiPlanner`, `StepByStepAiPlanner` — NL → automation steps | Import |
71
+ | **Workflows CRUD** | Create, load, save, validate `.workflow` files | REST |
72
+ | **Extensions** | Plugin discovery and execution via `api.json` | Import or REST |
73
+ | **Media** | Video/audio dimensions, YOLO training data | Import or REST |
74
+ | **Config** | File-based config CRUD with backup/validation | REST |
75
+
76
+ See **[TOOLS.md](./TOOLS.md)** for full function signatures, parameters, return types, and REST endpoint details.
77
+
46
78
  ## 🌟 Key Features
47
79
 
48
80
  - **Agentic UI Planning**: Deeply integrated AI that maps web pages and uses `robotjs` to simulate human clicks and typing.
package/TOOLS.md ADDED
@@ -0,0 +1,1080 @@
1
+ # Flow-Frame Tool Reference
2
+
3
+ > Complete glossary of every capability in `flow-frame-core` that can be used as a tool by an external agent (e.g. Woodbury).
4
+
5
+ **Package**: `flow-frame-core`
6
+ **Install**: `npm install flow-frame-core`
7
+ **Runtime**: Node.js 18+, ESM (`"type": "module"`)
8
+ **Two integration modes**: Import functions directly (programmatic), or run the server and call HTTP endpoints (REST API).
9
+
10
+ ---
11
+
12
+ ## Table of Contents
13
+
14
+ - [1. LLM / AI](#1-llm--ai)
15
+ - [2. Prompt Chains](#2-prompt-chains)
16
+ - [3. Workflow Engine](#3-workflow-engine)
17
+ - [4. JSON Utilities](#4-json-utilities)
18
+ - [5. Schema & Code Generation](#5-schema--code-generation)
19
+ - [6. Prompt Optimization](#6-prompt-optimization)
20
+ - [7. Image Analysis](#7-image-analysis)
21
+ - [8. Audio / TTS](#8-audio--tts)
22
+ - [9. PDF Processing](#9-pdf-processing)
23
+ - [10. Email](#10-email)
24
+ - [11. Web Scraping](#11-web-scraping)
25
+ - [12. Storage](#12-storage)
26
+ - [13. Queue Management](#13-queue-management)
27
+ - [14. File System Utilities](#14-file-system-utilities)
28
+ - [15. Template & Variable Generation](#15-template--variable-generation)
29
+ - [16. Browser & Desktop Automation](#16-browser--desktop-automation)
30
+ - [17. Screenshot & Screen Capture](#17-screenshot--screen-capture)
31
+ - [18. Self-Learning Vision Pipeline](#18-self-learning-vision-pipeline)
32
+ - [19. UI Automation Planning](#19-ui-automation-planning)
33
+ - [20. Workflow File Management](#20-workflow-file-management)
34
+ - [21. Extension System](#21-extension-system)
35
+ - [22. Media Processing](#22-media-processing)
36
+ - [23. Configuration Management](#23-configuration-management)
37
+ - [24. Constants & Selectors](#24-constants--selectors)
38
+ - [REST API Quick Reference](#rest-api-quick-reference)
39
+
40
+ ---
41
+
42
+ ## 1. LLM / AI
43
+
44
+ Send prompts to OpenAI or Groq models. All functions auto-route based on model name prefix.
45
+
46
+ ### `runPrompt(messages, model, images?, jsonMode?, timeout?)`
47
+
48
+ **Import**: `import { runPrompt } from 'flow-frame-core/services/runPrompt.js'`
49
+
50
+ The unified LLM call. Routes to Groq for non-GPT models, OpenAI otherwise.
51
+
52
+ | Param | Type | Default | Description |
53
+ |-------|------|---------|-------------|
54
+ | `messages` | `{role, content}[]` | required | Chat message array |
55
+ | `model` | `string` | required | Model ID (e.g. `'gpt-4o'`, `'meta-llama/llama-4-scout-17b-16e-instruct'`) |
56
+ | `images` | `string[]` | `[]` | Base64 image data URLs to attach |
57
+ | `jsonMode` | `boolean` | `false` | Request JSON output format |
58
+ | `timeout` | `number` | `600000` | Timeout in ms |
59
+
60
+ **Returns**: `string` — the model's response text.
61
+
62
+ **REST**: `POST /api/prompts/chat`
63
+ ```json
64
+ { "messages": [...], "model": "gpt-4o", "jsonMode": false }
65
+ → { "success": true, "result": "..." }
66
+ ```
67
+
68
+ ---
69
+
70
+ ### `runPromptGrok(messages, model, jsonMode?, maxRetries?, baseDelay?)`
71
+
72
+ **Import**: `import { runPromptGrok } from 'flow-frame-core'`
73
+
74
+ Groq-specific with exponential backoff retry on 503 capacity errors.
75
+
76
+ | Param | Type | Default | Description |
77
+ |-------|------|---------|-------------|
78
+ | `messages` | `{role, content}[]` | required | Chat messages |
79
+ | `model` | `string` | required | Groq model ID |
80
+ | `jsonMode` | `boolean` | `false` | JSON response mode |
81
+ | `maxRetries` | `number` | `3` | Max retry attempts |
82
+ | `baseDelay` | `number` | `15000` | Base backoff delay in ms |
83
+
84
+ **Returns**: `string` — response content.
85
+
86
+ ---
87
+
88
+ ### `runImagePromptGrok(prompt, base64_image, model?)`
89
+
90
+ **Import**: `import { runImagePromptGrok } from 'flow-frame-core'`
91
+
92
+ Send a text prompt with an image to Groq's vision model.
93
+
94
+ | Param | Type | Default | Description |
95
+ |-------|------|---------|-------------|
96
+ | `prompt` | `string` | required | Text prompt |
97
+ | `base64_image` | `string` | required | Base64 data URL of the image |
98
+ | `model` | `string` | `'meta-llama/llama-4-scout-17b-16e-instruct'` | Vision model |
99
+
100
+ **Returns**: `string` — response text.
101
+
102
+ **REST**: `POST /analyze-image-grok`
103
+ ```json
104
+ { "prompt": "Describe this image", "base64_image": "data:image/png;base64,..." }
105
+ → { "result": "..." }
106
+ ```
107
+
108
+ ---
109
+
110
+ ### `processLLMResponse(response, model, provider?)`
111
+
112
+ **Import**: `import { processLLMResponse } from 'flow-frame-core/services/runPrompt.js'`
113
+
114
+ Parse JSON from raw LLM output. On failure, asks the same model to repair the output.
115
+
116
+ | Param | Type | Description |
117
+ |-------|------|-------------|
118
+ | `response` | `string` | Raw LLM text |
119
+ | `model` | `string` | Model to use for repair |
120
+ | `provider` | `string` | `'grok'` or `'openai'` |
121
+
122
+ **Returns**: Parsed object or repaired JSON.
123
+
124
+ ---
125
+
126
+ ## 2. Prompt Chains
127
+
128
+ Execute multi-step prompt sequences with validation and auto-repair.
129
+
130
+ ### `executeChain({ chainDef, prompts, input?, preamble?, precontext?, serverUrl?, model?, logFn?, promptExecutor? })`
131
+
132
+ **Import**: `import { executeChain } from 'flow-frame-core/services/chainExecutor.js'`
133
+
134
+ Runs a chain of prompts in sequence or parallel, accumulating context across steps.
135
+
136
+ | Param | Type | Default | Description |
137
+ |-------|------|---------|-------------|
138
+ | `chainDef` | `object` | required | `{ steps: Step[] }` — each step is `{ promptKey, expectations? }` or an array (parallel block) |
139
+ | `prompts` | `object` | required | Map of prompt keys to prompt text strings |
140
+ | `input` | `string\|object` | `undefined` | Initial input/context |
141
+ | `preamble` | `string` | `undefined` | System preamble prepended to each step |
142
+ | `precontext` | `string` | `undefined` | Additional context |
143
+ | `serverUrl` | `string` | `undefined` | Base URL for API (mutually exclusive with `promptExecutor`) |
144
+ | `model` | `string` | `'gpt-4'` | LLM model ID |
145
+ | `logFn` | `function` | `console.log` | Logging callback |
146
+ | `promptExecutor` | `function` | `null` | Direct prompt execution function (bypasses HTTP) |
147
+
148
+ **Returns**: `{ result: object, history: StepResult[] }`
149
+
150
+ Each step with `expectations` triggers an LLM QA validation loop — if the output doesn't match expectations, a repair agent rewrites it (max 2 retries).
151
+
152
+ **Parallel blocks**: Wrap steps in an array to run them concurrently:
153
+ ```js
154
+ {
155
+ steps: [
156
+ { promptKey: 'step1' }, // serial
157
+ [{ promptKey: 'a' }, { promptKey: 'b' }], // parallel
158
+ { promptKey: 'step3' } // serial
159
+ ]
160
+ }
161
+ ```
162
+
163
+ ---
164
+
165
+ ## 3. Workflow Engine
166
+
167
+ Execute visual node-graph workflows (DAGs).
168
+
169
+ ### `executeFlow(nodes, edges, workflows, modelContext, initialCtx?, callback?, globalContext?)`
170
+
171
+ **Import**: `import { executeFlow } from 'flow-frame-core'`
172
+
173
+ The core workflow runtime. Topologically sorts a node-edge graph and executes each node.
174
+
175
+ | Param | Type | Description |
176
+ |-------|------|-------------|
177
+ | `nodes` | `Node[]` | Array of node objects with `{ id, type, data }` |
178
+ | `edges` | `Edge[]` | Array of `{ source, sourceHandle, target, targetHandle }` |
179
+ | `workflows` | `object` | Named workflow configs for subgraph references |
180
+ | `modelContext` | `object` | Configuration: `{ defaultServer?, loadConfiguration?, loadPromptLibrary?, promptExecutor?, extensionController? }` |
181
+ | `initialCtx` | `object` | `{}` — pre-populated node values |
182
+ | `callback` | `function` | `(nodeId, progress) => void` |
183
+ | `globalContext` | `object` | `{}` — shared mutable state across subgraphs |
184
+
185
+ #### Supported Node Types
186
+
187
+ | Node Type | Purpose |
188
+ |-----------|---------|
189
+ | **Data** | |
190
+ | `inputNode` | Reads named input or default value |
191
+ | `setNode` | Sets a key on modelContext |
192
+ | `getNode` | Reads a key from modelContext |
193
+ | `propertyNode` | Deep property access (dot notation) |
194
+ | `arrayItemNode` | Array index access |
195
+ | `inputArrayNode` | Parse raw JSON array |
196
+ | `globalNode` | Write to shared globalContext |
197
+ | `globalGetNode` | Read from globalContext (dot notation + default) |
198
+ | `resultNode` | Capture subgraph output |
199
+ | `outputNode` | POST result to a URL |
200
+ | **AI / Prompts** | |
201
+ | `promptNode` | LLM prompt with system/user/images handles |
202
+ | `autoPromptOptimizerNode` | Find best prompt via iterative search |
203
+ | `uiPlannerNode` | AI-powered UI automation planning |
204
+ | `uiPlannerExecNode` | Execute a UI plan's steps |
205
+ | **Control Flow** | |
206
+ | `switchNode` | Pattern-match input → route to handles |
207
+ | `ifNode` | Conditional branch (inline subgraphs) |
208
+ | `ifWorkflowNode` | Conditional branch (named workflow configs) |
209
+ | `ifGraphNode` | Conditional branch (automation ID match) |
210
+ | `forEachNode` | Iterate array → execute named graph per item |
211
+ | `forLoopNode` | Iterate array → execute inline bodyGraph per item |
212
+ | `pauseNode` | Sleep N seconds |
213
+ | **Network** | |
214
+ | `fetchNode` | HTTP request (method, timeout, body, response type) |
215
+ | `gmailNode` | Read filtered emails |
216
+ | `pollerNode` | Poll emails + LLM-route to labeled subgraphs |
217
+ | **Composition** | |
218
+ | `workflowNode` | Execute named workflow |
219
+ | `smartAutomationNode` | Execute named smart automation |
220
+ | `graphNode` | Load + execute named workflow config |
221
+ | **Code** | |
222
+ | `execJSNode` | Run arbitrary JS (inputs a-g, access to utils/fs/path/$global) |
223
+ | **Extensions** | |
224
+ | `extensionNode` | Resolve + run an extension by capability ID |
225
+ | **UI Map** | |
226
+ | `uiMapSelectorNode` | Generate UI map from workflow files |
227
+ | `uiMapProcessorNode` | Pass-through |
228
+ | `uiMapChatNode` | Return generated context |
229
+ | `uiDependencyGraphNode` | Parse bodyGraph JSON |
230
+
231
+ ### `computeExecutionOrder(nodes, edges)`
232
+
233
+ Kahn's topological sort on a node graph. Returns ordered node array.
234
+
235
+ ### `getSubgraph(startId, nodes, edges)`
236
+
237
+ BFS extraction of reachable nodes/edges from a start node.
238
+
239
+ ---
240
+
241
+ ## 4. JSON Utilities
242
+
243
+ Robust JSON extraction from messy LLM output.
244
+
245
+ ### `extractJSON(input)`
246
+
247
+ **Import**: `import { extractJSON } from 'flow-frame-core'`
248
+
249
+ Strips markdown fences, prose preambles, and parses JSON. Returns objects as-is.
250
+
251
+ | Param | Type | Description |
252
+ |-------|------|-------------|
253
+ | `input` | `string\|object` | Raw text or object |
254
+
255
+ **Returns**: Parsed object, or `null` on failure.
256
+
257
+ ### `cleanJSONString(str)`
258
+
259
+ Strips markdown code fences, text wrappers, normalizes escapes to isolate raw JSON.
260
+
261
+ ### `safeExtractJSON(input, options?)`
262
+
263
+ Wraps `extractJSON` with configurable fallback: `{ returnOriginalOnFail?, defaultValue?, throwOnError? }`.
264
+
265
+ ### `containsJSON(str)`
266
+
267
+ Returns `true` if string contains parseable JSON.
268
+
269
+ ### `extractMultipleJSON(str)`
270
+
271
+ Finds all JSON objects in a string. Returns `object[]`.
272
+
273
+ ---
274
+
275
+ ## 5. Schema & Code Generation
276
+
277
+ ### `inferSchema(prompt, model)`
278
+
279
+ **Import**: `import { inferSchema } from 'flow-frame-core/services/schemaInference.js'`
280
+
281
+ Uses OpenAI to generate a JSON Schema (draft-07) describing what a prompt's output should look like.
282
+
283
+ | Param | Type | Description |
284
+ |-------|------|-------------|
285
+ | `prompt` | `string` | The prompt to analyze |
286
+ | `model` | `string` | OpenAI model to use |
287
+
288
+ **Returns**: Parsed JSON Schema object.
289
+
290
+ ---
291
+
292
+ ### `generateJsTransformFromPrompt(opts)`
293
+
294
+ **Import**: `import { generateJsTransformFromPrompt } from 'flow-frame-core/services/generateJsTransformFromPrompt.js'`
295
+
296
+ Uses an LLM to generate a sandboxed JavaScript transform function from a natural language description.
297
+
298
+ | Param | Type | Default | Description |
299
+ |-------|------|---------|-------------|
300
+ | `opts.prompt` | `string` | required | Natural language description of the transform |
301
+ | `opts.inputSchema` | `object` | `undefined` | JSON Schema for input validation |
302
+ | `opts.outputSchema` | `object` | `undefined` | JSON Schema for output validation |
303
+ | `opts.examples` | `{input, expected}[]` | `[]` | Test cases |
304
+ | `opts.allowNet` | `boolean` | `false` | Allow network access in sandbox |
305
+ | `opts.maxExecMs` | `number` | `5000` | Sandbox execution timeout |
306
+ | `opts.model` | `string` | `'meta-llama/llama-4-maverick'` | LLM model |
307
+ | `opts.retries` | `number` | `3` | Retry count on failure |
308
+
309
+ **Returns**: `{ code: string, tests: object[], notes: string, plan: string, attempts: number, transform: Function }`
310
+
311
+ ---
312
+
313
+ ## 6. Prompt Optimization
314
+
315
+ ### `runAutoPromptSearch(taskConfig?, opts?)`
316
+
317
+ **Import**: `import { runAutoPromptSearch } from 'flow-frame-core/services/autoPromptOptimizer.js'`
318
+
319
+ Iterative prompt optimization: generates candidate system prompts, evaluates them on a dataset, feeds top performers back.
320
+
321
+ | Param | Type | Default | Description |
322
+ |-------|------|---------|-------------|
323
+ | `taskConfig` | `TaskConfig` | `TASK_CONFIG` | Task definition with dataset |
324
+ | `opts.maxIterations` | `number` | `5` | Search iterations |
325
+ | `opts.promptsPerRound` | `number` | `3` | Candidates per round |
326
+ | `opts.topPromptsToFeedBack` | `number` | `2` | Best prompts to feed back |
327
+ | `opts.model` | `string` | `DEFAULT_MODEL` | LLM model |
328
+
329
+ **Returns**: `{ bestPrompt: { name, text, avgScore }, allResults: object[] }`
330
+
331
+ #### Helpers
332
+
333
+ - `createTaskConfig(overrides)` — merge overrides onto base template
334
+ - `addDatasetExamples(taskConfig, examples)` — append examples to dataset
335
+ - `buildDatasetExample({ id, input, expectedOutput })` — construct one example
336
+
337
+ ---
338
+
339
+ ## 7. Image Analysis
340
+
341
+ Vision-model queries on images.
342
+
343
+ ### `classifyImageQuery(model, question, image)` / `classifyImageQuestion({...})`
344
+
345
+ **Import**: `import { classifyImageQuery } from 'flow-frame-core'`
346
+
347
+ Ask a yes/no question about an image.
348
+
349
+ | Param | Type | Description |
350
+ |-------|------|-------------|
351
+ | `model` | `string` | Vision model ID |
352
+ | `question` | `string` | Yes/no question |
353
+ | `image` | `string` | Base64 data URL |
354
+
355
+ **Returns**: `{ answer: 'yes'|'no', confidence: number, reason: string }`
356
+
357
+ ### `generalClassifyImageQuery(model, question, image)` / `generalClassifyImageQuestion({...})`
358
+
359
+ Ask any question about an image. Returns arbitrary JSON as specified in the question.
360
+
361
+ ### `findImageInImageQuery(model, imageA, imageB)` / `findImageInImage({...})`
362
+
363
+ Determine if imageA appears inside imageB.
364
+
365
+ **Returns**: `{ found: boolean, confidence: number, box: { x_center_rel, y_center_rel, width_rel, height_rel }, reason: string }`
366
+
367
+ **REST**: `POST /api/prompts/image-check`
368
+ ```json
369
+ { "base64_image": "data:image/...", "model": "..." }
370
+ → { "success": true, "result": { "hasText": true, "text": "...", "hasIcon": false } }
371
+ ```
372
+
373
+ ---
374
+
375
+ ## 8. Audio / TTS
376
+
377
+ ### `processAudio(filePath, text, voice, keepExisting?)`
378
+
379
+ **Import**: `import { processAudio } from 'flow-frame-core/services/audioService.js'`
380
+
381
+ Generate speech audio from text via ElevenLabs and save to disk.
382
+
383
+ | Param | Type | Default | Description |
384
+ |-------|------|---------|-------------|
385
+ | `filePath` | `string` | required | Output MP3 path |
386
+ | `text` | `string` | required | Text to synthesize |
387
+ | `voice` | `string` | required | ElevenLabs voice ID |
388
+ | `keepExisting` | `boolean` | `true` | Skip if file exists |
389
+
390
+ **Returns**: `{ audioPath: string, srtPath?: string }`
391
+
392
+ ### `generateAudio(text, voice, options?)`
393
+
394
+ Low-level: calls ElevenLabs API, returns raw buffer + alignment data.
395
+
396
+ **Returns**: `{ audioBuffer: Buffer, alignment: object }`
397
+
398
+ **REST**: `POST /generateAudio`
399
+ ```json
400
+ { "text": "Hello world", "filePath": "output.mp3", "voiceId": "..." }
401
+ → { "ok": true }
402
+ ```
403
+
404
+ ---
405
+
406
+ ## 9. PDF Processing
407
+
408
+ ### `extractPdf({ pdfPath?, pdfBuffer?, outDir, extractText?, extractImages?, renderPages?, pageRenderScale?, password? })`
409
+
410
+ **Import**: `import { extractPdf } from 'flow-frame-core/services/extractPdf.js'`
411
+
412
+ Extract text, images, and page renders from a PDF.
413
+
414
+ | Param | Type | Default | Description |
415
+ |-------|------|---------|-------------|
416
+ | `pdfPath` | `string` | — | Path to PDF file |
417
+ | `pdfBuffer` | `Buffer` | — | PDF as buffer (alternative to path) |
418
+ | `outDir` | `string` | required | Output directory |
419
+ | `extractText` | `boolean` | `true` | Extract text per page |
420
+ | `extractImages` | `boolean` | `true` | Extract embedded images |
421
+ | `renderPages` | `boolean` | `false` | Render pages to PNG |
422
+ | `pageRenderScale` | `number` | `2` | Render scale factor |
423
+ | `password` | `string` | — | PDF password |
424
+
425
+ **Returns**: `{ pdfPath, numPages, textByPage: string[], images: string[], renderedPages: string[] }`
426
+
427
+ **REST**: `GET /pdf/extract?pdfPath=...&outDir=...`
428
+ **REST**: `POST /pdf/extract-folder` — batch extract from a folder.
429
+
430
+ ---
431
+
432
+ ## 10. Email
433
+
434
+ ### `extractGmailBodyText(message)`
435
+
436
+ **Import**: `import { extractGmailBodyText } from 'flow-frame-core'`
437
+
438
+ Extract plain text from a Gmail API message object. Handles base64url decoding, MIME parts, HTML stripping.
439
+
440
+ | Param | Type | Description |
441
+ |-------|------|-------------|
442
+ | `message` | `object` | Gmail API message object |
443
+
444
+ **Returns**: `string` — extracted plain text.
445
+
446
+ ### Gmail Polling (server mode only)
447
+
448
+ The server runs a `FilterGmailPoller` singleton that exposes:
449
+
450
+ | Endpoint | Method | Description |
451
+ |----------|--------|-------------|
452
+ | `/api/emails` | GET | Paginated filtered inbox |
453
+ | `/api/emails/:id` | GET | Specific email by ID |
454
+ | `/api/stats` | GET | Email statistics |
455
+ | `/api/polling/start` | POST | Start polling |
456
+ | `/api/polling/stop` | POST | Stop polling |
457
+ | `/api/polling/status` | GET | Auth + polling state |
458
+ | `/api/config/filter` | PUT | Update filter config |
459
+
460
+ ---
461
+
462
+ ## 11. Web Scraping
463
+
464
+ ### `crawl(startUrl)`
465
+
466
+ **Import**: `import { crawl } from 'flow-frame-core/scraper.js'`
467
+
468
+ Depth-first crawl an entire website, staying on the same hostname.
469
+
470
+ | Param | Type | Description |
471
+ |-------|------|-------------|
472
+ | `startUrl` | `string` | Starting URL |
473
+
474
+ **Returns**: `Record<string, string>` — map of `{ url: pageText }`.
475
+
476
+ **REST**: `POST /scrape`
477
+ ```json
478
+ { "domain": "https://example.com" }
479
+ → { "startUrl": "...", "pages": [...] }
480
+ ```
481
+
482
+ ---
483
+
484
+ ## 12. Storage
485
+
486
+ JSON file-based key-value store with named profiles.
487
+
488
+ **Import**: `import { getItem, setItem, ... } from 'flow-frame-core'`
489
+
490
+ | Function | Params | Returns | Description |
491
+ |----------|--------|---------|-------------|
492
+ | `getItem(key)` | `string` | `any\|null` | Read a value by key |
493
+ | `setItem(key, value)` | `string, any` | `void` | Write a value by key |
494
+ | `listStorageProfiles()` | — | `string[]` | List available profiles |
495
+ | `getStorageProfile()` | — | `string` | Current active profile |
496
+ | `setStorageProfile(name)` | `string` | `void` | Switch active profile |
497
+ | `readStorageProfile(name)` | `string` | `object\|null` | Read a profile's full content |
498
+ | `saveStorageProfile(name, content)` | `string, any` | `void` | Save a profile |
499
+ | `deleteStorageProfile(name)` | `string` | `boolean` | Delete a profile (not `'default'`) |
500
+ | `isDocker()` | — | `boolean` | Detect Docker environment |
501
+
502
+ **REST endpoints**:
503
+ - `GET /storage-profiles` → `{ profiles, active }`
504
+ - `GET /storage-profiles/:name` → profile content
505
+ - `POST /storage-profiles` `{ name, content }` → create/update
506
+ - `DELETE /storage-profiles/:name` → delete
507
+ - `POST /storage-profiles/switch` `{ name }` → switch active
508
+ - `POST /get-key-value` `{ key }` → `{ value }`
509
+ - `POST /setObject` `{ key, value }` → `{ [key]: value }`
510
+
511
+ ---
512
+
513
+ ## 13. Queue Management
514
+
515
+ Serial job queue with progress tracking.
516
+
517
+ **Import**: `import queueManager from 'flow-frame-core'`
518
+
519
+ | Method | Params | Returns | Description |
520
+ |--------|--------|---------|-------------|
521
+ | `enqueue(fn)` | `(signal, progress) => Promise` | `number` (job ID) | Add job to queue |
522
+ | `status(id)` | `number` | `{ id, status, progress }\|null` | Check job status |
523
+ | `cancel(id)` | `number` | `boolean` | Cancel a running job |
524
+ | `list()` | — | `Job[]` | List all jobs |
525
+ | `waitForJobId(id, cb)` | `number, function` | `Promise` | Wait for job completion |
526
+
527
+ Events: `start`, `progress`, `done`, `aborted`, `error`.
528
+
529
+ **REST**:
530
+ - `GET /operations` → all queued jobs
531
+ - `GET /operations/:jobId/status` → job status
532
+ - `POST /operations/:jobId/cancel` → cancel job
533
+
534
+ ---
535
+
536
+ ## 14. File System Utilities
537
+
538
+ **Import**: `import { ... } from 'flow-frame-core'` (re-exported from utils.js)
539
+
540
+ | Function | Params | Returns | Description |
541
+ |----------|--------|---------|-------------|
542
+ | `ensureDir(dirPath)` | `string` | `Promise<void>` | Create directory recursively |
543
+ | `readProjectFile(filePath)` | `string` | `any[]` | Read JSON array or NDJSON file |
544
+ | `saveProjectFile(filePath, array)` | `string, any[]` | `void` | Write array as NDJSON |
545
+ | `downloadFile(url, destPath, onProgress?)` | `string, string, fn?` | `Promise<void>` | Download a file |
546
+ | `downloadFiles(urls, destFolder)` | `string[], string` | `Promise<string[]>` | Download multiple files |
547
+ | `deleteFileSync(filePath)` | `string` | `void` | Delete a file |
548
+ | `getFiles(dirPath)` | `string` | `Promise<string[]>` | List directory entries |
549
+ | `readJsonFiles(dirPath)` | `string` | `Promise<string[]>` | List `.json` file paths |
550
+ | `findFilesWithString(dir, str)` | `string, string` | `string[]` | Recursive file name search |
551
+ | `getDownloadsFolder()` | — | `string` | OS Downloads folder path |
552
+ | `unzipFile(zipPath, extractTo)` | `string, string` | `Promise<void>` | Extract zip file |
553
+ | `sanitizeFileName(name)` | `string` | `string` | Clean illegal characters |
554
+ | `sanitizeFolderName(name)` | `string` | `string` | Clean folder name |
555
+ | `getLastModifiedTimestampSync(path)` | `string` | `number` | File mtime in ms |
556
+ | `getSortedFilesByUpdatedAt(dir)` | `string` | `Promise<string[]>` | PNGs sorted by mtime |
557
+ | `createZipFromFolders(root, folders, name, opts?)` | various | `Promise<string>` | Create zip archive |
558
+ | `getLocalIp()` | — | `string` | Local IPv4 address |
559
+ | `applyTemplate(template, data)` | `string, object` | `string` | Fill `{key}` placeholders |
560
+ | `getMediaFileDuration(path)` | `string` | `Promise<number>` | Media duration in seconds |
561
+ | `getVideoDimensions(path)` | `string` | `Promise<{width,height}>` | Video pixel dimensions |
562
+ | `getVideoDuration(path)` | `string` | `Promise<{duration,width,height}>` | Full video info |
563
+
564
+ **REST**:
565
+ - `POST /readDir` `{ dirPath }` → directory listing
566
+ - `POST /readFiles` `{ filePaths }` → file contents
567
+ - `POST /readFile` `{ filePath, encoding? }` → single file content
568
+ - `POST /delete-files` `{ filePaths }` → per-file success/failure
569
+ - `POST /clear-directory` `{ directory }` → delete all files in dir
570
+ - `POST /moveFiles` `{ sourcePaths, destinationDir }` → move files
571
+ - `POST /waitForFiles` `{ directory, filePrefixes, timeout? }` → long-poll for file presence
572
+ - `POST /getFiles` `{ directory, filePrefixes, expectedCounts? }` → check file existence
573
+ - `POST /wait-for-file-stable` `{ file_path, min_size_mb?, max_wait_minutes? }` → wait for file to stop changing
574
+
575
+ ---
576
+
577
+ ## 15. Template & Variable Generation
578
+
579
+ Generate realistic fake data and fill templates.
580
+
581
+ ### `generateTextFromTemplate(template, entities, options?)`
582
+
583
+ **Import**: `import { generateTextFromTemplate } from 'flow-frame-core/services/variableGenerator.js'`
584
+
585
+ Full pipeline: generate entity values via LLM, then fill a template.
586
+
587
+ | Param | Type | Description |
588
+ |-------|------|-------------|
589
+ | `template` | `string` | Template with `{{KEY}}` placeholders |
590
+ | `entities` | `EntityDef[]` | `[{ key, type, description }]` |
591
+ | `options.model` | `string` | LLM model for generation |
592
+ | `options.reuseProbability` | `number` | 0-1 chance of reusing existing pool value |
593
+
594
+ **Returns**: `{ email: string, valuesByKey: object }`
595
+
596
+ ### `fillTemplate(template, valuesByKey)`
597
+
598
+ Simple `{{KEY}}` replacement without LLM.
599
+
600
+ ### `generateEntityValues(entities, options?)`
601
+
602
+ Generate values for all entities, managing the value pool.
603
+
604
+ **Returns**: `{ valuesByKey: object, pools: object }`
605
+
606
+ **REST**: `POST /generate-text-from-template`
607
+
608
+ ---
609
+
610
+ ## 16. Browser & Desktop Automation
611
+
612
+ Control the OS desktop, browser windows, mouse, and keyboard.
613
+
614
+ ### Browser Control
615
+
616
+ **Import**: `import { BrowserController } from 'flow-frame-core'`
617
+
618
+ | Method | Params | Description |
619
+ |--------|--------|-------------|
620
+ | `BrowserController.openChrome({ url })` | `string` | Open URL in Chrome |
621
+ | `BrowserController.closeChrome()` | — | Close Chrome |
622
+ | `BrowserController.closeChromeTab({ domain })` | `string` | Close tab by domain |
623
+ | `BrowserController.bringAppToFront({ appName })` | `string` | Focus an app window |
624
+ | `BrowserController.readFile({ filePath })` | `string` | Read a local file |
625
+
626
+ **REST**:
627
+ - `POST /openChrome` `{ url }`
628
+ - `POST /closeChrome`
629
+ - `POST /closeChromeTab` `{ domain }`
630
+ - `POST /bringAppToFront` `{ appName }`
631
+ - `POST /open-app` `{ appName }` — launch any app
632
+ - `POST /close-app` `{ appName, force? }` — kill any app
633
+
634
+ ### Mouse & Keyboard (requires robotjs)
635
+
636
+ **Import**: `import { moveMouse, mouseClick, ... } from 'flow-frame-core/operations.js'`
637
+
638
+ | Function | Params | Description |
639
+ |----------|--------|-------------|
640
+ | `moveMouse(position)` | `{left, top, height, width}` | Move mouse to element center (with browser chrome offset) |
641
+ | `moveMouseDesktop(position)` | `{left, top, height, width}` | Move mouse (no offset) |
642
+ | `moveMouseRelative(offset)` | `{left, top}` | Relative mouse move |
643
+ | `mouseClick()` | — | Left click at current position |
644
+ | `pressEscapeAsync()` | — | Press Escape key |
645
+ | `pressKey(params)` | `{keys, ctrl?, shift?, alt?}` | Press key with modifiers |
646
+ | `typeText(params)` | `{keys, ctrl?, shift?, alt?}` | Type key combo |
647
+ | `pasteText(text)` | `string` | Clipboard paste |
648
+ | `clearAllText()` | — | Select-all + delete |
649
+ | `pressReturn()` | — | Press Enter |
650
+ | `scroll(x?, y?)` | `number, number` | Scroll mouse wheel |
651
+ | `fileModalOperate(filePath)` | `string` | Navigate OS file picker |
652
+
653
+ ---
654
+
655
+ ## 17. Screenshot & Screen Capture
656
+
657
+ ### `captureScreenshotBase64(region?)`
658
+
659
+ **Import**: `import { captureScreenshotBase64 } from 'flow-frame-core/inference/capturescreenshot.js'`
660
+
661
+ Capture screen (or region) as base64 PNG data URL.
662
+
663
+ | Param | Type | Description |
664
+ |-------|------|-------------|
665
+ | `region` | `{x, y, width, height}` | Optional crop region |
666
+
667
+ **Returns**: `string` — `data:image/png;base64,...`
668
+
669
+ ### `captureFullScreenshot(targetFolder)`
670
+
671
+ Save full-screen capture as a PNG file.
672
+
673
+ **Returns**: `string` — filename.
674
+
675
+ ### `captureScreenshot(targetFolder, filename, region?)`
676
+
677
+ Save a named screenshot file.
678
+
679
+ **REST**: `POST /take-screenshot` `{ appName }` → `{ filename, filePath }`
680
+
681
+ ---
682
+
683
+ ## 18. Self-Learning Vision Pipeline
684
+
685
+ Computer vision system for recognizing and learning UI screens.
686
+
687
+ ### `ingestScreenshot({ imagePath, meta?, tags? })`
688
+
689
+ **Import**: `import { ingestScreenshot } from 'flow-frame-core/services/self-learning/injest.js'`
690
+
691
+ Ingest a screenshot: copies to store, computes perceptual hashes, logs event.
692
+
693
+ **Returns**: Event object with `{ aHash, dHash, width, height, ... }`.
694
+
695
+ ### `recognizeScreen(imagePath, options?)`
696
+
697
+ **Import**: `import { recognizeScreen } from 'flow-frame-core/services/self-learning/recognize.js'`
698
+
699
+ Match a screenshot against known screen signatures.
700
+
701
+ | Param | Type | Default | Description |
702
+ |-------|------|---------|-------------|
703
+ | `imagePath` | `string` | required | Path to screenshot |
704
+ | `options.topK` | `number` | `5` | Candidates to evaluate |
705
+ | `options.unknownThreshold` | `number` | — | Min score for a match |
706
+
707
+ **Returns**: `{ screenId, confidence, bestScore, candidates, reason? }`
708
+
709
+ ### `discoverScreens(options?)`
710
+
711
+ **Import**: `import { discoverScreens } from 'flow-frame-core/services/self-learning/discover.js'`
712
+
713
+ Cluster ingested screenshots and auto-generate screen signatures.
714
+
715
+ **Returns**: `{ learned, catalogs, clusters, message }`
716
+
717
+ ### `recordTransition({ takeScreenshot, recognizeScreen, performAction, action, meta? })`
718
+
719
+ Record a before/after screen state transition.
720
+
721
+ ### `buildTransitionGraph()` / `findPath(graph, start, goal)`
722
+
723
+ Build a directed graph of screen transitions; find shortest path between screens.
724
+
725
+ ### Perceptual Hashing
726
+
727
+ | Function | Description |
728
+ |----------|-------------|
729
+ | `aHashHex(imagePath)` | Average hash (64 hex chars) |
730
+ | `dHashHex(imagePath)` | Difference hash (64 hex chars) |
731
+ | `hammingHex(a, b)` | Hamming distance between hashes |
732
+ | `preScoreFromDistances(aDist, dDist)` | 0-1 similarity score |
733
+
734
+ ### Image Utilities
735
+
736
+ | Function | Description |
737
+ |----------|-------------|
738
+ | `fileToDataUrl(imagePath)` | Image file → base64 data URL |
739
+ | `cropToDataUrl({ imagePath, bbox })` | Crop region → base64 data URL |
740
+ | `getImageSize(imagePath)` | `{ width, height }` |
741
+
742
+ **REST**:
743
+ - `POST /recognize-screen-signature` `{ filePath }` → recognition result
744
+ - `POST /api/self-learning/injest` `{ imagePath, metadata?, tags? }` → event
745
+ - `POST /api/self-learning/discover` `{ ...options }` → discovery result
746
+ - `POST /api/self-learning/enhance` `{ userPrompt, model? }` → LLM response
747
+
748
+ ---
749
+
750
+ ## 19. UI Automation Planning
751
+
752
+ AI-powered planning that converts natural language into executable desktop automation steps.
753
+
754
+ ### `UiPlanner` class
755
+
756
+ **Import**: `import { UiPlanner } from 'flow-frame-core/services/uiPlanner.js'`
757
+
758
+ ```js
759
+ const planner = new UiPlanner(uiMap, pathFinder, macroRegistry, automationFiles);
760
+ const plan = await planner.plan('Upload a video titled "Hello"', 'home', {}, 'gpt-4o');
761
+ ```
762
+
763
+ **`plan(request, startStateId?, context?, model?)`** returns `{ steps: ExecutableStep[] }`.
764
+
765
+ ### `StepByStepAiPlanner` class
766
+
767
+ **Import**: `import { StepByStepAiPlanner } from 'flow-frame-core/services/stepByStepAiPlanner.js'`
768
+
769
+ Extends `UiPlanner` with dependency-graph-aware planning. Identifies key automation steps by ID rather than generating field-level goals.
770
+
771
+ ### `generateUIMap(files)`
772
+
773
+ **Import**: `import { generateUIMap } from 'flow-frame-core/services/uiMapService.js'`
774
+
775
+ Build a UI state machine map from automation recording files.
776
+
777
+ | Param | Type | Description |
778
+ |-------|------|-------------|
779
+ | `files` | `string[]` | Paths to `.automation` files |
780
+
781
+ **Returns**: `{ version, states, edges }`
782
+
783
+ **REST**: `POST /generate-ui-map` `{ files }` → `{ uiMap }`
784
+
785
+ ---
786
+
787
+ ## 20. Workflow File Management
788
+
789
+ CRUD for workflow/automation files.
790
+
791
+ ### Programmatic
792
+
793
+ **Import**: `import { WorkflowController } from 'flow-frame-core'`
794
+
795
+ | Method | Params | Description |
796
+ |--------|--------|-------------|
797
+ | `loadConfiguration({ name, configFolder })` | `string, string` | Load a `.workflow` file |
798
+ | `getWorkflowConfig({ name, workflowDictionary })` | `string, object` | Lookup from in-memory dictionary |
799
+
800
+ ### `buildWorkflowDirectory(jsonInput, targetDir)`
801
+
802
+ Materialize a `{ files: [{ path, content }] }` structure to disk.
803
+
804
+ ### `runWorkflowCLI(targetDir, workflowJsonPath?, parameters?)`
805
+
806
+ Run `node src/cli.js` in a target directory.
807
+
808
+ ### `installDependencies(targetDir)`
809
+
810
+ Run `npm install` in a target directory.
811
+
812
+ **REST**:
813
+ - `GET /configurations` → list all config files
814
+ - `GET /loadConfiguration?name=...` → load config
815
+ - `POST /saveConfiguration` `{ name, nodes, edges }` → save
816
+ - `POST /buildWorkflowDirectory` `{ jsonInput, targetDir }`
817
+ - `POST /runWorkflowCLI` `{ targetDir, workflowJsonPath?, parameters? }`
818
+ - `POST /installDependencies` `{ targetDir }`
819
+ - Full step-workflow CRUD at `/api/workflows/*` (see REST API section)
820
+
821
+ ---
822
+
823
+ ## 21. Extension System
824
+
825
+ Discover and run pluggable npm-based extensions.
826
+
827
+ ### `scanExtensions(extensionFolders)`
828
+
829
+ **Import**: `import { scanExtensions } from 'flow-frame-core/extensionUtils.js'`
830
+
831
+ Scan directories for subdirectories containing `api.json` files.
832
+
833
+ | Param | Type | Description |
834
+ |-------|------|-------------|
835
+ | `extensionFolders` | `string\|string[]` | Paths to scan |
836
+
837
+ **Returns**: `{ location, ...apiJsonData }[]`
838
+
839
+ ### `ExtensionController`
840
+
841
+ **Import**: `import { ExtensionController } from 'flow-frame-core'`
842
+
843
+ | Method | Description |
844
+ |--------|-------------|
845
+ | `getExtensions({ extensionFolders })` | Scan and return extensions |
846
+ | `getExtensionFolders()` | Get configured folders |
847
+ | `installDependencies({ targetDir })` | npm install in extension dir |
848
+ | `runWorkflowCLI({ targetDir, workflowJsonPath, parameters })` | Run extension CLI |
849
+
850
+ **REST**: `GET /get-extensions` → `{ extensions: [...] }`
851
+
852
+ ---
853
+
854
+ ## 22. Media Processing
855
+
856
+ ### Video/Audio
857
+
858
+ | Function | Params | Returns | Description |
859
+ |----------|--------|---------|-------------|
860
+ | `getMediaFileDuration(path)` | `string` | `Promise<number>` | Duration in seconds |
861
+ | `getVideoDimensions(path)` | `string` | `Promise<{width,height}>` | Pixel dimensions |
862
+ | `getVideoDuration(path)` | `string` | `Promise<{duration,width,height}>` | Full video info |
863
+ | `processFile(targetFile)` | `string` | `void` | Process project file through media pipeline |
864
+ | `fix(text)` | `string` | `string` | Sanitize for filename/prompt use |
865
+
866
+ **REST**:
867
+ - `POST /get-video-dimensions` `{ filePath }` → dimensions
868
+ - `POST /getAudioDurations` `{ audioFiles, videos }` → duration map
869
+ - `GET /image-dimensions/:name` → `{ width, height }`
870
+ - `POST /get-media-dimensions` `{ imageName }` or `{ videoName, timestamp }` → dimensions
871
+
872
+ ### YOLO Training Data
873
+
874
+ **REST**:
875
+ - `GET /fetch-training-folders` → folder names
876
+ - `GET /fetch-training-data/:folder/:size` → YAML config as JSON
877
+ - `GET /list-images/:folder/:size/:split` → image filenames
878
+ - `GET /fetch-labels/:folder/:size/:split/:image` → YOLO bounding boxes
879
+
880
+ ---
881
+
882
+ ## 23. Configuration Management
883
+
884
+ File-based config CRUD.
885
+
886
+ **REST**:
887
+
888
+ | Method | Path | Description |
889
+ |--------|------|-------------|
890
+ | GET | `/api/config/files` | List all config files + folder tree |
891
+ | GET | `/api/config/file/:name` | Read a config file |
892
+ | POST | `/api/config/file/:name` | Save/update (with optional backup) |
893
+ | POST | `/api/config/create` | Create new config file |
894
+ | DELETE | `/api/config/file/:name` | Delete (with optional backup) |
895
+ | PUT | `/api/config/rename/:name` | Rename a config file |
896
+ | POST | `/api/config/validate/:name` | Validate file content |
897
+ | GET | `/api/config/info` | Config folder metadata |
898
+
899
+ ---
900
+
901
+ ## 24. Constants & Selectors
902
+
903
+ **Import**: `import { KEYS, MODES, SUNO_SELECTORS, YOUTUBE_SELECTORS } from 'flow-frame-core'`
904
+
905
+ ### `MODES`
906
+
907
+ Operating mode constants:
908
+ - `MIDJOURNEY`, `MIDJOURNEY_IMAGES_TO_VIDEO`, `MIDJOURNEY_DOWNLOAD_MEDIA`, `MIDJOURNEY_DOWNLOAD_PUBLIC_MEDIA`
909
+ - `CLEAR_MIDJOURNEY_IMAGES`
910
+ - `SUNO`, `SUNO_FILM`
911
+ - `YOUTUBE`
912
+ - `FLOW_FRAME`
913
+
914
+ ### `KEYS`
915
+
916
+ 80+ storage key constants for all configuration, paths, and state:
917
+ - Folder paths: `workflow_folder`, `ui_map_folder`, `prompt_lib_folder`, `media_folder`, `audio_folder`, `video_folder`, `config_folder`, `learning_dir`, `extension_folders`, `training_jobs_folder`
918
+ - LLM config: `default_llm_model`, `default_llm_multi_modal_model`
919
+ - Mode/state: `mode`, `procedure`, `sourceFile`, `current_folder`, `images_folder`
920
+ - Suno state: `suno_state`, `suno_current_name`
921
+ - UI automation: `boxes`, `element_selectors`, `chrome_requests`
922
+ - And many more.
923
+
924
+ ### `SUNO_SELECTORS` / `YOUTUBE_SELECTORS`
925
+
926
+ CSS selector maps for Suno and YouTube Studio UI elements.
927
+
928
+ ---
929
+
930
+ ## REST API Quick Reference
931
+
932
+ All endpoints assume `Content-Type: application/json` unless noted. Server runs on port configured in `peers.ts` (default 3000).
933
+
934
+ ### Core
935
+
936
+ | Method | Path | Purpose |
937
+ |--------|------|---------|
938
+ | GET | `/` | Health check |
939
+ | GET | `/health` | Detailed health (uptime, memory, WS count) |
940
+ | GET | `/health/detailed` | Full process info |
941
+
942
+ ### LLM
943
+
944
+ | Method | Path | Purpose |
945
+ |--------|------|---------|
946
+ | POST | `/api/prompts/chat` | Run LLM prompt |
947
+ | POST | `/api/prompts/image-check` | Analyze image for text/icons |
948
+ | POST | `/analyze-image-grok` | Vision model image analysis |
949
+
950
+ ### Workflows
951
+
952
+ | Method | Path | Purpose |
953
+ |--------|------|---------|
954
+ | GET | `/configurations` | List workflow configs |
955
+ | GET | `/loadConfiguration?name=` | Load a workflow |
956
+ | POST | `/saveConfiguration` | Save a workflow |
957
+ | GET | `/api/workflows` | List automation workflows |
958
+ | GET | `/api/workflows/:id` | Get workflow |
959
+ | POST | `/api/workflows/:id` | Save workflow |
960
+ | DELETE | `/api/workflows/:id` | Delete workflow |
961
+ | POST | `/api/workflows/:id/execute` | Execute workflow steps |
962
+ | POST | `/api/workflows/:id/validate` | Validate workflow |
963
+ | POST | `/api/workflows/:id/duplicate` | Duplicate workflow |
964
+ | POST | `/api/workflows/import` | Import workflow file |
965
+
966
+ ### Storage & Config
967
+
968
+ | Method | Path | Purpose |
969
+ |--------|------|---------|
970
+ | POST | `/get-key-value` | Get storage value |
971
+ | POST | `/setObject` | Set storage value |
972
+ | GET | `/storage-profiles` | List profiles |
973
+ | POST | `/storage-profiles/switch` | Switch profile |
974
+ | GET | `/api/config/files` | List config files |
975
+ | GET | `/api/config/file/:name` | Read config |
976
+ | POST | `/api/config/file/:name` | Save config |
977
+
978
+ ### Files
979
+
980
+ | Method | Path | Purpose |
981
+ |--------|------|---------|
982
+ | POST | `/readDir` | List directory |
983
+ | POST | `/readFile` | Read file |
984
+ | POST | `/readFiles` | Read multiple files |
985
+ | POST | `/delete-files` | Delete files |
986
+ | POST | `/moveFiles` | Move files |
987
+ | POST | `/waitForFiles` | Wait for files to appear |
988
+ | POST | `/wait-for-file-stable` | Wait for file to stabilize |
989
+
990
+ ### Browser & Desktop
991
+
992
+ | Method | Path | Purpose |
993
+ |--------|------|---------|
994
+ | POST | `/openChrome` | Open Chrome URL |
995
+ | POST | `/closeChrome` | Close Chrome |
996
+ | POST | `/closeChromeTab` | Close Chrome tab |
997
+ | POST | `/bringAppToFront` | Focus app window |
998
+ | POST | `/open-app` | Launch application |
999
+ | POST | `/close-app` | Kill application |
1000
+ | POST | `/take-screenshot` | Capture screenshot |
1001
+ | POST | `/recognize-screen-signature` | Recognize UI screen |
1002
+
1003
+ ### Media
1004
+
1005
+ | Method | Path | Purpose |
1006
+ |--------|------|---------|
1007
+ | POST | `/generate-audio` | Generate audio from text |
1008
+ | POST | `/generateAudio` | TTS via ElevenLabs |
1009
+ | POST | `/get-video-dimensions` | Video dimensions |
1010
+ | POST | `/getAudioDurations` | Media durations |
1011
+ | GET | `/image-dimensions/:name` | Image dimensions |
1012
+ | GET | `/api/media` | List media files |
1013
+ | GET | `/api/media/:filename` | Serve media file |
1014
+ | POST | `/api/media/upload` | Upload media |
1015
+ | DELETE | `/api/media/:filename` | Delete media |
1016
+
1017
+ ### PDF
1018
+
1019
+ | Method | Path | Purpose |
1020
+ |--------|------|---------|
1021
+ | GET | `/pdf/extract` | Extract from PDF |
1022
+ | POST | `/pdf/extract-folder` | Extract from PDF folder |
1023
+
1024
+ ### Scraping
1025
+
1026
+ | Method | Path | Purpose |
1027
+ |--------|------|---------|
1028
+ | POST | `/scrape` | Crawl a website |
1029
+
1030
+ ### Self-Learning
1031
+
1032
+ | Method | Path | Purpose |
1033
+ |--------|------|---------|
1034
+ | POST | `/api/self-learning/injest` | Ingest screenshot |
1035
+ | POST | `/api/self-learning/discover` | Discover screens |
1036
+ | POST | `/api/self-learning/enhance` | LLM enhance prompt |
1037
+ | GET | `/api/self-learning/media-folder` | Get media folder |
1038
+ | POST | `/api/self-learning/media-folder` | Set media folder |
1039
+
1040
+ ### UI Maps & Prompt Libraries
1041
+
1042
+ | Method | Path | Purpose |
1043
+ |--------|------|---------|
1044
+ | GET | `/api/ui-maps` | List UI maps |
1045
+ | GET | `/api/ui-maps/:id` | Get UI map |
1046
+ | POST | `/api/ui-maps/:id` | Save UI map |
1047
+ | DELETE | `/api/ui-maps/:id` | Delete UI map |
1048
+ | POST | `/generate-ui-map` | Generate from files |
1049
+ | GET | `/api/prompt-libs` | List prompt libraries |
1050
+ | GET | `/api/prompt-libs/:id` | Get prompt library |
1051
+ | POST | `/api/prompt-libs/:id` | Save prompt library |
1052
+ | DELETE | `/api/prompt-libs/:id` | Delete prompt library |
1053
+
1054
+ ### Email
1055
+
1056
+ | Method | Path | Purpose |
1057
+ |--------|------|---------|
1058
+ | GET | `/api/emails` | Filtered inbox |
1059
+ | GET | `/api/emails/:id` | Email by ID |
1060
+ | GET | `/api/stats` | Email stats |
1061
+ | POST | `/api/polling/start` | Start polling |
1062
+ | POST | `/api/polling/stop` | Stop polling |
1063
+
1064
+ ### Extensions
1065
+
1066
+ | Method | Path | Purpose |
1067
+ |--------|------|---------|
1068
+ | GET | `/get-extensions` | List extensions |
1069
+ | POST | `/buildWorkflowDirectory` | Build from JSON |
1070
+ | POST | `/runWorkflowCLI` | Run workflow CLI |
1071
+ | POST | `/installDependencies` | npm install |
1072
+
1073
+ ### Training Data
1074
+
1075
+ | Method | Path | Purpose |
1076
+ |--------|------|---------|
1077
+ | GET | `/fetch-training-folders` | List training folders |
1078
+ | GET | `/fetch-training-data/:folder/:size` | Dataset config |
1079
+ | GET | `/list-images/:folder/:size/:split` | List images |
1080
+ | GET | `/fetch-labels/:folder/:size/:split/:image` | YOLO labels |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flow-frame-core",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -10,6 +10,7 @@
10
10
  "files": [
11
11
  "dist",
12
12
  "README.md",
13
+ "TOOLS.md",
13
14
  "LICENSE"
14
15
  ],
15
16
  "keywords": [