@officexapp/vidfarm-devcli 0.21.45 → 0.21.46
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/.agents/skills/editor-capabilities/SKILL.md +2 -0
- package/.agents/skills/vidfarm/SKILL.md +60 -7
- package/.agents/skills/vidfarm/harnesses/explainer.HARNESS.md +1 -1
- package/.agents/skills/vidfarm/harnesses/product-demo.HARNESS.md +2 -0
- package/.agents/skills/vidfarm/harnesses/short-form.HARNESS.md +1 -0
- package/.agents/skills/vidfarm/recipes/local-edit-render-approve.md +1 -1
- package/.agents/skills/vidfarm/references/agent-included-imagegen.md +75 -0
- package/.agents/skills/vidfarm/references/assets-and-sourcing.md +56 -2
- package/.agents/skills/vidfarm/references/automation-and-local-dev.md +13 -6
- package/.agents/skills/vidfarm/references/browser-harness.md +93 -0
- package/.agents/skills/vidfarm/references/editor-workflows.md +22 -0
- package/SKILL.director.md +322 -16
- package/SKILL.md +44 -3
- package/crowdsourcing.md +373 -2
- package/dist/src/cli.js +207 -4
- package/dist/src/devcli/agent-imagegen.js +181 -0
- package/dist/src/devcli/browser-harness.js +384 -0
- package/dist/src/devcli/clip-store.js +41 -3
- package/dist/src/devcli/cost-mode.js +23 -3
- package/dist/src/devcli/doctor.js +52 -3
- package/dist/src/devcli/hyperframes-cli.js +11 -1
- package/dist/src/devcli/local-render.js +4 -7
- package/dist/src/devcli/marketplace-gigs.js +623 -0
- package/dist/src/devcli/qa-check.js +89 -1
- package/dist/src/devcli/shared-folder.js +387 -0
- package/dist/src/devcli/stills.js +4 -8
- package/dist/src/lib/ffprobe-path.js +64 -0
- package/dist/src/lib/render-media-prep.js +2 -11
- package/dist/src/services/clip-curation/ffmpeg.js +4 -15
- package/dist/src/services/clip-curation/local-agent.js +6 -2
- package/package.json +8 -153
- package/public/assets/file-directory-app.js +34 -34
- package/public/serve-shells/library-files.html +5 -1
- package/public/serve-shells/library-raws.html +10 -1
- package/public/serve-shells/tools-clipper.html +5 -1
- package/public/serve-shells/tools-image.html +5 -1
- package/public/serve-shells/tools-video.html +5 -1
package/dist/src/cli.js
CHANGED
|
@@ -32,11 +32,14 @@ import { runSkillsCommand } from "./devcli/skills.js";
|
|
|
32
32
|
import { AmbiguousDocRef, DEFAULT_PACK, bundledPackDir, listPackDocs, listPackTopics, loadAngleBank, loadAwarenessLadder, loadIdeaBank, readPackDoc, readPackTopic, resolvePackTopic, searchPackDocs } from "./devcli/skill-docs.js";
|
|
33
33
|
import { initTelemetry, reportCliCrash } from "./devcli/telemetry.js";
|
|
34
34
|
import { resolveLocalDataDir, localBackendAvailable, LocalModeUnavailableError, localApiRequest } from "./devcli/local-backend.js";
|
|
35
|
+
import { NativeModuleUnavailableError } from "./devcli/clip-store.js";
|
|
35
36
|
import { startLocalFrontendServer, serveShellsPresent } from "./devcli/local-frontend-server.js";
|
|
36
37
|
import { readStoredAuth, writeStoredAuth, clearStoredAuth, hostsMatch } from "./devcli/auth-store.js";
|
|
37
38
|
import { CostModeBlockedError, assertBilledAllowed, clearStoredCostMode, costModeExplainer, costModeSummaryLine, normalizeCostMode, resolveCostMode, writeStoredCostMode, COST_MODE_BLURB, COST_MODE_DISPLAY_LIST, costModeDisplayName } from "./devcli/cost-mode.js";
|
|
38
39
|
import { INTERACTION_MODES, INTERACTION_MODE_BLURB, clearStoredInteractionMode, interactionModeExplainer, interactionModeSummaryLine, interactiveOfferLine, normalizeInteractionMode, resolveInteractionMode, writeStoredInteractionMode } from "./devcli/interaction-mode.js";
|
|
39
40
|
import { buildImageHandoff, buildRawsHandoff, formatHandoff } from "./devcli/handoff.js";
|
|
41
|
+
import { AGENT_IMAGEGEN_ALTERNATIVE, KNOWN_HOST_AGENTS, buildAgentImageBrief, detectHostAgent, formatAgentImageBrief } from "./devcli/agent-imagegen.js";
|
|
42
|
+
import { runBrowserHarnessCommand, runBrowseCommand } from "./devcli/browser-harness.js";
|
|
40
43
|
import { buildConsultBrief, CONSULT_ARTIFACTS, consultContextState, consultCountRange, defaultConsultCount, findOfferFile, formatConsultBrief, looksLikeOfferPath, planConsultation, resolveConsultStep, resolveOfferPath } from "./devcli/consult.js";
|
|
41
44
|
import { resolveRootFileCandidates } from "./lib/package-root.js";
|
|
42
45
|
import { STORYBOARD_FILENAME, readStoryboard, renderStoryboardScaffold, storyboardStage } from "./devcli/storyboard.js";
|
|
@@ -121,7 +124,31 @@ Account (persisted login — points the CLI + \`serve\` at cloud prod):
|
|
|
121
124
|
A manual clip-sourcing brief: what to search, how to
|
|
122
125
|
download (a downloader SEARCH, not a rotting link), and
|
|
123
126
|
the vidfarm clipper / raws scan follow-up. Try browser control
|
|
124
|
-
or "vidfarm raws scan" first.
|
|
127
|
+
("vidfarm browse", below) or "vidfarm raws scan" first.
|
|
128
|
+
agent-image "<subject>" [--items "a,b,c"] [--single] [--out ./sheet.png]
|
|
129
|
+
FREE CUSTOM ART — image generation YOUR OWN agent
|
|
130
|
+
subscription already includes. Antigravity / Gemini CLI
|
|
131
|
+
(Nano Banana / Imagen) and Codex / ChatGPT (gpt-image)
|
|
132
|
+
include one; Claude Code does NOT (Anthropic ships no
|
|
133
|
+
image model). Prints the prompt, the key-plate rules and
|
|
134
|
+
the cut + import commands. Vidfarm bills nothing and the
|
|
135
|
+
provider bills nothing extra, so it is allowed in EVERY
|
|
136
|
+
cost mode — minimize included.
|
|
137
|
+
--check (or no args) = is it included here? --json
|
|
138
|
+
(aliases: agent-imagegen, own-image, native-image)
|
|
139
|
+
browser [status|setup|doctor] FREE BROWSER SOURCING — set up browser-harness so I can
|
|
140
|
+
drive YOUR Chrome myself. It substitutes for the PAID
|
|
141
|
+
video-search / image-search / news-search / download-video
|
|
142
|
+
primitives at $0, on your own logged-in session and IP.
|
|
143
|
+
setup = install via uv + register the skill + the one
|
|
144
|
+
Chrome step (chrome://inspect) you must do once.
|
|
145
|
+
status = what's installed · doctor = connection check.
|
|
146
|
+
Suggest this to every free-plan user before saying "I can't".
|
|
147
|
+
browse <videos|images|news|page> "<query|url>"
|
|
148
|
+
Mint the browse recipe for one sourcing job: the Google
|
|
149
|
+
surface to open, what to pull off the page, and the vidfarm
|
|
150
|
+
command it feeds. --run pipes it straight into browser-harness,
|
|
151
|
+
--json for an agent, --legacy for the old tbm=… params.
|
|
125
152
|
consult [step] THE CONSULTATION / BRAINSTORM CHAIN, KEYLESS AND LOCAL.
|
|
126
153
|
The cloud runs these as brainstorm/* primitives that need
|
|
127
154
|
a provider key or wallet credits. This prints the IDENTICAL
|
|
@@ -1127,6 +1154,15 @@ Marketplace (paid, cloud-only — the bazaar never renders locally):
|
|
|
1127
1154
|
directory share-update <token> --mode/--label/--disable/--enable → PATCH /api/v1/user/me/directory/shares/:token
|
|
1128
1155
|
directory unshare <token> Delete a share link for good → DELETE /api/v1/user/me/directory/shares/:token
|
|
1129
1156
|
(alias: dir · save-url|from-url|import-url — CLI twin of the "Save to Files" picker)
|
|
1157
|
+
gigs <sub> Your vending machines, BOTH sides (client + gigworker)
|
|
1158
|
+
machines · tasks · add-task · proofs · approve · reject · ring-bell (client, paid)
|
|
1159
|
+
work · feed · join-feed · join · claim · submit · mine (gigworker, free — bring DOLLARPLATOON_API_KEY)
|
|
1160
|
+
e.g. vidfarm gigs add-task --task "60s explainer for acme.com" --price 0.50 --upload-link <share url>
|
|
1161
|
+
vidfarm gigs proofs --status pending · vidfarm gigs approve PRF_01H…
|
|
1162
|
+
(see: vidfarm gigs help)
|
|
1163
|
+
shared <sub> <link> USE a link someone shared with you — NO account, NO API key
|
|
1164
|
+
info · ls · search · mkdir · put · get e.g. vidfarm shared put <link> clip.mp4 --subfolder batch-01
|
|
1165
|
+
(the gigworker/agent side of directory share; see: vidfarm shared help)
|
|
1130
1166
|
put-file / get-file / files / annotate-file are the My Files (persistent) set;
|
|
1131
1167
|
upload is the throwaway temp store for dropping media into a composition.
|
|
1132
1168
|
Annotate assets you'll want back — esp. recurring characters, kept under
|
|
@@ -1165,6 +1201,12 @@ Cost spectrum (default to the cheapest approach that works; see SKILL.director.m
|
|
|
1165
1201
|
In minimize AND hybrid, 'vidfarm tts' DEFAULTS to the free local Kokoro voice — ask for
|
|
1166
1202
|
a premium voice (--style/--voice/--provider/--own-key/--cloud), or be in rich-ai /
|
|
1167
1203
|
pure-videogen, to opt out.
|
|
1204
|
+
minimize is NOT "no AI images". If the agent driving this terminal has image generation
|
|
1205
|
+
included in its own subscription (Google Antigravity / Gemini CLI, OpenAI Codex /
|
|
1206
|
+
ChatGPT — Claude Code does NOT, Anthropic ships no image model), it generates the
|
|
1207
|
+
graphic itself: nothing is billed by Vidfarm and nothing extra by the provider, so it
|
|
1208
|
+
is allowed in EVERY mode. 'vidfarm agent-image --check' answers "do I have it?", and
|
|
1209
|
+
'vidfarm agent-image "<subject>" --items "a,b,c"' prints the prompt + cut/import steps.
|
|
1168
1210
|
|
|
1169
1211
|
Escape hatch — call ANY route directly:
|
|
1170
1212
|
api <METHOD> <path> Raw REST call with auth + pretty errors
|
|
@@ -1477,6 +1519,23 @@ async function main() {
|
|
|
1477
1519
|
case "hand-off":
|
|
1478
1520
|
await runHandoffCommand(rest);
|
|
1479
1521
|
return;
|
|
1522
|
+
// Image generation the AGENT already pays for — free in every cost mode.
|
|
1523
|
+
case "agent-image":
|
|
1524
|
+
case "agent-imagegen":
|
|
1525
|
+
case "own-image":
|
|
1526
|
+
case "native-image":
|
|
1527
|
+
await runAgentImageCommand(rest);
|
|
1528
|
+
return;
|
|
1529
|
+
// Free browser sourcing — the agent drives the user's own Chrome instead of
|
|
1530
|
+
// paying for video-search / image-search / news-search / download-video.
|
|
1531
|
+
case "browser":
|
|
1532
|
+
case "browser-harness":
|
|
1533
|
+
case "bh":
|
|
1534
|
+
await runBrowserHarnessCommand(rest);
|
|
1535
|
+
return;
|
|
1536
|
+
case "browse":
|
|
1537
|
+
await runBrowseCommand(rest);
|
|
1538
|
+
return;
|
|
1480
1539
|
// The brainstorm chain with no AI key: the prompt goes to the agent that is
|
|
1481
1540
|
// already here, not to a provider. "consultation" is the director's word.
|
|
1482
1541
|
case "consult":
|
|
@@ -1547,6 +1606,15 @@ async function main() {
|
|
|
1547
1606
|
case "market":
|
|
1548
1607
|
await runMarketplaceCommand(rest);
|
|
1549
1608
|
return;
|
|
1609
|
+
// Both sides of the vending machines: a paid client posting tasks and
|
|
1610
|
+
// reviewing proofs, and a FREE gigworker with their own dollarplatoon key.
|
|
1611
|
+
case "gigs":
|
|
1612
|
+
case "gig":
|
|
1613
|
+
case "vending": {
|
|
1614
|
+
const { runGigsCommand } = await import("./devcli/marketplace-gigs.js");
|
|
1615
|
+
await runGigsCommand(rest);
|
|
1616
|
+
return;
|
|
1617
|
+
}
|
|
1550
1618
|
case "get-file":
|
|
1551
1619
|
await runGetFileCommand(rest);
|
|
1552
1620
|
return;
|
|
@@ -1561,6 +1629,15 @@ async function main() {
|
|
|
1561
1629
|
case "dir":
|
|
1562
1630
|
await runDirectoryCommand(rest);
|
|
1563
1631
|
return;
|
|
1632
|
+
// The VISITOR side of a share link — no account, no API key. A gigworker or
|
|
1633
|
+
// their agent works a folder someone else shared with them.
|
|
1634
|
+
case "shared":
|
|
1635
|
+
case "shared-folder":
|
|
1636
|
+
case "dropbox": {
|
|
1637
|
+
const { runSharedCommand } = await import("./devcli/shared-folder.js");
|
|
1638
|
+
await runSharedCommand(rest);
|
|
1639
|
+
return;
|
|
1640
|
+
}
|
|
1564
1641
|
case "migrate-local": {
|
|
1565
1642
|
if (!localBackendAvailable())
|
|
1566
1643
|
throw new LocalModeUnavailableError();
|
|
@@ -1866,6 +1943,7 @@ function guardBilled(ctx, input) {
|
|
|
1866
1943
|
json: ctx.json,
|
|
1867
1944
|
label: input.label,
|
|
1868
1945
|
estimate: input.estimate,
|
|
1946
|
+
agentAlternative: input.agentAlternative,
|
|
1869
1947
|
freeAlternative: input.freeAlternative
|
|
1870
1948
|
? `${input.freeAlternative}${interactiveNote}`
|
|
1871
1949
|
: (interactiveNote ? interactiveNote.trimStart() : undefined)
|
|
@@ -2664,6 +2742,7 @@ Rules:
|
|
|
2664
2742
|
- For replacement graphics, screenshots, or still-like scenes, prefer AI image generation plus Ken Burns before paying for AI video unless static_vs_pivot says motion footage is load-bearing.
|
|
2665
2743
|
- If narration must be customized, default to premium ElevenLabs first, then the user's own ElevenLabs path, then BYOK OpenAI/Gemini/OpenRouter. If captions or scenes were timed to the old VO, retime them to the new narration.
|
|
2666
2744
|
- NO HTML SLOP. You are editing HTML, but the output is a social video, not a web page. THE TEST IS THE NATIVE-EDITOR TEST: could you have made this element with the tools inside TikTok's own editor? That toolset is a font, a color, a stroke/outline, a soft shadow, a tight text box, alignment, opacity, rotation, animation presets — plus stickers, emoji, drawn marks and clips. It has NO padded capsule, NO border, NO gradient fill, NO blur panel, NO card. If you reached past it, cut it. Never author landing-page furniture: CTA "buttons" (a filled/gradient rounded capsule with action copy like "Sign Up for a Free Trial →"), benefit chip/badge rows ("✓ No Credit Card Needed"), bordered/shadowed/frosted cards holding a headline + URL, gradient text fills, feature grids, bulleted lists, or web-default fonts (Inter/Roboto/Arial/system-ui). AND NOT A SINGLE PILL EITHER: one lonely rounded, padded, filled capsule around a static stat or label — "10 hrs / week", "STEP 2", "EP.01", "+40%" — is a web badge, and being the only one on screen does not make it native. The ONLY legitimate capsule in a video is the active-word spotlight/karaoke caption highlight, because it moves with the spoken word. Emphasize a stat the way the editor would: bigger, heavier, ALL-CAPS, an accent color, a hand-drawn circle or underline, or its own beat on screen. Rule of thumb on anything holding words: border-radius over ~8px PLUS a background fill PLUS padding = a badge; drop the fill or drop the radius until the band hugs the glyphs. None of this appears in a real TikTok, and nothing in a video is clickable — say it as timed text on the footage instead. Arrows, scribble/underline marks, italics, ALL-CAPS, single-word color pops, emoji, transparent cut-out stickers, and mock social UI (iMessage bubbles, comment cards) are all fine. Captions use an imported family (Montserrat default / TikTok Sans / Abel / Source Code Pro / Yesteryear) at weight 700-900, ~36-64px on a 1080-wide frame, inside the 8%-85% safe zone, with exactly one of four backgrounds: outline, plain, an active-word spotlight/karaoke pill, or a tight-hugging solid band (radius <=8px, no border/shadow/gradient/blur).
|
|
2745
|
+
- NO LAYOUT TEMPLATES — JUDGE THE WHOLE FRAME, NOT JUST THE ELEMENT. Every rule above judges one element, and a frame can pass element-by-element and still be a web page. The archetype is the MODAL: the backdrop dimmed and blurred out of focus, and floating on top of it a rounded bordered box holding a big headline, a smaller support line, and a fat CTA button. THE STACK IS THE TELL, NOT THE BOX — delete the border, the fill and the capsule, keep headline then subheadline then CTA centred in a well with even margins, and it STILL reads as a landing page, because a viewer recognizes the SHAPE before reading a single word. Banned at frame level: a modal/dialog staged on top of a backdrop that has been dimmed, blurred, greyed or scaled back (nothing in a video pops "above" the video); the hero triplet and its cousins (title + kicker + logo lockup, question + answer + URL); a full-frame dark wash used to stage a floating block (a legibility band on ONE caption is legal, a page-wide wash to stage a panel is not; likewise a blurred backdrop is fine alone — a blurred fill behind a 16:9 clip in a 9:16 frame is a real technique — but blur PLUS dimming is modal staging); nav strip / hero / three-up feature row / testimonial block / footer fine print; a blurred website screenshot used as the background plate (if the backdrop is a web page, the frame is a screen recording of a web page — show the real product UI full-bleed and in focus, or don't show it); a centred content column with even gutters and document margins. THE FIX IS ALWAYS TO UNSTACK IT INTO TIME: the headline is the hook at start:0, the support line lands on the next cut, the CTA is SPOKEN or a bare caption on the final frame. You lose nothing — a viewer reads one line at a time anyway — and you gain the pacing that makes it look shot rather than designed. Self-check before you place any text group: am I arranging words relative to EACH OTHER, or relative to the PICTURE? Relative to each other is a layout, which is web. Two on-screen text runs at once is the ceiling. Verify on real pixels: \`vidfarm stills . --at <t>\` — if the still could be a screenshot of a website, rebuild the beat. \`vidfarm qa\` catches only the mechanical half (layout-template, modal-scrim); the frame-level judgement is yours.
|
|
2667
2746
|
- STRUCTURE BEFORE POLISH — THE FOUR CHARGES, WRITTEN BEFORE YOU TOUCH THE TIMELINE. Most agent-made videos fail on structure, not polish, because the timeline is the fun part so it gets built first and the words get retrofitted. Invert it: (1) HOOK — write the opening line as text first: a complete clause (subject + verb), no jargon, naming a SITUATION ("I've quit six businesses") not a label ("anonymity"); it goes on screen at start:0, because caption chunk 1 is read before any audio and muted autoplay is the default. Banned openings: throat-clearing ("so I was thinking", "here's the thing"), a logo, a title card, a fade from black, context before the claim. (2) LOOP — one open question by 0:10, said ON SCREEN, closing INSIDE this video (state the timestamp it closes at; if you can't, there is no loop), and the withheld answer must be one the viewer CANNOT supply themselves — a formally-correct loop with a guessable answer passes every mechanical check and dies in the field. (3) PAYOFF — shown, not summarized, ≥5 uninterrupted seconds, landing BEFORE the final beat; the payoff is not the CTA. (4) BAIT — one ask in the final beat and in the post caption; a keyword comment ask ("comment CLIPPER and I'll send the breakdown") is standard and allowed, but never "follow for part two", ragebait, or an earnings/health claim traded for the reply. Then build the timeline. Re-theming a decomposed template: viral_dna already names the source's hook/retention/payoff — rebuild each charge for the new subject, never flatten the loop into a product statement. Full craft harness: the vidfarm skill's references/hooks-and-virality.md. Checkable form: \`vidfarm harness show hooks\`.
|
|
2668
2747
|
- ORIENT THE COLD VIEWER IN THE FIRST 3 SECONDS — THE VIEWER HAS NO CONTEXT AND DID NOT CHOOSE THIS VIDEO. Distinct from the hook: the hook makes them WANT to watch, orientation makes the watching POSSIBLE. A stranger mid-scroll must be able to answer three things by ~3s — what am I looking at (the CATEGORY noun), who is it for, and why is this on my screen (the situation). The failure is not a bad first frame, it is a good video that BEGINS AT BEAT TWO, and the author cannot see it because the author already knows what the thing is. Signatures, each a rebuild not a polish: a pronoun with no referent ("it just works", "this changes everything", "here's how they do it"); starting at step three (the process already running, the dashboard already full); a metaphor whose subject only lands at 6s; insider vocabulary, a product's own feature name, or an ACRONYM in the first line; a detail crop that reads as texture until you know the whole. Instead, the opening beat is BOTH channels at once: an EASY IMAGE (one large subject, already moving, legible at a glance and at thumbnail scale — a relevant die-cut sticker names the category before a word is read) AND an EASY LINE (first spoken sentence one clause, <=12 words, everyday words, concrete noun + verb, no subordinate clause, brand name said once plainly, and the CATEGORY named: "X is a language app that…"). Give the SITUATION, not the label — "the end of the month, and your receipts are in a shoebox" orients, "expense automation" does not. THIS IS NOT AN INTRO AND COSTS NO EXTRA SECONDS: it replaces the wind-up sentence, it never precedes it, and it never licenses a logo, a title card or a fade from black. Test it on the render, not the script: play the first 3 seconds ONLY to somebody with no context and stop — they should say what kind of thing it is and roughly who it is for. "Something about audio" is a fail. Fullest form: \`vidfarm harness show product-explainer\` (Rule 0).
|
|
2669
2748
|
- THE FIRST FRAME IS THE THUMBNAIL. Frame 0 is one frame of ~30 in the first second, but every feed card, share link, and paused player freezes on it — more people see that frame than watch the video. It must never be black, empty, mid-fade, or mid-animation: a real visual at start:0 (\`vidfarm retime . --layer <key> --start 0\`), the hook words already on screen at t=0, and NO entrance transition on the FIRST clip (\`vidfarm transitions set . --layer <key> --in none\`; junction transitions between later clips are fine). Look at the actual pixels before you render: \`vidfarm stills . --at 0\`.
|
|
@@ -4682,6 +4761,7 @@ async function runGenerateCommand(argv) {
|
|
|
4682
4761
|
: {
|
|
4683
4762
|
label: "AI image generation",
|
|
4684
4763
|
estimate: "cheap, ~$0.01–$0.05",
|
|
4764
|
+
agentAlternative: AGENT_IMAGEGEN_ALTERNATIVE,
|
|
4685
4765
|
freeAlternative: 'free stock image/vector — vidfarm media search "<meaning>" --type image|vector ($0). ' +
|
|
4686
4766
|
"Openverse (CC images) is keyless and always on — check it first; a free Pixabay key adds " +
|
|
4687
4767
|
"photos/vectors and may already be saved (check vidfarm provider-keys). " +
|
|
@@ -4933,7 +5013,11 @@ async function runInpaintCommand(argv) {
|
|
|
4933
5013
|
}
|
|
4934
5014
|
});
|
|
4935
5015
|
const ctx = commonContext(parsed.values);
|
|
4936
|
-
guardBilled(ctx, {
|
|
5016
|
+
guardBilled(ctx, {
|
|
5017
|
+
label: "AI image inpaint",
|
|
5018
|
+
estimate: "cheap, ~$0.01–$0.05",
|
|
5019
|
+
agentAlternative: AGENT_IMAGEGEN_ALTERNATIVE
|
|
5020
|
+
});
|
|
4937
5021
|
const sourceArg = parsed.values.source ?? parsed.positionals[0];
|
|
4938
5022
|
if (!sourceArg)
|
|
4939
5023
|
throw new Error("inpaint requires a source image: `vidfarm inpaint <image|url> --mask <mask.png> --prompt \"...\"`.");
|
|
@@ -5069,7 +5153,11 @@ async function runCreateOverlayCommand(argv) {
|
|
|
5069
5153
|
}
|
|
5070
5154
|
});
|
|
5071
5155
|
const ctx = commonContext(parsed.values);
|
|
5072
|
-
guardBilled(ctx, {
|
|
5156
|
+
guardBilled(ctx, {
|
|
5157
|
+
label: "AI transparent overlay generation",
|
|
5158
|
+
estimate: "cheap, ~$0.01–$0.05",
|
|
5159
|
+
agentAlternative: AGENT_IMAGEGEN_ALTERNATIVE
|
|
5160
|
+
});
|
|
5073
5161
|
const prompt = (parsed.values.prompt ?? parsed.positionals.join(" ")).trim();
|
|
5074
5162
|
if (!prompt) {
|
|
5075
5163
|
throw new Error("create-overlay requires a subject prompt: `vidfarm create-overlay \"a cartoon rocket ship\" [--key-color #00FF00] [--out overlay.png]`. Describe ONLY the subject — the flat key-color background is added for you.");
|
|
@@ -6150,6 +6238,7 @@ async function runCutoutCommand(argv) {
|
|
|
6150
6238
|
guardBilled(ctx, {
|
|
6151
6239
|
label: "AI image generation (cutout plate)",
|
|
6152
6240
|
estimate: "cheap, ~$0.01–$0.05",
|
|
6241
|
+
agentAlternative: AGENT_IMAGEGEN_ALTERNATIVE,
|
|
6153
6242
|
freeAlternative: "pass an existing graphic instead — `vidfarm cutout <image|url>` keys+trims for $0.00",
|
|
6154
6243
|
interactiveAlternative: 'vidfarm handoff image --theme "<subject>" --single — the user generates the plate in a free web tool ' +
|
|
6155
6244
|
"and hands the PNG back; `vidfarm cutout <file>` then keys + trims it for $0"
|
|
@@ -6699,6 +6788,7 @@ async function runStickerPackCommand(argv) {
|
|
|
6699
6788
|
guardBilled(ctx, {
|
|
6700
6789
|
label: `AI image generation (sticker sheet of ${count} items)`,
|
|
6701
6790
|
estimate: "cheap, ~$0.01–$0.05 for the WHOLE pack (one image job, not one per sticker)",
|
|
6791
|
+
agentAlternative: AGENT_IMAGEGEN_ALTERNATIVE,
|
|
6702
6792
|
freeAlternative: "pass a greenscreen sheet you already have — `vidfarm sticker-pack <sheet.png>` cuts it up for $0.00",
|
|
6703
6793
|
interactiveAlternative: `vidfarm handoff image --theme "${generatePrompt.replace(/"/g, "'")}"${itemNames.length ? ` --items "${itemNames.join(",")}"` : ""} — ` +
|
|
6704
6794
|
"the user generates the SAME sheet in a free web tool (often better art than the API tier) and hands it " +
|
|
@@ -9478,6 +9568,15 @@ async function runCostModeCommand(argv) {
|
|
|
9478
9568
|
if (resolved.mode === "minimize") {
|
|
9479
9569
|
console.log(`${DIM}In minimize, ${interaction.mode === "interactive" ? "you're already on" : "offer"} the sweet spot: minimize + interactive = $0 videos that still get custom art (free web image gen → vidfarm sticker-pack) and hand-picked clips (vidfarm handoff raws).${RESET}`);
|
|
9480
9570
|
}
|
|
9571
|
+
// The one exception worth naming out loud: image generation the AGENT already
|
|
9572
|
+
// owns is free custom art with NO manual step, so minimize keeps it.
|
|
9573
|
+
if (resolved.mode === "minimize" || resolved.mode === "hybrid") {
|
|
9574
|
+
const detection = detectHostAgent();
|
|
9575
|
+
const verdict = detection.host
|
|
9576
|
+
? `${detection.host.name} — image generation ${detection.availability}`
|
|
9577
|
+
: "host agent not detected";
|
|
9578
|
+
console.log(`${DIM}Image generation included in YOUR agent's own subscription is free in every mode, minimize included (${verdict}). Check: ${BOLD}vidfarm agent-image --check${RESET}${DIM} · brief: vidfarm agent-image "<subject>".${RESET}`);
|
|
9579
|
+
}
|
|
9481
9580
|
}
|
|
9482
9581
|
// `vidfarm storyboard [dir]` — the PLAN pass, before any animation work.
|
|
9483
9582
|
// Storyboarding is a first-class part of the composition format now: a project
|
|
@@ -10029,6 +10128,106 @@ async function runHandoffCommand(argv) {
|
|
|
10029
10128
|
}
|
|
10030
10129
|
throw new Error('handoff needs a kind: `vidfarm handoff image --theme "…" --items "a,b,c"` (free web image gen → sticker pack) or `vidfarm handoff raws --keywords "…"` (manual clip sourcing).');
|
|
10031
10130
|
}
|
|
10131
|
+
// `vidfarm agent-image "<subject>"` — the brief for image generation the AGENT
|
|
10132
|
+
// runs on its OWN subscription. Vidfarm charges nothing and the provider charges
|
|
10133
|
+
// nothing extra, so this rung is allowed in EVERY cost mode, `minimize`
|
|
10134
|
+
// included. Antigravity / Gemini CLI and Codex / ChatGPT include an image tool;
|
|
10135
|
+
// Claude Code does not (Anthropic ships no image model) — those runs fall back
|
|
10136
|
+
// to stock, IconScout, a human hand-off, or a confirmed billed generation.
|
|
10137
|
+
async function runAgentImageCommand(argv) {
|
|
10138
|
+
const parsed = parseArgs({
|
|
10139
|
+
args: argv,
|
|
10140
|
+
allowPositionals: true,
|
|
10141
|
+
options: {
|
|
10142
|
+
...commonOptions(),
|
|
10143
|
+
theme: { type: "string" },
|
|
10144
|
+
items: { type: "string" },
|
|
10145
|
+
style: { type: "string" },
|
|
10146
|
+
"key-color": { type: "string" },
|
|
10147
|
+
"out-dir": { type: "string" },
|
|
10148
|
+
out: { type: "string" },
|
|
10149
|
+
folder: { type: "string" },
|
|
10150
|
+
grid: { type: "string" },
|
|
10151
|
+
single: { type: "boolean", default: false },
|
|
10152
|
+
zoned: { type: "boolean", default: false },
|
|
10153
|
+
check: { type: "boolean", default: false }
|
|
10154
|
+
}
|
|
10155
|
+
});
|
|
10156
|
+
const json = Boolean(parsed.values.json);
|
|
10157
|
+
const detection = detectHostAgent();
|
|
10158
|
+
// `--check` (and a bare invocation) answers only "do I have this at all?".
|
|
10159
|
+
if (parsed.values.check || (!parsed.values.theme && !parsed.values.items && !parsed.positionals.length)) {
|
|
10160
|
+
if (json) {
|
|
10161
|
+
return printJson({
|
|
10162
|
+
ok: true,
|
|
10163
|
+
host: detection.host?.id ?? null,
|
|
10164
|
+
host_name: detection.host?.name ?? null,
|
|
10165
|
+
availability: detection.availability,
|
|
10166
|
+
matched_env: detection.matched,
|
|
10167
|
+
known_hosts: KNOWN_HOST_AGENTS.map((h) => ({ id: h.id, name: h.name, availability: h.availability, note: h.note }))
|
|
10168
|
+
});
|
|
10169
|
+
}
|
|
10170
|
+
console.log(`${BOLD}Agent-included image generation${RESET}`);
|
|
10171
|
+
console.log(`${DIM}Vidfarm does not need to sell you an image model if the agent driving this terminal already has one.${RESET}\n`);
|
|
10172
|
+
if (detection.host) {
|
|
10173
|
+
const flag = detection.availability === "included" ? GREEN : detection.availability === "none" ? YELLOW : DIM;
|
|
10174
|
+
console.log(`Detected: ${flag}${detection.host.name}${RESET} — image generation ${BOLD}${detection.availability}${RESET}`);
|
|
10175
|
+
console.log(`${DIM}${detection.host.note}${RESET}`);
|
|
10176
|
+
console.log(`${DIM}Matched env: ${detection.matched.join(", ")}${RESET}\n`);
|
|
10177
|
+
}
|
|
10178
|
+
else {
|
|
10179
|
+
console.log(`${DIM}Host agent not detected from the environment.${RESET}\n`);
|
|
10180
|
+
}
|
|
10181
|
+
for (const h of KNOWN_HOST_AGENTS) {
|
|
10182
|
+
console.log(` ${h.availability === "included" ? GREEN + "✓" : h.availability === "none" ? YELLOW + "✗" : DIM + "?"}${RESET} ${h.name} ${DIM}— ${h.availability}${RESET}`);
|
|
10183
|
+
}
|
|
10184
|
+
console.log(`\n${DIM}The env check is a hint only. The authority is your own tool list — if you have an image tool, you have this.${RESET}`);
|
|
10185
|
+
console.log(`${DIM}Brief: ${BOLD}vidfarm agent-image "<subject>" --items "a,b,c"${RESET}${DIM} · free in EVERY cost mode, minimize included.${RESET}`);
|
|
10186
|
+
return;
|
|
10187
|
+
}
|
|
10188
|
+
const splitList = (raw) => (raw ?? "").split(/\s*[;,]\s*/).map((s) => s.trim()).filter(Boolean);
|
|
10189
|
+
const theme = parsed.values.theme?.trim() || parsed.positionals.join(" ").trim();
|
|
10190
|
+
const items = splitList(parsed.values.items);
|
|
10191
|
+
if (!theme && !items.length) {
|
|
10192
|
+
throw new Error('agent-image needs a subject: `vidfarm agent-image "cozy farm props" --items "barn,tractor,hay bale"`.');
|
|
10193
|
+
}
|
|
10194
|
+
const brief = buildAgentImageBrief({
|
|
10195
|
+
theme: theme || items.join(", "),
|
|
10196
|
+
items,
|
|
10197
|
+
style: parsed.values.style,
|
|
10198
|
+
keyColor: parsed.values["key-color"],
|
|
10199
|
+
outDir: parsed.values["out-dir"],
|
|
10200
|
+
outFile: parsed.values.out,
|
|
10201
|
+
folder: parsed.values.folder,
|
|
10202
|
+
grid: parsed.values.grid,
|
|
10203
|
+
pack: parsed.values.single ? false : undefined,
|
|
10204
|
+
zoned: Boolean(parsed.values.zoned),
|
|
10205
|
+
detection
|
|
10206
|
+
});
|
|
10207
|
+
if (json) {
|
|
10208
|
+
return printJson({
|
|
10209
|
+
ok: true,
|
|
10210
|
+
host: detection.host?.id ?? null,
|
|
10211
|
+
availability: brief.availability,
|
|
10212
|
+
out_file: brief.outFile,
|
|
10213
|
+
prompt: brief.prompt,
|
|
10214
|
+
steps: brief.steps,
|
|
10215
|
+
follow_up: brief.followUp,
|
|
10216
|
+
fallbacks: brief.fallbacks,
|
|
10217
|
+
key_color: brief.keyColor,
|
|
10218
|
+
key_color_note: brief.keyColorNote
|
|
10219
|
+
});
|
|
10220
|
+
}
|
|
10221
|
+
if (detection.availability === "none") {
|
|
10222
|
+
console.log(`${YELLOW}${BOLD}This host has no image tool of its own — read the fallbacks at the bottom first.${RESET}`);
|
|
10223
|
+
console.log(`${DIM}The prompt is still below: it is the same prompt for a human hand-off or a billed generation.${RESET}\n`);
|
|
10224
|
+
}
|
|
10225
|
+
else {
|
|
10226
|
+
console.log(`${BOLD}Generate this yourself — it is already in your subscription.${RESET}`);
|
|
10227
|
+
console.log(`${DIM}Costs $0 on Vidfarm and $0 extra on the provider, so it is allowed in cost mode minimize.${RESET}\n`);
|
|
10228
|
+
}
|
|
10229
|
+
console.log(formatAgentImageBrief(brief, detection));
|
|
10230
|
+
}
|
|
10032
10231
|
// `vidfarm consult [step]` — the consultation / brainstorm chain, run KEYLESS
|
|
10033
10232
|
// and LOCAL. The cloud version of each step is a `brainstorm/*` primitive that
|
|
10034
10233
|
// needs a provider key or wallet credits; this prints the identical prompt for
|
|
@@ -12843,7 +13042,11 @@ async function runUpdateSkillCommand(argv) {
|
|
|
12843
13042
|
void main().catch(async (error) => {
|
|
12844
13043
|
// Deliberate, expected user-facing conditions (e.g. local mode in the
|
|
12845
13044
|
// published cloud-only CLI) print just the message — no stack, no crash report.
|
|
12846
|
-
if (error instanceof LocalModeUnavailableError
|
|
13045
|
+
if (error instanceof LocalModeUnavailableError
|
|
13046
|
+
|| error instanceof CostModeBlockedError
|
|
13047
|
+
// A missing OPTIONAL native module (better-sqlite3 with no C++ toolchain,
|
|
13048
|
+
// the common Windows case) is an environment fact, not a vidfarm bug.
|
|
13049
|
+
|| error instanceof NativeModuleUnavailableError) {
|
|
12847
13050
|
console.error(error.message);
|
|
12848
13051
|
process.exit(1);
|
|
12849
13052
|
}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
// Agent-included image generation — the $0 rung between "free stock" and "pay
|
|
2
|
+
// Vidfarm to generate it".
|
|
3
|
+
//
|
|
4
|
+
// The premise: Vidfarm does not need to broker an image model when the agent
|
|
5
|
+
// driving the terminal ALREADY has one included in its own subscription. Google
|
|
6
|
+
// Antigravity / Gemini CLI ship image generation (Nano Banana / Imagen) at no
|
|
7
|
+
// extra charge. OpenAI Codex / ChatGPT ship gpt-image. Claude does not — there
|
|
8
|
+
// is no Anthropic image model, so Claude Code has nothing to fall back on here.
|
|
9
|
+
//
|
|
10
|
+
// That distinction is the whole feature. In cost mode `minimize` the old answer
|
|
11
|
+
// to "I need a graphic" was: free stock, IconScout, or hand the human a prompt.
|
|
12
|
+
// If the agent's own runtime includes image generation, there is a better answer
|
|
13
|
+
// that is still $0 — the agent generates the file itself and imports it. Same
|
|
14
|
+
// house pattern as `vidfarm consult`: the devcli writes the brief, the agent in
|
|
15
|
+
// the terminal executes it. See references/agent-included-imagegen.md.
|
|
16
|
+
//
|
|
17
|
+
// Availability is asserted by the AGENT, not sniffed by us. Env detection here
|
|
18
|
+
// is a hint for the opening line only; the authoritative check is the agent
|
|
19
|
+
// looking at its own tool list. Never claim a capability the agent has to prove.
|
|
20
|
+
//
|
|
21
|
+
// Backend-free (Node built-ins + pure sibling modules) so it ships in the public
|
|
22
|
+
// cloud-only package.
|
|
23
|
+
import { buildImageHandoff } from "./handoff.js";
|
|
24
|
+
/**
|
|
25
|
+
* Hosts we can say something concrete about. Kept deliberately short: a wrong
|
|
26
|
+
* "yes" costs the user a wasted turn, a wrong "no" costs them money, so anything
|
|
27
|
+
* we are not sure of stays `unknown` and the agent checks its own tools.
|
|
28
|
+
*/
|
|
29
|
+
export const KNOWN_HOST_AGENTS = [
|
|
30
|
+
{
|
|
31
|
+
id: "claude-code",
|
|
32
|
+
name: "Claude Code",
|
|
33
|
+
availability: "none",
|
|
34
|
+
envMarkers: ["CLAUDECODE", "CLAUDE_CODE", "CLAUDE_CODE_ENTRYPOINT"],
|
|
35
|
+
note: "Anthropic ships no image model, so there is nothing included here. Use free stock / IconScout, hand the user a prompt (`vidfarm handoff image`), or spend on `vidfarm generate image`."
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
id: "antigravity",
|
|
39
|
+
name: "Google Antigravity",
|
|
40
|
+
availability: "included",
|
|
41
|
+
tool: "the built-in Gemini image generation (Nano Banana / Imagen)",
|
|
42
|
+
envMarkers: ["ANTIGRAVITY", "ANTIGRAVITY_SESSION", "ANTIGRAVITY_WORKSPACE"],
|
|
43
|
+
note: "Image generation is part of the Gemini subscription — generating a graphic costs $0 extra."
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
id: "gemini-cli",
|
|
47
|
+
name: "Gemini CLI",
|
|
48
|
+
availability: "included",
|
|
49
|
+
tool: "the built-in Gemini image generation (Nano Banana / Imagen)",
|
|
50
|
+
envMarkers: ["GEMINI_CLI", "GEMINI_CLI_SESSION", "GEMINI_SANDBOX"],
|
|
51
|
+
note: "Image generation is part of the Gemini subscription — generating a graphic costs $0 extra."
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
id: "codex",
|
|
55
|
+
name: "OpenAI Codex",
|
|
56
|
+
availability: "included",
|
|
57
|
+
tool: "the built-in OpenAI image generation (gpt-image)",
|
|
58
|
+
envMarkers: ["CODEX_SANDBOX", "CODEX_HOME", "CODEX_CLI"],
|
|
59
|
+
note: "Image generation is part of the ChatGPT/Codex subscription — generating a graphic costs $0 extra."
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
id: "opencode",
|
|
63
|
+
name: "OpenCode",
|
|
64
|
+
availability: "unknown",
|
|
65
|
+
envMarkers: ["OPENCODE", "OPENCODE_SESSION"],
|
|
66
|
+
note: "Depends entirely on which model is configured — check your own tool list."
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
id: "cursor",
|
|
70
|
+
name: "Cursor",
|
|
71
|
+
availability: "unknown",
|
|
72
|
+
envMarkers: ["CURSOR_TRACE_ID", "CURSOR_SESSION_ID"],
|
|
73
|
+
note: "Depends on the selected model — check your own tool list."
|
|
74
|
+
}
|
|
75
|
+
];
|
|
76
|
+
/**
|
|
77
|
+
* Guess which agent runtime is driving this terminal from its env markers.
|
|
78
|
+
* A miss is normal and harmless — `availability: "unknown"` just means the brief
|
|
79
|
+
* asks the agent to check its own tools instead of asserting anything.
|
|
80
|
+
*/
|
|
81
|
+
export function detectHostAgent(env = process.env) {
|
|
82
|
+
for (const host of KNOWN_HOST_AGENTS) {
|
|
83
|
+
const matched = host.envMarkers.filter((k) => {
|
|
84
|
+
const v = env[k];
|
|
85
|
+
return typeof v === "string" && v.trim() !== "" && v.trim() !== "0" && v.trim().toLowerCase() !== "false";
|
|
86
|
+
});
|
|
87
|
+
if (matched.length)
|
|
88
|
+
return { host, matched, availability: host.availability };
|
|
89
|
+
}
|
|
90
|
+
return { host: null, matched: [], availability: "unknown" };
|
|
91
|
+
}
|
|
92
|
+
/** One line naming this rung, for cost-mode block messages and help text. */
|
|
93
|
+
export const AGENT_IMAGEGEN_ALTERNATIVE = "generate it YOURSELF for $0 if your own agent subscription includes image generation " +
|
|
94
|
+
"(Google Antigravity / Gemini CLI and OpenAI Codex / ChatGPT do; Claude Code does NOT — " +
|
|
95
|
+
'Anthropic ships no image model) — run `vidfarm agent-image "<subject>" --items "a,b,c"` for ' +
|
|
96
|
+
"the prompt, the plate rules and the import command, then `vidfarm put-file` the result";
|
|
97
|
+
/** The shorter form used inside prose blurbs. */
|
|
98
|
+
export const AGENT_IMAGEGEN_SHORT = 'if YOUR agent subscription includes image generation (Gemini/Antigravity, Codex/ChatGPT — not Claude), generate it yourself: `vidfarm agent-image "<subject>"`';
|
|
99
|
+
/**
|
|
100
|
+
* Build the brief the AGENT executes itself. The prompt body is shared verbatim
|
|
101
|
+
* with `vidfarm handoff image` (`buildImageHandoff`) — a plate that keys cleanly
|
|
102
|
+
* and art that survives the cut are the same craft whoever runs the generator —
|
|
103
|
+
* only the STEPS change, because here the runner is the agent, not the human.
|
|
104
|
+
*/
|
|
105
|
+
export function buildAgentImageBrief(input) {
|
|
106
|
+
const base = buildImageHandoff(input);
|
|
107
|
+
const detection = input.detection ?? detectHostAgent();
|
|
108
|
+
const items = input.items.map((s) => s.trim()).filter(Boolean);
|
|
109
|
+
const pack = input.pack ?? items.length > 1;
|
|
110
|
+
const outDir = input.outDir ?? "./stickers";
|
|
111
|
+
const outFile = input.outFile ?? (pack ? "./sheet.png" : "./art.png");
|
|
112
|
+
const folderFlag = input.folder ? ` --folder ${input.folder}` : "";
|
|
113
|
+
const cutCmd = pack
|
|
114
|
+
? `vidfarm sticker-pack ${outFile}${items.length ? ` --items "${items.join(",")}"` : ""} --out-dir ${outDir}`
|
|
115
|
+
: `vidfarm cutout ${outFile}`;
|
|
116
|
+
const steps = [
|
|
117
|
+
"Check YOUR OWN tool list for an image-generation tool included in this subscription — " +
|
|
118
|
+
"Antigravity / Gemini CLI have one (Nano Banana / Imagen), Codex / ChatGPT have one (gpt-image), " +
|
|
119
|
+
"Claude Code has none. If you have none, use the fallbacks below instead; do not pretend.",
|
|
120
|
+
`Generate the image with that tool using the prompt below, and save it to ${outFile}. ` +
|
|
121
|
+
"This spends nothing on Vidfarm and nothing extra on the provider — it is already in the subscription.",
|
|
122
|
+
"Look at the result before you use it: a flat even plate, crisp edges, nothing touching or " +
|
|
123
|
+
"cropped at the frame edge. Re-generate rather than shipping a sheet that will cut badly.",
|
|
124
|
+
`Cut it locally for $0: \`${cutCmd}\`.`,
|
|
125
|
+
`Bring the asset into the library so later videos reuse it: \`vidfarm put-file ${outDir}/<file>.png${folderFlag}\`.`
|
|
126
|
+
];
|
|
127
|
+
const fallbacks = [
|
|
128
|
+
'Free stock first, always — `vidfarm media search "<meaning>" --type image|vector` (Openverse is keyless).',
|
|
129
|
+
'Any icon, sticker, illustration, 3D prop or Lottie — `vidfarm iconscout "<meaning>" --free` beats generation on price AND quality.',
|
|
130
|
+
'Hand the human the prompt — `vidfarm handoff image --theme "<what>" --items "a,b,c"`; they run it in a free web generator.',
|
|
131
|
+
"Only then spend: `vidfarm generate image --prompt \"…\"` (~$0.01–$0.05, billed to the user's own provider key)."
|
|
132
|
+
];
|
|
133
|
+
return {
|
|
134
|
+
...base,
|
|
135
|
+
outFile,
|
|
136
|
+
availability: detection.availability,
|
|
137
|
+
hostName: detection.host?.name ?? null,
|
|
138
|
+
steps,
|
|
139
|
+
followUp: cutCmd,
|
|
140
|
+
fallbacks,
|
|
141
|
+
tools: detection.host?.tool
|
|
142
|
+
? [detection.host.tool]
|
|
143
|
+
: ["your own runtime's image-generation tool, if this subscription includes one"]
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
/** Render the brief as the block an agent reads (and may show the user). */
|
|
147
|
+
export function formatAgentImageBrief(brief, detection) {
|
|
148
|
+
const lines = [];
|
|
149
|
+
const host = detection.host;
|
|
150
|
+
if (host && host.availability === "included") {
|
|
151
|
+
lines.push(`Detected host: ${host.name} — image generation IS included in this subscription.`);
|
|
152
|
+
lines.push(host.note);
|
|
153
|
+
}
|
|
154
|
+
else if (host && host.availability === "none") {
|
|
155
|
+
lines.push(`Detected host: ${host.name} — image generation is NOT included.`);
|
|
156
|
+
lines.push(host.note);
|
|
157
|
+
}
|
|
158
|
+
else if (host) {
|
|
159
|
+
lines.push(`Detected host: ${host.name} — unclear whether image generation is included.`);
|
|
160
|
+
lines.push(host.note);
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
lines.push("Host agent not detected from the environment.");
|
|
164
|
+
}
|
|
165
|
+
lines.push("The env check is only a hint. YOU are the authority: look at your own tool list.");
|
|
166
|
+
lines.push("");
|
|
167
|
+
brief.steps.forEach((s, i) => lines.push(`${i + 1}. ${s}`));
|
|
168
|
+
lines.push("");
|
|
169
|
+
lines.push("─── the generation prompt ───");
|
|
170
|
+
lines.push(brief.prompt);
|
|
171
|
+
lines.push("─────────────────────────────");
|
|
172
|
+
if (brief.keyColorNote) {
|
|
173
|
+
lines.push("");
|
|
174
|
+
lines.push(`Plate: ${brief.keyColorNote}`);
|
|
175
|
+
}
|
|
176
|
+
lines.push("");
|
|
177
|
+
lines.push("If you have NO image tool of your own, in this order:");
|
|
178
|
+
brief.fallbacks.forEach((f) => lines.push(` • ${f}`));
|
|
179
|
+
return lines.join("\n");
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=agent-imagegen.js.map
|