@turns/dev 0.0.22 → 0.0.23

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.
@@ -209,6 +209,8 @@ class LineTransport {
209
209
  */
210
210
  const CLAUDE_NOTIFICATION_RESULT_GRACE_MS = 2_000;
211
211
  class ClaudeTransport extends LineTransport {
212
+ model;
213
+ thinkingLevel;
212
214
  nativeTurnActive = false;
213
215
  sessionId;
214
216
  permissionMode;
@@ -242,6 +244,8 @@ class ClaudeTransport extends LineTransport {
242
244
  super(anchor, 'claude', resolveHarnessCommand('claude', profile), args, anchor.cwd, {
243
245
  CLAUDE_CODE_ENTRYPOINT: 'turns-agent-anchor',
244
246
  });
247
+ this.model = anchor.model;
248
+ this.thinkingLevel = anchor.thinkingLevel;
245
249
  this.sessionId = anchor.agentSessionId;
246
250
  this.permissionMode = anchor.permissionMode;
247
251
  this.turnWaiter = null;
@@ -789,7 +793,12 @@ class CodexAppServerTransport extends LineTransport {
789
793
  this.turnId = null;
790
794
  this.turnIdWaiter = deferred();
791
795
  this.turnWaiter = waiter;
792
- const started = await this.request('turn/start', { threadId: this.threadId, input: [{ type: 'text', text }] }, timeoutMs).catch((error) => {
796
+ const started = await this.request('turn/start', {
797
+ threadId: this.threadId,
798
+ input: [{ type: 'text', text }],
799
+ ...(this.anchor.model && this.anchor.model !== 'auto' ? { model: this.anchor.model } : {}),
800
+ ...(this.anchor.thinkingLevel ? { effort: this.anchor.thinkingLevel } : {}),
801
+ }, timeoutMs).catch((error) => {
793
802
  if (this.turnWaiter === waiter)
794
803
  this.turnWaiter = null;
795
804
  this.turnIdWaiter?.resolve('');
@@ -1491,6 +1500,7 @@ class Anchor {
1491
1500
  protocol: 'turns.agent-anchor.v1',
1492
1501
  owner: 'turns.dev',
1493
1502
  capabilities: [
1503
+ 'model_settings',
1494
1504
  'interrupt',
1495
1505
  'shutdown',
1496
1506
  'answer_interaction',
@@ -1733,8 +1743,10 @@ class Anchor {
1733
1743
  cwd: path.resolve(request.cwd),
1734
1744
  transcriptPath: path.resolve(request.transcriptPath),
1735
1745
  workerId: String(request.workerId || ''),
1736
- model: String(request.model || ''),
1737
- thinkingLevel: String(request.thinkingLevel || ''),
1746
+ // Launch hints disappear after binding. Keep a warm session's choices
1747
+ // until the next explicit selection; never leak them across identities.
1748
+ model: String(request.model || (request.sessionId === this.sessionId ? this.model : '') || ''),
1749
+ thinkingLevel: String(request.thinkingLevel || (request.sessionId === this.sessionId ? this.thinkingLevel : '') || ''),
1738
1750
  permissionMode: requestedPermissionMode(request.permissionMode),
1739
1751
  codexHistoryMode,
1740
1752
  idleTimeoutMs: Math.max(1_000, Number(request.idleTimeoutMs) || 300_000),
@@ -1776,6 +1788,8 @@ class Anchor {
1776
1788
  if (!(this.transport instanceof ClaudeTransport) ||
1777
1789
  this.transport.child.exitCode !== null ||
1778
1790
  this.transport.sessionId !== this.agentSessionId ||
1791
+ this.transport.model !== this.model ||
1792
+ this.transport.thinkingLevel !== this.thinkingLevel ||
1779
1793
  this.transport.permissionMode !== this.permissionMode) {
1780
1794
  this.transport?.stop?.();
1781
1795
  this.transport = new ClaudeTransport(this, createSession);
@@ -559,21 +559,25 @@ export async function watchQueuedPrompts({ rpc, options, machine, getDescriptors
559
559
  }
560
560
  bindAnchor(connection, snapshot);
561
561
  }
562
- const usableAnchor = async (sessionId, source, agentSessionId) => {
562
+ const usableAnchor = async (sessionId, source, agentSessionId, modelSettings = false) => {
563
563
  let entry = anchors.get(sessionId);
564
564
  if (entry && !entry.connection.closed) {
565
565
  entry.snapshot = await entry.connection.request('snapshot', {}, 5_000).catch(() => entry.snapshot);
566
566
  if (String(entry.snapshot.source || '') === source &&
567
- String(entry.snapshot.agentSessionId || '') === agentSessionId)
567
+ String(entry.snapshot.agentSessionId || '') === agentSessionId &&
568
+ (!modelSettings || entry.snapshot.capabilities?.includes('model_settings')))
568
569
  return entry;
569
570
  if (entry.snapshot.status === 'running')
570
- throw new Error('The surviving anchor is running a different session identity.');
571
+ throw new Error('The surviving anchor must finish its turn before it can be replaced.');
571
572
  await entry.connection.request('shutdown', {}, 2_000).catch(() => { });
572
573
  entry.connection.close();
573
574
  anchors.delete(sessionId);
574
575
  }
575
576
  const connection = await launchAgentAnchor(sessionId);
576
577
  entry = bindAnchor(connection, connection.snapshot || {}, sessionId);
578
+ if (modelSettings && !entry.snapshot.capabilities?.includes('model_settings')) {
579
+ throw new Error('The installed agent anchor does not support session model settings. Update the Turns CLI.');
580
+ }
577
581
  await reportHarness(sessionId, 'idle', entry);
578
582
  return entry;
579
583
  };
@@ -684,7 +688,7 @@ export async function watchQueuedPrompts({ rpc, options, machine, getDescriptors
684
688
  // Codex installation leaves a recoverable unsent prompt in the queue.
685
689
  if (descriptor.harness === 'codex')
686
690
  resolveHarnessCommand('codex');
687
- entry = await usableAnchor(sessionId, descriptor.harness, agentSessionId);
691
+ entry = await usableAnchor(sessionId, descriptor.harness, agentSessionId, Boolean(claim.session?.modelSettings));
688
692
  }
689
693
  if (!entry)
690
694
  throw new Error(`No surviving agent anchor exists for ${sessionId}.`);
@@ -1399,6 +1403,7 @@ export async function watchQueuedPrompts({ rpc, options, machine, getDescriptors
1399
1403
  machineId: machine,
1400
1404
  machineHostname: os.hostname(),
1401
1405
  capabilities: {
1406
+ sessionModelSettings: true,
1402
1407
  fileSearch: true,
1403
1408
  git: true,
1404
1409
  fileRanges: true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@turns/dev",
3
- "version": "0.0.22",
3
+ "version": "0.0.23",
4
4
  "description": "Upload local AI agent sessions to turns.dev",
5
5
  "license": "MIT",
6
6
  "type": "module",