mixdog 1.3.4 → 1.3.5

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 (197) hide show
  1. package/LICENSES/oh-my-pi-MIT.txt +23 -0
  2. package/NOTICE.md +15 -0
  3. package/README.md +11 -0
  4. package/package.json +2 -1
  5. package/scripts/embed-google-oauth-client.mjs +49 -0
  6. package/scripts/lib/test-spawn-ledger.mjs +46 -1
  7. package/scripts/test.mjs +5 -0
  8. package/src/defaults/shipped-history.json +8 -0
  9. package/src/defaults/skills/browser-use/SKILL.md +21 -9
  10. package/src/defaults/skills/setup/SKILL.md +7 -2
  11. package/src/defaults/skills/setup/references/actions.md +82 -27
  12. package/src/defaults/skills/setup/references/surfaces.md +67 -34
  13. package/src/defaults/skills/setup-guide/SKILL.md +3 -3
  14. package/src/lib/keychain-cjs.cjs +359 -29
  15. package/src/rules/agent-mode/AGENT_MODE.md +10 -2
  16. package/src/rules/agent-mode/MIXY.md +12 -0
  17. package/src/runtime/agent/orchestrator/agent-runtime/heartbeat-completion.mjs +193 -0
  18. package/src/runtime/agent/orchestrator/config.mjs +18 -0
  19. package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +2 -2
  20. package/src/runtime/agent/orchestrator/mcp/client.mjs +6 -2
  21. package/src/runtime/agent/orchestrator/mcp/oauth-callback.mjs +31 -2
  22. package/src/runtime/agent/orchestrator/mcp/oauth-client.mjs +16 -3
  23. package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +42 -7
  24. package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +21 -2
  25. package/src/runtime/agent/orchestrator/mcp/oauth-shared.mjs +23 -0
  26. package/src/runtime/agent/orchestrator/mcp/oauth.mjs +11 -1
  27. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +68 -23
  28. package/src/runtime/agent/orchestrator/providers/admission-scheduler.mjs +22 -1
  29. package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +18 -5
  30. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  31. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +15 -3
  32. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +52 -8
  33. package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +10 -1
  34. package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +22 -6
  35. package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +15 -4
  36. package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +17 -2
  37. package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +19 -2
  38. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
  39. package/src/runtime/agent/orchestrator/providers/cursor-wire-normalization.mjs +10 -4
  40. package/src/runtime/agent/orchestrator/providers/cursor-wire-protobuf.mjs +10 -217
  41. package/src/runtime/agent/orchestrator/providers/cursor.mjs +7 -0
  42. package/src/runtime/agent/orchestrator/providers/devin-auth.mjs +409 -0
  43. package/src/runtime/agent/orchestrator/providers/devin-wire-families.mjs +187 -0
  44. package/src/runtime/agent/orchestrator/providers/devin-wire-identity.mjs +342 -0
  45. package/src/runtime/agent/orchestrator/providers/devin-wire-models.mjs +541 -0
  46. package/src/runtime/agent/orchestrator/providers/devin-wire-protobuf.mjs +305 -0
  47. package/src/runtime/agent/orchestrator/providers/devin-wire-request.mjs +558 -0
  48. package/src/runtime/agent/orchestrator/providers/devin-wire-schema.mjs +880 -0
  49. package/src/runtime/agent/orchestrator/providers/devin-wire-session.mjs +190 -0
  50. package/src/runtime/agent/orchestrator/providers/devin-wire-tool-args.mjs +351 -0
  51. package/src/runtime/agent/orchestrator/providers/devin-wire-transport.mjs +560 -0
  52. package/src/runtime/agent/orchestrator/providers/devin.mjs +491 -0
  53. package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +3 -0
  54. package/src/runtime/agent/orchestrator/providers/gemini-output-limit.mjs +46 -0
  55. package/src/runtime/agent/orchestrator/providers/gemini-reasoning-relay.mjs +30 -0
  56. package/src/runtime/agent/orchestrator/providers/gemini-request-body.mjs +7 -11
  57. package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +61 -22
  58. package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +1 -0
  59. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +71 -4
  60. package/src/runtime/agent/orchestrator/providers/gemini.mjs +25 -2
  61. package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
  62. package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +96 -5
  63. package/src/runtime/agent/orchestrator/providers/lib/tail-reminder-split.mjs +23 -5
  64. package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +17 -0
  65. package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +39 -3
  66. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +3 -1
  67. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +2 -0
  68. package/src/runtime/agent/orchestrator/providers/openai-error-contract.mjs +6 -1
  69. package/src/runtime/agent/orchestrator/providers/opencode-go-gemini.mjs +1 -0
  70. package/src/runtime/agent/orchestrator/providers/provider-availability.mjs +19 -0
  71. package/src/runtime/agent/orchestrator/providers/registry.mjs +17 -3
  72. package/src/runtime/agent/orchestrator/providers/wire-protobuf-codec.mjs +368 -0
  73. package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +2 -0
  74. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +1 -1
  75. package/src/runtime/agent/orchestrator/runtime-core/reaction-tool-defs.mjs +133 -0
  76. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
  77. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +23 -5
  78. package/src/runtime/agent/orchestrator/runtime-core/tool-profile.mjs +35 -10
  79. package/src/runtime/agent/orchestrator/runtime-core/workflow/agents.mjs +57 -10
  80. package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +9 -6
  81. package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +1 -1
  82. package/src/runtime/agent/orchestrator/session/agent-loop.mjs +18 -0
  83. package/src/runtime/agent/orchestrator/session/agent-room.d.mts +0 -3
  84. package/src/runtime/agent/orchestrator/session/agent-room.mjs +10 -4
  85. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +15 -3
  86. package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +5 -0
  87. package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +36 -4
  88. package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +6 -0
  89. package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +15 -3
  90. package/src/runtime/agent/orchestrator/session/loop/assistant-commit.mjs +8 -0
  91. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +8 -1
  92. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/segments.mjs +4 -1
  93. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +50 -2
  94. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +3 -0
  95. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +11 -2
  96. package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +11 -2
  97. package/src/runtime/agent/orchestrator/session/loop/turn-limits.mjs +60 -0
  98. package/src/runtime/agent/orchestrator/session/manager/ask-turn-commit.mjs +2 -0
  99. package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +14 -0
  100. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +2 -1
  101. package/src/runtime/agent/orchestrator/session/manager/session-tool-surface.mjs +13 -0
  102. package/src/runtime/agent/orchestrator/session/message-ids.mjs +5 -3
  103. package/src/runtime/agent/orchestrator/session/message-reactions.mjs +89 -0
  104. package/src/runtime/agent/orchestrator/session/message-reactions.test-support.mjs +75 -0
  105. package/src/runtime/agent/orchestrator/session/routine-result.d.mts +0 -2
  106. package/src/runtime/agent/orchestrator/session/routine-result.mjs +11 -2
  107. package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +20 -2
  108. package/src/runtime/agent/orchestrator/session/store-agent-worker-header-cache.mjs +85 -0
  109. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +125 -12
  110. package/src/runtime/agent/orchestrator/session/tail-reminder-rules.mjs +11 -5
  111. package/src/runtime/agent/orchestrator/session/tool-batch/state.mjs +4 -0
  112. package/src/runtime/agent/orchestrator/session/tool-batch.mjs +5 -0
  113. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +7 -1
  114. package/src/runtime/channels/lib/schedule-errors.mjs +51 -0
  115. package/src/runtime/channels/lib/scheduler.mjs +109 -14
  116. package/src/runtime/channels/lib/schedules-db.mjs +49 -0
  117. package/src/runtime/channels/lib/tool-dispatch.mjs +13 -0
  118. package/src/runtime/channels/lib/worker-main.mjs +9 -0
  119. package/src/runtime/office/com/com-adapter.mjs +17 -1
  120. package/src/runtime/office/com/office-com-host.ps1 +51 -1
  121. package/src/runtime/office/pdf/cfb-fixture.mjs +328 -0
  122. package/src/runtime/office/pdf/cfb-protection.mjs +311 -0
  123. package/src/runtime/office/pdf/document-preview.mjs +326 -8
  124. package/src/runtime/office/pdf/ooxml-crypto.mjs +469 -0
  125. package/src/runtime/office/pdf/ooxml-key-worker.mjs +14 -0
  126. package/src/runtime/office/portable/portable-soffice.mjs +45 -5
  127. package/src/runtime/shared/bot-hops.mjs +62 -2
  128. package/src/runtime/shared/config.mjs +49 -22
  129. package/src/runtime/shared/connector-catalog.d.mts +4 -2
  130. package/src/runtime/shared/connector-catalog.mjs +16 -8
  131. package/src/runtime/shared/developer-options.mjs +32 -1
  132. package/src/runtime/shared/google-oauth-client.generated.json +4 -0
  133. package/src/runtime/shared/google-oauth-client.mjs +34 -9
  134. package/src/runtime/shared/llm/anthropic-betas.mjs +7 -0
  135. package/src/runtime/shared/llm/anthropic-thinking-contract.mjs +12 -0
  136. package/src/runtime/shared/llm/provider-catalog-registry.mjs +1 -0
  137. package/src/runtime/shared/llm/well-formed.mjs +66 -0
  138. package/src/runtime/shared/provider-accounts.mjs +224 -58
  139. package/src/runtime/shared/provider-api-key.mjs +19 -8
  140. package/src/runtime/shared/routine-trigger.mjs +42 -0
  141. package/src/runtime/shared/tool-execution-contract.mjs +2 -0
  142. package/src/runtime/shared/transcript-metadata.mjs +38 -0
  143. package/src/runtime/shared/user-data-guard.mjs +30 -2
  144. package/src/runtime/shared/worktrees/activity-gate.mjs +12 -5
  145. package/src/session-runtime/agent-home-delivery.mjs +57 -13
  146. package/src/session-runtime/agent-room-delivery.mjs +28 -1
  147. package/src/session-runtime/agent-task-sessions.mjs +292 -79
  148. package/src/session-runtime/boot/begin.mjs +3 -2
  149. package/src/session-runtime/boot/tools.mjs +2 -0
  150. package/src/session-runtime/bot-chain.mjs +32 -0
  151. package/src/session-runtime/bot-status.mjs +7 -4
  152. package/src/session-runtime/channel-config-api.mjs +63 -17
  153. package/src/session-runtime/internal-tool-executor/reaction-tool.mjs +45 -0
  154. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +72 -5
  155. package/src/session-runtime/internal-tool-executor.mjs +4 -0
  156. package/src/session-runtime/mcp-glue/server-catalog.mjs +7 -1
  157. package/src/session-runtime/mixy-heartbeat.mjs +807 -0
  158. package/src/session-runtime/model-route/route-tuning.mjs +10 -6
  159. package/src/session-runtime/owned-automation-run.mjs +33 -12
  160. package/src/session-runtime/provider-auth/login.mjs +7 -0
  161. package/src/session-runtime/provider-models/row-hydration.mjs +13 -2
  162. package/src/session-runtime/routine-home-turn.mjs +33 -6
  163. package/src/session-runtime/schedule-session-run.mjs +7 -3
  164. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +8 -12
  165. package/src/session-runtime/services/channel-admin.mjs +66 -18
  166. package/src/session-runtime/services/channel-worker.mjs +1 -1
  167. package/src/session-runtime/services/provider-admin.mjs +128 -25
  168. package/src/session-runtime/services/schedule-access.mjs +14 -0
  169. package/src/session-runtime/services/usage-dashboard-model.mjs +1 -0
  170. package/src/session-runtime/session-create/session-options.mjs +7 -4
  171. package/src/session-runtime/settings-system-api.mjs +16 -1
  172. package/src/session-runtime/setup-tool/executor.mjs +49 -14
  173. package/src/session-runtime/setup-tool/extended-actions.mjs +29 -3
  174. package/src/session-runtime/setup-tool/settings-contract.mjs +65 -4
  175. package/src/session-runtime/setup-tool/tool-defs.mjs +30 -3
  176. package/src/session-runtime/task-session-route.mjs +99 -0
  177. package/src/session-runtime/tool-policy/policy-stage.mjs +5 -2
  178. package/src/session-runtime/tool-policy/surface-helpers.mjs +2 -3
  179. package/src/session-runtime/tool-surface.mjs +4 -0
  180. package/src/session-runtime/workflow-agents-api/agent-editor.mjs +98 -21
  181. package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +6 -1
  182. package/src/session-runtime/workspace/transitions.mjs +10 -2
  183. package/src/standalone/daemon-session-control.mjs +88 -20
  184. package/src/standalone/daemon.mjs +8 -0
  185. package/src/standalone/session-protocol.mjs +5 -0
  186. package/src/standalone/session-service/agent-tree/agent-cancel.mjs +6 -2
  187. package/src/standalone/session-service/session-calls/session-turns.mjs +6 -0
  188. package/src/standalone/session-service.mjs +13 -0
  189. package/src/standalone/session-tool-output.mjs +8 -5
  190. package/src/tui/app/model-options.mjs +2 -0
  191. package/src/tui/dist/index.mjs +24 -2
  192. package/src/tui/session/notice-surface.mjs +17 -1
  193. package/src/tui/session/session-api/integrations.mjs +1 -0
  194. package/src/tui/session/session-api/lifecycle.mjs +8 -0
  195. package/src/tui/session/session-api/settings.mjs +14 -2
  196. package/src/tui/session/turn-stream.mjs +17 -1
  197. package/src/tui/session/turn.mjs +22 -2
@@ -36,8 +36,18 @@ function retiredModelError(err, streamedText, model) {
36
36
  * @param {Function|null} deps.onToolCall
37
37
  * @param {Function|null} deps.onTextDelta
38
38
  * @param {Function|null} deps.onStreamDelta
39
+ * @param {Function|null} [deps.onReasoningDelta] receives thought-summary text
40
+ * @param {Function|null} [deps.retractReasoning] drops thinking a dead attempt already showed
39
41
  */
40
- export function createAntigravityStreamCollector({ tools, useModel, onToolCall, onTextDelta, onStreamDelta }) {
42
+ export function createAntigravityStreamCollector({
43
+ tools,
44
+ useModel,
45
+ onToolCall,
46
+ onTextDelta,
47
+ onStreamDelta,
48
+ onReasoningDelta = null,
49
+ retractReasoning = null,
50
+ }) {
41
51
  let textLeakGuard = null;
42
52
  let terminalFailure = null;
43
53
  // Streamed text is kept so a retirement notice can be told apart from
@@ -66,6 +76,7 @@ export function createAntigravityStreamCollector({ tools, useModel, onToolCall,
66
76
  // Each attempt starts from an empty record: a replayed request must not
67
77
  // inherit the dead attempt's text or failure.
68
78
  const beginAttempt = () => {
79
+ retractReasoning?.();
69
80
  textLeakGuard = createGeminiTextLeakGuard({
70
81
  knownToolNames: tools?.map((t) => t.name).filter(Boolean) ?? [],
71
82
  onTextDelta: relayText,
@@ -80,6 +91,8 @@ export function createAntigravityStreamCollector({ tools, useModel, onToolCall,
80
91
  textLeakGuard = null;
81
92
  };
82
93
 
94
+ const failureUsage = { model: useModel, normalize: normalizeAntigravityUsage };
95
+
83
96
  const consume = async (res, attemptSignal, { firstByteTimeoutMs } = {}) => {
84
97
  try {
85
98
  return await consumeGeminiRestStreamResponse(res, {
@@ -87,10 +100,11 @@ export function createAntigravityStreamCollector({ tools, useModel, onToolCall,
87
100
  firstByteTimeoutMs,
88
101
  onStreamDelta,
89
102
  onTextDelta: relayText,
103
+ onReasoningDelta,
90
104
  onChunk,
91
105
  textLeakGuard,
92
106
  label: 'Antigravity streamGenerateContent',
93
- failureUsage: { model: useModel, normalize: normalizeAntigravityUsage },
107
+ failureUsage,
94
108
  // Cloud Code Assist nests the Gemini payload under
95
109
  // `response`; in-band error events stay top level.
96
110
  unwrapChunk: (chunk) => (chunk && typeof chunk === 'object' && chunk.response ? chunk.response : chunk),
@@ -105,6 +119,7 @@ export function createAntigravityStreamCollector({ tools, useModel, onToolCall,
105
119
  beginAttempt,
106
120
  releaseGuard,
107
121
  consume,
122
+ failureUsage,
108
123
  get leakGuard() {
109
124
  return textLeakGuard;
110
125
  },
@@ -24,6 +24,7 @@ import { TIMEOUT_PHASE, isFirstByteTimeout } from '../../../shared/provider-time
24
24
  import { getLlmDispatcher } from '../../../shared/llm/http-agent.mjs';
25
25
  import { _scrubTokens } from './antigravity-oauth-tokens.mjs';
26
26
  import { applyGeminiErrorContract } from './gemini-error-contract.mjs';
27
+ import { geminiInvalidStreamReask } from './gemini-retry-policy.mjs';
27
28
  import { DETERMINISTIC_KINDS, providerErrorKind } from './provider-error-kind.mjs';
28
29
 
29
30
  // Rate-limit reason: 503/529 are capacity by status; a
@@ -113,9 +114,10 @@ export function antigravityError(res, text, endpoint) {
113
114
  * @param {string} deps.body serialized request
114
115
  * @param {object} deps.opts send options (stage heartbeat)
115
116
  * @param {AbortSignal|null} deps.signal retry-loop signal (session pass-through)
116
- * @param {{ beginAttempt: Function, consume: Function }} deps.collector
117
+ * @param {{ beginAttempt: Function, consume: Function, failureUsage?: { model: string, normalize: Function } }} deps.collector
117
118
  * @param {{ timeoutMs: number, maxMs: number, retries: number|null }} [deps.firstByte]
118
119
  * first-byte window per attempt (antigravityFirstBytePolicy)
120
+ * @param {boolean} [deps.afterToolResult] the request ends with a tool result (an empty STOP is then a valid answer)
119
121
  * @returns {() => Promise<object>} one retried request that resolves the final payload
120
122
  */
121
123
  export function createAntigravityRequest({
@@ -128,6 +130,7 @@ export function createAntigravityRequest({
128
130
  collector,
129
131
  sleepFn,
130
132
  firstByte = ANTIGRAVITY_UNCLASSED_FIRST_BYTE,
133
+ afterToolResult = false,
131
134
  }) {
132
135
  const log = (attempt, lastErr, delayMs) => {
133
136
  // A first-byte timeout runs on its own, shorter retry budget.
@@ -240,9 +243,23 @@ export function createAntigravityRequest({
240
243
  return async () => {
241
244
  const state = { capacityRetries: 0, quickRetried: false };
242
245
  const send = { attempts: 0, firstByteTimeouts: 0, firstByteWaitedMs: 0 };
246
+ let streamAttempt = 0;
243
247
  for (let tried = 1; ; tried++) {
244
248
  try {
245
- return await attemptOnce(send);
249
+ const response = await attemptOnce(send);
250
+ // A finished but unusable answer (empty STOP, malformed call) gets
251
+ // the same bounded re-ask as the API-key transport. The dead
252
+ // attempt's thinking is retracted when the next attempt begins.
253
+ if (signal?.aborted) return response;
254
+ const reask = geminiInvalidStreamReask(response, collector.leakGuard, {
255
+ afterToolResult,
256
+ streamAttempt,
257
+ failureUsage: collector.failureUsage,
258
+ });
259
+ if (!reask) return response;
260
+ log(streamAttempt + 1, reask.unusable, reask.waitMs);
261
+ streamAttempt += 1;
262
+ await sleepWithAbort(reask.waitMs, signal, sleepFn, 'Antigravity retry wait aborted');
246
263
  } catch (err) {
247
264
  const waitMs = antigravity429WaitMs(err, state);
248
265
  if (waitMs == null) {
@@ -20,7 +20,7 @@ import { createNpmVersionSource, maxSemver } from './npm-cli-version.mjs';
20
20
  // version (gpt-6.1-sol requires >= 0.159.0, measured 2026-10-09), so the
21
21
  // release workflow raises this to the published CLI version on every release
22
22
  // (scripts/sync-client-version-floors.mjs).
23
- export const CODEX_CLIENT_VERSION_FLOOR = '0.163.0';
23
+ export const CODEX_CLIENT_VERSION_FLOOR = '0.164.0';
24
24
  export const CODEX_CLI_NPM_PACKAGE = '@openai/codex';
25
25
  const live = createNpmVersionSource(CODEX_CLI_NPM_PACKAGE, { persistKey: 'codex-cli' });
26
26
 
@@ -197,19 +197,25 @@ function usagePercent(value) {
197
197
  return Math.round(normalized * 10_000) / 10_000;
198
198
  }
199
199
 
200
+ // The models the Auto pool (`autoPercentUsed`) meters: Auto under both of its
201
+ // ids and the Composer family. Every other model draws on the API pool.
202
+ const AUTO_POOL_MODELS = Object.freeze(['auto', 'default', 'composer']);
203
+
200
204
  // The included-plan windows: per-lane progress percentages when the dashboard
201
- // reports them, else one dollar window over the included balance.
205
+ // reports them, else one dollar window over the included balance. Each lane
206
+ // gates only the models it meters.
202
207
  function includedUsageWindows(included, plan, includedBalance, resetAt) {
203
208
  const progressWindows = [
204
- ['Basic', included.autoPercentUsed],
205
- ['API', included.apiPercentUsed],
209
+ ['Basic', included.autoPercentUsed, { models: [...AUTO_POOL_MODELS] }],
210
+ ['API', included.apiPercentUsed, { except: [...AUTO_POOL_MODELS] }],
206
211
  ].filter(([, value]) => Number.isFinite(Number(value)));
207
212
  if (progressWindows.length) {
208
- return progressWindows.map(([label, value]) => ({
213
+ return progressWindows.map(([label, value, scope]) => ({
209
214
  label,
210
215
  source: 'cursor-dashboard',
211
216
  usedPct: usagePercent(value),
212
217
  ...(resetAt ? { resetAt } : {}),
218
+ ...scope,
213
219
  }));
214
220
  }
215
221
  if (!includedBalance) return [];
@@ -1,9 +1,10 @@
1
- function fields(entries) {
2
- return Object.fromEntries(entries.map(([name, no, type, options = {}]) => [no, { name, no, type, ...options }]));
3
- }
4
-
5
- const map = (key, value) => ({ map: [key, value] });
6
- const repeated = { repeated: true };
1
+ import {
2
+ concatBytes,
3
+ createProtobufCodec,
4
+ protobufFields as fields,
5
+ mapOf as map,
6
+ repeated,
7
+ } from './wire-protobuf-codec.mjs';
7
8
 
8
9
  // Only the fields read or written by the provider are described here.
9
10
  const SCHEMAS = {
@@ -639,149 +640,10 @@ const SCHEMAS = {
639
640
  JsonList: fields([['values', 1, 'JsonValue', repeated]]),
640
641
  };
641
642
 
642
- const textEncoder = new TextEncoder();
643
- // A protobuf string is data, not a text document with a disposable BOM.
644
- const textDecoder = new TextDecoder('utf-8', { ignoreBOM: true });
645
-
646
- function concatBytes(parts) {
647
- const length = parts.reduce((sum, part) => sum + part.length, 0);
648
- const output = new Uint8Array(length);
649
- let offset = 0;
650
- for (const part of parts) {
651
- output.set(part, offset);
652
- offset += part.length;
653
- }
654
- return output;
655
- }
656
-
657
- function encodeVarint(value) {
658
- let current = BigInt(value ?? 0);
659
- if (current < 0) current = BigInt.asUintN(64, current);
660
- const bytes = [];
661
- do {
662
- let byte = Number(current & 0x7fn);
663
- current >>= 7n;
664
- if (current) byte |= 0x80;
665
- bytes.push(byte);
666
- } while (current);
667
- return Uint8Array.from(bytes);
668
- }
669
-
670
- function encodeTag(no, wireType) {
671
- return encodeVarint((BigInt(no) << 3n) | BigInt(wireType));
672
- }
673
-
674
- function isMessageType(type) {
675
- return Object.hasOwn(SCHEMAS, type);
676
- }
677
-
678
- function wireTypeFor(type) {
679
- if (type === 'double') return 1;
680
- if (['string', 'bytes', 'raw'].includes(type) || isMessageType(type)) return 2;
681
- return 0;
682
- }
683
-
684
- function scalarBytes(type, value) {
685
- if (type === 'string') return textEncoder.encode(String(value));
686
- if (type === 'bytes' || type === 'raw') return value instanceof Uint8Array ? value : new Uint8Array(value);
687
- if (type === 'double') {
688
- const buffer = new ArrayBuffer(8);
689
- new DataView(buffer).setFloat64(0, Number(value), true);
690
- return new Uint8Array(buffer);
691
- }
692
- if (type === 'bool') return encodeVarint(value ? 1 : 0);
693
- if (type === 'int' || type === 'uint') return encodeVarint(value);
694
- if (isMessageType(type)) return encodeMessage(type, value);
695
- throw new Error(`Unknown Cursor protobuf type: ${type}`);
696
- }
697
-
698
- function shouldWrite(type, value) {
699
- if (value == null) return false;
700
- if (type === 'string') return value !== '';
701
- return true;
702
- }
703
-
704
- function encodeField(no, type, value) {
705
- const wireType = wireTypeFor(type);
706
- const payload = scalarBytes(type, value);
707
- if (wireType === 2) return concatBytes([encodeTag(no, wireType), encodeVarint(payload.length), payload]);
708
- return concatBytes([encodeTag(no, wireType), payload]);
709
- }
710
-
711
- function encodeMapField(no, [keyType, valueType], value) {
712
- const parts = [];
713
- for (const [key, entryValue] of Object.entries(value || {})) {
714
- const entry = concatBytes([encodeField(1, keyType, key), encodeField(2, valueType, entryValue)]);
715
- parts.push(concatBytes([encodeTag(no, 2), encodeVarint(entry.length), entry]));
716
- }
717
- return parts;
718
- }
719
-
720
- export function encodeMessage(type, value = {}) {
721
- const schema = SCHEMAS[type];
722
- if (!schema) throw new Error(`Unknown Cursor protobuf message: ${type}`);
723
- const parts = [];
724
- for (const descriptor of Object.values(schema)) {
725
- const fieldValue = value[descriptor.name];
726
- if (descriptor.type?.map) {
727
- parts.push(...encodeMapField(descriptor.no, descriptor.type.map, fieldValue));
728
- continue;
729
- }
730
- let values = [fieldValue];
731
- if (descriptor.repeated) values = Array.isArray(fieldValue) ? fieldValue : [];
732
- for (const item of values) {
733
- // A oneof's explicit empty string is a value, not an absent field.
734
- if ((descriptor.presence && item != null) || shouldWrite(descriptor.type, item)) {
735
- parts.push(encodeField(descriptor.no, descriptor.type, item));
736
- }
737
- }
738
- }
739
- return concatBytes(parts);
740
- }
741
-
742
- class ProtoReader {
743
- constructor(bytes) {
744
- this.bytes = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes);
745
- this.offset = 0;
746
- }
747
-
748
- get done() {
749
- return this.offset >= this.bytes.length;
750
- }
751
-
752
- varint() {
753
- let value = 0n;
754
- let shift = 0n;
755
- while (!this.done) {
756
- const byte = this.bytes[this.offset++];
757
- value |= BigInt(byte & 0x7f) << shift;
758
- if ((byte & 0x80) === 0) return value;
759
- shift += 7n;
760
- if (shift > 70n) throw new Error('Invalid Cursor protobuf varint');
761
- }
762
- throw new Error('Truncated Cursor protobuf varint');
763
- }
764
-
765
- take(length) {
766
- const end = this.offset + length;
767
- if (end > this.bytes.length) throw new Error('Truncated Cursor protobuf field');
768
- const value = this.bytes.subarray(this.offset, end);
769
- this.offset = end;
770
- return value;
771
- }
643
+ const codec = createProtobufCodec(SCHEMAS, { label: 'Cursor protobuf' });
644
+ const { encodeField, ProtoReader } = codec;
772
645
 
773
- bytesValue() {
774
- return this.take(Number(this.varint()));
775
- }
776
-
777
- skip(wireType) {
778
- if (wireType === 0) this.varint();
779
- else if (wireType === 1) this.take(8);
780
- else if (wireType === 2) this.bytesValue();
781
- else if (wireType === 5) this.take(4);
782
- else throw new Error(`Unsupported Cursor protobuf wire type: ${wireType}`);
783
- }
784
- }
646
+ export const { encodeMessage, decodeMessage } = codec;
785
647
 
786
648
  export function rewriteConversationState(checkpoint, rootPromptMessagesJson, turns = []) {
787
649
  const preserved = [];
@@ -808,75 +670,6 @@ export function rewriteConversationState(checkpoint, rootPromptMessagesJson, tur
808
670
  return concatBytes([...preserved, ...replacement]);
809
671
  }
810
672
 
811
- function decodeScalar(reader, type, wireType) {
812
- if (type === 'string') return textDecoder.decode(reader.bytesValue());
813
- if (type === 'bytes' || type === 'raw') return new Uint8Array(reader.bytesValue());
814
- if (type === 'double') {
815
- if (wireType !== 1) throw new Error('Invalid Cursor protobuf double');
816
- const value = new DataView(reader.bytes.buffer, reader.bytes.byteOffset + reader.offset, 8).getFloat64(0, true);
817
- reader.offset += 8;
818
- return value;
819
- }
820
- if (type === 'bool') return reader.varint() !== 0n;
821
- if (type === 'int') return Number(BigInt.asIntN(64, reader.varint()));
822
- if (type === 'uint') return Number(reader.varint());
823
- if (isMessageType(type)) return decodeMessage(type, reader.bytesValue());
824
- throw new Error(`Unknown Cursor protobuf type: ${type}`);
825
- }
826
-
827
- function decodeMapEntry(bytes, [keyType, valueType]) {
828
- const reader = new ProtoReader(bytes);
829
- let key = '';
830
- let value = valueType === 'string' ? '' : undefined;
831
- while (!reader.done) {
832
- const tag = reader.varint();
833
- const no = Number(tag >> 3n);
834
- const wireType = Number(tag & 7n);
835
- if (no === 1) key = decodeScalar(reader, keyType, wireType);
836
- else if (no === 2) value = decodeScalar(reader, valueType, wireType);
837
- else reader.skip(wireType);
838
- }
839
- return [String(key), value];
840
- }
841
-
842
- export function decodeMessage(type, bytes) {
843
- const schema = SCHEMAS[type];
844
- if (!schema) throw new Error(`Unknown Cursor protobuf message: ${type}`);
845
- const reader = new ProtoReader(bytes);
846
- const output = {};
847
- while (!reader.done) {
848
- const tag = reader.varint();
849
- const no = Number(tag >> 3n);
850
- const wireType = Number(tag & 7n);
851
- const descriptor = schema[no];
852
- if (!descriptor) {
853
- const start = reader.offset;
854
- reader.skip(wireType);
855
- output.$unknown ||= [];
856
- output.$unknown.push({
857
- no,
858
- wireType,
859
- data: new Uint8Array(reader.bytes.subarray(start, reader.offset)),
860
- });
861
- continue;
862
- }
863
- if (descriptor.type?.map) {
864
- const [key, value] = decodeMapEntry(reader.bytesValue(), descriptor.type.map);
865
- output[descriptor.name] ||= {};
866
- output[descriptor.name][key] = value;
867
- continue;
868
- }
869
- const value = decodeScalar(reader, descriptor.type, wireType);
870
- if (descriptor.repeated) {
871
- output[descriptor.name] ||= [];
872
- output[descriptor.name].push(value);
873
- } else {
874
- output[descriptor.name] = value;
875
- }
876
- }
877
- return output;
878
- }
879
-
880
673
  function jsonToProtoValue(value) {
881
674
  if (value === null) return { nullValue: 0 };
882
675
  if (Array.isArray(value)) return { listValue: { values: value.map(jsonToProtoValue) } };
@@ -482,7 +482,14 @@ function selectParameterizedCursorVariant(group, requested, sendOpts = {}) {
482
482
  const parameters = { ...(defaultVariant?.parameters || {}), ...aliasParameters };
483
483
  const routeParameters =
484
484
  sendOpts.modelParameters && typeof sendOpts.modelParameters === 'object' ? sendOpts.modelParameters : {};
485
+ // The window picked the mode above: a stored `context` no variant of that
486
+ // mode offers (a 256k left beside a raised 500K window) is a stale value and
487
+ // yields to the mode's own; one the mode offers stays the user's choice.
488
+ const staleContext =
489
+ Object.hasOwn(routeParameters, 'context') &&
490
+ !availableVariants.some((variant) => String(variant.parameters?.context ?? '') === String(routeParameters.context));
485
491
  for (const definition of group.definitions) {
492
+ if (staleContext && definition.id === 'context') continue;
486
493
  if (Object.hasOwn(routeParameters, definition.id)) {
487
494
  parameters[definition.id] = String(routeParameters[definition.id]);
488
495
  }