b4pt0r-the-framework 0.1.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.
- b4pt0r_the_framework-0.1.0/.gitignore +13 -0
- b4pt0r_the_framework-0.1.0/AGENTS.md +59 -0
- b4pt0r_the_framework-0.1.0/CHANGELOG.md +16 -0
- b4pt0r_the_framework-0.1.0/LICENSE +21 -0
- b4pt0r_the_framework-0.1.0/PKG-INFO +245 -0
- b4pt0r_the_framework-0.1.0/README.md +206 -0
- b4pt0r_the_framework-0.1.0/docs/framework-api-simplification-audit.md +37 -0
- b4pt0r_the_framework-0.1.0/docs/framework-clarification-audit.md +51 -0
- b4pt0r_the_framework-0.1.0/docs/framework-model-style-audit.md +143 -0
- b4pt0r_the_framework-0.1.0/docs/framework.md +520 -0
- b4pt0r_the_framework-0.1.0/docs/starter-plan.md +87 -0
- b4pt0r_the_framework-0.1.0/examples/minimal_agent_app.py +87 -0
- b4pt0r_the_framework-0.1.0/pyproject.toml +60 -0
- b4pt0r_the_framework-0.1.0/starter/README.md +161 -0
- b4pt0r_the_framework-0.1.0/starter/__init__.py +1 -0
- b4pt0r_the_framework-0.1.0/starter/__main__.py +6 -0
- b4pt0r_the_framework-0.1.0/starter/application.py +70 -0
- b4pt0r_the_framework-0.1.0/starter/desktop.py +156 -0
- b4pt0r_the_framework-0.1.0/starter/instructions.md +47 -0
- b4pt0r_the_framework-0.1.0/starter/memory.md +25 -0
- b4pt0r_the_framework-0.1.0/starter/security.py +41 -0
- b4pt0r_the_framework-0.1.0/starter/server.py +179 -0
- b4pt0r_the_framework-0.1.0/starter/ui/.gitignore +2 -0
- b4pt0r_the_framework-0.1.0/starter/ui/index.html +12 -0
- b4pt0r_the_framework-0.1.0/starter/ui/package-lock.json +1153 -0
- b4pt0r_the_framework-0.1.0/starter/ui/package.json +18 -0
- b4pt0r_the_framework-0.1.0/starter/ui/src/api.js +25 -0
- b4pt0r_the_framework-0.1.0/starter/ui/src/main.jsx +380 -0
- b4pt0r_the_framework-0.1.0/starter/ui/src/realtime-audio.js +113 -0
- b4pt0r_the_framework-0.1.0/starter/ui/src/realtime-transcript.js +51 -0
- b4pt0r_the_framework-0.1.0/starter/ui/src/realtime-transcript.test.js +24 -0
- b4pt0r_the_framework-0.1.0/starter/ui/src/session.js +83 -0
- b4pt0r_the_framework-0.1.0/starter/ui/src/session.test.js +118 -0
- b4pt0r_the_framework-0.1.0/starter/ui/src/settings.jsx +117 -0
- b4pt0r_the_framework-0.1.0/starter/ui/src/style.css +297 -0
- b4pt0r_the_framework-0.1.0/starter/ui/src/voice.js +84 -0
- b4pt0r_the_framework-0.1.0/starter/ui/src/voice.test.js +106 -0
- b4pt0r_the_framework-0.1.0/starter/ui/vite.config.js +3 -0
- b4pt0r_the_framework-0.1.0/starter/voice.py +65 -0
- b4pt0r_the_framework-0.1.0/tests/agentic/test_agent_spec.py +365 -0
- b4pt0r_the_framework-0.1.0/tests/agentic/test_agentic_loop_control.py +206 -0
- b4pt0r_the_framework-0.1.0/tests/agentic/test_architecture.py +73 -0
- b4pt0r_the_framework-0.1.0/tests/agentic/test_atomic_persistence.py +78 -0
- b4pt0r_the_framework-0.1.0/tests/agentic/test_bash_plugin.py +230 -0
- b4pt0r_the_framework-0.1.0/tests/agentic/test_command_loop.py +60 -0
- b4pt0r_the_framework-0.1.0/tests/agentic/test_context_compaction.py +389 -0
- b4pt0r_the_framework-0.1.0/tests/agentic/test_declaration_schema.py +51 -0
- b4pt0r_the_framework-0.1.0/tests/agentic/test_dependencies.py +21 -0
- b4pt0r_the_framework-0.1.0/tests/agentic/test_embeddings.py +40 -0
- b4pt0r_the_framework-0.1.0/tests/agentic/test_event_loop.py +30 -0
- b4pt0r_the_framework-0.1.0/tests/agentic/test_fleet.py +663 -0
- b4pt0r_the_framework-0.1.0/tests/agentic/test_function_specs.py +52 -0
- b4pt0r_the_framework-0.1.0/tests/agentic/test_lifecycle.py +53 -0
- b4pt0r_the_framework-0.1.0/tests/agentic/test_native_model_coercion.py +196 -0
- b4pt0r_the_framework-0.1.0/tests/agentic/test_plugin_endpoint.py +59 -0
- b4pt0r_the_framework-0.1.0/tests/agentic/test_plugin_status.py +19 -0
- b4pt0r_the_framework-0.1.0/tests/agentic/test_plugin_tools.py +988 -0
- b4pt0r_the_framework-0.1.0/tests/agentic/test_recovery.py +105 -0
- b4pt0r_the_framework-0.1.0/tests/agentic/test_registry_plugin.py +148 -0
- b4pt0r_the_framework-0.1.0/tests/agentic/test_runtime_models.py +108 -0
- b4pt0r_the_framework-0.1.0/tests/agentic/test_scheduler_plugin.py +45 -0
- b4pt0r_the_framework-0.1.0/tests/agentic/test_server_runtime.py +73 -0
- b4pt0r_the_framework-0.1.0/tests/agentic/test_session.py +457 -0
- b4pt0r_the_framework-0.1.0/tests/agentic/test_starter_voice.py +90 -0
- b4pt0r_the_framework-0.1.0/tests/agentic/test_supervisor.py +115 -0
- b4pt0r_the_framework-0.1.0/tests/agentic/test_system_plugin.py +162 -0
- b4pt0r_the_framework-0.1.0/tests/agentic/test_tailscale.py +108 -0
- b4pt0r_the_framework-0.1.0/tests/agentic/test_tokenization.py +50 -0
- b4pt0r_the_framework-0.1.0/tests/agentic/test_usage.py +47 -0
- b4pt0r_the_framework-0.1.0/tests/agentic/test_web_search_plugin.py +44 -0
- b4pt0r_the_framework-0.1.0/tests/agentic/test_worker.py +867 -0
- b4pt0r_the_framework-0.1.0/tests/agentic/test_worker_process.py +77 -0
- b4pt0r_the_framework-0.1.0/tests/application/README.md +4 -0
- b4pt0r_the_framework-0.1.0/tests/application/fixtures/starter_restart_server.py +43 -0
- b4pt0r_the_framework-0.1.0/tests/application/fixtures/unauthenticated_worker.py +14 -0
- b4pt0r_the_framework-0.1.0/tests/application/test_application_bridge.py +138 -0
- b4pt0r_the_framework-0.1.0/tests/application/test_browser_rpc_lifecycle.py +140 -0
- b4pt0r_the_framework-0.1.0/tests/application/test_endpoint_models.py +124 -0
- b4pt0r_the_framework-0.1.0/tests/application/test_endpoint_registry.py +261 -0
- b4pt0r_the_framework-0.1.0/tests/application/test_framework.py +405 -0
- b4pt0r_the_framework-0.1.0/tests/application/test_framework_bootstrap.py +45 -0
- b4pt0r_the_framework-0.1.0/tests/application/test_framework_independence.py +76 -0
- b4pt0r_the_framework-0.1.0/tests/application/test_framework_wheel.py +89 -0
- b4pt0r_the_framework-0.1.0/tests/application/test_framework_worker_integration.py +111 -0
- b4pt0r_the_framework-0.1.0/tests/application/test_mapping_store.py +57 -0
- b4pt0r_the_framework-0.1.0/tests/application/test_media_response.py +5 -0
- b4pt0r_the_framework-0.1.0/tests/application/test_minimal_example.py +29 -0
- b4pt0r_the_framework-0.1.0/tests/application/test_plugin_host.py +289 -0
- b4pt0r_the_framework-0.1.0/tests/application/test_runtime_lifecycle.py +97 -0
- b4pt0r_the_framework-0.1.0/tests/application/test_scheduler.py +264 -0
- b4pt0r_the_framework-0.1.0/tests/application/test_services.py +124 -0
- b4pt0r_the_framework-0.1.0/tests/application/test_starter.py +211 -0
- b4pt0r_the_framework-0.1.0/tests/application/test_starter_browser_recovery.py +138 -0
- b4pt0r_the_framework-0.1.0/tests/application/test_starter_desktop.py +73 -0
- b4pt0r_the_framework-0.1.0/tests/application/test_starter_live.py +78 -0
- b4pt0r_the_framework-0.1.0/tests/application/test_starter_security.py +34 -0
- b4pt0r_the_framework-0.1.0/tests/application/test_starter_voice_live.py +87 -0
- b4pt0r_the_framework-0.1.0/tests/application/test_supervisor_shutdown.py +50 -0
- b4pt0r_the_framework-0.1.0/tests/application/test_surfaces.py +276 -0
- b4pt0r_the_framework-0.1.0/tests/application/test_system_control.py +238 -0
- b4pt0r_the_framework-0.1.0/tests/application/test_websockets.py +70 -0
- b4pt0r_the_framework-0.1.0/tests/fixtures/fake_worker.py +242 -0
- b4pt0r_the_framework-0.1.0/the_framework/__init__.py +30 -0
- b4pt0r_the_framework-0.1.0/the_framework/__main__.py +6 -0
- b4pt0r_the_framework-0.1.0/the_framework/agent/__init__.py +265 -0
- b4pt0r_the_framework-0.1.0/the_framework/agent/context/__init__.py +1 -0
- b4pt0r_the_framework-0.1.0/the_framework/agent/context/builder.py +137 -0
- b4pt0r_the_framework-0.1.0/the_framework/agent/context/caching.py +8 -0
- b4pt0r_the_framework-0.1.0/the_framework/agent/context/compaction.py +95 -0
- b4pt0r_the_framework-0.1.0/the_framework/agent/context/projections.py +37 -0
- b4pt0r_the_framework-0.1.0/the_framework/agent/context/session.py +504 -0
- b4pt0r_the_framework-0.1.0/the_framework/agent/extensions/__init__.py +1 -0
- b4pt0r_the_framework-0.1.0/the_framework/agent/extensions/commands.py +114 -0
- b4pt0r_the_framework-0.1.0/the_framework/agent/extensions/endpoints.py +132 -0
- b4pt0r_the_framework-0.1.0/the_framework/agent/extensions/hooks.py +45 -0
- b4pt0r_the_framework-0.1.0/the_framework/agent/extensions/instructions.py +53 -0
- b4pt0r_the_framework-0.1.0/the_framework/agent/extensions/plugin.py +196 -0
- b4pt0r_the_framework-0.1.0/the_framework/agent/extensions/providers.py +138 -0
- b4pt0r_the_framework-0.1.0/the_framework/agent/extensions/schema.py +155 -0
- b4pt0r_the_framework-0.1.0/the_framework/agent/extensions/specialists.py +180 -0
- b4pt0r_the_framework-0.1.0/the_framework/agent/extensions/tools.py +259 -0
- b4pt0r_the_framework-0.1.0/the_framework/agent/models/__init__.py +1 -0
- b4pt0r_the_framework-0.1.0/the_framework/agent/models/base.py +63 -0
- b4pt0r_the_framework-0.1.0/the_framework/agent/models/config.py +115 -0
- b4pt0r_the_framework-0.1.0/the_framework/agent/models/content.py +28 -0
- b4pt0r_the_framework-0.1.0/the_framework/agent/models/events.py +363 -0
- b4pt0r_the_framework-0.1.0/the_framework/agent/models/lifecycle.py +100 -0
- b4pt0r_the_framework-0.1.0/the_framework/agent/models/responses.py +454 -0
- b4pt0r_the_framework-0.1.0/the_framework/agent/models/state.py +28 -0
- b4pt0r_the_framework-0.1.0/the_framework/agent/models/usage.py +66 -0
- b4pt0r_the_framework-0.1.0/the_framework/agent/models/worker.py +60 -0
- b4pt0r_the_framework-0.1.0/the_framework/agent/runtime/__init__.py +1 -0
- b4pt0r_the_framework-0.1.0/the_framework/agent/runtime/agent.py +318 -0
- b4pt0r_the_framework-0.1.0/the_framework/agent/runtime/agentic_loop.py +623 -0
- b4pt0r_the_framework-0.1.0/the_framework/agent/runtime/application.py +25 -0
- b4pt0r_the_framework-0.1.0/the_framework/agent/runtime/chat.py +17 -0
- b4pt0r_the_framework-0.1.0/the_framework/agent/runtime/command_loop.py +82 -0
- b4pt0r_the_framework-0.1.0/the_framework/agent/runtime/event_loop.py +92 -0
- b4pt0r_the_framework-0.1.0/the_framework/agent/runtime/prompts/README.md +3 -0
- b4pt0r_the_framework-0.1.0/the_framework/agent/runtime/prompts/tool_outputs.md +23 -0
- b4pt0r_the_framework-0.1.0/the_framework/agent/runtime/protocol.py +274 -0
- b4pt0r_the_framework-0.1.0/the_framework/agent/runtime/worker.py +549 -0
- b4pt0r_the_framework-0.1.0/the_framework/agent/runtime/worker_process.py +100 -0
- b4pt0r_the_framework-0.1.0/the_framework/agent/spec.py +264 -0
- b4pt0r_the_framework-0.1.0/the_framework/cli.py +67 -0
- b4pt0r_the_framework-0.1.0/the_framework/plugins/__init__.py +1 -0
- b4pt0r_the_framework-0.1.0/the_framework/plugins/bash/__init__.py +3 -0
- b4pt0r_the_framework-0.1.0/the_framework/plugins/bash/instructions.md +18 -0
- b4pt0r_the_framework-0.1.0/the_framework/plugins/bash/plugin.py +531 -0
- b4pt0r_the_framework-0.1.0/the_framework/plugins/browser/__init__.py +3 -0
- b4pt0r_the_framework-0.1.0/the_framework/plugins/browser/instructions.md +9 -0
- b4pt0r_the_framework-0.1.0/the_framework/plugins/browser/plugin.py +259 -0
- b4pt0r_the_framework-0.1.0/the_framework/plugins/embeddings.py +50 -0
- b4pt0r_the_framework-0.1.0/the_framework/plugins/memory/__init__.py +1 -0
- b4pt0r_the_framework-0.1.0/the_framework/plugins/memory/curator.py +590 -0
- b4pt0r_the_framework-0.1.0/the_framework/plugins/memory/instructions.md +6 -0
- b4pt0r_the_framework-0.1.0/the_framework/plugins/memory/live.py +178 -0
- b4pt0r_the_framework-0.1.0/the_framework/plugins/memory/plugin.py +456 -0
- b4pt0r_the_framework-0.1.0/the_framework/plugins/memory/store.py +704 -0
- b4pt0r_the_framework-0.1.0/the_framework/plugins/realtime/__init__.py +3 -0
- b4pt0r_the_framework-0.1.0/the_framework/plugins/realtime/plugin.py +251 -0
- b4pt0r_the_framework-0.1.0/the_framework/plugins/registry/__init__.py +3 -0
- b4pt0r_the_framework-0.1.0/the_framework/plugins/registry/instructions.md +19 -0
- b4pt0r_the_framework-0.1.0/the_framework/plugins/registry/live.py +78 -0
- b4pt0r_the_framework-0.1.0/the_framework/plugins/registry/plugin.py +462 -0
- b4pt0r_the_framework-0.1.0/the_framework/plugins/scheduler/__init__.py +3 -0
- b4pt0r_the_framework-0.1.0/the_framework/plugins/scheduler/instructions.md +18 -0
- b4pt0r_the_framework-0.1.0/the_framework/plugins/scheduler/plugin.py +112 -0
- b4pt0r_the_framework-0.1.0/the_framework/plugins/scheduler/service.py +463 -0
- b4pt0r_the_framework-0.1.0/the_framework/plugins/system/__init__.py +3 -0
- b4pt0r_the_framework-0.1.0/the_framework/plugins/system/instructions.md +31 -0
- b4pt0r_the_framework-0.1.0/the_framework/plugins/system/plugin.py +146 -0
- b4pt0r_the_framework-0.1.0/the_framework/plugins/system/service.py +279 -0
- b4pt0r_the_framework-0.1.0/the_framework/plugins/web_search/__init__.py +3 -0
- b4pt0r_the_framework-0.1.0/the_framework/plugins/web_search/instructions.md +5 -0
- b4pt0r_the_framework-0.1.0/the_framework/plugins/web_search/plugin.py +34 -0
- b4pt0r_the_framework-0.1.0/the_framework/py.typed +1 -0
- b4pt0r_the_framework-0.1.0/the_framework/server/__init__.py +46 -0
- b4pt0r_the_framework-0.1.0/the_framework/server/api/__init__.py +1 -0
- b4pt0r_the_framework-0.1.0/the_framework/server/api/agent.py +168 -0
- b4pt0r_the_framework-0.1.0/the_framework/server/api/endpoints.py +513 -0
- b4pt0r_the_framework-0.1.0/the_framework/server/api/health.py +38 -0
- b4pt0r_the_framework-0.1.0/the_framework/server/api/media.py +15 -0
- b4pt0r_the_framework-0.1.0/the_framework/server/api/model_schema.py +59 -0
- b4pt0r_the_framework-0.1.0/the_framework/server/api/plugins.py +84 -0
- b4pt0r_the_framework-0.1.0/the_framework/server/api/surfaces.py +120 -0
- b4pt0r_the_framework-0.1.0/the_framework/server/api/transport.py +80 -0
- b4pt0r_the_framework-0.1.0/the_framework/server/api/uploads.py +139 -0
- b4pt0r_the_framework-0.1.0/the_framework/server/api/websockets.py +127 -0
- b4pt0r_the_framework-0.1.0/the_framework/server/clients/__init__.py +1 -0
- b4pt0r_the_framework-0.1.0/the_framework/server/clients/browser.py +497 -0
- b4pt0r_the_framework-0.1.0/the_framework/server/clients/browser_rpc.py +247 -0
- b4pt0r_the_framework-0.1.0/the_framework/server/clients/remote.py +1071 -0
- b4pt0r_the_framework-0.1.0/the_framework/server/clients/surfaces.py +418 -0
- b4pt0r_the_framework-0.1.0/the_framework/server/clients/tailscale.py +154 -0
- b4pt0r_the_framework-0.1.0/the_framework/server/composition/__init__.py +1 -0
- b4pt0r_the_framework-0.1.0/the_framework/server/composition/application.py +612 -0
- b4pt0r_the_framework-0.1.0/the_framework/server/composition/controls.py +46 -0
- b4pt0r_the_framework-0.1.0/the_framework/server/composition/dependencies.py +26 -0
- b4pt0r_the_framework-0.1.0/the_framework/server/composition/plugins.py +385 -0
- b4pt0r_the_framework-0.1.0/the_framework/server/composition/services.py +195 -0
- b4pt0r_the_framework-0.1.0/the_framework/server/runtime/__init__.py +1 -0
- b4pt0r_the_framework-0.1.0/the_framework/server/runtime/application.py +446 -0
- b4pt0r_the_framework-0.1.0/the_framework/server/runtime/bridge.py +309 -0
- b4pt0r_the_framework-0.1.0/the_framework/server/runtime/discovery.py +165 -0
- b4pt0r_the_framework-0.1.0/the_framework/server/runtime/fleet.py +658 -0
- b4pt0r_the_framework-0.1.0/the_framework/server/runtime/realtime.py +858 -0
- b4pt0r_the_framework-0.1.0/the_framework/server/runtime/supervisor.py +160 -0
- b4pt0r_the_framework-0.1.0/the_framework/utils/__init__.py +1 -0
- b4pt0r_the_framework-0.1.0/the_framework/utils/ids.py +7 -0
- b4pt0r_the_framework-0.1.0/the_framework/utils/persistence.py +76 -0
- b4pt0r_the_framework-0.1.0/the_framework/utils/tokens.py +97 -0
- b4pt0r_the_framework-0.1.0/uv.lock +1260 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Working on The Framework
|
|
2
|
+
|
|
3
|
+
The public Python package is `the_framework/`; `starter/` is an editable
|
|
4
|
+
example that uses it. Read [README.md](README.md) for the first-run path and
|
|
5
|
+
[docs/framework.md](docs/framework.md) for the composition API. This
|
|
6
|
+
file records the constraints to preserve when changing the framework.
|
|
7
|
+
|
|
8
|
+
## Ownership and contracts
|
|
9
|
+
|
|
10
|
+
- Keep application identity, instructions, policies and domain-specific
|
|
11
|
+
features outside `the_framework`. Dependencies point from applications to the
|
|
12
|
+
framework, never the reverse. The starter must depend on `the_framework`, not
|
|
13
|
+
on any particular application.
|
|
14
|
+
- An `AgentApplication` has one durable primary conversation. The worker is its
|
|
15
|
+
only history writer. Plugins may declare private specialist agents, but a
|
|
16
|
+
specialist must not write into primary history; results return through the
|
|
17
|
+
owning plugin or an ordered primary-agent input.
|
|
18
|
+
- The server owns authentication, routes, client connections and worker
|
|
19
|
+
supervision. Workers own inference, tools and their sessions. Clients own
|
|
20
|
+
their local interface and media/device execution. Do not move a
|
|
21
|
+
responsibility across these process boundaries merely to simplify a call.
|
|
22
|
+
- Treat saved sessions, task delivery, HTTP/WebSocket payloads and client
|
|
23
|
+
security as contracts. Preserve them when refactoring, or provide an explicit
|
|
24
|
+
tested migration. A client reconnection or worker restart must not create a
|
|
25
|
+
second main conversation or bypass safety controls.
|
|
26
|
+
- Plugins contribute through the framework's declarations and lifecycle, not
|
|
27
|
+
by mutating FastAPI internals or global registries. Loading a plugin is
|
|
28
|
+
separate from exposing its tools to an agent; server routes may remain
|
|
29
|
+
available when an agent binding is disabled.
|
|
30
|
+
|
|
31
|
+
## Making changes
|
|
32
|
+
|
|
33
|
+
- Keep the public API small and typed. Prefer improving an existing primitive
|
|
34
|
+
to adding a forwarding layer. Migrate internal callers when an internal API
|
|
35
|
+
changes rather than retaining obsolete aliases.
|
|
36
|
+
- Use `modict` for structured models where its mapping and validation features
|
|
37
|
+
fit. Inspect its API before adding a parallel model or conversion layer.
|
|
38
|
+
Backend-specific Responses behavior belongs at the `codex-backend-sdk`
|
|
39
|
+
boundary, not in ad hoc transport code elsewhere.
|
|
40
|
+
- Changes to shared dependencies such as `modict` or `codex-backend-sdk` must
|
|
41
|
+
remain generally useful and backward-compatible; test them in their own
|
|
42
|
+
repositories before relying on the change here.
|
|
43
|
+
- Keep the starter runnable from an installed wheel outside this checkout.
|
|
44
|
+
Its source and interface must remain editable application code, not hidden
|
|
45
|
+
framework policy.
|
|
46
|
+
|
|
47
|
+
## Verification
|
|
48
|
+
|
|
49
|
+
Add focused tests for the behavior being changed. Then run the framework suite:
|
|
50
|
+
|
|
51
|
+
```sh
|
|
52
|
+
uv sync --extra dev
|
|
53
|
+
uv run pytest -q tests/application tests/agentic
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
`tests/application/` covers observable contracts and includes wheel-only
|
|
57
|
+
checks. `tests/agentic/` covers internals that may evolve. For changes to the
|
|
58
|
+
starter UI, also run its npm tests and build as described in
|
|
59
|
+
[starter/README.md](starter/README.md).
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Notable changes to the Python distribution are recorded here. Versions follow
|
|
4
|
+
the distribution `b4pt0r-the-framework`; the import remains `the_framework`.
|
|
5
|
+
Until a stable release, minor versions may revise the public composition API.
|
|
6
|
+
|
|
7
|
+
## Unreleased
|
|
8
|
+
|
|
9
|
+
- No changes recorded yet.
|
|
10
|
+
|
|
11
|
+
## 0.1.0 - 2026-09-22
|
|
12
|
+
|
|
13
|
+
- Provide the `AgentApplication` composition API for one persistent primary
|
|
14
|
+
agent, server extensions, plugins, private specialists and client surfaces.
|
|
15
|
+
- Include the editable starter application and `the-framework bootstrap` CLI.
|
|
16
|
+
- Package typed Python modules and runtime resources with MIT licensing.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 B4PT0R
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: b4pt0r-the-framework
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Build persistent, extensible local agent applications with supervised workers and authenticated clients
|
|
5
|
+
Project-URL: Homepage, https://github.com/B4PT0R/the_framework
|
|
6
|
+
Project-URL: Documentation, https://github.com/B4PT0R/the_framework/blob/main/README.md
|
|
7
|
+
Project-URL: Repository, https://github.com/B4PT0R/the_framework
|
|
8
|
+
Project-URL: Changelog, https://github.com/B4PT0R/the_framework/blob/main/CHANGELOG.md
|
|
9
|
+
Project-URL: Issues, https://github.com/B4PT0R/the_framework/issues
|
|
10
|
+
Author: B4PT0R
|
|
11
|
+
License-Expression: MIT
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Keywords: agentic-applications,agents,fastapi,framework,plugins
|
|
14
|
+
Classifier: Development Status :: 3 - Alpha
|
|
15
|
+
Classifier: Framework :: FastAPI
|
|
16
|
+
Classifier: Intended Audience :: Developers
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
21
|
+
Classifier: Typing :: Typed
|
|
22
|
+
Requires-Python: >=3.12
|
|
23
|
+
Requires-Dist: codex-backend-sdk>=0.5.3
|
|
24
|
+
Requires-Dist: fastapi
|
|
25
|
+
Requires-Dist: httpx
|
|
26
|
+
Requires-Dist: jsonschema>=4.26.0
|
|
27
|
+
Requires-Dist: modict>=0.4.19
|
|
28
|
+
Requires-Dist: pillow
|
|
29
|
+
Requires-Dist: playwright
|
|
30
|
+
Requires-Dist: python-multipart
|
|
31
|
+
Requires-Dist: pyyaml
|
|
32
|
+
Requires-Dist: tiktoken
|
|
33
|
+
Requires-Dist: uvicorn
|
|
34
|
+
Requires-Dist: websockets
|
|
35
|
+
Provides-Extra: dev
|
|
36
|
+
Requires-Dist: httpx2>=2.0.0; extra == 'dev'
|
|
37
|
+
Requires-Dist: pytest; extra == 'dev'
|
|
38
|
+
Description-Content-Type: text/markdown
|
|
39
|
+
|
|
40
|
+
# The Framework
|
|
41
|
+
|
|
42
|
+
The Framework is a Python library for building applications around a persistent
|
|
43
|
+
AI agent. It supplies the parts that are easy to get wrong repeatedly: one
|
|
44
|
+
durable conversation, a supervised agent worker, plugin and specialist-agent
|
|
45
|
+
lifecycle, authenticated HTTP/WebSocket connections, and versioned web
|
|
46
|
+
interfaces. You supply the agent's identity, instructions, application
|
|
47
|
+
services, security policy and user experience.
|
|
48
|
+
|
|
49
|
+
You can use it for a local desktop companion, a private agent with tools and
|
|
50
|
+
memory, or another agent application whose browser and backend need to survive
|
|
51
|
+
worker restarts without losing the conversation. It is a library, not a hosted
|
|
52
|
+
agent service. The included [starter](https://github.com/B4PT0R/the_framework/blob/main/starter/README.md) is an editable
|
|
53
|
+
application that shows the pieces working together; you are free to build a
|
|
54
|
+
different frontend or none at all.
|
|
55
|
+
|
|
56
|
+
The PyPI distribution is named `b4pt0r-the-framework`. Python code imports
|
|
57
|
+
`the_framework`, and the template command is `the-framework`. Python 3.12 or
|
|
58
|
+
newer is required.
|
|
59
|
+
|
|
60
|
+
To install the published package in a virtual environment:
|
|
61
|
+
|
|
62
|
+
```sh
|
|
63
|
+
python3 -m venv .venv
|
|
64
|
+
. .venv/bin/activate
|
|
65
|
+
python -m pip install b4pt0r-the-framework
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
The Python wheel includes the framework and the editable starter template, but
|
|
69
|
+
not a prebuilt browser UI or Playwright's Chromium binary. Those are prepared
|
|
70
|
+
separately when you run the starter.
|
|
71
|
+
|
|
72
|
+
## What an application is made of
|
|
73
|
+
|
|
74
|
+
| Part | What it does | What your application decides |
|
|
75
|
+
| --- | --- | --- |
|
|
76
|
+
| `AgentApplication` | Validates and assembles one application | Name, version, plugins, server services, security and client surfaces |
|
|
77
|
+
| `AgentSpec` | Describes an agent and its session policy | Instructions, model configuration, tools and resources |
|
|
78
|
+
| `Plugin` / `PluginSpec` | Adds agent tools, context, hooks and optional server runtime | Which capabilities exist and when they are exposed |
|
|
79
|
+
| `Extension` / `@endpoint` | Starts services and exposes validated API routes | Application state, route schemas and authorization |
|
|
80
|
+
| `ClientSurface` | Builds, previews, publishes and rolls back an editable web UI | Source, build command, routes and release policy |
|
|
81
|
+
|
|
82
|
+
There is exactly **one primary, durable conversation**. Private specialist
|
|
83
|
+
agents can perform bounded background work, but their sessions are not new
|
|
84
|
+
user-facing conversations and they cannot edit the primary history directly.
|
|
85
|
+
The server supervises workers and owns authentication and client transport;
|
|
86
|
+
workers own inference and their own sessions; a browser client owns its local
|
|
87
|
+
interface and device/media execution. This separation lets a client reconnect
|
|
88
|
+
or refresh while the main conversation remains intact.
|
|
89
|
+
|
|
90
|
+
Plugins may provide agent-facing tools without a server runtime, or both. A
|
|
91
|
+
plugin's runtime state and its binding to an agent are separate: turning off its
|
|
92
|
+
tools for the agent need not remove routes that a settings screen still uses.
|
|
93
|
+
Specialists, durable task delivery and versioned public capabilities are
|
|
94
|
+
available when a simple plugin is not enough. More detail is in the
|
|
95
|
+
[framework guide](https://github.com/B4PT0R/the_framework/blob/main/docs/framework.md).
|
|
96
|
+
|
|
97
|
+
## Try a working application
|
|
98
|
+
|
|
99
|
+
Install [`uv`](https://docs.astral.sh/uv/) and Node.js/npm, then from this
|
|
100
|
+
checkout run:
|
|
101
|
+
|
|
102
|
+
```sh
|
|
103
|
+
uv sync
|
|
104
|
+
npm --prefix starter/ui ci
|
|
105
|
+
npm --prefix starter/ui run build
|
|
106
|
+
uv run playwright install chromium
|
|
107
|
+
uv run python -m starter
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Playwright Chromium also needs its system libraries; on Linux,
|
|
111
|
+
`uv run playwright install --with-deps chromium` can install them if you have
|
|
112
|
+
the required system permissions. The starter opens a local Chromium window with
|
|
113
|
+
chat, settings, file attachments and an editable React interface. Its server
|
|
114
|
+
listens on loopback and authenticates the browser. You can inspect the UI and
|
|
115
|
+
settings without model credentials; generating replies, using hosted search or
|
|
116
|
+
embeddings, and voice features require a usable account/capabilities through
|
|
117
|
+
`codex-backend-sdk`. The [starter guide](https://github.com/B4PT0R/the_framework/blob/main/starter/README.md) covers sign-in,
|
|
118
|
+
data storage and feature-by-feature behavior.
|
|
119
|
+
|
|
120
|
+
To make an independent, editable copy, run `the-framework bootstrap` in the
|
|
121
|
+
environment where you installed the package. From this checkout, prefix it
|
|
122
|
+
with `uv run`:
|
|
123
|
+
|
|
124
|
+
```sh
|
|
125
|
+
uv run the-framework bootstrap --code-dir /path/to/my-agent-code --data-dir /path/to/my-agent-data
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Both directories must be empty or absent, distinct and non-overlapping. The
|
|
129
|
+
command copies the starter source and records the private data location; it
|
|
130
|
+
does not install npm dependencies, build the UI or launch the app. From the new
|
|
131
|
+
code directory, run `npm --prefix starter/ui ci`,
|
|
132
|
+
`npm --prefix starter/ui run build`, then `python -m starter` in an environment
|
|
133
|
+
with `b4pt0r-the-framework` installed. Change `starter/application.py` and
|
|
134
|
+
`starter/instructions.md` first; `starter/ui/` contains the editable interface.
|
|
135
|
+
Keep the data directory private: it holds conversation history, configuration,
|
|
136
|
+
uploads, memory and browser profiles.
|
|
137
|
+
|
|
138
|
+
## Build a small application yourself
|
|
139
|
+
|
|
140
|
+
Save the following as `example.py`. It is a complete HTTP application; the
|
|
141
|
+
repository also includes an [expanded version](https://github.com/B4PT0R/the_framework/blob/main/examples/minimal_agent_app.py)
|
|
142
|
+
with `modict` request/response models and a health endpoint.
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
from the_framework import AgentApplication, AgentSpec, Extension, SessionPolicy, endpoint
|
|
146
|
+
from the_framework.server.api.endpoints import Principal
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
class BearerSecurity:
|
|
150
|
+
async def authenticate(self, request):
|
|
151
|
+
if request.headers.get("authorization") != "Bearer example-secret":
|
|
152
|
+
return None
|
|
153
|
+
return Principal(id="example-client", scopes=frozenset({"counter:write"}))
|
|
154
|
+
|
|
155
|
+
async def authorize(self, principal, requirement, request):
|
|
156
|
+
return requirement is None or requirement.get("scope") in principal.scopes
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
class Counter:
|
|
160
|
+
def __init__(self):
|
|
161
|
+
self.value = 0
|
|
162
|
+
self.running = False
|
|
163
|
+
|
|
164
|
+
async def start(self):
|
|
165
|
+
self.running = True
|
|
166
|
+
|
|
167
|
+
async def stop(self):
|
|
168
|
+
self.running = False
|
|
169
|
+
|
|
170
|
+
@endpoint(
|
|
171
|
+
"post", "/api/v1/counter/increment",
|
|
172
|
+
request={"type": "object", "properties": {"amount": {"type": "integer"}},
|
|
173
|
+
"required": ["amount"], "additionalProperties": False},
|
|
174
|
+
response={"type": "object", "properties": {"value": {"type": "integer"}},
|
|
175
|
+
"required": ["value"]},
|
|
176
|
+
authorization={"scope": "counter:write"},
|
|
177
|
+
)
|
|
178
|
+
def increment(self, amount: int):
|
|
179
|
+
"""Increment the application counter."""
|
|
180
|
+
self.value += amount
|
|
181
|
+
return {"value": self.value}
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
counter = Counter()
|
|
185
|
+
application = AgentApplication(
|
|
186
|
+
name="Counter Agent",
|
|
187
|
+
version="0.1",
|
|
188
|
+
primary_agent=AgentSpec(
|
|
189
|
+
name="assistant",
|
|
190
|
+
description="The application's primary agent",
|
|
191
|
+
session=SessionPolicy.durable(),
|
|
192
|
+
),
|
|
193
|
+
security=BearerSecurity(),
|
|
194
|
+
extensions=(Extension(name="counter", service=counter,
|
|
195
|
+
endpoints=(counter.increment,)),),
|
|
196
|
+
)
|
|
197
|
+
app = application.build()
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Start it with:
|
|
201
|
+
|
|
202
|
+
```sh
|
|
203
|
+
uv run uvicorn example:app --host 127.0.0.1 --port 8000
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Then, in another terminal:
|
|
207
|
+
|
|
208
|
+
```sh
|
|
209
|
+
curl -sS -X POST http://127.0.0.1:8000/api/v1/counter/increment \
|
|
210
|
+
-H 'Authorization: Bearer example-secret' \
|
|
211
|
+
-H 'Content-Type: application/json' \
|
|
212
|
+
-d '{"amount": 2}'
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
The result is `{"value":2}`. The literal bearer secret is **only** for this
|
|
216
|
+
loopback demonstration; use a real authentication policy for an application.
|
|
217
|
+
The primary agent declaration alone does not create a chat API or start
|
|
218
|
+
inference: the starter shows how to add its supervised worker and client
|
|
219
|
+
transport. `@endpoint` validates request and response data and contributes an
|
|
220
|
+
OpenAPI schema. `Extension` manages dependencies and service startup/shutdown;
|
|
221
|
+
`AgentApplication.compile()` checks the full graph before runtime startup.
|
|
222
|
+
|
|
223
|
+
For the next step, read [composition and runtime](https://github.com/B4PT0R/the_framework/blob/main/docs/framework.md) for
|
|
224
|
+
plugins, private specialists, persistent resources, security, voice and client
|
|
225
|
+
surfaces. The [starter source](https://github.com/B4PT0R/the_framework/tree/main/starter) shows these features in one application
|
|
226
|
+
without requiring you to adopt its UI design.
|
|
227
|
+
|
|
228
|
+
## Develop and package
|
|
229
|
+
|
|
230
|
+
```sh
|
|
231
|
+
uv sync --extra dev
|
|
232
|
+
uv run pytest -q tests/application tests/agentic
|
|
233
|
+
uv build
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
The build produces a wheel and source archive in `dist/`. The wheel contains
|
|
237
|
+
the typed `the_framework` package, runtime prompts and the editable starter
|
|
238
|
+
template; it does **not** bundle Node modules or a prebuilt browser UI. The
|
|
239
|
+
test suite includes a wheel-only import/bootstrap check outside the checkout.
|
|
240
|
+
For UI changes, also run `npm --prefix starter/ui test` and
|
|
241
|
+
`npm --prefix starter/ui run build`.
|
|
242
|
+
|
|
243
|
+
This repository is [MIT licensed](https://github.com/B4PT0R/the_framework/blob/main/LICENSE). See the [changelog](https://github.com/B4PT0R/the_framework/blob/main/CHANGELOG.md)
|
|
244
|
+
for version notes. Publishing to PyPI is a separate release action; building
|
|
245
|
+
locally does not publish anything.
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# The Framework
|
|
2
|
+
|
|
3
|
+
The Framework is a Python library for building applications around a persistent
|
|
4
|
+
AI agent. It supplies the parts that are easy to get wrong repeatedly: one
|
|
5
|
+
durable conversation, a supervised agent worker, plugin and specialist-agent
|
|
6
|
+
lifecycle, authenticated HTTP/WebSocket connections, and versioned web
|
|
7
|
+
interfaces. You supply the agent's identity, instructions, application
|
|
8
|
+
services, security policy and user experience.
|
|
9
|
+
|
|
10
|
+
You can use it for a local desktop companion, a private agent with tools and
|
|
11
|
+
memory, or another agent application whose browser and backend need to survive
|
|
12
|
+
worker restarts without losing the conversation. It is a library, not a hosted
|
|
13
|
+
agent service. The included [starter](https://github.com/B4PT0R/the_framework/blob/main/starter/README.md) is an editable
|
|
14
|
+
application that shows the pieces working together; you are free to build a
|
|
15
|
+
different frontend or none at all.
|
|
16
|
+
|
|
17
|
+
The PyPI distribution is named `b4pt0r-the-framework`. Python code imports
|
|
18
|
+
`the_framework`, and the template command is `the-framework`. Python 3.12 or
|
|
19
|
+
newer is required.
|
|
20
|
+
|
|
21
|
+
To install the published package in a virtual environment:
|
|
22
|
+
|
|
23
|
+
```sh
|
|
24
|
+
python3 -m venv .venv
|
|
25
|
+
. .venv/bin/activate
|
|
26
|
+
python -m pip install b4pt0r-the-framework
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
The Python wheel includes the framework and the editable starter template, but
|
|
30
|
+
not a prebuilt browser UI or Playwright's Chromium binary. Those are prepared
|
|
31
|
+
separately when you run the starter.
|
|
32
|
+
|
|
33
|
+
## What an application is made of
|
|
34
|
+
|
|
35
|
+
| Part | What it does | What your application decides |
|
|
36
|
+
| --- | --- | --- |
|
|
37
|
+
| `AgentApplication` | Validates and assembles one application | Name, version, plugins, server services, security and client surfaces |
|
|
38
|
+
| `AgentSpec` | Describes an agent and its session policy | Instructions, model configuration, tools and resources |
|
|
39
|
+
| `Plugin` / `PluginSpec` | Adds agent tools, context, hooks and optional server runtime | Which capabilities exist and when they are exposed |
|
|
40
|
+
| `Extension` / `@endpoint` | Starts services and exposes validated API routes | Application state, route schemas and authorization |
|
|
41
|
+
| `ClientSurface` | Builds, previews, publishes and rolls back an editable web UI | Source, build command, routes and release policy |
|
|
42
|
+
|
|
43
|
+
There is exactly **one primary, durable conversation**. Private specialist
|
|
44
|
+
agents can perform bounded background work, but their sessions are not new
|
|
45
|
+
user-facing conversations and they cannot edit the primary history directly.
|
|
46
|
+
The server supervises workers and owns authentication and client transport;
|
|
47
|
+
workers own inference and their own sessions; a browser client owns its local
|
|
48
|
+
interface and device/media execution. This separation lets a client reconnect
|
|
49
|
+
or refresh while the main conversation remains intact.
|
|
50
|
+
|
|
51
|
+
Plugins may provide agent-facing tools without a server runtime, or both. A
|
|
52
|
+
plugin's runtime state and its binding to an agent are separate: turning off its
|
|
53
|
+
tools for the agent need not remove routes that a settings screen still uses.
|
|
54
|
+
Specialists, durable task delivery and versioned public capabilities are
|
|
55
|
+
available when a simple plugin is not enough. More detail is in the
|
|
56
|
+
[framework guide](https://github.com/B4PT0R/the_framework/blob/main/docs/framework.md).
|
|
57
|
+
|
|
58
|
+
## Try a working application
|
|
59
|
+
|
|
60
|
+
Install [`uv`](https://docs.astral.sh/uv/) and Node.js/npm, then from this
|
|
61
|
+
checkout run:
|
|
62
|
+
|
|
63
|
+
```sh
|
|
64
|
+
uv sync
|
|
65
|
+
npm --prefix starter/ui ci
|
|
66
|
+
npm --prefix starter/ui run build
|
|
67
|
+
uv run playwright install chromium
|
|
68
|
+
uv run python -m starter
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Playwright Chromium also needs its system libraries; on Linux,
|
|
72
|
+
`uv run playwright install --with-deps chromium` can install them if you have
|
|
73
|
+
the required system permissions. The starter opens a local Chromium window with
|
|
74
|
+
chat, settings, file attachments and an editable React interface. Its server
|
|
75
|
+
listens on loopback and authenticates the browser. You can inspect the UI and
|
|
76
|
+
settings without model credentials; generating replies, using hosted search or
|
|
77
|
+
embeddings, and voice features require a usable account/capabilities through
|
|
78
|
+
`codex-backend-sdk`. The [starter guide](https://github.com/B4PT0R/the_framework/blob/main/starter/README.md) covers sign-in,
|
|
79
|
+
data storage and feature-by-feature behavior.
|
|
80
|
+
|
|
81
|
+
To make an independent, editable copy, run `the-framework bootstrap` in the
|
|
82
|
+
environment where you installed the package. From this checkout, prefix it
|
|
83
|
+
with `uv run`:
|
|
84
|
+
|
|
85
|
+
```sh
|
|
86
|
+
uv run the-framework bootstrap --code-dir /path/to/my-agent-code --data-dir /path/to/my-agent-data
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Both directories must be empty or absent, distinct and non-overlapping. The
|
|
90
|
+
command copies the starter source and records the private data location; it
|
|
91
|
+
does not install npm dependencies, build the UI or launch the app. From the new
|
|
92
|
+
code directory, run `npm --prefix starter/ui ci`,
|
|
93
|
+
`npm --prefix starter/ui run build`, then `python -m starter` in an environment
|
|
94
|
+
with `b4pt0r-the-framework` installed. Change `starter/application.py` and
|
|
95
|
+
`starter/instructions.md` first; `starter/ui/` contains the editable interface.
|
|
96
|
+
Keep the data directory private: it holds conversation history, configuration,
|
|
97
|
+
uploads, memory and browser profiles.
|
|
98
|
+
|
|
99
|
+
## Build a small application yourself
|
|
100
|
+
|
|
101
|
+
Save the following as `example.py`. It is a complete HTTP application; the
|
|
102
|
+
repository also includes an [expanded version](https://github.com/B4PT0R/the_framework/blob/main/examples/minimal_agent_app.py)
|
|
103
|
+
with `modict` request/response models and a health endpoint.
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
from the_framework import AgentApplication, AgentSpec, Extension, SessionPolicy, endpoint
|
|
107
|
+
from the_framework.server.api.endpoints import Principal
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
class BearerSecurity:
|
|
111
|
+
async def authenticate(self, request):
|
|
112
|
+
if request.headers.get("authorization") != "Bearer example-secret":
|
|
113
|
+
return None
|
|
114
|
+
return Principal(id="example-client", scopes=frozenset({"counter:write"}))
|
|
115
|
+
|
|
116
|
+
async def authorize(self, principal, requirement, request):
|
|
117
|
+
return requirement is None or requirement.get("scope") in principal.scopes
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
class Counter:
|
|
121
|
+
def __init__(self):
|
|
122
|
+
self.value = 0
|
|
123
|
+
self.running = False
|
|
124
|
+
|
|
125
|
+
async def start(self):
|
|
126
|
+
self.running = True
|
|
127
|
+
|
|
128
|
+
async def stop(self):
|
|
129
|
+
self.running = False
|
|
130
|
+
|
|
131
|
+
@endpoint(
|
|
132
|
+
"post", "/api/v1/counter/increment",
|
|
133
|
+
request={"type": "object", "properties": {"amount": {"type": "integer"}},
|
|
134
|
+
"required": ["amount"], "additionalProperties": False},
|
|
135
|
+
response={"type": "object", "properties": {"value": {"type": "integer"}},
|
|
136
|
+
"required": ["value"]},
|
|
137
|
+
authorization={"scope": "counter:write"},
|
|
138
|
+
)
|
|
139
|
+
def increment(self, amount: int):
|
|
140
|
+
"""Increment the application counter."""
|
|
141
|
+
self.value += amount
|
|
142
|
+
return {"value": self.value}
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
counter = Counter()
|
|
146
|
+
application = AgentApplication(
|
|
147
|
+
name="Counter Agent",
|
|
148
|
+
version="0.1",
|
|
149
|
+
primary_agent=AgentSpec(
|
|
150
|
+
name="assistant",
|
|
151
|
+
description="The application's primary agent",
|
|
152
|
+
session=SessionPolicy.durable(),
|
|
153
|
+
),
|
|
154
|
+
security=BearerSecurity(),
|
|
155
|
+
extensions=(Extension(name="counter", service=counter,
|
|
156
|
+
endpoints=(counter.increment,)),),
|
|
157
|
+
)
|
|
158
|
+
app = application.build()
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Start it with:
|
|
162
|
+
|
|
163
|
+
```sh
|
|
164
|
+
uv run uvicorn example:app --host 127.0.0.1 --port 8000
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Then, in another terminal:
|
|
168
|
+
|
|
169
|
+
```sh
|
|
170
|
+
curl -sS -X POST http://127.0.0.1:8000/api/v1/counter/increment \
|
|
171
|
+
-H 'Authorization: Bearer example-secret' \
|
|
172
|
+
-H 'Content-Type: application/json' \
|
|
173
|
+
-d '{"amount": 2}'
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
The result is `{"value":2}`. The literal bearer secret is **only** for this
|
|
177
|
+
loopback demonstration; use a real authentication policy for an application.
|
|
178
|
+
The primary agent declaration alone does not create a chat API or start
|
|
179
|
+
inference: the starter shows how to add its supervised worker and client
|
|
180
|
+
transport. `@endpoint` validates request and response data and contributes an
|
|
181
|
+
OpenAPI schema. `Extension` manages dependencies and service startup/shutdown;
|
|
182
|
+
`AgentApplication.compile()` checks the full graph before runtime startup.
|
|
183
|
+
|
|
184
|
+
For the next step, read [composition and runtime](https://github.com/B4PT0R/the_framework/blob/main/docs/framework.md) for
|
|
185
|
+
plugins, private specialists, persistent resources, security, voice and client
|
|
186
|
+
surfaces. The [starter source](https://github.com/B4PT0R/the_framework/tree/main/starter) shows these features in one application
|
|
187
|
+
without requiring you to adopt its UI design.
|
|
188
|
+
|
|
189
|
+
## Develop and package
|
|
190
|
+
|
|
191
|
+
```sh
|
|
192
|
+
uv sync --extra dev
|
|
193
|
+
uv run pytest -q tests/application tests/agentic
|
|
194
|
+
uv build
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
The build produces a wheel and source archive in `dist/`. The wheel contains
|
|
198
|
+
the typed `the_framework` package, runtime prompts and the editable starter
|
|
199
|
+
template; it does **not** bundle Node modules or a prebuilt browser UI. The
|
|
200
|
+
test suite includes a wheel-only import/bootstrap check outside the checkout.
|
|
201
|
+
For UI changes, also run `npm --prefix starter/ui test` and
|
|
202
|
+
`npm --prefix starter/ui run build`.
|
|
203
|
+
|
|
204
|
+
This repository is [MIT licensed](https://github.com/B4PT0R/the_framework/blob/main/LICENSE). See the [changelog](https://github.com/B4PT0R/the_framework/blob/main/CHANGELOG.md)
|
|
205
|
+
for version notes. Publishing to PyPI is a separate release action; building
|
|
206
|
+
locally does not publish anything.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Framework API simplification
|
|
2
|
+
|
|
3
|
+
## Decisions and evidence
|
|
4
|
+
|
|
5
|
+
| Objective | Result | Regression coverage |
|
|
6
|
+
| --- | --- | --- |
|
|
7
|
+
| One agent declaration | `AgentSpec` owns configuration, instructions, plugins, session/queue policy and completion settings. `agent_trigger(spec, ...)` owns selection and result handling only. | `test_agent_spec.py`, `test_framework.py`, worker/fleet tests |
|
|
8
|
+
| Internal wire representation | `WorkerProfile` remains a JSON execution payload, not a public facade export or a second source retained in AgentSpec. Older profile configuration fields are read at the worker boundary. | profile round trips, native coercion, real worker process tests |
|
|
9
|
+
| Explicit construction | `AgentResources` replaces implicit option dictionaries and parallel build keywords. Explicit resources bypass the factory completely. | factory identity, defaults, invalid contracts, configuration persistence tests |
|
|
10
|
+
| Concise plugin installation | Plugin classes with an explicit name normalize to PluginSpec; full declarations retain policies, dependencies and services. | shorthand/full-form discovery, duplicate identities, no construction during compilation |
|
|
11
|
+
| Lifecycle simplicity | Existing Extension start/stop adapters suffice. Permanent restart callback composition happens at construction; absent restart remains absent. No new manager or lifecycle abstraction. | `test_runtime_composition.py`, service rollback and runtime shutdown tests |
|
|
12
|
+
| Model endpoint contracts | Request/response modict classes work alongside explicit JSON Schema. Native validators/defaults are applied at the existing HTTP boundary; field metadata supplies OpenAPI. | `test_endpoint_models.py`, endpoint registry, minimal application tests |
|
|
13
|
+
|
|
14
|
+
The actual product migrated its primary construction, simple plugin declarations,
|
|
15
|
+
memory curator and visual specialists. The minimal standalone application uses
|
|
16
|
+
model-based endpoint contracts. No application-specific policy was added to the
|
|
17
|
+
core, and no Pydantic DTO or alternate dispatch path was introduced.
|
|
18
|
+
|
|
19
|
+
## Deliberate limits
|
|
20
|
+
|
|
21
|
+
Final verification: `pytest -q --tb=short tests/application tests/agentic` reports
|
|
22
|
+
**900 passed**. This includes the isolated wheel and real worker subprocess
|
|
23
|
+
tests. The product compiles 14 plugins and 10 agents. Ruff's F401/F811/F821/F822/
|
|
24
|
+
F823/E9 checks and `git diff --check` pass for the changed core and endpoint tests.
|
|
25
|
+
|
|
26
|
+
- OpenAPI projection describes JSON field types, required fields and extra-field
|
|
27
|
+
policy. It does not reverse-engineer Python validators or execute factories.
|
|
28
|
+
Unsupported/recursive hints require an explicit JSON Schema. Runtime model
|
|
29
|
+
validation remains authoritative for custom constraints.
|
|
30
|
+
- A wire profile cannot serialize Python closures or application services.
|
|
31
|
+
Application-backed workers continue resolving the original namespaced spec.
|
|
32
|
+
- This work verifies source, transports and packaging with automated tests.
|
|
33
|
+
It does not claim a production restart, real inference, voice or device run.
|
|
34
|
+
- No server restart, publish or push was performed for this goal.
|
|
35
|
+
|
|
36
|
+
The follow-ups already recorded in TODO.md remain separate from this API work:
|
|
37
|
+
YAML declaration errors, grouping usage records, and older architecture wording.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Framework clarification follow-up
|
|
2
|
+
|
|
3
|
+
## Changes and verification boundaries
|
|
4
|
+
|
|
5
|
+
- Usage payloads (`ResponseUsage`, `TokenDetails`) live in `agent/models/usage.py`.
|
|
6
|
+
The session store imports that owner, not the context builder. Public agent
|
|
7
|
+
exports remain; internal callers were migrated without compatibility aliases.
|
|
8
|
+
Recovery, coercion, session and context tests cover the unchanged behavior.
|
|
9
|
+
- Invalid YAML raises a contextual `ValueError` naming the declaring callable
|
|
10
|
+
and YAML location, with the parser exception chained. Invalid metadata shapes
|
|
11
|
+
no longer disappear through falsey fallback. Plain descriptions and empty
|
|
12
|
+
docstrings remain supported. Both tool and endpoint construction are tested.
|
|
13
|
+
- AGENTS.md now describes distributed capability ownership and authenticated
|
|
14
|
+
remote clients, rather than a local-desktop-only runtime. Evidence:
|
|
15
|
+
`server/clients/remote.py`, `the_harness/remote_composition.py`,
|
|
16
|
+
`docs/remote-client-protocol.md`, and `test_client_remote.py` (exclusive leases,
|
|
17
|
+
revocation, stale generations and remote ownership without local Chromium).
|
|
18
|
+
- Memory instructions now distinguish temporary working capacity from completion
|
|
19
|
+
constraints, omit the obsolete entry-count cap and describe deferred embedding.
|
|
20
|
+
Evidence: `plugins/memory/store.py::_validate_capacity`,
|
|
21
|
+
`plugins/memory/curator.py::completion_constraint_error` and `complete_curation`,
|
|
22
|
+
plus memory tests for soft capacity, reduction beyond hard capacity, deferred
|
|
23
|
+
embeddings and completion repair. No runtime policy or personal data changed.
|
|
24
|
+
|
|
25
|
+
## Schema comparison: deliberate non-extraction
|
|
26
|
+
|
|
27
|
+
Tools and signature-derived endpoints already share `signature_parameters` and
|
|
28
|
+
`annotation_schema`. The separate HTTP model projection reads modict field
|
|
29
|
+
metadata, defaults and required/extra policy; it never executes default factories.
|
|
30
|
+
The modict README field and configuration contracts were checked locally.
|
|
31
|
+
|
|
32
|
+
The remaining visitors overlap on scalar/list/union syntax, but differ in real
|
|
33
|
+
contracts: callable annotation inference is best-effort and accepts tuple/set
|
|
34
|
+
shapes, whereas explicit HTTP model contracts reject unsupported hints, non-string
|
|
35
|
+
mapping keys and recursive models rather than silently understating validation.
|
|
36
|
+
Combining them now would add policy switches or callbacks to a small visitor.
|
|
37
|
+
No new generic abstraction is introduced solely to deduplicate those branches.
|
|
38
|
+
|
|
39
|
+
Comparison did uncover a nullable-enum defect in callable projection: adding null
|
|
40
|
+
to `type` while preserving a non-null `enum` still excludes null. Union projection
|
|
41
|
+
now uses `anyOf` for constrained branches. A JSON Schema behavior test verifies
|
|
42
|
+
null and declared enum members are accepted, but arbitrary values are rejected.
|
|
43
|
+
|
|
44
|
+
No SDK/modict patch, publication, server restart or deployment was needed.
|
|
45
|
+
|
|
46
|
+
## Final verification
|
|
47
|
+
|
|
48
|
+
`pytest -q --tb=short tests/application tests/agentic`: **914 passed**,
|
|
49
|
+
including isolated-wheel imports and worker-process tests. Focused Ruff checks
|
|
50
|
+
(F401/F811/F821/F822/F823/E9) and `git diff --check` pass. The nullable contracts
|
|
51
|
+
are tested by accepted/rejected values rather than a prescribed JSON layout.
|