@dan-ai-studio/dshopencodego 0.1.82 → 0.1.84

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
@@ -73742,6 +73742,7 @@ var BACKGROUND_RETRY_BACKOFF_MS = 5 * 6e4;
73742
73742
  var MODEL_LISTING_MAX_BYTES = 1024 * 1024;
73743
73743
  var MODEL_METADATA_MAX_BYTES = 16 * 1024 * 1024;
73744
73744
  var UNKNOWN_MODEL_PROBE_COOLDOWN_MS = 5 * 6e4;
73745
+ var MAX_CATALOG_STALENESS_MS = 24 * 60 * 6e4;
73745
73746
 
73746
73747
  // src/catalog/gateway.ts
73747
73748
  import { attributionHeaders, LlmError as LlmError2 } from "@deepseek-ai/dsh-llm";
@@ -74412,35 +74413,40 @@ import { mkdirSync as mkdirSync4, readFileSync as readFileSync4, writeFileSync a
74412
74413
  import { join as join5 } from "node:path";
74413
74414
  var CACHE_FILE4 = "catalog-snapshot.json";
74414
74415
  var CACHE_VERSION4 = 1;
74416
+ function parseSnapshotFile(value) {
74417
+ if (value === null || typeof value !== "object") return void 0;
74418
+ const parsed = value;
74419
+ if (parsed.version !== CACHE_VERSION4) return void 0;
74420
+ if (parsed.facts === null || typeof parsed.facts !== "object") return void 0;
74421
+ const facts = /* @__PURE__ */ new Map();
74422
+ for (const [id, fact] of Object.entries(parsed.facts)) {
74423
+ if (fact === null || typeof fact !== "object") continue;
74424
+ if (typeof fact.id !== "string" || typeof fact.api !== "string") continue;
74425
+ facts.set(id, fact);
74426
+ }
74427
+ if (facts.size === 0) return void 0;
74428
+ const quotas = /* @__PURE__ */ new Map();
74429
+ for (const [id, quota] of Object.entries(parsed.quotas ?? {})) {
74430
+ if (quota === null || typeof quota !== "object") continue;
74431
+ quotas.set(id, quota);
74432
+ }
74433
+ const protocols = /* @__PURE__ */ new Map();
74434
+ for (const [id, protocol] of Object.entries(parsed.protocols ?? {})) {
74435
+ if (typeof protocol !== "string") continue;
74436
+ protocols.set(id, protocol);
74437
+ }
74438
+ return {
74439
+ facts,
74440
+ quotas,
74441
+ protocols,
74442
+ baseURL: typeof parsed.baseURL === "string" ? parsed.baseURL : void 0,
74443
+ updatedAt: typeof parsed.updatedAt === "number" ? parsed.updatedAt : 0
74444
+ };
74445
+ }
74415
74446
  function readSnapshotCache(cacheDir) {
74416
74447
  if (cacheDir === void 0) return void 0;
74417
74448
  try {
74418
- const parsed = JSON.parse(readFileSync4(join5(cacheDir, CACHE_FILE4), "utf8"));
74419
- if (parsed.version !== CACHE_VERSION4) return void 0;
74420
- if (parsed.facts === null || typeof parsed.facts !== "object") return void 0;
74421
- const facts = /* @__PURE__ */ new Map();
74422
- for (const [id, fact] of Object.entries(parsed.facts)) {
74423
- if (fact === null || typeof fact !== "object") continue;
74424
- if (typeof fact.id !== "string" || typeof fact.api !== "string") continue;
74425
- facts.set(id, fact);
74426
- }
74427
- if (facts.size === 0) return void 0;
74428
- const quotas = /* @__PURE__ */ new Map();
74429
- for (const [id, quota] of Object.entries(parsed.quotas ?? {})) {
74430
- if (quota === null || typeof quota !== "object") continue;
74431
- quotas.set(id, quota);
74432
- }
74433
- const protocols = /* @__PURE__ */ new Map();
74434
- for (const [id, protocol] of Object.entries(parsed.protocols ?? {})) {
74435
- if (typeof protocol !== "string") continue;
74436
- protocols.set(id, protocol);
74437
- }
74438
- return {
74439
- facts,
74440
- quotas,
74441
- protocols,
74442
- updatedAt: typeof parsed.updatedAt === "number" ? parsed.updatedAt : 0
74443
- };
74449
+ return parseSnapshotFile(JSON.parse(readFileSync4(join5(cacheDir, CACHE_FILE4), "utf8")));
74444
74450
  } catch {
74445
74451
  return void 0;
74446
74452
  }
@@ -74463,6 +74469,10 @@ function writeSnapshotCache(cacheDir, facts, quotas, protocols) {
74463
74469
  }
74464
74470
 
74465
74471
  // src/catalog/index.ts
74472
+ function snapshotIsFresh(fetchedAtMs, nowMs, refreshMs) {
74473
+ if (!Number.isFinite(fetchedAtMs) || fetchedAtMs <= 0) return false;
74474
+ return nowMs - fetchedAtMs < Math.min(refreshMs, MAX_CATALOG_STALENESS_MS);
74475
+ }
74466
74476
  function reasonText(reason) {
74467
74477
  if (reason instanceof Error) return reason.message;
74468
74478
  return typeof reason === "string" ? reason : String(reason);
@@ -74558,7 +74568,7 @@ var OpencodeGoCatalog = class {
74558
74568
  * shared snapshot cannot carry two different cancellations.
74559
74569
  */
74560
74570
  snapshot(force = false, signal) {
74561
- if (!force && this.served !== void 0 && Date.now() - this.served.fetchedAtMs < this.options.refreshMs) {
74571
+ if (!force && this.served !== void 0 && snapshotIsFresh(this.served.fetchedAtMs, Date.now(), this.options.refreshMs)) {
74562
74572
  return Promise.resolve(this.served);
74563
74573
  }
74564
74574
  if (!force) {
@@ -74619,17 +74629,14 @@ var OpencodeGoCatalog = class {
74619
74629
  return refresh === void 0 ? Promise.resolve() : refresh.then(() => void 0, () => void 0);
74620
74630
  }
74621
74631
  /**
74622
- * The catalog a previous build produced, read from disk.
74632
+ * Present a past listing as a stale-but-serving snapshot.
74623
74633
  *
74624
74634
  * It is presented as what it is: a listing from the past, being brought up
74625
74635
  * to date in the background. The facts it carries are the ones the last
74626
74636
  * build produced, so the protocols and the thinking levels are the ones
74627
74637
  * that were true then.
74628
- * @returns the remembered catalog, or undefined when there is none.
74629
74638
  */
74630
- readRememberedSnapshot() {
74631
- const remembered = readSnapshotCache(this.options.cacheDir);
74632
- if (remembered === void 0) return void 0;
74639
+ presentRemembered(remembered) {
74633
74640
  const facts = new Map(remembered.facts);
74634
74641
  return {
74635
74642
  facts,
@@ -74643,6 +74650,24 @@ var OpencodeGoCatalog = class {
74643
74650
  ...remembered.quotas.size === 0 ? {} : { documentQuotas: remembered.quotas }
74644
74651
  };
74645
74652
  }
74653
+ /**
74654
+ * The catalog a previous build produced, read from disk — or, when the
74655
+ * disk holds nothing, the snapshot baked in at publish time.
74656
+ *
74657
+ * The bundled seed is the floor, not a peer: the disk always wins when it
74658
+ * has anything to say, and the endpoint must match — a seed built for Go
74659
+ * never serves Console and vice versa. Either way the reading is served
74660
+ * stale with an immediate background refresh, never presented as current.
74661
+ * @returns the remembered catalog, or undefined when there is none.
74662
+ */
74663
+ readRememberedSnapshot() {
74664
+ const remembered = readSnapshotCache(this.options.cacheDir);
74665
+ if (remembered !== void 0) return this.presentRemembered(remembered);
74666
+ const seed = parseSnapshotFile(this.options.seed);
74667
+ if (seed === void 0) return void 0;
74668
+ if (seed.baseURL !== this.options.baseURL) return void 0;
74669
+ return this.presentRemembered(seed);
74670
+ }
74646
74671
  /**
74647
74672
  * The snapshot that can serve one exact model.
74648
74673
  *
@@ -74972,6 +74997,1250 @@ async function discoverCatalogModels(catalog, signal) {
74972
74997
  ];
74973
74998
  }
74974
74999
 
75000
+ // src/catalog/seed.snapshot.json
75001
+ var seed_snapshot_default = {
75002
+ version: 1,
75003
+ facts: {
75004
+ "deepseek-v4.1-flash": {
75005
+ id: "deepseek-v4.1-flash",
75006
+ name: "DeepSeek V4.1 Flash",
75007
+ api: "openai-completions",
75008
+ protocolSource: "builtin",
75009
+ contextWindow: 1e6,
75010
+ maxTokens: 384e3,
75011
+ assumedLimits: false,
75012
+ input: [
75013
+ "text",
75014
+ "image"
75015
+ ],
75016
+ inputModalities: [
75017
+ "text",
75018
+ "image"
75019
+ ],
75020
+ reasoning: true,
75021
+ thinkingLevelMap: {
75022
+ off: null,
75023
+ minimal: null,
75024
+ low: "low",
75025
+ medium: null,
75026
+ high: "high",
75027
+ xhigh: null,
75028
+ max: "max"
75029
+ },
75030
+ compat: {
75031
+ supportsStore: false,
75032
+ supportsDeveloperRole: false,
75033
+ maxTokensField: "max_tokens",
75034
+ requiresReasoningContentOnAssistantMessages: true,
75035
+ supportsStrictMode: true,
75036
+ thinkingFormat: "deepseek"
75037
+ },
75038
+ cost: {
75039
+ input: 0.15,
75040
+ output: 0.6,
75041
+ cacheRead: 3e-3,
75042
+ cacheWrite: 0
75043
+ },
75044
+ deprecated: false,
75045
+ releaseDate: "2026-09-10"
75046
+ },
75047
+ "deepseek-v4-pro": {
75048
+ id: "deepseek-v4-pro",
75049
+ name: "DeepSeek V4 Pro (New)",
75050
+ api: "openai-completions",
75051
+ protocolSource: "builtin",
75052
+ contextWindow: 1e6,
75053
+ maxTokens: 384e3,
75054
+ assumedLimits: false,
75055
+ input: [
75056
+ "text"
75057
+ ],
75058
+ inputModalities: [
75059
+ "text"
75060
+ ],
75061
+ reasoning: true,
75062
+ thinkingLevelMap: {
75063
+ off: null,
75064
+ minimal: null,
75065
+ low: null,
75066
+ medium: null,
75067
+ high: "high",
75068
+ xhigh: null,
75069
+ max: "max"
75070
+ },
75071
+ compat: {
75072
+ supportsStore: false,
75073
+ supportsDeveloperRole: false,
75074
+ maxTokensField: "max_tokens",
75075
+ requiresReasoningContentOnAssistantMessages: true,
75076
+ supportsStrictMode: true,
75077
+ thinkingFormat: "deepseek"
75078
+ },
75079
+ cost: {
75080
+ input: 0.66,
75081
+ output: 1.98,
75082
+ cacheRead: 0.022,
75083
+ cacheWrite: 0
75084
+ },
75085
+ deprecated: false,
75086
+ releaseDate: "2026-04-24"
75087
+ },
75088
+ "glm-5.2": {
75089
+ id: "glm-5.2",
75090
+ name: "GLM-5.2",
75091
+ api: "openai-completions",
75092
+ protocolSource: "builtin",
75093
+ contextWindow: 1e6,
75094
+ maxTokens: 131072,
75095
+ assumedLimits: false,
75096
+ input: [
75097
+ "text"
75098
+ ],
75099
+ inputModalities: [
75100
+ "text"
75101
+ ],
75102
+ reasoning: true,
75103
+ thinkingLevelMap: {
75104
+ off: null,
75105
+ minimal: null,
75106
+ low: null,
75107
+ medium: null,
75108
+ high: "high",
75109
+ xhigh: null,
75110
+ max: "max"
75111
+ },
75112
+ compat: {
75113
+ supportsStore: false,
75114
+ supportsDeveloperRole: false,
75115
+ maxTokensField: "max_tokens",
75116
+ requiresReasoningContentOnAssistantMessages: true,
75117
+ supportsStrictMode: true
75118
+ },
75119
+ cost: {
75120
+ input: 1.4,
75121
+ output: 4.4,
75122
+ cacheRead: 0.26,
75123
+ cacheWrite: 0
75124
+ },
75125
+ deprecated: false,
75126
+ releaseDate: "2026-06-13"
75127
+ },
75128
+ "glm-5.3": {
75129
+ id: "glm-5.3",
75130
+ name: "GLM-5.3",
75131
+ api: "openai-completions",
75132
+ protocolSource: "builtin",
75133
+ contextWindow: 1e6,
75134
+ maxTokens: 131072,
75135
+ assumedLimits: false,
75136
+ input: [
75137
+ "text"
75138
+ ],
75139
+ inputModalities: [
75140
+ "text"
75141
+ ],
75142
+ reasoning: true,
75143
+ thinkingLevelMap: {
75144
+ off: null,
75145
+ minimal: null,
75146
+ low: "low",
75147
+ medium: null,
75148
+ high: "high",
75149
+ xhigh: null,
75150
+ max: "max"
75151
+ },
75152
+ compat: {
75153
+ supportsStore: false,
75154
+ supportsDeveloperRole: false,
75155
+ maxTokensField: "max_tokens",
75156
+ requiresReasoningContentOnAssistantMessages: true,
75157
+ supportsStrictMode: true
75158
+ },
75159
+ cost: {
75160
+ input: 1.4,
75161
+ output: 4.4,
75162
+ cacheRead: 0.26,
75163
+ cacheWrite: 0
75164
+ },
75165
+ deprecated: false,
75166
+ releaseDate: "2026-08-14"
75167
+ },
75168
+ "grok-4.7": {
75169
+ id: "grok-4.7",
75170
+ name: "Grok 4.7",
75171
+ api: "openai-responses",
75172
+ protocolSource: "builtin",
75173
+ contextWindow: 5e5,
75174
+ maxTokens: 5e5,
75175
+ assumedLimits: false,
75176
+ input: [
75177
+ "text",
75178
+ "image"
75179
+ ],
75180
+ inputModalities: [
75181
+ "text",
75182
+ "image",
75183
+ "pdf"
75184
+ ],
75185
+ reasoning: true,
75186
+ thinkingLevelMap: {
75187
+ off: null,
75188
+ minimal: null,
75189
+ low: "low",
75190
+ medium: "medium",
75191
+ high: "high",
75192
+ xhigh: "xhigh",
75193
+ max: null
75194
+ },
75195
+ compat: {
75196
+ sessionAffinityFormat: "openai-nosession"
75197
+ },
75198
+ cost: {
75199
+ input: 2,
75200
+ output: 6,
75201
+ cacheRead: 0.5,
75202
+ cacheWrite: 0,
75203
+ tiers: [
75204
+ {
75205
+ input: 4,
75206
+ output: 12,
75207
+ cacheRead: 1,
75208
+ cacheWrite: 0,
75209
+ inputTokensAbove: 2e5
75210
+ }
75211
+ ]
75212
+ },
75213
+ deprecated: false,
75214
+ releaseDate: "2026-09-21"
75215
+ },
75216
+ "muse-spark-1.2-contributor": {
75217
+ id: "muse-spark-1.2-contributor",
75218
+ name: "Muse Spark 1.2 Contributor",
75219
+ api: "openai-responses",
75220
+ protocolSource: "builtin",
75221
+ contextWindow: 1048576,
75222
+ maxTokens: 131072,
75223
+ assumedLimits: false,
75224
+ input: [
75225
+ "text",
75226
+ "image"
75227
+ ],
75228
+ inputModalities: [
75229
+ "text",
75230
+ "image",
75231
+ "audio",
75232
+ "video",
75233
+ "pdf"
75234
+ ],
75235
+ reasoning: true,
75236
+ thinkingLevelMap: {
75237
+ off: null,
75238
+ minimal: "minimal",
75239
+ low: "low",
75240
+ medium: "medium",
75241
+ high: "high",
75242
+ xhigh: "xhigh",
75243
+ max: null
75244
+ },
75245
+ compat: {
75246
+ sessionAffinityFormat: "openai-nosession"
75247
+ },
75248
+ cost: {
75249
+ input: 0.1,
75250
+ output: 0.2,
75251
+ cacheRead: 2e-3,
75252
+ cacheWrite: 0
75253
+ },
75254
+ deprecated: false,
75255
+ releaseDate: "2026-08-05"
75256
+ },
75257
+ "muse-spark-1.3-contributor": {
75258
+ id: "muse-spark-1.3-contributor",
75259
+ name: "Muse Spark 1.3 Contributor",
75260
+ api: "openai-responses",
75261
+ protocolSource: "builtin",
75262
+ contextWindow: 1048576,
75263
+ maxTokens: 131072,
75264
+ assumedLimits: false,
75265
+ input: [
75266
+ "text",
75267
+ "image"
75268
+ ],
75269
+ inputModalities: [
75270
+ "text",
75271
+ "image",
75272
+ "audio",
75273
+ "video",
75274
+ "pdf"
75275
+ ],
75276
+ reasoning: true,
75277
+ thinkingLevelMap: {
75278
+ off: null,
75279
+ minimal: "minimal",
75280
+ low: "low",
75281
+ medium: "medium",
75282
+ high: "high",
75283
+ xhigh: "xhigh",
75284
+ max: null
75285
+ },
75286
+ compat: {
75287
+ sessionAffinityFormat: "openai-nosession"
75288
+ },
75289
+ cost: {
75290
+ input: 0.1,
75291
+ output: 0.2,
75292
+ cacheRead: 2e-3,
75293
+ cacheWrite: 0
75294
+ },
75295
+ deprecated: false,
75296
+ releaseDate: "2026-09-02"
75297
+ },
75298
+ "glm-5.3-flash": {
75299
+ id: "glm-5.3-flash",
75300
+ name: "GLM-5.3-Flash",
75301
+ api: "openai-completions",
75302
+ protocolSource: "builtin",
75303
+ contextWindow: 1e6,
75304
+ maxTokens: 131072,
75305
+ assumedLimits: false,
75306
+ input: [
75307
+ "text",
75308
+ "image"
75309
+ ],
75310
+ inputModalities: [
75311
+ "text",
75312
+ "image",
75313
+ "video"
75314
+ ],
75315
+ reasoning: true,
75316
+ thinkingLevelMap: {
75317
+ off: null,
75318
+ minimal: null,
75319
+ low: "low",
75320
+ medium: null,
75321
+ high: "high",
75322
+ xhigh: null,
75323
+ max: "max"
75324
+ },
75325
+ compat: {
75326
+ supportsStore: false,
75327
+ supportsDeveloperRole: false,
75328
+ maxTokensField: "max_tokens",
75329
+ requiresReasoningContentOnAssistantMessages: true,
75330
+ supportsStrictMode: true
75331
+ },
75332
+ cost: {
75333
+ input: 0.15,
75334
+ output: 0.5,
75335
+ cacheRead: 0.03,
75336
+ cacheWrite: 0
75337
+ },
75338
+ deprecated: false,
75339
+ releaseDate: "2026-08-26"
75340
+ },
75341
+ "gpt-5.6-luna": {
75342
+ id: "gpt-5.6-luna",
75343
+ name: "GPT-5.6 Luna",
75344
+ api: "openai-responses",
75345
+ protocolSource: "builtin",
75346
+ contextWindow: 105e4,
75347
+ maxInputTokens: 922e3,
75348
+ maxTokens: 128e3,
75349
+ assumedLimits: false,
75350
+ input: [
75351
+ "text",
75352
+ "image"
75353
+ ],
75354
+ inputModalities: [
75355
+ "text",
75356
+ "image",
75357
+ "pdf"
75358
+ ],
75359
+ reasoning: true,
75360
+ thinkingLevelMap: {
75361
+ off: "none",
75362
+ minimal: null,
75363
+ low: "low",
75364
+ medium: "medium",
75365
+ high: "high",
75366
+ xhigh: "xhigh",
75367
+ max: "max"
75368
+ },
75369
+ compat: {
75370
+ sessionAffinityFormat: "openai-nosession",
75371
+ supportsMidConvoSystemMessages: true,
75372
+ supportsAdditionalTools: true
75373
+ },
75374
+ cost: {
75375
+ input: 0.2,
75376
+ output: 1.2,
75377
+ cacheRead: 0.02,
75378
+ cacheWrite: 0.25,
75379
+ tiers: [
75380
+ {
75381
+ input: 0.4,
75382
+ output: 1.8,
75383
+ cacheRead: 0.04,
75384
+ cacheWrite: 0.5,
75385
+ inputTokensAbove: 272e3
75386
+ }
75387
+ ]
75388
+ },
75389
+ deprecated: false,
75390
+ releaseDate: "2026-07-09"
75391
+ },
75392
+ "gpt-6-luna": {
75393
+ id: "gpt-6-luna",
75394
+ name: "GPT-6 Luna",
75395
+ api: "openai-responses",
75396
+ protocolSource: "builtin",
75397
+ contextWindow: 105e4,
75398
+ maxInputTokens: 922e3,
75399
+ maxTokens: 128e3,
75400
+ assumedLimits: false,
75401
+ input: [
75402
+ "text",
75403
+ "image"
75404
+ ],
75405
+ inputModalities: [
75406
+ "text",
75407
+ "image",
75408
+ "pdf"
75409
+ ],
75410
+ reasoning: true,
75411
+ thinkingLevelMap: {
75412
+ off: "none",
75413
+ minimal: null,
75414
+ low: "low",
75415
+ medium: "medium",
75416
+ high: "high",
75417
+ xhigh: "xhigh",
75418
+ max: "max"
75419
+ },
75420
+ compat: {
75421
+ sessionAffinityFormat: "openai-nosession",
75422
+ supportsMidConvoSystemMessages: true,
75423
+ supportsAdditionalTools: true
75424
+ },
75425
+ cost: {
75426
+ input: 0.1,
75427
+ output: 0.5,
75428
+ cacheRead: 0.01,
75429
+ cacheWrite: 0.125,
75430
+ tiers: [
75431
+ {
75432
+ input: 0.2,
75433
+ output: 0.75,
75434
+ cacheRead: 0.02,
75435
+ cacheWrite: 0.25,
75436
+ inputTokensAbove: 272e3
75437
+ }
75438
+ ]
75439
+ },
75440
+ deprecated: false,
75441
+ releaseDate: "2026-09-22"
75442
+ },
75443
+ "claude-haiku-5-5": {
75444
+ id: "claude-haiku-5-5",
75445
+ name: "Claude Haiku 5.5",
75446
+ api: "anthropic-messages",
75447
+ protocolSource: "builtin",
75448
+ contextWindow: 1e6,
75449
+ maxTokens: 128e3,
75450
+ assumedLimits: false,
75451
+ input: [
75452
+ "text",
75453
+ "image"
75454
+ ],
75455
+ inputModalities: [
75456
+ "text",
75457
+ "image",
75458
+ "pdf"
75459
+ ],
75460
+ reasoning: true,
75461
+ thinkingLevelMap: {
75462
+ off: null,
75463
+ minimal: null,
75464
+ low: "low",
75465
+ medium: "medium",
75466
+ high: "high",
75467
+ xhigh: "xhigh",
75468
+ max: "max"
75469
+ },
75470
+ compat: {
75471
+ forceAdaptiveThinking: true,
75472
+ supportsTemperature: false
75473
+ },
75474
+ cost: {
75475
+ input: 0.1,
75476
+ output: 0.5,
75477
+ cacheRead: 0.01,
75478
+ cacheWrite: 0.125,
75479
+ tiers: [
75480
+ {
75481
+ input: 0.5,
75482
+ output: 2.5,
75483
+ cacheRead: 0.05,
75484
+ cacheWrite: 0.625,
75485
+ inputTokensAbove: 1e5
75486
+ }
75487
+ ]
75488
+ },
75489
+ deprecated: false,
75490
+ releaseDate: "2026-10-07"
75491
+ },
75492
+ hy3: {
75493
+ id: "hy3",
75494
+ name: "Hy3",
75495
+ api: "openai-completions",
75496
+ protocolSource: "builtin",
75497
+ contextWindow: 256e3,
75498
+ maxInputTokens: 192e3,
75499
+ maxTokens: 128e3,
75500
+ assumedLimits: false,
75501
+ input: [
75502
+ "text"
75503
+ ],
75504
+ inputModalities: [
75505
+ "text"
75506
+ ],
75507
+ reasoning: true,
75508
+ thinkingLevelMap: {
75509
+ off: "none",
75510
+ minimal: null,
75511
+ low: "low",
75512
+ medium: null,
75513
+ high: "high",
75514
+ xhigh: null,
75515
+ max: null
75516
+ },
75517
+ compat: {
75518
+ supportsStore: false,
75519
+ supportsDeveloperRole: false,
75520
+ maxTokensField: "max_tokens",
75521
+ supportsStrictMode: true
75522
+ },
75523
+ cost: {
75524
+ input: 0.14,
75525
+ output: 0.58,
75526
+ cacheRead: 0.035,
75527
+ cacheWrite: 0
75528
+ },
75529
+ deprecated: false,
75530
+ releaseDate: "2026-07-06"
75531
+ },
75532
+ "hy4-preview": {
75533
+ id: "hy4-preview",
75534
+ name: "Hy4 preview",
75535
+ api: "openai-completions",
75536
+ protocolSource: "builtin",
75537
+ contextWindow: 1024e3,
75538
+ maxTokens: 64e3,
75539
+ assumedLimits: false,
75540
+ input: [
75541
+ "text"
75542
+ ],
75543
+ inputModalities: [
75544
+ "text"
75545
+ ],
75546
+ reasoning: true,
75547
+ thinkingLevelMap: {
75548
+ off: "none",
75549
+ minimal: null,
75550
+ low: null,
75551
+ medium: null,
75552
+ high: "high",
75553
+ xhigh: null,
75554
+ max: null
75555
+ },
75556
+ compat: {
75557
+ supportsStore: false,
75558
+ supportsDeveloperRole: false,
75559
+ maxTokensField: "max_tokens",
75560
+ supportsStrictMode: true
75561
+ },
75562
+ cost: {
75563
+ input: 0.834,
75564
+ output: 2.501,
75565
+ cacheRead: 0.042,
75566
+ cacheWrite: 0
75567
+ },
75568
+ deprecated: false,
75569
+ releaseDate: "2026-08-28"
75570
+ },
75571
+ "kimi-k2.7-code": {
75572
+ id: "kimi-k2.7-code",
75573
+ name: "Kimi K2.7 Code",
75574
+ api: "openai-completions",
75575
+ protocolSource: "builtin",
75576
+ contextWindow: 262144,
75577
+ maxTokens: 262144,
75578
+ assumedLimits: false,
75579
+ input: [
75580
+ "text",
75581
+ "image"
75582
+ ],
75583
+ inputModalities: [
75584
+ "text",
75585
+ "image",
75586
+ "video"
75587
+ ],
75588
+ reasoning: true,
75589
+ thinkingLevelMap: {
75590
+ off: null,
75591
+ minimal: null,
75592
+ low: null,
75593
+ medium: null,
75594
+ high: null,
75595
+ xhigh: null,
75596
+ max: null
75597
+ },
75598
+ compat: {
75599
+ supportsStore: false,
75600
+ supportsDeveloperRole: false,
75601
+ maxTokensField: "max_tokens",
75602
+ requiresReasoningContentOnAssistantMessages: true,
75603
+ supportsStrictMode: true
75604
+ },
75605
+ cost: {
75606
+ input: 0.95,
75607
+ output: 4,
75608
+ cacheRead: 0.19,
75609
+ cacheWrite: 0
75610
+ },
75611
+ deprecated: false,
75612
+ releaseDate: "2026-06-12"
75613
+ },
75614
+ "kimi-k3": {
75615
+ id: "kimi-k3",
75616
+ name: "Kimi K3",
75617
+ api: "openai-completions",
75618
+ protocolSource: "builtin",
75619
+ contextWindow: 1048576,
75620
+ maxTokens: 131072,
75621
+ assumedLimits: false,
75622
+ input: [
75623
+ "text",
75624
+ "image"
75625
+ ],
75626
+ inputModalities: [
75627
+ "text",
75628
+ "image",
75629
+ "video"
75630
+ ],
75631
+ reasoning: true,
75632
+ thinkingLevelMap: {
75633
+ off: null,
75634
+ minimal: null,
75635
+ low: null,
75636
+ medium: null,
75637
+ high: null,
75638
+ xhigh: null,
75639
+ max: "max"
75640
+ },
75641
+ compat: {
75642
+ supportsStore: false,
75643
+ supportsDeveloperRole: false,
75644
+ maxTokensField: "max_tokens",
75645
+ requiresReasoningContentOnAssistantMessages: true,
75646
+ supportsStrictMode: true,
75647
+ supportsMidConvoSystemMessages: true,
75648
+ supportsMidConvoToolAdditions: true
75649
+ },
75650
+ cost: {
75651
+ input: 3,
75652
+ output: 15,
75653
+ cacheRead: 0.3,
75654
+ cacheWrite: 3
75655
+ },
75656
+ deprecated: false,
75657
+ releaseDate: "2026-07-16"
75658
+ },
75659
+ "mimo-v2.6-flash": {
75660
+ id: "mimo-v2.6-flash",
75661
+ name: "MiMo-V2.6-Flash",
75662
+ api: "openai-completions",
75663
+ protocolSource: "builtin",
75664
+ contextWindow: 1048576,
75665
+ maxTokens: 131072,
75666
+ assumedLimits: false,
75667
+ input: [
75668
+ "text",
75669
+ "image"
75670
+ ],
75671
+ inputModalities: [
75672
+ "text",
75673
+ "image",
75674
+ "audio",
75675
+ "video"
75676
+ ],
75677
+ reasoning: true,
75678
+ thinkingLevelMap: {
75679
+ off: null,
75680
+ minimal: null,
75681
+ low: null,
75682
+ medium: null,
75683
+ high: null,
75684
+ xhigh: null,
75685
+ max: null
75686
+ },
75687
+ compat: {
75688
+ supportsStore: false,
75689
+ supportsDeveloperRole: false,
75690
+ maxTokensField: "max_tokens",
75691
+ requiresReasoningContentOnAssistantMessages: true,
75692
+ supportsStrictMode: true
75693
+ },
75694
+ cost: {
75695
+ input: 0.14,
75696
+ output: 0.28,
75697
+ cacheRead: 28e-4,
75698
+ cacheWrite: 0
75699
+ },
75700
+ deprecated: false,
75701
+ releaseDate: "2026-09-22"
75702
+ },
75703
+ "mimo-v2.6-pro": {
75704
+ id: "mimo-v2.6-pro",
75705
+ name: "MiMo-V2.6-Pro",
75706
+ api: "openai-completions",
75707
+ protocolSource: "builtin",
75708
+ contextWindow: 1048576,
75709
+ maxTokens: 131072,
75710
+ assumedLimits: false,
75711
+ input: [
75712
+ "text",
75713
+ "image"
75714
+ ],
75715
+ inputModalities: [
75716
+ "text",
75717
+ "image",
75718
+ "audio",
75719
+ "video"
75720
+ ],
75721
+ reasoning: true,
75722
+ thinkingLevelMap: {
75723
+ off: null,
75724
+ minimal: null,
75725
+ low: null,
75726
+ medium: null,
75727
+ high: null,
75728
+ xhigh: null,
75729
+ max: null
75730
+ },
75731
+ compat: {
75732
+ supportsStore: false,
75733
+ supportsDeveloperRole: false,
75734
+ maxTokensField: "max_tokens",
75735
+ requiresReasoningContentOnAssistantMessages: true,
75736
+ supportsStrictMode: true
75737
+ },
75738
+ cost: {
75739
+ input: 0.435,
75740
+ output: 0.87,
75741
+ cacheRead: 3625e-6,
75742
+ cacheWrite: 0
75743
+ },
75744
+ deprecated: false,
75745
+ releaseDate: "2026-09-22"
75746
+ },
75747
+ "minimax-m3": {
75748
+ id: "minimax-m3",
75749
+ name: "MiniMax-M3",
75750
+ api: "anthropic-messages",
75751
+ protocolSource: "builtin",
75752
+ contextWindow: 1e6,
75753
+ maxTokens: 131072,
75754
+ assumedLimits: false,
75755
+ input: [
75756
+ "text",
75757
+ "image"
75758
+ ],
75759
+ inputModalities: [
75760
+ "text",
75761
+ "image",
75762
+ "video"
75763
+ ],
75764
+ reasoning: true,
75765
+ thinkingLevelMap: {
75766
+ off: null,
75767
+ minimal: null,
75768
+ low: null,
75769
+ medium: null,
75770
+ high: null,
75771
+ xhigh: null,
75772
+ max: null
75773
+ },
75774
+ compat: {},
75775
+ cost: {
75776
+ input: 0.3,
75777
+ output: 1.2,
75778
+ cacheRead: 0.06,
75779
+ cacheWrite: 0,
75780
+ tiers: [
75781
+ {
75782
+ input: 0.6,
75783
+ output: 2.4,
75784
+ cacheRead: 0.12,
75785
+ cacheWrite: 0,
75786
+ inputTokensAbove: 512e3
75787
+ }
75788
+ ]
75789
+ },
75790
+ deprecated: false,
75791
+ releaseDate: "2026-06-01"
75792
+ },
75793
+ "minimax-m3.1-flash": {
75794
+ id: "minimax-m3.1-flash",
75795
+ name: "MiniMax M3.1 Flash",
75796
+ api: "openai-completions",
75797
+ protocolSource: "document",
75798
+ contextWindow: 1e6,
75799
+ maxTokens: 512e3,
75800
+ assumedLimits: false,
75801
+ input: [
75802
+ "text",
75803
+ "image"
75804
+ ],
75805
+ inputModalities: [
75806
+ "text",
75807
+ "image",
75808
+ "video"
75809
+ ],
75810
+ reasoning: true,
75811
+ thinkingLevelMap: {
75812
+ off: null,
75813
+ minimal: null,
75814
+ low: "low",
75815
+ medium: "medium",
75816
+ high: "high",
75817
+ xhigh: "xhigh",
75818
+ max: "max"
75819
+ },
75820
+ compat: {
75821
+ supportsStore: false,
75822
+ supportsDeveloperRole: false,
75823
+ maxTokensField: "max_tokens",
75824
+ requiresReasoningContentOnAssistantMessages: true,
75825
+ supportsStrictMode: true
75826
+ },
75827
+ cost: {
75828
+ input: 0.15,
75829
+ output: 0.6,
75830
+ cacheRead: 0.015,
75831
+ cacheWrite: 0
75832
+ },
75833
+ deprecated: false,
75834
+ releaseDate: "2026-10-19"
75835
+ },
75836
+ "longcat-2.0": {
75837
+ id: "longcat-2.0",
75838
+ name: "LongCat-2.0",
75839
+ api: "openai-completions",
75840
+ protocolSource: "builtin",
75841
+ contextWindow: 1e6,
75842
+ maxTokens: 131072,
75843
+ assumedLimits: false,
75844
+ input: [
75845
+ "text"
75846
+ ],
75847
+ inputModalities: [
75848
+ "text"
75849
+ ],
75850
+ reasoning: true,
75851
+ thinkingLevelMap: {
75852
+ off: null,
75853
+ minimal: null,
75854
+ low: null,
75855
+ medium: null,
75856
+ high: null,
75857
+ xhigh: null,
75858
+ max: null
75859
+ },
75860
+ compat: {
75861
+ supportsStore: false,
75862
+ supportsDeveloperRole: false,
75863
+ maxTokensField: "max_tokens",
75864
+ requiresReasoningContentOnAssistantMessages: true,
75865
+ supportsStrictMode: true
75866
+ },
75867
+ cost: {
75868
+ input: 0.3,
75869
+ output: 1.2,
75870
+ cacheRead: 6e-3,
75871
+ cacheWrite: 0
75872
+ },
75873
+ deprecated: false,
75874
+ releaseDate: "2026-06-30"
75875
+ },
75876
+ "step-5-preview": {
75877
+ id: "step-5-preview",
75878
+ name: "Step 5 Preview",
75879
+ api: "openai-completions",
75880
+ protocolSource: "builtin",
75881
+ contextWindow: 1e6,
75882
+ maxInputTokens: 1e6,
75883
+ maxTokens: 65536,
75884
+ assumedLimits: false,
75885
+ input: [
75886
+ "text",
75887
+ "image"
75888
+ ],
75889
+ inputModalities: [
75890
+ "text",
75891
+ "image",
75892
+ "video"
75893
+ ],
75894
+ reasoning: true,
75895
+ thinkingLevelMap: {
75896
+ off: null,
75897
+ minimal: null,
75898
+ low: "low",
75899
+ medium: "medium",
75900
+ high: "high",
75901
+ xhigh: null,
75902
+ max: null
75903
+ },
75904
+ compat: {
75905
+ supportsStore: false,
75906
+ supportsDeveloperRole: false,
75907
+ maxTokensField: "max_tokens",
75908
+ requiresReasoningContentOnAssistantMessages: true,
75909
+ supportsStrictMode: true
75910
+ },
75911
+ cost: {
75912
+ input: 1,
75913
+ output: 2.7,
75914
+ cacheRead: 0.1,
75915
+ cacheWrite: 0
75916
+ },
75917
+ deprecated: false,
75918
+ releaseDate: "2026-09-16"
75919
+ },
75920
+ "beam-free": {
75921
+ id: "beam-free",
75922
+ name: "Beam Free",
75923
+ api: "openai-completions",
75924
+ protocolSource: "builtin",
75925
+ contextWindow: 1048576,
75926
+ maxTokens: 131072,
75927
+ assumedLimits: false,
75928
+ input: [
75929
+ "text"
75930
+ ],
75931
+ inputModalities: [
75932
+ "text"
75933
+ ],
75934
+ reasoning: true,
75935
+ thinkingLevelMap: {
75936
+ off: null,
75937
+ minimal: null,
75938
+ low: "low",
75939
+ medium: "medium",
75940
+ high: "high",
75941
+ xhigh: "xhigh",
75942
+ max: "max"
75943
+ },
75944
+ compat: {
75945
+ supportsStore: false,
75946
+ supportsDeveloperRole: false,
75947
+ maxTokensField: "max_tokens",
75948
+ requiresReasoningContentOnAssistantMessages: true,
75949
+ supportsStrictMode: true
75950
+ },
75951
+ cost: {
75952
+ input: 0,
75953
+ output: 0,
75954
+ cacheRead: 0,
75955
+ cacheWrite: 0
75956
+ },
75957
+ deprecated: false,
75958
+ releaseDate: "2026-10-05"
75959
+ },
75960
+ "qwen3.8-max": {
75961
+ id: "qwen3.8-max",
75962
+ name: "Qwen3.8 Max",
75963
+ api: "anthropic-messages",
75964
+ protocolSource: "builtin",
75965
+ contextWindow: 1e6,
75966
+ maxTokens: 131072,
75967
+ assumedLimits: false,
75968
+ input: [
75969
+ "text",
75970
+ "image"
75971
+ ],
75972
+ inputModalities: [
75973
+ "text",
75974
+ "image",
75975
+ "video"
75976
+ ],
75977
+ reasoning: true,
75978
+ thinkingLevelMap: {
75979
+ off: null,
75980
+ minimal: null,
75981
+ low: "low",
75982
+ medium: "medium",
75983
+ high: null,
75984
+ xhigh: "xhigh",
75985
+ max: null
75986
+ },
75987
+ compat: {},
75988
+ cost: {
75989
+ input: 2,
75990
+ output: 6,
75991
+ cacheRead: 0.25,
75992
+ cacheWrite: 2.5
75993
+ },
75994
+ deprecated: false,
75995
+ releaseDate: "2026-08-03"
75996
+ },
75997
+ "qwen3.8-flash": {
75998
+ id: "qwen3.8-flash",
75999
+ name: "Qwen3.8 Flash",
76000
+ api: "anthropic-messages",
76001
+ protocolSource: "builtin",
76002
+ contextWindow: 1e6,
76003
+ maxTokens: 131072,
76004
+ assumedLimits: false,
76005
+ input: [
76006
+ "text",
76007
+ "image"
76008
+ ],
76009
+ inputModalities: [
76010
+ "text",
76011
+ "image",
76012
+ "video"
76013
+ ],
76014
+ reasoning: true,
76015
+ thinkingLevelMap: {
76016
+ off: null,
76017
+ minimal: null,
76018
+ low: "low",
76019
+ medium: "medium",
76020
+ high: null,
76021
+ xhigh: "xhigh",
76022
+ max: null
76023
+ },
76024
+ compat: {
76025
+ allowEmptySignature: true
76026
+ },
76027
+ cost: {
76028
+ input: 0.15,
76029
+ output: 0.47,
76030
+ cacheRead: 0.016,
76031
+ cacheWrite: 0.2
76032
+ },
76033
+ deprecated: false,
76034
+ releaseDate: "2026-08-26"
76035
+ },
76036
+ "qwen3.7-plus": {
76037
+ id: "qwen3.7-plus",
76038
+ name: "Qwen3.7 Plus",
76039
+ api: "anthropic-messages",
76040
+ protocolSource: "builtin",
76041
+ contextWindow: 1e6,
76042
+ maxTokens: 65536,
76043
+ assumedLimits: false,
76044
+ input: [
76045
+ "text",
76046
+ "image"
76047
+ ],
76048
+ inputModalities: [
76049
+ "text",
76050
+ "image",
76051
+ "video"
76052
+ ],
76053
+ reasoning: true,
76054
+ thinkingLevelMap: {
76055
+ off: null,
76056
+ minimal: null,
76057
+ low: null,
76058
+ medium: null,
76059
+ high: null,
76060
+ xhigh: null,
76061
+ max: null
76062
+ },
76063
+ compat: {},
76064
+ cost: {
76065
+ input: 0.4,
76066
+ output: 1.6,
76067
+ cacheRead: 0.04,
76068
+ cacheWrite: 0.5,
76069
+ tiers: [
76070
+ {
76071
+ input: 1.2,
76072
+ output: 4.8,
76073
+ cacheRead: 0.12,
76074
+ cacheWrite: 1.5,
76075
+ inputTokensAbove: 256e3
76076
+ }
76077
+ ]
76078
+ },
76079
+ deprecated: false,
76080
+ releaseDate: "2026-06-02"
76081
+ },
76082
+ "kimi-k3.1-pro": {
76083
+ id: "kimi-k3.1-pro",
76084
+ name: "Kimi K3.1 Pro",
76085
+ api: "openai-completions",
76086
+ protocolSource: "document",
76087
+ contextWindow: 1048576,
76088
+ maxTokens: 131072,
76089
+ assumedLimits: false,
76090
+ input: [
76091
+ "text",
76092
+ "image"
76093
+ ],
76094
+ inputModalities: [
76095
+ "text",
76096
+ "image",
76097
+ "video"
76098
+ ],
76099
+ reasoning: true,
76100
+ thinkingLevelMap: {
76101
+ off: null,
76102
+ minimal: null,
76103
+ low: "low",
76104
+ medium: null,
76105
+ high: "high",
76106
+ xhigh: null,
76107
+ max: "max"
76108
+ },
76109
+ compat: {
76110
+ supportsStore: false,
76111
+ supportsDeveloperRole: false,
76112
+ maxTokensField: "max_tokens",
76113
+ requiresReasoningContentOnAssistantMessages: true,
76114
+ supportsStrictMode: true,
76115
+ supportsMidConvoSystemMessages: true,
76116
+ supportsMidConvoToolAdditions: true
76117
+ },
76118
+ cost: {
76119
+ input: 2,
76120
+ output: 10,
76121
+ cacheRead: 0.2,
76122
+ cacheWrite: 2
76123
+ },
76124
+ deprecated: false,
76125
+ releaseDate: "2026-10-23"
76126
+ },
76127
+ "iceman-contributor-free": {
76128
+ id: "iceman-contributor-free",
76129
+ name: "Iceman Contributor Free",
76130
+ api: "openai-completions",
76131
+ protocolSource: "document",
76132
+ contextWindow: 262144,
76133
+ maxTokens: 131072,
76134
+ assumedLimits: false,
76135
+ input: [
76136
+ "text"
76137
+ ],
76138
+ inputModalities: [
76139
+ "text"
76140
+ ],
76141
+ reasoning: true,
76142
+ thinkingLevelMap: {
76143
+ off: null,
76144
+ minimal: null,
76145
+ low: null,
76146
+ medium: null,
76147
+ high: null,
76148
+ xhigh: null,
76149
+ max: null
76150
+ },
76151
+ compat: {
76152
+ supportsStore: false,
76153
+ supportsDeveloperRole: false,
76154
+ maxTokensField: "max_tokens"
76155
+ },
76156
+ cost: {
76157
+ input: 0,
76158
+ output: 0,
76159
+ cacheRead: 0,
76160
+ cacheWrite: 0
76161
+ },
76162
+ deprecated: false,
76163
+ releaseDate: "2026-10-24"
76164
+ },
76165
+ "gemini-4-argon": {
76166
+ id: "gemini-4-argon",
76167
+ name: "Gemini 4 Argon",
76168
+ api: "openai-completions",
76169
+ protocolSource: "inferred",
76170
+ contextWindow: 1048576,
76171
+ maxTokens: 65536,
76172
+ assumedLimits: false,
76173
+ input: [
76174
+ "text",
76175
+ "image"
76176
+ ],
76177
+ inputModalities: [
76178
+ "text",
76179
+ "image",
76180
+ "audio",
76181
+ "video",
76182
+ "pdf"
76183
+ ],
76184
+ reasoning: true,
76185
+ thinkingLevelMap: {
76186
+ off: null,
76187
+ minimal: null,
76188
+ low: "low",
76189
+ medium: "medium",
76190
+ high: "high",
76191
+ xhigh: null,
76192
+ max: null
76193
+ },
76194
+ compat: {
76195
+ supportsStore: false,
76196
+ supportsDeveloperRole: false,
76197
+ maxTokensField: "max_tokens"
76198
+ },
76199
+ cost: {
76200
+ input: 2,
76201
+ output: 10,
76202
+ cacheRead: 0.1,
76203
+ cacheWrite: 0
76204
+ },
76205
+ deprecated: false,
76206
+ releaseDate: "2026-10-13"
76207
+ }
76208
+ },
76209
+ protocols: {
76210
+ "grok-4.7": "openai-responses",
76211
+ "gpt-6-luna": "openai-responses",
76212
+ "gpt-5.6-luna": "openai-responses",
76213
+ "claude-haiku-5-5": "anthropic-messages",
76214
+ "glm-5.3-flash": "openai-completions",
76215
+ "glm-5.3": "openai-completions",
76216
+ "glm-5.2": "openai-completions",
76217
+ "kimi-k3.1-pro": "openai-completions",
76218
+ "kimi-k3": "openai-completions",
76219
+ "kimi-k2.7-code": "openai-completions",
76220
+ "longcat-2.0": "openai-completions",
76221
+ "deepseek-v4.1-flash": "openai-completions",
76222
+ "deepseek-v4-pro": "openai-completions",
76223
+ "mimo-v2.6-flash": "openai-completions",
76224
+ "mimo-v2.6-pro": "openai-completions",
76225
+ "mimo-v2.5": "openai-completions",
76226
+ "mimo-v2.5-pro": "openai-completions",
76227
+ "minimax-m3.1-flash": "openai-completions",
76228
+ "minimax-m3": "anthropic-messages",
76229
+ "muse-spark-1.3-contributor": "openai-responses",
76230
+ "muse-spark-1.2-contributor": "openai-responses",
76231
+ "qwen3.8-max": "anthropic-messages",
76232
+ "qwen3.8-flash": "anthropic-messages",
76233
+ "qwen3.7-plus": "anthropic-messages",
76234
+ "hy4-preview": "openai-completions",
76235
+ hy3: "openai-completions",
76236
+ "step-5-preview": "openai-completions",
76237
+ "beam-free": "openai-completions",
76238
+ "iceman-contributor-free": "openai-completions"
76239
+ },
76240
+ updatedAt: 1793342934047,
76241
+ baseURL: "https://opencode.ai/inference/go/v1"
76242
+ };
76243
+
74975
76244
  // src/config.ts
74976
76245
  import { LlmError as LlmError5, RetryPolicySchema } from "@deepseek-ai/dsh-llm";
74977
76246
  import { MAX_TIMER_DELAY_MS } from "@deepseek-ai/dsh-timeout";
@@ -76803,6 +78072,9 @@ var OpencodeGoAdapter = class extends LlmAdapter {
76803
78072
  input: ["text"]
76804
78073
  },
76805
78074
  overrides: config.modelProtocols,
78075
+ // The bundled seed is validated (and endpoint-checked) by the
78076
+ // catalog; an out-of-date or foreign seed reads as absent.
78077
+ seed: seed_snapshot_default,
76806
78078
  ...this.options.readDocument === void 0 ? {} : { readDocument: this.options.readDocument },
76807
78079
  ...this.options.cacheDir === void 0 ? {} : { cacheDir: this.options.cacheDir },
76808
78080
  ...this.options.fetch === void 0 ? {} : { fetch: this.options.fetch },
@@ -76907,30 +78179,113 @@ var OpencodeGoAdapter = class extends LlmAdapter {
76907
78179
  "UNSUPPORTED_REASONING_EFFORT"
76908
78180
  );
76909
78181
  }
78182
+ /**
78183
+ * Open the request's log row.
78184
+ *
78185
+ * Called before any wait the request may hit — the catalog included — so
78186
+ * a cold catalog reads as preparation instead of invisible time, and a
78187
+ * failure before the first byte still leaves a row behind. Everything
78188
+ * here is already known or pure: the protocol arrives later, through
78189
+ * `identify`, once the catalog has answered.
78190
+ */
78191
+ startSpan(options, config, protocol) {
78192
+ const containsImage = options.messages.some((message) => contentHasImage2(message.content));
78193
+ const headers = providerHeaders(options.sessionId === void 0 ? void 0 : String(options.sessionId));
78194
+ const imageBudget = IMAGE_BUDGETS[config.imageBudgetPreset];
78195
+ const imageBytes = containsImage ? estimateImageWireBytes(options.messages, imageBudget.maxBytes) : void 0;
78196
+ return this.options.requestLog?.start({
78197
+ model: options.model,
78198
+ sessionId: options.sessionId === void 0 ? void 0 : String(options.sessionId),
78199
+ ...protocol === void 0 ? {} : { protocol },
78200
+ method: "POST",
78201
+ url: config.baseURL,
78202
+ messageCount: options.messages.length,
78203
+ hasImage: containsImage,
78204
+ toolCount: options.tools?.length ?? 0,
78205
+ ...imageBytes === void 0 ? {} : { imageBytes },
78206
+ headers: {
78207
+ ...options.sessionId === void 0 ? {} : { session: String(options.sessionId) },
78208
+ ...typeof headers["user-agent"] === "string" ? { userAgent: headers["user-agent"] } : {}
78209
+ }
78210
+ });
78211
+ }
78212
+ /**
78213
+ * Record a failure that happened before any request was built.
78214
+ *
78215
+ * Preparation (unlike dispatch) knows no session and no messages, so the
78216
+ * row reads as unbuilt rather than empty — but it still names the model
78217
+ * and the code, instead of leaving the caller with an error the log never
78218
+ * heard of.
78219
+ */
78220
+ logUnstartedFailure(config, model, error) {
78221
+ this.options.requestLog?.start({
78222
+ model,
78223
+ sessionId: void 0,
78224
+ method: "POST",
78225
+ url: config.baseURL,
78226
+ messageCount: 0,
78227
+ hasImage: false,
78228
+ toolCount: 0,
78229
+ headers: {}
78230
+ })?.finish(false, error instanceof LlmError9 ? error.code : void 0);
78231
+ }
76910
78232
  async prepareCall(_provider, model, _signal) {
76911
78233
  const config = this.options.config();
76912
78234
  assertStreamIdleTimeoutMs(config.streamIdleTimeoutMs);
76913
- const snapshot2 = await this.catalogOf(config).forModel(model);
78235
+ let snapshot2;
78236
+ try {
78237
+ snapshot2 = await this.catalogOf(config).forModel(model);
78238
+ } catch (error) {
78239
+ this.logUnstartedFailure(config, model, error);
78240
+ throw error;
78241
+ }
76914
78242
  const facts = snapshot2.facts.get(model);
76915
- if (facts === void 0) throw new LlmError9(`opencode-go has no model "${model}"`, "UNKNOWN_MODEL");
78243
+ if (facts === void 0) {
78244
+ const error = new LlmError9(`opencode-go has no model "${model}"`, "UNKNOWN_MODEL");
78245
+ this.logUnstartedFailure(config, model, error);
78246
+ throw error;
78247
+ }
76916
78248
  const prepared = this.modelInfo(withModelLimit(toPiModel(facts, config.baseURL), config.modelLimits));
76917
78249
  return {
76918
78250
  model: prepared,
76919
- stream: (options) => this.streamWithSnapshot(options, config, snapshot2)
78251
+ stream: (options) => {
78252
+ const span = this.startSpan(options, config, facts.api);
78253
+ return this.streamWithSnapshot(options, config, snapshot2, span);
78254
+ }
76920
78255
  };
76921
78256
  }
76922
78257
  async *stream(options) {
76923
78258
  const config = this.options.config();
76924
78259
  assertStreamIdleTimeoutMs(config.streamIdleTimeoutMs);
76925
- const snapshot2 = await this.catalogOf(config).forModel(options.model);
76926
- yield* this.streamWithSnapshot(options, config, snapshot2);
78260
+ const span = this.startSpan(options, config);
78261
+ let snapshot2;
78262
+ try {
78263
+ snapshot2 = await this.catalogOf(config).forModel(options.model);
78264
+ } catch (error) {
78265
+ span?.finish(false, error instanceof LlmError9 ? error.code : void 0);
78266
+ throw error;
78267
+ }
78268
+ yield* this.streamWithSnapshot(options, config, snapshot2, span);
76927
78269
  }
76928
- async *streamWithSnapshot(options, config, snapshot2) {
78270
+ async *streamWithSnapshot(options, config, snapshot2, outerSpan) {
76929
78271
  var _stack = [];
76930
78272
  try {
76931
- assertStreamIdleTimeoutMs(config.streamIdleTimeoutMs);
78273
+ const span = outerSpan ?? this.startSpan(options, config);
78274
+ const failSpan = (error) => {
78275
+ span?.finish(false, error instanceof LlmError9 ? error.code : void 0);
78276
+ throw error;
78277
+ };
78278
+ try {
78279
+ assertStreamIdleTimeoutMs(config.streamIdleTimeoutMs);
78280
+ } catch (error) {
78281
+ failSpan(error);
78282
+ }
76932
78283
  const facts = snapshot2.facts.get(options.model);
76933
- if (facts === void 0) throw new LlmError9(`opencode-go has no model "${options.model}"`, "UNKNOWN_MODEL");
78284
+ if (facts === void 0) {
78285
+ const error = new LlmError9(`opencode-go has no model "${options.model}"`, "UNKNOWN_MODEL");
78286
+ span?.finish(false, error.code);
78287
+ throw error;
78288
+ }
76934
78289
  const model = withModelLimit(toPiModel(facts, config.baseURL), config.modelLimits);
76935
78290
  const rates2 = usableRates(facts.cost);
76936
78291
  const stop = stopSequencesFor(model, options.stop);
@@ -76938,32 +78293,24 @@ var OpencodeGoAdapter = class extends LlmAdapter {
76938
78293
  const maxTokens = options.maxTokens === void 0 || ceiling === null || ceiling === void 0 ? options.maxTokens : Math.min(options.maxTokens, ceiling);
76939
78294
  const apiKey = await this.options.resolveApiKey();
76940
78295
  if (apiKey === void 0 || apiKey.length === 0) {
76941
- throw new LlmError9("dshopencodego: no credential resolved for the opencode-go route", "MISSING_CREDENTIAL");
78296
+ const error = new LlmError9("dshopencodego: no credential resolved for the opencode-go route", "MISSING_CREDENTIAL");
78297
+ span?.finish(false, error.code);
78298
+ throw error;
78299
+ }
78300
+ let reasoning;
78301
+ try {
78302
+ reasoning = this.resolveReasoningLevel(model, options.reasoningEffort);
78303
+ } catch (error) {
78304
+ failSpan(error);
76942
78305
  }
76943
- const reasoning = this.resolveReasoningLevel(model, options.reasoningEffort);
76944
78306
  const consumer = new AbortController();
76945
78307
  const upstream = options.signal === void 0 ? consumer.signal : AbortSignal.any([options.signal, consumer.signal]);
76946
78308
  const watchdog = __using(_stack, idleWatchdog(upstream, config.streamIdleTimeoutMs, "LLM_STREAM_IDLE_TIMEOUT"));
76947
78309
  let timedOut = false;
78310
+ span?.identify(facts.api);
76948
78311
  const containsImage = options.messages.some((message) => contentHasImage2(message.content));
76949
78312
  const headers = providerHeaders(options.sessionId === void 0 ? void 0 : String(options.sessionId));
76950
78313
  const imageBudget = IMAGE_BUDGETS[config.imageBudgetPreset];
76951
- const imageBytes = containsImage ? estimateImageWireBytes(options.messages, imageBudget.maxBytes) : void 0;
76952
- const span = this.options.requestLog?.start({
76953
- model: options.model,
76954
- sessionId: options.sessionId === void 0 ? void 0 : String(options.sessionId),
76955
- protocol: facts.api,
76956
- method: "POST",
76957
- url: config.baseURL,
76958
- messageCount: options.messages.length,
76959
- hasImage: containsImage,
76960
- toolCount: options.tools?.length ?? 0,
76961
- ...imageBytes === void 0 ? {} : { imageBytes },
76962
- headers: {
76963
- ...options.sessionId === void 0 ? {} : { session: String(options.sessionId) },
76964
- ...typeof headers["user-agent"] === "string" ? { userAgent: headers["user-agent"] } : {}
76965
- }
76966
- });
76967
78314
  const fetchFactory = this.options.fetch;
76968
78315
  const requestFetch = span === void 0 || fetchFactory === void 0 ? fetchFactory : () => {
76969
78316
  const base = fetchFactory();
@@ -77937,6 +79284,9 @@ var RequestLog = class {
77937
79284
  let reported = false;
77938
79285
  let finished = false;
77939
79286
  return {
79287
+ identify: (protocol) => {
79288
+ if (record2.protocol === void 0) record2.protocol = protocol;
79289
+ },
77940
79290
  token: () => {
77941
79291
  const now = Date.now();
77942
79292
  if (firstTokenAt === void 0) {
@@ -77969,7 +79319,10 @@ var RequestLog = class {
77969
79319
  seq,
77970
79320
  atMs: startedAt,
77971
79321
  model: detail.model,
77972
- ...detail.protocol === void 0 ? {} : { protocol: detail.protocol },
79322
+ // The protocol may have arrived after the row opened, through
79323
+ // `identify` — the running row and the completion read the same
79324
+ // field, so they never disagree.
79325
+ ...record2.protocol === void 0 ? {} : { protocol: record2.protocol },
77973
79326
  session,
77974
79327
  method: record2.method,
77975
79328
  url: record2.url,
@@ -78134,7 +79487,7 @@ function createUpdateChecker(deps) {
78134
79487
  }
78135
79488
 
78136
79489
  // src/update/version.ts
78137
- var PLUGIN_VERSION = true ? "0.1.82" : "0.0.0-dev";
79490
+ var PLUGIN_VERSION = true ? "0.1.84" : "0.0.0-dev";
78138
79491
 
78139
79492
  // src/update/service.ts
78140
79493
  import { TypertRemoteService as TypertRemoteService4 } from "@deepseek-ai/dsh-typert-protocol";
@@ -78382,8 +79735,15 @@ function apply(ctx, raw) {
78382
79735
  });
78383
79736
  ctx.plugin(OpencodeGoUpdateService, { currentVersion: PLUGIN_VERSION });
78384
79737
  ctx.effect(() => {
78385
- void adapter.catalogOf(current2()).snapshot().catch(() => void 0);
79738
+ const refresh = () => {
79739
+ void adapter.catalogOf(current2()).snapshot().catch(() => void 0);
79740
+ };
79741
+ refresh();
79742
+ const intervalMs = Math.min(Math.max(current2().refreshMinutes, 1) * 6e4, MAX_CATALOG_STALENESS_MS);
79743
+ const timer = setInterval(refresh, intervalMs);
79744
+ if (typeof timer.unref === "function") timer.unref();
78386
79745
  return () => {
79746
+ clearInterval(timer);
78387
79747
  };
78388
79748
  }, "dshopencodego: catalog warm-up");
78389
79749
  let registration;