@kenkaiiii/gg-agent 5.39.3 → 5.40.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;
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;
package/dist/index.js CHANGED
@@ -160,6 +160,17 @@ function isMalformedStream(err) {
160
160
  const msg = err.message;
161
161
  return /\bin JSON at position \d+/i.test(msg);
162
162
  }
163
+ var TIMEOUT_NAMES = /* @__PURE__ */ new Set(["TimeoutError", "ConnectTimeoutError", "HeadersTimeoutError"]);
164
+ var TIMEOUT_MESSAGES = [
165
+ /^request timed out\.?$/i,
166
+ /\brequest to [\w .-]+ timed out\b/i,
167
+ /\b(?:connection|socket|headers|stream) timed out\b/i
168
+ ];
169
+ function isBareTimeout(e) {
170
+ if (typeof e.name === "string" && TIMEOUT_NAMES.has(e.name)) return true;
171
+ if (typeof e.message !== "string") return false;
172
+ return TIMEOUT_MESSAGES.some((re) => re.test(e.message));
173
+ }
163
174
  function isTransportFailure(err) {
164
175
  const codes = /* @__PURE__ */ new Set([
165
176
  "ECONNRESET",
@@ -196,6 +207,8 @@ function isTransportFailure(err) {
196
207
  if (typeof e.message === "string") {
197
208
  for (const re of messages) if (re.test(e.message)) return true;
198
209
  }
210
+ const clientError = typeof e.status === "number" && e.status >= 400 && e.status < 500;
211
+ if (!clientError && isBareTimeout(e)) return true;
199
212
  cur = e.cause;
200
213
  }
201
214
  return false;
@@ -387,6 +400,21 @@ async function* agentLoop(messages, options) {
387
400
  diag("stream_call", { nonStreaming: useNonStreamingFallback });
388
401
  streamCallStart = Date.now();
389
402
  providerAttemptStartedAt = streamCallStart;
403
+ let liveApiKey = options.apiKey;
404
+ let liveAccountId = options.accountId;
405
+ let liveProjectId = options.projectId;
406
+ if (options.resolveCredentials) {
407
+ try {
408
+ const fresh = await options.resolveCredentials();
409
+ liveApiKey = fresh.apiKey;
410
+ if (fresh.accountId !== void 0) liveAccountId = fresh.accountId;
411
+ if (fresh.projectId !== void 0) liveProjectId = fresh.projectId;
412
+ } catch (credErr) {
413
+ diag("credential_refresh_failed", {
414
+ error: (credErr instanceof Error ? credErr.message : String(credErr)).slice(0, 200)
415
+ });
416
+ }
417
+ }
390
418
  const result = stream({
391
419
  provider: options.provider,
392
420
  model: options.model,
@@ -398,12 +426,12 @@ async function* agentLoop(messages, options) {
398
426
  maxTokens: options.maxTokens,
399
427
  temperature: options.temperature,
400
428
  thinking: options.thinking,
401
- apiKey: options.apiKey,
429
+ apiKey: liveApiKey,
402
430
  baseUrl: options.baseUrl,
403
431
  signal: streamController.signal,
404
- accountId: options.accountId,
432
+ accountId: liveAccountId,
405
433
  transportSessionId: options.transportSessionId,
406
- projectId: options.projectId,
434
+ projectId: liveProjectId,
407
435
  cacheRetention: options.cacheRetention,
408
436
  promptCacheKey: options.promptCacheKey,
409
437
  serviceTier: options.serviceTier,