@ashlr/hub 3.7.0 → 3.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. package/CHANGELOG.md +257 -0
  2. package/dist/build-identity.json +2 -2
  3. package/dist/cli/resource-profile.js +95 -21
  4. package/dist/cli/resource-profile.js.map +1 -1
  5. package/dist/core/policy/local-only.d.ts +142 -2
  6. package/dist/core/policy/local-only.js +204 -15
  7. package/dist/core/policy/local-only.js.map +1 -1
  8. package/dist/core/resources/native-profile.d.ts +56 -0
  9. package/dist/core/resources/native-profile.js +368 -6
  10. package/dist/core/resources/native-profile.js.map +1 -1
  11. package/dist/core/run/budget.d.ts +22 -8
  12. package/dist/core/run/budget.js +80 -12
  13. package/dist/core/run/budget.js.map +1 -1
  14. package/dist/core/run/model-catalog.js +8 -1
  15. package/dist/core/run/model-catalog.js.map +1 -1
  16. package/dist/core/run/sandboxed-engine.js +3 -3
  17. package/dist/core/run/sandboxed-engine.js.map +1 -1
  18. package/dist/core/universe/builtins/preparation/manifest.json +1 -1
  19. package/dist/core/universe/builtins/preparation/preparation-bridge.mjs +69 -10
  20. package/dist/core/universe/builtins/preparation/preparation-verification-fixtures.mjs +68 -9
  21. package/dist/core/verse/adapters/claude.d.ts +49 -2
  22. package/dist/core/verse/adapters/claude.js +317 -56
  23. package/dist/core/verse/adapters/claude.js.map +1 -1
  24. package/dist/core/verse/adapters/codex.d.ts +81 -5
  25. package/dist/core/verse/adapters/codex.js +409 -47
  26. package/dist/core/verse/adapters/codex.js.map +1 -1
  27. package/dist/core/verse/adapters/grok.d.ts +13 -1
  28. package/dist/core/verse/adapters/grok.js +28 -2
  29. package/dist/core/verse/adapters/grok.js.map +1 -1
  30. package/dist/core/verse/adapters/index.d.ts +32 -0
  31. package/dist/core/verse/adapters/index.js +2 -0
  32. package/dist/core/verse/adapters/index.js.map +1 -1
  33. package/dist/core/verse/codex-rollout.d.ts +284 -0
  34. package/dist/core/verse/codex-rollout.js +786 -0
  35. package/dist/core/verse/codex-rollout.js.map +1 -0
  36. package/dist/core/verse/context-fit.d.ts +63 -0
  37. package/dist/core/verse/context-fit.js +355 -0
  38. package/dist/core/verse/context-fit.js.map +1 -0
  39. package/dist/core/verse/context-math.d.ts +215 -0
  40. package/dist/core/verse/context-math.js +365 -0
  41. package/dist/core/verse/context-math.js.map +1 -0
  42. package/dist/core/verse/local-models.d.ts +137 -1
  43. package/dist/core/verse/local-models.js +209 -5
  44. package/dist/core/verse/local-models.js.map +1 -1
  45. package/dist/core/verse/model-windows.d.ts +217 -0
  46. package/dist/core/verse/model-windows.js +616 -0
  47. package/dist/core/verse/model-windows.js.map +1 -0
  48. package/dist/core/verse/preferences.d.ts +123 -0
  49. package/dist/core/verse/preferences.js +403 -0
  50. package/dist/core/verse/preferences.js.map +1 -0
  51. package/dist/core/verse/project-memory.d.ts +112 -0
  52. package/dist/core/verse/project-memory.js +295 -0
  53. package/dist/core/verse/project-memory.js.map +1 -0
  54. package/dist/core/verse/seats.d.ts +106 -4
  55. package/dist/core/verse/seats.js +291 -89
  56. package/dist/core/verse/seats.js.map +1 -1
  57. package/dist/core/verse/session-engine.d.ts +117 -2
  58. package/dist/core/verse/session-engine.js +763 -65
  59. package/dist/core/verse/session-engine.js.map +1 -1
  60. package/dist/core/verse/session-handoff.d.ts +94 -0
  61. package/dist/core/verse/session-handoff.js +551 -0
  62. package/dist/core/verse/session-handoff.js.map +1 -0
  63. package/dist/core/verse/session-search.d.ts +63 -0
  64. package/dist/core/verse/session-search.js +213 -0
  65. package/dist/core/verse/session-search.js.map +1 -0
  66. package/dist/core/verse/session-store.d.ts +16 -2
  67. package/dist/core/verse/session-store.js +80 -6
  68. package/dist/core/verse/session-store.js.map +1 -1
  69. package/dist/core/verse/types.d.ts +333 -1
  70. package/dist/core/verse/types.js +54 -2
  71. package/dist/core/verse/types.js.map +1 -1
  72. package/dist/core/verse/verse-api.d.ts +40 -5
  73. package/dist/core/verse/verse-api.js +724 -25
  74. package/dist/core/verse/verse-api.js.map +1 -1
  75. package/dist/core/web/api.d.ts +14 -4
  76. package/dist/core/web/api.js +26 -11
  77. package/dist/core/web/api.js.map +1 -1
  78. package/dist/core/web/public/next/assets/{App-vtaHB9mp.js → App-XURmiAAp.js} +5 -5
  79. package/dist/core/web/public/next/assets/{App-vtaHB9mp.js.map → App-XURmiAAp.js.map} +1 -1
  80. package/dist/core/web/public/next/assets/{ApprovalsSection-B-bFJ0I9.js → ApprovalsSection-BriUzoZc.js} +2 -2
  81. package/dist/core/web/public/next/assets/{ApprovalsSection-B-bFJ0I9.js.map → ApprovalsSection-BriUzoZc.js.map} +1 -1
  82. package/dist/core/web/public/next/assets/AutonomySection-C4GBsQVc.js +2 -0
  83. package/dist/core/web/public/next/assets/{AutonomySection-DoqmsCjw.js.map → AutonomySection-C4GBsQVc.js.map} +1 -1
  84. package/dist/core/web/public/next/assets/ChatSection-BpOBOUvg.css +1 -0
  85. package/dist/core/web/public/next/assets/ChatSection-hlgPBRco.js +84 -0
  86. package/dist/core/web/public/next/assets/ChatSection-hlgPBRco.js.map +1 -0
  87. package/dist/core/web/public/next/assets/ConfirmDialog-BdQYI-Ng.js +2 -0
  88. package/dist/core/web/public/next/assets/ConfirmDialog-BdQYI-Ng.js.map +1 -0
  89. package/dist/core/web/public/next/assets/{Dialog-CPM9JxBc.js → Dialog-BxdIfmFH.js} +2 -2
  90. package/dist/core/web/public/next/assets/{Dialog-CPM9JxBc.js.map → Dialog-BxdIfmFH.js.map} +1 -1
  91. package/dist/core/web/public/next/assets/{DiffViewer-B84qVef9.js → DiffViewer-DmeRWuc4.js} +2 -2
  92. package/dist/core/web/public/next/assets/{DiffViewer-B84qVef9.js.map → DiffViewer-DmeRWuc4.js.map} +1 -1
  93. package/dist/core/web/public/next/assets/{McpSection-CEUpV_5X.js → McpSection-q34T7Tho.js} +2 -2
  94. package/dist/core/web/public/next/assets/{McpSection-CEUpV_5X.js.map → McpSection-q34T7Tho.js.map} +1 -1
  95. package/dist/core/web/public/next/assets/{MutationTokenDialog-DA8t97XT.js → MutationTokenDialog-CFAkwOEt.js} +2 -2
  96. package/dist/core/web/public/next/assets/{MutationTokenDialog-DA8t97XT.js.map → MutationTokenDialog-CFAkwOEt.js.map} +1 -1
  97. package/dist/core/web/public/next/assets/{ResourcePoolConsoleApp-Bq7Vyud0.js → ResourcePoolConsoleApp-DHc8GFOY.js} +4 -4
  98. package/dist/core/web/public/next/assets/{ResourcePoolConsoleApp-Bq7Vyud0.js.map → ResourcePoolConsoleApp-DHc8GFOY.js.map} +1 -1
  99. package/dist/core/web/public/next/assets/{RouteErrorBoundary-Badio_uO.js → RouteErrorBoundary-ZL9F4qUn.js} +2 -2
  100. package/dist/core/web/public/next/assets/{RouteErrorBoundary-Badio_uO.js.map → RouteErrorBoundary-ZL9F4qUn.js.map} +1 -1
  101. package/dist/core/web/public/next/assets/{Meter-CLcr-4wS.css → Segmented-8cf0Fypn.css} +1 -1
  102. package/dist/core/web/public/next/assets/{Meter--h3MmZS-.js → Segmented-DbRjVye3.js} +2 -2
  103. package/dist/core/web/public/next/assets/Segmented-DbRjVye3.js.map +1 -0
  104. package/dist/core/web/public/next/assets/SettingsSection-nJGGGYqv.js +2 -0
  105. package/dist/core/web/public/next/assets/{SettingsSection-BwrpQlpP.js.map → SettingsSection-nJGGGYqv.js.map} +1 -1
  106. package/dist/core/web/public/next/assets/UniverseConsoleApp-6GJydgo4.js +2 -0
  107. package/dist/core/web/public/next/assets/{UniverseConsoleApp-_FSohAdN.js.map → UniverseConsoleApp-6GJydgo4.js.map} +1 -1
  108. package/dist/core/web/public/next/assets/{UniverseView-DqcXbed4.js → UniverseView-DLDtNYL8.js} +2 -2
  109. package/dist/core/web/public/next/assets/{UniverseView-DqcXbed4.js.map → UniverseView-DLDtNYL8.js.map} +1 -1
  110. package/dist/core/web/public/next/assets/UsageSection-Cf9d9iFH.js +2 -0
  111. package/dist/core/web/public/next/assets/UsageSection-Cf9d9iFH.js.map +1 -0
  112. package/dist/core/web/public/next/assets/VerseConsoleApp-DsdKQoTH.css +1 -0
  113. package/dist/core/web/public/next/assets/VerseConsoleApp-y0uOHixd.js +3 -0
  114. package/dist/core/web/public/next/assets/VerseConsoleApp-y0uOHixd.js.map +1 -0
  115. package/dist/core/web/public/next/assets/{charts-CTZJ-JrH.js → charts-CVooqJWN.js} +2 -2
  116. package/dist/core/web/public/next/assets/{charts-CTZJ-JrH.js.map → charts-CVooqJWN.js.map} +1 -1
  117. package/dist/core/web/public/next/assets/context-model-Bqv8DVuH.js +2 -0
  118. package/dist/core/web/public/next/assets/context-model-Bqv8DVuH.js.map +1 -0
  119. package/dist/core/web/public/next/assets/global-eaY9GyX3.js +2 -0
  120. package/dist/core/web/public/next/assets/global-eaY9GyX3.js.map +1 -0
  121. package/dist/core/web/public/next/assets/{icons-D9vlf85u.js → icons-vex8rclC.js} +2 -2
  122. package/dist/core/web/public/next/assets/{icons-D9vlf85u.js.map → icons-vex8rclC.js.map} +1 -1
  123. package/dist/core/web/public/next/assets/{index-CZamKRUg.js → index-D2Eik-zt.js} +3 -3
  124. package/dist/core/web/public/next/assets/{index-CZamKRUg.js.map → index-D2Eik-zt.js.map} +1 -1
  125. package/dist/core/web/public/next/assets/{queries-B8eBnFox.js → queries-bAYU0VNy.js} +2 -2
  126. package/dist/core/web/public/next/assets/{queries-B8eBnFox.js.map → queries-bAYU0VNy.js.map} +1 -1
  127. package/dist/core/web/public/next/assets/use-guarded-action-C7QrP7Yp.js +2 -0
  128. package/dist/core/web/public/next/assets/{use-guarded-action-bzrVVAYq.js.map → use-guarded-action-C7QrP7Yp.js.map} +1 -1
  129. package/dist/core/web/public/next/assets/verse-model-TfDk9cky.js +2 -0
  130. package/dist/core/web/public/next/assets/verse-model-TfDk9cky.js.map +1 -0
  131. package/dist/core/web/public/next/assets/{workspace-model-v0a1gl-C.js → workspace-model-CHol5RVp.js} +2 -2
  132. package/dist/core/web/public/next/assets/{workspace-model-v0a1gl-C.js.map → workspace-model-CHol5RVp.js.map} +1 -1
  133. package/dist/core/web/public/next/index.html +1 -1
  134. package/dist/release-dependency-inventory.json +1 -1
  135. package/docs/README.md +1 -0
  136. package/package.json +1 -1
  137. package/dist/core/web/public/next/assets/AutonomySection-DoqmsCjw.js +0 -2
  138. package/dist/core/web/public/next/assets/ChatSection-BfnLe5dT.css +0 -1
  139. package/dist/core/web/public/next/assets/ChatSection-vNPIJffd.js +0 -80
  140. package/dist/core/web/public/next/assets/ChatSection-vNPIJffd.js.map +0 -1
  141. package/dist/core/web/public/next/assets/ConfirmDialog-Dd2APQhB.js +0 -2
  142. package/dist/core/web/public/next/assets/ConfirmDialog-Dd2APQhB.js.map +0 -1
  143. package/dist/core/web/public/next/assets/Meter--h3MmZS-.js.map +0 -1
  144. package/dist/core/web/public/next/assets/SettingsSection-BwrpQlpP.js +0 -2
  145. package/dist/core/web/public/next/assets/UniverseConsoleApp-_FSohAdN.js +0 -2
  146. package/dist/core/web/public/next/assets/UsageSection-Bq6Daaby.js +0 -2
  147. package/dist/core/web/public/next/assets/UsageSection-Bq6Daaby.js.map +0 -1
  148. package/dist/core/web/public/next/assets/VerseConsoleApp-CMkCizvL.css +0 -1
  149. package/dist/core/web/public/next/assets/VerseConsoleApp-CsIQv9id.js +0 -3
  150. package/dist/core/web/public/next/assets/VerseConsoleApp-CsIQv9id.js.map +0 -1
  151. package/dist/core/web/public/next/assets/global-D6bTxIRn.js +0 -2
  152. package/dist/core/web/public/next/assets/global-D6bTxIRn.js.map +0 -1
  153. package/dist/core/web/public/next/assets/use-guarded-action-bzrVVAYq.js +0 -2
  154. package/dist/core/web/public/next/assets/verse-model-CvtK6vP6.js +0 -2
  155. package/dist/core/web/public/next/assets/verse-model-CvtK6vP6.js.map +0 -1
@@ -1951,13 +1951,20 @@ var init_model_catalog = __esm({
1951
1951
  // minEffort 2: measured ~590 s/task against 53-381 s for the previous
1952
1952
  // generation. Consistent, but too slow to be the pick for trivial work —
1953
1953
  // `maxEffort: 1` queries keep falling through to the lighter entries.
1954
+ //
1955
+ // NO 'long-context' (Verse 3.9). The tag is `…-ctx64k`: its Modelfile pins
1956
+ // `num_ctx 65536`, Ollama serves it at exactly 65536 (`n_ctx_slot = 65536`
1957
+ // in every server log), and on the llama-server lane each slot gets 65536
1958
+ // too. That is below the >=100k the capability promises, so tagging it sent
1959
+ // long-context work to a model that would overflow. The architecture's
1960
+ // 262144 is reachable only through a differently pinned tag.
1954
1961
  {
1955
1962
  id: `local-coder:${DEFAULT_LOCAL_MODEL_TAG}`,
1956
1963
  engine: "local-coder",
1957
1964
  tier: "mid",
1958
1965
  costPerMTokIn: 0,
1959
1966
  costPerMTokOut: 0,
1960
- capabilities: ["coder", "reasoning", "long-context"],
1967
+ capabilities: ["coder", "reasoning"],
1961
1968
  minEffort: 2
1962
1969
  },
1963
1970
  // -- Local -- small (catch-all tiny model for trivial tasks) --------------
@@ -3171,6 +3178,33 @@ function engineLocality(engine, cfg, env = process.env) {
3171
3178
  function providerLocality(providerId) {
3172
3179
  return LOCAL_PROVIDER_IDS.has(providerId.trim().toLowerCase()) ? "local" : "cloud";
3173
3180
  }
3181
+ function endpointMeteredness(baseUrl) {
3182
+ if (typeof baseUrl !== "string" || baseUrl.trim().length === 0) return "unknown";
3183
+ try {
3184
+ new URL(baseUrl.trim());
3185
+ } catch {
3186
+ return "unknown";
3187
+ }
3188
+ return isLoopbackEndpoint(baseUrl) ? "free" : "metered";
3189
+ }
3190
+ function providerMeteredness(providerId) {
3191
+ return LOCAL_PROVIDER_IDS.has(providerId.trim().toLowerCase()) ? "free" : "metered";
3192
+ }
3193
+ function engineMeteredness(engine, cfg, env = process.env) {
3194
+ const id3 = engine.trim().toLowerCase();
3195
+ if (id3 === ALWAYS_PERMITTED_ENGINE) return "free";
3196
+ const spec = resolveEngineSpec(engine, cfg);
3197
+ if (!spec) {
3198
+ if (id3 === "llama-server") return endpointMeteredness(llamaServerBaseUrl(cfg, env));
3199
+ return "unknown";
3200
+ }
3201
+ if (spec.kind === "builtin") return "free";
3202
+ if (spec.kind === "cli-agent") return CLI_AGENT_METEREDNESS[id3] ?? "unknown";
3203
+ const api = spec.api;
3204
+ const fromEnv = api?.baseUrlEnv ? env[api.baseUrlEnv]?.trim() : void 0;
3205
+ const baseUrl = (fromEnv && fromEnv.length > 0 ? fromEnv : void 0) ?? api?.defaultBaseUrl;
3206
+ return endpointMeteredness(baseUrl);
3207
+ }
3174
3208
  function engineIdForBin(bin, cfg) {
3175
3209
  const raw = bin.trim();
3176
3210
  if (raw.length === 0) return void 0;
@@ -3186,25 +3220,37 @@ function engineIdForBin(bin, cfg) {
3186
3220
  }
3187
3221
  function decidePermission(subject, cfg, env = process.env) {
3188
3222
  const mode = resolveLocalOnlyMode(cfg, env);
3189
- if (!mode.enabled || subject.locality === "local") {
3223
+ if (!mode.enabled || subject.meteredness === "free") {
3190
3224
  return { permitted: true, subject, mode, reason: null };
3191
3225
  }
3192
3226
  return { permitted: false, subject, mode, reason: refusalReason(subject, mode) };
3193
3227
  }
3194
3228
  function refusalReason(subject, mode) {
3195
3229
  const noun = SUBJECT_NOUN[subject.kind];
3196
- return `local-only: refusing to dispatch to cloud ${noun} '${subject.id}'. ${mode.detail} No cloud ${noun} is reachable while local-only is on \u2014 run this work on a local engine (builtin, local-coder, llama-server), or turn the mode off with cfg.foundry.localOnly=false (and unset ${LOCAL_ONLY_ENV_VAR}).`;
3230
+ const head = subject.meteredness === "unknown" ? `local-only: refusing to dispatch to ${noun} '${subject.id}' \u2014 the hub cannot verify it is free. It may reach a paid backend after dispatch and nothing here would see it, so it is not provably free and is refused. ` : `local-only: refusing to dispatch to cloud ${noun} '${subject.id}'. `;
3231
+ const tail = subject.meteredness === "unknown" ? "" : `No cloud ${noun} is reachable while local-only is on \u2014 `;
3232
+ return `${head}${mode.detail} ${tail}run this work on a local engine (builtin, local-coder, llama-server), or turn the mode off with cfg.foundry.localOnly=false (and unset ${LOCAL_ONLY_ENV_VAR}).`;
3197
3233
  }
3198
3234
  function enginePermitted(engine, cfg, env = process.env) {
3199
3235
  return decidePermission(
3200
- { kind: "engine", id: engine, locality: engineLocality(engine, cfg, env) },
3236
+ {
3237
+ kind: "engine",
3238
+ id: engine,
3239
+ locality: engineLocality(engine, cfg, env),
3240
+ meteredness: engineMeteredness(engine, cfg, env)
3241
+ },
3201
3242
  cfg,
3202
3243
  env
3203
3244
  );
3204
3245
  }
3205
3246
  function providerPermitted(providerId, cfg, env = process.env) {
3206
3247
  return decidePermission(
3207
- { kind: "provider", id: providerId, locality: providerLocality(providerId) },
3248
+ {
3249
+ kind: "provider",
3250
+ id: providerId,
3251
+ locality: providerLocality(providerId),
3252
+ meteredness: providerMeteredness(providerId)
3253
+ },
3208
3254
  cfg,
3209
3255
  env
3210
3256
  );
@@ -3214,7 +3260,8 @@ function endpointPermitted(baseUrl, cfg, env = process.env) {
3214
3260
  {
3215
3261
  kind: "endpoint",
3216
3262
  id: baseUrl,
3217
- locality: isLoopbackEndpoint(baseUrl) ? "local" : "cloud"
3263
+ locality: isLoopbackEndpoint(baseUrl) ? "local" : "cloud",
3264
+ meteredness: endpointMeteredness(baseUrl)
3218
3265
  },
3219
3266
  cfg,
3220
3267
  env
@@ -3225,7 +3272,10 @@ function binPermitted(bin, cfg, env = process.env) {
3225
3272
  if (id3 === void 0) {
3226
3273
  return {
3227
3274
  permitted: true,
3228
- subject: { kind: "engine", id: bin, locality: "local" },
3275
+ // Deliberate: an executable no engine claims is outside the roster this
3276
+ // policy governs, so it is 'free' in the only sense that applies — the
3277
+ // hub is not handing it a seat, or credentials, or work.
3278
+ subject: { kind: "engine", id: bin, locality: "local", meteredness: "free" },
3229
3279
  mode: resolveLocalOnlyMode(cfg, env),
3230
3280
  reason: null
3231
3281
  };
@@ -3233,12 +3283,12 @@ function binPermitted(bin, cfg, env = process.env) {
3233
3283
  return enginePermitted(id3, cfg, env);
3234
3284
  }
3235
3285
  function cloudSubjectPermitted(kind, id3, cfg, env = process.env) {
3236
- return decidePermission({ kind, id: id3, locality: "cloud" }, cfg, env);
3286
+ return decidePermission({ kind, id: id3, locality: "cloud", meteredness: "metered" }, cfg, env);
3237
3287
  }
3238
3288
  function assertPermitted(verdict) {
3239
3289
  if (!verdict.permitted) throw new LocalOnlyRefusal(verdict);
3240
3290
  }
3241
- var LOCAL_ONLY_ENV_VAR, ENV_OFF_TOKENS, latchedConfigLocalOnly, LOCAL_CLI_AGENTS, LOCAL_PROVIDER_IDS, ALWAYS_PERMITTED_ENGINE, SUBJECT_NOUN, LocalOnlyRefusal;
3291
+ var LOCAL_ONLY_ENV_VAR, ENV_OFF_TOKENS, latchedConfigLocalOnly, LOCAL_CLI_AGENTS, LOCAL_PROVIDER_IDS, ALWAYS_PERMITTED_ENGINE, CLI_AGENT_METEREDNESS, SUBJECT_NOUN, LocalOnlyRefusal;
3242
3292
  var init_local_only = __esm({
3243
3293
  "src/core/policy/local-only.ts"() {
3244
3294
  "use strict";
@@ -3256,6 +3306,14 @@ var init_local_only = __esm({
3256
3306
  "builtin"
3257
3307
  ]);
3258
3308
  ALWAYS_PERMITTED_ENGINE = "builtin";
3309
+ CLI_AGENT_METEREDNESS = Object.freeze({
3310
+ claude: "metered",
3311
+ codex: "metered",
3312
+ hermes: "metered",
3313
+ opencode: "metered",
3314
+ ashlrcode: "metered",
3315
+ aw: "unknown"
3316
+ });
3259
3317
  SUBJECT_NOUN = {
3260
3318
  engine: "engine",
3261
3319
  provider: "provider",
@@ -29949,6 +30007,7 @@ var init_budget_alert = __esm({
29949
30007
  var init_budget = __esm({
29950
30008
  "src/core/run/budget.ts"() {
29951
30009
  "use strict";
30010
+ init_local_only();
29952
30011
  }
29953
30012
  });
29954
30013
 
@@ -11,6 +11,25 @@
11
11
  * llama-server lane — the normalising proxy in front of llama-server. The
12
12
  * adapter does not choose; it forwards the choice `seats.ts` already made.
13
13
  *
14
+ * V3.9 context flags (docs/VERSE-CONTEXT.md). Every flag and env var below was
15
+ * checked on BOTH binaries a seat can be pinned to — `claude --help` on
16
+ * 2.1.257 and 2.1.280 lists `--autocompact <auto|tokens>`,
17
+ * `--append-system-prompt <prompt>`, `--add-dir <directories...>` and
18
+ * `--exclude-dynamic-system-prompt-sections`, and both binaries' strings
19
+ * contain `CLAUDE_CODE_MAX_CONTEXT_TOKENS`:
20
+ *
21
+ * - claude seats, 1M-native models: `--autocompact 400000` in standard mode,
22
+ * `--autocompact auto` in expansive (context-math `claudeAutocompactFlag`).
23
+ * 200k models get no flag — they already compact near 167k natively.
24
+ * - local seats: `CLAUDE_CODE_MAX_CONTEXT_TOKENS=<the session's window>` so
25
+ * the CLI compacts before Ollama truncates (without it the CLI assumes its
26
+ * 200k unknown-model default and never compacts a 64k runner), plus
27
+ * `--exclude-dynamic-system-prompt-sections` so the per-launch git status
28
+ * and env block stop invalidating the local runner's prefix cache.
29
+ * - shared project memory (launch.memory): `--add-dir <dir>` when writable and
30
+ * `--append-system-prompt=<block>`, the SAME snapshotted block every turn so
31
+ * the prompt prefix stays byte-identical.
32
+ *
14
33
  * Parse: claude's stream-json is JSONL where streaming deltas are wrapped as
15
34
  * `{type:'stream_event', event:{...Anthropic Messages wire event}}` and whole
16
35
  * messages arrive as `{type:'assistant'|'user', message:{content:[...]}}`,
@@ -21,17 +40,45 @@ import type { VerseAdapter, VerseTurnParser } from './index.js';
21
40
  type JsonObject = Record<string, unknown>;
22
41
  /** Parse one JSONL line into an object, or null for anything that is not one. */
23
42
  export declare function parseJsonObjectLine(line: string): JsonObject | null;
43
+ /**
44
+ * The context window the CLI reported for this turn's model in
45
+ * `result.modelUsage` — the same number it compacts against, computed at
46
+ * result time, so it already reflects a long-context credit clamp (1M → 200k)
47
+ * or grok's mid-session window upgrade.
48
+ *
49
+ * Which row: `modelUsage` is keyed per model and a turn can touch several
50
+ * (claude runs side calls on Haiku). So, in order:
51
+ * 1. the row whose key IS the turn's model (canonicalised — a record naming
52
+ * the retired alias `claude-opus-5.5` still finds `claude-opus-5-5`);
53
+ * 2. the same comparison with a `[1m]` suffix stripped from both sides;
54
+ * 3. the ONLY row carrying a numeric `contextWindow` — grok's key can differ
55
+ * from the CLI id (`grok-4.6-build` for `grok-4.6`) and grok puts the
56
+ * window on the current model's row alone.
57
+ * Anything else (several windowed rows, none matching) is ambiguous and yields
58
+ * null: an unknown window is shown as unknown, never guessed.
59
+ */
60
+ export declare function runtimeContextWindow(modelUsage: unknown, model: string | null): number | null;
24
61
  /**
25
62
  * Shared parser for the Anthropic Messages wire format. Accepts:
26
63
  * - bare wire events (`message_start`, `content_block_start`, `content_block_delta`,
27
64
  * `content_block_stop`, `message_delta`, `message_stop`) — grok's streaming-messages-json;
28
65
  * - the same events wrapped in claude's `{type:'stream_event', event:{...}}`;
29
- * - claude's whole-message envelopes `assistant` / `user` and the terminal `result`;
30
- * - `system` (`init` captures session_id).
66
+ * - claude's whole-message envelopes `assistant` / `user` and the terminal `result`
67
+ * (whose `modelUsage` carries the CLI's context window for the turn);
68
+ * - `system` (`init` captures session_id and model; `compact_boundary`
69
+ * becomes a `compaction` event).
31
70
  *
32
71
  * A text/tool_use/thinking block can arrive twice — once via the streamed
33
72
  * content_block_* events and again inside an `assistant` envelope — so block
34
73
  * events are deduplicated by content within a turn.
74
+ *
75
+ * Usage is deduplicated the same way, by API call. With partial messages on,
76
+ * ONE call is reported by `message_start` + `message_delta` AND by one
77
+ * `assistant` envelope per content block. Summing every report (as this parser
78
+ * once did) counted a two-block call three times; the turn total only looked
79
+ * right because the terminal `result` replaced it. Each call is keyed by its
80
+ * message id and its readings are merged, so the fallback total is right too
81
+ * when a process dies before `result`.
35
82
  */
36
83
  /**
37
84
  * Shared by the claude/local and grok adapters — both speak the Anthropic wire