takomi 2.1.38 → 2.1.39

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 (88) hide show
  1. package/.agents/plugins/marketplace.json +32 -0
  2. package/.pi/agents/architect.md +4 -2
  3. package/.pi/agents/designer.md +2 -0
  4. package/.pi/agents/orchestrator.md +9 -9
  5. package/.pi/prompts/design-prompt.md +3 -1
  6. package/.pi/prompts/genesis-prompt.md +2 -0
  7. package/.pi/prompts/takomi-prompt.md +10 -9
  8. package/README.md +38 -24
  9. package/assets/.agent/skills/takomi-flow/SKILL.md +235 -0
  10. package/assets/.agent/workflows/README.md +3 -3
  11. package/assets/.agent/workflows/mode-architect.md +7 -5
  12. package/assets/.agent/workflows/vibe-design.md +3 -1
  13. package/assets/.agent/workflows/vibe-genesis.md +2 -0
  14. package/assets/Takomi-Agents/custom_modes.yaml +1253 -1252
  15. package/assets/Takomi-Agents/vibe-architect.yaml +11 -6
  16. package/assets/Takomi-Agents/vibe-orchestrator.yaml +2 -2
  17. package/docs/features/TakomiFlow_Portable_Plugin.md +78 -0
  18. package/docs/takomi-flow-onboarding.md +76 -0
  19. package/docs/takomi-flow-public-distribution.md +94 -0
  20. package/package.json +19 -2
  21. package/plugins/takomi-codex/.codex-plugin/plugin.json +37 -0
  22. package/plugins/takomi-codex/assets/composer-icon.png +0 -0
  23. package/plugins/takomi-codex/assets/logo-dark.png +0 -0
  24. package/plugins/takomi-codex/assets/logo.png +0 -0
  25. package/plugins/takomi-codex/scripts/takomi-board.ps1 +197 -0
  26. package/plugins/takomi-codex/scripts/takomi-detect.ps1 +125 -0
  27. package/plugins/takomi-codex/scripts/takomi-doctor.ps1 +88 -0
  28. package/plugins/takomi-codex/scripts/takomi-harness.ps1 +52 -0
  29. package/plugins/takomi-codex/scripts/takomi-pi-dispatch.ps1 +93 -0
  30. package/plugins/takomi-codex/scripts/takomi-policy.ps1 +108 -0
  31. package/plugins/takomi-codex/skills/takomi-codex/SKILL.md +194 -0
  32. package/plugins/takomi-flow/.codex-plugin/plugin.json +36 -0
  33. package/plugins/takomi-flow/.mcp.json +11 -0
  34. package/plugins/takomi-flow/assets/capabilities.json +171 -0
  35. package/plugins/takomi-flow/assets/collection.schema.json +29 -0
  36. package/plugins/takomi-flow/assets/composer-icon.png +0 -0
  37. package/plugins/takomi-flow/assets/examples.json +94 -0
  38. package/plugins/takomi-flow/assets/logo-dark.png +0 -0
  39. package/plugins/takomi-flow/assets/logo.png +0 -0
  40. package/plugins/takomi-flow/assets/request.schema.json +67 -0
  41. package/plugins/takomi-flow/assets/result.schema.json +45 -0
  42. package/plugins/takomi-flow/assets/templates/image-request.json +13 -0
  43. package/plugins/takomi-flow/assets/templates/video-request.json +15 -0
  44. package/plugins/takomi-flow/package.json +38 -0
  45. package/plugins/takomi-flow/pnpm-lock.yaml +813 -0
  46. package/plugins/takomi-flow/references/flow-provider-contract.md +326 -0
  47. package/plugins/takomi-flow/scripts/lib/agent-plan.mjs +130 -0
  48. package/plugins/takomi-flow/scripts/lib/api.mjs +113 -0
  49. package/plugins/takomi-flow/scripts/lib/args.mjs +57 -0
  50. package/plugins/takomi-flow/scripts/lib/audit.mjs +65 -0
  51. package/plugins/takomi-flow/scripts/lib/browser.mjs +39 -0
  52. package/plugins/takomi-flow/scripts/lib/capabilities.mjs +11 -0
  53. package/plugins/takomi-flow/scripts/lib/collect.mjs +53 -0
  54. package/plugins/takomi-flow/scripts/lib/commands.mjs +175 -0
  55. package/plugins/takomi-flow/scripts/lib/doctor.mjs +77 -0
  56. package/plugins/takomi-flow/scripts/lib/examples.mjs +17 -0
  57. package/plugins/takomi-flow/scripts/lib/flow-outcome.mjs +90 -0
  58. package/plugins/takomi-flow/scripts/lib/flow-ui.mjs +165 -0
  59. package/plugins/takomi-flow/scripts/lib/generation.mjs +90 -0
  60. package/plugins/takomi-flow/scripts/lib/inspect.mjs +81 -0
  61. package/plugins/takomi-flow/scripts/lib/mcp-prompts.mjs +39 -0
  62. package/plugins/takomi-flow/scripts/lib/mcp-resources.mjs +16 -0
  63. package/plugins/takomi-flow/scripts/lib/mcp-tools.mjs +150 -0
  64. package/plugins/takomi-flow/scripts/lib/media.mjs +78 -0
  65. package/plugins/takomi-flow/scripts/lib/observe.mjs +54 -0
  66. package/plugins/takomi-flow/scripts/lib/paths.mjs +37 -0
  67. package/plugins/takomi-flow/scripts/lib/playwright-loader.mjs +23 -0
  68. package/plugins/takomi-flow/scripts/lib/prompts.mjs +72 -0
  69. package/plugins/takomi-flow/scripts/lib/report.mjs +141 -0
  70. package/plugins/takomi-flow/scripts/lib/request-validator.mjs +58 -0
  71. package/plugins/takomi-flow/scripts/lib/request.mjs +55 -0
  72. package/plugins/takomi-flow/scripts/lib/resource-files.mjs +69 -0
  73. package/plugins/takomi-flow/scripts/lib/result.mjs +31 -0
  74. package/plugins/takomi-flow/scripts/lib/review.mjs +44 -0
  75. package/plugins/takomi-flow/scripts/lib/selftest.mjs +153 -0
  76. package/plugins/takomi-flow/scripts/lib/settings-plan.mjs +39 -0
  77. package/plugins/takomi-flow/scripts/lib/templates.mjs +37 -0
  78. package/plugins/takomi-flow/scripts/lib/trusted-chrome.mjs +67 -0
  79. package/plugins/takomi-flow/scripts/lib/workflow.mjs +56 -0
  80. package/plugins/takomi-flow/scripts/mcp-server.mjs +18 -0
  81. package/plugins/takomi-flow/scripts/mcp-smoke.mjs +142 -0
  82. package/plugins/takomi-flow/scripts/takomi-flow.mjs +17 -0
  83. package/plugins/takomi-flow/skills/takomi-flow/SKILL.md +235 -0
  84. package/plugins/takomi-flow/skills/takomi-flow/agents/openai.yaml +7 -0
  85. package/scripts/install-takomi-flow.ps1 +85 -0
  86. package/src/pi-takomi-core/orchestration.ts +1 -1
  87. package/src/pi-takomi-core/workflows.ts +4 -4
  88. package/src/skills-catalog.js +11 -7
@@ -0,0 +1,326 @@
1
+ # TakomiFlow Provider Contract
2
+
3
+ ## Purpose
4
+
5
+ TakomiFlow gives agents a stable interface for asking Google Flow to create assets through a browser profile the user controls.
6
+
7
+ ## Surfaces
8
+
9
+ - Skill: route Codex behavior and safety rules.
10
+ - CLI: run browser workflows, request preparation, validation, and asset inspection.
11
+ - MCP: expose safe no-spend commands as callable agent tools.
12
+
13
+ MCP server:
14
+
15
+ ```bash
16
+ node scripts/mcp-server.mjs
17
+ ```
18
+
19
+ Smoke test:
20
+
21
+ ```bash
22
+ node scripts/mcp-smoke.mjs
23
+ ```
24
+
25
+ MCP tools mirror stable JSON operations: capabilities, doctor, audit, examples, template, prepare, workflow, validate, observe, generate, selftest, inspect, latest, runs, assets, review, collect, and report.
26
+
27
+ Browser-capable MCP tools require explicit `allowBrowser=true`. Generation also requires the normal spend guard.
28
+
29
+ MCP resources:
30
+
31
+ - `takomi-flow://contract`
32
+ - `takomi-flow://capabilities`
33
+ - `takomi-flow://examples`
34
+ - `takomi-flow://schemas/request`
35
+ - `takomi-flow://schemas/result`
36
+ - `takomi-flow://schemas/collection`
37
+ - `takomi-flow://templates/video`
38
+ - `takomi-flow://templates/image`
39
+
40
+ MCP prompts:
41
+
42
+ - `takomi_flow_video_workflow`
43
+ - `takomi_flow_image_workflow`
44
+ - `takomi_flow_review_workflow`
45
+ - `takomi_flow_collect_workflow`
46
+
47
+ ## Agent Preflight
48
+
49
+ Run this before browser work when reliability matters:
50
+
51
+ ```bash
52
+ node scripts/takomi-flow.mjs doctor
53
+ node scripts/takomi-flow.mjs audit
54
+ ```
55
+
56
+ `audit` is the preferred agent preflight. It reports readiness, safe no-spend actions, gated browser/spend actions, recent runs, and recommended next steps.
57
+
58
+ First-run agents should also check for an existing trusted Chrome DevTools endpoint before launching a new browser:
59
+
60
+ ```bash
61
+ curl http://127.0.0.1:9222/json/version
62
+ ```
63
+
64
+ If the endpoint exists, reuse it with `--cdp-url http://127.0.0.1:9222`. If it does not exist, run `trusted-chrome` and ask the user to sign into Google Flow manually. MCP is optional; every MCP operation has a CLI equivalent through `node scripts/takomi-flow.mjs`.
65
+
66
+ Run this after install or edits:
67
+
68
+ ```bash
69
+ node scripts/takomi-flow.mjs selftest
70
+ ```
71
+
72
+ Discover supported agent options:
73
+
74
+ ```bash
75
+ node scripts/takomi-flow.mjs capabilities
76
+ node scripts/takomi-flow.mjs examples
77
+ ```
78
+
79
+ Observe the current Flow UI without spending credits:
80
+
81
+ ```bash
82
+ node scripts/takomi-flow.mjs observe
83
+ node scripts/takomi-flow.mjs observe --browser-channel chrome
84
+ ```
85
+
86
+ If Google login shows "This browser or app may not be secure", rerun browser commands with
87
+ `trusted-chrome`. Playwright-launched Chrome can still expose automation flags such as
88
+ `--no-sandbox`; `trusted-chrome` starts Chrome directly with a remote debugging port and a dedicated
89
+ TakomiFlow profile. After manual login, pass `--cdp-url http://127.0.0.1:9222` so TakomiFlow attaches
90
+ to the trusted browser session instead of automating credential entry.
91
+
92
+ Verified signed-in observation currently sees a Flow dashboard with project cards, `PRO` account
93
+ state, and a `New project` button. Treat this as the preferred selector discovery starting point.
94
+ The project editor currently exposes a prompt textbox with text `What do you want to create?`, plus
95
+ `Agent`, `Agent Instructions`, `Settings`, file input, and `Create` buttons. Prompt filling has been
96
+ verified without pressing Create.
97
+ Live video durations are `4`, `6`, `8`, and `10` seconds. If the agent asks for an unsupported
98
+ duration, Flow may ask a follow-up. A verified generation also asked for explicit approval before
99
+ spending 7 credits for one video. After output creation, opening the generated media reveals a
100
+ toolbar `download` button that saves the MP4.
101
+
102
+ Use templates when starting a request from scratch:
103
+
104
+ ```bash
105
+ node scripts/takomi-flow.mjs template --kind video
106
+ node scripts/takomi-flow.mjs template --kind image
107
+ ```
108
+
109
+ Validate before generation:
110
+
111
+ ```bash
112
+ node scripts/takomi-flow.mjs validate --request <request.json>
113
+ ```
114
+
115
+ One-call agent workflow:
116
+
117
+ ```bash
118
+ node scripts/takomi-flow.mjs workflow --kind video --prompt "cinematic AI lab scene" --variations 2
119
+ ```
120
+
121
+ `workflow` prepares and validates a request in one call. Add `--submit --allow-browser --allow-spend` only after explicit user approval; the normal spend guard still applies.
122
+
123
+ ## Request JSON
124
+
125
+ Agents can read `takomi-flow://schemas/request` for the JSON Schema version of this shape.
126
+
127
+ ```json
128
+ {
129
+ "schemaVersion": 1,
130
+ "kind": "video",
131
+ "prompt": "cinematic AI lab scene with practical lighting",
132
+ "variations": 2,
133
+ "aspectRatio": "16:9",
134
+ "durationSeconds": 8,
135
+ "mode": "text-to-video",
136
+ "modelHint": "best-available",
137
+ "outputDir": "C:/Users/johno/.takomi-flow/runs",
138
+ "allowSpend": false,
139
+ "extractFrames": 4,
140
+ "notes": "Optional agent notes for traceability."
141
+ }
142
+ ```
143
+
144
+ ## Fields
145
+
146
+ Agents can discover the same fields from `capabilities.requestFields`.
147
+
148
+ - `kind`: `video` or `image`.
149
+ - `prompt`: Required non-empty generation prompt.
150
+ - `variations`: Positive integer. Defaults to `1`.
151
+ - `aspectRatio`: Optional UI hint such as `16:9`, `9:16`, or `1:1`.
152
+ - `durationSeconds`: Optional video duration hint.
153
+ - `mode`: Optional Flow mode hint such as `text-to-video`, `image-to-video`, or `text-to-image`.
154
+ - `modelHint`: Optional human-readable model or quality hint.
155
+ - `outputDir`: Optional base output directory.
156
+ - `allowSpend`: Must be `true` for generation submission.
157
+ - `extractFrames`: Optional number of review frames to extract from downloaded videos.
158
+ - `sourceAssets`: Optional array of local file paths for future image/video-to-video flows.
159
+
160
+ ## Validation JSON
161
+
162
+ `validate` normalizes request values, checks them against `capabilities`, verifies source asset paths, and reports spend-guard state:
163
+
164
+ ```json
165
+ {
166
+ "schemaVersion": 1,
167
+ "status": "ok",
168
+ "normalized": {},
169
+ "errors": [],
170
+ "warnings": []
171
+ }
172
+ ```
173
+
174
+ ## Result JSON
175
+
176
+ Agents can read `takomi-flow://schemas/result` for the JSON Schema version of run metadata.
177
+
178
+ ```json
179
+ {
180
+ "schemaVersion": 1,
181
+ "status": "manual_action_required",
182
+ "runId": "20260701-120000-flow",
183
+ "kind": "video",
184
+ "prompt": "cinematic AI lab scene with practical lighting",
185
+ "projectUrl": "https://labs.google/fx/tools/flow/project/example",
186
+ "settingsPlan": {
187
+ "requested": {
188
+ "mode": "text-to-video",
189
+ "variations": 2,
190
+ "aspectRatio": "16:9",
191
+ "durationSeconds": 8
192
+ },
193
+ "automatic": ["prompt", "download folder", "metadata", "asset catalog"],
194
+ "selectorDependent": [
195
+ { "field": "aspectRatio", "value": "16:9" }
196
+ ]
197
+ },
198
+ "assets": [],
199
+ "assetCatalogPath": "C:/Users/johno/.takomi-flow/runs/20260701-120000-flow/assets.json",
200
+ "screenshots": [],
201
+ "errors": [],
202
+ "manualActions": [
203
+ "Complete Google login or Flow consent in the opened browser."
204
+ ],
205
+ "metadataPath": "C:/Users/johno/.takomi-flow/runs/20260701-120000-flow/run.json"
206
+ }
207
+ ```
208
+
209
+ `projectUrl` records the exact Flow project/editor URL used for the run so agents do not lose track of generated projects. `settingsPlan` preserves the user's requested Flow options in run metadata. Prompt entry, downloads, metadata, asset cataloging, and frame extraction are automated. Mode, aspect ratio, duration, model controls, source assets, and multi-variation UI selection are selector-dependent until `observe` captures the live Flow controls.
210
+
211
+ ## Status Values
212
+
213
+ - `prepared`: Request file created; no browser action happened.
214
+ - `ok`: Command completed and artifacts were written.
215
+ - `downloaded`: One or more assets were downloaded.
216
+ - `manual_action_required`: User action is required in the browser.
217
+ - `blocked`: Flow showed quota, safety, captcha, account, or unsupported UI state.
218
+ - `failed`: Script error or unrecoverable automation failure.
219
+
220
+ ## Safety Invariants
221
+
222
+ - Never store Google credentials.
223
+ - Never submit generation unless request `allowSpend` is true or `TAKOMI_FLOW_ALLOW_SPEND=true`.
224
+ - Never bypass Google account, captcha, safety, or quota controls.
225
+ - Always write a result file, even on failure.
226
+ - Always save downloads into the run directory unless the request explicitly overrides it.
227
+
228
+ ## Asset Catalog
229
+
230
+ Run:
231
+
232
+ ```bash
233
+ node scripts/takomi-flow.mjs assets --run <run.json|run-dir> --frames 4
234
+ ```
235
+
236
+ The command writes `assets.json` next to `run.json`. Video assets are probed with `ffprobe` when available, and review frames are extracted with `ffmpeg` when `--frames` is greater than zero.
237
+
238
+ ## Run Review
239
+
240
+ Run:
241
+
242
+ ```bash
243
+ node scripts/takomi-flow.mjs review --run <run.json|run-dir> --frames 4
244
+ ```
245
+
246
+ `review` is the preferred post-generation agent command. It inspects the run, catalogs downloaded assets, extracts review frames, writes a Markdown report, and returns next actions.
247
+
248
+ ## Collection
249
+
250
+ Run:
251
+
252
+ ```bash
253
+ node scripts/takomi-flow.mjs collect --run <run.json|run-dir> --target-dir <path> --frames 4 --include-frames
254
+ ```
255
+
256
+ `collect` reviews a run, copies assets/report/optional frames into a downstream target folder, and writes `takomi-flow-collection.json` as a manifest.
257
+
258
+ Agents can read `takomi-flow://schemas/collection` for the JSON Schema version of the collection manifest.
259
+
260
+ ## Markdown Reports
261
+
262
+ Run:
263
+
264
+ ```bash
265
+ node scripts/takomi-flow.mjs report --run <run.json|run-dir>
266
+ node scripts/takomi-flow.mjs report --output-dir <runs-dir> --limit 10
267
+ ```
268
+
269
+ The command writes `report.md` next to a single run, or `takomi-flow-report.md` in a runs directory. Reports include status, metadata paths, screenshots, assets, errors, manual actions, and catalog details when `assets.json` exists.
270
+
271
+ ## Diagnostics JSON
272
+
273
+ `doctor` returns:
274
+
275
+ ```json
276
+ {
277
+ "schemaVersion": 1,
278
+ "status": "ok",
279
+ "flowUrl": "https://labs.google/fx/tools/flow",
280
+ "profileDir": "C:/Users/johno/.takomi-flow/browser-profile",
281
+ "outputDir": "C:/Users/johno/.takomi-flow/runs",
282
+ "checks": [],
283
+ "recommendations": []
284
+ }
285
+ ```
286
+
287
+ ## Capabilities JSON
288
+
289
+ `capabilities` returns supported kinds, modes, variation limits, aspect ratios, output artifact names, safety invariants, and available commands. Agents should prefer this over hard-coded assumptions.
290
+
291
+ ## Observation JSON
292
+
293
+ `observe` writes a normal `run.json` and includes a `controls` object:
294
+
295
+ ```json
296
+ {
297
+ "controls": {
298
+ "buttons": [],
299
+ "inputs": [],
300
+ "links": []
301
+ }
302
+ }
303
+ ```
304
+
305
+ Use it to tune Flow selectors after Google changes the UI.
306
+
307
+ ## Self-Test JSON
308
+
309
+ `selftest` runs a deterministic no-spend verification pass:
310
+
311
+ - doctor diagnostics
312
+ - readiness audit
313
+ - capability loading
314
+ - example loading
315
+ - video/image template loading
316
+ - request preparation
317
+ - one-call workflow preparation/validation
318
+ - settings-plan metadata for requested Flow options
319
+ - request validation
320
+ - spend-guard expectation
321
+ - synthetic MP4 cataloging and frame extraction
322
+ - Markdown report generation
323
+ - one-call run review
324
+ - downstream asset collection
325
+
326
+ It writes artifacts under `<outputDir>/selftest`.
@@ -0,0 +1,130 @@
1
+ import { loadCapabilities } from './capabilities.mjs';
2
+ import { normalizeRequest } from './request.mjs';
3
+
4
+ export function createAgentPlan(args = {}) {
5
+ const request = normalizeRequest(args);
6
+ const capabilities = loadCapabilities();
7
+ const submit = Boolean(args.submit);
8
+ const collectTarget = args.targetDir || args['target-dir'];
9
+ return {
10
+ schemaVersion: 1,
11
+ status: 'ready',
12
+ provider: capabilities.provider,
13
+ summary: `${request.kind} ${request.mode} Flow job with ${request.variations} variation(s).`,
14
+ request,
15
+ gates: gates(request, submit),
16
+ mcpSequence: mcpSequence(request, { submit, collectTarget }),
17
+ cliSequence: cliSequence(request, { submit, collectTarget }),
18
+ expectedOutputs: expectedOutputs(request, collectTarget),
19
+ nextActions: nextActions(submit, collectTarget),
20
+ };
21
+ }
22
+
23
+ function gates(request, submit) {
24
+ const items = [
25
+ {
26
+ name: 'spend',
27
+ required: submit,
28
+ satisfied: request.allowSpend,
29
+ note: 'Generation submission may spend Flow credits and requires allowSpend=true.',
30
+ },
31
+ {
32
+ name: 'browser',
33
+ required: submit,
34
+ satisfied: false,
35
+ note: 'Browser-opening MCP tools require allowBrowser=true at call time.',
36
+ },
37
+ ];
38
+ return submit ? items : items.map(item => ({ ...item, required: false }));
39
+ }
40
+
41
+ function mcpSequence(request, options) {
42
+ const workflowArgs = {
43
+ kind: request.kind,
44
+ prompt: request.prompt,
45
+ variations: request.variations,
46
+ aspectRatio: request.aspectRatio,
47
+ durationSeconds: request.durationSeconds,
48
+ mode: request.mode,
49
+ modelHint: request.modelHint,
50
+ outputDir: request.outputDir,
51
+ allowSpend: request.allowSpend,
52
+ extractFrames: request.extractFrames,
53
+ sourceAssets: request.sourceAssets,
54
+ submit: options.submit,
55
+ allowBrowser: options.submit,
56
+ };
57
+ const steps = [
58
+ { tool: 'takomi_flow_audit', arguments: { outputDir: request.outputDir } },
59
+ { tool: 'takomi_flow_workflow', arguments: compact(workflowArgs) },
60
+ { tool: 'takomi_flow_review', arguments: { run: '<run.json|run-dir>', frames: request.extractFrames || 0 } },
61
+ ];
62
+ if (options.collectTarget) {
63
+ steps.push({
64
+ tool: 'takomi_flow_collect',
65
+ arguments: {
66
+ run: '<run.json|run-dir>',
67
+ targetDir: options.collectTarget,
68
+ frames: request.extractFrames || 0,
69
+ includeFrames: true,
70
+ },
71
+ });
72
+ }
73
+ return steps;
74
+ }
75
+
76
+ function cliSequence(request, options) {
77
+ const base = [
78
+ 'node scripts/takomi-flow.mjs audit',
79
+ `node scripts/takomi-flow.mjs workflow --kind ${request.kind} --prompt "${escapeArg(request.prompt)}"${optionArgs(request, options.submit)}`,
80
+ `node scripts/takomi-flow.mjs review --run <run.json|run-dir> --frames ${request.extractFrames || 0}`,
81
+ ];
82
+ if (options.collectTarget) {
83
+ base.push(`node scripts/takomi-flow.mjs collect --run <run.json|run-dir> --target-dir "${escapeArg(options.collectTarget)}" --frames ${request.extractFrames || 0} --include-frames`);
84
+ }
85
+ return base;
86
+ }
87
+
88
+ function optionArgs(request, submit) {
89
+ const args = [];
90
+ if (request.variations) args.push(`--variations ${request.variations}`);
91
+ if (request.aspectRatio) args.push(`--aspect-ratio ${request.aspectRatio}`);
92
+ if (request.durationSeconds) args.push(`--duration ${request.durationSeconds}`);
93
+ if (request.mode) args.push(`--mode ${request.mode}`);
94
+ if (request.modelHint) args.push(`--model "${escapeArg(request.modelHint)}"`);
95
+ if (request.outputDir) args.push(`--output-dir "${escapeArg(request.outputDir)}"`);
96
+ if (request.extractFrames) args.push(`--extract-frames ${request.extractFrames}`);
97
+ if (request.sourceAssets.length) args.push(`--assets "${escapeArg(request.sourceAssets.join(','))}"`);
98
+ if (submit) args.push('--submit --allow-browser --allow-spend');
99
+ return args.length ? ` ${args.join(' ')}` : '';
100
+ }
101
+
102
+ function expectedOutputs(request, collectTarget) {
103
+ const outputs = [
104
+ `${request.outputDir}/requests/<timestamp>-request.json`,
105
+ `${request.outputDir}/<runId>/run.json`,
106
+ `${request.outputDir}/<runId>/downloads/`,
107
+ `${request.outputDir}/<runId>/assets.json`,
108
+ `${request.outputDir}/<runId>/report.md`,
109
+ ];
110
+ if (request.extractFrames) outputs.push(`${request.outputDir}/<runId>/frames/`);
111
+ if (collectTarget) outputs.push(`${collectTarget}/takomi-flow-collection.json`);
112
+ return outputs;
113
+ }
114
+
115
+ function nextActions(submit, collectTarget) {
116
+ const actions = ['Run the audit step first and treat missing profile as a bootstrap/login gate.'];
117
+ if (!submit) actions.push('Use the workflow step without submit to prepare and validate the request without spending credits.');
118
+ if (submit) actions.push('Confirm the user explicitly approved spending Flow credits before running the submit step.');
119
+ actions.push('After generation, review run metadata, errors, screenshots, and downloaded assets.');
120
+ if (collectTarget) actions.push('Collect reviewed outputs into the downstream target folder for pipeline reuse.');
121
+ return actions;
122
+ }
123
+
124
+ function compact(value) {
125
+ return Object.fromEntries(Object.entries(value).filter(([, item]) => item !== undefined));
126
+ }
127
+
128
+ function escapeArg(value) {
129
+ return String(value).replaceAll('"', '\\"');
130
+ }
@@ -0,0 +1,113 @@
1
+ import { createPreparedRequest } from './request.mjs';
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import { validateRequestFile } from './request-validator.mjs';
5
+ import { runDoctor } from './doctor.mjs';
6
+ import { loadCapabilities } from './capabilities.mjs';
7
+ import { listTemplates, loadTemplate, writeTemplate } from './templates.mjs';
8
+ import { runSelfTest } from './selftest.mjs';
9
+ import { inspectRun, latestRun, listRuns, resolveRun } from './inspect.mjs';
10
+ import { catalogAssets } from './media.mjs';
11
+ import { observeFlow } from './observe.mjs';
12
+ import { generateFromRequest } from './generation.mjs';
13
+ import { createReport } from './report.mjs';
14
+ import { runWorkflow } from './workflow.mjs';
15
+ import { reviewRun } from './review.mjs';
16
+ import { runAudit } from './audit.mjs';
17
+ import { collectRun } from './collect.mjs';
18
+ import { loadExamples } from './examples.mjs';
19
+ import { createAgentPlan } from './agent-plan.mjs';
20
+
21
+ export async function doctor(args = {}) {
22
+ return runDoctor({ profileDir: args.profileDir, outputDir: args.outputDir });
23
+ }
24
+
25
+ export function capabilities() {
26
+ return loadCapabilities();
27
+ }
28
+
29
+ export async function observe(args = {}) {
30
+ return observeFlow({
31
+ profileDir: args.profileDir,
32
+ outputDir: args.outputDir,
33
+ browserChannel: args.browserChannel,
34
+ cdpUrl: args.cdpUrl,
35
+ headless: Boolean(args.headless),
36
+ });
37
+ }
38
+
39
+ export function template(args = {}) {
40
+ if (!args.kind) return { templates: listTemplates() };
41
+ if (args.outputDir) return writeTemplate(args.kind, args.outputDir);
42
+ return loadTemplate(args.kind);
43
+ }
44
+
45
+ export function prepare(args = {}) {
46
+ const { request, requestPath } = createPreparedRequest(args);
47
+ return { status: 'prepared', requestPath, request };
48
+ }
49
+
50
+ export function validate(args = {}) {
51
+ return validateRequestFile(args.request);
52
+ }
53
+
54
+ export async function selftest(args = {}) {
55
+ return runSelfTest({ outputDir: args.outputDir });
56
+ }
57
+
58
+ export function inspect(args = {}) {
59
+ return inspectRun(args.run);
60
+ }
61
+
62
+ export function latest(args = {}) {
63
+ return latestRun(args.outputDir);
64
+ }
65
+
66
+ export function runs(args = {}) {
67
+ return listRuns(args.outputDir, args.limit);
68
+ }
69
+
70
+ export async function assets(args = {}) {
71
+ const run = resolveRun(args.run);
72
+ return catalogAssets(run, assetPathsForRun(run), { frames: args.frames || 0 });
73
+ }
74
+
75
+ export async function generate(args = {}) {
76
+ return generateFromRequest(args);
77
+ }
78
+
79
+ export function report(args = {}) {
80
+ return createReport(args);
81
+ }
82
+
83
+ export async function workflow(args = {}) {
84
+ return runWorkflow(args);
85
+ }
86
+
87
+ export async function review(args = {}) {
88
+ return reviewRun(args);
89
+ }
90
+
91
+ export async function audit(args = {}) {
92
+ return runAudit(args);
93
+ }
94
+
95
+ export async function collect(args = {}) {
96
+ return collectRun(args);
97
+ }
98
+
99
+ export function examples(args = {}) {
100
+ return loadExamples(args.name);
101
+ }
102
+
103
+ export function plan(args = {}) {
104
+ return createAgentPlan(args);
105
+ }
106
+
107
+ function assetPathsForRun(run) {
108
+ if (run.data.assets?.length) return run.data.assets;
109
+ if (!fs.existsSync(run.downloadsDir)) return [];
110
+ return fs.readdirSync(run.downloadsDir)
111
+ .map(name => path.join(run.downloadsDir, name))
112
+ .filter(filePath => fs.statSync(filePath).isFile());
113
+ }
@@ -0,0 +1,57 @@
1
+ export function parseArgs(argv) {
2
+ const args = { _: [] };
3
+ for (let i = 0; i < argv.length; i += 1) {
4
+ const token = argv[i];
5
+ if (!token.startsWith('--')) {
6
+ args._.push(token);
7
+ continue;
8
+ }
9
+ const key = token.slice(2);
10
+ const next = argv[i + 1];
11
+ if (!next || next.startsWith('--')) {
12
+ args[key] = true;
13
+ continue;
14
+ }
15
+ args[key] = next;
16
+ i += 1;
17
+ }
18
+ return args;
19
+ }
20
+
21
+ export function printUsage() {
22
+ console.log(`
23
+ TakomiFlow
24
+
25
+ Usage:
26
+ node scripts/takomi-flow.mjs bootstrap [--profile-dir <path>] [--browser-channel chrome] [--cdp-url <url>] [--headless]
27
+ node scripts/takomi-flow.mjs doctor [--profile-dir <path>] [--output-dir <path>]
28
+ node scripts/takomi-flow.mjs audit [--profile-dir <path>] [--output-dir <path>]
29
+ node scripts/takomi-flow.mjs capabilities
30
+ node scripts/takomi-flow.mjs examples [--name <example-name>]
31
+ node scripts/takomi-flow.mjs trusted-chrome [--port 9222] [--profile-dir <path>] [--chrome-path <path>]
32
+ node scripts/takomi-flow.mjs plan --kind <video|image> --prompt <text> [--submit --target-dir <path>]
33
+ node scripts/takomi-flow.mjs observe [--profile-dir <path>] [--output-dir <path>] [--browser-channel chrome] [--cdp-url <url>] [--headless]
34
+ node scripts/takomi-flow.mjs smoke [--profile-dir <path>] [--output-dir <path>] [--browser-channel chrome] [--cdp-url <url>]
35
+ node scripts/takomi-flow.mjs prepare --kind <video|image> --prompt <text> [--variations 1]
36
+ node scripts/takomi-flow.mjs workflow --kind <video|image> --prompt <text> [--submit --allow-browser --allow-spend]
37
+ node scripts/takomi-flow.mjs template --kind <video|image> [--output-dir <path>]
38
+ node scripts/takomi-flow.mjs validate --request <path>
39
+ node scripts/takomi-flow.mjs generate --request <path>
40
+ node scripts/takomi-flow.mjs selftest [--output-dir <path>]
41
+ node scripts/takomi-flow.mjs inspect --run <run.json|run-dir>
42
+ node scripts/takomi-flow.mjs latest [--output-dir <path>]
43
+ node scripts/takomi-flow.mjs runs [--output-dir <path>] [--limit 20]
44
+ node scripts/takomi-flow.mjs assets --run <run.json|run-dir> [--frames 4]
45
+ node scripts/takomi-flow.mjs review --run <run.json|run-dir> [--frames 4]
46
+ node scripts/takomi-flow.mjs collect --run <run.json|run-dir> --target-dir <path> [--frames 4 --include-frames]
47
+ node scripts/takomi-flow.mjs report [--run <run.json|run-dir>] [--output-dir <path>]
48
+
49
+ Spend guard:
50
+ generation submits only when request allowSpend=true or TAKOMI_FLOW_ALLOW_SPEND=true.
51
+
52
+ Google login note:
53
+ If Google says the browser may not be secure, use trusted Chrome attach mode:
54
+ node scripts/takomi-flow.mjs trusted-chrome
55
+ Then log in manually and attach with --cdp-url http://127.0.0.1:9222.
56
+ `);
57
+ }
@@ -0,0 +1,65 @@
1
+ import fs from 'node:fs';
2
+ import { runDoctor } from './doctor.mjs';
3
+ import { loadCapabilities } from './capabilities.mjs';
4
+ import { listRuns } from './inspect.mjs';
5
+
6
+ export async function runAudit(args = {}) {
7
+ const doctor = await runDoctor({
8
+ profileDir: args.profileDir,
9
+ outputDir: args.outputDir,
10
+ });
11
+ const capabilities = loadCapabilities();
12
+ const history = listRuns(doctor.outputDir, args.limit || 5);
13
+ const profileReady = fs.existsSync(doctor.profileDir);
14
+ const browserReady = doctor.checks.every(check => (
15
+ check.name === 'profileDir' || check.status !== 'failed'
16
+ ));
17
+ return {
18
+ schemaVersion: 1,
19
+ status: doctor.status === 'failed' ? 'failed' : 'ok',
20
+ readiness: {
21
+ browserAutomation: browserReady,
22
+ flowProfile: profileReady,
23
+ mediaReview: hasCheck(doctor, 'ffmpeg') && hasCheck(doctor, 'ffprobe'),
24
+ mcpTools: capabilities.mcpTools.length,
25
+ mcpResources: capabilities.mcpResources.length,
26
+ },
27
+ safeActions: [
28
+ 'capabilities',
29
+ 'examples',
30
+ 'plan',
31
+ 'template',
32
+ 'workflow without submit',
33
+ 'validate',
34
+ 'runs',
35
+ 'inspect',
36
+ 'assets',
37
+ 'review',
38
+ 'collect',
39
+ 'report',
40
+ 'selftest',
41
+ ],
42
+ gatedActions: [
43
+ 'bootstrap requires a headed browser and manual Google login',
44
+ 'observe requires allowBrowser=true',
45
+ 'generate requires allowBrowser=true and allowSpend=true',
46
+ 'workflow submit requires allowBrowser=true and allowSpend=true',
47
+ ],
48
+ doctor,
49
+ recentRuns: history.runs,
50
+ nextActions: nextActions(doctor, profileReady, history.runs),
51
+ };
52
+ }
53
+
54
+ function hasCheck(doctor, name) {
55
+ return doctor.checks.some(check => check.name === name && check.status === 'ok');
56
+ }
57
+
58
+ function nextActions(doctor, profileReady, runs) {
59
+ const actions = [...doctor.recommendations];
60
+ if (!profileReady) actions.push('Run bootstrap in headed mode and log into Google Flow manually.');
61
+ if (!runs.length) actions.push('Run workflow to prepare the first request, or smoke after login.');
62
+ if (runs.some(run => run.status === 'downloaded')) actions.push('Run review on downloaded runs before reusing assets.');
63
+ if (!actions.length) actions.push('TakomiFlow is ready for safe no-spend workflow preparation.');
64
+ return [...new Set(actions)];
65
+ }