@ai-agent-tools/picgen 0.1.0-alpha.2 → 0.1.0-alpha.3
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/README.md +6 -0
- package/dist/cli.js +71 -15
- package/docs/release-alpha.md +8 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -101,6 +101,12 @@ Provider `base_url` values should be host-only. Do not include `/v1` or `/v1beta
|
|
|
101
101
|
|
|
102
102
|
Providers may optionally set `test_model` in `~/.picgen/config.yaml` when health checks should use a lightweight model instead of the first generation model.
|
|
103
103
|
|
|
104
|
+
Generation requests use adaptive provider timeouts: fast draft requests allow 120s, balanced requests allow 180s, and high quality or large requests allow 300s. If a third-party channel is slower, override it with `PICGEN_PROVIDER_TIMEOUT_MS`:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
PICGEN_PROVIDER_TIMEOUT_MS=450000 picgen create --yes --preset poster "一张产品发布会主视觉"
|
|
108
|
+
```
|
|
109
|
+
|
|
104
110
|
Providers expose capabilities such as `text-to-image` and `reference-image`. Old configs that omit capabilities are upgraded in memory from the provider protocol: Gemini supports both text and reference-image generation, while OpenAI-compatible `/v1/images/generations` supports text-to-image only.
|
|
105
111
|
|
|
106
112
|
Generated image data and provider-only fields such as base64 image payloads and Gemini thought signatures are redacted from metadata. PicGen keeps the generated assets as local image files and keeps stdout compact for agent workflows.
|
package/dist/cli.js
CHANGED
|
@@ -459,6 +459,53 @@ async function ensureConfig() {
|
|
|
459
459
|
// src/providers/gemini.ts
|
|
460
460
|
import { readFile as readFile2 } from "fs/promises";
|
|
461
461
|
|
|
462
|
+
// src/providers/timeout.ts
|
|
463
|
+
var FAST_PROVIDER_TIMEOUT_MS = 12e4;
|
|
464
|
+
var DEFAULT_PROVIDER_TIMEOUT_MS = 18e4;
|
|
465
|
+
var SLOW_PROVIDER_TIMEOUT_MS = 3e5;
|
|
466
|
+
function resolveProviderTimeoutMs(plan) {
|
|
467
|
+
const override = parseTimeoutOverride(process.env.PICGEN_PROVIDER_TIMEOUT_MS);
|
|
468
|
+
if (override !== void 0) return override;
|
|
469
|
+
if (plan.presetName === "fast-draft" || plan.modeName === "fast" || plan.preset.quality === "low") {
|
|
470
|
+
return FAST_PROVIDER_TIMEOUT_MS;
|
|
471
|
+
}
|
|
472
|
+
if (plan.modeName === "premium" || plan.preset.size === "large" || plan.preset.quality === "high") {
|
|
473
|
+
return SLOW_PROVIDER_TIMEOUT_MS;
|
|
474
|
+
}
|
|
475
|
+
return DEFAULT_PROVIDER_TIMEOUT_MS;
|
|
476
|
+
}
|
|
477
|
+
async function fetchWithProviderTimeout(input3, init, timeoutMs) {
|
|
478
|
+
const controller = new AbortController();
|
|
479
|
+
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
480
|
+
try {
|
|
481
|
+
return await fetch(input3, {
|
|
482
|
+
...init,
|
|
483
|
+
signal: controller.signal
|
|
484
|
+
});
|
|
485
|
+
} catch (error) {
|
|
486
|
+
if (isAbortError(error)) {
|
|
487
|
+
throw new Error(formatProviderTimeoutError(timeoutMs));
|
|
488
|
+
}
|
|
489
|
+
throw error;
|
|
490
|
+
} finally {
|
|
491
|
+
clearTimeout(timeout);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
function formatProviderTimeoutError(timeoutMs) {
|
|
495
|
+
return `Provider request timed out after ${Math.ceil(
|
|
496
|
+
timeoutMs / 1e3
|
|
497
|
+
)}s. The provider may still be processing or temporarily unavailable. Try again, use a faster preset, or increase PICGEN_PROVIDER_TIMEOUT_MS.`;
|
|
498
|
+
}
|
|
499
|
+
function parseTimeoutOverride(value) {
|
|
500
|
+
if (!value) return void 0;
|
|
501
|
+
const timeoutMs = Number(value);
|
|
502
|
+
if (!Number.isInteger(timeoutMs) || timeoutMs <= 0) return void 0;
|
|
503
|
+
return timeoutMs;
|
|
504
|
+
}
|
|
505
|
+
function isAbortError(error) {
|
|
506
|
+
return error instanceof Error && error.name === "AbortError";
|
|
507
|
+
}
|
|
508
|
+
|
|
462
509
|
// src/providers/urls.ts
|
|
463
510
|
function normalizeProviderBaseUrl(baseUrl) {
|
|
464
511
|
const url = new URL(baseUrl);
|
|
@@ -495,15 +542,20 @@ var GeminiAdapter = class {
|
|
|
495
542
|
const providerImages = [];
|
|
496
543
|
const requestCount = Math.max(1, plan.preset.n);
|
|
497
544
|
const referenceParts = await readReferenceImageParts(plan);
|
|
545
|
+
const timeoutMs = resolveProviderTimeoutMs(plan);
|
|
498
546
|
for (let index = 0; index < requestCount; index += 1) {
|
|
499
|
-
const response = await
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
"
|
|
503
|
-
|
|
547
|
+
const response = await fetchWithProviderTimeout(
|
|
548
|
+
buildGeminiGenerateContentUrl(plan.provider.base_url, plan.model),
|
|
549
|
+
{
|
|
550
|
+
method: "POST",
|
|
551
|
+
headers: {
|
|
552
|
+
"x-goog-api-key": apiKey,
|
|
553
|
+
"Content-Type": "application/json"
|
|
554
|
+
},
|
|
555
|
+
body: JSON.stringify(buildGeminiGenerateContentRequest(plan, referenceParts))
|
|
504
556
|
},
|
|
505
|
-
|
|
506
|
-
|
|
557
|
+
timeoutMs
|
|
558
|
+
);
|
|
507
559
|
const raw = await readJsonResponse(response);
|
|
508
560
|
if (!response.ok) {
|
|
509
561
|
throw new Error(formatGeminiError(response.status, response.statusText, raw));
|
|
@@ -624,14 +676,18 @@ var OpenAIImagesAdapter = class {
|
|
|
624
676
|
if (!apiKey) {
|
|
625
677
|
throw new Error(`Missing API key environment variable: ${plan.provider.api_key_env}`);
|
|
626
678
|
}
|
|
627
|
-
const response = await
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
679
|
+
const response = await fetchWithProviderTimeout(
|
|
680
|
+
buildOpenAIImagesUrl(plan.provider.base_url),
|
|
681
|
+
{
|
|
682
|
+
method: "POST",
|
|
683
|
+
headers: {
|
|
684
|
+
Authorization: `Bearer ${apiKey}`,
|
|
685
|
+
"Content-Type": "application/json"
|
|
686
|
+
},
|
|
687
|
+
body: JSON.stringify(buildOpenAIImagesRequest(plan))
|
|
632
688
|
},
|
|
633
|
-
|
|
634
|
-
|
|
689
|
+
resolveProviderTimeoutMs(plan)
|
|
690
|
+
);
|
|
635
691
|
const raw = await readJsonResponse2(response);
|
|
636
692
|
if (!response.ok) {
|
|
637
693
|
throw new Error(formatOpenAIImagesError(response.status, response.statusText, raw));
|
|
@@ -999,7 +1055,7 @@ import { homedir as homedir2 } from "os";
|
|
|
999
1055
|
|
|
1000
1056
|
// src/version.ts
|
|
1001
1057
|
var PACKAGE_NAME = "@ai-agent-tools/picgen";
|
|
1002
|
-
var VERSION = "0.1.0-alpha.
|
|
1058
|
+
var VERSION = "0.1.0-alpha.3";
|
|
1003
1059
|
|
|
1004
1060
|
// src/commands/update.ts
|
|
1005
1061
|
var UPDATE_CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
package/docs/release-alpha.md
CHANGED
|
@@ -143,6 +143,14 @@ picgen provider test <provider-name> --json
|
|
|
143
143
|
|
|
144
144
|
Check `base_url`, API key, model name, and provider availability.
|
|
145
145
|
|
|
146
|
+
`Provider request timed out`
|
|
147
|
+
|
|
148
|
+
High quality, large, or slow third-party image channels can take longer. Try again, use a faster preset, or raise the request timeout:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
PICGEN_PROVIDER_TIMEOUT_MS=450000 picgen create --yes --preset poster "<prompt>"
|
|
152
|
+
```
|
|
153
|
+
|
|
146
154
|
`No enabled provider can satisfy...`
|
|
147
155
|
|
|
148
156
|
Run `picgen provider list`, enable a provider, add a fallback provider, or adjust the selected mode/model.
|