@hraness/slopcamera 3.5.0 → 3.6.0

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.
@@ -0,0 +1,217 @@
1
+ /**
2
+ * Provider list prices for the image models Slopcamera can bill, and the
3
+ * cost of one Vercel AI Gateway image call derived from them.
4
+ *
5
+ * The AI Gateway charges the provider's list price with no markup
6
+ * (https://vercel.com/docs/ai-gateway/pricing, checked 2026-09-26), so the
7
+ * OpenAI and Recraft list prices below are what one call costs. Every price
8
+ * is integer micro-USD.
9
+ *
10
+ * A request never sets size or quality, so OpenAI chooses them ("auto"). The
11
+ * worst case is therefore the highest quality at the largest size, plus the
12
+ * prompt's text input tokens. Slopcamera never sends reference or edit
13
+ * images, so every input token is a text token.
14
+ */
15
+
16
+ export type ProviderCostBasis = "reported" | "contractual" | "estimated" | "unknown"
17
+
18
+ /** One provider cost line, in the shape Hraness Credits accepts. */
19
+ export interface SlopcameraProviderCost {
20
+ readonly provider: string
21
+ readonly operation: string
22
+ readonly microUsd: number
23
+ readonly basis: ProviderCostBasis
24
+ }
25
+
26
+ /** Token counts a Gateway image call returned, as the AI SDK reports them. */
27
+ export interface SlopcameraImageUsage {
28
+ readonly inputTokens?: number | undefined
29
+ readonly outputTokens?: number | undefined
30
+ }
31
+
32
+ interface TokenPricedImageModel {
33
+ readonly kind: "tokens"
34
+ /** Text input tokens, micro-USD per million. */
35
+ readonly textInputPerMillion: number
36
+ /**
37
+ * Output tokens, micro-USD per million. This is the image output rate,
38
+ * which is the highest output rate the model has, so it also bounds any
39
+ * text output tokens.
40
+ */
41
+ readonly outputPerMillion: number
42
+ /** OpenAI's published price for one high-quality 1024x1536 image. */
43
+ readonly worstImage: number
44
+ readonly source: string
45
+ }
46
+
47
+ interface ImagePricedModel {
48
+ readonly kind: "image"
49
+ /** Flat price for one image in the style Slopcamera requests (none). */
50
+ readonly perImage: number
51
+ readonly source: string
52
+ }
53
+
54
+ export type SlopcameraImageModelPrice = TokenPricedImageModel | ImagePricedModel
55
+
56
+ export const slopcameraProviderPricesCheckedAt = "2026-09-26"
57
+
58
+ /**
59
+ * Cited list prices. A model without an entry here cannot be billed: the
60
+ * hosted service refuses it before any hold.
61
+ */
62
+ export const slopcameraImageModelPrices: Readonly<
63
+ Record<string, SlopcameraImageModelPrice>
64
+ > = Object.freeze({
65
+ "openai/gpt-image-1": Object.freeze({
66
+ kind: "tokens",
67
+ textInputPerMillion: 5_000_000,
68
+ outputPerMillion: 40_000_000,
69
+ worstImage: 250_000,
70
+ source: "https://developers.openai.com/api/docs/models/gpt-image-1",
71
+ }),
72
+ "openai/gpt-image-1-mini": Object.freeze({
73
+ kind: "tokens",
74
+ textInputPerMillion: 2_000_000,
75
+ outputPerMillion: 8_000_000,
76
+ worstImage: 52_000,
77
+ source: "https://developers.openai.com/api/docs/models/gpt-image-1-mini",
78
+ }),
79
+ "openai/gpt-image-1.5": Object.freeze({
80
+ kind: "tokens",
81
+ textInputPerMillion: 5_000_000,
82
+ outputPerMillion: 32_000_000,
83
+ worstImage: 200_000,
84
+ source: "https://developers.openai.com/api/docs/models/gpt-image-1.5",
85
+ }),
86
+ "recraft/recraft-v4.1-utility": Object.freeze({
87
+ kind: "image",
88
+ perImage: 35_000,
89
+ source: "https://vercel.com/ai-gateway/models/recraft-v4.1-utility",
90
+ }),
91
+ })
92
+
93
+ /**
94
+ * Tokens allowed on top of the prompt's UTF-8 byte count when no usage came
95
+ * back. A byte-level BPE token covers at least one byte, so the byte count
96
+ * bounds the prompt's own tokens; the allowance covers request framing.
97
+ */
98
+ export const slopcameraPromptTokenAllowance = 64
99
+
100
+ export const slopcameraCostProvider = "vercel-ai-gateway"
101
+
102
+ export function slopcameraImageModelPrice(
103
+ model: string,
104
+ ): SlopcameraImageModelPrice | undefined {
105
+ return Object.hasOwn(slopcameraImageModelPrices, model)
106
+ ? slopcameraImageModelPrices[model]
107
+ : undefined
108
+ }
109
+
110
+ function tokenCost(tokens: number, perMillion: number): number {
111
+ // Round up so a partial micro-dollar is never dropped.
112
+ return Math.ceil((tokens * perMillion) / 1_000_000)
113
+ }
114
+
115
+ function promptBytes(prompt: string): number {
116
+ return Buffer.byteLength(prompt, "utf8")
117
+ }
118
+
119
+ function validTokenCount(value: unknown): value is number {
120
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 0
121
+ }
122
+
123
+ /**
124
+ * The most one image call for this model and prompt can cost: highest
125
+ * quality at the largest size, and every prompt byte counted as a token.
126
+ */
127
+ export function worstCaseImageCostMicroUsd(
128
+ model: string,
129
+ prompt: string,
130
+ ): number | undefined {
131
+ const price = slopcameraImageModelPrice(model)
132
+ if (price === undefined) return undefined
133
+ if (price.kind === "image") return price.perImage
134
+ return (
135
+ price.worstImage +
136
+ tokenCost(
137
+ promptBytes(prompt) + slopcameraPromptTokenAllowance,
138
+ price.textInputPerMillion,
139
+ )
140
+ )
141
+ }
142
+
143
+ function estimatedLines(
144
+ model: string,
145
+ prompt: string,
146
+ price: SlopcameraImageModelPrice,
147
+ ): SlopcameraProviderCost[] {
148
+ if (price.kind === "image") {
149
+ return [{
150
+ provider: slopcameraCostProvider,
151
+ operation: `${model} image`,
152
+ microUsd: price.perImage,
153
+ basis: "estimated",
154
+ }]
155
+ }
156
+ return [
157
+ {
158
+ provider: slopcameraCostProvider,
159
+ operation: `${model} image output`,
160
+ microUsd: price.worstImage,
161
+ basis: "estimated",
162
+ },
163
+ {
164
+ provider: slopcameraCostProvider,
165
+ operation: `${model} text input`,
166
+ microUsd: tokenCost(
167
+ promptBytes(prompt) + slopcameraPromptTokenAllowance,
168
+ price.textInputPerMillion,
169
+ ),
170
+ basis: "estimated",
171
+ },
172
+ ]
173
+ }
174
+
175
+ /**
176
+ * Cost lines for one image call that reached the provider. Returned usage
177
+ * prices the call at the official per-token rates (basis "reported");
178
+ * without usage, the worst case stands in (basis "estimated").
179
+ */
180
+ export function imageCallCosts(
181
+ model: string,
182
+ prompt: string,
183
+ usage: SlopcameraImageUsage | undefined,
184
+ ): SlopcameraProviderCost[] {
185
+ const price = slopcameraImageModelPrice(model)
186
+ if (price === undefined) {
187
+ return [{
188
+ provider: slopcameraCostProvider,
189
+ operation: `${model} image`,
190
+ microUsd: 0,
191
+ basis: "unknown",
192
+ }]
193
+ }
194
+ if (
195
+ price.kind === "tokens" &&
196
+ usage !== undefined &&
197
+ validTokenCount(usage.inputTokens) &&
198
+ validTokenCount(usage.outputTokens) &&
199
+ usage.outputTokens > 0
200
+ ) {
201
+ return [
202
+ {
203
+ provider: slopcameraCostProvider,
204
+ operation: `${model} image output`,
205
+ microUsd: tokenCost(usage.outputTokens, price.outputPerMillion),
206
+ basis: "reported",
207
+ },
208
+ {
209
+ provider: slopcameraCostProvider,
210
+ operation: `${model} text input`,
211
+ microUsd: tokenCost(usage.inputTokens, price.textInputPerMillion),
212
+ basis: "reported",
213
+ },
214
+ ]
215
+ }
216
+ return estimatedLines(model, prompt, price)
217
+ }
package/src/support.ts CHANGED
@@ -1,9 +1,15 @@
1
1
  import {
2
2
  maybeShowSupportInvitation,
3
3
  runSupportCommand,
4
+ supportAdvancedHelp,
5
+ supportHelpLine,
4
6
  type SupportCommandOptions,
5
7
  } from "@hraness/support-foundation/node"
6
8
 
9
+ /** The one support line for root help, and the agent verbs for `help advanced`. */
10
+ export const slopcameraSupportHelpLine = () => supportHelpLine({ command: ["slopcamera"] })
11
+ export const slopcameraSupportAdvancedHelp = () => supportAdvancedHelp({ command: ["slopcamera"] })
12
+
7
13
  export const supportProfile = {
8
14
  id: "slopcamera",
9
15
  name: "Slopcamera",
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const SLOPCAMERA_VERSION = "3.5.0" as const
1
+ export const SLOPCAMERA_VERSION = "3.6.0" as const
@@ -1,3 +0,0 @@
1
- // @bun
2
- import{__require}from"./index-80a36bc0.js";import{createHash,randomUUID}from"crypto";import{link,rm,writeFile}from"fs/promises";import{dirname,extname,resolve}from"path";class SlopcameraCloudError extends Error{code;constructor(code,message,options){super(`[${code}] ${message}`,options);this.name="SlopcameraCloudError";this.code=code}}var slopcameraGatewayApiBaseUrl="https://ai-gateway.vercel.sh/v4/ai";var slopcameraImageModels=Object.freeze(["openai/gpt-image-1.5","recraft/recraft-v4.1-utility"]);var slopcameraResponseMediaTypes=Object.freeze(["image/png","image/jpeg","image/webp"]);var slopcameraMaximumPromptBytes=32*1024;var slopcameraMaximumRawImageBytes=64*1024*1024;var defaultGenerationTimeoutMs=5*60000;var maximumGenerationTimeoutMs=30*60000;var defaultMaximumGatewayResponseBytes=96*1024*1024;function invalidArgument(message){throw new SlopcameraCloudError("INVALID_ARGUMENT",message)}function credentialValue(value){if(value.length<16||value.length>16*1024||value.trim()!==value||/[^\x21-\x7e]/u.test(value)){throw new SlopcameraCloudError("AUTHENTICATION_REQUIRED","The selected Vercel AI Gateway credential is invalid.")}return value}function environment(injected){return injected??process.env}function resolveSlopcameraGatewayCredential(injected){const values=environment(injected);if(values.AI_GATEWAY_API_KEY!==undefined){return{source:"AI_GATEWAY_API_KEY",token:credentialValue(values.AI_GATEWAY_API_KEY)}}if(values.VERCEL_OIDC_TOKEN!==undefined){return{source:"VERCEL_OIDC_TOKEN",token:credentialValue(values.VERCEL_OIDC_TOKEN)}}throw new SlopcameraCloudError("AUTHENTICATION_REQUIRED","Set AI_GATEWAY_API_KEY or run Slopcamera through `vercel env run -- \u2026` with VERCEL_OIDC_TOKEN available.")}function slopcameraGatewayCredentialStatus(injected){const values=environment(injected);if(values.AI_GATEWAY_API_KEY!==undefined){credentialValue(values.AI_GATEWAY_API_KEY);return{available:true,source:"AI_GATEWAY_API_KEY"}}if(values.VERCEL_OIDC_TOKEN!==undefined){credentialValue(values.VERCEL_OIDC_TOKEN);return{available:true,source:"VERCEL_OIDC_TOKEN"}}return{available:false,source:null}}function validateModel(value){if(typeof value!=="string"||value.length<3||value.length>256||!/^[a-z0-9][a-z0-9._-]*\/[a-z0-9][a-z0-9._:-]*$/iu.test(value)){invalidArgument("Model must be a bounded Vercel AI Gateway provider/model id.")}return value}function validatePrompt(value){if(typeof value!=="string"||value.trim().length===0||/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/u.test(value)||Buffer.byteLength(value,"utf8")>slopcameraMaximumPromptBytes){invalidArgument(`Prompt must be non-empty and no more than ${slopcameraMaximumPromptBytes} UTF-8 bytes.`)}return value}function validateTimeout(value){const timeout=value??defaultGenerationTimeoutMs;if(!Number.isSafeInteger(timeout)||timeout<1000||timeout>maximumGenerationTimeoutMs){invalidArgument(`timeoutMs must be an integer from 1000 through ${maximumGenerationTimeoutMs}.`)}return timeout}function isObject(value){return typeof value==="object"&&value!==null||typeof value==="function"}function parseFunction(value){if(typeof value!=="function"){throw new SlopcameraCloudError("GENERATION_FAILED","The Vercel AI Gateway runtime is unavailable.")}return value}function disableAiSdkWarningLogging(){globalThis.AI_SDK_LOG_WARNINGS=false}function assertGenerationActive(signal){if(signal.aborted){throw new SlopcameraCloudError("GENERATION_FAILED","Vercel AI Gateway image generation was cancelled or exceeded its deadline.")}}async function loadDefaultGatewayRuntime(){let aiModule;let gatewayModule;try{[aiModule,gatewayModule]=await Promise.all([import("ai-v7"),import("@ai-sdk/gateway-v4")])}catch{throw new SlopcameraCloudError("GENERATION_FAILED","The Vercel AI Gateway runtime is unavailable.")}if(!isObject(aiModule)||!isObject(gatewayModule)){throw new SlopcameraCloudError("GENERATION_FAILED","The Vercel AI Gateway runtime is unavailable.")}const generateImage=parseFunction(aiModule.generateImage);if(typeof gatewayModule.createGateway!=="function"){throw new SlopcameraCloudError("GENERATION_FAILED","The Vercel AI Gateway runtime is unavailable.")}const createGateway=gatewayModule.createGateway;return{createGateway:(settings)=>{const provider=createGateway(settings);if(!isObject(provider)||typeof provider.imageModel!=="function"){throw new SlopcameraCloudError("GENERATION_FAILED","The Vercel AI Gateway runtime is unavailable.")}const imageModel=provider.imageModel;return{imageModel:(modelId)=>imageModel.call(provider,modelId)}},generateImage}}function gatewayUrl(input){try{if(input instanceof Request)return new URL(input.url);if(input instanceof URL)return new URL(input.href);return new URL(input,slopcameraGatewayApiBaseUrl)}catch{throw new SlopcameraCloudError("GENERATION_FAILED","The Vercel AI Gateway request was rejected.")}}function canonicalGatewayInput(input,url){if(!(input instanceof Request))return url;const snapshot=new Request(input);const body=snapshot.method==="GET"||snapshot.method==="HEAD"?undefined:snapshot.body??undefined;const requestInit={headers:snapshot.headers,method:snapshot.method,signal:snapshot.signal,...body===undefined?{}:{body,duplex:"half"}};return new Request(url.href,requestInit)}function boundedResponse(response,maximumBytes){const declared=response.headers.get("content-length");if(declared!==null){const value=Number(declared);if(!Number.isSafeInteger(value)||value<0||value>maximumBytes){response.body?.cancel().catch(()=>{return});throw new SlopcameraCloudError("GENERATION_INVALID_RESPONSE","Vercel AI Gateway returned an invalid bounded response.")}}if(response.body===null)return response;const reader=response.body.getReader();let bytes=0;const body=new ReadableStream({cancel:async(reason)=>await reader.cancel(reason),pull:async(controller)=>{try{const next=await reader.read();if(next.done){reader.releaseLock();controller.close();return}bytes+=next.value.byteLength;if(bytes>maximumBytes){await reader.cancel().catch(()=>{return});controller.error(new SlopcameraCloudError("GENERATION_INVALID_RESPONSE","Vercel AI Gateway returned an invalid bounded response."));return}controller.enqueue(next.value)}catch{controller.error(new SlopcameraCloudError("GENERATION_INVALID_RESPONSE","Vercel AI Gateway returned an invalid bounded response."))}}});return new Response(body,{headers:response.headers,status:response.status,statusText:response.statusText})}function createFixedGatewayFetch(options={}){const fetchImplementation=options.fetch??globalThis.fetch;const maximumResponseBytes=options.maximumResponseBytes??defaultMaximumGatewayResponseBytes;if(!Number.isSafeInteger(maximumResponseBytes)||maximumResponseBytes<1||maximumResponseBytes>1024*1024*1024){invalidArgument("maximumResponseBytes is outside the supported range.")}const fixed=new URL(slopcameraGatewayApiBaseUrl);return async(input,init)=>{const url=gatewayUrl(input);if(url.origin!==fixed.origin||url.pathname!==fixed.pathname&&!url.pathname.startsWith(`${fixed.pathname}/`)||url.username!==""||url.password!==""){throw new SlopcameraCloudError("GENERATION_FAILED","The Vercel AI Gateway request was rejected.")}const canonicalInput=canonicalGatewayInput(input,url);let response;try{response=await fetchImplementation(canonicalInput,{...init,redirect:"error"})}catch(error){if(error instanceof SlopcameraCloudError)throw error;throw new SlopcameraCloudError("GENERATION_FAILED","Vercel AI Gateway image generation failed; the request was not retried.")}if(response.redirected||response.status>=300&&response.status<400){await response.body?.cancel().catch(()=>{return});throw new SlopcameraCloudError("GENERATION_FAILED","The Vercel AI Gateway request was rejected.")}return boundedResponse(response,maximumResponseBytes)}}function combineSignals(caller,timeoutMs){const controller=new AbortController;const abort=()=>controller.abort(caller?.reason);let rejectInterruption;const interruption=new Promise((_resolve,reject)=>{rejectInterruption=reject});const rejectOnAbort=()=>{rejectInterruption?.(new SlopcameraCloudError("GENERATION_FAILED","Vercel AI Gateway image generation was cancelled or exceeded its deadline."))};controller.signal.addEventListener("abort",rejectOnAbort,{once:true});if(caller?.aborted===true)abort();caller?.addEventListener("abort",abort,{once:true});const timer=setTimeout(()=>controller.abort(),timeoutMs);return{dispose:()=>{clearTimeout(timer);caller?.removeEventListener("abort",abort);controller.signal.removeEventListener("abort",rejectOnAbort);rejectInterruption=undefined},interruption,signal:controller.signal}}function mediaType(value){if(typeof value!=="string"||!slopcameraResponseMediaTypes.includes(value)){throw new SlopcameraCloudError("GENERATION_INVALID_RESPONSE","Vercel AI Gateway returned an unsupported image type.")}return value}function validImageBytes(bytes,type){if(bytes.byteLength<12||bytes.byteLength>slopcameraMaximumRawImageBytes){return false}if(type==="image/png"){return Buffer.from(bytes.subarray(0,8)).equals(Buffer.from([137,80,78,71,13,10,26,10]))}if(type==="image/jpeg"){return bytes[0]===255&&bytes[1]===216&&bytes.at(-2)===255&&bytes.at(-1)===217}return bytes.byteLength>=16&&Buffer.from(bytes.subarray(0,4)).toString("ascii")==="RIFF"&&Buffer.from(bytes).readUInt32LE(4)===bytes.byteLength-8&&Buffer.from(bytes.subarray(8,12)).toString("ascii")==="WEBP"&&["VP8 ","VP8L","VP8X"].includes(Buffer.from(bytes.subarray(12,16)).toString("ascii"))}function warningReceipt(value){let type="provider-warning";let detail="Provider warning";if(typeof value==="string"){detail=value}else if(isObject(value)){if(typeof value.type==="string"&&value.type.length<=64){type=value.type.replace(/[^a-z0-9._-]/giu,"-")||type}if(typeof value.message==="string")detail=value.message;else if(typeof value.details==="string")detail=value.details}return`${type} sha256:${createHash("sha256").update(detail).digest("hex")}`}function parseResult(value,model){if(!isObject(value)||!Array.isArray(value.images)||value.images.length!==1){throw new SlopcameraCloudError("GENERATION_INVALID_RESPONSE","Vercel AI Gateway did not return exactly one image.")}const image=value.images[0];if(!isObject(image)||!(image.uint8Array instanceof Uint8Array)){throw new SlopcameraCloudError("GENERATION_INVALID_RESPONSE","Vercel AI Gateway returned an invalid bounded image.")}const type=mediaType(image.mediaType);if(!validImageBytes(image.uint8Array,type)){throw new SlopcameraCloudError("GENERATION_INVALID_RESPONSE","Vercel AI Gateway returned an invalid bounded image.")}const gateway=isObject(value.providerMetadata)&&isObject(value.providerMetadata.gateway)?value.providerMetadata.gateway:undefined;const foreignGenerationId=gateway!==undefined&&typeof gateway.generationId==="string"&&gateway.generationId.length>0&&gateway.generationId.length<=256&&!/[\u0000-\u001f\u007f]/u.test(gateway.generationId)?gateway.generationId:randomUUID();const requestId=`sha256:${createHash("sha256").update("slopcamera.gateway-generation-id/v1\x00").update(foreignGenerationId).digest("hex")}`;const warnings=Array.isArray(value.warnings)?value.warnings.slice(0,100).map(warningReceipt):[];return{bytes:image.uint8Array,response:{image:{base64:Buffer.from(image.uint8Array).toString("base64"),mediaType:type},model,provider:"vercel-ai-gateway",requestId,warnings}}}async function performGeneration(input,dependencies){const model=validateModel(input.model);const prompt=validatePrompt(input.prompt);const credential=resolveSlopcameraGatewayCredential(dependencies.environment);const timeout=combineSignals(input.signal,validateTimeout(input.timeoutMs));try{const generation=(async()=>{assertGenerationActive(timeout.signal);disableAiSdkWarningLogging();const runtime=await(dependencies.loadRuntime??loadDefaultGatewayRuntime)();assertGenerationActive(timeout.signal);const provider=runtime.createGateway({apiKey:credential.token,baseURL:slopcameraGatewayApiBaseUrl,fetch:createFixedGatewayFetch({...dependencies.fetch===undefined?{}:{fetch:dependencies.fetch},...dependencies.maximumResponseBytes===undefined?{}:{maximumResponseBytes:dependencies.maximumResponseBytes}})});assertGenerationActive(timeout.signal);const generated=await runtime.generateImage({abortSignal:timeout.signal,maxRetries:0,model:provider.imageModel(model),n:1,prompt});return parseResult(generated,model)})();return await Promise.race([generation,timeout.interruption])}catch(error){if(error instanceof SlopcameraCloudError)throw error;throw new SlopcameraCloudError("GENERATION_FAILED","Vercel AI Gateway image generation failed; the request was not retried.")}finally{timeout.dispose()}}async function generateSlopcameraImage(input,dependencies={}){return(await performGeneration(input,dependencies)).response}function expectedMediaType(outputPath){const extension=extname(outputPath).toLocaleLowerCase("en-US");if(extension===".png")return"image/png";if(extension===".jpg"||extension===".jpeg")return"image/jpeg";if(extension===".webp")return"image/webp";invalidArgument("Output path must end in .png, .jpg, .jpeg, or .webp.")}async function atomicImageWrite(outputPath,bytes){const absolutePath=resolve(outputPath);const temporaryPath=resolve(dirname(absolutePath),`.${randomUUID()}.slopcamera-generate.tmp`);try{await writeFile(temporaryPath,bytes,{flag:"wx"});await link(temporaryPath,absolutePath);return absolutePath}catch{throw new SlopcameraCloudError("OUTPUT_WRITE_FAILED","Slopcamera could not atomically write the generated image.")}finally{await rm(temporaryPath,{force:true}).catch(()=>{return})}}async function generateSlopcameraImageFile(input,dependencies={}){if(typeof input.outputPath!=="string"||input.outputPath.length<1||input.outputPath.length>4096||input.outputPath.includes("\x00")){invalidArgument("Output path must be a non-empty local path.")}const expected=expectedMediaType(input.outputPath);const generated=await performGeneration(input,dependencies);if(generated.response.image.mediaType!==expected){throw new SlopcameraCloudError("GENERATION_INVALID_RESPONSE",`Generated ${generated.response.image.mediaType} does not match the requested ${expected} output path.`)}const outputPath=await atomicImageWrite(input.outputPath,generated.bytes);return{bytes:generated.bytes.byteLength,mediaType:generated.response.image.mediaType,model:generated.response.model,outputPath,provider:generated.response.provider,requestId:generated.response.requestId,sha256:createHash("sha256").update(generated.bytes).digest("hex"),warnings:generated.response.warnings}}
3
- export{SlopcameraCloudError,slopcameraGatewayApiBaseUrl,slopcameraImageModels,slopcameraResponseMediaTypes,slopcameraMaximumPromptBytes,slopcameraMaximumRawImageBytes,resolveSlopcameraGatewayCredential,slopcameraGatewayCredentialStatus,createFixedGatewayFetch,generateSlopcameraImage,generateSlopcameraImageFile};