@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 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 fetch(buildGeminiGenerateContentUrl(plan.provider.base_url, plan.model), {
500
- method: "POST",
501
- headers: {
502
- "x-goog-api-key": apiKey,
503
- "Content-Type": "application/json"
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
- body: JSON.stringify(buildGeminiGenerateContentRequest(plan, referenceParts))
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 fetch(buildOpenAIImagesUrl(plan.provider.base_url), {
628
- method: "POST",
629
- headers: {
630
- Authorization: `Bearer ${apiKey}`,
631
- "Content-Type": "application/json"
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
- body: JSON.stringify(buildOpenAIImagesRequest(plan))
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.2";
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;
@@ -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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-agent-tools/picgen",
3
- "version": "0.1.0-alpha.2",
3
+ "version": "0.1.0-alpha.3",
4
4
  "description": "A lightweight image generation connector for AI agents.",
5
5
  "type": "module",
6
6
  "bin": {