@kenkaiiii/gg-ai 5.87.1 → 5.87.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/dist/index.cjs CHANGED
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
+ CLAUDE_CODE_FALLBACK_VERSION: () => CLAUDE_CODE_FALLBACK_VERSION,
33
34
  CODEX_CLIENT_VERSION: () => CODEX_CLIENT_VERSION,
34
35
  EventStream: () => EventStream,
35
36
  FAST_MODE_SUFFIX: () => FAST_MODE_SUFFIX,
@@ -49,6 +50,8 @@ __export(index_exports, {
49
50
  formatChatError: () => formatChatError,
50
51
  formatError: () => formatError,
51
52
  formatErrorForDisplay: () => formatErrorForDisplay,
53
+ getClaudeCliUserAgent: () => getClaudeCliUserAgent,
54
+ getClaudeCodeVersion: () => getClaudeCodeVersion,
52
55
  hasLoneSurrogate: () => hasLoneSurrogate,
53
56
  isHardBillingMessage: () => isHardBillingMessage,
54
57
  isUsageLimitError: () => isUsageLimitError,
@@ -62,6 +65,7 @@ __export(index_exports, {
62
65
  palsuThinking: () => palsuThinking,
63
66
  palsuToolCall: () => palsuToolCall,
64
67
  parseFastModeRejection: () => parseFastModeRejection,
68
+ pendingClaudeCodeVersionRefresh: () => pendingClaudeCodeVersionRefresh,
65
69
  prewarmAnthropicCache: () => prewarmAnthropicCache,
66
70
  providerRegistry: () => providerRegistry,
67
71
  redactText: () => redactText,
@@ -639,6 +643,145 @@ var StreamResult = class _StreamResult {
639
643
  }
640
644
  };
641
645
 
646
+ // src/claude-code-version.ts
647
+ var import_promises = __toESM(require("fs/promises"), 1);
648
+ var import_node_os = __toESM(require("os"), 1);
649
+ var import_node_path = __toESM(require("path"), 1);
650
+
651
+ // src/utils/diag.ts
652
+ var _diagFn = null;
653
+ function setProviderDiagnostic(fn) {
654
+ _diagFn = fn;
655
+ }
656
+ function providerDiag(phase, data) {
657
+ _diagFn?.(phase, data);
658
+ }
659
+
660
+ // src/claude-code-version.ts
661
+ var NPM_LATEST_URL = "https://registry.npmjs.org/@anthropic-ai/claude-code/latest";
662
+ var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
663
+ var FETCH_TIMEOUT_MS = 3e3;
664
+ var CLAUDE_CODE_FALLBACK_VERSION = "2.1.316";
665
+ function isOlder(a, b) {
666
+ const pa = a.split(".").map((n) => Number.parseInt(n, 10) || 0);
667
+ const pb = b.split(".").map((n) => Number.parseInt(n, 10) || 0);
668
+ for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
669
+ const x = pa[i] ?? 0;
670
+ const y = pb[i] ?? 0;
671
+ if (x !== y) return x < y;
672
+ }
673
+ return false;
674
+ }
675
+ function atLeastFallback(version) {
676
+ return isOlder(version, CLAUDE_CODE_FALLBACK_VERSION) ? CLAUDE_CODE_FALLBACK_VERSION : version;
677
+ }
678
+ var memoryCache = null;
679
+ var inflight = null;
680
+ function agentDir() {
681
+ return import_node_path.default.join(import_node_os.default.homedir(), ".gg");
682
+ }
683
+ function cachePath() {
684
+ return import_node_path.default.join(agentDir(), "claude-code-version.json");
685
+ }
686
+ async function readDiskCache() {
687
+ try {
688
+ const raw = await import_promises.default.readFile(cachePath(), "utf-8");
689
+ const parsed = JSON.parse(raw);
690
+ if (typeof parsed.version === "string" && typeof parsed.fetchedAt === "number") {
691
+ return parsed;
692
+ }
693
+ return null;
694
+ } catch {
695
+ return null;
696
+ }
697
+ }
698
+ async function writeDiskCache(data) {
699
+ try {
700
+ await import_promises.default.mkdir(agentDir(), { recursive: true, mode: 448 });
701
+ await import_promises.default.writeFile(cachePath(), JSON.stringify(data), { mode: 384 });
702
+ } catch (err) {
703
+ providerDiag("claude_code_version_cache_write_failed", {
704
+ error: err instanceof Error ? err.message : String(err)
705
+ });
706
+ }
707
+ }
708
+ async function fetchLatest() {
709
+ const controller = new AbortController();
710
+ const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
711
+ try {
712
+ const response = await fetch(NPM_LATEST_URL, { signal: controller.signal });
713
+ if (!response.ok) return null;
714
+ const data = await response.json();
715
+ if (typeof data.version === "string" && /^\d/.test(data.version)) {
716
+ return data.version;
717
+ }
718
+ return null;
719
+ } catch {
720
+ return null;
721
+ } finally {
722
+ clearTimeout(timer);
723
+ }
724
+ }
725
+ var refreshing = null;
726
+ function refreshInBackground() {
727
+ refreshing ??= (async () => {
728
+ try {
729
+ const fetched = await fetchLatest();
730
+ if (!fetched) return;
731
+ await writeDiskCache({ version: fetched, fetchedAt: Date.now() });
732
+ memoryCache = { version: fetched, expiresAt: Date.now() + CACHE_TTL_MS };
733
+ } finally {
734
+ refreshing = null;
735
+ }
736
+ })();
737
+ return refreshing;
738
+ }
739
+ function pendingClaudeCodeVersionRefresh() {
740
+ return refreshing;
741
+ }
742
+ async function getClaudeCodeVersion() {
743
+ if (memoryCache && Date.now() < memoryCache.expiresAt) {
744
+ return memoryCache.version;
745
+ }
746
+ if (inflight) return inflight;
747
+ inflight = (async () => {
748
+ const disk = await readDiskCache();
749
+ const diskFresh = disk && Date.now() - disk.fetchedAt < CACHE_TTL_MS;
750
+ if (disk && diskFresh) {
751
+ const version = atLeastFallback(disk.version);
752
+ memoryCache = { version, expiresAt: Date.now() + CACHE_TTL_MS };
753
+ return version;
754
+ }
755
+ if (disk) {
756
+ const version = atLeastFallback(disk.version);
757
+ memoryCache = { version, expiresAt: Date.now() + 5 * 60 * 1e3 };
758
+ void refreshInBackground();
759
+ return version;
760
+ }
761
+ const fetched = await fetchLatest();
762
+ if (fetched) {
763
+ await writeDiskCache({ version: fetched, fetchedAt: Date.now() });
764
+ memoryCache = { version: fetched, expiresAt: Date.now() + CACHE_TTL_MS };
765
+ return fetched;
766
+ }
767
+ const resolved = CLAUDE_CODE_FALLBACK_VERSION;
768
+ memoryCache = { version: resolved, expiresAt: Date.now() + 5 * 60 * 1e3 };
769
+ providerDiag("claude_code_version_fallback", { version: resolved });
770
+ return resolved;
771
+ })();
772
+ try {
773
+ return await inflight;
774
+ } finally {
775
+ inflight = null;
776
+ }
777
+ }
778
+ function claudeCliUserAgent(version) {
779
+ return `claude-cli/${version} (external, cli)`;
780
+ }
781
+ async function getClaudeCliUserAgent() {
782
+ return claudeCliUserAgent(await getClaudeCodeVersion());
783
+ }
784
+
642
785
  // src/utils/provider-options.ts
643
786
  var RESERVED_BODY_FIELDS = /* @__PURE__ */ new Set([
644
787
  "contents",
@@ -1806,7 +1949,7 @@ function parseToolArguments(argsJson) {
1806
1949
 
1807
1950
  // src/utils/provider-fetch.ts
1808
1951
  var import_undici = require("undici");
1809
- var PROVIDER_TRANSPORT_TIMEOUT_MS = 30 * 6e4;
1952
+ var PROVIDER_TRANSPORT_TIMEOUT_MS = 45 * 6e4;
1810
1953
  function nodeUsesEnvProxy({
1811
1954
  env = process.env,
1812
1955
  execArgv = process.execArgv,
@@ -1834,6 +1977,25 @@ function createProviderFetch(timeoutMs, { useEnvProxy = nodeUsesEnvProxy() } = {
1834
1977
  };
1835
1978
  return Object.assign(providerFetch2, { Response: globalThis.Response });
1836
1979
  }
1980
+ function withBodyActivity(fetchImpl, onActivity) {
1981
+ return async (input, init2) => {
1982
+ const response = await fetchImpl(input, init2);
1983
+ if (!response.body || !response.headers.get("content-type")?.includes("text/event-stream")) {
1984
+ return response;
1985
+ }
1986
+ const tap = new TransformStream({
1987
+ transform(chunk, controller) {
1988
+ onActivity();
1989
+ controller.enqueue(chunk);
1990
+ }
1991
+ });
1992
+ return new Response(response.body.pipeThrough(tap), {
1993
+ status: response.status,
1994
+ statusText: response.statusText,
1995
+ headers: response.headers
1996
+ });
1997
+ };
1998
+ }
1837
1999
  var providerFetch = createProviderFetch(
1838
2000
  PROVIDER_TRANSPORT_TIMEOUT_MS
1839
2001
  );
@@ -1890,9 +2052,13 @@ function sumUsageIterations(usage) {
1890
2052
  }
1891
2053
  return totals;
1892
2054
  }
2055
+ async function withClaudeUserAgent(options) {
2056
+ if (options.userAgent || !options.apiKey?.startsWith("sk-ant-oat")) return options;
2057
+ return { ...options, userAgent: await getClaudeCliUserAgent() };
2058
+ }
1893
2059
  function createClient(options) {
1894
2060
  const isOAuth = options.apiKey?.startsWith("sk-ant-oat");
1895
- const userAgent = isOAuth ? options.userAgent ?? "claude-cli/2.1.75 (external, cli)" : "";
2061
+ const userAgent = isOAuth ? options.userAgent ?? claudeCliUserAgent(CLAUDE_CODE_FALLBACK_VERSION) : "";
1896
2062
  const cacheKey = `${options.apiKey ?? ""}|${options.baseUrl ?? ""}|${userAgent}`;
1897
2063
  if (!options.fetch) {
1898
2064
  const cached = anthropicClientCache.get(cacheKey);
@@ -1922,11 +2088,13 @@ function createClient(options) {
1922
2088
  }
1923
2089
  async function prewarmAnthropicCache(options) {
1924
2090
  try {
1925
- const client = createClient({
1926
- apiKey: options.apiKey,
1927
- baseUrl: options.baseUrl,
1928
- userAgent: options.userAgent
1929
- });
2091
+ const client = createClient(
2092
+ await withClaudeUserAgent({
2093
+ apiKey: options.apiKey,
2094
+ baseUrl: options.baseUrl,
2095
+ userAgent: options.userAgent
2096
+ })
2097
+ );
1930
2098
  const cacheControl = toAnthropicCacheControl(options.cacheRetention ?? "long", options.baseUrl);
1931
2099
  const { system, messages } = toAnthropicMessages(
1932
2100
  [
@@ -1980,7 +2148,7 @@ function streamAnthropic(options) {
1980
2148
  return new StreamResult(runStream(options), options.signal);
1981
2149
  }
1982
2150
  async function* runStream(options) {
1983
- const client = createClient(options);
2151
+ const client = createClient(await withClaudeUserAgent(options));
1984
2152
  const isOAuth = options.apiKey?.startsWith("sk-ant-oat");
1985
2153
  const useStreaming = options.streaming !== false && !options.prewarm;
1986
2154
  const cacheControl = toAnthropicCacheControl(options.cacheRetention, options.baseUrl);
@@ -2134,8 +2302,10 @@ async function* runStream(options) {
2134
2302
  const keepalive = { type: "keepalive" };
2135
2303
  let receivedAnyEvent = false;
2136
2304
  try {
2305
+ const onActivity = options.onTransportActivity;
2306
+ const streamClient = onActivity ? client.withOptions({ fetch: withBodyActivity(options.fetch ?? providerFetch, onActivity) }) : client;
2137
2307
  const stream2 = await send(
2138
- (p, o) => client.messages.create(p, o)
2308
+ (p, o) => streamClient.messages.create(p, o)
2139
2309
  );
2140
2310
  for await (const event of stream2) {
2141
2311
  receivedAnyEvent = true;
@@ -2559,15 +2729,6 @@ function fnv1aHash(value) {
2559
2729
  return (hash >>> 0).toString(16).padStart(8, "0");
2560
2730
  }
2561
2731
 
2562
- // src/utils/diag.ts
2563
- var _diagFn = null;
2564
- function setProviderDiagnostic(fn) {
2565
- _diagFn = fn;
2566
- }
2567
- function providerDiag(phase, data) {
2568
- _diagFn?.(phase, data);
2569
- }
2570
-
2571
2732
  // src/providers/moonshot-video.ts
2572
2733
  async function uploadMoonshotVideos(client, messages, signal) {
2573
2734
  for (const msg of messages) {
@@ -2793,11 +2954,11 @@ async function* runStream2(options) {
2793
2954
  }
2794
2955
  const requestParams = mergeProviderOptions(params, options.providerOptions);
2795
2956
  if (getEnvironment()?.GGAI_DUMP_REQUEST) {
2796
- const fs = await import("fs");
2957
+ const fs2 = await import("fs");
2797
2958
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
2798
2959
  const dumpPath = `/tmp/ggai-request-${ts}.json`;
2799
- fs.writeFileSync(dumpPath, JSON.stringify(requestParams, null, 2));
2800
- fs.appendFileSync(
2960
+ fs2.writeFileSync(dumpPath, JSON.stringify(requestParams, null, 2));
2961
+ fs2.appendFileSync(
2801
2962
  "/tmp/ggai-requests.log",
2802
2963
  `[${ts}] ${dumpPath} messages=${requestParams.messages.length}
2803
2964
  `
@@ -3127,7 +3288,7 @@ function toError2(err, provider = "openai") {
3127
3288
  }
3128
3289
 
3129
3290
  // src/providers/openai-codex.ts
3130
- var import_node_os = __toESM(require("os"), 1);
3291
+ var import_node_os2 = __toESM(require("os"), 1);
3131
3292
  var zstd = __toESM(require("@bokuweb/zstd-wasm"), 1);
3132
3293
 
3133
3294
  // src/utils/sse.ts
@@ -3729,7 +3890,7 @@ async function* runStream3(options, retriedWithoutReasoning = false) {
3729
3890
  Authorization: `Bearer ${options.apiKey}`,
3730
3891
  "OpenAI-Beta": "responses=experimental",
3731
3892
  originator: responsesLite ? "codex_cli_rs" : "ggcoder",
3732
- "User-Agent": responsesLite ? `codex_cli_rs/${CODEX_CLIENT_VERSION}` : `ggcoder (${import_node_os.default.platform()} ${import_node_os.default.release()}; ${import_node_os.default.arch()})`,
3893
+ "User-Agent": responsesLite ? `codex_cli_rs/${CODEX_CLIENT_VERSION}` : `ggcoder (${import_node_os2.default.platform()} ${import_node_os2.default.release()}; ${import_node_os2.default.arch()})`,
3733
3894
  ...responsesLite ? { version: CODEX_CLIENT_VERSION } : {},
3734
3895
  ...liteShape ? { "X-OpenAI-Internal-Codex-Responses-Lite": "true" } : {}
3735
3896
  };
@@ -4853,8 +5014,8 @@ function bound(text) {
4853
5014
  const trimmed = text.trim();
4854
5015
  return trimmed.length > MAX_ERROR_MESSAGE_CHARS ? `${trimmed.slice(0, MAX_ERROR_MESSAGE_CHARS)}\u2026` : trimmed;
4855
5016
  }
4856
- function joinUrl(baseUrl, path) {
4857
- return `${baseUrl.replace(/\/+$/, "")}/${path.replace(/^\/+/, "")}`;
5017
+ function joinUrl(baseUrl, path2) {
5018
+ return `${baseUrl.replace(/\/+$/, "")}/${path2.replace(/^\/+/, "")}`;
4858
5019
  }
4859
5020
 
4860
5021
  // src/providers/gemini-embeddings.ts
@@ -6065,6 +6226,7 @@ function palsuRerankScore(query, document) {
6065
6226
  }
6066
6227
  // Annotate the CommonJS export names for ESM import in node:
6067
6228
  0 && (module.exports = {
6229
+ CLAUDE_CODE_FALLBACK_VERSION,
6068
6230
  CODEX_CLIENT_VERSION,
6069
6231
  EventStream,
6070
6232
  FAST_MODE_SUFFIX,
@@ -6084,6 +6246,8 @@ function palsuRerankScore(query, document) {
6084
6246
  formatChatError,
6085
6247
  formatError,
6086
6248
  formatErrorForDisplay,
6249
+ getClaudeCliUserAgent,
6250
+ getClaudeCodeVersion,
6087
6251
  hasLoneSurrogate,
6088
6252
  isHardBillingMessage,
6089
6253
  isUsageLimitError,
@@ -6097,6 +6261,7 @@ function palsuRerankScore(query, document) {
6097
6261
  palsuThinking,
6098
6262
  palsuToolCall,
6099
6263
  parseFastModeRejection,
6264
+ pendingClaudeCodeVersionRefresh,
6100
6265
  prewarmAnthropicCache,
6101
6266
  providerRegistry,
6102
6267
  redactText,