meshagent-codex 0.43.2__tar.gz → 0.44.0__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 (45) hide show
  1. {meshagent_codex-0.43.2/meshagent_codex.egg-info → meshagent_codex-0.44.0}/PKG-INFO +5 -5
  2. {meshagent_codex-0.43.2 → meshagent_codex-0.44.0}/meshagent/codex/process.py +22 -1
  3. {meshagent_codex-0.43.2 → meshagent_codex-0.44.0}/meshagent/codex/process_test.py +7 -1
  4. {meshagent_codex-0.43.2 → meshagent_codex-0.44.0}/meshagent/codex/supervisor.py +75 -10
  5. {meshagent_codex-0.43.2 → meshagent_codex-0.44.0}/meshagent/codex/thread_storage.py +16 -1
  6. {meshagent_codex-0.43.2 → meshagent_codex-0.44.0}/meshagent/codex/thread_storage_test.py +3 -1
  7. meshagent_codex-0.44.0/meshagent/codex/version.py +1 -0
  8. {meshagent_codex-0.43.2 → meshagent_codex-0.44.0/meshagent_codex.egg-info}/PKG-INFO +5 -5
  9. meshagent_codex-0.44.0/meshagent_codex.egg-info/requires.txt +6 -0
  10. {meshagent_codex-0.43.2 → meshagent_codex-0.44.0}/pyproject.toml +4 -4
  11. meshagent_codex-0.43.2/meshagent/codex/version.py +0 -1
  12. meshagent_codex-0.43.2/meshagent_codex.egg-info/requires.txt +0 -6
  13. {meshagent_codex-0.43.2 → meshagent_codex-0.44.0}/LICENSE +0 -0
  14. {meshagent_codex-0.43.2 → meshagent_codex-0.44.0}/MANIFEST.in +0 -0
  15. {meshagent_codex-0.43.2 → meshagent_codex-0.44.0}/README.md +0 -0
  16. {meshagent_codex-0.43.2 → meshagent_codex-0.44.0}/meshagent/codex/__init__.py +0 -0
  17. {meshagent_codex-0.43.2 → meshagent_codex-0.44.0}/meshagent/codex/process_e2e_test.py +0 -0
  18. {meshagent_codex-0.43.2 → meshagent_codex-0.44.0}/meshagent/codex/py.typed +0 -0
  19. {meshagent_codex-0.43.2 → meshagent_codex-0.44.0}/meshagent/codex/supervisor_test.py +0 -0
  20. {meshagent_codex-0.43.2 → meshagent_codex-0.44.0}/meshagent/codex/vendor/__init__.py +0 -0
  21. {meshagent_codex-0.43.2 → meshagent_codex-0.44.0}/meshagent/codex/vendor/openai_codex/LICENSE +0 -0
  22. {meshagent_codex-0.43.2 → meshagent_codex-0.44.0}/meshagent/codex/vendor/openai_codex/__init__.py +0 -0
  23. {meshagent_codex-0.43.2 → meshagent_codex-0.44.0}/meshagent/codex/vendor/openai_codex/_approval_mode.py +0 -0
  24. {meshagent_codex-0.43.2 → meshagent_codex-0.44.0}/meshagent/codex/vendor/openai_codex/_initialize_metadata.py +0 -0
  25. {meshagent_codex-0.43.2 → meshagent_codex-0.44.0}/meshagent/codex/vendor/openai_codex/_inputs.py +0 -0
  26. {meshagent_codex-0.43.2 → meshagent_codex-0.44.0}/meshagent/codex/vendor/openai_codex/_login.py +0 -0
  27. {meshagent_codex-0.43.2 → meshagent_codex-0.44.0}/meshagent/codex/vendor/openai_codex/_message_router.py +0 -0
  28. {meshagent_codex-0.43.2 → meshagent_codex-0.44.0}/meshagent/codex/vendor/openai_codex/_run.py +0 -0
  29. {meshagent_codex-0.43.2 → meshagent_codex-0.44.0}/meshagent/codex/vendor/openai_codex/_version.py +0 -0
  30. {meshagent_codex-0.43.2 → meshagent_codex-0.44.0}/meshagent/codex/vendor/openai_codex/api.py +0 -0
  31. {meshagent_codex-0.43.2 → meshagent_codex-0.44.0}/meshagent/codex/vendor/openai_codex/async_client.py +0 -0
  32. {meshagent_codex-0.43.2 → meshagent_codex-0.44.0}/meshagent/codex/vendor/openai_codex/client.py +0 -0
  33. {meshagent_codex-0.43.2 → meshagent_codex-0.44.0}/meshagent/codex/vendor/openai_codex/client_test.py +0 -0
  34. {meshagent_codex-0.43.2 → meshagent_codex-0.44.0}/meshagent/codex/vendor/openai_codex/errors.py +0 -0
  35. {meshagent_codex-0.43.2 → meshagent_codex-0.44.0}/meshagent/codex/vendor/openai_codex/generated/__init__.py +0 -0
  36. {meshagent_codex-0.43.2 → meshagent_codex-0.44.0}/meshagent/codex/vendor/openai_codex/generated/notification_registry.py +0 -0
  37. {meshagent_codex-0.43.2 → meshagent_codex-0.44.0}/meshagent/codex/vendor/openai_codex/generated/v2_all.py +0 -0
  38. {meshagent_codex-0.43.2 → meshagent_codex-0.44.0}/meshagent/codex/vendor/openai_codex/models.py +0 -0
  39. {meshagent_codex-0.43.2 → meshagent_codex-0.44.0}/meshagent/codex/vendor/openai_codex/py.typed +0 -0
  40. {meshagent_codex-0.43.2 → meshagent_codex-0.44.0}/meshagent/codex/vendor/openai_codex/retry.py +0 -0
  41. {meshagent_codex-0.43.2 → meshagent_codex-0.44.0}/meshagent/codex/vendor/openai_codex/types.py +0 -0
  42. {meshagent_codex-0.43.2 → meshagent_codex-0.44.0}/meshagent_codex.egg-info/SOURCES.txt +0 -0
  43. {meshagent_codex-0.43.2 → meshagent_codex-0.44.0}/meshagent_codex.egg-info/dependency_links.txt +0 -0
  44. {meshagent_codex-0.43.2 → meshagent_codex-0.44.0}/meshagent_codex.egg-info/top_level.txt +0 -0
  45. {meshagent_codex-0.43.2 → meshagent_codex-0.44.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshagent-codex
3
- Version: 0.43.2
3
+ Version: 0.44.0
4
4
  Summary: Codex app-server adapter and chatbot for Meshagent
5
5
  License-Expression: Apache-2.0
6
6
  Project-URL: Documentation, https://docs.meshagent.com
@@ -9,10 +9,10 @@ Project-URL: Source, https://www.meshagent.com
9
9
  Requires-Python: >=3.13
10
10
  Description-Content-Type: text/markdown
11
11
  License-File: LICENSE
12
- Requires-Dist: meshagent-api==0.43.2
13
- Requires-Dist: meshagent-agents==0.43.2
14
- Requires-Dist: meshagent-openai==0.43.2
15
- Requires-Dist: meshagent-tools==0.43.2
12
+ Requires-Dist: meshagent-api==0.44.0
13
+ Requires-Dist: meshagent-agents==0.44.0
14
+ Requires-Dist: meshagent-openai==0.44.0
15
+ Requires-Dist: meshagent-tools==0.44.0
16
16
  Requires-Dist: pytest~=8.4
17
17
  Requires-Dist: pytest-asyncio~=0.26
18
18
  Dynamic: license-file
@@ -27,6 +27,7 @@ from meshagent.agents.messages import (
27
27
  AGENT_EVENT_TURN_STEERED,
28
28
  AGENT_EVENT_TURN_STEER_ACCEPTED,
29
29
  AGENT_EVENT_TURN_STEER_REJECTED,
30
+ AGENT_EVENT_THREAD_UPDATED,
30
31
  AGENT_MESSAGE_CAPABILITIES_REQUEST,
31
32
  AGENT_MESSAGE_CAPABILITIES_RESPONSE,
32
33
  AGENT_MESSAGE_MODEL_CHANGE,
@@ -45,6 +46,7 @@ from meshagent.agents.messages import (
45
46
  AgentTextContentEnded,
46
47
  AgentTextContentStarted,
47
48
  AgentThreadEvent,
49
+ AgentThreadListEntry,
48
50
  AgentThreadMessage,
49
51
  AgentToolCallEnded,
50
52
  AgentToolCallStarted,
@@ -57,6 +59,7 @@ from meshagent.agents.messages import (
57
59
  ModelsResponse,
58
60
  OpenThread,
59
61
  ThreadLoaded,
62
+ ThreadUpdated,
60
63
  TurnEnded,
61
64
  TurnInterrupt,
62
65
  TurnInterrupted,
@@ -91,6 +94,7 @@ from .vendor.openai_codex.generated.v2_all import (
91
94
  ThreadReadResponse,
92
95
  ThreadResumeResponse,
93
96
  ThreadStartResponse,
97
+ ThreadNameUpdatedNotification,
94
98
  ThreadTokenUsageUpdatedNotification,
95
99
  TokenUsageBreakdown,
96
100
  TurnCompletedNotification,
@@ -344,7 +348,6 @@ class CodexAgentProcess(AgentProcess):
344
348
  turn_messages.append(
345
349
  AgentTextContentDelta(
346
350
  type=AGENT_EVENT_TEXT_CONTENT_DELTA,
347
- message_id=thread_item.id,
348
351
  thread_id=thread_id,
349
352
  turn_id=turn.id,
350
353
  item_id=thread_item.id,
@@ -730,6 +733,24 @@ class CodexAgentProcess(AgentProcess):
730
733
  ),
731
734
  )
732
735
  return
736
+ if isinstance(payload, ThreadNameUpdatedNotification):
737
+ name = (
738
+ payload.thread_name.strip()
739
+ if isinstance(payload.thread_name, str)
740
+ else ""
741
+ )
742
+ if name != "":
743
+ self.emit(
744
+ sender=active_turn.sender,
745
+ payload=ThreadUpdated(
746
+ type=AGENT_EVENT_THREAD_UPDATED,
747
+ thread=AgentThreadListEntry(
748
+ path=self._thread_id_or_raise(),
749
+ name=name,
750
+ ),
751
+ ),
752
+ )
753
+ return
733
754
  diff_tool = _codex_diff_tool_from_notification(notification=notification)
734
755
  if diff_tool is not None:
735
756
  self._emit_codex_diff_tool(tool=diff_tool, active_turn=active_turn)
@@ -82,7 +82,11 @@ class _FakeCodexClient:
82
82
  ) -> ThreadStartResponse:
83
83
  self.thread_start_calls.append(params)
84
84
  return ThreadStartResponse.model_construct(
85
- thread=Thread.model_construct(id="codex-thread-1")
85
+ thread=Thread.model_construct(
86
+ id="codex-thread-1",
87
+ name=None,
88
+ preview="Codex Thread",
89
+ )
86
90
  )
87
91
 
88
92
  async def thread_inject_items(self, thread_id: str, items: list[Any]) -> None:
@@ -689,6 +693,8 @@ async def test_codex_agent_process_loads_thread_messages_on_open() -> None:
689
693
  AgentTextContent(type="text", text="loaded hello")
690
694
  ]
691
695
  assert process.messages[1].text == "loaded response"
696
+ assert process.messages[1].item_id == "agent-item-1"
697
+ assert process.messages[1].message_id != "agent-item-1"
692
698
 
693
699
  session = _NoopChatClient()._create_thread_session(thread_path="thread-1")
694
700
  for agent_message in process.messages:
@@ -23,11 +23,13 @@ from meshagent.agents.messages import (
23
23
  from meshagent.agents.process import (
24
24
  AgentProcess,
25
25
  AgentSupervisor,
26
+ CreatedAgentThread,
26
27
  ThreadIsolationMode,
27
28
  )
28
29
  from meshagent.agents.thread_status_publisher import AgentMessageThreadStatusPublisher
29
30
  from meshagent.agents.thread_storage import (
30
31
  NoopThreadStorageRepository,
32
+ ThreadListEntry,
31
33
  ThreadStorage,
32
34
  ThreadStorageRepository,
33
35
  )
@@ -245,23 +247,86 @@ class CodexBackend:
245
247
  del sender
246
248
  return None
247
249
 
248
- async def create_thread_id(
250
+ async def create_thread(
249
251
  self,
250
252
  *,
251
253
  supervisor: AgentSupervisor,
252
254
  start_thread: StartThread,
253
255
  sender: Participant | None,
254
- ) -> str:
255
- del supervisor
256
- del sender
256
+ ) -> CreatedAgentThread:
257
257
  if self._thread_storage == "dataset":
258
- return self._new_dataset_thread_id()
258
+ thread_id = self._new_dataset_thread_id()
259
+ name = self._thread_name_for_start_thread(start_thread=start_thread)
260
+ return CreatedAgentThread(
261
+ thread_id=thread_id,
262
+ name=name,
263
+ metadata=lambda: self._publish_thread_metadata(
264
+ supervisor=supervisor,
265
+ thread_id=thread_id,
266
+ name=name,
267
+ start_thread=start_thread,
268
+ sender=sender,
269
+ ),
270
+ )
259
271
  if self._thread_storage == "none":
260
- return self._new_tmp_thread_id()
261
- return await CodexThreadStorageRepository(
262
- client_provider=lambda: self.client,
263
- default_model=lambda: self.default_model,
264
- ).create_thread_id(start_thread=start_thread)
272
+ thread_id = self._new_tmp_thread_id()
273
+ name = self._thread_name_for_start_thread(start_thread=start_thread)
274
+ return CreatedAgentThread(
275
+ thread_id=thread_id,
276
+ name=name,
277
+ metadata=lambda: self._publish_thread_metadata(
278
+ supervisor=supervisor,
279
+ thread_id=thread_id,
280
+ name=name,
281
+ start_thread=start_thread,
282
+ sender=sender,
283
+ ),
284
+ )
285
+ params: dict[str, object] = {
286
+ "model": start_thread.model or self.default_model,
287
+ }
288
+ if start_thread.instructions is not None:
289
+ params["developerInstructions"] = start_thread.instructions
290
+ if start_thread.name is not None:
291
+ params["config"] = {"name": start_thread.name}
292
+ response = await self.client.thread_start(params)
293
+ thread = response.thread
294
+ name = thread.name.strip() if isinstance(thread.name, str) else ""
295
+ if name == "" and isinstance(thread.preview, str):
296
+ name = thread.preview.strip()
297
+ if name == "":
298
+ name = thread.id
299
+ return CreatedAgentThread(
300
+ thread_id=thread.id,
301
+ name=name,
302
+ metadata=lambda: self._publish_thread_metadata(
303
+ supervisor=supervisor,
304
+ thread_id=thread.id,
305
+ name=name,
306
+ start_thread=start_thread,
307
+ sender=sender,
308
+ ),
309
+ )
310
+
311
+ async def _publish_thread_metadata(
312
+ self,
313
+ *,
314
+ supervisor: AgentSupervisor,
315
+ thread_id: str,
316
+ name: str,
317
+ start_thread: StartThread,
318
+ sender: Participant | None,
319
+ ) -> ThreadListEntry | None:
320
+ return await supervisor.on_thread_started(
321
+ created_thread=CreatedAgentThread(thread_id=thread_id, name=name),
322
+ start_thread=start_thread,
323
+ sender=sender,
324
+ )
325
+
326
+ def _thread_name_for_start_thread(self, *, start_thread: StartThread) -> str:
327
+ if isinstance(start_thread.name, str) and start_thread.name.strip() != "":
328
+ return start_thread.name.strip()
329
+ return "New Chat"
265
330
 
266
331
  def create_thread_process(
267
332
  self,
@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  import asyncio
4
4
  from collections.abc import AsyncIterator, Callable
5
+ from datetime import datetime, timezone
5
6
  from typing import Any, Protocol
6
7
 
7
8
  from meshagent.agents.context import AgentSessionContext
@@ -37,6 +38,10 @@ class CodexThreadStorage:
37
38
  self._path = path
38
39
  self._is_ephemeral = is_ephemeral
39
40
 
41
+ @property
42
+ def scheme(self) -> str:
43
+ return "codex"
44
+
40
45
  @property
41
46
  def path(self) -> str:
42
47
  return self._path
@@ -103,6 +108,10 @@ class CodexThreadStorageRepository:
103
108
  self._client_provider = client_provider
104
109
  self._default_model = default_model
105
110
 
111
+ @property
112
+ def scheme(self) -> str:
113
+ return "codex"
114
+
106
115
  @property
107
116
  def client(self) -> CodexThreadClient:
108
117
  if self._client is not None:
@@ -136,7 +145,13 @@ class CodexThreadStorageRepository:
136
145
  name: str,
137
146
  ) -> ThreadListEntry | None:
138
147
  await self.client.thread_set_name(path, name)
139
- return None
148
+ now = datetime.now(timezone.utc).isoformat()
149
+ return ThreadListEntry(
150
+ path=path,
151
+ name=name,
152
+ created_at=now,
153
+ modified_at=now,
154
+ )
140
155
 
141
156
  async def delete_thread(
142
157
  self,
@@ -85,7 +85,9 @@ async def test_codex_thread_repository_lists_renames_and_deletes_threads() -> No
85
85
  await repository.delete_thread(path="thread-2")
86
86
 
87
87
  assert [entry.name for entry in page.threads] == ["Named Thread", "Preview Thread"]
88
- assert renamed is None
88
+ assert renamed is not None
89
+ assert renamed.path == "thread-1"
90
+ assert renamed.name == "Renamed"
89
91
  assert client.renamed_threads == [("thread-1", "Renamed")]
90
92
  assert client.archived_thread_ids == ["thread-2"]
91
93
 
@@ -0,0 +1 @@
1
+ __version__ = "0.44.0"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshagent-codex
3
- Version: 0.43.2
3
+ Version: 0.44.0
4
4
  Summary: Codex app-server adapter and chatbot for Meshagent
5
5
  License-Expression: Apache-2.0
6
6
  Project-URL: Documentation, https://docs.meshagent.com
@@ -9,10 +9,10 @@ Project-URL: Source, https://www.meshagent.com
9
9
  Requires-Python: >=3.13
10
10
  Description-Content-Type: text/markdown
11
11
  License-File: LICENSE
12
- Requires-Dist: meshagent-api==0.43.2
13
- Requires-Dist: meshagent-agents==0.43.2
14
- Requires-Dist: meshagent-openai==0.43.2
15
- Requires-Dist: meshagent-tools==0.43.2
12
+ Requires-Dist: meshagent-api==0.44.0
13
+ Requires-Dist: meshagent-agents==0.44.0
14
+ Requires-Dist: meshagent-openai==0.44.0
15
+ Requires-Dist: meshagent-tools==0.44.0
16
16
  Requires-Dist: pytest~=8.4
17
17
  Requires-Dist: pytest-asyncio~=0.26
18
18
  Dynamic: license-file
@@ -0,0 +1,6 @@
1
+ meshagent-api==0.44.0
2
+ meshagent-agents==0.44.0
3
+ meshagent-openai==0.44.0
4
+ meshagent-tools==0.44.0
5
+ pytest~=8.4
6
+ pytest-asyncio~=0.26
@@ -10,10 +10,10 @@ requires-python = ">=3.13"
10
10
  license = "Apache-2.0"
11
11
  keywords = []
12
12
  dependencies = [
13
- "meshagent-api==0.43.2",
14
- "meshagent-agents==0.43.2",
15
- "meshagent-openai==0.43.2",
16
- "meshagent-tools==0.43.2",
13
+ "meshagent-api==0.44.0",
14
+ "meshagent-agents==0.44.0",
15
+ "meshagent-openai==0.44.0",
16
+ "meshagent-tools==0.44.0",
17
17
  "pytest~=8.4",
18
18
  "pytest-asyncio~=0.26",
19
19
  ]
@@ -1 +0,0 @@
1
- __version__ = "0.43.2"
@@ -1,6 +0,0 @@
1
- meshagent-api==0.43.2
2
- meshagent-agents==0.43.2
3
- meshagent-openai==0.43.2
4
- meshagent-tools==0.43.2
5
- pytest~=8.4
6
- pytest-asyncio~=0.26