bazaar-compute-node 0.1.3__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 (62) hide show
  1. bazaar_compute_node/__init__.py +3 -0
  2. bazaar_compute_node/app/__init__.py +1 -0
  3. bazaar_compute_node/app/application.py +398 -0
  4. bazaar_compute_node/app/attachments.py +154 -0
  5. bazaar_compute_node/app/command.py +342 -0
  6. bazaar_compute_node/app/config.py +121 -0
  7. bazaar_compute_node/app/registry.py +120 -0
  8. bazaar_compute_node/app/transport.py +264 -0
  9. bazaar_compute_node/app/windows_pipe.py +463 -0
  10. bazaar_compute_node/app/wrapper.py +63 -0
  11. bazaar_compute_node/bcc.py +524 -0
  12. bazaar_compute_node/cli.py +382 -0
  13. bazaar_compute_node/contrib/__init__.py +1 -0
  14. bazaar_compute_node/contrib/codex_app_server/__init__.py +63 -0
  15. bazaar_compute_node/contrib/codex_app_server/approval.py +168 -0
  16. bazaar_compute_node/contrib/codex_app_server/client.py +408 -0
  17. bazaar_compute_node/contrib/codex_app_server/events.py +431 -0
  18. bazaar_compute_node/contrib/codex_app_server/plugin.py +15 -0
  19. bazaar_compute_node/contrib/codex_app_server/process.py +583 -0
  20. bazaar_compute_node/contrib/codex_app_server/protocol.py +103 -0
  21. bazaar_compute_node/contrib/codex_app_server/runtime.py +513 -0
  22. bazaar_compute_node/contrib/logging/__init__.py +5 -0
  23. bazaar_compute_node/contrib/logging/audit.py +61 -0
  24. bazaar_compute_node/contrib/logging/plugin.py +11 -0
  25. bazaar_compute_node/contrib/sqlite/__init__.py +14 -0
  26. bazaar_compute_node/contrib/sqlite/codec.py +768 -0
  27. bazaar_compute_node/contrib/sqlite/database.py +282 -0
  28. bazaar_compute_node/contrib/sqlite/migrations.py +646 -0
  29. bazaar_compute_node/contrib/sqlite/plugin.py +11 -0
  30. bazaar_compute_node/contrib/sqlite/repository.py +1059 -0
  31. bazaar_compute_node/contrib/wecom/__init__.py +1 -0
  32. bazaar_compute_node/contrib/wecom/channel.py +960 -0
  33. bazaar_compute_node/contrib/wecom/markdown.py +146 -0
  34. bazaar_compute_node/contrib/wecom/plugin.py +29 -0
  35. bazaar_compute_node/core/__init__.py +5 -0
  36. bazaar_compute_node/core/approval.py +51 -0
  37. bazaar_compute_node/core/audit.py +101 -0
  38. bazaar_compute_node/core/channel.py +121 -0
  39. bazaar_compute_node/core/client.py +30 -0
  40. bazaar_compute_node/core/command.py +85 -0
  41. bazaar_compute_node/core/concurrency.py +29 -0
  42. bazaar_compute_node/core/correlation.py +48 -0
  43. bazaar_compute_node/core/instruction.py +224 -0
  44. bazaar_compute_node/core/lifecycle.py +48 -0
  45. bazaar_compute_node/core/models/__init__.py +63 -0
  46. bazaar_compute_node/core/models/entities.py +514 -0
  47. bazaar_compute_node/core/models/states.py +369 -0
  48. bazaar_compute_node/core/observability.py +47 -0
  49. bazaar_compute_node/core/orchestration/__init__.py +5 -0
  50. bazaar_compute_node/core/orchestration/command.py +614 -0
  51. bazaar_compute_node/core/orchestration/services.py +135 -0
  52. bazaar_compute_node/core/orchestration/session.py +891 -0
  53. bazaar_compute_node/core/orchestration/turn.py +451 -0
  54. bazaar_compute_node/core/outcomes.py +51 -0
  55. bazaar_compute_node/core/paths.py +19 -0
  56. bazaar_compute_node/core/runtime.py +118 -0
  57. bazaar_compute_node/core/storage.py +167 -0
  58. bazaar_compute_node-0.1.3.dist-info/METADATA +178 -0
  59. bazaar_compute_node-0.1.3.dist-info/RECORD +62 -0
  60. bazaar_compute_node-0.1.3.dist-info/WHEEL +4 -0
  61. bazaar_compute_node-0.1.3.dist-info/entry_points.txt +15 -0
  62. bazaar_compute_node-0.1.3.dist-info/licenses/LICENSE +613 -0
@@ -0,0 +1,408 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import Mapping
4
+ from dataclasses import dataclass
5
+ from pathlib import Path
6
+
7
+ from ...core.client import ClientInfo
8
+ from .process import JsonlProcessSupervisor
9
+ from .protocol import (
10
+ CodexAppServerProtocolError,
11
+ JsonlMessage,
12
+ )
13
+
14
+
15
+ @dataclass(frozen=True, slots=True)
16
+ class CodexThreadInfo:
17
+ """Provider-local thread identity returned by App Server."""
18
+
19
+ thread_id: str
20
+ session_id: str | None = None
21
+ path: str | None = None
22
+
23
+
24
+ @dataclass(frozen=True, slots=True)
25
+ class CodexTurnInfo:
26
+ """Provider-local turn identity and terminal status."""
27
+
28
+ turn_id: str
29
+ status: str
30
+ error_message: str | None = None
31
+
32
+
33
+ @dataclass(frozen=True, slots=True)
34
+ class CodexErrorInfo:
35
+ """Provider-local error notification fields needed by the runtime adapter."""
36
+
37
+ thread_id: str
38
+ turn_id: str
39
+ will_retry: bool
40
+ message: str
41
+ error_type: str | None = None
42
+
43
+
44
+ def build_initialize_params(
45
+ client_info: ClientInfo,
46
+ ) -> dict[str, object]:
47
+ return {
48
+ "clientInfo": {
49
+ "name": client_info.name,
50
+ "version": client_info.version,
51
+ },
52
+ "capabilities": {"experimentalApi": True},
53
+ }
54
+
55
+
56
+ def build_thread_start_params(
57
+ developer_instructions: str,
58
+ *,
59
+ model: str | None = None,
60
+ approval_policy: str | None = None,
61
+ cwd: Path | None = None,
62
+ ephemeral: bool | None = None,
63
+ ) -> dict[str, object]:
64
+ """Build provider-local parameters for a Codex ``thread/start`` request."""
65
+
66
+ _validate_non_empty_string("developer_instructions", developer_instructions)
67
+ params: dict[str, object] = {
68
+ "developerInstructions": developer_instructions,
69
+ }
70
+ if model is not None:
71
+ _validate_non_empty_string("model", model)
72
+ params["model"] = model
73
+ if approval_policy is not None:
74
+ _validate_non_empty_string("approval_policy", approval_policy)
75
+ params["approvalPolicy"] = approval_policy
76
+ if cwd is not None:
77
+ params["cwd"] = _path_text(cwd, "cwd")
78
+ if ephemeral is not None:
79
+ if not isinstance(ephemeral, bool):
80
+ raise TypeError("ephemeral must be a bool or None")
81
+ params["ephemeral"] = ephemeral
82
+ return params
83
+
84
+
85
+ def build_thread_resume_params(
86
+ thread_id: str,
87
+ *,
88
+ model: str | None = None,
89
+ approval_policy: str | None = None,
90
+ cwd: Path | None = None,
91
+ ) -> dict[str, object]:
92
+ """Build provider-local parameters for a persisted thread resume."""
93
+
94
+ _validate_non_empty_string("thread_id", thread_id)
95
+ params: dict[str, object] = {
96
+ "threadId": thread_id,
97
+ "excludeTurns": True,
98
+ }
99
+ if model is not None:
100
+ _validate_non_empty_string("model", model)
101
+ params["model"] = model
102
+ if approval_policy is not None:
103
+ _validate_non_empty_string("approval_policy", approval_policy)
104
+ params["approvalPolicy"] = approval_policy
105
+ if cwd is not None:
106
+ params["cwd"] = _path_text(cwd, "cwd")
107
+ return params
108
+
109
+
110
+ def build_turn_start_params(
111
+ thread_id: str,
112
+ input_text: str,
113
+ *,
114
+ client_user_message_id: str | None = None,
115
+ model: str | None = None,
116
+ effort: str | None = None,
117
+ approval_policy: str | None = None,
118
+ cwd: Path | None = None,
119
+ sandbox_policy: Mapping[str, object] | None = None,
120
+ ) -> dict[str, object]:
121
+ """Build a text turn request with optional model and reasoning effort."""
122
+
123
+ _validate_non_empty_string("thread_id", thread_id)
124
+ _validate_non_empty_string("input_text", input_text)
125
+ params: dict[str, object] = {
126
+ "threadId": thread_id,
127
+ "input": [{"type": "text", "text": input_text}],
128
+ }
129
+ if client_user_message_id is not None:
130
+ _validate_non_empty_string("client_user_message_id", client_user_message_id)
131
+ params["clientUserMessageId"] = client_user_message_id
132
+ if model is not None:
133
+ _validate_non_empty_string("model", model)
134
+ params["model"] = model
135
+ if effort is not None:
136
+ _validate_non_empty_string("effort", effort)
137
+ params["effort"] = effort
138
+ if approval_policy is not None:
139
+ _validate_non_empty_string("approval_policy", approval_policy)
140
+ params["approvalPolicy"] = approval_policy
141
+ if cwd is not None:
142
+ params["cwd"] = _path_text(cwd, "cwd")
143
+ if sandbox_policy is not None:
144
+ if not sandbox_policy:
145
+ raise ValueError("sandbox_policy must not be empty")
146
+ params["sandboxPolicy"] = dict(sandbox_policy)
147
+ return params
148
+
149
+
150
+ def build_turn_interrupt_params(thread_id: str, turn_id: str) -> dict[str, object]:
151
+ _validate_non_empty_string("thread_id", thread_id)
152
+ _validate_non_empty_string("turn_id", turn_id)
153
+ return {"threadId": thread_id, "turnId": turn_id}
154
+
155
+
156
+ class CodexAppServerClient:
157
+ """Typed facade over the adapter-local Codex JSONL supervisor."""
158
+
159
+ def __init__(self, supervisor: JsonlProcessSupervisor) -> None:
160
+ self.supervisor = supervisor
161
+
162
+ async def initialize(
163
+ self,
164
+ *,
165
+ client_info: ClientInfo,
166
+ timeout: float,
167
+ ) -> JsonlMessage:
168
+ response = await self.supervisor.request(
169
+ "initialize",
170
+ build_initialize_params(client_info),
171
+ timeout=timeout,
172
+ )
173
+ await self.supervisor.notify("initialized", timeout=timeout)
174
+ return response
175
+
176
+ async def start_thread(
177
+ self,
178
+ developer_instructions: str,
179
+ *,
180
+ model: str | None = None,
181
+ approval_policy: str | None = None,
182
+ cwd: Path | None = None,
183
+ ephemeral: bool | None = None,
184
+ timeout: float,
185
+ ) -> JsonlMessage:
186
+ return await self.supervisor.request(
187
+ "thread/start",
188
+ build_thread_start_params(
189
+ developer_instructions,
190
+ model=model,
191
+ approval_policy=approval_policy,
192
+ cwd=cwd,
193
+ ephemeral=ephemeral,
194
+ ),
195
+ timeout=timeout,
196
+ )
197
+
198
+ async def resume_thread(
199
+ self,
200
+ thread_id: str,
201
+ *,
202
+ model: str | None = None,
203
+ approval_policy: str | None = None,
204
+ cwd: Path | None = None,
205
+ timeout: float,
206
+ ) -> JsonlMessage:
207
+ return await self.supervisor.request(
208
+ "thread/resume",
209
+ build_thread_resume_params(
210
+ thread_id,
211
+ model=model,
212
+ approval_policy=approval_policy,
213
+ cwd=cwd,
214
+ ),
215
+ timeout=timeout,
216
+ )
217
+
218
+ async def read_thread(
219
+ self,
220
+ thread_id: str,
221
+ *,
222
+ include_turns: bool = True,
223
+ timeout: float,
224
+ ) -> JsonlMessage:
225
+ _validate_non_empty_string("thread_id", thread_id)
226
+ return await self.supervisor.request(
227
+ "thread/read",
228
+ {"threadId": thread_id, "includeTurns": include_turns},
229
+ timeout=timeout,
230
+ )
231
+
232
+ async def start_turn(
233
+ self,
234
+ thread_id: str,
235
+ input_text: str,
236
+ *,
237
+ client_user_message_id: str | None = None,
238
+ model: str | None = None,
239
+ effort: str | None = None,
240
+ approval_policy: str | None = None,
241
+ cwd: Path | None = None,
242
+ sandbox_policy: Mapping[str, object] | None = None,
243
+ timeout: float,
244
+ ) -> JsonlMessage:
245
+ return await self.supervisor.request(
246
+ "turn/start",
247
+ build_turn_start_params(
248
+ thread_id,
249
+ input_text,
250
+ client_user_message_id=client_user_message_id,
251
+ model=model,
252
+ effort=effort,
253
+ approval_policy=approval_policy,
254
+ cwd=cwd,
255
+ sandbox_policy=sandbox_policy,
256
+ ),
257
+ timeout=timeout,
258
+ )
259
+
260
+ async def interrupt_turn(
261
+ self,
262
+ thread_id: str,
263
+ turn_id: str,
264
+ *,
265
+ timeout: float,
266
+ ) -> JsonlMessage:
267
+ return await self.supervisor.request(
268
+ "turn/interrupt",
269
+ build_turn_interrupt_params(thread_id, turn_id),
270
+ timeout=timeout,
271
+ )
272
+
273
+ async def receive(self, *, timeout: float | None = None) -> JsonlMessage:
274
+ return await self.supervisor.receive(timeout=timeout)
275
+
276
+
277
+ def parse_thread_response(response: Mapping[str, object]) -> CodexThreadInfo:
278
+ result = _require_mapping(response, "result")
279
+ thread = _require_mapping(result, "thread")
280
+ thread_id = _require_text(thread, "id", "thread.id")
281
+ return CodexThreadInfo(
282
+ thread_id=thread_id,
283
+ session_id=_optional_text(thread.get("sessionId"), "thread.sessionId"),
284
+ path=_optional_text(thread.get("path"), "thread.path"),
285
+ )
286
+
287
+
288
+ def parse_turn_response(response: Mapping[str, object]) -> CodexTurnInfo:
289
+ result = _require_mapping(response, "result")
290
+ return _parse_turn(_require_mapping(result, "turn"))
291
+
292
+
293
+ def parse_turn_notification(message: Mapping[str, object]) -> tuple[str, CodexTurnInfo]:
294
+ params = _require_mapping(message, "params")
295
+ thread_id = _require_text(params, "threadId", "params.threadId")
296
+ turn = _parse_turn(_require_mapping(params, "turn"))
297
+ return thread_id, turn
298
+
299
+
300
+ def parse_error_notification(message: Mapping[str, object]) -> CodexErrorInfo:
301
+ params = _require_mapping(message, "params")
302
+ thread_id = _require_text(params, "threadId", "params.threadId")
303
+ turn_id = _require_text(params, "turnId", "params.turnId")
304
+ will_retry = params.get("willRetry")
305
+ if not isinstance(will_retry, bool):
306
+ raise CodexAppServerProtocolError("params.willRetry must be a bool")
307
+ error = _require_mapping(params, "error")
308
+ message_text = _require_text(error, "message", "params.error.message")
309
+ error_type = _error_type(error.get("codexErrorInfo"))
310
+ return CodexErrorInfo(
311
+ thread_id=thread_id,
312
+ turn_id=turn_id,
313
+ will_retry=will_retry,
314
+ message=message_text,
315
+ error_type=error_type,
316
+ )
317
+
318
+
319
+ def _parse_turn(value: Mapping[str, object]) -> CodexTurnInfo:
320
+ turn_id = _require_text(value, "id", "turn.id")
321
+ status = _require_text(value, "status", "turn.status")
322
+ error_value = value.get("error")
323
+ error_message = None
324
+ if error_value is not None:
325
+ if not isinstance(error_value, Mapping):
326
+ raise CodexAppServerProtocolError("turn.error must be an object")
327
+ error_message = _require_text(
328
+ error_value,
329
+ "message",
330
+ "turn.error.message",
331
+ )
332
+ return CodexTurnInfo(
333
+ turn_id=turn_id,
334
+ status=status,
335
+ error_message=error_message,
336
+ )
337
+
338
+
339
+ def _error_type(value: object) -> str | None:
340
+ if value is None:
341
+ return None
342
+ if isinstance(value, str) and value:
343
+ return value
344
+ if isinstance(value, Mapping):
345
+ if len(value) != 1:
346
+ raise CodexAppServerProtocolError(
347
+ "params.error.codexErrorInfo must contain one error type"
348
+ )
349
+ key = next(iter(value))
350
+ if not isinstance(key, str) or not key:
351
+ raise CodexAppServerProtocolError(
352
+ "params.error.codexErrorInfo has an invalid error type"
353
+ )
354
+ return key
355
+ raise CodexAppServerProtocolError(
356
+ "params.error.codexErrorInfo must be text, an object, or null"
357
+ )
358
+
359
+
360
+ def _require_mapping(value: Mapping[str, object], key: str) -> Mapping[str, object]:
361
+ nested = value.get(key)
362
+ if not isinstance(nested, Mapping):
363
+ raise CodexAppServerProtocolError(f"{key} must be an object")
364
+ return nested
365
+
366
+
367
+ def _require_text(value: Mapping[str, object], key: str, field_name: str) -> str:
368
+ nested = value.get(key)
369
+ if not isinstance(nested, str) or not nested:
370
+ raise CodexAppServerProtocolError(f"{field_name} must be non-empty text")
371
+ return nested
372
+
373
+
374
+ def _optional_text(value: object, field_name: str) -> str | None:
375
+ if value is None:
376
+ return None
377
+ if not isinstance(value, str) or not value:
378
+ raise CodexAppServerProtocolError(f"{field_name} must be non-empty text")
379
+ return value
380
+
381
+
382
+ def _path_text(value: Path, field_name: str) -> str:
383
+ if not isinstance(value, Path):
384
+ raise TypeError(f"{field_name} must be a Path")
385
+ return str(value)
386
+
387
+
388
+ def _validate_non_empty_string(name: str, value: str) -> None:
389
+ if not isinstance(value, str) or not value:
390
+ raise ValueError(f"{name} must be a non-empty string")
391
+
392
+
393
+ __all__ = [
394
+ "CodexAppServerClient",
395
+ "CodexAppServerProtocolError",
396
+ "CodexErrorInfo",
397
+ "CodexThreadInfo",
398
+ "CodexTurnInfo",
399
+ "build_initialize_params",
400
+ "build_thread_resume_params",
401
+ "build_thread_start_params",
402
+ "build_turn_interrupt_params",
403
+ "build_turn_start_params",
404
+ "parse_error_notification",
405
+ "parse_thread_response",
406
+ "parse_turn_notification",
407
+ "parse_turn_response",
408
+ ]