image-skill 0.1.43 → 0.1.45
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/CHANGELOG.md +16 -0
- package/README.md +9 -9
- package/SKILL.md +10 -10
- package/bin/image-skill.mjs +430 -22
- package/cli.md +13 -4
- package/commands.json +1 -0
- package/llms.txt +2 -2
- package/package.json +1 -1
- package/skill.md +10 -10
- package/skills/agent-image-generation/SKILL.md +78 -0
- package/skills/ai-audio-generation/SKILL.md +3 -3
- package/skills/ai-image-generation/SKILL.md +3 -3
- package/skills/ai-video-generation/SKILL.md +3 -3
- package/skills/creative-media/SKILL.md +3 -3
- package/skills/image-edit/SKILL.md +3 -3
- package/skills/image-generation/SKILL.md +3 -3
- package/skills/image-skill/SKILL.md +10 -10
- package/skills/image-skill/references/cli.md +13 -4
- package/skills/image-skill/references/commands.json +1 -0
- package/skills/image-skill/references/llms.txt +2 -2
- package/skills/image-to-3d/SKILL.md +3 -3
package/bin/image-skill.mjs
CHANGED
|
@@ -15,7 +15,7 @@ import { Readable } from "node:stream";
|
|
|
15
15
|
import { pipeline } from "node:stream/promises";
|
|
16
16
|
import os from "node:os";
|
|
17
17
|
|
|
18
|
-
const VERSION = "0.1.
|
|
18
|
+
const VERSION = "0.1.45";
|
|
19
19
|
const PACKAGE_NAME = "image-skill";
|
|
20
20
|
const DEFAULT_API_BASE_URL = "https://api.image-skill.com";
|
|
21
21
|
const DEFAULT_DOCS_BASE_URL = "https://image-skill.com";
|
|
@@ -49,6 +49,9 @@ const HOSTED_SIGNUP_TOKEN_RETURNED_WARNING =
|
|
|
49
49
|
const PUBLIC_NPX_COMMAND_PREFIX =
|
|
50
50
|
"npm_config_update_notifier=false npx -y image-skill@latest";
|
|
51
51
|
const CREDIT_UNIT_USD = 0.01;
|
|
52
|
+
const TARGET_GROSS_MARGIN = 0.4;
|
|
53
|
+
const PAYMENT_BACKED_CREDIT_PAYMENT_FEE_RATE = 0.015;
|
|
54
|
+
const PAYMENT_BACKED_CREDIT_PAYMENT_FEE_MODEL = "stripe_stablecoin_usd_percent";
|
|
52
55
|
const MODALITY_COMMAND_ALIASES = new Map([
|
|
53
56
|
["image", { command: "create", intent: null }],
|
|
54
57
|
["video", { command: "create", intent: "video" }],
|
|
@@ -529,6 +532,7 @@ function commandHelpByKey(key) {
|
|
|
529
532
|
docs_url: "https://image-skill.com/cli.md#image-skill-edit",
|
|
530
533
|
required_flags: ["--input"],
|
|
531
534
|
optional_flags: [
|
|
535
|
+
"--guide",
|
|
532
536
|
"--dry-run",
|
|
533
537
|
"--prompt",
|
|
534
538
|
"--model",
|
|
@@ -1607,17 +1611,19 @@ async function capabilities(argv) {
|
|
|
1607
1611
|
});
|
|
1608
1612
|
}
|
|
1609
1613
|
|
|
1610
|
-
async function createGuide(args) {
|
|
1614
|
+
async function createGuide(args, options = {}) {
|
|
1615
|
+
const guideOperation = options.guideOperation ?? "create";
|
|
1616
|
+
const command = `image-skill ${guideOperation} --guide`;
|
|
1611
1617
|
if (flagBool(args, "dry-run")) {
|
|
1612
1618
|
return invalid(
|
|
1613
|
-
|
|
1614
|
-
|
|
1619
|
+
command,
|
|
1620
|
+
`${guideOperation} --guide cannot be combined with --dry-run; the guide returns the dry-run escape hatch separately`,
|
|
1615
1621
|
);
|
|
1616
1622
|
}
|
|
1617
1623
|
if (hasReferenceFlags(args)) {
|
|
1618
1624
|
return invalid(
|
|
1619
|
-
|
|
1620
|
-
|
|
1625
|
+
command,
|
|
1626
|
+
`${guideOperation} --guide does not upload or resolve reference images; inspect the model with models show, then run ${guideOperation} --dry-run before live referenced media calls`,
|
|
1621
1627
|
);
|
|
1622
1628
|
}
|
|
1623
1629
|
const modelParameters = jsonObjectFlag(args, "model-parameters-json");
|
|
@@ -1632,6 +1638,10 @@ async function createGuide(args) {
|
|
|
1632
1638
|
const requestedProviderId = flagString(args, "provider");
|
|
1633
1639
|
const requestedIntentFlag = flagString(args, "intent");
|
|
1634
1640
|
const requestedIntent = requestedIntentFlag ?? "explore";
|
|
1641
|
+
const requestedModelParametersJson =
|
|
1642
|
+
modelParameters.value === null
|
|
1643
|
+
? null
|
|
1644
|
+
: JSON.stringify(modelParameters.value);
|
|
1635
1645
|
const maxEstimatedUsdPerImage = flagNumber(
|
|
1636
1646
|
args,
|
|
1637
1647
|
"max-estimated-usd-per-image",
|
|
@@ -1662,17 +1672,58 @@ async function createGuide(args) {
|
|
|
1662
1672
|
const selected =
|
|
1663
1673
|
models.envelope.ok && models.envelope.data?.models
|
|
1664
1674
|
? selectCreateGuideModel(models.envelope.data.models, requestedModelId, {
|
|
1675
|
+
operation: guideOperation,
|
|
1665
1676
|
prompt: trimmedPrompt,
|
|
1666
1677
|
intent: requestedIntent,
|
|
1667
1678
|
maxEstimatedUsdPerImage,
|
|
1668
1679
|
})
|
|
1669
1680
|
: null;
|
|
1670
1681
|
const selectedAspectRatio = createGuideSuggestedAspectRatio(selected);
|
|
1671
|
-
const
|
|
1682
|
+
const pricingContext = {
|
|
1683
|
+
aspectRatio: selectedAspectRatio ?? "1:1",
|
|
1684
|
+
outputCount: 1,
|
|
1685
|
+
};
|
|
1686
|
+
const defaultedModelParameters =
|
|
1687
|
+
selected === null || createGuideSelectedModelRequiresInputImage(selected)
|
|
1688
|
+
? {
|
|
1689
|
+
modelParameters: modelParameters.value ?? {},
|
|
1690
|
+
defaultsApplied: [],
|
|
1691
|
+
}
|
|
1692
|
+
: createGuideDefaultModelParameters({
|
|
1693
|
+
model: selected,
|
|
1694
|
+
aspectRatio: pricingContext.aspectRatio,
|
|
1695
|
+
intent: requestedIntent,
|
|
1696
|
+
modelParameters: modelParameters.value ?? {},
|
|
1697
|
+
maxEstimatedUsdPerImage,
|
|
1698
|
+
});
|
|
1699
|
+
const shouldPriceModelParameters =
|
|
1700
|
+
selected !== null &&
|
|
1701
|
+
!createGuideSelectedModelRequiresInputImage(selected) &&
|
|
1702
|
+
createGuideCanPriceModelParameters(selected) &&
|
|
1703
|
+
(defaultedModelParameters.defaultsApplied.length > 0 ||
|
|
1704
|
+
Object.keys(modelParameters.value ?? {}).length > 0);
|
|
1705
|
+
const pricing =
|
|
1706
|
+
selected === null
|
|
1707
|
+
? null
|
|
1708
|
+
: shouldPriceModelParameters
|
|
1709
|
+
? createGuidePricingForModel(
|
|
1710
|
+
selected,
|
|
1711
|
+
defaultedModelParameters.modelParameters,
|
|
1712
|
+
pricingContext,
|
|
1713
|
+
)
|
|
1714
|
+
: createGuideModelCreditPricing(selected);
|
|
1715
|
+
const providerCostEstimate =
|
|
1716
|
+
selected === null || !shouldPriceModelParameters
|
|
1717
|
+
? null
|
|
1718
|
+
: createGuideProviderCostEstimateForModel(
|
|
1719
|
+
selected,
|
|
1720
|
+
defaultedModelParameters.modelParameters,
|
|
1721
|
+
pricingContext,
|
|
1722
|
+
);
|
|
1672
1723
|
const estimatedCredits = pricing?.credits_required ?? null;
|
|
1673
1724
|
const estimatedProviderUsdPerImage =
|
|
1725
|
+
providerCostEstimate?.estimated_provider_cost_usd ??
|
|
1674
1726
|
selected?.economics?.estimated_usd_per_image ??
|
|
1675
|
-
pricing?.estimated_provider_cost_usd ??
|
|
1676
1727
|
pricing?.fallback_provider_cost_usd ??
|
|
1677
1728
|
(typeof selected?.estimated_usd_per_image === "number"
|
|
1678
1729
|
? selected.estimated_usd_per_image
|
|
@@ -1699,6 +1750,9 @@ async function createGuide(args) {
|
|
|
1699
1750
|
token.source === "anonymous" ? "none" : token.source;
|
|
1700
1751
|
const stage = createGuideStage({
|
|
1701
1752
|
prompt: trimmedPrompt,
|
|
1753
|
+
promptRequired:
|
|
1754
|
+
trimmedPrompt.length === 0 &&
|
|
1755
|
+
(selected === null || !PROMPTLESS_EDIT_MODEL_IDS.has(selected.id)),
|
|
1702
1756
|
health,
|
|
1703
1757
|
models,
|
|
1704
1758
|
selected,
|
|
@@ -1730,9 +1784,12 @@ async function createGuide(args) {
|
|
|
1730
1784
|
requestedIntent,
|
|
1731
1785
|
requestedIntentFlag,
|
|
1732
1786
|
requestedModelId,
|
|
1787
|
+
guideOperation,
|
|
1788
|
+
inputReference: options.inputReference,
|
|
1733
1789
|
maxEstimatedUsdPerImage,
|
|
1734
1790
|
budgetGuard,
|
|
1735
1791
|
aspectRatio: selectedAspectRatio,
|
|
1792
|
+
modelParametersJson: requestedModelParametersJson,
|
|
1736
1793
|
apiBaseUrl: explicitApiBaseUrl(args),
|
|
1737
1794
|
paymentSummary,
|
|
1738
1795
|
commandPrefix: guideCommandPrefix,
|
|
@@ -1748,9 +1805,12 @@ async function createGuide(args) {
|
|
|
1748
1805
|
requestedIntent,
|
|
1749
1806
|
requestedIntentFlag,
|
|
1750
1807
|
requestedModelId,
|
|
1808
|
+
guideOperation,
|
|
1809
|
+
inputReference: options.inputReference,
|
|
1751
1810
|
maxEstimatedUsdPerImage,
|
|
1752
1811
|
budgetGuard,
|
|
1753
1812
|
aspectRatio: selectedAspectRatio,
|
|
1813
|
+
modelParametersJson: requestedModelParametersJson,
|
|
1754
1814
|
apiBaseUrl: explicitApiBaseUrl(args),
|
|
1755
1815
|
commandPrefix: guideCommandPrefix,
|
|
1756
1816
|
});
|
|
@@ -1792,10 +1852,13 @@ async function createGuide(args) {
|
|
|
1792
1852
|
explicitApiBaseUrl(args),
|
|
1793
1853
|
guideCommandPrefix,
|
|
1794
1854
|
{
|
|
1855
|
+
operation: guideOperation,
|
|
1856
|
+
inputReference: options.inputReference,
|
|
1795
1857
|
modelId: requestedModelId,
|
|
1796
1858
|
providerId: requestedProviderId,
|
|
1797
1859
|
intent: requestedIntentFlag,
|
|
1798
1860
|
maxEstimatedUsdPerImage,
|
|
1861
|
+
modelParametersJson: requestedModelParametersJson,
|
|
1799
1862
|
},
|
|
1800
1863
|
)
|
|
1801
1864
|
: null;
|
|
@@ -1818,8 +1881,19 @@ async function createGuide(args) {
|
|
|
1818
1881
|
tokenSource: publicTokenSource,
|
|
1819
1882
|
commandPrefix: guideCommandPrefix,
|
|
1820
1883
|
});
|
|
1821
|
-
|
|
1822
|
-
|
|
1884
|
+
const guideRecovery = createGuideRecovery(stage, {
|
|
1885
|
+
blocker,
|
|
1886
|
+
nextCommand,
|
|
1887
|
+
noSpendNextCommand,
|
|
1888
|
+
afterNext,
|
|
1889
|
+
escapeHatches,
|
|
1890
|
+
selfFundNextCommand,
|
|
1891
|
+
});
|
|
1892
|
+
return createGuideSuccess(command, quota?.envelope.actor ?? null, {
|
|
1893
|
+
schema:
|
|
1894
|
+
guideOperation === "edit"
|
|
1895
|
+
? "image-skill.edit-guide.v1"
|
|
1896
|
+
: "image-skill.create-guide.v1",
|
|
1823
1897
|
ready: stage === "ready_to_create",
|
|
1824
1898
|
stage,
|
|
1825
1899
|
checks: {
|
|
@@ -1884,6 +1958,7 @@ async function createGuide(args) {
|
|
|
1884
1958
|
selected,
|
|
1885
1959
|
trimmedPrompt,
|
|
1886
1960
|
requestedIntent,
|
|
1961
|
+
guideOperation,
|
|
1887
1962
|
)
|
|
1888
1963
|
: createGuideSelectedModelRequiresInputImage(selected)
|
|
1889
1964
|
? selected.modality === "3d"
|
|
@@ -1898,6 +1973,9 @@ async function createGuide(args) {
|
|
|
1898
1973
|
estimated_provider_usd_per_image: estimatedProviderUsdPerImage,
|
|
1899
1974
|
credit_unit_usd: pricing?.credit_unit_usd ?? CREDIT_UNIT_USD,
|
|
1900
1975
|
pricing_confidence: pricing?.pricing_confidence ?? null,
|
|
1976
|
+
pricing_source: pricing?.pricing_source ?? null,
|
|
1977
|
+
model_parameter_defaults_applied:
|
|
1978
|
+
defaultedModelParameters.defaultsApplied,
|
|
1901
1979
|
},
|
|
1902
1980
|
blocker,
|
|
1903
1981
|
guide_warning: guideWarning,
|
|
@@ -1910,6 +1988,7 @@ async function createGuide(args) {
|
|
|
1910
1988
|
no_spend_next_command_label: noSpendNextCommandLabel,
|
|
1911
1989
|
no_spend_next_command_effect: noSpendNextCommandEffect,
|
|
1912
1990
|
no_spend_evaluation: noSpendEvaluation,
|
|
1991
|
+
guide_recovery: guideRecovery,
|
|
1913
1992
|
recommended_no_spend_command: noSpendNextCommand,
|
|
1914
1993
|
recommended_no_spend_command_label: noSpendNextCommandLabel,
|
|
1915
1994
|
recommended_no_spend_command_effect: noSpendNextCommandEffect,
|
|
@@ -1930,8 +2009,8 @@ async function createGuide(args) {
|
|
|
1930
2009
|
});
|
|
1931
2010
|
}
|
|
1932
2011
|
|
|
1933
|
-
function createGuideSuccess(actor, data) {
|
|
1934
|
-
const result = success(
|
|
2012
|
+
function createGuideSuccess(command, actor, data) {
|
|
2013
|
+
const result = success(command, data);
|
|
1935
2014
|
result.envelope.actor = actor;
|
|
1936
2015
|
return result;
|
|
1937
2016
|
}
|
|
@@ -1939,7 +2018,12 @@ function createGuideSuccess(actor, data) {
|
|
|
1939
2018
|
function selectCreateGuideModel(
|
|
1940
2019
|
models,
|
|
1941
2020
|
requestedModelId,
|
|
1942
|
-
{
|
|
2021
|
+
{
|
|
2022
|
+
operation = "create",
|
|
2023
|
+
prompt = "",
|
|
2024
|
+
intent = undefined,
|
|
2025
|
+
maxEstimatedUsdPerImage = null,
|
|
2026
|
+
} = {},
|
|
1943
2027
|
) {
|
|
1944
2028
|
const isExecutableCreate = (model) =>
|
|
1945
2029
|
model?.status === "available" &&
|
|
@@ -1953,14 +2037,19 @@ function selectCreateGuideModel(
|
|
|
1953
2037
|
(model.supports.includes("edit") || model.supports.includes("variation")) &&
|
|
1954
2038
|
createGuideSelectedModelRequiresInputImage(model);
|
|
1955
2039
|
const isExecutableGuideModel = (model) =>
|
|
1956
|
-
|
|
2040
|
+
operation === "edit"
|
|
2041
|
+
? isExecutableInputImageEdit(model)
|
|
2042
|
+
: isExecutableCreate(model) || isExecutableInputImageEdit(model);
|
|
1957
2043
|
if (requestedModelId !== null) {
|
|
1958
2044
|
const requested = models.find((model) => model.id === requestedModelId);
|
|
1959
2045
|
return requested !== undefined && isExecutableGuideModel(requested)
|
|
1960
2046
|
? requested
|
|
1961
2047
|
: null;
|
|
1962
2048
|
}
|
|
1963
|
-
const candidates =
|
|
2049
|
+
const candidates =
|
|
2050
|
+
operation === "edit"
|
|
2051
|
+
? models.filter(isExecutableInputImageEdit)
|
|
2052
|
+
: models.filter(isExecutableCreate);
|
|
1964
2053
|
if (createGuideImplies3d({ prompt, intent })) {
|
|
1965
2054
|
const eligible3d = guideCandidatesWithinBudget({
|
|
1966
2055
|
candidates: models.filter(
|
|
@@ -2068,6 +2157,221 @@ function guideBudgetUsdForModel(model) {
|
|
|
2068
2157
|
);
|
|
2069
2158
|
}
|
|
2070
2159
|
|
|
2160
|
+
function createGuideDefaultModelParameters(input) {
|
|
2161
|
+
const modelParameters = { ...(input.modelParameters ?? {}) };
|
|
2162
|
+
const defaultsApplied = [];
|
|
2163
|
+
|
|
2164
|
+
if (
|
|
2165
|
+
input.model?.id === "xai.grok-imagine-image-quality" &&
|
|
2166
|
+
modelParameters.resolution === undefined
|
|
2167
|
+
) {
|
|
2168
|
+
const twoKEstimate = createGuideProviderCostEstimateForModel(
|
|
2169
|
+
input.model,
|
|
2170
|
+
{ resolution: "2k" },
|
|
2171
|
+
{ aspectRatio: input.aspectRatio },
|
|
2172
|
+
).estimated_provider_cost_usd;
|
|
2173
|
+
const twoKAllowedByBudget =
|
|
2174
|
+
input.maxEstimatedUsdPerImage === null ||
|
|
2175
|
+
twoKEstimate === null ||
|
|
2176
|
+
twoKEstimate <= input.maxEstimatedUsdPerImage;
|
|
2177
|
+
const intentClass = createGuideIntentClass(input.intent);
|
|
2178
|
+
const resolution =
|
|
2179
|
+
intentClass !== "budget_draft" && twoKAllowedByBudget ? "2k" : "1k";
|
|
2180
|
+
modelParameters.resolution = resolution;
|
|
2181
|
+
defaultsApplied.push(`resolution=${resolution}`);
|
|
2182
|
+
}
|
|
2183
|
+
|
|
2184
|
+
if (
|
|
2185
|
+
input.model?.id === "fal.flux-dev" &&
|
|
2186
|
+
modelParameters.image_size === undefined
|
|
2187
|
+
) {
|
|
2188
|
+
const imageSize = falDefaultImageSize(input.aspectRatio);
|
|
2189
|
+
if (imageSize !== null) {
|
|
2190
|
+
modelParameters.image_size = imageSize;
|
|
2191
|
+
defaultsApplied.push(`image_size=${imageSize}`);
|
|
2192
|
+
}
|
|
2193
|
+
}
|
|
2194
|
+
|
|
2195
|
+
if (
|
|
2196
|
+
input.model?.id === "openai.gpt-image-2" &&
|
|
2197
|
+
modelParameters.quality === undefined
|
|
2198
|
+
) {
|
|
2199
|
+
const mediumEstimate = createGuideProviderCostEstimateForModel(
|
|
2200
|
+
input.model,
|
|
2201
|
+
{ ...modelParameters, quality: "medium" },
|
|
2202
|
+
{ aspectRatio: input.aspectRatio },
|
|
2203
|
+
).estimated_provider_cost_usd;
|
|
2204
|
+
const mediumAllowedByBudget =
|
|
2205
|
+
input.maxEstimatedUsdPerImage === null ||
|
|
2206
|
+
mediumEstimate === null ||
|
|
2207
|
+
mediumEstimate <= input.maxEstimatedUsdPerImage;
|
|
2208
|
+
if (mediumAllowedByBudget) {
|
|
2209
|
+
modelParameters.quality = "medium";
|
|
2210
|
+
defaultsApplied.push("quality=medium");
|
|
2211
|
+
}
|
|
2212
|
+
}
|
|
2213
|
+
|
|
2214
|
+
return { modelParameters, defaultsApplied };
|
|
2215
|
+
}
|
|
2216
|
+
|
|
2217
|
+
function createGuidePricingForModel(model, modelParameters, context = {}) {
|
|
2218
|
+
const estimate = createGuideProviderCostEstimateForModel(
|
|
2219
|
+
model,
|
|
2220
|
+
modelParameters,
|
|
2221
|
+
context,
|
|
2222
|
+
);
|
|
2223
|
+
if (estimate.estimated_provider_cost_usd === null) {
|
|
2224
|
+
return createGuideModelCreditPricing(model);
|
|
2225
|
+
}
|
|
2226
|
+
return createGuideCreditPricingForProviderCost({
|
|
2227
|
+
providerCostUsd: estimate.estimated_provider_cost_usd,
|
|
2228
|
+
pricingConfidence: estimate.pricing_confidence,
|
|
2229
|
+
pricingSource: estimate.pricing_source,
|
|
2230
|
+
});
|
|
2231
|
+
}
|
|
2232
|
+
|
|
2233
|
+
function createGuideCanPriceModelParameters(model) {
|
|
2234
|
+
return String(model?.id ?? "").startsWith("xai.grok-imagine-image");
|
|
2235
|
+
}
|
|
2236
|
+
|
|
2237
|
+
function createGuideProviderCostEstimateForModel(
|
|
2238
|
+
model,
|
|
2239
|
+
modelParameters = {},
|
|
2240
|
+
context = {},
|
|
2241
|
+
) {
|
|
2242
|
+
if (String(model?.id ?? "").startsWith("xai.grok-imagine-image")) {
|
|
2243
|
+
return createGuideXaiImageCostEstimate(model, modelParameters, context);
|
|
2244
|
+
}
|
|
2245
|
+
return {
|
|
2246
|
+
estimated_provider_cost_usd:
|
|
2247
|
+
typeof model?.economics?.estimated_usd_per_image === "number"
|
|
2248
|
+
? model.economics.estimated_usd_per_image
|
|
2249
|
+
: (createGuideModelCreditPricing(model)?.estimated_provider_cost_usd ??
|
|
2250
|
+
null),
|
|
2251
|
+
pricing_source: "model_registry",
|
|
2252
|
+
pricing_confidence: "known",
|
|
2253
|
+
};
|
|
2254
|
+
}
|
|
2255
|
+
|
|
2256
|
+
function createGuideXaiImageCostEstimate(model, modelParameters, context) {
|
|
2257
|
+
const modelId = String(model?.id ?? "");
|
|
2258
|
+
const quality = modelId.includes("-quality");
|
|
2259
|
+
const edit = modelId.endsWith("-edit");
|
|
2260
|
+
const resolution = modelParameters?.resolution === "2k" ? "2k" : "1k";
|
|
2261
|
+
const outputImageCount =
|
|
2262
|
+
Number.isInteger(context?.outputCount) && context.outputCount > 0
|
|
2263
|
+
? context.outputCount
|
|
2264
|
+
: 1;
|
|
2265
|
+
const referenceAssetCount =
|
|
2266
|
+
Number.isInteger(context?.referenceAssetCount) &&
|
|
2267
|
+
context.referenceAssetCount > 0
|
|
2268
|
+
? context.referenceAssetCount
|
|
2269
|
+
: 0;
|
|
2270
|
+
const sourceImageCount = edit ? 1 + referenceAssetCount : 0;
|
|
2271
|
+
const inputUsdPerImage = quality ? 0.01 : 0.002;
|
|
2272
|
+
const outputUsdPerImage =
|
|
2273
|
+
quality && resolution === "2k" ? 0.07 : quality ? 0.05 : 0.02;
|
|
2274
|
+
const defaultResolution =
|
|
2275
|
+
modelParameters?.resolution === undefined ||
|
|
2276
|
+
modelParameters?.resolution === null ||
|
|
2277
|
+
modelParameters?.resolution === "1k";
|
|
2278
|
+
const defaultShape =
|
|
2279
|
+
defaultResolution &&
|
|
2280
|
+
outputImageCount === 1 &&
|
|
2281
|
+
sourceImageCount === (edit ? 1 : 0);
|
|
2282
|
+
return {
|
|
2283
|
+
estimated_provider_cost_usd: roundUsdMicro(
|
|
2284
|
+
inputUsdPerImage * sourceImageCount +
|
|
2285
|
+
outputUsdPerImage * outputImageCount,
|
|
2286
|
+
),
|
|
2287
|
+
pricing_source: defaultShape ? "model_registry" : "model_parameters",
|
|
2288
|
+
pricing_confidence: "known",
|
|
2289
|
+
};
|
|
2290
|
+
}
|
|
2291
|
+
|
|
2292
|
+
function createGuideCreditPricingForProviderCost(input) {
|
|
2293
|
+
const providerCostUsd = roundUsdMicro(input.providerCostUsd);
|
|
2294
|
+
const creditsRequired = Math.max(
|
|
2295
|
+
1,
|
|
2296
|
+
Math.ceil(
|
|
2297
|
+
roundUsdMicro(
|
|
2298
|
+
providerCostUsd / (1 - TARGET_GROSS_MARGIN) / CREDIT_UNIT_USD,
|
|
2299
|
+
),
|
|
2300
|
+
),
|
|
2301
|
+
);
|
|
2302
|
+
const estimatedRevenueUsd = roundUsd(creditsRequired * CREDIT_UNIT_USD);
|
|
2303
|
+
const estimatedPaymentFeeUsd = roundUsdMicro(
|
|
2304
|
+
estimatedRevenueUsd * PAYMENT_BACKED_CREDIT_PAYMENT_FEE_RATE,
|
|
2305
|
+
);
|
|
2306
|
+
const estimatedNetRevenueUsd = roundUsdMicro(
|
|
2307
|
+
estimatedRevenueUsd - estimatedPaymentFeeUsd,
|
|
2308
|
+
);
|
|
2309
|
+
const estimatedGrossMargin =
|
|
2310
|
+
estimatedRevenueUsd > 0
|
|
2311
|
+
? roundRatio(
|
|
2312
|
+
(estimatedRevenueUsd - providerCostUsd) / estimatedRevenueUsd,
|
|
2313
|
+
)
|
|
2314
|
+
: null;
|
|
2315
|
+
const estimatedFeeAdjustedMargin =
|
|
2316
|
+
estimatedRevenueUsd > 0
|
|
2317
|
+
? roundRatio(
|
|
2318
|
+
(estimatedNetRevenueUsd - providerCostUsd) / estimatedRevenueUsd,
|
|
2319
|
+
)
|
|
2320
|
+
: null;
|
|
2321
|
+
const selfFundBlockReason =
|
|
2322
|
+
estimatedNetRevenueUsd + 1e-9 < providerCostUsd
|
|
2323
|
+
? "payment_fee_margin_negative"
|
|
2324
|
+
: null;
|
|
2325
|
+
return {
|
|
2326
|
+
credits_required: creditsRequired,
|
|
2327
|
+
credit_unit_usd: CREDIT_UNIT_USD,
|
|
2328
|
+
estimated_provider_cost_usd: providerCostUsd,
|
|
2329
|
+
fallback_provider_cost_usd: null,
|
|
2330
|
+
estimated_revenue_usd: estimatedRevenueUsd,
|
|
2331
|
+
estimated_gross_margin: estimatedGrossMargin,
|
|
2332
|
+
payment_fee_rate: PAYMENT_BACKED_CREDIT_PAYMENT_FEE_RATE,
|
|
2333
|
+
payment_fee_model: PAYMENT_BACKED_CREDIT_PAYMENT_FEE_MODEL,
|
|
2334
|
+
estimated_payment_fee_usd: estimatedPaymentFeeUsd,
|
|
2335
|
+
estimated_net_revenue_usd: estimatedNetRevenueUsd,
|
|
2336
|
+
estimated_fee_adjusted_margin: estimatedFeeAdjustedMargin,
|
|
2337
|
+
self_fundable: selfFundBlockReason === null,
|
|
2338
|
+
self_fund_block_reason: selfFundBlockReason,
|
|
2339
|
+
target_gross_margin: TARGET_GROSS_MARGIN,
|
|
2340
|
+
pricing_confidence: input.pricingConfidence,
|
|
2341
|
+
pricing_source: input.pricingSource,
|
|
2342
|
+
margin_model: "provider_cost_plus_margin",
|
|
2343
|
+
};
|
|
2344
|
+
}
|
|
2345
|
+
|
|
2346
|
+
function falDefaultImageSize(aspectRatio) {
|
|
2347
|
+
switch (aspectRatio) {
|
|
2348
|
+
case "1:1":
|
|
2349
|
+
return "square_hd";
|
|
2350
|
+
case "4:3":
|
|
2351
|
+
return "landscape_4_3";
|
|
2352
|
+
case "3:4":
|
|
2353
|
+
return "portrait_4_3";
|
|
2354
|
+
case "16:9":
|
|
2355
|
+
return "landscape_16_9";
|
|
2356
|
+
case "9:16":
|
|
2357
|
+
return "portrait_16_9";
|
|
2358
|
+
default:
|
|
2359
|
+
return null;
|
|
2360
|
+
}
|
|
2361
|
+
}
|
|
2362
|
+
|
|
2363
|
+
function roundUsd(value) {
|
|
2364
|
+
return Math.round(value * 100) / 100;
|
|
2365
|
+
}
|
|
2366
|
+
|
|
2367
|
+
function roundRatio(value) {
|
|
2368
|
+
return Math.round(value * 1000) / 1000;
|
|
2369
|
+
}
|
|
2370
|
+
|
|
2371
|
+
function roundUsdMicro(value) {
|
|
2372
|
+
return Math.round(value * 1_000_000) / 1_000_000;
|
|
2373
|
+
}
|
|
2374
|
+
|
|
2071
2375
|
function guideModelExecutionStatus(model) {
|
|
2072
2376
|
if (
|
|
2073
2377
|
isRecord(model?.execution) &&
|
|
@@ -2155,7 +2459,12 @@ function createGuideSelectedModelRequiresInputImage(model) {
|
|
|
2155
2459
|
);
|
|
2156
2460
|
}
|
|
2157
2461
|
|
|
2158
|
-
function createGuideSelectionReason(
|
|
2462
|
+
function createGuideSelectionReason(
|
|
2463
|
+
model,
|
|
2464
|
+
prompt,
|
|
2465
|
+
intent,
|
|
2466
|
+
operation = "create",
|
|
2467
|
+
) {
|
|
2159
2468
|
if (
|
|
2160
2469
|
createGuideSelectedModelRequiresInputImage(model) &&
|
|
2161
2470
|
createGuideImplies3d({ prompt, intent })
|
|
@@ -2183,7 +2492,9 @@ function createGuideSelectionReason(model, prompt, intent) {
|
|
|
2183
2492
|
? "guide selected a draft/budget create model with high-definition defaults"
|
|
2184
2493
|
: "guide selected the strongest currently available quality-first create model for this intent";
|
|
2185
2494
|
}
|
|
2186
|
-
return
|
|
2495
|
+
return operation === "edit"
|
|
2496
|
+
? "guide selected the first available executable input-image edit model"
|
|
2497
|
+
: "guide selected the first available executable create model";
|
|
2187
2498
|
}
|
|
2188
2499
|
|
|
2189
2500
|
function createGuidePaymentSummary(data, commandPrefix) {
|
|
@@ -2398,7 +2709,7 @@ function renderCopyRunnablePaymentCommand(commandPrefix, command) {
|
|
|
2398
2709
|
}
|
|
2399
2710
|
|
|
2400
2711
|
function createGuideStage(input) {
|
|
2401
|
-
if (input.
|
|
2712
|
+
if (input.promptRequired) {
|
|
2402
2713
|
return "prompt_required";
|
|
2403
2714
|
}
|
|
2404
2715
|
if (!input.health.envelope.ok || !input.models.envelope.ok) {
|
|
@@ -2805,6 +3116,64 @@ function createGuideNoSpendEvaluation(stage, input) {
|
|
|
2805
3116
|
};
|
|
2806
3117
|
}
|
|
2807
3118
|
|
|
3119
|
+
function createGuideRecovery(stage, input) {
|
|
3120
|
+
let noSpendCommand = null;
|
|
3121
|
+
let noSpendCommandField = null;
|
|
3122
|
+
if (stage === "ready_to_create" && input.noSpendNextCommand !== null) {
|
|
3123
|
+
noSpendCommand = input.noSpendNextCommand;
|
|
3124
|
+
noSpendCommandField = "recommended_no_spend_command";
|
|
3125
|
+
} else if (stage === "quota_required") {
|
|
3126
|
+
noSpendCommand = input.escapeHatches.quota;
|
|
3127
|
+
noSpendCommandField = "escape_hatches.quota";
|
|
3128
|
+
} else if (
|
|
3129
|
+
stage === "no_executable_model" ||
|
|
3130
|
+
stage === "service_unreachable"
|
|
3131
|
+
) {
|
|
3132
|
+
noSpendCommand = input.nextCommand;
|
|
3133
|
+
noSpendCommandField = "next_command";
|
|
3134
|
+
} else if (stage === "auth_required" || stage === "prompt_required") {
|
|
3135
|
+
noSpendCommand = input.nextCommand;
|
|
3136
|
+
noSpendCommandField = "next_command";
|
|
3137
|
+
}
|
|
3138
|
+
const noSpendMissingInputs =
|
|
3139
|
+
noSpendCommand === null
|
|
3140
|
+
? []
|
|
3141
|
+
: createGuideNextCommandMissingInputs(noSpendCommand);
|
|
3142
|
+
const liveCreateCommandField =
|
|
3143
|
+
stage === "ready_to_create" ? "next_command" : null;
|
|
3144
|
+
const livePaymentCommandField =
|
|
3145
|
+
stage === "quota_required" && input.selfFundNextCommand !== null
|
|
3146
|
+
? "self_fund_next_command"
|
|
3147
|
+
: null;
|
|
3148
|
+
const doubleSpendGuardRequired =
|
|
3149
|
+
liveCreateCommandField !== null || livePaymentCommandField !== null;
|
|
3150
|
+
return {
|
|
3151
|
+
schema: "image-skill.guide-recovery.v1",
|
|
3152
|
+
stage,
|
|
3153
|
+
precondition_code: input.blocker?.code ?? null,
|
|
3154
|
+
precondition_message: input.blocker?.message ?? null,
|
|
3155
|
+
no_spend_command: noSpendCommand,
|
|
3156
|
+
no_spend_command_field: noSpendCommandField,
|
|
3157
|
+
no_spend_command_copy_runnable:
|
|
3158
|
+
noSpendCommand === null ? null : noSpendMissingInputs.length === 0,
|
|
3159
|
+
no_spend_command_missing_inputs: noSpendMissingInputs,
|
|
3160
|
+
after_success_command: input.afterNext,
|
|
3161
|
+
after_success_command_field: input.afterNext === null ? null : "after_next",
|
|
3162
|
+
live_create_command_field: liveCreateCommandField,
|
|
3163
|
+
live_payment_command_field: livePaymentCommandField,
|
|
3164
|
+
double_spend_guard: {
|
|
3165
|
+
required: doubleSpendGuardRequired,
|
|
3166
|
+
safe_rerun_command_field: noSpendCommandField,
|
|
3167
|
+
warning:
|
|
3168
|
+
liveCreateCommandField !== null
|
|
3169
|
+
? "Do not blindly rerun data.next_command after a partial or unknown create/edit failure; use data.guide_recovery.no_spend_command, jobs/activity, or error.recovery before any live retry."
|
|
3170
|
+
: livePaymentCommandField !== null
|
|
3171
|
+
? "Do not blindly rerun live payment commands with fresh identifiers after a partial or unknown payment failure; use data.guide_recovery.no_spend_command and payment status recovery before any new buy."
|
|
3172
|
+
: "No live payment or live media command is exposed for this stage; follow the no-spend command and rerun the guide after the precondition is satisfied.",
|
|
3173
|
+
},
|
|
3174
|
+
};
|
|
3175
|
+
}
|
|
3176
|
+
|
|
2808
3177
|
function createGuideWarning(stage, input) {
|
|
2809
3178
|
const effect = input.nextCommandEffect;
|
|
2810
3179
|
const base = {
|
|
@@ -2925,10 +3294,13 @@ function escapeRegExp(value) {
|
|
|
2925
3294
|
function createGuideNextCommand(stage, input) {
|
|
2926
3295
|
if (stage === "prompt_required") {
|
|
2927
3296
|
return renderGuideCommand("PROMPT", input.apiBaseUrl, input.commandPrefix, {
|
|
3297
|
+
operation: input.guideOperation,
|
|
3298
|
+
inputReference: input.inputReference,
|
|
2928
3299
|
modelId: input.requestedModelId,
|
|
2929
3300
|
providerId: input.requestedProviderId,
|
|
2930
3301
|
intent: input.requestedIntentFlag,
|
|
2931
3302
|
maxEstimatedUsdPerImage: input.maxEstimatedUsdPerImage,
|
|
3303
|
+
modelParametersJson: input.modelParametersJson,
|
|
2932
3304
|
});
|
|
2933
3305
|
}
|
|
2934
3306
|
if (stage === "no_executable_model" || stage === "service_unreachable") {
|
|
@@ -2950,7 +3322,9 @@ function createGuideNextCommand(stage, input) {
|
|
|
2950
3322
|
return renderInputImageGuideCommand({
|
|
2951
3323
|
modelId: input.selected.id,
|
|
2952
3324
|
prompt: input.prompt,
|
|
3325
|
+
inputReference: input.inputReference,
|
|
2953
3326
|
budgetGuard: input.budgetGuard,
|
|
3327
|
+
modelParametersJson: input.modelParametersJson,
|
|
2954
3328
|
dryRun: false,
|
|
2955
3329
|
idempotencyKey: `edit-guide-${Date.now()}-${randomBytes(4).toString("hex")}`,
|
|
2956
3330
|
apiBaseUrl: input.apiBaseUrl,
|
|
@@ -2964,6 +3338,7 @@ function createGuideNextCommand(stage, input) {
|
|
|
2964
3338
|
intent: input.requestedIntent,
|
|
2965
3339
|
budgetGuard: input.budgetGuard,
|
|
2966
3340
|
aspectRatio: input.aspectRatio,
|
|
3341
|
+
modelParametersJson: input.modelParametersJson,
|
|
2967
3342
|
dryRun: false,
|
|
2968
3343
|
// Retry-safe by default (#1228): bake a stable idempotency key into the
|
|
2969
3344
|
// advertised create command so an agent that copies it and retries after a
|
|
@@ -2993,16 +3368,22 @@ function createGuideEscapeHatches(input) {
|
|
|
2993
3368
|
"usage quota --json",
|
|
2994
3369
|
),
|
|
2995
3370
|
dry_run:
|
|
2996
|
-
input.selected === null ||
|
|
3371
|
+
input.selected === null ||
|
|
3372
|
+
(input.prompt.length === 0 &&
|
|
3373
|
+
!PROMPTLESS_EDIT_MODEL_IDS.has(input.selected.id))
|
|
2997
3374
|
? renderGuidePrefixedCommand(
|
|
2998
3375
|
input.commandPrefix,
|
|
2999
|
-
|
|
3376
|
+
input.guideOperation === "edit"
|
|
3377
|
+
? "edit --dry-run --input image_... --prompt PROMPT --json"
|
|
3378
|
+
: "create --dry-run --prompt PROMPT --json",
|
|
3000
3379
|
)
|
|
3001
3380
|
: createGuideSelectedModelRequiresInputImage(input.selected)
|
|
3002
3381
|
? renderInputImageGuideCommand({
|
|
3003
3382
|
modelId: input.selected.id,
|
|
3004
3383
|
prompt: input.prompt,
|
|
3384
|
+
inputReference: input.inputReference,
|
|
3005
3385
|
budgetGuard: input.budgetGuard,
|
|
3386
|
+
modelParametersJson: input.modelParametersJson,
|
|
3006
3387
|
dryRun: true,
|
|
3007
3388
|
apiBaseUrl: input.apiBaseUrl,
|
|
3008
3389
|
commandPrefix: input.commandPrefix,
|
|
@@ -3014,6 +3395,7 @@ function createGuideEscapeHatches(input) {
|
|
|
3014
3395
|
intent: input.requestedIntent,
|
|
3015
3396
|
budgetGuard: input.budgetGuard,
|
|
3016
3397
|
aspectRatio: input.aspectRatio,
|
|
3398
|
+
modelParametersJson: input.modelParametersJson,
|
|
3017
3399
|
dryRun: true,
|
|
3018
3400
|
apiBaseUrl: input.apiBaseUrl,
|
|
3019
3401
|
commandPrefix: input.commandPrefix,
|
|
@@ -3027,10 +3409,16 @@ function renderGuideCommand(
|
|
|
3027
3409
|
commandPrefix = "image-skill",
|
|
3028
3410
|
options = {},
|
|
3029
3411
|
) {
|
|
3412
|
+
const operation = options.operation ?? "create";
|
|
3030
3413
|
return [
|
|
3031
3414
|
commandPrefix,
|
|
3032
|
-
|
|
3415
|
+
`${operation} --guide --prompt`,
|
|
3033
3416
|
shellQuote(prompt),
|
|
3417
|
+
...(operation === "edit" &&
|
|
3418
|
+
typeof options.inputReference === "string" &&
|
|
3419
|
+
options.inputReference.trim().length > 0
|
|
3420
|
+
? ["--input", shellQuote(options.inputReference.trim())]
|
|
3421
|
+
: []),
|
|
3034
3422
|
...(options.modelId === null ||
|
|
3035
3423
|
options.modelId === undefined ||
|
|
3036
3424
|
options.modelId === ""
|
|
@@ -3053,6 +3441,10 @@ function renderGuideCommand(
|
|
|
3053
3441
|
"--max-estimated-usd-per-image",
|
|
3054
3442
|
shellQuote(formatUsd(options.maxEstimatedUsdPerImage)),
|
|
3055
3443
|
]),
|
|
3444
|
+
...(options.modelParametersJson === null ||
|
|
3445
|
+
options.modelParametersJson === undefined
|
|
3446
|
+
? []
|
|
3447
|
+
: ["--model-parameters-json", shellQuote(options.modelParametersJson)]),
|
|
3056
3448
|
...(apiBaseUrl === null ? [] : ["--api-base-url", shellQuote(apiBaseUrl)]),
|
|
3057
3449
|
"--json",
|
|
3058
3450
|
].join(" ");
|
|
@@ -3107,12 +3499,18 @@ function renderInputImageGuideCommand(input) {
|
|
|
3107
3499
|
"edit",
|
|
3108
3500
|
...(input.dryRun ? ["--dry-run"] : []),
|
|
3109
3501
|
"--input",
|
|
3110
|
-
|
|
3502
|
+
input.inputReference?.trim()
|
|
3503
|
+
? shellQuote(input.inputReference.trim())
|
|
3504
|
+
: "image_...",
|
|
3111
3505
|
"--model",
|
|
3112
3506
|
shellQuote(input.modelId),
|
|
3113
3507
|
...(promptless ? [] : ["--prompt", shellQuote(input.prompt)]),
|
|
3114
3508
|
"--max-estimated-usd-per-image",
|
|
3115
3509
|
shellQuote(formatUsd(input.budgetGuard)),
|
|
3510
|
+
...(input.modelParametersJson === null ||
|
|
3511
|
+
input.modelParametersJson === undefined
|
|
3512
|
+
? []
|
|
3513
|
+
: ["--model-parameters-json", shellQuote(input.modelParametersJson)]),
|
|
3116
3514
|
...(input.idempotencyKey === undefined || input.idempotencyKey === null
|
|
3117
3515
|
? []
|
|
3118
3516
|
: ["--idempotency-key", shellQuote(input.idempotencyKey)]),
|
|
@@ -3142,6 +3540,10 @@ function renderCreateCommand(input) {
|
|
|
3142
3540
|
: ["--aspect-ratio", shellQuote(input.aspectRatio)]),
|
|
3143
3541
|
"--max-estimated-usd-per-image",
|
|
3144
3542
|
shellQuote(formatUsd(input.budgetGuard)),
|
|
3543
|
+
...(input.modelParametersJson === null ||
|
|
3544
|
+
input.modelParametersJson === undefined
|
|
3545
|
+
? []
|
|
3546
|
+
: ["--model-parameters-json", shellQuote(input.modelParametersJson)]),
|
|
3145
3547
|
...(input.idempotencyKey === undefined || input.idempotencyKey === null
|
|
3146
3548
|
? []
|
|
3147
3549
|
: ["--idempotency-key", shellQuote(input.idempotencyKey)]),
|
|
@@ -3377,6 +3779,12 @@ async function edit(argv) {
|
|
|
3377
3779
|
const args = parseArgs(argv);
|
|
3378
3780
|
const input = flagString(args, "input") ?? args.positionals[0];
|
|
3379
3781
|
const modelId = flagString(args, "model");
|
|
3782
|
+
if (flagBool(args, "guide")) {
|
|
3783
|
+
return createGuide(args, {
|
|
3784
|
+
guideOperation: "edit",
|
|
3785
|
+
inputReference: input,
|
|
3786
|
+
});
|
|
3787
|
+
}
|
|
3380
3788
|
if (input === undefined) {
|
|
3381
3789
|
return invalid(
|
|
3382
3790
|
"image-skill edit",
|