python-codex 0.3.3__py3-none-any.whl → 0.4.1__py3-none-any.whl

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 (61) hide show
  1. pycodex/__init__.py +3 -27
  2. pycodex/bootstrap.py +5 -45
  3. pycodex/cli.py +1 -14
  4. pycodex/context.py +1 -1
  5. pycodex/events.py +1 -1
  6. pycodex/model.py +2 -2
  7. pycodex/portable/__init__.py +45 -0
  8. pycodex/{portable.py → portable/client.py} +4 -7
  9. pycodex/{portable_server.py → portable/server.py} +3 -3
  10. pycodex/protocol.py +1 -1
  11. pycodex/runtime.py +2 -2
  12. pycodex/tools/base_tool.py +1 -1
  13. pycodex/tools/close_agent_tool.py +1 -1
  14. pycodex/tools/code_mode_manager.py +1 -1
  15. pycodex/tools/request_permissions_tool.py +1 -1
  16. pycodex/tools/resume_agent_tool.py +1 -1
  17. pycodex/{runtime_services.py → tools/runtime_services.py} +5 -5
  18. pycodex/tools/send_input_tool.py +1 -1
  19. pycodex/tools/spawn_agent_tool.py +1 -1
  20. pycodex/tools/unified_exec_manager.py +1 -1
  21. pycodex/tools/update_plan_tool.py +1 -1
  22. pycodex/tools/view_image_tool.py +5 -0
  23. pycodex/tools/wait_agent_tool.py +1 -1
  24. pycodex/utils/__init__.py +0 -4
  25. pycodex/utils/_aes_gcm/LICENSE +56 -0
  26. pycodex/utils/_aes_gcm/README.md +61 -0
  27. pycodex/utils/_aes_gcm/__init__.py +1 -0
  28. pycodex/utils/_aes_gcm/aes.py +175 -0
  29. pycodex/utils/_aes_gcm/gcm.py +73 -0
  30. pycodex/utils/_aes_gcm/source-sha256.json +4 -0
  31. pycodex/utils/async_bridge.py +3 -4
  32. pycodex/{compat.py → utils/compat.py} +2 -0
  33. pycodex/utils/crypto.py +35 -0
  34. pycodex/utils/debug.py +24 -0
  35. pycodex/{doctor.py → utils/doctor.py} +3 -3
  36. pycodex/utils/image_utils.py +3 -2
  37. pycodex/{model_metadata.py → utils/model_metadata.py} +2 -2
  38. pycodex/utils/session_persist.py +28 -0
  39. {python_codex-0.3.3.dist-info → python_codex-0.4.1.dist-info}/METADATA +124 -42
  40. python_codex-0.4.1.dist-info/RECORD +90 -0
  41. {python_codex-0.3.3.dist-info → python_codex-0.4.1.dist-info}/entry_points.txt +0 -1
  42. responses_server/app.py +28 -15
  43. pycodex/feishu_card.py +0 -793
  44. pycodex/feishu_link.py +0 -440
  45. pycodex/tools/ipython_tool.py +0 -142
  46. python_codex-0.3.3.dist-info/RECORD +0 -98
  47. workspace_server/__init__.py +0 -39
  48. workspace_server/__main__.py +0 -4
  49. workspace_server/app.py +0 -1906
  50. workspace_server/content_views.LICENSE.txt +0 -470
  51. workspace_server/content_views.css +0 -1
  52. workspace_server/content_views.mjs +0 -25
  53. workspace_server/editor.css +0 -1
  54. workspace_server/editor.mjs +0 -1260
  55. workspace_server/owned_process.py +0 -27
  56. workspace_server/workspace.html +0 -2267
  57. workspace_server/workspace_views.py +0 -533
  58. workspace_server/workspaces.html +0 -550
  59. workspace_server/workspaces.py +0 -632
  60. {python_codex-0.3.3.dist-info → python_codex-0.4.1.dist-info}/WHEEL +0 -0
  61. {python_codex-0.3.3.dist-info → python_codex-0.4.1.dist-info}/licenses/LICENSE +0 -0
pycodex/feishu_link.py DELETED
@@ -1,440 +0,0 @@
1
- import asyncio
2
- import threading
3
- import time
4
- import typing
5
-
6
- from .events import SessionStateEvent
7
- from .feishu_card import PycodexCard
8
- from .runtime import AgentRuntime
9
-
10
- CARD_UPDATE_FLUSH_INTERVAL_SECONDS = 0.5
11
- _LISTENER = None
12
- _LISTENER_LOCK = threading.Lock()
13
-
14
-
15
- class PycodexRuntimeLink:
16
- def __init__(
17
- self,
18
- runtime: "AgentRuntime",
19
- target: str,
20
- loop=None,
21
- card: "typing.Union[PycodexCard, None]" = None,
22
- ) -> None:
23
- self.runtime = runtime
24
- self.target = target
25
- self.loop = loop
26
- self.card = card or PycodexCard.from_env()
27
- self.session_key = None
28
- self.message_id = None
29
- self._listener = None
30
- self._frontend_id = None
31
- self._detached = False
32
- self._update_thread = None
33
- self._update_stop = threading.Event()
34
- self._update_lock = threading.Lock()
35
- self._update_pending = False
36
-
37
- async def start_async(self) -> "PycodexRuntimeLink":
38
- self.loop = asyncio.get_event_loop()
39
- self.card.apply_event(SessionStateEvent("attach", self.runtime.snapshot()))
40
- try:
41
- await self.loop.run_in_executor(None, self.start)
42
- except Exception:
43
- await self.loop.run_in_executor(None, self.stop)
44
- raise
45
- self._frontend_id = self.runtime.attach(self._handle_runtime_event)
46
- return self
47
-
48
- def start(self) -> "PycodexRuntimeLink":
49
- if self.loop is None:
50
- raise RuntimeError("PycodexRuntimeLink.start_async() is required")
51
- self.card.send(self.target)
52
- self.session_key = self.card.session_key
53
- self.message_id = self.card.message_id
54
- self._listener = _feishu_listener(self.card)
55
- self._listener.register(self)
56
- self._listener.start()
57
- self._start_update_thread()
58
- return self
59
-
60
- def stop(self) -> None:
61
- self._detach_frontend()
62
- if self._listener is not None:
63
- _release_feishu_listener(self._listener, self)
64
- self._listener = None
65
- self._stop_update_thread()
66
-
67
- def detach(self) -> None:
68
- self._detached = True
69
- self._detach_frontend()
70
- if self._listener is not None:
71
- _release_feishu_listener(self._listener, self)
72
- self._listener = None
73
- self.card.detach()
74
- self._safe_update_card()
75
- self._stop_update_thread()
76
-
77
- def _detach_frontend(self) -> None:
78
- if self._frontend_id is not None:
79
- self.runtime.detach(self._frontend_id)
80
- self._frontend_id = None
81
-
82
- def _handle_runtime_event(self, event) -> None:
83
- if self._detached:
84
- return
85
- self.card.apply_event(event)
86
- self._update_card()
87
-
88
- async def _submit(
89
- self, action: "typing.Dict[str, object]"
90
- ) -> "typing.Dict[str, object]":
91
- if self._detached:
92
- return {"toast": {"type": "warning", "content": "pycodex is detached."}}
93
- if action.get("action") == "history":
94
- try:
95
- self.card.show_history(action.get("history_index"))
96
- except ValueError as exc:
97
- return {"toast": {"type": "warning", "content": str(exc)}}
98
- self._update_card()
99
- return {}
100
- if action.get("action") != "send":
101
- return {
102
- "toast": {
103
- "type": "info",
104
- "content": "Unsupported action: {0}".format(action.get("action")),
105
- }
106
- }
107
- prompt = str(action.get("prompt") or "").strip()
108
- future = asyncio.run_coroutine_threadsafe(
109
- self.runtime.submit_input(
110
- prompt, sender=str(action.get("sender") or "feishu")
111
- ),
112
- self.loop,
113
- )
114
- try:
115
- await asyncio.wrap_future(future)
116
- except (ValueError, RuntimeError) as exc:
117
- return {"toast": {"type": "warning", "content": str(exc)}}
118
- return {"toast": {"type": "info", "content": "Input submitted."}}
119
-
120
- def _update_card(self) -> None:
121
- with self._update_lock:
122
- self._update_pending = True
123
-
124
- def _safe_update_card(self) -> None:
125
- try:
126
- self.card.update()
127
- except Exception as e:
128
- print(e)
129
-
130
- def _start_update_thread(self) -> None:
131
- if self._update_thread is not None and self._update_thread.is_alive():
132
- return
133
- self._update_stop.clear()
134
- self._update_thread = threading.Thread(
135
- target=self._run_update_loop,
136
- name="pycodex-feishu-card",
137
- )
138
- self._update_thread.daemon = True
139
- self._update_thread.start()
140
-
141
- def _stop_update_thread(self) -> None:
142
- self._update_stop.set()
143
- thread = self._update_thread
144
- if thread is not None and thread.is_alive():
145
- thread.join(timeout=2.0)
146
- self._update_thread = None
147
-
148
- def _run_update_loop(self) -> None:
149
- while not self._update_stop.wait(CARD_UPDATE_FLUSH_INTERVAL_SECONDS):
150
- with self._update_lock:
151
- if not self._update_pending:
152
- continue
153
- self._update_pending = False
154
- self._safe_update_card()
155
-
156
-
157
- def _feishu_listener(card: PycodexCard) -> "_FeishuCardActionListener":
158
- global _LISTENER
159
- with _LISTENER_LOCK:
160
- if _LISTENER is None:
161
- _LISTENER = _FeishuCardActionListener(card)
162
- else:
163
- _LISTENER.assert_compatible(card)
164
- return _LISTENER
165
-
166
-
167
- def _release_feishu_listener(
168
- listener: "_FeishuCardActionListener",
169
- link: PycodexRuntimeLink,
170
- ) -> None:
171
- global _LISTENER
172
- with _LISTENER_LOCK:
173
- listener.unregister(link)
174
- if listener.empty():
175
- listener.stop()
176
- if _LISTENER is listener:
177
- _LISTENER = None
178
-
179
-
180
- class _FeishuCardActionListener:
181
- def __init__(self, card: PycodexCard) -> None:
182
- self.app_id = card.app_id
183
- self.app_secret = card.app_secret
184
- self.domain = card.domain
185
- self.encrypt_key = card.encrypt_key
186
- self.verification_token = card.verification_token
187
- self._links = {}
188
- self._links_lock = threading.Lock()
189
- self._async_thread = _AsyncLoopThread()
190
- self._thread = None
191
- self._client = None
192
- self._client_loop = None
193
- self._stop_requested = threading.Event()
194
-
195
- def assert_compatible(self, card: PycodexCard) -> None:
196
- if self.app_id != card.app_id or self.domain != card.domain:
197
- raise RuntimeError("Feishu listener is already running for another app")
198
-
199
- def start(self) -> None:
200
- if not self.app_id or not self.app_secret:
201
- raise RuntimeError("FEISHU_APP_ID and FEISHU_APP_SECRET are required")
202
- if self._thread is not None and self._thread.is_alive():
203
- return
204
- self._stop_requested.clear()
205
- self._async_thread.start()
206
- self._thread = threading.Thread(
207
- target=self._listen,
208
- name="pycodex-feishu-link",
209
- )
210
- self._thread.daemon = True
211
- self._thread.start()
212
-
213
- def register(self, link: PycodexRuntimeLink) -> None:
214
- message_id = str(getattr(link, "message_id", "") or "").strip()
215
- if not message_id:
216
- raise RuntimeError("Feishu linked card message_id is required")
217
- with self._links_lock:
218
- self._links[message_id] = link
219
-
220
- def unregister(self, link: PycodexRuntimeLink) -> None:
221
- message_id = str(getattr(link, "message_id", "") or "").strip()
222
- with self._links_lock:
223
- if message_id and self._links.get(message_id) is link:
224
- del self._links[message_id]
225
- return
226
- stale_ids = [
227
- registered_id
228
- for registered_id, registered_link in self._links.items()
229
- if registered_link is link
230
- ]
231
- for registered_id in stale_ids:
232
- del self._links[registered_id]
233
-
234
- def empty(self) -> bool:
235
- with self._links_lock:
236
- return not self._links
237
-
238
- def stop(self) -> None:
239
- self._stop_requested.set()
240
- client = self._client
241
- loop = self._client_loop
242
- if loop is not None:
243
- _stop_lark_client(client, loop)
244
- thread = self._thread
245
- if thread is not None and thread.is_alive():
246
- thread.join(timeout=2.0)
247
- self._thread = None
248
- self._async_thread.stop()
249
-
250
- def _listen(self) -> None:
251
- try:
252
- import lark_oapi as lark
253
- import lark_oapi.ws as lark_ws
254
- from lark_oapi.event.callback.model.p2_card_action_trigger import (
255
- P2CardActionTriggerResponse,
256
- )
257
- except ImportError as exc:
258
- raise RuntimeError(
259
- "lark-oapi is required for Feishu long-connection mode"
260
- ) from exc
261
-
262
- def on_card_action(event):
263
- return P2CardActionTriggerResponse(self._handle_card_action(event))
264
-
265
- handler = (
266
- lark.EventDispatcherHandler.builder(
267
- self.encrypt_key or "",
268
- self.verification_token or "",
269
- lark.LogLevel.INFO,
270
- )
271
- .register_p2_card_action_trigger(on_card_action)
272
- .build()
273
- )
274
- import lark_oapi.ws.client as lark_ws_client
275
-
276
- client = None
277
- loop = asyncio.new_event_loop()
278
- self._client_loop = loop
279
- asyncio.set_event_loop(loop)
280
- lark_ws_client.loop = loop
281
- try:
282
- if self._stop_requested.is_set():
283
- return
284
- client = lark_ws.Client(
285
- self.app_id,
286
- self.app_secret,
287
- event_handler=handler,
288
- domain=self.domain,
289
- )
290
- self._client = client
291
- if self._stop_requested.is_set():
292
- return
293
- client.start()
294
- except RuntimeError as exc:
295
- stopped = "Event loop stopped before Future completed" in str(exc)
296
- if not self._stop_requested.is_set() or not stopped:
297
- raise
298
- finally:
299
- if self._client is client:
300
- self._client = None
301
- if self._client_loop is loop:
302
- self._client_loop = None
303
- _close_loop(loop)
304
- asyncio.set_event_loop(None)
305
-
306
- def _handle_card_action(self, event) -> "typing.Dict[str, object]":
307
- try:
308
- message_id = _event_message_id(event)
309
- link = self._resolve_link(message_id)
310
- if link is None or link._detached:
311
- return {
312
- "toast": {
313
- "type": "warning",
314
- "content": "pycodex is detached.",
315
- }
316
- }
317
- action = link.card.parse_action(event)
318
- return self._async_thread.run(link._submit(action))
319
- except Exception as exc:
320
- return {
321
- "toast": {
322
- "type": "error",
323
- "content": "pycodex error: {0}".format(exc),
324
- }
325
- }
326
-
327
- def _resolve_link(self, message_id):
328
- message_id = str(message_id or "").strip()
329
- with self._links_lock:
330
- if message_id:
331
- return self._links.get(message_id)
332
- if len(self._links) == 1:
333
- return next(iter(self._links.values()))
334
- return None
335
-
336
-
337
- def _event_message_id(event) -> "typing.Union[str, None]":
338
- event_data = getattr(event, "event", None)
339
- context = getattr(event_data, "context", None)
340
- for name in ("open_message_id", "message_id"):
341
- value = str(getattr(context, name, None) or "").strip()
342
- if value:
343
- return value
344
- return None
345
-
346
-
347
- def _stop_lark_client(client, loop) -> None:
348
- if loop.is_closed():
349
- return
350
- disconnect = getattr(client, "_disconnect", None) if client is not None else None
351
- if loop.is_running():
352
- future = asyncio.run_coroutine_threadsafe(
353
- _disconnect_then_stop(disconnect, loop),
354
- loop,
355
- )
356
- try:
357
- future.result(timeout=2.0)
358
- except Exception as exc:
359
- future.cancel()
360
- print(exc)
361
- loop.call_soon_threadsafe(loop.stop)
362
- return
363
- if callable(disconnect):
364
- try:
365
- loop.run_until_complete(disconnect())
366
- except Exception as exc:
367
- print(exc)
368
-
369
-
370
- async def _disconnect_then_stop(disconnect, loop) -> None:
371
- try:
372
- if callable(disconnect):
373
- await disconnect()
374
- except Exception as exc:
375
- print(exc)
376
- finally:
377
- loop.stop()
378
-
379
-
380
- def _close_loop(loop) -> None:
381
- if loop.is_closed():
382
- return
383
- tasks = list(_all_loop_tasks(loop))
384
- for task in tasks:
385
- task.cancel()
386
- if tasks:
387
- loop.run_until_complete(asyncio.gather(*tasks, return_exceptions=True))
388
- shutdown_asyncgens = getattr(loop, "shutdown_asyncgens", None)
389
- if callable(shutdown_asyncgens):
390
- loop.run_until_complete(shutdown_asyncgens())
391
- loop.close()
392
-
393
-
394
- def _all_loop_tasks(loop):
395
- all_tasks = getattr(asyncio, "all_tasks", None)
396
- if callable(all_tasks):
397
- return all_tasks(loop)
398
- return asyncio.Task.all_tasks(loop)
399
-
400
-
401
- class _AsyncLoopThread:
402
- def __init__(self) -> None:
403
- self.loop = None
404
- self.thread = None
405
- self._started = threading.Event()
406
-
407
- def start(self) -> None:
408
- if self.loop is not None and self.loop.is_running():
409
- return
410
- self.loop = asyncio.new_event_loop()
411
- self._started.clear()
412
- self.thread = threading.Thread(
413
- target=self._run_loop,
414
- name="pycodex-feishu-asyncio",
415
- )
416
- self.thread.daemon = True
417
- self.thread.start()
418
- self._started.wait()
419
-
420
- def run(self, coro):
421
- if self.loop is None or not self.loop.is_running():
422
- raise RuntimeError("Feishu asyncio loop is not running")
423
- return asyncio.run_coroutine_threadsafe(coro, self.loop).result()
424
-
425
- def stop(self) -> None:
426
- loop = self.loop
427
- if loop is None:
428
- return
429
- if loop.is_running():
430
- loop.call_soon_threadsafe(loop.stop)
431
- if self.thread is not None:
432
- self.thread.join()
433
- loop.close()
434
- self.loop = None
435
- self.thread = None
436
-
437
- def _run_loop(self) -> None:
438
- asyncio.set_event_loop(self.loop)
439
- self._started.set()
440
- self.loop.run_forever()
@@ -1,142 +0,0 @@
1
- """Optional tool that executes code in the current IPython kernel."""
2
-
3
- from ..events import ToolCompletedEvent
4
- from ..utils.event_helpers import colorize_tool_message
5
- from .base_tool import BaseTool, ToolContext
6
-
7
-
8
- class IPythonTool(BaseTool):
9
- name = "ipython"
10
- description = (
11
- "Execute Python code in the current IPython kernel namespace. Use this "
12
- "only when running inside IPython and live notebook/session variables "
13
- "need to be inspected."
14
- )
15
- input_schema = {
16
- "type": "object",
17
- "properties": {
18
- "code": {
19
- "type": "string",
20
- "description": "Python code to execute in the current IPython session.",
21
- },
22
- },
23
- "required": ["code"],
24
- "additionalProperties": False,
25
- }
26
- supports_parallel = False
27
-
28
- def __init__(self, shell, name="ipython"):
29
- self._shell = shell
30
- self.name = name
31
-
32
- async def run(self, context: "ToolContext", args):
33
- del context
34
- if not isinstance(args, dict):
35
- return {"error": "arguments must be an object"}
36
-
37
- code = args.get("code", "")
38
- if not isinstance(code, str) or not code.strip():
39
- return {"error": "`code` must be a non-empty string"}
40
-
41
- from IPython.display import Code, display
42
- from IPython.utils.capture import capture_output
43
-
44
- display(Code(code, language="python"))
45
- with capture_output() as captured:
46
- result = self._shell.run_cell(code, store_history=False)
47
- captured.show()
48
-
49
- output = {
50
- "stdout": captured.stdout,
51
- "stderr": captured.stderr,
52
- }
53
-
54
- display_outputs = []
55
- for item in captured.outputs:
56
- data = getattr(item, "data", None)
57
- if isinstance(data, dict):
58
- display_outputs.append(
59
- data.get("text/plain") or data.get("text/html") or repr(data)
60
- )
61
- else:
62
- display_outputs.append(repr(item))
63
- if display_outputs:
64
- output["display"] = display_outputs
65
-
66
- if getattr(result, "result", None) is not None:
67
- output["result"] = repr(result.result)
68
-
69
- error = result.error_before_exec or result.error_in_exec
70
- if error is not None:
71
- output["error"] = f"{type(error).__name__}: {error}"
72
-
73
- return output
74
-
75
-
76
- def _install_agent_shortcut(shell):
77
- existing = shell.user_ns.get("_pycodex_agent_shortcut_transform")
78
- if existing in shell.input_transformers_cleanup:
79
- return existing
80
-
81
- def transform(lines):
82
- if len(lines) != 1:
83
- return lines
84
-
85
- line = lines[0]
86
- stripped = line.lstrip()
87
- indent = line[: len(line) - len(stripped)]
88
- if not stripped.startswith("@"):
89
- return lines
90
-
91
- body = stripped[1:].rstrip("\n")
92
- parts = body.split(None, 1)
93
- if not parts:
94
- return lines
95
-
96
- agent_name = parts[0]
97
- if not agent_name.isidentifier():
98
- return lines
99
-
100
- agent = shell.user_ns.get(agent_name)
101
- if agent is None or not callable(getattr(agent, "run_turn", None)):
102
- return lines
103
-
104
- prompt = "" if len(parts) == 1 else parts[1]
105
- if not prompt.strip():
106
- return [f"{indent}print('Usage: @{agent_name} <prompt>')\n"]
107
-
108
- return [f"{indent}print({agent_name}.ask({prompt!r}).output_text)\n"]
109
-
110
- shell.input_transformers_cleanup.append(transform)
111
- shell.user_ns["_pycodex_agent_shortcut_transform"] = transform
112
- return transform
113
-
114
-
115
- def attach_ipython_event_printer(agent, color=True):
116
- def handle_event(event):
117
- if isinstance(event, ToolCompletedEvent):
118
- tool_name = event.call.name
119
- message = event.visualize()
120
- for line in message.splitlines() or [""]:
121
- print(colorize_tool_message(line, color, tool_name), flush=True)
122
-
123
- agent.event_handler = handle_event
124
- return handle_event
125
-
126
-
127
- def attach_ipython_tool(
128
- agent, name="current_ipython", shortcut=True, print_tool_events=True, color=True
129
- ):
130
- from IPython import get_ipython
131
-
132
- shell = get_ipython()
133
- if shell is None:
134
- raise RuntimeError("not running inside IPython")
135
-
136
- tool = IPythonTool(shell, name=name)
137
- agent.tool_registry.register(tool)
138
- if shortcut:
139
- _install_agent_shortcut(shell)
140
- if print_tool_events:
141
- attach_ipython_event_printer(agent, color=color)
142
- return tool
@@ -1,98 +0,0 @@
1
- pycodex/__init__.py,sha256=4BBGUXImsNBdSQjp2KtshkjQK9BMz5gK93DzpWokkWY,3235
2
- pycodex/__main__.py,sha256=MHKZ_ae3fSLGTLUUMOx15fWdeOnJSHhq-zslRP5F5Lc,79
3
- pycodex/agent.py,sha256=zCIG2DV0oQntLXHFj8FVRkgBp5TCC0YJ7sz0lni9J1s,21177
4
- pycodex/bootstrap.py,sha256=DSVx8u94tHRYbUa_e9zdKPqozOv_CrfctbTKZ4JG064,13765
5
- pycodex/cli.py,sha256=m5IJhnodNqsfMTIzdwbuaHBl2r-N8x1MxYSpe_hlHiM,12997
6
- pycodex/compat.py,sha256=yoQQWMiAQ6ytZv3DAMIbp66ImA0kyY4G5eKHrtwmj6c,3490
7
- pycodex/context.py,sha256=nkq2Y0coZNpWs5IJj7uVVT65fDqh58Z9c07y_Wy0f4Q,26604
8
- pycodex/doctor.py,sha256=9p624b1zloXbhyMRi1-Of1YtnYeoF4zHxfGFhfujDS4,10620
9
- pycodex/events.py,sha256=MZljtqra6-Hnt9Emjbn_wgp5cGaODx1w3CbmIKd5htI,29692
10
- pycodex/feishu_card.py,sha256=Gclo4TI3KTfdT5NDLiv58CRg6hH3sUCRXuSrHgXgYjI,27767
11
- pycodex/feishu_link.py,sha256=yUbEvO-8g-Bxo8_cF9s6vLZguz3NA6q3qt2A9Q09fsE,14523
12
- pycodex/model.py,sha256=HeHeaYEC06idh_66mM4uzyc7IZc_AS789ajByvOqbr8,44571
13
- pycodex/model_metadata.py,sha256=RMYhvgkm2v1nhCslSiDXPAwrRAx8FPz9QJqv8QTbWlc,1332
14
- pycodex/portable.py,sha256=rfOpVnBZ01RS0Kyjo_w2FNKHY2t-lUcHVtWhPsbp1-k,16158
15
- pycodex/portable_server.py,sha256=A4IY3xHtBQLRxdHQ4O5zdaVGjqENaLvypsSkLGZvCZ0,7498
16
- pycodex/protocol.py,sha256=dRcTVKTaE7Eaq_jiSYdCzBMebIo3gnL7wB1x-NJqY5E,12027
17
- pycodex/runtime.py,sha256=bRlqrmXqK6kPndAG96QoGALKicbWmfuXgo2jDvbQzdE,23806
18
- pycodex/runtime_services.py,sha256=4jDCMlXHwgbJZPJkWzVEPCRHPxrD0mpCBbDInVToGG8,15033
19
- pycodex/prompts/default_base_instructions.md,sha256=D65mcj6bo4CDvVom-D9cbJRJVNquo0NghKt164_fRsg,20923
20
- pycodex/prompts/models.json,sha256=u-bS5xtI7ZHbrG_nbzrt-xmp5RtQT6YL8PHbd_4XZB4,397650
21
- pycodex/prompts/permissions/approval_policy/never.md,sha256=QceTG6wjkaJARjYr0HYV1aPnPcpGcrkRUW-smWRr6MQ,120
22
- pycodex/prompts/permissions/approval_policy/on_failure.md,sha256=dfJjpXkpO6_ANdCKxbVJ8o4vyLxevrJWfKsGHTqtbkc,289
23
- pycodex/prompts/permissions/approval_policy/on_request.md,sha256=hVQalzh0FAdkKzw5u-N4H7-LtC9ijVDlYsh3OKsZKzo,3661
24
- pycodex/prompts/permissions/approval_policy/on_request_rule_request_permission.md,sha256=mOinishp1k-wlPsaEuIOMn5GoVm_dAIsWIuEMmv2r7o,1725
25
- pycodex/prompts/permissions/approval_policy/unless_trusted.md,sha256=XHpi1Lfx1iIXFbbQ_ho_kGstA3JN-RLho291HM30UNw,247
26
- pycodex/prompts/permissions/sandbox_mode/danger_full_access.md,sha256=nZ7YHacBd3cAHKRZc9XClOOOnXJPXPh0WFBueh5C2D0,197
27
- pycodex/prompts/permissions/sandbox_mode/read_only.md,sha256=2rAPEXsBYCcuttI5j3euS-3uv_v97catIsnhxlSQSIM,173
28
- pycodex/prompts/permissions/sandbox_mode/workspace_write.md,sha256=lVN-LwrBbHqlv5yVjcd_mU8tzZW8jfKpTatJKIZu9HI,277
29
- pycodex/tools/__init__.py,sha256=UYwmsX_Ckw_YaYQ6TYhUU6w5pxi2qzZoTrq6BAgNErM,1857
30
- pycodex/tools/agent_tool_schemas.py,sha256=8cL9ml4So0H6IIeK0ZzjAo9bk3VeprDOSYPpIamOqEU,2048
31
- pycodex/tools/apply_patch_tool.py,sha256=t8XFCGZ7q-s9C1Ty6qkReBRk-QD3ONvcKXLAz9djKRY,13956
32
- pycodex/tools/base_tool.py,sha256=kNNzPWijtdl4C_GunyR5G1qvsr7KQtnFJ2RiRHHnAYo,6478
33
- pycodex/tools/clock_tool.py,sha256=2_RYbBEw4V9_f1L-qZl3hhJ6XNPM_gBDmOlCh1cCAjo,6575
34
- pycodex/tools/close_agent_tool.py,sha256=zQtvd5iGW6YCPFiec8zc2OdGtgNIxoA4p2ZTuCoJOaI,2031
35
- pycodex/tools/code_mode_manager.py,sha256=VFVn7S_qUHCOHW952CMeGxTIE-7CPOx2uuXJZgBml8o,19160
36
- pycodex/tools/exec_command_tool.py,sha256=iqRiKaaX-AjG6LjATAMOakHIP0gpCWCj2o8af_8eAiQ,4464
37
- pycodex/tools/exec_runtime.js,sha256=DR1uocKailTqNWAcJNFJuQgFFMSUzTpT_uQsRaneg2s,3643
38
- pycodex/tools/exec_tool.py,sha256=tuC21rlhP8CPSYml4XnSDSRV0UPGkQ6aHj0DLIoOOvM,2274
39
- pycodex/tools/grep_files_tool.py,sha256=Ysw68VKI9OEvUH5haYx8FWuthkHykc1wskbuzjj8gTk,5293
40
- pycodex/tools/ipython_tool.py,sha256=SKVYpJEwlYjOQZQWbpqvrA-3K9aJTlIG9KM50p5JYUM,4496
41
- pycodex/tools/list_dir_tool.py,sha256=_U6ouRcVbGHT5mChVyUsiMgDGrFK7EFMFaspPLAHtH8,5337
42
- pycodex/tools/read_file_tool.py,sha256=YK__uhIVldBjAQega5S_ZuZU5jgP_kLOwr-YhjAmRo4,9735
43
- pycodex/tools/request_permissions_tool.py,sha256=n8eg29SgRbx1DUxxLbAztnc5i-0j2N2WnDupspjwWbE,3979
44
- pycodex/tools/request_user_input_tool.py,sha256=_7siHF2p3KiNDFwsTqKKIUw2kPCXMzLaR12PkZ1wdIQ,4050
45
- pycodex/tools/resume_agent_tool.py,sha256=D_OcWQbIbsWf-2NrRgDab4hB6BUbay0XidfPInhg88Y,1614
46
- pycodex/tools/send_input_tool.py,sha256=J91LLz4RpvHmBWti0XZgI9xWipWwD8-1hQIdC8-Jd5E,3762
47
- pycodex/tools/shell_command_tool.py,sha256=US63I5xiV5zfO1Oox2yHUg7F6XoKzmyxtohfaQIsmrw,4216
48
- pycodex/tools/shell_tool.py,sha256=lqFH2XosfBg7yQKhpB7i4vLGz9sNQtEZihD0rjsmBCQ,4068
49
- pycodex/tools/spawn_agent_tool.py,sha256=n_WZi1IX4Waj-GQ-hR1BVlk3zzw_ssvem7zcj3tYI38,6209
50
- pycodex/tools/unified_exec_manager.py,sha256=sO1H3uoXyZ6DiyF98-eidQ77mS-P5gSWyPqM3L50yTQ,14538
51
- pycodex/tools/update_plan_tool.py,sha256=8zyANrQgj8u2LBJ2yz_0Cg5jP3S6ibp6eASxUupX9C8,3199
52
- pycodex/tools/view_image_tool.py,sha256=UZRkBEwuCkqxOw7XBwacdgPZAtbnD6uSHTdm-6amUo4,3902
53
- pycodex/tools/wait_agent_tool.py,sha256=2OWfb9FCGu5SjbRp33dVEJWG3apMtQgczvQR1V_rm6I,3829
54
- pycodex/tools/wait_tool.py,sha256=0_OO_DvMsBhG3oDKZePTOjZTBq1lmWntXAzqIqvebdA,3206
55
- pycodex/tools/web_search_tool.py,sha256=3ao1IvJw7MwcP35UKLbqrM-nlm5Z-UUFVdEzkJYOV1o,988
56
- pycodex/tools/write_stdin_tool.py,sha256=jvBDchLLmoDITd7g-ZVeEVXHRhWKkmnjM5laL-53FOM,3609
57
- pycodex/utils/__init__.py,sha256=lbf-jbo6JS7t1wfFkQqLHlG4zZVqXYGkOIj2cvtrjx8,591
58
- pycodex/utils/async_bridge.py,sha256=d21Pjim-nsQbSG5pJddd0WaQ03CzA3w3TINWDmmjWbg,1815
59
- pycodex/utils/compactor.py,sha256=0tlszw1n54aMEGH6sL1U1dEgFSU5ioYL2NI5uSvHSiM,6119
60
- pycodex/utils/debug.py,sha256=BdXmuAQVWVB1BONKRDlkMpgXpkt4M1jhvEAq5n2AumI,296
61
- pycodex/utils/dotenv.py,sha256=h7ZgvqpEswetqjhtwfiaHyokAHwNKPakizTAHPHz5Ds,1865
62
- pycodex/utils/event_helpers.py,sha256=pnxL0-nBC7cnOheHPCIfkHqJjMbkJg3C348_EzAVhFA,6342
63
- pycodex/utils/get_env.py,sha256=L4S8h84tkgxZKvrxY7ezTgePbXepG-yIigUTKeY6uuE,6094
64
- pycodex/utils/image_utils.py,sha256=1kXhtTqL4xtazpEABHhtvJBUJlceo8hSzg6ukmf_4FA,2407
65
- pycodex/utils/random_ids.py,sha256=jLTxZZ0MBbRdQOFDFWGVRjWzIo6FKSQ5ADXbQSLPp1s,379
66
- pycodex/utils/session_persist.py,sha256=v9KhmjUB2yCg55c85i8ZU1BWfc-WEMDPmpT0Rv4K8a8,22489
67
- pycodex/utils/truncation.py,sha256=5D6vAorT8EgXgjd7ASwtraAyIZdlCR-w5jKZqJxDzho,5446
68
- responses_server/__init__.py,sha256=sx9C88YWqmehASZy24FUMqT14A36doM_rj0MIZtQ9iQ,377
69
- responses_server/__main__.py,sha256=876xZTqhPeDBD2GKKr8pKX33Af8PhFTosAI8bYQsFgQ,61
70
- responses_server/app.py,sha256=9uhglqUaRXhotYDkGFemnETopgx9Moi2wHOE0pDCwtU,7755
71
- responses_server/config.py,sha256=sCJYGisPHW9Uup26-R9Zv0o9W_kRVt-ETc2MFCVjG90,2795
72
- responses_server/messages_api.py,sha256=ialAYTMmN0y-uxQB3Y51ukq-kvkSVO84WVLXaqLsKw0,18775
73
- responses_server/payload_processors.py,sha256=dqPwqHD-FhyiIwjzFEMf2wCtQDxkRyerZzbdqnH1aDE,3561
74
- responses_server/server.py,sha256=k4DbsOYkaHHcy38uF9u_QXahJC1cplKsTu-MdC3DCIs,2286
75
- responses_server/session_store.py,sha256=nwGxQL6nUVKnDVeDHz8IzqNQ7dWk8Ybf0URekOHdxTo,1133
76
- responses_server/stream_router.py,sha256=TQX2-8uOGad3TBJnRu9SOtDaHBHjYwE-WERYz6rcuo8,46274
77
- responses_server/trajectory_dump.py,sha256=5_Wy6tslszrqx3j1JeP_boyTbzIicKy8No84PzMnmHk,5111
78
- responses_server/tools/__init__.py,sha256=ivsBSEy0SBUhY-Uea5v1XMLXShkwHdCVl0id-1FwdZg,150
79
- responses_server/tools/custom_adapter.py,sha256=SnIiNUdomff3APtTriURAC9YCeEdhCDjzGMEYusfUdk,8340
80
- responses_server/tools/web_search.py,sha256=pnKH9JyTScRehWpZS3HpXRvjWsQvC0QZqxjEOCT4ndg,8936
81
- workspace_server/__init__.py,sha256=PRM4ONODb6hxjBUHkBD4TprE_pkTCIlT9sfftK5ic6M,866
82
- workspace_server/__main__.py,sha256=876xZTqhPeDBD2GKKr8pKX33Af8PhFTosAI8bYQsFgQ,61
83
- workspace_server/app.py,sha256=aoo5vq5AciEHe3r5gcgt2B349uuWLY6fbFYbOQ2CRAE,67164
84
- workspace_server/content_views.LICENSE.txt,sha256=PUOceZvrZI9c2LeLVh6wJNv5wwALKoJ8jOOfq-05WmQ,64183
85
- workspace_server/content_views.css,sha256=n1yPrOZbzNS0phv2JGwaYbK8t81MI2kKe9rc3sY2TRI,1662
86
- workspace_server/content_views.mjs,sha256=8sbYqAgwYrAE9SMd3bO6jv6DlHwWru1gboID8h2oTLE,16241
87
- workspace_server/editor.css,sha256=4qBe2ZLqloAFQ2YNyJYvsJelvTHIIQCxpfg4EVTubk8,346450
88
- workspace_server/editor.mjs,sha256=oZpBsmnA56VIogpbg_NDg8cs4bIQZkuUCtXPJnVLook,4110455
89
- workspace_server/owned_process.py,sha256=j1cJ89Nm7gS91Zj62kYKabFbb9qhbU7-q1YDsWcVcn8,895
90
- workspace_server/workspace.html,sha256=r1cBihjnyt8cxjI9xGqTVBs3zboMcoYHemgvwNMpN2A,74728
91
- workspace_server/workspace_views.py,sha256=acV-SS3Uw-Qy5AI_KV16AowB1R3cbJN4Okk6CDbpPzw,22172
92
- workspace_server/workspaces.html,sha256=72WEextEEUZeAYCmZ5UcWbg1m7voFezxgL6j48koRuU,15794
93
- workspace_server/workspaces.py,sha256=hMvGyZtuFshGV3l56AMhGJN0vDOvvVj8iv9-VAJJHhw,22524
94
- python_codex-0.3.3.dist-info/METADATA,sha256=ucgUraJ7rlCeUstF-FlAE8qiURNuqF-qOw6xKMbYF7M,42715
95
- python_codex-0.3.3.dist-info/WHEEL,sha256=KGYbc1zXlYddvwxnNty23BeaKzh7YuoSIvIMO4jEhvw,87
96
- python_codex-0.3.3.dist-info/entry_points.txt,sha256=vkV2UWCtEKvQNMJuPNjt8HyBKiwp83JyqBatrBNGDp8,80
97
- python_codex-0.3.3.dist-info/licenses/LICENSE,sha256=0X8ifk312hYAORM4hlzg8wVSEXYKNmiPgWlB1YIy2Nw,10926
98
- python_codex-0.3.3.dist-info/RECORD,,