@prestyj/agent 5.11.0 → 5.12.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.
package/dist/index.d.cts CHANGED
@@ -215,6 +215,22 @@ interface AgentOptions {
215
215
  temperature?: number;
216
216
  thinking?: StreamOptions["thinking"];
217
217
  apiKey?: string;
218
+ /**
219
+ * Re-resolve the credential at the start of every turn. A run can span many
220
+ * minutes, and an OAuth grant refreshed by any process (another app window, a
221
+ * CLI session, the usage poller) invalidates the access token captured when
222
+ * the run began — so a pinned `apiKey` goes dead mid-run and every remaining
223
+ * turn fails with an authentication error. Returning the current credential
224
+ * here keeps a long run alive across rotations.
225
+ *
226
+ * Falls back to `apiKey`/`accountId`/`projectId` when omitted or when the
227
+ * resolver throws (the provider call then surfaces the real auth error).
228
+ */
229
+ resolveCredentials?: () => Promise<{
230
+ apiKey: string;
231
+ accountId?: string;
232
+ projectId?: string;
233
+ }>;
218
234
  baseUrl?: string;
219
235
  signal?: AbortSignal;
220
236
  accountId?: string;
@@ -374,7 +390,7 @@ declare function isBillingError(err: unknown): boolean;
374
390
  * plan running out of usage). Unlike a transient per-minute 429, this does NOT
375
391
  * clear with a quick retry — the user must wait for the window to reset — so the
376
392
  * loop surfaces it immediately instead of retrying for minutes. Matches the
377
- * canonical message gg-ai stamps onto the provider error.
393
+ * canonical message @prestyj/ai stamps onto the provider error.
378
394
  */
379
395
  declare function isUsageLimitError(err: unknown): boolean;
380
396
  declare function agentLoop(messages: Message[], options: AgentOptions): AsyncGenerator<AgentEvent, AgentResult>;
package/dist/index.d.ts CHANGED
@@ -215,6 +215,22 @@ interface AgentOptions {
215
215
  temperature?: number;
216
216
  thinking?: StreamOptions["thinking"];
217
217
  apiKey?: string;
218
+ /**
219
+ * Re-resolve the credential at the start of every turn. A run can span many
220
+ * minutes, and an OAuth grant refreshed by any process (another app window, a
221
+ * CLI session, the usage poller) invalidates the access token captured when
222
+ * the run began — so a pinned `apiKey` goes dead mid-run and every remaining
223
+ * turn fails with an authentication error. Returning the current credential
224
+ * here keeps a long run alive across rotations.
225
+ *
226
+ * Falls back to `apiKey`/`accountId`/`projectId` when omitted or when the
227
+ * resolver throws (the provider call then surfaces the real auth error).
228
+ */
229
+ resolveCredentials?: () => Promise<{
230
+ apiKey: string;
231
+ accountId?: string;
232
+ projectId?: string;
233
+ }>;
218
234
  baseUrl?: string;
219
235
  signal?: AbortSignal;
220
236
  accountId?: string;
@@ -374,7 +390,7 @@ declare function isBillingError(err: unknown): boolean;
374
390
  * plan running out of usage). Unlike a transient per-minute 429, this does NOT
375
391
  * clear with a quick retry — the user must wait for the window to reset — so the
376
392
  * loop surfaces it immediately instead of retrying for minutes. Matches the
377
- * canonical message gg-ai stamps onto the provider error.
393
+ * canonical message @prestyj/ai stamps onto the provider error.
378
394
  */
379
395
  declare function isUsageLimitError(err: unknown): boolean;
380
396
  declare function agentLoop(messages: Message[], options: AgentOptions): AsyncGenerator<AgentEvent, AgentResult>;
package/dist/index.js CHANGED
@@ -57,7 +57,13 @@ function isContextOverflow(err) {
57
57
  if (overflowStatus === 402) return false;
58
58
  if (isBillingError(err)) return false;
59
59
  const msg = err.message.toLowerCase();
60
- return msg.includes("prompt is too long") || msg.includes("prompt too long") || msg.includes("input is too long") || msg.includes("context_length_exceeded") || msg.includes("context_window_exceeded") || msg.includes("maximum context length") || msg.includes("exceeds model context window") || msg.includes("exceeds the context window") || msg.includes("content_too_large") || msg.includes("request_too_large") || msg.includes("reduce the length") || msg.includes("please shorten") || msg.includes("token") && msg.includes("exceed");
60
+ if (msg.includes("prompt is too long") || msg.includes("prompt too long") || msg.includes("input is too long") || msg.includes("context_length_exceeded") || msg.includes("context_window_exceeded") || msg.includes("maximum context length") || msg.includes("exceeds model context window") || msg.includes("exceeds the context window") || msg.includes("content_too_large") || msg.includes("request_too_large") || msg.includes("reduce the length") || msg.includes("please shorten")) {
61
+ return true;
62
+ }
63
+ const rateLimited = overflowStatus === 429 || msg.includes("rate limit") || msg.includes("rate_limit") || msg.includes("too many requests");
64
+ const perUnitTime = msg.includes("per min") || msg.includes("/min") || msg.includes("per minute") || msg.includes("per hour") || msg.includes("per day") || msg.includes("tpm") || msg.includes("rpm");
65
+ if (rateLimited && perUnitTime) return false;
66
+ return msg.includes("token") && msg.includes("exceed");
61
67
  }
62
68
  function parseOverflowNumber(value) {
63
69
  return Number(value.replace(/[,_\s]/g, ""));
@@ -170,6 +176,17 @@ function isMalformedStream(err) {
170
176
  const msg = err.message;
171
177
  return /\bin JSON at position \d+/i.test(msg);
172
178
  }
179
+ var TIMEOUT_NAMES = /* @__PURE__ */ new Set(["TimeoutError", "ConnectTimeoutError", "HeadersTimeoutError"]);
180
+ var TIMEOUT_MESSAGES = [
181
+ /^request timed out\.?$/i,
182
+ /\brequest to [\w .-]+ timed out\b/i,
183
+ /\b(?:connection|socket|headers|stream) timed out\b/i
184
+ ];
185
+ function isBareTimeout(e) {
186
+ if (typeof e.name === "string" && TIMEOUT_NAMES.has(e.name)) return true;
187
+ if (typeof e.message !== "string") return false;
188
+ return TIMEOUT_MESSAGES.some((re) => re.test(e.message));
189
+ }
173
190
  function isTransportFailure(err) {
174
191
  const codes = /* @__PURE__ */ new Set([
175
192
  "ECONNRESET",
@@ -206,6 +223,8 @@ function isTransportFailure(err) {
206
223
  if (typeof e.message === "string") {
207
224
  for (const re of messages) if (re.test(e.message)) return true;
208
225
  }
226
+ const clientError = typeof e.status === "number" && e.status >= 400 && e.status < 500;
227
+ if (!clientError && isBareTimeout(e)) return true;
209
228
  cur = e.cause;
210
229
  }
211
230
  return false;
@@ -431,6 +450,21 @@ async function* agentLoop(messages, options) {
431
450
  diag("stream_call", { nonStreaming: useNonStreamingFallback });
432
451
  streamCallStart = Date.now();
433
452
  providerAttemptStartedAt = streamCallStart;
453
+ let liveApiKey = options.apiKey;
454
+ let liveAccountId = options.accountId;
455
+ let liveProjectId = options.projectId;
456
+ if (options.resolveCredentials) {
457
+ try {
458
+ const fresh = await options.resolveCredentials();
459
+ liveApiKey = fresh.apiKey;
460
+ if (fresh.accountId !== void 0) liveAccountId = fresh.accountId;
461
+ if (fresh.projectId !== void 0) liveProjectId = fresh.projectId;
462
+ } catch (credErr) {
463
+ diag("credential_refresh_failed", {
464
+ error: (credErr instanceof Error ? credErr.message : String(credErr)).slice(0, 200)
465
+ });
466
+ }
467
+ }
434
468
  const result = stream({
435
469
  provider: options.provider,
436
470
  model: options.model,
@@ -442,12 +476,12 @@ async function* agentLoop(messages, options) {
442
476
  maxTokens: options.maxTokens,
443
477
  temperature: options.temperature,
444
478
  thinking: options.thinking,
445
- apiKey: options.apiKey,
479
+ apiKey: liveApiKey,
446
480
  baseUrl: options.baseUrl,
447
481
  signal: streamController.signal,
448
- accountId: options.accountId,
482
+ accountId: liveAccountId,
449
483
  transportSessionId: options.transportSessionId,
450
- projectId: options.projectId,
484
+ projectId: liveProjectId,
451
485
  cacheRetention: options.cacheRetention,
452
486
  promptCacheKey: options.promptCacheKey,
453
487
  serviceTier: options.serviceTier,