circle-ir-ai 2.20.2 → 2.20.6

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.
@@ -108,6 +108,19 @@ export declare class AxLLMClient {
108
108
  * (not just char counts). Reset to `undefined` on entry. cognium-ai#125.
109
109
  */
110
110
  private lastUsage;
111
+ /**
112
+ * Set by `_chatJSONImpl` to the final value of its loop counter
113
+ * `attemptIdx` (1 = no retry, 2 = one retry, …). The outer `chatJSON`
114
+ * wrapper reads this to log `retryCount = attemptIdx - 1` on the
115
+ * `kind:'call'` JSONL row. Reset to `undefined` on entry.
116
+ *
117
+ * cognium-ai#148 — the wrapper previously logged its own input
118
+ * parameter `retryCount` (always 0 in practice since recursion was
119
+ * eliminated in #39/#40), so per-call retry totals were always zero
120
+ * even when the inline retry loop fired. The per-attempt rows
121
+ * (`kind:'attempt'`) were correct; only the per-call summary lied.
122
+ */
123
+ private lastAttemptCount;
111
124
  constructor(config?: Partial<LLMConfig>);
112
125
  /**
113
126
  * Check if LLM is currently available (not disabled due to failures)
@@ -1 +1 @@
1
- {"version":3,"file":"ax-client.d.ts","sourceRoot":"","sources":["../../src/llm/ax-client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ax-client.d.ts","sourceRoot":"","sources":["../../src/llm/ax-client.ts"],"names":[],"mappings":"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"}
@@ -258,6 +258,19 @@ export class AxLLMClient {
258
258
  * (not just char counts). Reset to `undefined` on entry. cognium-ai#125.
259
259
  */
260
260
  lastUsage = undefined;
261
+ /**
262
+ * Set by `_chatJSONImpl` to the final value of its loop counter
263
+ * `attemptIdx` (1 = no retry, 2 = one retry, …). The outer `chatJSON`
264
+ * wrapper reads this to log `retryCount = attemptIdx - 1` on the
265
+ * `kind:'call'` JSONL row. Reset to `undefined` on entry.
266
+ *
267
+ * cognium-ai#148 — the wrapper previously logged its own input
268
+ * parameter `retryCount` (always 0 in practice since recursion was
269
+ * eliminated in #39/#40), so per-call retry totals were always zero
270
+ * even when the inline retry loop fired. The per-attempt rows
271
+ * (`kind:'attempt'`) were correct; only the per-call summary lied.
272
+ */
273
+ lastAttemptCount = undefined;
261
274
  constructor(config) {
262
275
  this.config = { ...getDefaultLLMConfig(), ...config };
263
276
  // Validate required configuration
@@ -647,6 +660,7 @@ INFORMATION EXPOSURE (CWE-200/209) SPECIFIC:
647
660
  let errorMsg;
648
661
  this.lastErrorCategory = undefined;
649
662
  this.lastUsage = undefined;
663
+ this.lastAttemptCount = undefined;
650
664
  try {
651
665
  result = await this._chatJSONImpl(systemPrompt, userPrompt, phase, retryCount);
652
666
  }
@@ -687,7 +701,15 @@ INFORMATION EXPOSURE (CWE-200/209) SPECIFIC:
687
701
  success: result !== null && errorMsg === undefined,
688
702
  error: errorMsg,
689
703
  parseError: result === null && errorMsg === undefined,
690
- retryCount,
704
+ // cognium-ai#148 — prefer the threaded loop count from
705
+ // `_chatJSONImpl`. `attemptIdx` starts at 1 (first iteration), so
706
+ // `retries = attemptIdx - 1`. The parameter `retryCount` is the
707
+ // fallback for code paths that bypass the queue (pro-model
708
+ // preflight, breaker-tripped no-op) — those have 0 retries by
709
+ // definition.
710
+ retryCount: this.lastAttemptCount !== undefined
711
+ ? Math.max(0, this.lastAttemptCount - 1)
712
+ : retryCount,
691
713
  errorCategory: result === null || errorMsg !== undefined ? errorCategory : undefined,
692
714
  context: callCtx
693
715
  ? { file: callCtx.file, method: callCtx.method, cwe: callCtx.cwe, tier: callCtx.tier }
@@ -769,260 +791,275 @@ INFORMATION EXPOSURE (CWE-200/209) SPECIFIC:
769
791
  this.llmDisabled = true;
770
792
  return null;
771
793
  }
772
- // All LLM requests go through the shared throttled queue
794
+ // All LLM requests go through the shared throttled queue.
795
+ //
796
+ // cognium-ai#148 — `try/finally` captures the final `attemptIdx`
797
+ // for the outer `chatJSON` wrapper regardless of which `return`
798
+ // path inside the while-loop fires (success, parse_error, http
799
+ // error, timeout, connection_error, rate-limit/5xx budget exhaust,
800
+ // empty_response). Without this the per-call retry totals always
801
+ // reported 0.
773
802
  return llmQueue.add(async () => {
774
- while (true) {
775
- attemptIdx++;
776
- const attemptStart = Date.now();
777
- // On retry, request fewer tokens to reduce truncation risk
778
- const maxTokens = attempt > 0
779
- ? Math.min(phaseConfig.maxTokens, 4000)
780
- : phaseConfig.maxTokens;
781
- const controller = new AbortController();
782
- const timeoutMs = phaseConfig.timeout || 60000;
783
- const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
784
- let response;
785
- try {
786
- // #43 / #81: OpenAI reasoning models (gpt-5*, o[1-9]) reject
787
- // the gpt-4 request shape with HTTP 400 they need
788
- // `max_completion_tokens` and no `temperature`. Delegate to
789
- // the shared helper in `./config.ts` so the CWE benchmark
790
- // runner and other call sites stay in sync.
791
- const requestBody = buildChatCompletionBody(phaseConfig.model, [
792
- { role: 'system', content: systemPrompt },
793
- { role: 'user', content: userPrompt },
794
- ], { maxTokens, temperature: phaseConfig.temperature });
795
- response = await fetch(`${this.config.baseUrl}/chat/completions`, {
796
- method: 'POST',
797
- headers: {
798
- 'Content-Type': 'application/json',
799
- 'Authorization': `Bearer ${this.config.apiKey}`,
800
- },
801
- body: JSON.stringify(requestBody),
802
- signal: controller.signal,
803
- });
804
- clearTimeout(timeoutId);
805
- }
806
- catch (fetchError) {
807
- clearTimeout(timeoutId);
808
- // Connection-class errors mean the endpoint isn't running.
809
- // Trip the breaker immediately — don't burn time on retries.
810
- if (this.isConnectionError(fetchError)) {
811
- this.lastErrorCategory = 'connection_error';
812
- emitAttempt('connection_error', attemptStart);
813
- this.tripBreakerOnConnectionFailure(fetchError);
814
- return null;
803
+ try {
804
+ while (true) {
805
+ attemptIdx++;
806
+ const attemptStart = Date.now();
807
+ // On retry, request fewer tokens to reduce truncation risk
808
+ const maxTokens = attempt > 0
809
+ ? Math.min(phaseConfig.maxTokens, 4000)
810
+ : phaseConfig.maxTokens;
811
+ const controller = new AbortController();
812
+ const timeoutMs = phaseConfig.timeout || 60000;
813
+ const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
814
+ let response;
815
+ try {
816
+ // #43 / #81: OpenAI reasoning models (gpt-5*, o[1-9]) reject
817
+ // the gpt-4 request shape with HTTP 400 — they need
818
+ // `max_completion_tokens` and no `temperature`. Delegate to
819
+ // the shared helper in `./config.ts` so the CWE benchmark
820
+ // runner and other call sites stay in sync.
821
+ const requestBody = buildChatCompletionBody(phaseConfig.model, [
822
+ { role: 'system', content: systemPrompt },
823
+ { role: 'user', content: userPrompt },
824
+ ], { maxTokens, temperature: phaseConfig.temperature });
825
+ response = await fetch(`${this.config.baseUrl}/chat/completions`, {
826
+ method: 'POST',
827
+ headers: {
828
+ 'Content-Type': 'application/json',
829
+ 'Authorization': `Bearer ${this.config.apiKey}`,
830
+ },
831
+ body: JSON.stringify(requestBody),
832
+ signal: controller.signal,
833
+ });
834
+ clearTimeout(timeoutId);
815
835
  }
816
- if (fetchError instanceof Error && fetchError.name === 'AbortError') {
817
- console.error(`LLM call timed out (attempt ${attempt + 1}/${maxRetries + 1})`);
818
- if (attempt < maxRetries) {
819
- attempt++;
836
+ catch (fetchError) {
837
+ clearTimeout(timeoutId);
838
+ // Connection-class errors mean the endpoint isn't running.
839
+ // Trip the breaker immediately — don't burn time on retries.
840
+ if (this.isConnectionError(fetchError)) {
841
+ this.lastErrorCategory = 'connection_error';
842
+ emitAttempt('connection_error', attemptStart);
843
+ this.tripBreakerOnConnectionFailure(fetchError);
844
+ return null;
845
+ }
846
+ if (fetchError instanceof Error && fetchError.name === 'AbortError') {
847
+ console.error(`LLM call timed out (attempt ${attempt + 1}/${maxRetries + 1})`);
848
+ if (attempt < maxRetries) {
849
+ attempt++;
850
+ emitAttempt('timeout', attemptStart);
851
+ console.error('Retrying LLM call with reduced tokens...');
852
+ continue;
853
+ }
820
854
  emitAttempt('timeout', attemptStart);
821
- console.error('Retrying LLM call with reduced tokens...');
822
- continue;
855
+ this.lastErrorCategory = 'timeout';
823
856
  }
824
- emitAttempt('timeout', attemptStart);
825
- this.lastErrorCategory = 'timeout';
826
- }
827
- else {
828
- console.error('LLM fetch failed:', fetchError);
829
- if (attempt < maxRetries) {
830
- attempt++;
857
+ else {
858
+ console.error('LLM fetch failed:', fetchError);
859
+ if (attempt < maxRetries) {
860
+ attempt++;
861
+ emitAttempt('connection_error', attemptStart);
862
+ console.error('Retrying LLM call due to network error...');
863
+ continue;
864
+ }
831
865
  emitAttempt('connection_error', attemptStart);
832
- console.error('Retrying LLM call due to network error...');
833
- continue;
866
+ this.lastErrorCategory = 'connection_error';
834
867
  }
835
- emitAttempt('connection_error', attemptStart);
836
- this.lastErrorCategory = 'connection_error';
837
- }
838
- this.trackFailure();
839
- return null;
840
- }
841
- if (!response.ok) {
842
- // #12: rate-limit-aware retry. Honor Retry-After, sleep, retry
843
- // inline — without bumping `attempt` (which reduces tokens —
844
- // wrong response to throttling) and without `trackFailure`
845
- // (rate limits are transient, not endpoint failures).
846
- if (response.status === 429 && rateLimitAttempt < maxRateLimitRetries) {
847
- const sleepMs = parseRetryAfterMs(response.headers.get('Retry-After'), rateLimitAttempt);
848
- console.error(`LLM rate limited (HTTP 429); sleeping ${sleepMs}ms before retry ${rateLimitAttempt + 1}/${maxRateLimitRetries}`);
849
- emitAttempt('rate_limited', attemptStart, {
850
- httpStatus: 429,
851
- backoffMs: sleepMs,
852
- });
853
- await sleep(sleepMs);
854
- rateLimitAttempt++;
855
- continue;
868
+ this.trackFailure();
869
+ return null;
856
870
  }
857
- // #96: transient 5xx retry. 500/502/503/504 are usually
858
- // proxy/upstream hiccups; reuse the rate-limit backoff curve
859
- // (Retry-After-honoring with exp-backoff fallback) but with
860
- // a smaller, independent budget so a flaky proxy doesn't
861
- // burn the 429 budget. Don't reduce tokens or call
862
- // `trackFailure` same reasoning as 429.
863
- if (TRANSIENT_5XX_STATUSES.has(response.status) &&
864
- transient5xxAttempt < maxTransient5xxRetries) {
865
- const sleepMs = parseRetryAfterMs(response.headers.get('Retry-After'), transient5xxAttempt);
866
- console.error(`LLM transient server error (HTTP ${response.status}); ` +
867
- `sleeping ${sleepMs}ms before retry ${transient5xxAttempt + 1}/${maxTransient5xxRetries}`);
868
- emitAttempt('transient_server_error', attemptStart, {
871
+ if (!response.ok) {
872
+ // #12: rate-limit-aware retry. Honor Retry-After, sleep, retry
873
+ // inline without bumping `attempt` (which reduces tokens —
874
+ // wrong response to throttling) and without `trackFailure`
875
+ // (rate limits are transient, not endpoint failures).
876
+ if (response.status === 429 && rateLimitAttempt < maxRateLimitRetries) {
877
+ const sleepMs = parseRetryAfterMs(response.headers.get('Retry-After'), rateLimitAttempt);
878
+ console.error(`LLM rate limited (HTTP 429); sleeping ${sleepMs}ms before retry ${rateLimitAttempt + 1}/${maxRateLimitRetries}`);
879
+ emitAttempt('rate_limited', attemptStart, {
880
+ httpStatus: 429,
881
+ backoffMs: sleepMs,
882
+ });
883
+ await sleep(sleepMs);
884
+ rateLimitAttempt++;
885
+ continue;
886
+ }
887
+ // #96: transient 5xx retry. 500/502/503/504 are usually
888
+ // proxy/upstream hiccups; reuse the rate-limit backoff curve
889
+ // (Retry-After-honoring with exp-backoff fallback) but with
890
+ // a smaller, independent budget so a flaky proxy doesn't
891
+ // burn the 429 budget. Don't reduce tokens or call
892
+ // `trackFailure` — same reasoning as 429.
893
+ if (TRANSIENT_5XX_STATUSES.has(response.status) &&
894
+ transient5xxAttempt < maxTransient5xxRetries) {
895
+ const sleepMs = parseRetryAfterMs(response.headers.get('Retry-After'), transient5xxAttempt);
896
+ console.error(`LLM transient server error (HTTP ${response.status}); ` +
897
+ `sleeping ${sleepMs}ms before retry ${transient5xxAttempt + 1}/${maxTransient5xxRetries}`);
898
+ emitAttempt('transient_server_error', attemptStart, {
899
+ httpStatus: response.status,
900
+ backoffMs: sleepMs,
901
+ });
902
+ await sleep(sleepMs);
903
+ transient5xxAttempt++;
904
+ continue;
905
+ }
906
+ // #43: log the response body too, not just the status code.
907
+ // OpenAI's 400s contain useful messages like "Unsupported
908
+ // parameter: 'temperature'" or "Use 'max_completion_tokens'
909
+ // instead of 'max_tokens'" that would otherwise be invisible.
910
+ let bodySnippet = '';
911
+ try {
912
+ bodySnippet = (await response.text()).slice(0, 300);
913
+ }
914
+ catch {
915
+ // ignore — body may have been consumed or stream errored
916
+ }
917
+ console.error(`LLM call failed: HTTP ${response.status}${bodySnippet ? ' — ' + bodySnippet : ''}`);
918
+ let terminalCategory;
919
+ if (response.status === 429) {
920
+ terminalCategory = 'rate_limited';
921
+ }
922
+ else if (TRANSIENT_5XX_STATUSES.has(response.status)) {
923
+ terminalCategory = 'transient_server_error';
924
+ }
925
+ else {
926
+ terminalCategory = 'http_error';
927
+ }
928
+ this.lastErrorCategory = terminalCategory;
929
+ emitAttempt(terminalCategory, attemptStart, {
869
930
  httpStatus: response.status,
870
- backoffMs: sleepMs,
931
+ responseSnippet: bodySnippet || undefined,
871
932
  });
872
- await sleep(sleepMs);
873
- transient5xxAttempt++;
874
- continue;
933
+ this.trackFailure();
934
+ return null;
875
935
  }
876
- // #43: log the response body too, not just the status code.
877
- // OpenAI's 400s contain useful messages like "Unsupported
878
- // parameter: 'temperature'" or "Use 'max_completion_tokens'
879
- // instead of 'max_tokens'" that would otherwise be invisible.
880
- let bodySnippet = '';
881
- try {
882
- bodySnippet = (await response.text()).slice(0, 300);
936
+ // Success reset failure counter
937
+ this.resetFailures();
938
+ const data = await response.json();
939
+ const rawContent = data.choices?.[0]?.message?.content;
940
+ if (data.usage) {
941
+ this.lastUsage = {
942
+ inputTokens: data.usage.prompt_tokens,
943
+ outputTokens: data.usage.completion_tokens,
944
+ };
883
945
  }
884
- catch {
885
- // ignore body may have been consumed or stream errored
946
+ // Handle case where LLM returns JSON object directly (not as string)
947
+ if (rawContent && typeof rawContent === 'object') {
948
+ const responseChars = JSON.stringify(rawContent).length;
949
+ emitAttempt('success', attemptStart, { responseChars, httpStatus: response.status });
950
+ return rawContent;
886
951
  }
887
- console.error(`LLM call failed: HTTP ${response.status}${bodySnippet ? ' ' + bodySnippet : ''}`);
888
- let terminalCategory;
889
- if (response.status === 429) {
890
- terminalCategory = 'rate_limited';
952
+ // #96: strip `<think>...</think>` reasoning blocks emitted by
953
+ // thinking models (deepseek-r1, o1, o3, qwen3.6 thinking
954
+ // variants). The Ollama OpenAI-compat endpoint forwards them
955
+ // unchanged and they break the downstream JSON parser.
956
+ // Centralized here so every call site benefits — not just the
957
+ // benchmark runner.
958
+ const content = typeof rawContent === 'string' ? stripThinkBlocks(rawContent) : '';
959
+ // #96: empty-response detection. Some models (notably
960
+ // qwen3.6:35b-a3b on certain prompts — see CLAUDE.md MoE
961
+ // routing note) return HTTP 200 with empty `content`. The
962
+ // previous code fell through to JSON.parse('') which throws,
963
+ // burned a token-reduced retry, then returned null with no
964
+ // signal in the JSONL log. Now: short-circuit, categorize, and
965
+ // do NOT retry — empty responses are deterministic per prompt,
966
+ // so retrying with the same input just wastes wall-clock.
967
+ if (content === '') {
968
+ console.error('LLM returned empty content (after <think> strip) — no retry');
969
+ this.lastErrorCategory = 'empty_response';
970
+ emitAttempt('empty_response', attemptStart, { httpStatus: response.status });
971
+ this.trackFailure();
972
+ return null;
891
973
  }
892
- else if (TRANSIENT_5XX_STATUSES.has(response.status)) {
893
- terminalCategory = 'transient_server_error';
974
+ // Parse JSON from response (handle markdown code blocks)
975
+ let jsonStr = content;
976
+ const jsonMatch = content.match(/```(?:json)?\s*([\s\S]*?)```/);
977
+ if (jsonMatch) {
978
+ jsonStr = jsonMatch[1];
894
979
  }
895
- else {
896
- terminalCategory = 'http_error';
980
+ // Fix common JSON issues from LLM
981
+ jsonStr = jsonStr.trim();
982
+ // #37: small / quantized models (llama3.2:3b, qwen2.5-coder:1.5b)
983
+ // emit double-braced JSON like `{{ "key": ... }}` — likely
984
+ // Jinja-template syntax bleeding from training data. Strip the
985
+ // outer extra brace pair (or just the leading `{{` if the tail
986
+ // got truncated, which `tryRecoverTruncatedJSON` then completes).
987
+ if (jsonStr.startsWith('{{')) {
988
+ jsonStr = jsonStr.slice(1);
989
+ if (jsonStr.endsWith('}}')) {
990
+ jsonStr = jsonStr.slice(0, -1);
991
+ }
897
992
  }
898
- this.lastErrorCategory = terminalCategory;
899
- emitAttempt(terminalCategory, attemptStart, {
900
- httpStatus: response.status,
901
- responseSnippet: bodySnippet || undefined,
902
- });
903
- this.trackFailure();
904
- return null;
905
- }
906
- // Success — reset failure counter
907
- this.resetFailures();
908
- const data = await response.json();
909
- const rawContent = data.choices?.[0]?.message?.content;
910
- if (data.usage) {
911
- this.lastUsage = {
912
- inputTokens: data.usage.prompt_tokens,
913
- outputTokens: data.usage.completion_tokens,
993
+ // Fix word-numbers (e.g., "0. nine" -> "0.9")
994
+ const wordToNum = {
995
+ 'zero': '0', 'one': '1', 'two': '2', 'three': '3', 'four': '4',
996
+ 'five': '5', 'six': '6', 'seven': '7', 'eight': '8', 'nine': '9',
914
997
  };
915
- }
916
- // Handle case where LLM returns JSON object directly (not as string)
917
- if (rawContent && typeof rawContent === 'object') {
918
- const responseChars = JSON.stringify(rawContent).length;
919
- emitAttempt('success', attemptStart, { responseChars, httpStatus: response.status });
920
- return rawContent;
921
- }
922
- // #96: strip `<think>...</think>` reasoning blocks emitted by
923
- // thinking models (deepseek-r1, o1, o3, qwen3.6 thinking
924
- // variants). The Ollama OpenAI-compat endpoint forwards them
925
- // unchanged and they break the downstream JSON parser.
926
- // Centralized here so every call site benefits — not just the
927
- // benchmark runner.
928
- const content = typeof rawContent === 'string' ? stripThinkBlocks(rawContent) : '';
929
- // #96: empty-response detection. Some models (notably
930
- // qwen3.6:35b-a3b on certain prompts — see CLAUDE.md MoE
931
- // routing note) return HTTP 200 with empty `content`. The
932
- // previous code fell through to JSON.parse('') which throws,
933
- // burned a token-reduced retry, then returned null with no
934
- // signal in the JSONL log. Now: short-circuit, categorize, and
935
- // do NOT retry — empty responses are deterministic per prompt,
936
- // so retrying with the same input just wastes wall-clock.
937
- if (content === '') {
938
- console.error('LLM returned empty content (after <think> strip) — no retry');
939
- this.lastErrorCategory = 'empty_response';
940
- emitAttempt('empty_response', attemptStart, { httpStatus: response.status });
941
- this.trackFailure();
942
- return null;
943
- }
944
- // Parse JSON from response (handle markdown code blocks)
945
- let jsonStr = content;
946
- const jsonMatch = content.match(/```(?:json)?\s*([\s\S]*?)```/);
947
- if (jsonMatch) {
948
- jsonStr = jsonMatch[1];
949
- }
950
- // Fix common JSON issues from LLM
951
- jsonStr = jsonStr.trim();
952
- // #37: small / quantized models (llama3.2:3b, qwen2.5-coder:1.5b)
953
- // emit double-braced JSON like `{{ "key": ... }}` — likely
954
- // Jinja-template syntax bleeding from training data. Strip the
955
- // outer extra brace pair (or just the leading `{{` if the tail
956
- // got truncated, which `tryRecoverTruncatedJSON` then completes).
957
- if (jsonStr.startsWith('{{')) {
958
- jsonStr = jsonStr.slice(1);
959
- if (jsonStr.endsWith('}}')) {
960
- jsonStr = jsonStr.slice(0, -1);
998
+ jsonStr = jsonStr.replace(/(\d+)\.\s*(zero|one|two|three|four|five|six|seven|eight|nine)/gi, (_, int, word) => `${int}.${wordToNum[word.toLowerCase()]}`);
999
+ // Fix trailing decimal points followed by any non-digit
1000
+ jsonStr = jsonStr.replace(/(\d+)\.\s*([,}\]\n\r])/g, '$1.0$2');
1001
+ // Fix decimal points followed by space then digit
1002
+ jsonStr = jsonStr.replace(/(\d+)\.\s+(\d)/g, '$1.$2');
1003
+ // Fix missing quotes around string values that look like identifiers
1004
+ jsonStr = jsonStr.replace(/:\s*([A-Z_]+)\s*([,}\]])/g, ': "$1"$2');
1005
+ try {
1006
+ const parsed = JSON.parse(jsonStr);
1007
+ emitAttempt('success', attemptStart, {
1008
+ responseChars: content.length,
1009
+ httpStatus: response.status,
1010
+ });
1011
+ return parsed;
961
1012
  }
962
- }
963
- // Fix word-numbers (e.g., "0. nine" -> "0.9")
964
- const wordToNum = {
965
- 'zero': '0', 'one': '1', 'two': '2', 'three': '3', 'four': '4',
966
- 'five': '5', 'six': '6', 'seven': '7', 'eight': '8', 'nine': '9',
967
- };
968
- jsonStr = jsonStr.replace(/(\d+)\.\s*(zero|one|two|three|four|five|six|seven|eight|nine)/gi, (_, int, word) => `${int}.${wordToNum[word.toLowerCase()]}`);
969
- // Fix trailing decimal points followed by any non-digit
970
- jsonStr = jsonStr.replace(/(\d+)\.\s*([,}\]\n\r])/g, '$1.0$2');
971
- // Fix decimal points followed by space then digit
972
- jsonStr = jsonStr.replace(/(\d+)\.\s+(\d)/g, '$1.$2');
973
- // Fix missing quotes around string values that look like identifiers
974
- jsonStr = jsonStr.replace(/:\s*([A-Z_]+)\s*([,}\]])/g, ': "$1"$2');
975
- try {
976
- const parsed = JSON.parse(jsonStr);
977
- emitAttempt('success', attemptStart, {
978
- responseChars: content.length,
979
- httpStatus: response.status,
980
- });
981
- return parsed;
982
- }
983
- catch {
984
- // Try to recover truncated JSON by completing brackets
985
- const recovered = this.tryRecoverTruncatedJSON(jsonStr);
986
- if (recovered) {
987
- try {
988
- const parsed = JSON.parse(recovered);
1013
+ catch {
1014
+ // Try to recover truncated JSON by completing brackets
1015
+ const recovered = this.tryRecoverTruncatedJSON(jsonStr);
1016
+ if (recovered) {
1017
+ try {
1018
+ const parsed = JSON.parse(recovered);
1019
+ emitAttempt('success', attemptStart, {
1020
+ responseChars: content.length,
1021
+ httpStatus: response.status,
1022
+ });
1023
+ return parsed;
1024
+ }
1025
+ catch {
1026
+ // Recovery failed, fall through to verification recovery
1027
+ }
1028
+ }
1029
+ // Try to extract verification response from truncated JSON
1030
+ const verificationRecovered = this.tryRecoverVerificationJSON(jsonStr);
1031
+ if (verificationRecovered) {
989
1032
  emitAttempt('success', attemptStart, {
990
1033
  responseChars: content.length,
991
1034
  httpStatus: response.status,
992
1035
  });
993
- return parsed;
1036
+ return verificationRecovered;
994
1037
  }
995
- catch {
996
- // Recovery failed, fall through to verification recovery
1038
+ console.error('Failed to parse JSON:', jsonStr.substring(0, 100));
1039
+ if (attempt < maxRetries) {
1040
+ attempt++;
1041
+ emitAttempt('parse_error', attemptStart, {
1042
+ httpStatus: response.status,
1043
+ responseSnippet: jsonStr.slice(0, 300),
1044
+ });
1045
+ console.error('Retrying LLM call with reduced tokens...');
1046
+ continue;
997
1047
  }
998
- }
999
- // Try to extract verification response from truncated JSON
1000
- const verificationRecovered = this.tryRecoverVerificationJSON(jsonStr);
1001
- if (verificationRecovered) {
1002
- emitAttempt('success', attemptStart, {
1003
- responseChars: content.length,
1004
- httpStatus: response.status,
1005
- });
1006
- return verificationRecovered;
1007
- }
1008
- console.error('Failed to parse JSON:', jsonStr.substring(0, 100));
1009
- if (attempt < maxRetries) {
1010
- attempt++;
1048
+ this.lastErrorCategory = 'parse_error';
1011
1049
  emitAttempt('parse_error', attemptStart, {
1012
1050
  httpStatus: response.status,
1013
1051
  responseSnippet: jsonStr.slice(0, 300),
1014
1052
  });
1015
- console.error('Retrying LLM call with reduced tokens...');
1016
- continue;
1053
+ return null;
1017
1054
  }
1018
- this.lastErrorCategory = 'parse_error';
1019
- emitAttempt('parse_error', attemptStart, {
1020
- httpStatus: response.status,
1021
- responseSnippet: jsonStr.slice(0, 300),
1022
- });
1023
- return null;
1024
1055
  }
1025
1056
  }
1057
+ finally {
1058
+ // cognium-ai#148 — capture final attemptIdx for the outer
1059
+ // chatJSON wrapper. Runs after every `return` inside the
1060
+ // while-loop above (success and failure paths alike).
1061
+ this.lastAttemptCount = attemptIdx;
1062
+ }
1026
1063
  });
1027
1064
  }
1028
1065
  /**