gestalt-mobile 0.25.3 → 0.25.4

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.
@@ -29,6 +29,7 @@ class SessionResource {
29
29
  writtenThreadName;
30
30
  capabilities = new Map();
31
31
  spawnedAgentModels = new Map();
32
+ attemptedAgentModelRecovery = new Set();
32
33
  ownedChildProcesses = new Map();
33
34
  constructor(sessionId, process, planStatusLease, planMeasurementToken, unregister, onDisposed) {
34
35
  this.sessionId = sessionId;
@@ -337,7 +338,7 @@ export class CodexSessionRuntime {
337
338
  ? response.nextCursor
338
339
  : undefined;
339
340
  if (!next)
340
- return children;
341
+ return this.withResolvedChildModels(owned, children);
341
342
  if (cursors.has(next) || children.length >= 64)
342
343
  throw new Error('CODEX_CHILD_LIST_UNSUPPORTED');
343
344
  cursors.add(next);
@@ -345,7 +346,31 @@ export class CodexSessionRuntime {
345
346
  }
346
347
  if (cursor)
347
348
  throw new Error('CODEX_CHILD_LIST_UNSUPPORTED');
348
- return children;
349
+ return this.withResolvedChildModels(owned, children);
350
+ }
351
+ async withResolvedChildModels(resource, children) {
352
+ for (const child of children) {
353
+ if (child.status !== 'notLoaded' ||
354
+ resource.spawnedAgentModels.has(child.id) ||
355
+ resource.attemptedAgentModelRecovery.has(child.id))
356
+ continue;
357
+ resource.attemptedAgentModelRecovery.add(child.id);
358
+ try {
359
+ const response = await resource.process.rpc.request('thread/resume', {
360
+ threadId: child.id,
361
+ });
362
+ const model = boundedString(asRecord(response)?.model, 256);
363
+ if (model)
364
+ resource.spawnedAgentModels.set(child.id, model);
365
+ }
366
+ catch {
367
+ // A live settings notification can still provide the model later.
368
+ }
369
+ }
370
+ return children.map((child) => {
371
+ const model = child.model ?? resource.spawnedAgentModels.get(child.id);
372
+ return model && model !== child.model ? { ...child, model } : child;
373
+ });
349
374
  }
350
375
  /** Reads only bounded process metadata; command text and output never enter lifecycle state. */
351
376
  async inspectChildProcesses(session, child) {
@@ -496,7 +521,6 @@ export class CodexSessionRuntime {
496
521
  async decodeHistory(process, threadId, resource) {
497
522
  const response = await process.rpc.request('thread/read', { threadId, includeTurns: true });
498
523
  if (resource) {
499
- resource.spawnedAgentModels.clear();
500
524
  for (const [childId, model] of decodeSpawnedAgentModels(response))
501
525
  resource.spawnedAgentModels.set(childId, model);
502
526
  }
@@ -668,6 +692,11 @@ export class CodexSessionRuntime {
668
692
  const notificationUnsubscribe = process.rpc.onNotification((notification) => {
669
693
  if (!resource.active)
670
694
  return;
695
+ const childModel = decodeThreadSettingsModel(notification);
696
+ if (childModel &&
697
+ (resource.spawnedAgentModels.has(childModel.threadId) ||
698
+ resource.spawnedAgentModels.size < 256))
699
+ resource.spawnedAgentModels.set(childModel.threadId, childModel.model);
671
700
  const resolvedRequestId = resolvedServerRequestId(notification);
672
701
  if (resolvedRequestId) {
673
702
  const pending = resource.pendingRequests.get(resolvedRequestId);
@@ -771,6 +800,15 @@ function decodeAgentTaskPath(value) {
771
800
  const path = boundedString(spawn?.agent_path, 256);
772
801
  return path?.startsWith('/') && !path.includes('..') ? path : undefined;
773
802
  }
803
+ /** Captures the resolved model that Codex applies after spawning a child thread. */
804
+ function decodeThreadSettingsModel(notification) {
805
+ if (notification.method !== 'thread/settings/updated')
806
+ return undefined;
807
+ const params = asRecord(notification.params);
808
+ const threadId = boundedString(params?.threadId, 256);
809
+ const model = boundedString(asRecord(params?.threadSettings)?.model, 256);
810
+ return threadId && model ? { threadId, model } : undefined;
811
+ }
774
812
  function childProcessKey(childThreadId, processId) {
775
813
  return `${childThreadId}:${processId}`;
776
814
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gestalt-mobile",
3
- "version": "0.25.3",
3
+ "version": "0.25.4",
4
4
  "description": "Mobile-first web relay for durable Codex development sessions",
5
5
  "keywords": [
6
6
  "codex",