devcopilot 0.2.0__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 (189) hide show
  1. api/__init__.py +17 -0
  2. api/admin_config.py +1303 -0
  3. api/admin_routes.py +287 -0
  4. api/admin_static/admin.css +459 -0
  5. api/admin_static/admin.js +497 -0
  6. api/admin_static/index.html +77 -0
  7. api/admin_urls.py +34 -0
  8. api/app.py +194 -0
  9. api/command_utils.py +164 -0
  10. api/dependencies.py +144 -0
  11. api/detection.py +152 -0
  12. api/gateway_model_ids.py +54 -0
  13. api/model_catalog.py +133 -0
  14. api/model_router.py +125 -0
  15. api/models/__init__.py +45 -0
  16. api/models/anthropic.py +234 -0
  17. api/models/openai_responses.py +28 -0
  18. api/models/responses.py +60 -0
  19. api/optimization_handlers.py +154 -0
  20. api/request_pipeline.py +424 -0
  21. api/routes.py +156 -0
  22. api/runtime.py +334 -0
  23. api/validation_log.py +48 -0
  24. api/web_server_tools.py +22 -0
  25. api/web_tools/__init__.py +17 -0
  26. api/web_tools/constants.py +15 -0
  27. api/web_tools/egress.py +99 -0
  28. api/web_tools/outbound.py +278 -0
  29. api/web_tools/parsers.py +104 -0
  30. api/web_tools/request.py +87 -0
  31. api/web_tools/streaming.py +206 -0
  32. cli/__init__.py +5 -0
  33. cli/claude_env.py +12 -0
  34. cli/entrypoints.py +166 -0
  35. cli/env.example +209 -0
  36. cli/launchers/__init__.py +1 -0
  37. cli/launchers/claude.py +84 -0
  38. cli/launchers/codex.py +204 -0
  39. cli/launchers/codex_model_catalog.py +186 -0
  40. cli/launchers/common.py +93 -0
  41. cli/managed/__init__.py +6 -0
  42. cli/managed/claude.py +215 -0
  43. cli/managed/manager.py +157 -0
  44. cli/managed/session.py +260 -0
  45. cli/process_registry.py +78 -0
  46. config/__init__.py +5 -0
  47. config/constants.py +13 -0
  48. config/logging_config.py +159 -0
  49. config/nim.py +118 -0
  50. config/paths.py +91 -0
  51. config/provider_catalog.py +259 -0
  52. config/provider_ids.py +7 -0
  53. config/settings.py +538 -0
  54. core/__init__.py +1 -0
  55. core/anthropic/__init__.py +46 -0
  56. core/anthropic/content.py +31 -0
  57. core/anthropic/conversion.py +587 -0
  58. core/anthropic/emitted_sse_tracker.py +346 -0
  59. core/anthropic/errors.py +70 -0
  60. core/anthropic/native_messages_request.py +280 -0
  61. core/anthropic/native_sse_block_policy.py +313 -0
  62. core/anthropic/provider_stream_error.py +34 -0
  63. core/anthropic/server_tool_sse.py +14 -0
  64. core/anthropic/sse.py +440 -0
  65. core/anthropic/stream_contracts.py +205 -0
  66. core/anthropic/stream_recovery.py +346 -0
  67. core/anthropic/stream_recovery_session.py +133 -0
  68. core/anthropic/thinking.py +140 -0
  69. core/anthropic/tokens.py +117 -0
  70. core/anthropic/tools.py +212 -0
  71. core/anthropic/utils.py +9 -0
  72. core/openai_responses/__init__.py +5 -0
  73. core/openai_responses/adapter.py +31 -0
  74. core/openai_responses/anthropic_sse.py +59 -0
  75. core/openai_responses/errors.py +22 -0
  76. core/openai_responses/events.py +19 -0
  77. core/openai_responses/ids.py +21 -0
  78. core/openai_responses/input.py +258 -0
  79. core/openai_responses/items.py +37 -0
  80. core/openai_responses/reasoning.py +52 -0
  81. core/openai_responses/stream.py +25 -0
  82. core/openai_responses/stream_state.py +654 -0
  83. core/openai_responses/tools.py +374 -0
  84. core/openai_responses/usage.py +37 -0
  85. core/rate_limit.py +60 -0
  86. core/trace.py +216 -0
  87. devcopilot-0.2.0.dist-info/METADATA +687 -0
  88. devcopilot-0.2.0.dist-info/RECORD +189 -0
  89. devcopilot-0.2.0.dist-info/WHEEL +4 -0
  90. devcopilot-0.2.0.dist-info/entry_points.txt +6 -0
  91. devcopilot-0.2.0.dist-info/licenses/LICENSE +21 -0
  92. messaging/__init__.py +26 -0
  93. messaging/cli_event_constants.py +67 -0
  94. messaging/command_context.py +66 -0
  95. messaging/command_dispatcher.py +37 -0
  96. messaging/commands.py +275 -0
  97. messaging/event_parser.py +181 -0
  98. messaging/limiter.py +300 -0
  99. messaging/models.py +36 -0
  100. messaging/node_event_pipeline.py +127 -0
  101. messaging/node_runner.py +342 -0
  102. messaging/platforms/__init__.py +15 -0
  103. messaging/platforms/base.py +228 -0
  104. messaging/platforms/discord.py +567 -0
  105. messaging/platforms/factory.py +103 -0
  106. messaging/platforms/outbox.py +144 -0
  107. messaging/platforms/telegram.py +688 -0
  108. messaging/platforms/voice_flow.py +295 -0
  109. messaging/rendering/__init__.py +3 -0
  110. messaging/rendering/discord_markdown.py +318 -0
  111. messaging/rendering/markdown_tables.py +49 -0
  112. messaging/rendering/profiles.py +55 -0
  113. messaging/rendering/telegram_markdown.py +327 -0
  114. messaging/safe_diagnostics.py +17 -0
  115. messaging/session.py +334 -0
  116. messaging/transcript.py +581 -0
  117. messaging/transcription.py +164 -0
  118. messaging/trees/__init__.py +15 -0
  119. messaging/trees/data.py +482 -0
  120. messaging/trees/manager.py +433 -0
  121. messaging/trees/processor.py +179 -0
  122. messaging/trees/repository.py +177 -0
  123. messaging/turn_intake.py +235 -0
  124. messaging/ui_updates.py +101 -0
  125. messaging/voice.py +76 -0
  126. messaging/workflow.py +200 -0
  127. providers/__init__.py +31 -0
  128. providers/base.py +152 -0
  129. providers/cerebras/__init__.py +7 -0
  130. providers/cerebras/client.py +31 -0
  131. providers/cerebras/request.py +55 -0
  132. providers/codestral/__init__.py +7 -0
  133. providers/codestral/client.py +34 -0
  134. providers/deepseek/__init__.py +11 -0
  135. providers/deepseek/client.py +51 -0
  136. providers/deepseek/request.py +475 -0
  137. providers/defaults.py +41 -0
  138. providers/error_mapping.py +309 -0
  139. providers/exceptions.py +113 -0
  140. providers/fireworks/__init__.py +5 -0
  141. providers/fireworks/client.py +45 -0
  142. providers/fireworks/request.py +48 -0
  143. providers/gemini/__init__.py +7 -0
  144. providers/gemini/client.py +49 -0
  145. providers/gemini/request.py +199 -0
  146. providers/groq/__init__.py +7 -0
  147. providers/groq/client.py +31 -0
  148. providers/groq/request.py +83 -0
  149. providers/kimi/__init__.py +10 -0
  150. providers/kimi/client.py +53 -0
  151. providers/kimi/request.py +42 -0
  152. providers/llamacpp/__init__.py +3 -0
  153. providers/llamacpp/client.py +16 -0
  154. providers/lmstudio/__init__.py +5 -0
  155. providers/lmstudio/client.py +16 -0
  156. providers/mistral/__init__.py +7 -0
  157. providers/mistral/client.py +31 -0
  158. providers/mistral/request.py +37 -0
  159. providers/model_listing.py +133 -0
  160. providers/nvidia_nim/__init__.py +7 -0
  161. providers/nvidia_nim/client.py +91 -0
  162. providers/nvidia_nim/request.py +430 -0
  163. providers/nvidia_nim/voice.py +95 -0
  164. providers/ollama/__init__.py +7 -0
  165. providers/ollama/client.py +39 -0
  166. providers/open_router/__init__.py +7 -0
  167. providers/open_router/client.py +124 -0
  168. providers/open_router/request.py +42 -0
  169. providers/opencode/__init__.py +11 -0
  170. providers/opencode/client.py +31 -0
  171. providers/opencode/request.py +35 -0
  172. providers/rate_limit.py +300 -0
  173. providers/registry.py +527 -0
  174. providers/transports/__init__.py +1 -0
  175. providers/transports/anthropic_messages/__init__.py +5 -0
  176. providers/transports/anthropic_messages/http.py +118 -0
  177. providers/transports/anthropic_messages/recovery.py +206 -0
  178. providers/transports/anthropic_messages/stream.py +295 -0
  179. providers/transports/anthropic_messages/transport.py +236 -0
  180. providers/transports/openai_chat/__init__.py +5 -0
  181. providers/transports/openai_chat/recovery.py +217 -0
  182. providers/transports/openai_chat/stream.py +384 -0
  183. providers/transports/openai_chat/tool_calls.py +293 -0
  184. providers/transports/openai_chat/transport.py +156 -0
  185. providers/wafer/__init__.py +10 -0
  186. providers/wafer/client.py +50 -0
  187. providers/zai/__init__.py +10 -0
  188. providers/zai/client.py +46 -0
  189. providers/zai/request.py +42 -0
@@ -0,0 +1,144 @@
1
+ """Shared queued delivery helper for messaging platforms."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+ from collections.abc import Awaitable, Callable
7
+ from typing import Any, cast
8
+
9
+ SendOperation = Callable[
10
+ [str, str, str | None, str | None, str | None],
11
+ Awaitable[str],
12
+ ]
13
+ EditOperation = Callable[[str, str, str, str | None], Awaitable[None]]
14
+ DeleteOperation = Callable[[str, str], Awaitable[None]]
15
+ DeleteManyOperation = Callable[[str, list[str]], Awaitable[None]]
16
+ LimiterGetter = Callable[[], Any | None]
17
+
18
+
19
+ class PlatformOutbox:
20
+ """Own queueing, deduplication, and fire-and-forget delivery policy."""
21
+
22
+ def __init__(
23
+ self,
24
+ *,
25
+ get_limiter: LimiterGetter,
26
+ send: SendOperation,
27
+ edit: EditOperation,
28
+ delete: DeleteOperation,
29
+ delete_many: DeleteManyOperation,
30
+ ) -> None:
31
+ self._get_limiter = get_limiter
32
+ self._send = send
33
+ self._edit = edit
34
+ self._delete = delete
35
+ self._delete_many = delete_many
36
+
37
+ async def queue_send_message(
38
+ self,
39
+ chat_id: str,
40
+ text: str,
41
+ reply_to: str | None = None,
42
+ parse_mode: str | None = None,
43
+ fire_and_forget: bool = True,
44
+ message_thread_id: str | None = None,
45
+ ) -> str | None:
46
+ """Queue or immediately send a platform message."""
47
+ limiter = self._get_limiter()
48
+ if limiter is None:
49
+ return await self._send(
50
+ chat_id,
51
+ text,
52
+ reply_to,
53
+ parse_mode,
54
+ message_thread_id,
55
+ )
56
+
57
+ async def _send() -> str:
58
+ return await self._send(
59
+ chat_id,
60
+ text,
61
+ reply_to,
62
+ parse_mode,
63
+ message_thread_id,
64
+ )
65
+
66
+ if fire_and_forget:
67
+ limiter.fire_and_forget(_send)
68
+ return None
69
+ return cast(str | None, await limiter.enqueue(_send))
70
+
71
+ async def queue_edit_message(
72
+ self,
73
+ chat_id: str,
74
+ message_id: str,
75
+ text: str,
76
+ parse_mode: str | None = None,
77
+ fire_and_forget: bool = True,
78
+ ) -> None:
79
+ """Queue or immediately edit a platform message."""
80
+ limiter = self._get_limiter()
81
+ if limiter is None:
82
+ await self._edit(chat_id, message_id, text, parse_mode)
83
+ return
84
+
85
+ async def _edit() -> None:
86
+ await self._edit(chat_id, message_id, text, parse_mode)
87
+
88
+ dedup_key = f"edit:{chat_id}:{message_id}"
89
+ if fire_and_forget:
90
+ limiter.fire_and_forget(_edit, dedup_key=dedup_key)
91
+ else:
92
+ await limiter.enqueue(_edit, dedup_key=dedup_key)
93
+
94
+ async def queue_delete_message(
95
+ self,
96
+ chat_id: str,
97
+ message_id: str,
98
+ fire_and_forget: bool = True,
99
+ ) -> None:
100
+ """Queue or immediately delete a platform message."""
101
+ limiter = self._get_limiter()
102
+ if limiter is None:
103
+ await self._delete(chat_id, message_id)
104
+ return
105
+
106
+ async def _delete() -> None:
107
+ await self._delete(chat_id, message_id)
108
+
109
+ dedup_key = f"del:{chat_id}:{message_id}"
110
+ if fire_and_forget:
111
+ limiter.fire_and_forget(_delete, dedup_key=dedup_key)
112
+ else:
113
+ await limiter.enqueue(_delete, dedup_key=dedup_key)
114
+
115
+ async def queue_delete_messages(
116
+ self,
117
+ chat_id: str,
118
+ message_ids: list[str],
119
+ fire_and_forget: bool = True,
120
+ ) -> None:
121
+ """Queue or immediately bulk-delete platform messages."""
122
+ if not message_ids:
123
+ return
124
+
125
+ limiter = self._get_limiter()
126
+ if limiter is None:
127
+ await self._delete_many(chat_id, message_ids)
128
+ return
129
+
130
+ async def _delete_many() -> None:
131
+ await self._delete_many(chat_id, message_ids)
132
+
133
+ dedup_key = f"del_bulk:{chat_id}:{hash(tuple(message_ids))}"
134
+ if fire_and_forget:
135
+ limiter.fire_and_forget(_delete_many, dedup_key=dedup_key)
136
+ else:
137
+ await limiter.enqueue(_delete_many, dedup_key=dedup_key)
138
+
139
+ def fire_and_forget(self, task: Awaitable[Any]) -> None:
140
+ """Execute a coroutine or future without awaiting it."""
141
+ if asyncio.iscoroutine(task):
142
+ _ = asyncio.create_task(task)
143
+ else:
144
+ _ = asyncio.ensure_future(task)