agentshim 0.15.4__tar.gz → 0.15.6__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 (112) hide show
  1. {agentshim-0.15.4 → agentshim-0.15.6}/CHANGELOG.md +25 -0
  2. {agentshim-0.15.4 → agentshim-0.15.6}/PKG-INFO +1 -1
  3. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/__init__.py +1 -1
  4. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/core/session_policy.py +15 -4
  5. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/codex/app_server/transport.py +12 -8
  6. {agentshim-0.15.4 → agentshim-0.15.6}/pyproject.toml +1 -1
  7. {agentshim-0.15.4 → agentshim-0.15.6}/.gitignore +0 -0
  8. {agentshim-0.15.4 → agentshim-0.15.6}/LICENSE +0 -0
  9. {agentshim-0.15.4 → agentshim-0.15.6}/README.md +0 -0
  10. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/agent.py +0 -0
  11. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/core/__init__.py +0 -0
  12. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/core/_files.py +0 -0
  13. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/core/checkpoints.py +0 -0
  14. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/core/clock.py +0 -0
  15. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/core/conversation.py +0 -0
  16. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/core/env.py +0 -0
  17. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/core/errors.py +0 -0
  18. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/core/events.py +0 -0
  19. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/core/home.py +0 -0
  20. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/core/ids.py +0 -0
  21. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/core/mcp.py +0 -0
  22. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/core/permissions.py +0 -0
  23. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/core/pricing.py +0 -0
  24. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/core/profile.py +0 -0
  25. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/core/provider.py +0 -0
  26. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/core/schema.py +0 -0
  27. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/core/skills.py +0 -0
  28. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/core/status.py +0 -0
  29. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/core/stream.py +0 -0
  30. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/core/turn.py +0 -0
  31. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/core/usage.py +0 -0
  32. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/execution/__init__.py +0 -0
  33. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/execution/confinement.py +0 -0
  34. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/execution/docker.py +0 -0
  35. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/execution/executor.py +0 -0
  36. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/execution/host.py +0 -0
  37. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/execution/process.py +0 -0
  38. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/execution/transform.py +0 -0
  39. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/oneshot.py +0 -0
  40. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/probe.py +0 -0
  41. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/__init__.py +0 -0
  42. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/claude/__init__.py +0 -0
  43. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/claude/events.py +0 -0
  44. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/claude/failures.py +0 -0
  45. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/claude/hooks/__init__.py +0 -0
  46. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/claude/hooks/confine_reads.py +0 -0
  47. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/claude/parser.py +0 -0
  48. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/claude/probe.py +0 -0
  49. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/claude/provider.py +0 -0
  50. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/claude/rate_limits.py +0 -0
  51. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/claude/sandbox.py +0 -0
  52. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/claude/scripted.py +0 -0
  53. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/claude/stream_argv.py +0 -0
  54. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/claude/stream_transport.py +0 -0
  55. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/claude/user_hooks.py +0 -0
  56. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/codex/__init__.py +0 -0
  57. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/codex/_toml.py +0 -0
  58. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/codex/app_server/__init__.py +0 -0
  59. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/codex/app_server/_wire.py +0 -0
  60. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/codex/app_server/approvals.py +0 -0
  61. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/codex/app_server/channel.py +0 -0
  62. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/codex/app_server/errors.py +0 -0
  63. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/codex/app_server/items.py +0 -0
  64. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/codex/app_server/mcp.py +0 -0
  65. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/codex/app_server/permissions.py +0 -0
  66. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/codex/app_server/profile.py +0 -0
  67. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/codex/app_server/protocol.py +0 -0
  68. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/codex/app_server/rate_limits.py +0 -0
  69. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/codex/app_server/usage.py +0 -0
  70. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/codex/events.py +0 -0
  71. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/codex/failures.py +0 -0
  72. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/codex/mcp_scope.py +0 -0
  73. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/codex/parser.py +0 -0
  74. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/codex/probe.py +0 -0
  75. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/codex/provider.py +0 -0
  76. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/codex/rules.py +0 -0
  77. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/codex/sandbox.py +0 -0
  78. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/codex/scripted.py +0 -0
  79. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/codex/skills.py +0 -0
  80. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/copilot/__init__.py +0 -0
  81. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/copilot/events.py +0 -0
  82. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/copilot/parser.py +0 -0
  83. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/copilot/probe.py +0 -0
  84. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/copilot/provider.py +0 -0
  85. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/copilot/scripted.py +0 -0
  86. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/gemini/__init__.py +0 -0
  87. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/gemini/events.py +0 -0
  88. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/gemini/parser.py +0 -0
  89. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/gemini/probe.py +0 -0
  90. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/gemini/provider.py +0 -0
  91. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/gemini/scripted.py +0 -0
  92. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/opencode/__init__.py +0 -0
  93. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/opencode/events.py +0 -0
  94. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/opencode/parser.py +0 -0
  95. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/opencode/probe.py +0 -0
  96. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/opencode/provider.py +0 -0
  97. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/providers/opencode/scripted.py +0 -0
  98. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/py.typed +0 -0
  99. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/runtime.py +0 -0
  100. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/session.py +0 -0
  101. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/testing/__init__.py +0 -0
  102. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/testing/claude_stream.py +0 -0
  103. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/testing/clock.py +0 -0
  104. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/testing/codex_app_server.py +0 -0
  105. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/testing/confinement.py +0 -0
  106. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/testing/contracts.py +0 -0
  107. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/testing/conversation.py +0 -0
  108. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/testing/probe.py +0 -0
  109. {agentshim-0.15.4 → agentshim-0.15.6}/agentshim/testing/process.py +0 -0
  110. {agentshim-0.15.4 → agentshim-0.15.6}/tests/fixtures/claude_stream/README.md +0 -0
  111. {agentshim-0.15.4 → agentshim-0.15.6}/tests/fixtures/codex/README.md +0 -0
  112. {agentshim-0.15.4 → agentshim-0.15.6}/tests/fixtures/codex_app_server/README.md +0 -0
@@ -1,5 +1,30 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.15.6 (2026-10-09)
4
+
5
+ ### Fixed
6
+
7
+ - A Codex app-server that ignores the interrupt of a timed-out turn is stopped, and the
8
+ next turn replaces it by resuming the thread, as the Claude stream transport already
9
+ does. Before, the conversation was written off: the next turn failed with "the previous
10
+ turn did not stop" and the session then forgot the thread, so one hung turn cost two
11
+ failed turns and the conversation's history.
12
+
13
+ ## 0.15.5 (2026-10-09)
14
+
15
+ ### Fixed
16
+
17
+ - A conversation whose provider thread was lost under it is no longer wedged. When a
18
+ turn that did not itself resume (its conversation was opened during the turn)
19
+ failed with `SessionResumeError` (the Codex app-server died mid-turn and its thread
20
+ could not be resumed in the new process), the session kept the dead conversation
21
+ open and every later turn raised the same error. The session now closes and forgets
22
+ it, still without replaying the turn that may have run.
23
+ - A Codex app-server that never acknowledges a turn (silent or wedged) is stopped when
24
+ the turn times out, so the next turn replaces it by resuming the thread instead of
25
+ timing out against the same process forever. (The Claude stream transport already
26
+ killed a process that ignored its interrupt.)
27
+
3
28
  ## 0.15.4 (2026-10-09)
4
29
 
5
30
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: agentshim
3
- Version: 0.15.4
3
+ Version: 0.15.6
4
4
  Summary: Provider-agnostic coding-agent CLI shims
5
5
  License-Expression: MIT
6
6
  License-File: LICENSE
@@ -156,7 +156,7 @@ from .providers.opencode import OpencodeProvider
156
156
  from .runtime import Agent
157
157
  from .session import Session, Turn, TurnTicket, map_mcp_servers
158
158
 
159
- __version__ = "0.15.4"
159
+ __version__ = "0.15.6"
160
160
 
161
161
  __all__ = [
162
162
  "Agent",
@@ -12,7 +12,9 @@ What the policy decides, per turn:
12
12
  * A ``TRANSIENT`` failure is retried in place after each delay of the
13
13
  ``RetryPolicy``; the waits end early when the shell reports a stop.
14
14
  * A refused resume replaces the conversation once, unless the turn must not
15
- lose its conversation (``strict`` or ``pinned``).
15
+ lose its conversation (``strict`` or ``pinned``). A refusal during a turn that
16
+ did not itself resume (the conversation was lost under it) forgets the
17
+ conversation without replaying the turn.
16
18
  * An unclassified failure of a resumed turn forgets the conversation.
17
19
  * After a successful turn that exhausts the provider's ``RenewalBudget`` the
18
20
  conversation is retired.
@@ -531,13 +533,22 @@ class SessionPolicy:
531
533
  if event.outcome is Outcome.TRANSIENT:
532
534
  return self._retry_transient(state, turn, event)
533
535
  if event.outcome is Outcome.RESUME_REFUSED:
534
- if turn.resumed and not turn.keeps_conversation:
535
- return _replace_conversation(state, turn)
536
- return _give_up(state, event.now)
536
+ return self._on_resume_refused(state, turn, event)
537
537
  if event.outcome is Outcome.OTHER and turn.resumed and not turn.keeps_conversation:
538
538
  return _forget_conversation(state, event.now)
539
539
  return _give_up(state, event.now)
540
540
 
541
+ def _on_resume_refused(self, state: SessionState, turn: TurnState, event: Failed) -> Step:
542
+ if turn.keeps_conversation:
543
+ return _give_up(state, event.now)
544
+ if turn.resumed:
545
+ return _replace_conversation(state, turn)
546
+ # The turn began in a conversation it opened itself and the provider
547
+ # then lost it (a process died mid-turn and its thread could not be
548
+ # resumed). The turn may have run, so it is not replayed, but the
549
+ # conversation is gone: holding it would refuse every later turn.
550
+ return _forget_conversation(state, event.now)
551
+
541
552
  def _retry_transient(self, state: SessionState, turn: TurnState, event: Failed) -> Step:
542
553
  delays = self.config.retry.delays
543
554
  if turn.retries >= len(delays):
@@ -153,7 +153,7 @@ class CodexAppServerTransport:
153
153
  The timeouts are in seconds on *clock*: ``startup_timeout`` bounds the
154
154
  handshake, ``close_timeout`` each step of shutting the process down, and
155
155
  ``interrupt_grace`` how long an interrupted or timed-out turn may take to
156
- wind down before the conversation is written off.
156
+ wind down before its process is stopped.
157
157
  """
158
158
 
159
159
  # Each argument is an independent documented option of the public constructor.
@@ -369,7 +369,6 @@ class _Conversation:
369
369
  self._skills: SkillTracker | None = None
370
370
  self._failed_servers: dict[str, str] = {}
371
371
  self._deferred_failure: TurnFailedError | None = None
372
- self._stuck = False
373
372
 
374
373
  # -- Conversation protocol
375
374
 
@@ -559,9 +558,6 @@ class _Conversation:
559
558
  if self._running:
560
559
  msg = "a turn is already running in this conversation"
561
560
  raise SessionStateError(msg)
562
- if self._stuck:
563
- msg = "the previous turn did not stop, so this conversation cannot take another"
564
- raise TurnFailedError(msg, kind=FailureKind.OTHER, detail=msg)
565
561
  self._running = True
566
562
  self._turn_id = None
567
563
  self._interrupt_asked = False
@@ -596,6 +592,12 @@ class _Conversation:
596
592
  self._handle(self._channel.read(deadline), turn)
597
593
  except Expired:
598
594
  self._wind_down(turn)
595
+ if turn.turn_id is None:
596
+ # The server never acknowledged the turn, so it is silent or
597
+ # wedged and no interrupt can reach it. Stop it: the next turn
598
+ # replaces the process by resuming the thread, where holding
599
+ # it would time out every later turn too.
600
+ _stop(self._channel.process, self._timeouts.close)
599
601
  raise TurnTimeoutError(request.timeout or 0.0) from None
600
602
  except Gone as gone:
601
603
  raise self._gone_error(gone) from None
@@ -853,8 +855,10 @@ class _Conversation:
853
855
  def _wind_down(self, turn: _Turn) -> None:
854
856
  """Stop a turn that is being abandoned and wait, within bounds, for the server to agree.
855
857
 
856
- If the server never reports the turn over, the conversation is written
857
- off: another ``turn/start`` on it could collide with the one still running.
858
+ If the server never reports the turn over, the process is stopped:
859
+ another ``turn/start`` on it could collide with the one still running.
860
+ The next turn replaces it by resuming the thread, as the Claude stream
861
+ transport does for a process that ignores its interrupt.
858
862
  """
859
863
  if turn.turn_id is None or turn.completed is not None:
860
864
  return
@@ -865,7 +869,7 @@ class _Conversation:
865
869
  while turn.completed is None:
866
870
  self._handle(self._channel.read(deadline), turn)
867
871
  except (Expired, Gone, AgentShimError):
868
- self._stuck = True
872
+ _stop(self._channel.process, self._timeouts.close)
869
873
 
870
874
  # -- finishing
871
875
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "agentshim"
3
- version = "0.15.4"
3
+ version = "0.15.6"
4
4
  description = "Provider-agnostic coding-agent CLI shims"
5
5
  readme = "README.md"
6
6
  license = "MIT"
File without changes
File without changes
File without changes