@dan-ai-studio/dshopencodego 0.1.62 → 0.1.64

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/lib/index.js CHANGED
@@ -365,17 +365,17 @@ function contentText(content, separator = "\n") {
365
365
  }
366
366
  function getSystemMessageText(message) {
367
367
  const parts = [contentText(message.content)];
368
- for (const text of Object.values(message.sections ?? {})) {
369
- if (text !== null)
370
- parts.push(text);
368
+ for (const text2 of Object.values(message.sections ?? {})) {
369
+ if (text2 !== null)
370
+ parts.push(text2);
371
371
  }
372
372
  return parts.filter((part) => part.length > 0).join("\n\n");
373
373
  }
374
374
  function renderSystemMessageUpdate(message) {
375
375
  const parts = [];
376
- const text = contentText(message.content);
377
- if (text.length > 0)
378
- parts.push(text);
376
+ const text2 = contentText(message.content);
377
+ if (text2.length > 0)
378
+ parts.push(text2);
379
379
  for (const [name2, value] of Object.entries(message.sections ?? {})) {
380
380
  parts.push(value === null ? `Removed system prompt section "${name2}".` : `Updated system prompt section "${name2}":
381
381
 
@@ -433,9 +433,9 @@ function getCurrentSystemMessage(messages) {
433
433
  if (!isSystemMessage(message))
434
434
  continue;
435
435
  timestamp ??= message.timestamp;
436
- const text = contentText(message.content);
437
- if (text.length > 0)
438
- content.push(text);
436
+ const text2 = contentText(message.content);
437
+ if (text2.length > 0)
438
+ content.push(text2);
439
439
  for (const [name2, value] of Object.entries(message.sections ?? {})) {
440
440
  if (value === null)
441
441
  sections.delete(name2);
@@ -884,9 +884,9 @@ var init_values = __esm({
884
884
  }
885
885
  return n;
886
886
  };
887
- safeJSON = (text) => {
887
+ safeJSON = (text2) => {
888
888
  try {
889
- return JSON.parse(text);
889
+ return JSON.parse(text2);
890
890
  } catch (err) {
891
891
  return void 0;
892
892
  }
@@ -1616,12 +1616,12 @@ function requireSecureTokenEndpoint(baseURL) {
1616
1616
  throw new WorkloadIdentityError(`Refusing to send credential over non-https token endpoint "${baseURL}"`);
1617
1617
  }
1618
1618
  async function parseTokenResponse(resp, requestId) {
1619
- const text = await readLimitedText(resp);
1619
+ const text2 = await readLimitedText(resp);
1620
1620
  let data;
1621
1621
  try {
1622
- data = JSON.parse(text);
1622
+ data = JSON.parse(text2);
1623
1623
  } catch {
1624
- throw new WorkloadIdentityError(`Token endpoint returned non-JSON response (status ${resp.status})`, resp.status, redactSensitive(text), requestId);
1624
+ throw new WorkloadIdentityError(`Token endpoint returned non-JSON response (status ${resp.status})`, resp.status, redactSensitive(text2), requestId);
1625
1625
  }
1626
1626
  if (!data.access_token) {
1627
1627
  throw new WorkloadIdentityError(`Token endpoint response missing access_token: ${JSON.stringify(redactSensitive(data))}`, resp.status, redactSensitive(data), requestId);
@@ -2315,8 +2315,8 @@ function oidcFederationProvider(config) {
2315
2315
  }
2316
2316
  const requestId = resp.headers.get("Request-Id");
2317
2317
  if (!resp.ok) {
2318
- const text = await resp.text().catch(() => "");
2319
- const redacted = redactSensitive(text);
2318
+ const text2 = await resp.text().catch(() => "");
2319
+ const redacted = redactSensitive(text2);
2320
2320
  let hint = "";
2321
2321
  if (resp.status === 401) {
2322
2322
  const hintMiddle = config.workspaceId ? "" : "If your federation rule is scoped to multiple workspaces, set the ANTHROPIC_WORKSPACE_ID environment variable, the 'workspace_id' config key, or the `workspaceId` option. ";
@@ -2395,8 +2395,8 @@ function userOAuthProvider(config) {
2395
2395
  }
2396
2396
  const requestId = resp.headers.get("Request-Id");
2397
2397
  if (!resp.ok) {
2398
- const text = await resp.text().catch(() => "");
2399
- throw new WorkloadIdentityError(`User OAuth refresh failed (HTTP ${resp.status}): ${redactSensitive(text)}`, resp.status, redactSensitive(text), requestId);
2398
+ const text2 = await resp.text().catch(() => "");
2399
+ throw new WorkloadIdentityError(`User OAuth refresh failed (HTTP ${resp.status}): ${redactSensitive(text2)}`, resp.status, redactSensitive(text2), requestId);
2400
2400
  }
2401
2401
  const data = await parseTokenResponse(resp, requestId);
2402
2402
  const expiresIn = Number(data.expires_in);
@@ -2923,8 +2923,8 @@ async function defaultParseResponse(client, props) {
2923
2923
  const json = await response.json();
2924
2924
  return addResponseIDs(json, response);
2925
2925
  }
2926
- const text = await response.text();
2927
- return text;
2926
+ const text2 = await response.text();
2927
+ return text2;
2928
2928
  })().finally(() => {
2929
2929
  if (!props.options.stream && !props.options.__binaryResponse) {
2930
2930
  releaseRequestSignal(props.controller);
@@ -8198,15 +8198,15 @@ function betaEditTool(ctx) {
8198
8198
  throw e;
8199
8199
  throw new ToolError(`edit: ${fsErrorMessage(e, file_path)}`);
8200
8200
  }
8201
- const count = data.split(old_string).length - 1;
8202
- if (count === 0)
8201
+ const count2 = data.split(old_string).length - 1;
8202
+ if (count2 === 0)
8203
8203
  throw new ToolError(`edit: old_string not found in ${file_path}`);
8204
8204
  let updated;
8205
8205
  if (replace_all) {
8206
8206
  updated = data.split(old_string).join(new_string);
8207
8207
  } else {
8208
- if (count > 1)
8209
- throw new ToolError(`edit: old_string appears ${count} times in ${file_path} (must be unique)`);
8208
+ if (count2 > 1)
8209
+ throw new ToolError(`edit: old_string appears ${count2} times in ${file_path} (must be unique)`);
8210
8210
  updated = data.replace(old_string, () => new_string);
8211
8211
  }
8212
8212
  try {
@@ -8214,7 +8214,7 @@ function betaEditTool(ctx) {
8214
8214
  } catch (e) {
8215
8215
  throw new ToolError(`edit: write: ${fsErrorMessage(e, file_path)}`);
8216
8216
  }
8217
- return `edited ${file_path} (${replace_all ? count : 1} replacement(s))`;
8217
+ return `edited ${file_path} (${replace_all ? count2 : 1} replacement(s))`;
8218
8218
  }
8219
8219
  });
8220
8220
  }
@@ -18327,8 +18327,8 @@ var init_provider_retry = __esm({
18327
18327
  });
18328
18328
 
18329
18329
  // node_modules/@earendil-works/pi-ai/dist/utils/sanitize-unicode.js
18330
- function sanitizeSurrogates(text) {
18331
- return text.replace(/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g, "");
18330
+ function sanitizeSurrogates(text2) {
18331
+ return text2.replace(/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g, "");
18332
18332
  }
18333
18333
  var init_sanitize_unicode = __esm({
18334
18334
  "node_modules/@earendil-works/pi-ai/dist/utils/sanitize-unicode.js"() {
@@ -18613,8 +18613,8 @@ function estimateTextAndImageContentChars(content) {
18613
18613
  chars += block.type === "text" ? block.text.length : ESTIMATED_IMAGE_CHARS;
18614
18614
  return chars;
18615
18615
  }
18616
- function estimateTextTokens(text) {
18617
- return Math.ceil(text.length / CHARS_PER_TOKEN);
18616
+ function estimateTextTokens(text2) {
18617
+ return Math.ceil(text2.length / CHARS_PER_TOKEN);
18618
18618
  }
18619
18619
  function estimateTextAndImageContentTokens(content) {
18620
18620
  return Math.ceil(estimateTextAndImageContentChars(content) / CHARS_PER_TOKEN);
@@ -19094,9 +19094,9 @@ function decodeSseLine(line, state2) {
19094
19094
  }
19095
19095
  return null;
19096
19096
  }
19097
- function nextLineBreakIndex(text) {
19098
- const carriageReturnIndex = text.indexOf("\r");
19099
- const newlineIndex = text.indexOf("\n");
19097
+ function nextLineBreakIndex(text2) {
19098
+ const carriageReturnIndex = text2.indexOf("\r");
19099
+ const newlineIndex = text2.indexOf("\n");
19100
19100
  if (carriageReturnIndex === -1) {
19101
19101
  return newlineIndex;
19102
19102
  }
@@ -19105,18 +19105,18 @@ function nextLineBreakIndex(text) {
19105
19105
  }
19106
19106
  return Math.min(carriageReturnIndex, newlineIndex);
19107
19107
  }
19108
- function consumeLine(text) {
19109
- const lineBreakIndex = nextLineBreakIndex(text);
19108
+ function consumeLine(text2) {
19109
+ const lineBreakIndex = nextLineBreakIndex(text2);
19110
19110
  if (lineBreakIndex === -1) {
19111
19111
  return null;
19112
19112
  }
19113
19113
  let nextIndex = lineBreakIndex + 1;
19114
- if (text[lineBreakIndex] === "\r" && text[nextIndex] === "\n") {
19114
+ if (text2[lineBreakIndex] === "\r" && text2[nextIndex] === "\n") {
19115
19115
  nextIndex += 1;
19116
19116
  }
19117
19117
  return {
19118
- line: text.slice(0, lineBreakIndex),
19119
- rest: text.slice(nextIndex)
19118
+ line: text2.slice(0, lineBreakIndex),
19119
+ rest: text2.slice(nextIndex)
19120
19120
  };
19121
19121
  }
19122
19122
  async function* iterateSseMessages(body, signal) {
@@ -19448,10 +19448,10 @@ function convertMessages(transformedMessages, isOAuthToken2, cacheControl, allow
19448
19448
  for (let i = 0; i < transformedMessages.length; i++) {
19449
19449
  const msg = transformedMessages[i];
19450
19450
  if (msg.role === "system") {
19451
- const text = renderSystemMessageUpdate(msg);
19451
+ const text2 = renderSystemMessageUpdate(msg);
19452
19452
  const blocks = [];
19453
- if (text.length > 0)
19454
- blocks.push({ type: "text", text: sanitizeSurrogates(text) });
19453
+ if (text2.length > 0)
19454
+ blocks.push({ type: "text", text: sanitizeSurrogates(text2) });
19455
19455
  if (convertToolDefinitions) {
19456
19456
  const added = msg.toolsAdded ?? [];
19457
19457
  const redefined = new Set(added.map((tool) => tool.name));
@@ -20378,9 +20378,9 @@ var init_values2 = __esm({
20378
20378
  }
20379
20379
  return n;
20380
20380
  };
20381
- safeJSON2 = (text) => {
20381
+ safeJSON2 = (text2) => {
20382
20382
  try {
20383
- return JSON.parse(text);
20383
+ return JSON.parse(text2);
20384
20384
  } catch (err) {
20385
20385
  return void 0;
20386
20386
  }
@@ -21539,8 +21539,8 @@ async function defaultParseResponse2(client, props) {
21539
21539
  jsonBodyLength = bodyText.length;
21540
21540
  return addRequestID(json, response);
21541
21541
  }
21542
- const text = await response.text();
21543
- return text;
21542
+ const text2 = await response.text();
21543
+ return text2;
21544
21544
  })().catch((error) => {
21545
21545
  throw asAbortError(error, props.controller.signal);
21546
21546
  });
@@ -21728,19 +21728,19 @@ var init_detect_platform2 = __esm({
21728
21728
  });
21729
21729
 
21730
21730
  // node_modules/openai/internal/request-options.mjs
21731
- function observeJSONRequestBody(body, observer) {
21731
+ function observeJSONRequestBody(body, observer2) {
21732
21732
  let observers = jsonRequestBodyObservers.get(body);
21733
21733
  if (!observers) {
21734
21734
  observers = /* @__PURE__ */ new Set();
21735
21735
  jsonRequestBodyObservers.set(body, observers);
21736
21736
  }
21737
- observers.add(observer);
21737
+ observers.add(observer2);
21738
21738
  return () => {
21739
21739
  const active = jsonRequestBodyObservers.get(body);
21740
21740
  if (!active) {
21741
21741
  return;
21742
21742
  }
21743
- active.delete(observer);
21743
+ active.delete(observer2);
21744
21744
  if (active.size === 0) {
21745
21745
  jsonRequestBodyObservers.delete(body);
21746
21746
  }
@@ -21759,16 +21759,16 @@ var init_request_options2 = __esm({
21759
21759
  const active = [...observers];
21760
21760
  encoded = JSON.stringify(body, function(key, value) {
21761
21761
  let observed = value;
21762
- for (const observer of active) {
21763
- const replacement = observer.value(this, key, observed);
21762
+ for (const observer2 of active) {
21763
+ const replacement = observer2.value(this, key, observed);
21764
21764
  if (replacement !== void 0) {
21765
21765
  observed = replacement;
21766
21766
  }
21767
21767
  }
21768
21768
  return observed;
21769
21769
  });
21770
- for (const observer of active) {
21771
- observer.complete();
21770
+ for (const observer2 of active) {
21771
+ observer2.complete();
21772
21772
  }
21773
21773
  }
21774
21774
  return {
@@ -33412,14 +33412,14 @@ function isPrimitiveAssistantStreamArrayDelta(accumulator, delta) {
33412
33412
  return delta.every(isPrimitiveAssistantStreamValue) && accumulator.every(isPrimitiveAssistantStreamValue);
33413
33413
  }
33414
33414
  function countOwnAssistantStreamArrayEntries(accumulator) {
33415
- let count = 0;
33415
+ let count2 = 0;
33416
33416
  for (const key of Object.keys(accumulator)) {
33417
33417
  const index = Number(key);
33418
33418
  if (Number.isSafeInteger(index) && index >= 0 && index < accumulator.length && String(index) === key) {
33419
- count += 1;
33419
+ count2 += 1;
33420
33420
  }
33421
33421
  }
33422
- return count;
33422
+ return count2;
33423
33423
  }
33424
33424
  function getAssistantStreamArrayOwnEntryCount(accumulator, enforceSparseHoleBudget, cachedState) {
33425
33425
  if (!enforceSparseHoleBudget) {
@@ -36481,27 +36481,27 @@ function getOutputText(context, output) {
36481
36481
  if (output.type !== "message") {
36482
36482
  return "";
36483
36483
  }
36484
- let text = "";
36484
+ let text2 = "";
36485
36485
  for (const content of output.content) {
36486
36486
  if (content.type === "output_text") {
36487
- text += content.text;
36487
+ text2 += content.text;
36488
36488
  }
36489
36489
  }
36490
- context.outputTextLengths.set(output, text.length);
36491
- return text;
36490
+ context.outputTextLengths.set(output, text2.length);
36491
+ return text2;
36492
36492
  }
36493
36493
  function ensureCanonicalOutputText(context, snapshot2) {
36494
36494
  if (context.canonicalSnapshot === snapshot2) {
36495
36495
  return;
36496
36496
  }
36497
36497
  const outputTextIndex = new OutputTextIndex();
36498
- let text = "";
36498
+ let text2 = "";
36499
36499
  for (const output of snapshot2.output) {
36500
36500
  const outputText = getOutputText(context, output);
36501
- text += outputText;
36501
+ text2 += outputText;
36502
36502
  outputTextIndex.append(outputText.length);
36503
36503
  }
36504
- snapshot2.output_text = text;
36504
+ snapshot2.output_text = text2;
36505
36505
  context.outputTextIndex = outputTextIndex;
36506
36506
  context.canonicalSnapshot = snapshot2;
36507
36507
  }
@@ -36802,12 +36802,12 @@ function accumulateOutputItemEvent(event, snapshot2, context) {
36802
36802
  snapshot2.output.push(output);
36803
36803
  addOutputItemIdentities(identityIndex.identities, identities);
36804
36804
  identityIndex.length = snapshot2.output.length;
36805
- const text = getOutputText(context, output);
36805
+ const text2 = getOutputText(context, output);
36806
36806
  if (context.canonicalSnapshot === snapshot2) {
36807
- context.outputTextIndex.append(text.length);
36807
+ context.outputTextIndex.append(text2.length);
36808
36808
  }
36809
- if (text) {
36810
- snapshot2.output_text += text;
36809
+ if (text2) {
36810
+ snapshot2.output_text += text2;
36811
36811
  }
36812
36812
  return true;
36813
36813
  }
@@ -40289,10 +40289,10 @@ function formatProviderError(norm, prefix) {
40289
40289
  }
40290
40290
  return prefix !== void 0 ? `${prefix} (${norm.status}): ${norm.body}` : `${norm.status}: ${norm.body}`;
40291
40291
  }
40292
- function truncateErrorText(text, maxChars) {
40293
- if (text.length <= maxChars)
40294
- return text;
40295
- return `${text.slice(0, maxChars)}... [truncated ${text.length - maxChars} chars]`;
40292
+ function truncateErrorText(text2, maxChars) {
40293
+ if (text2.length <= maxChars)
40294
+ return text2;
40295
+ return `${text2.slice(0, maxChars)}... [truncated ${text2.length - maxChars} chars]`;
40296
40296
  }
40297
40297
  function safeJsonStringify2(value) {
40298
40298
  try {
@@ -40810,9 +40810,9 @@ function convertMessages2(model, context, compat, options) {
40810
40810
  };
40811
40811
  params.push(kimiToolMessage);
40812
40812
  }
40813
- const text = i === 0 ? getSystemMessageText(msg) : renderSystemMessageUpdate(msg);
40814
- if (text.length > 0) {
40815
- params.push({ role: instructionRole, content: sanitizeSurrogates(text) });
40813
+ const text2 = i === 0 ? getSystemMessageText(msg) : renderSystemMessageUpdate(msg);
40814
+ if (text2.length > 0) {
40815
+ params.push({ role: instructionRole, content: sanitizeSurrogates(text2) });
40816
40816
  }
40817
40817
  } else if (msg.role === "user") {
40818
40818
  if (typeof msg.content === "string") {
@@ -41623,9 +41623,9 @@ function convertResponsesMessages(model, context, allowedToolCallProviders, opti
41623
41623
  if (!isLeadingSystemMessage)
41624
41624
  appendSystemToolAdditions(msg, `system:${msgIndex}`);
41625
41625
  if (!isLeadingSystemMessage || includeInitialSystemMessage) {
41626
- const text = isLeadingSystemMessage ? getSystemMessageText(msg) : renderSystemMessageUpdate(msg);
41627
- if (text.length > 0) {
41628
- messages.push({ role: instructionRole, content: sanitizeSurrogates(text) });
41626
+ const text2 = isLeadingSystemMessage ? getSystemMessageText(msg) : renderSystemMessageUpdate(msg);
41627
+ if (text2.length > 0) {
41628
+ messages.push({ role: instructionRole, content: sanitizeSurrogates(text2) });
41629
41629
  }
41630
41630
  }
41631
41631
  } else if (msg.role === "user") {
@@ -63484,12 +63484,12 @@ var require_cache_handler = __commonJS({
63484
63484
  return void 0;
63485
63485
  }
63486
63486
  let originUrl;
63487
- let requestUrl;
63487
+ let requestUrl2;
63488
63488
  let locationUrl;
63489
63489
  try {
63490
63490
  originUrl = new URL(cacheKey.origin);
63491
- requestUrl = new URL(cacheKey.path, originUrl);
63492
- locationUrl = new URL(location, requestUrl);
63491
+ requestUrl2 = new URL(cacheKey.path, originUrl);
63492
+ locationUrl = new URL(location, requestUrl2);
63493
63493
  } catch {
63494
63494
  return void 0;
63495
63495
  }
@@ -72962,15 +72962,15 @@ ${value}`;
72962
72962
  pos = 0;
72963
72963
  }
72964
72964
  }
72965
- discardLeadingBytes(count) {
72966
- while (count > 0 && this.lineChunkIndex < this.chunks.length) {
72965
+ discardLeadingBytes(count2) {
72966
+ while (count2 > 0 && this.lineChunkIndex < this.chunks.length) {
72967
72967
  const chunk = this.chunks[this.lineChunkIndex];
72968
72968
  const remaining = chunk.length - this.linePos;
72969
- if (count < remaining) {
72970
- this.linePos += count;
72971
- count = 0;
72969
+ if (count2 < remaining) {
72970
+ this.linePos += count2;
72971
+ count2 = 0;
72972
72972
  } else {
72973
- count -= remaining;
72973
+ count2 -= remaining;
72974
72974
  this.lineChunkIndex++;
72975
72975
  this.linePos = 0;
72976
72976
  }
@@ -73544,6 +73544,7 @@ ${captureLines}` : capture.stack;
73544
73544
  });
73545
73545
 
73546
73546
  // src/index.ts
73547
+ import dc from "node:diagnostics_channel";
73547
73548
  import { credentialRef } from "@deepseek-ai/dsh-credentials";
73548
73549
  import { launchEnvironmentOf } from "@deepseek-ai/dsh-launch-environment";
73549
73550
  import * as llm2 from "@deepseek-ai/dsh-llm";
@@ -73555,6 +73556,7 @@ init_transcript();
73555
73556
  import {
73556
73557
  attributionHeaders as attributionHeaders5,
73557
73558
  contentHasImage as contentHasImage2,
73559
+ isTokenDelta,
73558
73560
  LlmAdapter,
73559
73561
  LlmError as LlmError8,
73560
73562
  ReasoningEffortId,
@@ -73629,16 +73631,16 @@ async function readBoundedJson(response, url, maxBytes) {
73629
73631
  });
73630
73632
  throw new LlmError(`${url} declares ${declared} bytes, over the ${maxBytes}-byte cap`, "DISCOVERY_FAILED");
73631
73633
  }
73632
- let text;
73634
+ let text2;
73633
73635
  try {
73634
- text = await readBoundedText(response, maxBytes);
73636
+ text2 = await readBoundedText(response, maxBytes);
73635
73637
  } catch (error) {
73636
73638
  if (error instanceof LlmError) throw error;
73637
73639
  const detail = error instanceof Error ? error.message : String(error);
73638
73640
  throw new LlmError(`could not read ${url}: ${detail}`, "DISCOVERY_FAILED", { cause: error });
73639
73641
  }
73640
73642
  try {
73641
- return JSON.parse(text);
73643
+ return JSON.parse(text2);
73642
73644
  } catch (error) {
73643
73645
  throw new LlmError(`${url} did not answer with JSON`, "DISCOVERY_FAILED", { cause: error });
73644
73646
  }
@@ -73860,7 +73862,7 @@ var ENDPOINT_PROTOCOLS = {
73860
73862
  "/responses": "openai-responses"
73861
73863
  };
73862
73864
  function cell(value) {
73863
- return (value ?? "").replace(/[*`]/g, "").trim();
73865
+ return (value ?? "").replace(/<small>.*?<\/small>/gi, " ").replace(/~~.*?~~/g, " ").replace(/<[^>]*>/g, " ").replace(/[*`]/g, "").replace(/\s+/g, " ").trim();
73864
73866
  }
73865
73867
  function baseName(name2) {
73866
73868
  return name2.replace(/\s*\(.*\)\s*$/, "").trim();
@@ -73884,7 +73886,8 @@ function protocolOfEndpoint(endpoint) {
73884
73886
  return void 0;
73885
73887
  }
73886
73888
  function tableRows(lines, required) {
73887
- const start = lines.findIndex((line) => line.trimStart().startsWith("|") && line.includes(required));
73889
+ const want = required.toLowerCase();
73890
+ const start = lines.findIndex((line) => line.trimStart().startsWith("|") && line.toLowerCase().includes(want));
73888
73891
  if (start < 0) return [];
73889
73892
  const rows = [];
73890
73893
  for (let index = start + 2; index < lines.length; index++) {
@@ -75721,6 +75724,11 @@ var MAX_KEEP_ALIVE_TIMEOUT_SECONDS = 1800;
75721
75724
  var DEFAULT_KEEP_ALIVE_TIMEOUT_MS = DEFAULT_KEEP_ALIVE_TIMEOUT_SECONDS * 1e3;
75722
75725
  var MAX_KEEP_ALIVE_TIMEOUT_MS = MAX_KEEP_ALIVE_TIMEOUT_SECONDS * 1e3;
75723
75726
 
75727
+ // src/request-log/limits.ts
75728
+ var DEFAULT_REQUEST_LOG_MAX_ENTRIES = 200;
75729
+ var MIN_REQUEST_LOG_MAX_ENTRIES = 50;
75730
+ var MAX_REQUEST_LOG_MAX_ENTRIES = 500;
75731
+
75724
75732
  // src/config.ts
75725
75733
  var DEFAULT_API_KEY_ENV = "OPENCODE_GO_API_KEY";
75726
75734
  var DEFAULT_REFRESH_MINUTES = 60;
@@ -75749,6 +75757,11 @@ var fields = {
75749
75757
  maxTokens: Schema.union([Schema.const(null), Schema.number().step(1).min(1).max(Number.MAX_SAFE_INTEGER)])
75750
75758
  })])).default({}),
75751
75759
  modelProtocols: Schema.dict(Schema.string()).default({}),
75760
+ // Off by default: the request path must read exactly as it does without
75761
+ // the log, so the recorder is constructed only when this is true.
75762
+ requestLogEnabled: Schema.boolean().default(false),
75763
+ requestLogDebug: Schema.boolean().default(false),
75764
+ requestLogMaxEntries: Schema.number().step(1).min(MIN_REQUEST_LOG_MAX_ENTRIES).max(MAX_REQUEST_LOG_MAX_ENTRIES).default(DEFAULT_REQUEST_LOG_MAX_ENTRIES),
75752
75765
  pinnedAddresses: Schema.dict(Schema.string()).default({}),
75753
75766
  retryPolicy: RetryPolicySchema
75754
75767
  };
@@ -76021,8 +76034,8 @@ function splitSystemPrompt(options) {
76021
76034
  if (options.system !== void 0) return { systemPrompt: options.system, messages: options.messages };
76022
76035
  const [first, ...rest] = options.messages;
76023
76036
  if (first?.role !== "system") return { systemPrompt: void 0, messages: options.messages };
76024
- const text = flattenText(first);
76025
- return { systemPrompt: text.length > 0 ? text : void 0, messages: rest };
76037
+ const text2 = flattenText(first);
76038
+ return { systemPrompt: text2.length > 0 ? text2 : void 0, messages: rest };
76026
76039
  }
76027
76040
  function collectImageRefs(blocks, refs) {
76028
76041
  for (const block of blocks) {
@@ -76300,8 +76313,8 @@ function mapStopReason4(message, contextWindow) {
76300
76313
  failure: { message: message.errorMessage ?? "pi-ai stream aborted", code: "ABORTED" }
76301
76314
  };
76302
76315
  case "error": {
76303
- const text = message.errorMessage ?? "pi-ai stream error";
76304
- return { kind: "error", failure: { message: text, code: classifyPiAiError(text) } };
76316
+ const text2 = message.errorMessage ?? "pi-ai stream error";
76317
+ return { kind: "error", failure: { message: text2, code: classifyPiAiError(text2) } };
76305
76318
  }
76306
76319
  }
76307
76320
  }
@@ -76580,6 +76593,11 @@ function stopSequencesFor(model, stop) {
76580
76593
  "UNSUPPORTED_OPTION"
76581
76594
  );
76582
76595
  }
76596
+ function requestUrl(input) {
76597
+ if (typeof input === "string") return input;
76598
+ if (input instanceof URL) return input.toString();
76599
+ return input.url;
76600
+ }
76583
76601
  async function* observingTerminalUsage(events, observe) {
76584
76602
  for await (const event of events) {
76585
76603
  if (event.type === "done") observe(event.message.usage);
@@ -76748,8 +76766,32 @@ var OpencodeGoAdapter = class extends LlmAdapter {
76748
76766
  const upstream = options.signal === void 0 ? consumer.signal : AbortSignal.any([options.signal, consumer.signal]);
76749
76767
  const watchdog = __using(_stack, idleWatchdog(upstream, config.streamIdleTimeoutMs, "LLM_STREAM_IDLE_TIMEOUT"));
76750
76768
  let timedOut = false;
76769
+ const containsImage = options.messages.some((message) => contentHasImage2(message.content));
76770
+ const headers = providerHeaders(options.sessionId === void 0 ? void 0 : String(options.sessionId));
76771
+ const span = this.options.requestLog?.start({
76772
+ model: options.model,
76773
+ sessionId: options.sessionId === void 0 ? void 0 : String(options.sessionId),
76774
+ method: "POST",
76775
+ url: config.baseURL,
76776
+ messageCount: options.messages.length,
76777
+ hasImage: containsImage,
76778
+ toolCount: options.tools?.length ?? 0,
76779
+ headers: {
76780
+ ...options.sessionId === void 0 ? {} : { session: String(options.sessionId) },
76781
+ ...typeof headers["user-agent"] === "string" ? { userAgent: headers["user-agent"] } : {}
76782
+ }
76783
+ });
76784
+ const fetchFactory = this.options.fetch;
76785
+ const requestFetch = span === void 0 || fetchFactory === void 0 ? fetchFactory : () => {
76786
+ const base = fetchFactory();
76787
+ return (async (input, init) => {
76788
+ const response = await base(input, init);
76789
+ span.request(typeof init?.method === "string" ? init.method : "POST", requestUrl(input));
76790
+ span.status(response.status);
76791
+ return response;
76792
+ });
76793
+ };
76751
76794
  try {
76752
- const containsImage = options.messages.some((message) => contentHasImage2(message.content));
76753
76795
  if (containsImage && !model.input.includes("image")) {
76754
76796
  throw new LlmError8(`opencode-go model "${model.id}" does not support image input`, "UNSUPPORTED_CONTENT");
76755
76797
  }
@@ -76769,6 +76811,7 @@ var OpencodeGoAdapter = class extends LlmAdapter {
76769
76811
  }
76770
76812
  const context = imageRequest === void 0 ? await toPiContext(options, void 0, this.options.onReplayDegrade) : await toPiContext({ ...options, signal: watchdog.signal }, imageRequest, this.options.onReplayDegrade);
76771
76813
  let reportedReasoning;
76814
+ let pendingUsage;
76772
76815
  const events = observingTerminalUsage(snapshot2.provider.streamSimple(model, normalizeContext(context), {
76773
76816
  apiKey,
76774
76817
  ...reasoning === void 0 || reasoning === "off" ? {} : { reasoning },
@@ -76781,12 +76824,14 @@ var OpencodeGoAdapter = class extends LlmAdapter {
76781
76824
  ...options.sessionId === void 0 ? {} : { sessionId: String(options.sessionId) },
76782
76825
  signal: watchdog.signal,
76783
76826
  // The gateway refuses a request without `x-opencode-session`; the
76784
- // attribution user-agent rides along on the same object.
76785
- headers: providerHeaders(options.sessionId === void 0 ? void 0 : String(options.sessionId)),
76827
+ // attribution user-agent rides along on the same object. Computed
76828
+ // once above so the request log can reuse the allowlisted values.
76829
+ headers,
76786
76830
  // The request goes to the gateway, so it goes through the fetch that
76787
76831
  // honours the gateway's pin — and through the system's own resolution
76788
- // when the pinned address turns out to be gone.
76789
- ...this.options.fetch === void 0 ? {} : { fetch: this.options.fetch() },
76832
+ // when the pinned address turns out to be gone. Invoked once per
76833
+ // request, exactly as the factory was before.
76834
+ ...requestFetch === void 0 ? {} : { fetch: requestFetch() },
76790
76835
  // The agent recovery layer owns visible attempts; one adapter call is
76791
76836
  // one SDK attempt.
76792
76837
  maxRetries: 0
@@ -76805,7 +76850,9 @@ var OpencodeGoAdapter = class extends LlmAdapter {
76805
76850
  exhausted = true;
76806
76851
  return;
76807
76852
  }
76853
+ if (span !== void 0 && isTokenDelta(result.value)) span.firstToken();
76808
76854
  if (result.value.type === "usage") {
76855
+ pendingUsage = result.value.usage;
76809
76856
  this.options.onUsage?.({
76810
76857
  model: options.model,
76811
76858
  usage: {
@@ -76816,6 +76863,18 @@ var OpencodeGoAdapter = class extends LlmAdapter {
76816
76863
  ...rates2 === void 0 ? {} : { rates: rates2 }
76817
76864
  }
76818
76865
  });
76866
+ } else if (result.value.type === "finish") {
76867
+ const reason = result.value.reason;
76868
+ const ok = reason.kind === "stop" || reason.kind === "tool-calls" || reason.kind === "max-tokens";
76869
+ span?.finish(
76870
+ ok,
76871
+ ok ? void 0 : reason.failure?.code,
76872
+ pendingUsage === void 0 ? void 0 : {
76873
+ inputTokens: pendingUsage.inputTokens,
76874
+ outputTokens: pendingUsage.outputTokens,
76875
+ ...pendingUsage.cacheReadTokens === void 0 ? {} : { cacheReadTokens: pendingUsage.cacheReadTokens }
76876
+ }
76877
+ );
76819
76878
  }
76820
76879
  yield result.value;
76821
76880
  }
@@ -76832,11 +76891,14 @@ var OpencodeGoAdapter = class extends LlmAdapter {
76832
76891
  }
76833
76892
  } catch (error) {
76834
76893
  if (timedOut || timeoutOf(watchdog.signal, "LLM_STREAM_IDLE_TIMEOUT") !== void 0) {
76894
+ span?.finish(false, "TIMEOUT");
76835
76895
  throw new LlmError8("opencode-go stream idle timeout", "TIMEOUT", { cause: error });
76836
76896
  }
76837
76897
  if (options.signal?.aborted) {
76898
+ span?.finish(false, "ABORTED");
76838
76899
  throw new LlmError8("opencode-go request aborted by caller", "ABORTED", { cause: error });
76839
76900
  }
76901
+ span?.finish(false, error instanceof LlmError8 ? error.code : void 0);
76840
76902
  throw error;
76841
76903
  } finally {
76842
76904
  consumer.abort("opencode-go stream consumer stopped");
@@ -76929,7 +76991,7 @@ function parseCatalogReading(value) {
76929
76991
  throw new Error("invalid catalog reading");
76930
76992
  }
76931
76993
  const numbers = counts;
76932
- const count = (key) => {
76994
+ const count2 = (key) => {
76933
76995
  const entry = numbers[key];
76934
76996
  if (typeof entry !== "number" || !Number.isFinite(entry) || entry < 0) throw new Error(`invalid catalog count "${key}"`);
76935
76997
  return entry;
@@ -76948,11 +77010,11 @@ function parseCatalogReading(value) {
76948
77010
  fetchedAtMs: row["fetchedAtMs"],
76949
77011
  quotaSource: quotaSource ?? "seed",
76950
77012
  counts: {
76951
- total: count("total"),
76952
- enabled: count("enabled"),
76953
- deprecated: count("deprecated"),
76954
- unconfigured: count("unconfigured"),
76955
- inferred: count("inferred")
77013
+ total: count2("total"),
77014
+ enabled: count2("enabled"),
77015
+ deprecated: count2("deprecated"),
77016
+ unconfigured: count2("unconfigured"),
77017
+ inferred: count2("inferred")
76956
77018
  }
76957
77019
  };
76958
77020
  }
@@ -77021,6 +77083,106 @@ var networkRemote = {
77021
77083
  ]
77022
77084
  };
77023
77085
 
77086
+ // src/request-log/contract.ts
77087
+ function count(key, row, optional) {
77088
+ const entry = row[key];
77089
+ if (entry === void 0) {
77090
+ if (optional === true) return void 0;
77091
+ throw new Error(`invalid request-log entry "${key}"`);
77092
+ }
77093
+ if (typeof entry !== "number" || !Number.isFinite(entry) || entry < 0) {
77094
+ throw new Error(`invalid request-log entry "${key}"`);
77095
+ }
77096
+ return entry;
77097
+ }
77098
+ function text(key, row, optional) {
77099
+ const entry = row[key];
77100
+ if (entry === void 0) {
77101
+ if (optional === true) return void 0;
77102
+ throw new Error(`invalid request-log entry "${key}"`);
77103
+ }
77104
+ if (typeof entry !== "string") throw new Error(`invalid request-log entry "${key}"`);
77105
+ return entry;
77106
+ }
77107
+ function parseEntry(value) {
77108
+ if (value === null || typeof value !== "object") throw new Error("invalid request-log entry");
77109
+ const row = value;
77110
+ const shape = row["shape"];
77111
+ const headers = row["headers"];
77112
+ return {
77113
+ seq: count("seq", row),
77114
+ atMs: count("atMs", row),
77115
+ model: text("model", row),
77116
+ session: text("session", row),
77117
+ method: text("method", row),
77118
+ url: text("url", row),
77119
+ ...row["status"] === void 0 ? {} : { status: count("status", row) },
77120
+ ...row["inputTokens"] === void 0 ? {} : { inputTokens: count("inputTokens", row) },
77121
+ ...row["outputTokens"] === void 0 ? {} : { outputTokens: count("outputTokens", row) },
77122
+ ...row["cacheReadTokens"] === void 0 ? {} : { cacheReadTokens: count("cacheReadTokens", row) },
77123
+ ...row["durationMs"] === void 0 ? {} : { durationMs: count("durationMs", row) },
77124
+ ...row["firstTokenMs"] === void 0 ? {} : { firstTokenMs: count("firstTokenMs", row) },
77125
+ ok: row["ok"] === true,
77126
+ ...typeof row["code"] === "string" ? { code: row["code"] } : {},
77127
+ ...typeof row["poolKey"] === "string" ? { poolKey: row["poolKey"] } : {},
77128
+ ...shape !== null && typeof shape === "object" ? {
77129
+ shape: {
77130
+ messages: count("messages", shape),
77131
+ hasImage: shape["hasImage"] === true,
77132
+ tools: count("tools", shape)
77133
+ }
77134
+ } : {},
77135
+ ...headers !== null && typeof headers === "object" ? {
77136
+ headers: {
77137
+ ...typeof headers["session"] === "string" ? { session: headers["session"] } : {},
77138
+ ...typeof headers["userAgent"] === "string" ? { userAgent: headers["userAgent"] } : {}
77139
+ }
77140
+ } : {}
77141
+ };
77142
+ }
77143
+ function parsePoolEvent(value) {
77144
+ if (value === null || typeof value !== "object") throw new Error("invalid request-log pool event");
77145
+ const row = value;
77146
+ const type = row["type"];
77147
+ if (type !== "create" && type !== "close") throw new Error("invalid request-log pool event");
77148
+ return { atMs: count("atMs", row), type, key: text("key", row) };
77149
+ }
77150
+ function parseRequestLogSnapshot(value) {
77151
+ if (value === null || typeof value !== "object") throw new Error("invalid request-log snapshot");
77152
+ const row = value;
77153
+ if (!Array.isArray(row["entries"]) || !Array.isArray(row["poolEvents"])) {
77154
+ throw new Error("invalid request-log snapshot");
77155
+ }
77156
+ return {
77157
+ entries: row["entries"].map(parseEntry),
77158
+ poolEvents: row["poolEvents"].map(parsePoolEvent),
77159
+ totalRecords: count("totalRecords", row),
77160
+ droppedRecords: count("droppedRecords", row),
77161
+ newConnections: count("newConnections", row),
77162
+ ...typeof row["poolKey"] === "string" ? { poolKey: row["poolKey"] } : {}
77163
+ };
77164
+ }
77165
+ var codec3 = {
77166
+ mode: "strict",
77167
+ typeSymbol: "@dan-ai-studio/dshopencodego#RequestLogSnapshot",
77168
+ schema: { parse: parseRequestLogSnapshot },
77169
+ create: () => ({ parse: parseRequestLogSnapshot })
77170
+ };
77171
+ var requestLogRemote = {
77172
+ package: "@dan-ai-studio/dshopencodego",
77173
+ descriptors: [
77174
+ {
77175
+ id: "@dan-ai-studio/dshopencodego#opencodeGoRequestLog/readLog",
77176
+ service: "opencodeGoRequestLog",
77177
+ namespace: "opencodeGoRequestLog",
77178
+ method: "readLog",
77179
+ invocation: { kind: "direct" },
77180
+ parameters: [],
77181
+ result: codec3
77182
+ }
77183
+ ]
77184
+ };
77185
+
77024
77186
  // src/update/contract.ts
77025
77187
  function parseUpdateStatus(value) {
77026
77188
  if (value === null || typeof value !== "object") throw new Error("invalid update reading");
@@ -77040,7 +77202,7 @@ function parseUpdateStatus(value) {
77040
77202
  checked: row["checked"]
77041
77203
  };
77042
77204
  }
77043
- var codec3 = (typeSymbol, parse) => ({
77205
+ var codec4 = (typeSymbol, parse) => ({
77044
77206
  mode: "strict",
77045
77207
  typeSymbol,
77046
77208
  schema: { parse },
@@ -77056,7 +77218,7 @@ var updateRemote = {
77056
77218
  method: "readUpdate",
77057
77219
  invocation: { kind: "direct" },
77058
77220
  parameters: [],
77059
- result: codec3("@dan-ai-studio/dshopencodego#UpdateStatus", parseUpdateStatus)
77221
+ result: codec4("@dan-ai-studio/dshopencodego#UpdateStatus", parseUpdateStatus)
77060
77222
  },
77061
77223
  {
77062
77224
  id: "@dan-ai-studio/dshopencodego#opencodeGoUpdate/refreshUpdate",
@@ -77065,7 +77227,7 @@ var updateRemote = {
77065
77227
  method: "refreshUpdate",
77066
77228
  invocation: { kind: "direct" },
77067
77229
  parameters: [],
77068
- result: codec3("@dan-ai-studio/dshopencodego#UpdateStatus", parseUpdateStatus)
77230
+ result: codec4("@dan-ai-studio/dshopencodego#UpdateStatus", parseUpdateStatus)
77069
77231
  }
77070
77232
  ]
77071
77233
  };
@@ -77092,22 +77254,22 @@ function parseUsageWindows(value) {
77092
77254
  function parseTotals(value) {
77093
77255
  if (value === null || typeof value !== "object") throw new Error("invalid meter totals");
77094
77256
  const row = value;
77095
- const count = (key) => {
77257
+ const count2 = (key) => {
77096
77258
  const entry = row[key];
77097
77259
  if (typeof entry !== "number" || !Number.isFinite(entry) || entry < 0) throw new Error(`invalid meter field "${key}"`);
77098
77260
  return entry;
77099
77261
  };
77100
- const optionalCount = (key) => row[key] === void 0 ? void 0 : count(key);
77262
+ const optionalCount = (key) => row[key] === void 0 ? void 0 : count2(key);
77101
77263
  const reasoningTokens = optionalCount("reasoningTokens");
77102
77264
  const estimatedUSD = optionalCount("estimatedUSD");
77103
77265
  const unpricedTokens = optionalCount("unpricedTokens");
77104
77266
  return {
77105
- calls: count("calls"),
77106
- inputTokens: count("inputTokens"),
77107
- outputTokens: count("outputTokens"),
77108
- cacheReadTokens: count("cacheReadTokens"),
77109
- cacheWriteTokens: count("cacheWriteTokens"),
77110
- totalTokens: count("totalTokens"),
77267
+ calls: count2("calls"),
77268
+ inputTokens: count2("inputTokens"),
77269
+ outputTokens: count2("outputTokens"),
77270
+ cacheReadTokens: count2("cacheReadTokens"),
77271
+ cacheWriteTokens: count2("cacheWriteTokens"),
77272
+ totalTokens: count2("totalTokens"),
77111
77273
  ...reasoningTokens === void 0 ? {} : { reasoningTokens },
77112
77274
  ...estimatedUSD === void 0 ? {} : { estimatedUSD },
77113
77275
  ...unpricedTokens === void 0 ? {} : { unpricedTokens }
@@ -77131,7 +77293,7 @@ function parseGoMeter(value) {
77131
77293
  })
77132
77294
  };
77133
77295
  }
77134
- var codec4 = (typeSymbol, parse) => ({
77296
+ var codec5 = (typeSymbol, parse) => ({
77135
77297
  mode: "strict",
77136
77298
  typeSymbol,
77137
77299
  schema: { parse },
@@ -77147,7 +77309,7 @@ var usageRemote = {
77147
77309
  method: "readWindows",
77148
77310
  invocation: { kind: "direct" },
77149
77311
  parameters: [],
77150
- result: codec4("@dan-ai-studio/dshopencodego#GoUsageWindows", parseUsageWindows)
77312
+ result: codec5("@dan-ai-studio/dshopencodego#GoUsageWindows", parseUsageWindows)
77151
77313
  },
77152
77314
  {
77153
77315
  id: "@dan-ai-studio/dshopencodego#opencodeGoUsage/readMeter",
@@ -77156,7 +77318,7 @@ var usageRemote = {
77156
77318
  method: "readMeter",
77157
77319
  invocation: { kind: "direct" },
77158
77320
  parameters: [],
77159
- result: codec4("@dan-ai-studio/dshopencodego#GoMeter", parseGoMeter)
77321
+ result: codec5("@dan-ai-studio/dshopencodego#GoMeter", parseGoMeter)
77160
77322
  }
77161
77323
  ]
77162
77324
  };
@@ -77168,7 +77330,8 @@ var contribution = {
77168
77330
  ...usageRemote.descriptors,
77169
77331
  ...catalogRemote.descriptors,
77170
77332
  ...updateRemote.descriptors,
77171
- ...networkRemote.descriptors
77333
+ ...networkRemote.descriptors,
77334
+ ...requestLogRemote.descriptors
77172
77335
  ]
77173
77336
  };
77174
77337
  function registerRemotes(ctx) {
@@ -77338,21 +77501,30 @@ function pinnedLookup(address) {
77338
77501
  };
77339
77502
  }
77340
77503
  var current;
77504
+ var observer;
77505
+ function observePool(next) {
77506
+ observer = next;
77507
+ }
77341
77508
  function dispatcherFor(host, address, keepAliveTimeoutMs) {
77342
77509
  const key = `${host}@${address}@${String(keepAliveTimeoutMs)}`;
77343
77510
  if (current?.key === key) return current.agent;
77344
- void current?.agent.close();
77511
+ const previous = current;
77512
+ void previous?.agent.close();
77513
+ if (previous !== void 0) observer?.close(previous.key);
77345
77514
  const agent = new import_undici.Agent({
77346
77515
  connect: { lookup: pinnedLookup(address) },
77347
77516
  keepAliveTimeout: keepAliveTimeoutMs,
77348
77517
  keepAliveMaxTimeout: keepAliveTimeoutMs
77349
77518
  });
77350
77519
  current = { key, agent };
77520
+ observer?.create(key);
77351
77521
  return agent;
77352
77522
  }
77353
77523
  async function closeDispatcher() {
77354
77524
  const agent = current?.agent;
77525
+ const key = current?.key;
77355
77526
  current = void 0;
77527
+ if (key !== void 0) observer?.close(key);
77356
77528
  if (agent !== void 0) await agent.close();
77357
77529
  }
77358
77530
  var SPENT_ADDRESS_CODES = /* @__PURE__ */ new Set([
@@ -77468,6 +77640,148 @@ var OpencodeGoNetworkService = class extends TypertRemoteService2 {
77468
77640
  }
77469
77641
  };
77470
77642
 
77643
+ // src/request-log/service.ts
77644
+ import { TypertRemoteService as TypertRemoteService3 } from "@deepseek-ai/dsh-typert-protocol";
77645
+ var OpencodeGoRequestLogService = class extends TypertRemoteService3 {
77646
+ options;
77647
+ constructor(ctx, options) {
77648
+ super(ctx, "opencodeGoRequestLog");
77649
+ this.options = options;
77650
+ }
77651
+ /** The current reading, trimmed to the configured bound first. */
77652
+ readLog() {
77653
+ this.options.log.setMaxEntries(this.options.maxEntries());
77654
+ return this.options.log.snapshot();
77655
+ }
77656
+ };
77657
+
77658
+ // src/request-log/store.ts
77659
+ var SESSION_PREFIX_LENGTH = 8;
77660
+ var MAX_POOL_EVENTS = 20;
77661
+ var RequestLog = class {
77662
+ gates;
77663
+ entries = [];
77664
+ poolEvents = [];
77665
+ seq = 0;
77666
+ totalRecords = 0;
77667
+ droppedRecords = 0;
77668
+ newConnections = 0;
77669
+ poolKey;
77670
+ constructor(gates) {
77671
+ this.gates = gates;
77672
+ }
77673
+ /**
77674
+ * Count one accepted socket. Called from the diagnostics channel, not the
77675
+ * request path, so its cost never lands on a request.
77676
+ */
77677
+ connectionOpened() {
77678
+ this.newConnections += 1;
77679
+ }
77680
+ /**
77681
+ * Record one pool lifecycle event. Pools live for minutes, so this is rare
77682
+ * by construction; still gated on debug so the common log stays request-only.
77683
+ */
77684
+ poolEvent(type, key) {
77685
+ if (!this.gates.enabled() || !this.gates.debug()) return;
77686
+ this.poolKey = type === "create" ? key : this.poolKey;
77687
+ if (type === "close" && this.poolKey === key) this.poolKey = void 0;
77688
+ this.poolEvents = [{ atMs: Date.now(), type, key }, ...this.poolEvents].slice(0, MAX_POOL_EVENTS);
77689
+ }
77690
+ /**
77691
+ * Begin one request's span, or nothing when the log is disabled.
77692
+ *
77693
+ * This is the single gate on the request path: a disabled log costs one
77694
+ * method call and one boolean read, and constructs nothing.
77695
+ */
77696
+ start(detail) {
77697
+ if (!this.gates.enabled()) return void 0;
77698
+ const debug = this.gates.debug();
77699
+ const startedAt = Date.now();
77700
+ const full = detail.sessionId ?? "";
77701
+ const session = debug || full.length === 0 ? full : full.slice(0, SESSION_PREFIX_LENGTH);
77702
+ let firstTokenAt;
77703
+ let method;
77704
+ let url;
77705
+ let status;
77706
+ let finished = false;
77707
+ return {
77708
+ firstToken: () => {
77709
+ if (firstTokenAt === void 0) firstTokenAt = Date.now();
77710
+ },
77711
+ request: (nextMethod, nextUrl) => {
77712
+ if (method === void 0) {
77713
+ method = nextMethod;
77714
+ url = nextUrl;
77715
+ }
77716
+ },
77717
+ status: (value) => {
77718
+ status = value;
77719
+ },
77720
+ finish: (ok, code, usage) => {
77721
+ if (finished) return;
77722
+ finished = true;
77723
+ const endedAt = Date.now();
77724
+ const entry = {
77725
+ seq: ++this.seq,
77726
+ atMs: startedAt,
77727
+ model: detail.model,
77728
+ session,
77729
+ method: method ?? detail.method ?? "POST",
77730
+ url: url ?? detail.url ?? "",
77731
+ ...status === void 0 ? {} : { status },
77732
+ ...usage === void 0 ? {} : {
77733
+ inputTokens: usage.inputTokens,
77734
+ outputTokens: usage.outputTokens,
77735
+ ...usage.cacheReadTokens === void 0 || usage.cacheReadTokens <= 0 ? {} : { cacheReadTokens: usage.cacheReadTokens }
77736
+ },
77737
+ durationMs: Math.max(0, endedAt - startedAt),
77738
+ ...firstTokenAt === void 0 ? {} : { firstTokenMs: Math.max(0, firstTokenAt - startedAt) },
77739
+ ok,
77740
+ ...code === void 0 ? {} : { code },
77741
+ // The pool in force when the request finished. Pool switches are
77742
+ // rare enough that attributing the finishing pool is honest; the
77743
+ // create/close events carry the exact history.
77744
+ ...this.poolKey === void 0 ? {} : { poolKey: this.poolKey },
77745
+ shape: { messages: detail.messageCount, hasImage: detail.hasImage, tools: detail.toolCount },
77746
+ ...!debug ? {} : {
77747
+ headers: {
77748
+ ...detail.headers.session === void 0 ? {} : { session: detail.headers.session },
77749
+ ...detail.headers.userAgent === void 0 ? {} : { userAgent: detail.headers.userAgent }
77750
+ }
77751
+ }
77752
+ };
77753
+ this.append(entry);
77754
+ }
77755
+ };
77756
+ }
77757
+ append(entry) {
77758
+ this.totalRecords += 1;
77759
+ const bound = Math.max(1, Math.floor(this.gates.maxEntries()));
77760
+ const next = [entry, ...this.entries].slice(0, bound);
77761
+ this.droppedRecords += this.entries.length + 1 - next.length;
77762
+ this.entries = next;
77763
+ }
77764
+ /** Shrink the ring to a new bound immediately; growing backfills nothing. */
77765
+ setMaxEntries(bound) {
77766
+ if (!Number.isSafeInteger(bound) || bound < 1) return;
77767
+ if (this.entries.length > bound) {
77768
+ this.droppedRecords += this.entries.length - bound;
77769
+ this.entries = this.entries.slice(0, bound);
77770
+ }
77771
+ }
77772
+ /** The current reading, newest first. Computed lazily: nothing on the hot path. */
77773
+ snapshot() {
77774
+ return {
77775
+ entries: this.entries,
77776
+ poolEvents: this.poolEvents,
77777
+ totalRecords: this.totalRecords,
77778
+ droppedRecords: this.droppedRecords,
77779
+ newConnections: this.newConnections,
77780
+ ...this.poolKey === void 0 ? {} : { poolKey: this.poolKey }
77781
+ };
77782
+ }
77783
+ };
77784
+
77471
77785
  // src/update/check.ts
77472
77786
  var PACKAGE_NAME = "@dan-ai-studio/dshopencodego";
77473
77787
  var REGISTRY_LATEST_URL = `https://registry.npmjs.org/${encodeURIComponent(PACKAGE_NAME)}/latest`;
@@ -77561,11 +77875,11 @@ function createUpdateChecker(deps) {
77561
77875
  }
77562
77876
 
77563
77877
  // src/update/version.ts
77564
- var PLUGIN_VERSION = true ? "0.1.62" : "0.0.0-dev";
77878
+ var PLUGIN_VERSION = true ? "0.1.64" : "0.0.0-dev";
77565
77879
 
77566
77880
  // src/update/service.ts
77567
- import { TypertRemoteService as TypertRemoteService3 } from "@deepseek-ai/dsh-typert-protocol";
77568
- var OpencodeGoUpdateService = class extends TypertRemoteService3 {
77881
+ import { TypertRemoteService as TypertRemoteService4 } from "@deepseek-ai/dsh-typert-protocol";
77882
+ var OpencodeGoUpdateService = class extends TypertRemoteService4 {
77569
77883
  check;
77570
77884
  constructor(ctx, options) {
77571
77885
  super(ctx, "opencodeGoUpdate");
@@ -77645,7 +77959,7 @@ async function readUsageWindows(options) {
77645
77959
 
77646
77960
  // src/usage/service.ts
77647
77961
  import { randomUUID as randomUUID3 } from "node:crypto";
77648
- import { RemoteError as RemoteError2, TypertRemoteService as TypertRemoteService4 } from "@deepseek-ai/dsh-typert-protocol";
77962
+ import { RemoteError as RemoteError2, TypertRemoteService as TypertRemoteService5 } from "@deepseek-ai/dsh-typert-protocol";
77649
77963
  import { LlmError as LlmError11 } from "@deepseek-ai/dsh-llm";
77650
77964
  function usageFailure(error, source) {
77651
77965
  const missing = error instanceof LlmError11 && error.code === "MISSING_CREDENTIAL";
@@ -77656,7 +77970,7 @@ function usageFailure(error, source) {
77656
77970
  { cause: error }
77657
77971
  );
77658
77972
  }
77659
- var OpencodeGoUsageService = class extends TypertRemoteService4 {
77973
+ var OpencodeGoUsageService = class extends TypertRemoteService5 {
77660
77974
  identity;
77661
77975
  options;
77662
77976
  constructor(ctx, options) {
@@ -77731,6 +78045,29 @@ function apply(ctx, raw) {
77731
78045
  };
77732
78046
  const meter = new UsageMeter();
77733
78047
  const cacheDir = resolveCacheDir(ctx);
78048
+ const requestLog = new RequestLog({
78049
+ enabled: () => current2().requestLogEnabled,
78050
+ debug: () => current2().requestLogDebug,
78051
+ maxEntries: () => current2().requestLogMaxEntries
78052
+ });
78053
+ observePool({
78054
+ create: (key) => {
78055
+ requestLog.poolEvent("create", key);
78056
+ },
78057
+ close: (key) => {
78058
+ requestLog.poolEvent("close", key);
78059
+ }
78060
+ });
78061
+ ctx.effect(() => {
78062
+ const channel = dc.channel("undici:client:connected");
78063
+ const onConnect = () => {
78064
+ requestLog.connectionOpened();
78065
+ };
78066
+ channel.subscribe(onConnect);
78067
+ return () => {
78068
+ channel.unsubscribe(onConnect);
78069
+ };
78070
+ }, "dshopencodego: connection counter");
77734
78071
  const gatewayRequest = () => gatewayFetch(
77735
78072
  resolveGatewayPin(current2().pinnedAddresses, current2().baseURL),
77736
78073
  current2().keepAliveTimeoutMs
@@ -77759,7 +78096,8 @@ function apply(ctx, raw) {
77759
78096
  },
77760
78097
  onUsage: ({ model, usage }) => {
77761
78098
  meter.record(model, usage);
77762
- }
78099
+ },
78100
+ requestLog
77763
78101
  });
77764
78102
  registerRemotes(ctx);
77765
78103
  ctx.plugin(OpencodeGoUsageService, {
@@ -77768,6 +78106,10 @@ function apply(ctx, raw) {
77768
78106
  meter,
77769
78107
  fetch: gatewayRequest
77770
78108
  });
78109
+ ctx.plugin(OpencodeGoRequestLogService, {
78110
+ log: requestLog,
78111
+ maxEntries: () => current2().requestLogMaxEntries
78112
+ });
77771
78113
  ctx.plugin(OpencodeGoNetworkService, {
77772
78114
  baseURL: () => current2().baseURL,
77773
78115
  pinnedAddresses: () => current2().pinnedAddresses