forge-ai-runtime 0.7.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 (116) hide show
  1. forge_ai_runtime-0.7.0/LICENSE +0 -0
  2. forge_ai_runtime-0.7.0/MANIFEST.in +13 -0
  3. forge_ai_runtime-0.7.0/PKG-INFO +351 -0
  4. forge_ai_runtime-0.7.0/README.md +332 -0
  5. forge_ai_runtime-0.7.0/ai_runtime/__init__.py +100 -0
  6. forge_ai_runtime-0.7.0/ai_runtime/adapters/__init__.py +0 -0
  7. forge_ai_runtime-0.7.0/ai_runtime/adapters/litellm/__init__.py +0 -0
  8. forge_ai_runtime-0.7.0/ai_runtime/adapters/litellm/response_adapter.py +58 -0
  9. forge_ai_runtime-0.7.0/ai_runtime/agents/__init__.py +12 -0
  10. forge_ai_runtime-0.7.0/ai_runtime/agents/agent.py +62 -0
  11. forge_ai_runtime-0.7.0/ai_runtime/agents/config_files.py +39 -0
  12. forge_ai_runtime-0.7.0/ai_runtime/agents/runner.py +177 -0
  13. forge_ai_runtime-0.7.0/ai_runtime/agents/subagent.py +31 -0
  14. forge_ai_runtime-0.7.0/ai_runtime/cli.py +81 -0
  15. forge_ai_runtime-0.7.0/ai_runtime/commands/__init__.py +5 -0
  16. forge_ai_runtime-0.7.0/ai_runtime/commands/registry.py +62 -0
  17. forge_ai_runtime-0.7.0/ai_runtime/compat.py +32 -0
  18. forge_ai_runtime-0.7.0/ai_runtime/context/__init__.py +15 -0
  19. forge_ai_runtime-0.7.0/ai_runtime/context/window.py +110 -0
  20. forge_ai_runtime-0.7.0/ai_runtime/conversation/__init__.py +5 -0
  21. forge_ai_runtime-0.7.0/ai_runtime/conversation/conversation.py +33 -0
  22. forge_ai_runtime-0.7.0/ai_runtime/conversation/enums.py +8 -0
  23. forge_ai_runtime-0.7.0/ai_runtime/conversation/message.py +75 -0
  24. forge_ai_runtime-0.7.0/ai_runtime/conversation/request.py +38 -0
  25. forge_ai_runtime-0.7.0/ai_runtime/conversation/response.py +32 -0
  26. forge_ai_runtime-0.7.0/ai_runtime/conversation/usage.py +9 -0
  27. forge_ai_runtime-0.7.0/ai_runtime/eventing/__init__.py +1 -0
  28. forge_ai_runtime-0.7.0/ai_runtime/eventing/bus.py +34 -0
  29. forge_ai_runtime-0.7.0/ai_runtime/execution/__init__.py +8 -0
  30. forge_ai_runtime-0.7.0/ai_runtime/execution/background.py +90 -0
  31. forge_ai_runtime-0.7.0/ai_runtime/execution/context.py +92 -0
  32. forge_ai_runtime-0.7.0/ai_runtime/execution/engine.py +195 -0
  33. forge_ai_runtime-0.7.0/ai_runtime/execution/event_processor.py +88 -0
  34. forge_ai_runtime-0.7.0/ai_runtime/execution/hooks.py +79 -0
  35. forge_ai_runtime-0.7.0/ai_runtime/execution/mode.py +8 -0
  36. forge_ai_runtime-0.7.0/ai_runtime/execution/pipeline/__init__.py +13 -0
  37. forge_ai_runtime-0.7.0/ai_runtime/execution/pipeline/compaction_stage.py +60 -0
  38. forge_ai_runtime-0.7.0/ai_runtime/execution/pipeline/llm_stage.py +51 -0
  39. forge_ai_runtime-0.7.0/ai_runtime/execution/pipeline/memory_consolidation_stage.py +76 -0
  40. forge_ai_runtime-0.7.0/ai_runtime/execution/pipeline/pipeline.py +39 -0
  41. forge_ai_runtime-0.7.0/ai_runtime/execution/pipeline/planner_stage.py +132 -0
  42. forge_ai_runtime-0.7.0/ai_runtime/execution/pipeline/request_builder_stage.py +28 -0
  43. forge_ai_runtime-0.7.0/ai_runtime/execution/pipeline/stage.py +20 -0
  44. forge_ai_runtime-0.7.0/ai_runtime/execution/pipeline/supervisor_stage.py +89 -0
  45. forge_ai_runtime-0.7.0/ai_runtime/execution/pipeline/tool_loop_stage.py +242 -0
  46. forge_ai_runtime-0.7.0/ai_runtime/execution/plan.py +39 -0
  47. forge_ai_runtime-0.7.0/ai_runtime/mcp/__init__.py +13 -0
  48. forge_ai_runtime-0.7.0/ai_runtime/mcp/adapter.py +48 -0
  49. forge_ai_runtime-0.7.0/ai_runtime/mcp/client.py +110 -0
  50. forge_ai_runtime-0.7.0/ai_runtime/memory/__init__.py +12 -0
  51. forge_ai_runtime-0.7.0/ai_runtime/memory/conversation_memory.py +42 -0
  52. forge_ai_runtime-0.7.0/ai_runtime/memory/semantic.py +55 -0
  53. forge_ai_runtime-0.7.0/ai_runtime/memory/store.py +48 -0
  54. forge_ai_runtime-0.7.0/ai_runtime/providers/__init__.py +17 -0
  55. forge_ai_runtime-0.7.0/ai_runtime/providers/base.py +89 -0
  56. forge_ai_runtime-0.7.0/ai_runtime/providers/capabilities.py +22 -0
  57. forge_ai_runtime-0.7.0/ai_runtime/providers/config.py +68 -0
  58. forge_ai_runtime-0.7.0/ai_runtime/providers/default_registry.py +41 -0
  59. forge_ai_runtime-0.7.0/ai_runtime/providers/enums.py +9 -0
  60. forge_ai_runtime-0.7.0/ai_runtime/providers/exceptions.py +54 -0
  61. forge_ai_runtime-0.7.0/ai_runtime/providers/litellm_exception_mapper.py +49 -0
  62. forge_ai_runtime-0.7.0/ai_runtime/providers/litellm_mapper.py +104 -0
  63. forge_ai_runtime-0.7.0/ai_runtime/providers/litellm_provider.py +158 -0
  64. forge_ai_runtime-0.7.0/ai_runtime/providers/litellm_stream_parser.py +100 -0
  65. forge_ai_runtime-0.7.0/ai_runtime/providers/provider.py +35 -0
  66. forge_ai_runtime-0.7.0/ai_runtime/providers/provider_info.py +18 -0
  67. forge_ai_runtime-0.7.0/ai_runtime/providers/registry.py +78 -0
  68. forge_ai_runtime-0.7.0/ai_runtime/providers/sdk_info.py +7 -0
  69. forge_ai_runtime-0.7.0/ai_runtime/rag/__init__.py +12 -0
  70. forge_ai_runtime-0.7.0/ai_runtime/rag/document.py +13 -0
  71. forge_ai_runtime-0.7.0/ai_runtime/rag/retriever.py +41 -0
  72. forge_ai_runtime-0.7.0/ai_runtime/rag/vector_store.py +90 -0
  73. forge_ai_runtime-0.7.0/ai_runtime/runtime.py +81 -0
  74. forge_ai_runtime-0.7.0/ai_runtime/server/__init__.py +13 -0
  75. forge_ai_runtime-0.7.0/ai_runtime/server/agent_server.py +111 -0
  76. forge_ai_runtime-0.7.0/ai_runtime/server/protocol.py +54 -0
  77. forge_ai_runtime-0.7.0/ai_runtime/session/__init__.py +1 -0
  78. forge_ai_runtime-0.7.0/ai_runtime/session/session.py +31 -0
  79. forge_ai_runtime-0.7.0/ai_runtime/skills/__init__.py +10 -0
  80. forge_ai_runtime-0.7.0/ai_runtime/skills/registry.py +48 -0
  81. forge_ai_runtime-0.7.0/ai_runtime/skills/skill.py +26 -0
  82. forge_ai_runtime-0.7.0/ai_runtime/streaming/__init__.py +25 -0
  83. forge_ai_runtime-0.7.0/ai_runtime/streaming/completed.py +19 -0
  84. forge_ai_runtime-0.7.0/ai_runtime/streaming/enums.py +13 -0
  85. forge_ai_runtime-0.7.0/ai_runtime/streaming/error.py +16 -0
  86. forge_ai_runtime-0.7.0/ai_runtime/streaming/event.py +18 -0
  87. forge_ai_runtime-0.7.0/ai_runtime/streaming/factory.py +42 -0
  88. forge_ai_runtime-0.7.0/ai_runtime/streaming/finish_reason.py +9 -0
  89. forge_ai_runtime-0.7.0/ai_runtime/streaming/permission.py +23 -0
  90. forge_ai_runtime-0.7.0/ai_runtime/streaming/text.py +18 -0
  91. forge_ai_runtime-0.7.0/ai_runtime/streaming/thinking.py +18 -0
  92. forge_ai_runtime-0.7.0/ai_runtime/streaming/tool_call.py +21 -0
  93. forge_ai_runtime-0.7.0/ai_runtime/streaming/tool_result.py +29 -0
  94. forge_ai_runtime-0.7.0/ai_runtime/streaming/usage.py +19 -0
  95. forge_ai_runtime-0.7.0/ai_runtime/tools/__init__.py +26 -0
  96. forge_ai_runtime-0.7.0/ai_runtime/tools/adapters/function_adapter.py +26 -0
  97. forge_ai_runtime-0.7.0/ai_runtime/tools/builtin/__init__.py +31 -0
  98. forge_ai_runtime-0.7.0/ai_runtime/tools/builtin/file_tools.py +135 -0
  99. forge_ai_runtime-0.7.0/ai_runtime/tools/builtin/shell_tool.py +45 -0
  100. forge_ai_runtime-0.7.0/ai_runtime/tools/checkpoints.py +50 -0
  101. forge_ai_runtime-0.7.0/ai_runtime/tools/executor.py +47 -0
  102. forge_ai_runtime-0.7.0/ai_runtime/tools/guarded_executor.py +63 -0
  103. forge_ai_runtime-0.7.0/ai_runtime/tools/permissions.py +77 -0
  104. forge_ai_runtime-0.7.0/ai_runtime/tools/registry.py +23 -0
  105. forge_ai_runtime-0.7.0/ai_runtime/tools/tool.py +27 -0
  106. forge_ai_runtime-0.7.0/ai_runtime/version.py +1 -0
  107. forge_ai_runtime-0.7.0/ai_runtime/workspace/__init__.py +5 -0
  108. forge_ai_runtime-0.7.0/ai_runtime/workspace/project.py +51 -0
  109. forge_ai_runtime-0.7.0/forge_ai_runtime.egg-info/PKG-INFO +351 -0
  110. forge_ai_runtime-0.7.0/forge_ai_runtime.egg-info/SOURCES.txt +114 -0
  111. forge_ai_runtime-0.7.0/forge_ai_runtime.egg-info/dependency_links.txt +1 -0
  112. forge_ai_runtime-0.7.0/forge_ai_runtime.egg-info/entry_points.txt +2 -0
  113. forge_ai_runtime-0.7.0/forge_ai_runtime.egg-info/requires.txt +9 -0
  114. forge_ai_runtime-0.7.0/forge_ai_runtime.egg-info/top_level.txt +1 -0
  115. forge_ai_runtime-0.7.0/pyproject.toml +35 -0
  116. forge_ai_runtime-0.7.0/setup.cfg +4 -0
File without changes
@@ -0,0 +1,13 @@
1
+ # Only ship the ai_runtime library. Explicitly exclude the web app and
2
+ # other non-library directories so `pip install forge-ai-runtime` never bundles them.
3
+ recursive-exclude web *
4
+ recursive-exclude tests *
5
+ recursive-exclude docs *
6
+ recursive-exclude venv *
7
+ recursive-exclude .ai-runtime *
8
+ recursive-exclude .vscode *
9
+ recursive-exclude copilot-agentic-research.md
10
+ recursive-exclude CHANGELOG.md
11
+ recursive-exclude PUBLISHING.md
12
+ global-exclude *.pyc
13
+ global-exclude __pycache__
@@ -0,0 +1,351 @@
1
+ Metadata-Version: 2.4
2
+ Name: forge-ai-runtime
3
+ Version: 0.7.0
4
+ Summary: Provider-agnostic AI Runtime SDK
5
+ Author: Kirit Vaghela
6
+ License: MIT
7
+ Requires-Python: >=3.12
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+ Requires-Dist: litellm>=1.75
11
+ Requires-Dist: pydantic>=2.8.0
12
+ Requires-Dist: httpx>=0.28
13
+ Provides-Extra: dev
14
+ Requires-Dist: pytest>=8; extra == "dev"
15
+ Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
16
+ Requires-Dist: ruff>=0.5; extra == "dev"
17
+ Requires-Dist: mypy>=1.10; extra == "dev"
18
+ Dynamic: license-file
19
+
20
+ # AI Runtime
21
+
22
+ AI Runtime is a provider-agnostic Python runtime for building AI
23
+ applications and agent workflows.
24
+
25
+ ## Features
26
+
27
+ - Provider abstraction with a unified LLM contract
28
+ - Built-in default provider registry and plugin discovery
29
+ - Custom provider registration with test doubles
30
+ - Conversation management and session-based execution
31
+ - Streaming responses with event processing
32
+ - Streaming timeout/cancellation boundary handling
33
+ - Automatic tool-calling loop (model requests tools → runtime executes → re-invokes)
34
+ - Capability-gated request mapping (tools, structured output, vision, metadata)
35
+ - Expanded provider contract: chat, stream, embeddings, image, transcription
36
+ - Retries via `ProviderConfig.max_retries` (forwarded to the backend)
37
+ - Uniform events: `chat()` and `stream()` both emit `StreamEvent`s
38
+ - Rich streaming events: text, usage, tool call, tool result, thinking, permission
39
+ - Execution engine and pipeline stages
40
+ - Provider metadata, capabilities, and request mapping
41
+ - Fully tested runtime and provider integration coverage
42
+
43
+ ### Agentic capabilities (v0.6.0)
44
+
45
+ `ai_runtime` now closes the gap with agentic coding tools (Claude Code,
46
+ OpenAI Codex, Cursor):
47
+
48
+ - **Plan mode** — `AgentRunner.plan()` / `ExecutionEngine.plan()` produce a
49
+ reviewable `Plan` (read-only, no tools run) before execution.
50
+ - **Sub-agents** — declare `SubAgentSpec`s on an `Agent`; the `SupervisorStage`
51
+ fans them out in parallel with isolated contexts and aggregates results.
52
+ - **Permissions** — `PermissionPolicy` + `GuardedToolExecutor` enforce
53
+ allow/deny/ask rules (glob-matched) over tool calls, mirroring tiered
54
+ permission modes.
55
+ - **Hooks** — `HookRegistry` with `PreToolUse` / `PostToolUse` / `PreLLM` /
56
+ `PostLLM` / `OnPlan` / `OnCompact` / `OnError` lifecycle hooks.
57
+ - **Auto compaction** — `CompactionStage` summarizes or drops old turns when
58
+ the context window exceeds its token budget.
59
+ - **Memory consolidation** — `MemoryConsolidationStage` writes durable
60
+ learnings (`LEARNING: ...`) back to the agent's `MemoryStore`.
61
+ - **MCP client** — `MCPClient` + `StdioTransport` speak JSON-RPC over stdio;
62
+ `register_mcp_tools()` wraps server tools as runtime `Tool`s.
63
+ - **Background tasks** — `BackgroundTaskRegistry` for resumable async tasks
64
+ (à la `codex resume` / Claude `/tasks`).
65
+ - **Skill scoping** — `Skill` gains `paths` / `globs` / `disable_model_invocation`.
66
+ - **Reasoning controls** — `ProviderConfig.reasoning_effort` / `thinking_enabled`
67
+ / `thinking_budget_tokens`, forwarded when the provider supports reasoning.
68
+
69
+ ### Integration surfaces (v0.7.0)
70
+
71
+ To embed `ai_runtime` in a **web app, desktop app, VS Code, or CLI** like
72
+ Claude Code / Codex / Cursor / Copilot, the framework now ships:
73
+
74
+ - **Built-in tools** — `ReadFileTool`, `WriteFileTool`, `EditFileTool`,
75
+ `GlobTool`, `GrepTool`, `BashTool` (scoped to a sandbox root via
76
+ `register_builtin_tools`). These mirror the file/shell/grep primitives of
77
+ the four tools.
78
+ - **Checkpoints / undo** — `CheckpointManager` snapshots files before edits
79
+ so the UI can roll back (à la Cursor/Claude/Copilot checkpoints).
80
+ - **Agent config files** — `load_project_instructions()` discovers
81
+ `.github/copilot-instructions.md`, `AGENTS.md`, `CLAUDE.md`,
82
+ `.cursor/rules` from the project root and folds them into the system prompt.
83
+ - **Transport-agnostic server** — `AgentServer` exposes an `Agent` over a
84
+ JSON-line protocol (`AgentRequest` / `AgentResponse` / `StreamEvent`) via
85
+ `serve_stdio()` (VS Code / CLI) and `serve_http()` (web / desktop).
86
+ - **CLI** — `ai-runtime` console script: `ai-runtime "prompt" --model ...`,
87
+ `--mode plan|stream`, `--serve` (stdio), `--http` (HTTP server), `--yolo`.
88
+ - **Workspace / project** — `Project` scopes memory, tools, permissions, and
89
+ checkpoints to a project root (the unit you mount in a client).
90
+ - **Slash commands** — `CommandRegistry` / `default_commands()`
91
+ (`/compact`, `/context`, `/clear`) mirroring Copilot's `/` menu.
92
+ - **BYO provider** — `ProviderConfig.from_env()` reads `COPILOT_PROVIDER_*`
93
+ vars to point at Ollama / vLLM / any OpenAI-compatible endpoint.
94
+
95
+ ### Web application (`web/`)
96
+
97
+ A ready-to-run web UI + REST/WebSocket API that exercises the full framework:
98
+
99
+ ```bash
100
+ export AI_RUNTIME_API_KEY=sk-... # or AI_RUNTIME_PROVIDER/AI_RUNTIME_BASE_URL
101
+ ./venv/bin/python web/run.py # serves http://127.0.0.1:8787
102
+ ```
103
+
104
+ Features exposed in the UI:
105
+ - **Streaming chat** (WebSocket streams `StreamEvent`s: text, tool calls, tool
106
+ results, thinking, usage, completion)
107
+ - **Plan mode** (`/api/chat` with `mode: plan` returns a reviewable `Plan`)
108
+ - **Projects** — `Project` scoping with auto-loaded instruction files + sandboxed
109
+ built-in tools (Read/Write/Edit/Glob/Grep/Bash)
110
+ - **Checkpoints / undo** — snapshot + restore files before agent edits
111
+ - **Permissions** — `PermissionPolicy` allow/deny/ask rules per tool + params
112
+ - **Sub-agents** — configure `SubAgentSpec`s; supervisor fans them out
113
+ - **Background tasks** — submit/resume/cancel via `BackgroundTaskRegistry`
114
+ - **Slash commands** — `/compact`, `/context`, `/clear`
115
+ - **MCP** — connect a stdio MCP server and register its tools
116
+ - **Reasoning controls** — `reasoning_effort` / `thinking_enabled` per request
117
+
118
+ See `web/README.md` for the full API reference.
119
+
120
+ ## Installation
121
+
122
+ ### From PyPI
123
+
124
+ ```bash
125
+ pip install ai-runtime
126
+ ```
127
+
128
+ ### From source
129
+
130
+ ```bash
131
+ git clone https://github.com/KiritVaghela/ai-runtime.git
132
+ cd ai-runtime
133
+ pip install -e .
134
+ ```
135
+
136
+ ## Quick Start
137
+
138
+ ```python
139
+ import os
140
+
141
+ from ai_runtime import AgentRuntime
142
+ from ai_runtime.conversation import ChatMessage
143
+ from ai_runtime.providers.enums import ProviderType
144
+
145
+ runtime = AgentRuntime.from_provider(
146
+ provider=ProviderType.GROQ,
147
+ model="groq/llama-3.3-70b-versatile",
148
+ api_key=os.getenv("GROQ_API_KEY"),
149
+ )
150
+
151
+ session = runtime.create_session()
152
+
153
+ response = await session.chat(
154
+ ChatMessage.user("Hello!")
155
+ )
156
+
157
+ print(response.message.content)
158
+ ```
159
+
160
+ ## Streaming
161
+
162
+ ```python
163
+ from ai_runtime.conversation import ChatMessage
164
+ from ai_runtime.streaming import TextDeltaEvent
165
+
166
+ async for event in session.stream(
167
+ ChatMessage.user("Write a haiku.")
168
+ ):
169
+ if isinstance(event, TextDeltaEvent):
170
+ print(event.delta, end="")
171
+ ```
172
+
173
+ ## Streaming with timeout
174
+
175
+ The runtime supports stream timeout propagation through `ChatRequest.timeout`.
176
+ If a provider stream stalls, an `ErrorEvent` is emitted and the stream stops.
177
+
178
+ ```python
179
+ from ai_runtime.conversation import ChatMessage, ChatRequest
180
+ from ai_runtime.streaming import ErrorEvent, TextDeltaEvent
181
+
182
+ request = ChatRequest(
183
+ messages=[ChatMessage.user("Generate a poem.")],
184
+ timeout=10.0,
185
+ )
186
+
187
+ async for event in session.stream(request):
188
+ if isinstance(event, TextDeltaEvent):
189
+ print(event.delta, end="")
190
+ elif isinstance(event, ErrorEvent):
191
+ print("\nStream timed out or failed:", event.message)
192
+ ```
193
+
194
+ ## Provider registry
195
+
196
+ The runtime uses a provider registry so you can register custom providers or
197
+ replace the default provider implementation during tests.
198
+
199
+ ```python
200
+ from ai_runtime import AgentRuntime
201
+ from ai_runtime.providers import ProviderRegistry
202
+ from ai_runtime.providers.enums import ProviderType
203
+
204
+ registry = ProviderRegistry()
205
+ registry.register(ProviderType.OPENAI, MyCustomProvider)
206
+
207
+ runtime = AgentRuntime.from_provider(
208
+ provider=ProviderType.OPENAI,
209
+ model="gpt-4.1",
210
+ api_key=os.getenv("OPENAI_API_KEY"),
211
+ registry=registry,
212
+ )
213
+ ```
214
+
215
+ ## Architecture
216
+
217
+ AgentRuntime
218
+ └── Session
219
+ └── ExecutionEngine
220
+ └── ExecutionPipeline
221
+ ├── RequestBuilderStage
222
+ ├── LLMStage
223
+ └── ToolLoopStage
224
+ └── EventProcessor
225
+
226
+ ## Tools
227
+
228
+ Register tools with a `ToolRegistry`, wrap it in a `ToolExecutor`, and attach
229
+ it to the session context. When the model requests a tool, the runtime
230
+ executes it and feeds the result back automatically.
231
+
232
+ ```python
233
+ from ai_runtime.tools import ToolRegistry, ToolExecutor, FunctionTool
234
+ from ai_runtime.conversation import ChatMessage
235
+
236
+ registry = ToolRegistry()
237
+ registry.register(
238
+ FunctionTool("get_weather", lambda ctx, inp: f"Weather in {inp['city']}: sunny")
239
+ )
240
+
241
+ session.context.tool_executor = ToolExecutor(registry)
242
+
243
+ response = await session.chat(
244
+ ChatMessage.user("What is the weather in Paris?")
245
+ )
246
+ print(response.message.content)
247
+ ```
248
+
249
+ ## Agents
250
+
251
+ An `Agent` bundles a provider, system prompt, tools, memory, and skills.
252
+ `AgentRunner` drives execution (including the automatic tool-call loop) and
253
+ persists conversation memory across turns.
254
+
255
+ ```python
256
+ from ai_runtime import AgentRuntime, Agent, AgentRunner
257
+ from ai_runtime.tools import ToolRegistry, ToolExecutor, FunctionTool
258
+
259
+ runtime = AgentRuntime.from_provider(
260
+ provider=ProviderType.GROQ,
261
+ model="llama-3.3-70b-versatile",
262
+ api_key=os.getenv("GROQ_API_KEY"),
263
+ )
264
+
265
+ registry = ToolRegistry()
266
+ registry.register(FunctionTool("ping", lambda ctx, inp: "pong"))
267
+
268
+ agent = runtime.create_agent(
269
+ name="helper",
270
+ system_prompt="You are a helpful assistant.",
271
+ tool_registry=registry,
272
+ )
273
+
274
+ runner = AgentRunner(agent)
275
+ response = await runner.run("Ping the tool for me.")
276
+ print(response.message.content)
277
+ ```
278
+
279
+ ## Memory, RAG & Skills
280
+
281
+ - `ai_runtime.memory` — `MemoryStore`, `ConversationMemory`, `SemanticMemory`.
282
+ - `ai_runtime.rag` — `Document`, `VectorStore`, `Retriever` for retrieval.
283
+ - `ai_runtime.skills` — `Skill` + `SkillRegistry` for composable behaviors.
284
+ - `ai_runtime.context` — `ContextWindow` for token budgeting/truncation.
285
+
286
+ ## Documentation
287
+
288
+ - [Migration Guide](docs/migration_guide.md)
289
+ - [Adapter Tutorial](docs/adapter_tutorial.md)
290
+ - [Examples](docs/examples.md)
291
+ - [Release Checklist](docs/release_checklist.md)
292
+
293
+ See [CHANGELOG.md](CHANGELOG.md) for version history.
294
+
295
+ ## Testing
296
+
297
+ ```bash
298
+ pytest
299
+ ```
300
+
301
+ Current status:
302
+
303
+ - Provider registry with custom provider registration
304
+ - Streaming response support with timeouts and completion events
305
+ - Session-based execution and conversation accumulation
306
+ - Provider integration coverage with test doubles
307
+
308
+ ## Roadmap
309
+
310
+ ### v0.3.x
311
+
312
+ - Tool registry
313
+ - Tool execution
314
+ - Permission manager
315
+ - Filesystem tools
316
+ - Bash tools
317
+
318
+ ### Future
319
+
320
+ - MCP support
321
+ - Multi-agent workflows
322
+ - Desktop and terminal integrations
323
+ - AI Factory integration
324
+
325
+ ## Publishing to PyPI
326
+
327
+ 1. Update version in `pyproject.toml`.
328
+ 2. Build:
329
+
330
+ ```bash
331
+ python -m build
332
+ ```
333
+
334
+ 3. Check:
335
+
336
+ ```bash
337
+ twine check dist/*
338
+ ```
339
+
340
+ 4. Upload to TestPyPI:
341
+
342
+ ```bash
343
+ twine upload --repository testpypi dist/*
344
+ ```
345
+
346
+ 5. Upload to PyPI:
347
+
348
+ ```bash
349
+ twine upload dist/*
350
+ ```
351
+
@@ -0,0 +1,332 @@
1
+ # AI Runtime
2
+
3
+ AI Runtime is a provider-agnostic Python runtime for building AI
4
+ applications and agent workflows.
5
+
6
+ ## Features
7
+
8
+ - Provider abstraction with a unified LLM contract
9
+ - Built-in default provider registry and plugin discovery
10
+ - Custom provider registration with test doubles
11
+ - Conversation management and session-based execution
12
+ - Streaming responses with event processing
13
+ - Streaming timeout/cancellation boundary handling
14
+ - Automatic tool-calling loop (model requests tools → runtime executes → re-invokes)
15
+ - Capability-gated request mapping (tools, structured output, vision, metadata)
16
+ - Expanded provider contract: chat, stream, embeddings, image, transcription
17
+ - Retries via `ProviderConfig.max_retries` (forwarded to the backend)
18
+ - Uniform events: `chat()` and `stream()` both emit `StreamEvent`s
19
+ - Rich streaming events: text, usage, tool call, tool result, thinking, permission
20
+ - Execution engine and pipeline stages
21
+ - Provider metadata, capabilities, and request mapping
22
+ - Fully tested runtime and provider integration coverage
23
+
24
+ ### Agentic capabilities (v0.6.0)
25
+
26
+ `ai_runtime` now closes the gap with agentic coding tools (Claude Code,
27
+ OpenAI Codex, Cursor):
28
+
29
+ - **Plan mode** — `AgentRunner.plan()` / `ExecutionEngine.plan()` produce a
30
+ reviewable `Plan` (read-only, no tools run) before execution.
31
+ - **Sub-agents** — declare `SubAgentSpec`s on an `Agent`; the `SupervisorStage`
32
+ fans them out in parallel with isolated contexts and aggregates results.
33
+ - **Permissions** — `PermissionPolicy` + `GuardedToolExecutor` enforce
34
+ allow/deny/ask rules (glob-matched) over tool calls, mirroring tiered
35
+ permission modes.
36
+ - **Hooks** — `HookRegistry` with `PreToolUse` / `PostToolUse` / `PreLLM` /
37
+ `PostLLM` / `OnPlan` / `OnCompact` / `OnError` lifecycle hooks.
38
+ - **Auto compaction** — `CompactionStage` summarizes or drops old turns when
39
+ the context window exceeds its token budget.
40
+ - **Memory consolidation** — `MemoryConsolidationStage` writes durable
41
+ learnings (`LEARNING: ...`) back to the agent's `MemoryStore`.
42
+ - **MCP client** — `MCPClient` + `StdioTransport` speak JSON-RPC over stdio;
43
+ `register_mcp_tools()` wraps server tools as runtime `Tool`s.
44
+ - **Background tasks** — `BackgroundTaskRegistry` for resumable async tasks
45
+ (à la `codex resume` / Claude `/tasks`).
46
+ - **Skill scoping** — `Skill` gains `paths` / `globs` / `disable_model_invocation`.
47
+ - **Reasoning controls** — `ProviderConfig.reasoning_effort` / `thinking_enabled`
48
+ / `thinking_budget_tokens`, forwarded when the provider supports reasoning.
49
+
50
+ ### Integration surfaces (v0.7.0)
51
+
52
+ To embed `ai_runtime` in a **web app, desktop app, VS Code, or CLI** like
53
+ Claude Code / Codex / Cursor / Copilot, the framework now ships:
54
+
55
+ - **Built-in tools** — `ReadFileTool`, `WriteFileTool`, `EditFileTool`,
56
+ `GlobTool`, `GrepTool`, `BashTool` (scoped to a sandbox root via
57
+ `register_builtin_tools`). These mirror the file/shell/grep primitives of
58
+ the four tools.
59
+ - **Checkpoints / undo** — `CheckpointManager` snapshots files before edits
60
+ so the UI can roll back (à la Cursor/Claude/Copilot checkpoints).
61
+ - **Agent config files** — `load_project_instructions()` discovers
62
+ `.github/copilot-instructions.md`, `AGENTS.md`, `CLAUDE.md`,
63
+ `.cursor/rules` from the project root and folds them into the system prompt.
64
+ - **Transport-agnostic server** — `AgentServer` exposes an `Agent` over a
65
+ JSON-line protocol (`AgentRequest` / `AgentResponse` / `StreamEvent`) via
66
+ `serve_stdio()` (VS Code / CLI) and `serve_http()` (web / desktop).
67
+ - **CLI** — `ai-runtime` console script: `ai-runtime "prompt" --model ...`,
68
+ `--mode plan|stream`, `--serve` (stdio), `--http` (HTTP server), `--yolo`.
69
+ - **Workspace / project** — `Project` scopes memory, tools, permissions, and
70
+ checkpoints to a project root (the unit you mount in a client).
71
+ - **Slash commands** — `CommandRegistry` / `default_commands()`
72
+ (`/compact`, `/context`, `/clear`) mirroring Copilot's `/` menu.
73
+ - **BYO provider** — `ProviderConfig.from_env()` reads `COPILOT_PROVIDER_*`
74
+ vars to point at Ollama / vLLM / any OpenAI-compatible endpoint.
75
+
76
+ ### Web application (`web/`)
77
+
78
+ A ready-to-run web UI + REST/WebSocket API that exercises the full framework:
79
+
80
+ ```bash
81
+ export AI_RUNTIME_API_KEY=sk-... # or AI_RUNTIME_PROVIDER/AI_RUNTIME_BASE_URL
82
+ ./venv/bin/python web/run.py # serves http://127.0.0.1:8787
83
+ ```
84
+
85
+ Features exposed in the UI:
86
+ - **Streaming chat** (WebSocket streams `StreamEvent`s: text, tool calls, tool
87
+ results, thinking, usage, completion)
88
+ - **Plan mode** (`/api/chat` with `mode: plan` returns a reviewable `Plan`)
89
+ - **Projects** — `Project` scoping with auto-loaded instruction files + sandboxed
90
+ built-in tools (Read/Write/Edit/Glob/Grep/Bash)
91
+ - **Checkpoints / undo** — snapshot + restore files before agent edits
92
+ - **Permissions** — `PermissionPolicy` allow/deny/ask rules per tool + params
93
+ - **Sub-agents** — configure `SubAgentSpec`s; supervisor fans them out
94
+ - **Background tasks** — submit/resume/cancel via `BackgroundTaskRegistry`
95
+ - **Slash commands** — `/compact`, `/context`, `/clear`
96
+ - **MCP** — connect a stdio MCP server and register its tools
97
+ - **Reasoning controls** — `reasoning_effort` / `thinking_enabled` per request
98
+
99
+ See `web/README.md` for the full API reference.
100
+
101
+ ## Installation
102
+
103
+ ### From PyPI
104
+
105
+ ```bash
106
+ pip install ai-runtime
107
+ ```
108
+
109
+ ### From source
110
+
111
+ ```bash
112
+ git clone https://github.com/KiritVaghela/ai-runtime.git
113
+ cd ai-runtime
114
+ pip install -e .
115
+ ```
116
+
117
+ ## Quick Start
118
+
119
+ ```python
120
+ import os
121
+
122
+ from ai_runtime import AgentRuntime
123
+ from ai_runtime.conversation import ChatMessage
124
+ from ai_runtime.providers.enums import ProviderType
125
+
126
+ runtime = AgentRuntime.from_provider(
127
+ provider=ProviderType.GROQ,
128
+ model="groq/llama-3.3-70b-versatile",
129
+ api_key=os.getenv("GROQ_API_KEY"),
130
+ )
131
+
132
+ session = runtime.create_session()
133
+
134
+ response = await session.chat(
135
+ ChatMessage.user("Hello!")
136
+ )
137
+
138
+ print(response.message.content)
139
+ ```
140
+
141
+ ## Streaming
142
+
143
+ ```python
144
+ from ai_runtime.conversation import ChatMessage
145
+ from ai_runtime.streaming import TextDeltaEvent
146
+
147
+ async for event in session.stream(
148
+ ChatMessage.user("Write a haiku.")
149
+ ):
150
+ if isinstance(event, TextDeltaEvent):
151
+ print(event.delta, end="")
152
+ ```
153
+
154
+ ## Streaming with timeout
155
+
156
+ The runtime supports stream timeout propagation through `ChatRequest.timeout`.
157
+ If a provider stream stalls, an `ErrorEvent` is emitted and the stream stops.
158
+
159
+ ```python
160
+ from ai_runtime.conversation import ChatMessage, ChatRequest
161
+ from ai_runtime.streaming import ErrorEvent, TextDeltaEvent
162
+
163
+ request = ChatRequest(
164
+ messages=[ChatMessage.user("Generate a poem.")],
165
+ timeout=10.0,
166
+ )
167
+
168
+ async for event in session.stream(request):
169
+ if isinstance(event, TextDeltaEvent):
170
+ print(event.delta, end="")
171
+ elif isinstance(event, ErrorEvent):
172
+ print("\nStream timed out or failed:", event.message)
173
+ ```
174
+
175
+ ## Provider registry
176
+
177
+ The runtime uses a provider registry so you can register custom providers or
178
+ replace the default provider implementation during tests.
179
+
180
+ ```python
181
+ from ai_runtime import AgentRuntime
182
+ from ai_runtime.providers import ProviderRegistry
183
+ from ai_runtime.providers.enums import ProviderType
184
+
185
+ registry = ProviderRegistry()
186
+ registry.register(ProviderType.OPENAI, MyCustomProvider)
187
+
188
+ runtime = AgentRuntime.from_provider(
189
+ provider=ProviderType.OPENAI,
190
+ model="gpt-4.1",
191
+ api_key=os.getenv("OPENAI_API_KEY"),
192
+ registry=registry,
193
+ )
194
+ ```
195
+
196
+ ## Architecture
197
+
198
+ AgentRuntime
199
+ └── Session
200
+ └── ExecutionEngine
201
+ └── ExecutionPipeline
202
+ ├── RequestBuilderStage
203
+ ├── LLMStage
204
+ └── ToolLoopStage
205
+ └── EventProcessor
206
+
207
+ ## Tools
208
+
209
+ Register tools with a `ToolRegistry`, wrap it in a `ToolExecutor`, and attach
210
+ it to the session context. When the model requests a tool, the runtime
211
+ executes it and feeds the result back automatically.
212
+
213
+ ```python
214
+ from ai_runtime.tools import ToolRegistry, ToolExecutor, FunctionTool
215
+ from ai_runtime.conversation import ChatMessage
216
+
217
+ registry = ToolRegistry()
218
+ registry.register(
219
+ FunctionTool("get_weather", lambda ctx, inp: f"Weather in {inp['city']}: sunny")
220
+ )
221
+
222
+ session.context.tool_executor = ToolExecutor(registry)
223
+
224
+ response = await session.chat(
225
+ ChatMessage.user("What is the weather in Paris?")
226
+ )
227
+ print(response.message.content)
228
+ ```
229
+
230
+ ## Agents
231
+
232
+ An `Agent` bundles a provider, system prompt, tools, memory, and skills.
233
+ `AgentRunner` drives execution (including the automatic tool-call loop) and
234
+ persists conversation memory across turns.
235
+
236
+ ```python
237
+ from ai_runtime import AgentRuntime, Agent, AgentRunner
238
+ from ai_runtime.tools import ToolRegistry, ToolExecutor, FunctionTool
239
+
240
+ runtime = AgentRuntime.from_provider(
241
+ provider=ProviderType.GROQ,
242
+ model="llama-3.3-70b-versatile",
243
+ api_key=os.getenv("GROQ_API_KEY"),
244
+ )
245
+
246
+ registry = ToolRegistry()
247
+ registry.register(FunctionTool("ping", lambda ctx, inp: "pong"))
248
+
249
+ agent = runtime.create_agent(
250
+ name="helper",
251
+ system_prompt="You are a helpful assistant.",
252
+ tool_registry=registry,
253
+ )
254
+
255
+ runner = AgentRunner(agent)
256
+ response = await runner.run("Ping the tool for me.")
257
+ print(response.message.content)
258
+ ```
259
+
260
+ ## Memory, RAG & Skills
261
+
262
+ - `ai_runtime.memory` — `MemoryStore`, `ConversationMemory`, `SemanticMemory`.
263
+ - `ai_runtime.rag` — `Document`, `VectorStore`, `Retriever` for retrieval.
264
+ - `ai_runtime.skills` — `Skill` + `SkillRegistry` for composable behaviors.
265
+ - `ai_runtime.context` — `ContextWindow` for token budgeting/truncation.
266
+
267
+ ## Documentation
268
+
269
+ - [Migration Guide](docs/migration_guide.md)
270
+ - [Adapter Tutorial](docs/adapter_tutorial.md)
271
+ - [Examples](docs/examples.md)
272
+ - [Release Checklist](docs/release_checklist.md)
273
+
274
+ See [CHANGELOG.md](CHANGELOG.md) for version history.
275
+
276
+ ## Testing
277
+
278
+ ```bash
279
+ pytest
280
+ ```
281
+
282
+ Current status:
283
+
284
+ - Provider registry with custom provider registration
285
+ - Streaming response support with timeouts and completion events
286
+ - Session-based execution and conversation accumulation
287
+ - Provider integration coverage with test doubles
288
+
289
+ ## Roadmap
290
+
291
+ ### v0.3.x
292
+
293
+ - Tool registry
294
+ - Tool execution
295
+ - Permission manager
296
+ - Filesystem tools
297
+ - Bash tools
298
+
299
+ ### Future
300
+
301
+ - MCP support
302
+ - Multi-agent workflows
303
+ - Desktop and terminal integrations
304
+ - AI Factory integration
305
+
306
+ ## Publishing to PyPI
307
+
308
+ 1. Update version in `pyproject.toml`.
309
+ 2. Build:
310
+
311
+ ```bash
312
+ python -m build
313
+ ```
314
+
315
+ 3. Check:
316
+
317
+ ```bash
318
+ twine check dist/*
319
+ ```
320
+
321
+ 4. Upload to TestPyPI:
322
+
323
+ ```bash
324
+ twine upload --repository testpypi dist/*
325
+ ```
326
+
327
+ 5. Upload to PyPI:
328
+
329
+ ```bash
330
+ twine upload dist/*
331
+ ```
332
+