mixdog 0.9.148 → 0.9.149

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.
@@ -461,6 +461,42 @@ export async function askSession(sessionId, prompt, context, onToolCall, cwdOver
461
461
  effectiveContextWindowPercent: contextMeta.effectiveContextWindowPercent,
462
462
  autoCompactTokenLimit: contextMeta.autoCompactTokenLimit,
463
463
  };
464
+ const effectiveCwd = cwdOverride || session.cwd;
465
+ if (session.sessionStartMetaInjected !== true
466
+ && !hasUserConversationMessage(session.messages)) {
467
+ refreshSessionBp3Environment(session, effectiveCwd);
468
+ }
469
+ let _startupProviderPrewarm = null;
470
+ if (session.provider === 'openai-oauth'
471
+ && Number(session.totalInputTokens || 0) === 0
472
+ && !session.providerState
473
+ && typeof provider.prewarmWsTransportForSession === 'function') {
474
+ try {
475
+ _startupProviderPrewarm = Promise.resolve(
476
+ provider.prewarmWsTransportForSession({
477
+ sessionId,
478
+ session,
479
+ messages: filterModelVisibleSessionMessages(session.messages),
480
+ model: session.model,
481
+ tools: session.tools,
482
+ effort: session.effort || null,
483
+ fast: session.fast === true,
484
+ modelParameters: session.modelParameters || {},
485
+ selectedContextWindow: session.selectedContextWindow || session.contextWindow || null,
486
+ promptCacheKey: session.promptCacheKey || null,
487
+ providerCacheKey: session.promptCacheKey || null,
488
+ ...(session.providerCacheOpts || {}),
489
+ ...(codexWireSendOpts(session, {
490
+ requestKind: 'prewarm',
491
+ turnId: _codexTurnId,
492
+ startedAtMs: _turnCheckpointStartedAt,
493
+ }) || {}),
494
+ }),
495
+ ).catch(() => false);
496
+ } catch {
497
+ _startupProviderPrewarm = null;
498
+ }
499
+ }
464
500
  // Cap caller-supplied / prefetched context so an oversized
465
501
  // payload can't blow the session token budget before the
466
502
  // first model call. 32 KB ~ 8k tokens at the 4 B/tok
@@ -489,11 +525,6 @@ export async function askSession(sessionId, prompt, context, onToolCall, cwdOver
489
525
  if (explicitPrefetchResult) {
490
526
  _contextBlock += `# Prefetch\n${_capCtx(explicitPrefetchResult)}\n\n`;
491
527
  }
492
- const effectiveCwd = cwdOverride || session.cwd;
493
- if (session.sessionStartMetaInjected !== true
494
- && !hasUserConversationMessage(session.messages)) {
495
- refreshSessionBp3Environment(session, effectiveCwd);
496
- }
497
528
  const historyMessages = filterModelVisibleSessionMessages(session.messages);
498
529
  const beforeCount = historyMessages.length + 1;
499
530
  const promptTextForMetrics = promptContentText(prompt);
@@ -576,6 +607,13 @@ export async function askSession(sessionId, prompt, context, onToolCall, cwdOver
576
607
  },
577
608
  });
578
609
  } catch { /* trace must never break the ask path */ }
610
+ if (_startupProviderPrewarm) {
611
+ try {
612
+ await runAbortable(turnSignal, () => _startupProviderPrewarm);
613
+ } catch {
614
+ throwIfAborted(turnSignal);
615
+ }
616
+ }
579
617
  const agentLoop = await runAbortable(turnSignal, () => _getAgentLoop());
580
618
  const _trackTextDelta = (chunk) => {
581
619
  _turnInterruption.recordTextDelta(chunk);
@@ -46,6 +46,7 @@ import {
46
46
  } from '../approval-mode.mjs';
47
47
  import { describeShellStartupPolicy } from '../../tools/builtin/runtime-capabilities.mjs';
48
48
  import { captureOriginalUserCwd } from '../../../../shared/user-cwd.mjs';
49
+ import { refreshSessionBp3Environment } from './prompt-utils.mjs';
49
50
 
50
51
  function buildSessionProviderCacheOpts(providerName, sessionId, agent = null) {
51
52
  // Keep this in sync with createSession's provider-cache policy: only
@@ -477,6 +478,7 @@ export function createSession(opts) {
477
478
  ownerSessionId: opts.ownerSessionId || null,
478
479
  clientHostPid: opts.clientHostPid || null,
479
480
  };
481
+ refreshSessionBp3Environment(session, opts.cwd);
480
482
  // In-process registry + async debounced save: same-process create → load
481
483
  // reads live memory; disk flush is for cross-process / restart durability.
482
484
  setLiveSession(session);
@@ -244,7 +244,7 @@ export const BUILTIN_TOOLS = [
244
244
  },
245
245
  hidden: { type: 'boolean', description: 'Include dotfiles.' },
246
246
  meta: { type: 'boolean', description: 'Per-entry size bytes, UTC mtime, octal mode.' },
247
- limit: { type: 'integer', minimum: 0, description: 'Max entries; default 200; 0 unlimited.' },
247
+ limit: { type: 'integer', minimum: 0, description: 'Max entries; default 100; 0 unlimited.' },
248
248
  offset: { type: 'integer', minimum: 0, description: 'Entry offset.' },
249
249
  },
250
250
  required: [],
@@ -32,6 +32,20 @@ test('aborted list work cannot poison the result cache', async () => {
32
32
  }
33
33
  });
34
34
 
35
+ test('list defaults to a 100-entry page with an offset continuation', async () => {
36
+ const root = await mkdtemp(join(tmpdir(), 'mixdog-list-default-page-'));
37
+ try {
38
+ await Promise.all(Array.from({ length: 101 }, (_, index) => (
39
+ writeFile(join(root, `entry-${String(index).padStart(3, '0')}.txt`), 'ok')
40
+ )));
41
+ const out = await executeListTool({ path: root, hidden: true }, process.cwd());
42
+ assert.equal(out.split('\n').filter((line) => line.endsWith('\tfile')).length, 100);
43
+ assert.match(out, /\[entries 1-100 of 101; pass offset:100 to continue\]/);
44
+ } finally {
45
+ await rm(root, { recursive: true, force: true });
46
+ }
47
+ });
48
+
35
49
  test('root readdir failures are errors, stay uncached, and mark a repeatedly failing runtime worker unhealthy', async () => {
36
50
  const originalRuntimeWorkerPid = process.env.MIXDOG_SESSION_RUNTIME_WORKER_PID;
37
51
  const roots = [];
@@ -100,7 +100,7 @@ function recordDirectoryWalkTelemetry(options, status, walkResult, warningCount
100
100
  };
101
101
  }
102
102
 
103
- // A/B override surface for the default result caps (stock: list/tree 200,
103
+ // A/B override surface for the default result caps (stock: list 100, tree 200,
104
104
  // fuzzy find 25). Env-gated so bench variants can match competitor-style
105
105
  // generous caps without changing the shipped defaults.
106
106
  function _listDefaultHeadLimit(fallback) {
@@ -256,7 +256,7 @@ export async function executeListTool(args, workDir, options = {}) {
256
256
  const hidden = Boolean(args.hidden);
257
257
  const sort = ['name', 'mtime', 'size'].includes(args.sort) ? args.sort : 'name';
258
258
  const typeFilter = ['any', 'file', 'dir'].includes(args.type) ? args.type : 'any';
259
- const headLimit = normalizeListHeadLimit(args.head_limit, _listDefaultHeadLimit(200));
259
+ const headLimit = normalizeListHeadLimit(args.head_limit, _listDefaultHeadLimit(100));
260
260
  const offset = typeof args.offset === 'number' && args.offset > 0 ? args.offset : 0;
261
261
  const needsGlobalStat = sort === 'mtime' || sort === 'size';
262
262
  const includeNoise = Boolean(args.include_noise);
@@ -27,7 +27,6 @@
27
27
  "MIXDOG_CACHE_MESSAGES_TTL",
28
28
  "MIXDOG_OAI_TRANSPORT",
29
29
  "MIXDOG_OPENAI_OAUTH_WS_WARMUP",
30
- "MIXDOG_OAI_CODEX_WIRE_PARITY",
31
30
  "MIXDOG_OAI_WS_DUMP_DIR",
32
31
  "MIXDOG_SESSION_TRANSCRIPT_LOG",
33
32
  "MIXDOG_USAGE_LOG"
@@ -333,6 +333,15 @@ export function createSessionLifecycle({
333
333
  throwIfAborted(signal);
334
334
  // best-effort: ordinary hook failure never breaks session create
335
335
  }
336
+ if (rt.session.provider === 'openai-oauth'
337
+ && Number(rt.session.totalInputTokens || 0) === 0
338
+ && !rt.session.providerState
339
+ && typeof providerImpl.prewarmWsTransportForSession === 'function') {
340
+ void Promise.resolve(providerImpl.prewarmWsTransportForSession({
341
+ sessionId: rt.session.id,
342
+ session: rt.session,
343
+ })).catch(() => {});
344
+ }
336
345
  throwIfAborted(signal);
337
346
  bootProfile('session:create:ready', {
338
347
  ms: (performance.now() - startedAt).toFixed(1),
@@ -337,10 +337,10 @@ export function createSpawnFlow({
337
337
  const spec = spawnSessionSpec(plan, args, context);
338
338
  const { session, effectiveCwd } = prepareAgentSession(spec);
339
339
  bindSpawnedSession(session, plan);
340
- // Spawn prewarm opens the worker's WebSocket now, in
341
- // parallel with the remaining prep / first-prompt build, so the first
342
- // request skips the handshake. Fire-and-forget: failures fall back to the
343
- // lazy per-send handshake. MIXDOG_AGENT_SPAWN_WS_PREWARM=0 disables.
340
+ // Spawn prewarm builds the materialized stable prompt and keeps the
341
+ // resulting Codex-style client handle reserved for the first turn.
342
+ // Fire-and-forget: failures fall back to the lazy per-send handshake.
343
+ // MIXDOG_AGENT_SPAWN_WS_PREWARM=0 disables.
344
344
  maybePrewarmSpawnTransport(plan, session);
345
345
  return preparedSpawnResult(
346
346
  { ...plan, workerCwd: effectiveCwd || plan.workerCwd },