muse-code-sdk 1.4.6__tar.gz → 1.4.8__tar.gz

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 (67) hide show
  1. {muse_code_sdk-1.4.6/src/muse_code_sdk.egg-info → muse_code_sdk-1.4.8}/PKG-INFO +1 -1
  2. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/pyproject.toml +1 -1
  3. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/src/muse_code/__init__.py +2 -2
  4. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/src/muse_code/facade/client.py +7 -0
  5. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/src/muse_code/facade/turn_handle.py +4 -3
  6. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/src/muse_code/fold/session_fold.py +26 -1
  7. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8/src/muse_code_sdk.egg-info}/PKG-INFO +1 -1
  8. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/tests/test_facade_turn.py +45 -0
  9. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/tests/test_session_fold.py +72 -0
  10. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/LICENSE +0 -0
  11. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/README.md +0 -0
  12. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/setup.cfg +0 -0
  13. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/src/muse_code/connection/__init__.py +0 -0
  14. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/src/muse_code/connection/connection.py +0 -0
  15. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/src/muse_code/connection/discovery.py +0 -0
  16. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/src/muse_code/connection/spawn.py +0 -0
  17. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/src/muse_code/connection/validation.py +0 -0
  18. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/src/muse_code/errors.py +0 -0
  19. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/src/muse_code/facade/__init__.py +0 -0
  20. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/src/muse_code/facade/approval.py +0 -0
  21. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/src/muse_code/facade/discarded.py +0 -0
  22. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/src/muse_code/facade/gap_fill.py +0 -0
  23. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/src/muse_code/facade/host_death.py +0 -0
  24. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/src/muse_code/facade/host_start.py +0 -0
  25. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/src/muse_code/facade/session.py +0 -0
  26. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/src/muse_code/facade/turn_submit.py +0 -0
  27. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/src/muse_code/fold/__init__.py +0 -0
  28. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/src/muse_code/fold/item_store.py +0 -0
  29. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/src/muse_code/fold/state_store.py +0 -0
  30. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/src/muse_code/pending/__init__.py +0 -0
  31. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/src/muse_code/pending/pending_command_set.py +0 -0
  32. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/src/muse_code/py.typed +0 -0
  33. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/src/muse_code/replay.py +0 -0
  34. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/src/muse_code/sync_facade.py +0 -0
  35. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/src/muse_code_sdk.egg-info/SOURCES.txt +0 -0
  36. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/src/muse_code_sdk.egg-info/dependency_links.txt +0 -0
  37. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/src/muse_code_sdk.egg-info/requires.txt +0 -0
  38. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/src/muse_code_sdk.egg-info/top_level.txt +0 -0
  39. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/tests/test_asyncio_cancellation.py +0 -0
  40. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/tests/test_compatibility_row.py +0 -0
  41. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/tests/test_connection.py +0 -0
  42. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/tests/test_connection_error_arms.py +0 -0
  43. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/tests/test_docs_generation.py +0 -0
  44. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/tests/test_external_audience.py +0 -0
  45. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/tests/test_facade_approval.py +0 -0
  46. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/tests/test_facade_gap_fill.py +0 -0
  47. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/tests/test_facade_open_same_chunk.py +0 -0
  48. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/tests/test_facade_persistent_approval.py +0 -0
  49. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/tests/test_facade_required_selection.py +0 -0
  50. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/tests/test_host_discovery.py +0 -0
  51. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/tests/test_item_store.py +0 -0
  52. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/tests/test_manifests.py +0 -0
  53. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/tests/test_muse_serve_child.py +0 -0
  54. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/tests/test_pending_command_corpus.py +0 -0
  55. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/tests/test_pending_command_set.py +0 -0
  56. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/tests/test_pending_command_wire_binding.py +0 -0
  57. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/tests/test_permission_state_wire_types.py +0 -0
  58. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/tests/test_public_mirror_text.py +0 -0
  59. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/tests/test_publish_shape.py +0 -0
  60. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/tests/test_source_closure.py +0 -0
  61. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/tests/test_spawn_handshake.py +0 -0
  62. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/tests/test_spawn_host_lost.py +0 -0
  63. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/tests/test_state_store.py +0 -0
  64. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/tests/test_sync_facade.py +0 -0
  65. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/tests/test_tolerance_corpus.py +0 -0
  66. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/tests/test_transcript_replay.py +0 -0
  67. {muse_code_sdk-1.4.6 → muse_code_sdk-1.4.8}/tests/test_typing_gates.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: muse-code-sdk
3
- Version: 1.4.6
3
+ Version: 1.4.8
4
4
  Summary: Muse Code SDK for MSP: asyncio-first facade over the generated wire types (muse-code-msp), with a thin sync wrapper.
5
5
  License-Expression: MIT
6
6
  Project-URL: Homepage, https://github.com/meta-models/muse-code-sdk
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
5
5
 
6
6
  [project]
7
7
  name = "muse-code-sdk"
8
- version = "1.4.6"
8
+ version = "1.4.8"
9
9
  description = "Muse Code SDK for MSP: asyncio-first facade over the generated wire types (muse-code-msp), with a thin sync wrapper."
10
10
  readme = "README.md"
11
11
  requires-python = ">=3.10"
@@ -80,7 +80,7 @@ __all__ = [
80
80
  ]
81
81
 
82
82
  EXPECTED_SCHEMA_FINGERPRINT: Final[str] = (
83
- "sha256:eae467ab60cb9a5d5af4de616830f065e59375c987fd59269c8cc33ed2a1137f"
83
+ "sha256:4e3200c3c9dc0cd7919d11022630d43f9bc1c5cdda375381e90b0183b5665069"
84
84
  )
85
85
  """The stable schema-bundle fingerprint this SDK was built against.
86
86
 
@@ -92,7 +92,7 @@ Python SDK reds this lane instead of drifting silently.
92
92
  # The lockstep rule: the release train bumps pyproject.toml, the
93
93
  # distribution-metadata authority; this constant is aligned at publication
94
94
  # time.
95
- __version__: Final[str] = "1.4.6"
95
+ __version__: Final[str] = "1.4.8"
96
96
 
97
97
  # The facade is imported last so the constants above are already bound: the
98
98
  # spawn path reads ``EXPECTED_SCHEMA_FINGERPRINT`` (lazily, at initialize
@@ -130,12 +130,17 @@ class ResumeSessionOptions:
130
130
  exclude_items: Ask the host to omit item bodies from the history.
131
131
  history: The history preference forwarded as the wire's ``history``
132
132
  member.
133
+ permission_profile: The permission profile pick forwarded as the
134
+ wire's ``permissionProfile`` member: the host restores the
135
+ retained authority first, then applies the pick. Omitted means
136
+ no override.
133
137
  """
134
138
 
135
139
  session_id: str
136
140
  cursor: str | None = None
137
141
  exclude_items: bool | None = None
138
142
  history: Mapping[str, Any] | None = None
143
+ permission_profile: str | None = None
139
144
 
140
145
 
141
146
  # Drift pins — the Python twin of the TS `AssertNever` on START_FORWARDED /
@@ -483,6 +488,8 @@ class MuseClient(Generic[_I]):
483
488
  params["excludeItems"] = options.exclude_items
484
489
  if options.history is not None:
485
490
  params["history"] = options.history
491
+ if options.permission_profile is not None:
492
+ params["permissionProfile"] = options.permission_profile
486
493
  return await self._open("session/resume", params, _ResumeOpening)
487
494
 
488
495
  async def close(self) -> None:
@@ -97,9 +97,10 @@ class _TerminalUnknown:
97
97
 
98
98
  TurnOutcome = Union[_Completed, _Unqueued, _TerminalUnknown]
99
99
  """How a turn ended, from a waiter's point of view. ``turn/retracted``,
100
- ``turn/retryScheduled``, and ``turn/foregroundCompleted`` are deliberately
101
- absent: a retracted turn still reaches its own terminal, and a scheduled
102
- retry or a foreground notice is explicitly non-terminal."""
100
+ ``turn/retryScheduled``, ``turn/modelRetryScheduled``, and
101
+ ``turn/foregroundCompleted`` are deliberately absent: a retracted turn still
102
+ reaches its own terminal, and a scheduled retry, a scheduled backoff, or a
103
+ foreground notice is explicitly non-terminal."""
103
104
 
104
105
 
105
106
  def is_launch_failure(outcome: TurnOutcome) -> bool:
@@ -10,7 +10,8 @@ are neither an item nor a state family:
10
10
 
11
11
  - the TURN LIFECYCLE — ``turn/started``, ``turn/completed``,
12
12
  ``turn/retracted``, ``turn/unqueued``, and the non-terminal
13
- ``turn/retryScheduled`` and ``turn/foregroundCompleted``;
13
+ ``turn/retryScheduled``, ``turn/modelRetryScheduled``, and
14
+ ``turn/foregroundCompleted``;
14
15
  - the APPROVAL and USER-INPUT view events as fold INPUTS — the pending sets
15
16
  and their first durable terminal. The decision flow (choosing and sending a
16
17
  resolution) is the facade's, not the fold's;
@@ -71,6 +72,7 @@ VIEW_EVENT_METHODS: frozenset[str] = frozenset(
71
72
  "turn/foregroundCompleted",
72
73
  "turn/retracted",
73
74
  "turn/retryScheduled",
75
+ "turn/modelRetryScheduled",
74
76
  "turn/unqueued",
75
77
  "approval/requested",
76
78
  "approval/updated",
@@ -139,6 +141,9 @@ class TurnEntry:
139
141
  ``turn/completed`` folded.
140
142
  error: Present iff the terminal was ``"failed"``.
141
143
  retry_scheduled: The latest scheduled model retry; non-terminal.
144
+ model_retry_scheduled: The latest scheduled provider-backoff retry;
145
+ non-terminal. The model-attempt twin of ``retry_scheduled``;
146
+ clears on the turn's terminal.
142
147
  foreground_completed: The latest foreground-completed notice;
143
148
  non-terminal. Tells a renderer the answer is done while
144
149
  ``blockingAgents`` hold the turn; clears on the turn's terminal.
@@ -150,6 +155,7 @@ class TurnEntry:
150
155
  terminal: str | None = None
151
156
  error: Params | None = None
152
157
  retry_scheduled: Params | None = None
158
+ model_retry_scheduled: Params | None = None
153
159
  foreground_completed: Params | None = None
154
160
 
155
161
 
@@ -422,6 +428,7 @@ class _InternalTurn:
422
428
  terminal: str | None = None
423
429
  error: Params | None = None
424
430
  retry_scheduled: Params | None = None
431
+ model_retry_scheduled: Params | None = None
425
432
  foreground_completed: Params | None = None
426
433
 
427
434
 
@@ -572,6 +579,8 @@ class SessionFold:
572
579
  return self._turn_unqueued(params)
573
580
  if method == "turn/retryScheduled":
574
581
  return self._turn_retry_scheduled(params)
582
+ if method == "turn/modelRetryScheduled":
583
+ return self._turn_model_retry_scheduled(params)
575
584
  if method == "turn/foregroundCompleted":
576
585
  return self._turn_foreground_completed(params)
577
586
  if method == "approval/requested":
@@ -675,6 +684,9 @@ class SessionFold:
675
684
  # The retry hint is a "retrying in Ns" countdown, and it clears on the
676
685
  # turn's next event — which a completion is.
677
686
  turn.retry_scheduled = None
687
+ # Same for the provider-backoff hint: a finished turn is not
688
+ # waiting out a backoff.
689
+ turn.model_retry_scheduled = None
678
690
  # Same for the foreground hint: a finished turn is not
679
691
  # background-waiting.
680
692
  turn.foreground_completed = None
@@ -720,6 +732,18 @@ class SessionFold:
720
732
  turn.retry_scheduled = params
721
733
  return TurnFold(turn_id, turn.state)
722
734
 
735
+ def _turn_model_retry_scheduled(self, params: Params) -> FoldOutcome:
736
+ # Non-terminal by contract: it never resolves a turn-wait.
737
+ turn_id = str(params["turnId"])
738
+ turn = self._turn_for(turn_id)
739
+ # ...but it is still a turn frame, so it takes the same redelivery
740
+ # guard as the retry hint: a replayed page must not re-plant the
741
+ # provider-backoff hint on a turn that already left `running`.
742
+ if turn.state != "running":
743
+ return IgnoredStaleFrame("turn/modelRetryScheduled", turn_id)
744
+ turn.model_retry_scheduled = params
745
+ return TurnFold(turn_id, turn.state)
746
+
723
747
  def _turn_foreground_completed(self, params: Params) -> FoldOutcome:
724
748
  # Non-terminal by contract: it never resolves a turn-wait.
725
749
  turn_id = str(params["turnId"])
@@ -753,6 +777,7 @@ class SessionFold:
753
777
  terminal=turn.terminal,
754
778
  error=turn.error,
755
779
  retry_scheduled=turn.retry_scheduled,
780
+ model_retry_scheduled=turn.model_retry_scheduled,
756
781
  foreground_completed=turn.foreground_completed,
757
782
  )
758
783
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: muse-code-sdk
3
- Version: 1.4.6
3
+ Version: 1.4.8
4
4
  Summary: Muse Code SDK for MSP: asyncio-first facade over the generated wire types (muse-code-msp), with a thin sync wrapper.
5
5
  License-Expression: MIT
6
6
  Project-URL: Homepage, https://github.com/meta-models/muse-code-sdk
@@ -139,6 +139,25 @@ def turn_retry_scheduled(turn_id: str, view_cursor: str) -> dict[str, Any]:
139
139
  }
140
140
 
141
141
 
142
+ def turn_model_retry_scheduled(turn_id: str, view_cursor: str) -> dict[str, Any]:
143
+ return {
144
+ "method": "turn/modelRetryScheduled",
145
+ "params": {
146
+ "attempt": 2,
147
+ "errorKind": "overloaded",
148
+ "httpStatus": 529,
149
+ "maxAttempts": 5,
150
+ "nextAttempt": 3,
151
+ "retryDelayMs": 4_000,
152
+ "sessionId": SESSION,
153
+ "sourceRange": SOURCE,
154
+ "system": "meta",
155
+ "turnId": turn_id,
156
+ "viewCursor": view_cursor,
157
+ },
158
+ }
159
+
160
+
142
161
  def turn_foreground_completed(turn_id: str, view_cursor: str) -> dict[str, Any]:
143
162
  return {
144
163
  "method": "turn/foregroundCompleted",
@@ -331,6 +350,32 @@ async def test_turn_retry_scheduled_never_settles_the_wait() -> None:
331
350
  await watcher
332
351
 
333
352
 
353
+ @pytest.mark.asyncio
354
+ async def test_turn_model_retry_scheduled_never_settles_the_wait() -> None:
355
+ s = session()
356
+ turn = s.turn("t-1")
357
+ s.apply(turn_started("t-1", "v:1"))
358
+ s.apply(turn_model_retry_scheduled("t-1", "v:2"))
359
+
360
+ settled = False
361
+
362
+ async def watch() -> None:
363
+ nonlocal settled
364
+ await turn.completed
365
+ settled = True
366
+
367
+ import asyncio
368
+
369
+ watcher = asyncio.ensure_future(watch())
370
+ for _ in range(5):
371
+ await asyncio.sleep(0)
372
+ assert settled is False, "a scheduled backoff is a fact about a RUNNING turn"
373
+
374
+ s.apply(turn_completed("t-1", "completed", "v:3"))
375
+ assert (await turn.completed).kind == "completed"
376
+ await watcher
377
+
378
+
334
379
  @pytest.mark.asyncio
335
380
  async def test_turn_foreground_completed_never_settles_the_wait() -> None:
336
381
  s = session()
@@ -110,6 +110,25 @@ def retry_scheduled(turn_id: str, view_cursor: str) -> dict[str, Any]:
110
110
  }
111
111
 
112
112
 
113
+ def model_retry_scheduled(turn_id: str, view_cursor: str) -> dict[str, Any]:
114
+ return {
115
+ "method": "turn/modelRetryScheduled",
116
+ "params": {
117
+ "attempt": 2,
118
+ "errorKind": "overloaded",
119
+ "httpStatus": 529,
120
+ "maxAttempts": 5,
121
+ "nextAttempt": 3,
122
+ "retryDelayMs": 4_000,
123
+ "sessionId": SESSION,
124
+ "sourceRange": SOURCE,
125
+ "system": "meta",
126
+ "turnId": turn_id,
127
+ "viewCursor": view_cursor,
128
+ },
129
+ }
130
+
131
+
113
132
  def foreground_completed(turn_id: str, view_cursor: str) -> dict[str, Any]:
114
133
  return {
115
134
  "method": "turn/foregroundCompleted",
@@ -493,6 +512,58 @@ def test_a_replayed_page_never_re_plants_the_retry_hint_on_a_turn_that_left_runn
493
512
  assert fold.apply(retry) == IgnoredStaleFrame("turn/retryScheduled", "turn-1")
494
513
 
495
514
 
515
+ def test_turn_model_retry_scheduled_is_non_terminal_the_turn_keeps_running() -> None:
516
+ fold = SessionFold()
517
+ fold.apply(turn_started("turn-1", "cmd-1", "v:s:1"))
518
+ fold.apply(model_retry_scheduled("turn-1", "v:s:2"))
519
+
520
+ assert fold.active_turn_id == "turn-1", "a scheduled backoff never settles a turn"
521
+ held = fold.turn("turn-1")
522
+ assert held is not None
523
+ assert held.state == "running"
524
+ assert held.model_retry_scheduled is not None
525
+ assert held.model_retry_scheduled["nextAttempt"] == 3
526
+
527
+
528
+ def test_turn_completed_clears_the_provider_backoff_hint() -> None:
529
+ fold = SessionFold()
530
+ fold.apply(turn_started("turn-1", "cmd-1", "v:s:1"))
531
+ fold.apply(model_retry_scheduled("turn-1", "v:s:2"))
532
+ held = fold.turn("turn-1")
533
+ assert held is not None and held.model_retry_scheduled is not None, (
534
+ "the hint is set while the turn runs"
535
+ )
536
+
537
+ fold.apply(turn_completed("turn-1", "completed", "v:s:3"))
538
+
539
+ held = fold.turn("turn-1")
540
+ assert held is not None and held.model_retry_scheduled is None
541
+
542
+
543
+ def test_a_replayed_page_never_re_plants_the_backoff_hint_on_a_turn_that_left_running() -> None:
544
+ fold = SessionFold()
545
+ backoff = model_retry_scheduled("turn-1", "v:s:2")
546
+ page = [
547
+ turn_started("turn-1", "cmd-1", "v:s:1"),
548
+ backoff,
549
+ turn_completed("turn-1", "cancelled", "v:s:3"),
550
+ turn_retracted("turn-1", "cmd-1", "v:s:4"),
551
+ ]
552
+ for event in page:
553
+ fold.apply(event)
554
+ held = fold.turn("turn-1")
555
+ assert held is not None and held.model_retry_scheduled is None, "in-order delivery is clean"
556
+
557
+ for event in page:
558
+ fold.apply(event)
559
+
560
+ held = fold.turn("turn-1")
561
+ assert held is not None
562
+ assert held.state == "retracted"
563
+ assert held.model_retry_scheduled is None, "the replayed hint is dropped"
564
+ assert fold.apply(backoff) == IgnoredStaleFrame("turn/modelRetryScheduled", "turn-1")
565
+
566
+
496
567
  def test_turn_completed_clears_the_foreground_hint() -> None:
497
568
  fold = SessionFold()
498
569
  fold.apply(turn_started("turn-1", "cmd-1", "v:s:1"))
@@ -1081,6 +1152,7 @@ def test_every_generated_view_notification_is_routed_never_the_default() -> None
1081
1152
  "turn/completed": turn_completed("turn-t", "completed", "v:t:6"),
1082
1153
  "turn/retracted": turn_retracted("turn-t2", "cmd-t2", "v:t:7"),
1083
1154
  "turn/retryScheduled": retry_scheduled("turn-t3", "v:t:8"),
1155
+ "turn/modelRetryScheduled": model_retry_scheduled("turn-t3", "v:t:8b"),
1084
1156
  "turn/foregroundCompleted": foreground_completed("turn-t5", "v:t:23"),
1085
1157
  "turn/unqueued": turn_unqueued("turn-t4", "cmd-t4", "v:t:9"),
1086
1158
  "approval/requested": approval_requested("a-t", "v:t:10"),
File without changes
File without changes
File without changes