runspace 0.2.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.
- runspace-0.2.0/.github/ISSUE_TEMPLATE/bug_report.yml +40 -0
- runspace-0.2.0/.github/ISSUE_TEMPLATE/config.yml +5 -0
- runspace-0.2.0/.github/ISSUE_TEMPLATE/feature_request.yml +23 -0
- runspace-0.2.0/.github/PULL_REQUEST_TEMPLATE.md +15 -0
- runspace-0.2.0/.github/workflows/release.yml +52 -0
- runspace-0.2.0/.github/workflows/tests.yml +129 -0
- runspace-0.2.0/.gitignore +33 -0
- runspace-0.2.0/CHANGELOG.md +156 -0
- runspace-0.2.0/CLAUDE.md +82 -0
- runspace-0.2.0/CODE_OF_CONDUCT.md +42 -0
- runspace-0.2.0/CONTRIBUTING.md +55 -0
- runspace-0.2.0/LICENSE +202 -0
- runspace-0.2.0/NOTICE +17 -0
- runspace-0.2.0/PKG-INFO +297 -0
- runspace-0.2.0/README.md +208 -0
- runspace-0.2.0/SECURITY.md +36 -0
- runspace-0.2.0/conftest.py +55 -0
- runspace-0.2.0/docs/4-RUNTIME-RECIPE.md +393 -0
- runspace-0.2.0/docs/AGENT_CREATION_GUIDE.md +190 -0
- runspace-0.2.0/docs/NEW_APP_BOILERPLATE.md +197 -0
- runspace-0.2.0/docs/PUBLISHING.md +160 -0
- runspace-0.2.0/docs/VISION_GUIDE.md +179 -0
- runspace-0.2.0/docs/WEB_CRAWLING_GUIDE.md +148 -0
- runspace-0.2.0/docs/adr/0001-adapter-pattern.md +251 -0
- runspace-0.2.0/docs/adr/0002-mcp-ui-block-integrity.md +91 -0
- runspace-0.2.0/examples/grid/README.md +57 -0
- runspace-0.2.0/examples/grid/agents/_grid.py +95 -0
- runspace-0.2.0/examples/grid/agents/analyst/SOUL.md +44 -0
- runspace-0.2.0/examples/grid/agents/analyst/tools/grid.py +163 -0
- runspace-0.2.0/examples/grid/routines.yml +31 -0
- runspace-0.2.0/examples/grid/workspace.yml +21 -0
- runspace-0.2.0/pyproject.toml +182 -0
- runspace-0.2.0/scripts/agent_smoke.py +363 -0
- runspace-0.2.0/scripts/agents_inspect.py +194 -0
- runspace-0.2.0/scripts/render_tool_docs.py +180 -0
- runspace-0.2.0/scripts/tests/__init__.py +0 -0
- runspace-0.2.0/scripts/tests/test_agent_smoke.py +376 -0
- runspace-0.2.0/scripts/tests/test_agents_inspect.py +148 -0
- runspace-0.2.0/scripts/tests/test_render_tool_docs.py +150 -0
- runspace-0.2.0/scripts/tests/test_tools_diff.py +293 -0
- runspace-0.2.0/scripts/tools_diff.py +267 -0
- runspace-0.2.0/scripts/tools_usage.py +148 -0
- runspace-0.2.0/src/runspace/__init__.py +11 -0
- runspace-0.2.0/src/runspace/contracts/__init__.py +69 -0
- runspace-0.2.0/src/runspace/contracts/chat.py +80 -0
- runspace-0.2.0/src/runspace/contracts/runtime.py +94 -0
- runspace-0.2.0/src/runspace/contracts/scheduling.py +239 -0
- runspace-0.2.0/src/runspace/contracts/tests/__init__.py +0 -0
- runspace-0.2.0/src/runspace/contracts/tests/test_chat.py +77 -0
- runspace-0.2.0/src/runspace/contracts/tests/test_no_runtime_leaks.py +174 -0
- runspace-0.2.0/src/runspace/contracts/tests/test_runtime.py +62 -0
- runspace-0.2.0/src/runspace/contracts/tests/test_scheduling.py +99 -0
- runspace-0.2.0/src/runspace/contracts/tests/test_tool.py +93 -0
- runspace-0.2.0/src/runspace/contracts/tests/test_workspace.py +97 -0
- runspace-0.2.0/src/runspace/contracts/tool.py +68 -0
- runspace-0.2.0/src/runspace/contracts/workspace.py +91 -0
- runspace-0.2.0/src/runspace/helpers/__init__.py +0 -0
- runspace-0.2.0/src/runspace/helpers/bootstrap.py +257 -0
- runspace-0.2.0/src/runspace/helpers/documents/__init__.py +0 -0
- runspace-0.2.0/src/runspace/helpers/documents/article_reader.py +290 -0
- runspace-0.2.0/src/runspace/helpers/documents/branded_pdf.py +244 -0
- runspace-0.2.0/src/runspace/helpers/documents/store.py +113 -0
- runspace-0.2.0/src/runspace/helpers/messaging/__init__.py +0 -0
- runspace-0.2.0/src/runspace/helpers/messaging/messages.py +32 -0
- runspace-0.2.0/src/runspace/helpers/session/__init__.py +0 -0
- runspace-0.2.0/src/runspace/helpers/session/store.py +102 -0
- runspace-0.2.0/src/runspace/helpers/supabase_db.py +161 -0
- runspace-0.2.0/src/runspace/helpers/supabase_exec_sql.sql +42 -0
- runspace-0.2.0/src/runspace/helpers/web_crawler/__init__.py +40 -0
- runspace-0.2.0/src/runspace/helpers/web_crawler/core.py +292 -0
- runspace-0.2.0/src/runspace/ingestion/README.md +67 -0
- runspace-0.2.0/src/runspace/ingestion/__init__.py +39 -0
- runspace-0.2.0/src/runspace/ingestion/_redact.py +29 -0
- runspace-0.2.0/src/runspace/ingestion/_render.py +267 -0
- runspace-0.2.0/src/runspace/ingestion/buffer.py +126 -0
- runspace-0.2.0/src/runspace/ingestion/pairing.py +378 -0
- runspace-0.2.0/src/runspace/ingestion/polling.py +299 -0
- runspace-0.2.0/src/runspace/ingestion/routes.py +69 -0
- runspace-0.2.0/src/runspace/ingestion/telegram.py +1299 -0
- runspace-0.2.0/src/runspace/ingestion/transport.py +184 -0
- runspace-0.2.0/src/runspace/protocols/README.md +119 -0
- runspace-0.2.0/src/runspace/protocols/__init__.py +133 -0
- runspace-0.2.0/src/runspace/protocols/clock.py +92 -0
- runspace-0.2.0/src/runspace/protocols/config.py +342 -0
- runspace-0.2.0/src/runspace/protocols/conversations/__init__.py +32 -0
- runspace-0.2.0/src/runspace/protocols/conversations/in_memory.py +121 -0
- runspace-0.2.0/src/runspace/protocols/conversations/models.py +66 -0
- runspace-0.2.0/src/runspace/protocols/conversations/protocol.py +71 -0
- runspace-0.2.0/src/runspace/protocols/conversations/schema.sql +35 -0
- runspace-0.2.0/src/runspace/protocols/conversations/supabase_conversations.py +187 -0
- runspace-0.2.0/src/runspace/protocols/embeddings/__init__.py +30 -0
- runspace-0.2.0/src/runspace/protocols/embeddings/fixture.py +65 -0
- runspace-0.2.0/src/runspace/protocols/embeddings/openai_compat.py +48 -0
- runspace-0.2.0/src/runspace/protocols/embeddings/protocol.py +52 -0
- runspace-0.2.0/src/runspace/protocols/file_storage/__init__.py +37 -0
- runspace-0.2.0/src/runspace/protocols/file_storage/local.py +165 -0
- runspace-0.2.0/src/runspace/protocols/file_storage/protocol.py +78 -0
- runspace-0.2.0/src/runspace/protocols/file_storage/supabase.py +146 -0
- runspace-0.2.0/src/runspace/protocols/prompt/__init__.py +25 -0
- runspace-0.2.0/src/runspace/protocols/prompt/envelope.py +49 -0
- runspace-0.2.0/src/runspace/protocols/prompt/flatten.py +124 -0
- runspace-0.2.0/src/runspace/protocols/prompt/tests/__init__.py +0 -0
- runspace-0.2.0/src/runspace/protocols/prompt/tests/test_envelope.py +45 -0
- runspace-0.2.0/src/runspace/protocols/prompt/tests/test_flatten.py +71 -0
- runspace-0.2.0/src/runspace/protocols/prompt/tests/test_real_tenants.py +132 -0
- runspace-0.2.0/src/runspace/protocols/registry.py +146 -0
- runspace-0.2.0/src/runspace/protocols/sandbox_lint.py +126 -0
- runspace-0.2.0/src/runspace/protocols/store/__init__.py +15 -0
- runspace-0.2.0/src/runspace/protocols/store/file_store.py +134 -0
- runspace-0.2.0/src/runspace/protocols/store/in_memory.py +82 -0
- runspace-0.2.0/src/runspace/protocols/store/protocol.py +58 -0
- runspace-0.2.0/src/runspace/protocols/store/supabase_store.py +106 -0
- runspace-0.2.0/src/runspace/protocols/tests/__init__.py +0 -0
- runspace-0.2.0/src/runspace/protocols/tests/fixtures/vision/sample_invoice.jpg +0 -0
- runspace-0.2.0/src/runspace/protocols/tests/fixtures/vision/sample_invoice.json +10 -0
- runspace-0.2.0/src/runspace/protocols/tests/test_clock.py +153 -0
- runspace-0.2.0/src/runspace/protocols/tests/test_codex_vision_pdf.py +104 -0
- runspace-0.2.0/src/runspace/protocols/tests/test_config.py +263 -0
- runspace-0.2.0/src/runspace/protocols/tests/test_e2e_agent_flow.py +205 -0
- runspace-0.2.0/src/runspace/protocols/tests/test_embeddings.py +233 -0
- runspace-0.2.0/src/runspace/protocols/tests/test_file_inbox_transport.py +151 -0
- runspace-0.2.0/src/runspace/protocols/tests/test_file_storage.py +139 -0
- runspace-0.2.0/src/runspace/protocols/tests/test_file_storage_property.py +150 -0
- runspace-0.2.0/src/runspace/protocols/tests/test_file_store.py +152 -0
- runspace-0.2.0/src/runspace/protocols/tests/test_fixture_vision.py +88 -0
- runspace-0.2.0/src/runspace/protocols/tests/test_lazy_backend_imports.py +153 -0
- runspace-0.2.0/src/runspace/protocols/tests/test_multitenant_isolation.py +288 -0
- runspace-0.2.0/src/runspace/protocols/tests/test_package_includes.py +86 -0
- runspace-0.2.0/src/runspace/protocols/tests/test_registry.py +73 -0
- runspace-0.2.0/src/runspace/protocols/tests/test_store_contract.py +240 -0
- runspace-0.2.0/src/runspace/protocols/tests/test_supabase_store_42p10_fallback.py +120 -0
- runspace-0.2.0/src/runspace/protocols/tests/test_transcriber.py +72 -0
- runspace-0.2.0/src/runspace/protocols/tests/test_vision_snapshot.py +134 -0
- runspace-0.2.0/src/runspace/protocols/transcriber.py +44 -0
- runspace-0.2.0/src/runspace/protocols/transport/__init__.py +27 -0
- runspace-0.2.0/src/runspace/protocols/transport/file_inbox.py +91 -0
- runspace-0.2.0/src/runspace/protocols/transport/protocol.py +74 -0
- runspace-0.2.0/src/runspace/protocols/transport/telegram.py +123 -0
- runspace-0.2.0/src/runspace/protocols/vision/__init__.py +23 -0
- runspace-0.2.0/src/runspace/protocols/vision/codex_vision.py +156 -0
- runspace-0.2.0/src/runspace/protocols/vision/fixture_vision.py +64 -0
- runspace-0.2.0/src/runspace/protocols/vision/protocol.py +38 -0
- runspace-0.2.0/src/runspace/py.typed +0 -0
- runspace-0.2.0/src/runspace/runspace_cli/__init__.py +90 -0
- runspace-0.2.0/src/runspace/runspace_cli/tests/__init__.py +0 -0
- runspace-0.2.0/src/runspace/runspace_cli/tests/test_dispatcher.py +116 -0
- runspace-0.2.0/src/runspace/templates/widgets.md +70 -0
- runspace-0.2.0/src/runspace/workspace/README.md +83 -0
- runspace-0.2.0/src/runspace/workspace/__init__.py +31 -0
- runspace-0.2.0/src/runspace/workspace/backend/__init__.py +25 -0
- runspace-0.2.0/src/runspace/workspace/backend/_mcp_ui.py +106 -0
- runspace-0.2.0/src/runspace/workspace/backend/activity_log.py +73 -0
- runspace-0.2.0/src/runspace/workspace/backend/app_registry.py +415 -0
- runspace-0.2.0/src/runspace/workspace/backend/attachments.py +224 -0
- runspace-0.2.0/src/runspace/workspace/backend/bootstrap.py +402 -0
- runspace-0.2.0/src/runspace/workspace/backend/file_extractors.py +154 -0
- runspace-0.2.0/src/runspace/workspace/backend/gateway.py +2263 -0
- runspace-0.2.0/src/runspace/workspace/backend/history_sqlite.py +142 -0
- runspace-0.2.0/src/runspace/workspace/backend/media.py +59 -0
- runspace-0.2.0/src/runspace/workspace/backend/messaging.py +455 -0
- runspace-0.2.0/src/runspace/workspace/backend/messaging_sqlite.py +411 -0
- runspace-0.2.0/src/runspace/workspace/backend/models.py +30 -0
- runspace-0.2.0/src/runspace/workspace/backend/pricing.py +94 -0
- runspace-0.2.0/src/runspace/workspace/backend/registry.py +246 -0
- runspace-0.2.0/src/runspace/workspace/backend/response_filter.py +41 -0
- runspace-0.2.0/src/runspace/workspace/backend/routines_store.py +362 -0
- runspace-0.2.0/src/runspace/workspace/backend/runners/__init__.py +0 -0
- runspace-0.2.0/src/runspace/workspace/backend/runners/ab.py +122 -0
- runspace-0.2.0/src/runspace/workspace/backend/runners/base.py +104 -0
- runspace-0.2.0/src/runspace/workspace/backend/runners/executor.py +133 -0
- runspace-0.2.0/src/runspace/workspace/backend/runners/loader.py +123 -0
- runspace-0.2.0/src/runspace/workspace/backend/runners/workload.py +166 -0
- runspace-0.2.0/src/runspace/workspace/backend/runtimes/__init__.py +20 -0
- runspace-0.2.0/src/runspace/workspace/backend/runtimes/agentino.py +425 -0
- runspace-0.2.0/src/runspace/workspace/backend/runtimes/claude_code.py +269 -0
- runspace-0.2.0/src/runspace/workspace/backend/runtimes/codex.py +230 -0
- runspace-0.2.0/src/runspace/workspace/backend/runtimes/mcp_harness.py +220 -0
- runspace-0.2.0/src/runspace/workspace/backend/runtimes/openclaw.py +277 -0
- runspace-0.2.0/src/runspace/workspace/backend/runtimes/pi.py +298 -0
- runspace-0.2.0/src/runspace/workspace/backend/scoring/__init__.py +0 -0
- runspace-0.2.0/src/runspace/workspace/backend/scoring/base.py +51 -0
- runspace-0.2.0/src/runspace/workspace/backend/scoring/match.py +55 -0
- runspace-0.2.0/src/runspace/workspace/backend/sessions.py +314 -0
- runspace-0.2.0/src/runspace/workspace/backend/tests/__init__.py +0 -0
- runspace-0.2.0/src/runspace/workspace/backend/tests/test_advanced.py +452 -0
- runspace-0.2.0/src/runspace/workspace/backend/tests/test_app_registry_no_runtime_imports.py +96 -0
- runspace-0.2.0/src/runspace/workspace/backend/tests/test_bootstrap.py +385 -0
- runspace-0.2.0/src/runspace/workspace/backend/tests/test_channel_message_persistence.py +258 -0
- runspace-0.2.0/src/runspace/workspace/backend/tests/test_chat_persistence_and_attachments.py +209 -0
- runspace-0.2.0/src/runspace/workspace/backend/tests/test_chat_stream_disconnect.py +199 -0
- runspace-0.2.0/src/runspace/workspace/backend/tests/test_claude_code_runtime.py +229 -0
- runspace-0.2.0/src/runspace/workspace/backend/tests/test_codex_runtime.py +226 -0
- runspace-0.2.0/src/runspace/workspace/backend/tests/test_documentation_samples.py +74 -0
- runspace-0.2.0/src/runspace/workspace/backend/tests/test_documented_imports.py +252 -0
- runspace-0.2.0/src/runspace/workspace/backend/tests/test_documents_mirror.py +118 -0
- runspace-0.2.0/src/runspace/workspace/backend/tests/test_examples.py +95 -0
- runspace-0.2.0/src/runspace/workspace/backend/tests/test_external_channel_telegram.py +294 -0
- runspace-0.2.0/src/runspace/workspace/backend/tests/test_external_channels_transport.py +448 -0
- runspace-0.2.0/src/runspace/workspace/backend/tests/test_frontend_layering.py +183 -0
- runspace-0.2.0/src/runspace/workspace/backend/tests/test_gate_manager_wiring.py +216 -0
- runspace-0.2.0/src/runspace/workspace/backend/tests/test_gateway.py +324 -0
- runspace-0.2.0/src/runspace/workspace/backend/tests/test_history_sqlite.py +124 -0
- runspace-0.2.0/src/runspace/workspace/backend/tests/test_markdown_renderer_contract.py +61 -0
- runspace-0.2.0/src/runspace/workspace/backend/tests/test_mcp_ui_fences.py +74 -0
- runspace-0.2.0/src/runspace/workspace/backend/tests/test_media.py +87 -0
- runspace-0.2.0/src/runspace/workspace/backend/tests/test_messaging_sqlite.py +181 -0
- runspace-0.2.0/src/runspace/workspace/backend/tests/test_openclaw_runtime.py +140 -0
- runspace-0.2.0/src/runspace/workspace/backend/tests/test_pairing_and_callbacks.py +1941 -0
- runspace-0.2.0/src/runspace/workspace/backend/tests/test_pdf_chat_context_hint.py +83 -0
- runspace-0.2.0/src/runspace/workspace/backend/tests/test_pi_runtime.py +306 -0
- runspace-0.2.0/src/runspace/workspace/backend/tests/test_pricing.py +72 -0
- runspace-0.2.0/src/runspace/workspace/backend/tests/test_register_soul_flattening.py +146 -0
- runspace-0.2.0/src/runspace/workspace/backend/tests/test_registry_mount.py +80 -0
- runspace-0.2.0/src/runspace/workspace/backend/tests/test_resolve_files_original_name.py +83 -0
- runspace-0.2.0/src/runspace/workspace/backend/tests/test_response_filter.py +48 -0
- runspace-0.2.0/src/runspace/workspace/backend/tests/test_routines_store.py +370 -0
- runspace-0.2.0/src/runspace/workspace/backend/tests/test_runners.py +407 -0
- runspace-0.2.0/src/runspace/workspace/backend/tests/test_secrets_stay_out_of_prompts.py +88 -0
- runspace-0.2.0/src/runspace/workspace/backend/tests/test_soul_includes.py +104 -0
- runspace-0.2.0/src/runspace/workspace/backend/tests/test_std_bundles.py +71 -0
- runspace-0.2.0/src/runspace/workspace/backend/tests/test_token_redaction.py +110 -0
- runspace-0.2.0/src/runspace/workspace/backend/tests/test_tools_usage.py +256 -0
- runspace-0.2.0/src/runspace/workspace/backend/tests/test_widget_validator.py +118 -0
- runspace-0.2.0/src/runspace/workspace/backend/tests/test_workspace.py +365 -0
- runspace-0.2.0/src/runspace/workspace/backend/tools_usage.py +145 -0
- runspace-0.2.0/src/runspace/workspace/backend/widget_validator.py +128 -0
- runspace-0.2.0/src/runspace/workspace/cli/__init__.py +10 -0
- runspace-0.2.0/src/runspace/workspace/cli/__main__.py +81 -0
- runspace-0.2.0/src/runspace/workspace/cli/init_cmd.py +293 -0
- runspace-0.2.0/src/runspace/workspace/cli/tests/__init__.py +0 -0
- runspace-0.2.0/src/runspace/workspace/cli/tests/test_console_scripts.py +51 -0
- runspace-0.2.0/src/runspace/workspace/cli/tests/test_init_cmd.py +193 -0
- runspace-0.2.0/src/runspace/workspace/plugin.py +54 -0
- runspace-0.2.0/src/runspace/workspace/serve.py +74 -0
- runspace-0.2.0/templates/workspace.yml.example +28 -0
- runspace-0.2.0/tests/conftest.py +1 -0
- runspace-0.2.0/tests/test_conversations.py +97 -0
- runspace-0.2.0/tests/test_create_tools_comprehensive.py +285 -0
- runspace-0.2.0/tests/test_shared_tools_filestorage_migration.py +178 -0
- runspace-0.2.0/tests/test_shared_tools_storage_refactor.py +296 -0
- runspace-0.2.0/tests/test_telegram_render.py +287 -0
- runspace-0.2.0/workspace/frontend/.npmrc +3 -0
- runspace-0.2.0/workspace/frontend/dialog/components/AgentPicker.tsx +73 -0
- runspace-0.2.0/workspace/frontend/dialog/components/DialogComposer.tsx +413 -0
- runspace-0.2.0/workspace/frontend/dialog/components/DialogMessageRow.tsx +146 -0
- runspace-0.2.0/workspace/frontend/dialog/components/ThreadListSidebar.tsx +181 -0
- runspace-0.2.0/workspace/frontend/dialog/components/index.ts +5 -0
- runspace-0.2.0/workspace/frontend/dialog/components/threadStore.ts +223 -0
- runspace-0.2.0/workspace/frontend/dialog/hooks/useThreads.ts +89 -0
- runspace-0.2.0/workspace/frontend/dialog/pages/DialogChat.tsx +403 -0
- runspace-0.2.0/workspace/frontend/dialog/pages/index.ts +1 -0
- runspace-0.2.0/workspace/frontend/index.d.ts +279 -0
- runspace-0.2.0/workspace/frontend/package.json +40 -0
- runspace-0.2.0/workspace/frontend/shared/api-proxies/generate.sh +100 -0
- runspace-0.2.0/workspace/frontend/shared/components/BotAvatar.tsx +30 -0
- runspace-0.2.0/workspace/frontend/shared/components/BotPopover.tsx +75 -0
- runspace-0.2.0/workspace/frontend/shared/components/DateDivider.tsx +32 -0
- runspace-0.2.0/workspace/frontend/shared/components/InlineChart.tsx +392 -0
- runspace-0.2.0/workspace/frontend/shared/components/InlineMermaid.tsx +64 -0
- runspace-0.2.0/workspace/frontend/shared/components/InlineTable.tsx +398 -0
- runspace-0.2.0/workspace/frontend/shared/components/InsightCard.tsx +103 -0
- runspace-0.2.0/workspace/frontend/shared/components/KPIBlock.tsx +69 -0
- runspace-0.2.0/workspace/frontend/shared/components/KPICard.tsx +31 -0
- runspace-0.2.0/workspace/frontend/shared/components/MarkdownContent.test.js +159 -0
- runspace-0.2.0/workspace/frontend/shared/components/MarkdownContent.tsx +126 -0
- runspace-0.2.0/workspace/frontend/shared/components/MessageActions.tsx +105 -0
- runspace-0.2.0/workspace/frontend/shared/components/MessageBubble.tsx +259 -0
- runspace-0.2.0/workspace/frontend/shared/components/MessageComposer.tsx +430 -0
- runspace-0.2.0/workspace/frontend/shared/components/ToolBadge.tsx +13 -0
- runspace-0.2.0/workspace/frontend/shared/components/TypingIndicator.tsx +42 -0
- runspace-0.2.0/workspace/frontend/shared/components/index.ts +23 -0
- runspace-0.2.0/workspace/frontend/shared/components/parseChartConfig.test.js +276 -0
- runspace-0.2.0/workspace/frontend/shared/components/parseChartConfig.ts +154 -0
- runspace-0.2.0/workspace/frontend/shared/components/widgetIntent.tsx +74 -0
- runspace-0.2.0/workspace/frontend/shared/hooks/useChannelMessages.ts +184 -0
- runspace-0.2.0/workspace/frontend/shared/hooks/useChatStream.ts +203 -0
- runspace-0.2.0/workspace/frontend/shared/hooks/useLocalState.ts +79 -0
- runspace-0.2.0/workspace/frontend/shared/utils/describeSchedule.test.mjs +39 -0
- runspace-0.2.0/workspace/frontend/shared/utils/describeSchedule.ts +45 -0
- runspace-0.2.0/workspace/frontend/shared/utils/loosePayload.test.mjs +72 -0
- runspace-0.2.0/workspace/frontend/shared/utils/loosePayload.ts +117 -0
- runspace-0.2.0/workspace/frontend/team/components/DashboardPanel.tsx +131 -0
- runspace-0.2.0/workspace/frontend/team/components/Kanban.tsx +176 -0
- runspace-0.2.0/workspace/frontend/team/components/KnowledgeBrowser.tsx +220 -0
- runspace-0.2.0/workspace/frontend/team/components/ModeSwitcher.tsx +50 -0
- runspace-0.2.0/workspace/frontend/team/components/ResizeHandle.tsx +66 -0
- runspace-0.2.0/workspace/frontend/team/components/Sidebar.tsx +269 -0
- runspace-0.2.0/workspace/frontend/team/components/ThreadPanel.tsx +136 -0
- runspace-0.2.0/workspace/frontend/team/components/index.ts +7 -0
- runspace-0.2.0/workspace/frontend/team/components/settings/GatewayStatusWidget.tsx +105 -0
- runspace-0.2.0/workspace/frontend/team/components/settings/KeyValueWidget.tsx +39 -0
- runspace-0.2.0/workspace/frontend/team/components/settings/NumberPairWidget.tsx +44 -0
- runspace-0.2.0/workspace/frontend/team/components/settings/ScheduleWidget.tsx +71 -0
- runspace-0.2.0/workspace/frontend/team/components/settings/TextWidget.tsx +27 -0
- runspace-0.2.0/workspace/frontend/team/components/settings/ToggleListWidget.tsx +36 -0
- runspace-0.2.0/workspace/frontend/team/components/settings/examples/GatewayStatusWidget.tsx +128 -0
- runspace-0.2.0/workspace/frontend/team/components/settings/examples/README.md +28 -0
- runspace-0.2.0/workspace/frontend/team/components/settings/examples/ScheduleWidget.tsx +54 -0
- runspace-0.2.0/workspace/frontend/team/components/settings/index.ts +7 -0
- runspace-0.2.0/workspace/frontend/team/pages/ActivityLogPage.tsx +113 -0
- runspace-0.2.0/workspace/frontend/team/pages/AgentChat.tsx +438 -0
- runspace-0.2.0/workspace/frontend/team/pages/BotDMPage.tsx +18 -0
- runspace-0.2.0/workspace/frontend/team/pages/ChannelPage.tsx +194 -0
- runspace-0.2.0/workspace/frontend/team/pages/GeneralChannel.tsx +617 -0
- runspace-0.2.0/workspace/frontend/team/pages/RoutinesPage.tsx +217 -0
- runspace-0.2.0/workspace/frontend/team/pages/SettingsPage.tsx +163 -0
- runspace-0.2.0/workspace/frontend/team/pages/TeamGrid.tsx +46 -0
- runspace-0.2.0/workspace/frontend/team/pages/WorkspaceLayout.tsx +233 -0
- runspace-0.2.0/workspace/frontend/team/pages/WorkspaceShell.tsx +205 -0
- runspace-0.2.0/workspace/frontend/team/pages/index.ts +10 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
name: Bug report
|
|
2
|
+
description: Something behaves differently from what the docs say
|
|
3
|
+
labels: [bug]
|
|
4
|
+
body:
|
|
5
|
+
- type: textarea
|
|
6
|
+
id: what-happened
|
|
7
|
+
attributes:
|
|
8
|
+
label: What happened
|
|
9
|
+
description: What you did, what you expected, and what you got instead.
|
|
10
|
+
validations:
|
|
11
|
+
required: true
|
|
12
|
+
- type: textarea
|
|
13
|
+
id: reproduce
|
|
14
|
+
attributes:
|
|
15
|
+
label: Minimal reproduction
|
|
16
|
+
description: >
|
|
17
|
+
The smallest script or config that shows the problem. This is the
|
|
18
|
+
single most useful thing you can include.
|
|
19
|
+
render: python
|
|
20
|
+
validations:
|
|
21
|
+
required: true
|
|
22
|
+
- type: input
|
|
23
|
+
id: version
|
|
24
|
+
attributes:
|
|
25
|
+
label: Version
|
|
26
|
+
description: Release number or commit SHA.
|
|
27
|
+
validations:
|
|
28
|
+
required: true
|
|
29
|
+
- type: input
|
|
30
|
+
id: python
|
|
31
|
+
attributes:
|
|
32
|
+
label: Python version
|
|
33
|
+
placeholder: "3.12.3"
|
|
34
|
+
validations:
|
|
35
|
+
required: true
|
|
36
|
+
- type: textarea
|
|
37
|
+
id: traceback
|
|
38
|
+
attributes:
|
|
39
|
+
label: Traceback or logs
|
|
40
|
+
render: text
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
name: Feature request
|
|
2
|
+
description: Propose a change to what Runspace does
|
|
3
|
+
labels: [enhancement]
|
|
4
|
+
body:
|
|
5
|
+
- type: textarea
|
|
6
|
+
id: problem
|
|
7
|
+
attributes:
|
|
8
|
+
label: The problem
|
|
9
|
+
description: >
|
|
10
|
+
What are you trying to do that is awkward or impossible today?
|
|
11
|
+
Describe the situation, not the solution.
|
|
12
|
+
validations:
|
|
13
|
+
required: true
|
|
14
|
+
- type: textarea
|
|
15
|
+
id: proposal
|
|
16
|
+
attributes:
|
|
17
|
+
label: What you have in mind
|
|
18
|
+
description: If you have an API or config shape in mind, sketch it.
|
|
19
|
+
- type: textarea
|
|
20
|
+
id: alternatives
|
|
21
|
+
attributes:
|
|
22
|
+
label: What you tried instead
|
|
23
|
+
description: Workarounds you have used, and why they fall short.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
## What this changes
|
|
2
|
+
|
|
3
|
+
<!-- One paragraph. What is different after this lands? -->
|
|
4
|
+
|
|
5
|
+
## Why
|
|
6
|
+
|
|
7
|
+
<!-- The reasoning a reviewer cannot get from the diff. Link the issue if
|
|
8
|
+
there is one. -->
|
|
9
|
+
|
|
10
|
+
## Checklist
|
|
11
|
+
|
|
12
|
+
- [ ] Tests cover the change, and a bug fix has a test that failed before it
|
|
13
|
+
- [ ] `pytest` passes locally
|
|
14
|
+
- [ ] `ruff check .` and `ruff format --check .` pass
|
|
15
|
+
- [ ] Docs updated if behaviour or configuration changed
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: write # to attach build artifacts to the release
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
build:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
- uses: actions/setup-python@v5
|
|
17
|
+
with:
|
|
18
|
+
python-version: "3.12"
|
|
19
|
+
- run: pip install build twine
|
|
20
|
+
- run: python -m build
|
|
21
|
+
- run: twine check dist/*
|
|
22
|
+
- uses: actions/upload-artifact@v4
|
|
23
|
+
with:
|
|
24
|
+
name: dist
|
|
25
|
+
path: dist/
|
|
26
|
+
- name: Attach the artifacts to the release
|
|
27
|
+
if: github.event_name == 'release'
|
|
28
|
+
run: gh release upload "$GITHUB_REF_NAME" dist/*
|
|
29
|
+
env:
|
|
30
|
+
GH_TOKEN: ${{ github.token }}
|
|
31
|
+
|
|
32
|
+
# Publishing is a separate job so a build failure never leaves a partial
|
|
33
|
+
# upload, and so the PyPI credential is scoped to this job alone. It uses
|
|
34
|
+
# Trusted Publishing (OIDC) — there is no API token stored in the repo.
|
|
35
|
+
#
|
|
36
|
+
# Before the first run, configure a pending publisher on PyPI:
|
|
37
|
+
# https://pypi.org/manage/account/publishing/
|
|
38
|
+
# owner: <the GitHub owner> repository: runspace
|
|
39
|
+
# workflow: release.yml environment: pypi
|
|
40
|
+
publish:
|
|
41
|
+
needs: build
|
|
42
|
+
if: github.event_name == 'release'
|
|
43
|
+
runs-on: ubuntu-latest
|
|
44
|
+
environment: pypi
|
|
45
|
+
permissions:
|
|
46
|
+
id-token: write # required for Trusted Publishing
|
|
47
|
+
steps:
|
|
48
|
+
- uses: actions/download-artifact@v4
|
|
49
|
+
with:
|
|
50
|
+
name: dist
|
|
51
|
+
path: dist/
|
|
52
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
concurrency:
|
|
12
|
+
group: ci-${{ github.ref }}
|
|
13
|
+
cancel-in-progress: true
|
|
14
|
+
|
|
15
|
+
env:
|
|
16
|
+
# The test job checks out agentino beside this repo. That step needs
|
|
17
|
+
# agentino to be public, or a token with access to it — until then this
|
|
18
|
+
# job cannot run on a fork or a fresh clone.
|
|
19
|
+
AGENTINO_REF: main
|
|
20
|
+
|
|
21
|
+
jobs:
|
|
22
|
+
lint:
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@v4
|
|
26
|
+
- uses: actions/setup-python@v5
|
|
27
|
+
with:
|
|
28
|
+
python-version: "3.12"
|
|
29
|
+
- run: pip install ruff
|
|
30
|
+
- name: ruff check
|
|
31
|
+
run: ruff check .
|
|
32
|
+
- name: ruff format --check
|
|
33
|
+
run: ruff format --check .
|
|
34
|
+
|
|
35
|
+
test:
|
|
36
|
+
runs-on: ubuntu-latest
|
|
37
|
+
strategy:
|
|
38
|
+
fail-fast: false
|
|
39
|
+
matrix:
|
|
40
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
41
|
+
steps:
|
|
42
|
+
- uses: actions/checkout@v4
|
|
43
|
+
- uses: actions/checkout@v4
|
|
44
|
+
with:
|
|
45
|
+
repository: islavutin-oss/agentino
|
|
46
|
+
ref: ${{ env.AGENTINO_REF }}
|
|
47
|
+
path: _agentino
|
|
48
|
+
- uses: actions/setup-python@v5
|
|
49
|
+
with:
|
|
50
|
+
python-version: ${{ matrix.python-version }}
|
|
51
|
+
- name: Install dependencies
|
|
52
|
+
run: |
|
|
53
|
+
# Install through the package's own metadata, not a hand-kept list.
|
|
54
|
+
# A hand-kept list makes CI green while `pip install runspace` is
|
|
55
|
+
# broken, which is exactly how two missing core dependencies once
|
|
56
|
+
# went unnoticed. Every extra except [agentino] is installed from
|
|
57
|
+
# pyproject; the runtime comes from the checkout beside us because
|
|
58
|
+
# it is not on PyPI during CI.
|
|
59
|
+
# The document tools live in agentino's [docgen] extra.
|
|
60
|
+
pip install "./_agentino[docgen]"
|
|
61
|
+
pip install -e ".[redis,server,supabase,workspace,documents,scheduler,crawler,dev]"
|
|
62
|
+
pip install pytest-timeout
|
|
63
|
+
# testpaths in pyproject covers every test location, so one run is the
|
|
64
|
+
# whole suite. It used to be two commands and the second was easy to
|
|
65
|
+
# skip, which let a broken console-script entry point sit unnoticed.
|
|
66
|
+
- name: pytest
|
|
67
|
+
env:
|
|
68
|
+
PYTHONPATH: "src"
|
|
69
|
+
run: pytest -q
|
|
70
|
+
- name: sandbox_lint self-test
|
|
71
|
+
env:
|
|
72
|
+
PYTHONPATH: "src"
|
|
73
|
+
run: python -m runspace.protocols.sandbox_lint .
|
|
74
|
+
|
|
75
|
+
build:
|
|
76
|
+
runs-on: ubuntu-latest
|
|
77
|
+
steps:
|
|
78
|
+
- uses: actions/checkout@v4
|
|
79
|
+
- uses: actions/setup-python@v5
|
|
80
|
+
with:
|
|
81
|
+
python-version: "3.12"
|
|
82
|
+
- run: pip install build twine
|
|
83
|
+
- name: Build the distribution
|
|
84
|
+
run: python -m build
|
|
85
|
+
- name: Check the distribution metadata
|
|
86
|
+
run: twine check dist/*
|
|
87
|
+
|
|
88
|
+
frontend:
|
|
89
|
+
runs-on: ubuntu-latest
|
|
90
|
+
steps:
|
|
91
|
+
- uses: actions/checkout@v4
|
|
92
|
+
- uses: actions/setup-node@v4
|
|
93
|
+
with:
|
|
94
|
+
node-version: "22"
|
|
95
|
+
- name: Frontend unit tests
|
|
96
|
+
run: |
|
|
97
|
+
node --experimental-strip-types workspace/frontend/shared/utils/loosePayload.test.mjs
|
|
98
|
+
node --experimental-strip-types --test workspace/frontend/shared/utils/describeSchedule.test.mjs
|
|
99
|
+
|
|
100
|
+
installable:
|
|
101
|
+
# Guards the one thing the test suite cannot see: that the built
|
|
102
|
+
# distribution is usable by someone who runs `pip install runspace`
|
|
103
|
+
# with nothing else present.
|
|
104
|
+
runs-on: ubuntu-latest
|
|
105
|
+
steps:
|
|
106
|
+
- uses: actions/checkout@v4
|
|
107
|
+
- uses: actions/setup-python@v5
|
|
108
|
+
with:
|
|
109
|
+
python-version: "3.12"
|
|
110
|
+
- run: pip install build
|
|
111
|
+
- name: Build the wheel
|
|
112
|
+
run: python -m build --wheel --outdir dist
|
|
113
|
+
- name: Install it into an empty environment
|
|
114
|
+
run: |
|
|
115
|
+
python -m venv /tmp/clean
|
|
116
|
+
/tmp/clean/bin/pip install dist/*.whl
|
|
117
|
+
- name: Import it with no agent runtime installed
|
|
118
|
+
run: |
|
|
119
|
+
cd /tmp
|
|
120
|
+
/tmp/clean/bin/python -c "
|
|
121
|
+
import runspace, runspace.contracts, runspace.protocols
|
|
122
|
+
try:
|
|
123
|
+
import agentino
|
|
124
|
+
raise SystemExit('agentino must not be a core dependency')
|
|
125
|
+
except ImportError:
|
|
126
|
+
pass
|
|
127
|
+
from runspace.protocols import get_store, get_vision, get_transport
|
|
128
|
+
print(type(get_store()).__name__, type(get_vision()).__name__, type(get_transport()).__name__)
|
|
129
|
+
"
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.pyc
|
|
3
|
+
.env
|
|
4
|
+
node_modules/
|
|
5
|
+
.pytest_cache/
|
|
6
|
+
|
|
7
|
+
# Runtime artifacts
|
|
8
|
+
sessions/
|
|
9
|
+
sessions.jsonl
|
|
10
|
+
usage.jsonl
|
|
11
|
+
.agentino/
|
|
12
|
+
.docs/
|
|
13
|
+
|
|
14
|
+
# Build artifacts
|
|
15
|
+
dist/
|
|
16
|
+
build/
|
|
17
|
+
*.egg-info/
|
|
18
|
+
*.so
|
|
19
|
+
*.c
|
|
20
|
+
!setup.c
|
|
21
|
+
agentino_pkg/
|
|
22
|
+
|
|
23
|
+
# Large repos cloned by agents
|
|
24
|
+
|
|
25
|
+
# Local scratch / experiments — not part of the shared package.
|
|
26
|
+
_tmp/
|
|
27
|
+
vscode-extension/
|
|
28
|
+
|
|
29
|
+
# Tooling caches
|
|
30
|
+
.venv/
|
|
31
|
+
.ruff_cache/
|
|
32
|
+
.hypothesis/
|
|
33
|
+
.runspace/
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project aims
|
|
5
|
+
to follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html) from 1.0
|
|
6
|
+
onward.
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- A SQLite messaging backend, now the default. Channels, threads, direct
|
|
13
|
+
messages and read state previously required `SUPABASE_URL` and
|
|
14
|
+
`SUPABASE_KEY`: without them `MessagingService` was never constructed, every
|
|
15
|
+
channel route returned 404 and nothing persisted. Since channels are the
|
|
16
|
+
workspace's main surface, a fresh install looked broken rather than
|
|
17
|
+
unconfigured. Supabase is still used when it is configured.
|
|
18
|
+
- `InsightCard` reports a payload that parsed but is not an insight, naming
|
|
19
|
+
the keys it did receive. It previously rendered an empty card, which reads
|
|
20
|
+
as a layout bug rather than a malformed block.
|
|
21
|
+
|
|
22
|
+
- Apache-2.0 licence, `NOTICE`, contribution guide, security policy, code of
|
|
23
|
+
conduct, and issue and pull-request templates.
|
|
24
|
+
- `response_filter` in `workspace.yml`: a dotted path to a callable the
|
|
25
|
+
application owns. Runspace resolves and calls it without knowing what it
|
|
26
|
+
checks.
|
|
27
|
+
- `max_turns` as per-app configuration, defaulting to 10.
|
|
28
|
+
- `gpt-5.4-codex` is the default model for the agent runtimes and vision.
|
|
29
|
+
- `WorkspaceRegistry.mount(app)`: exposes every tenant's gateway routes on one
|
|
30
|
+
application, resolving the tenant per request. A single-tenant host could
|
|
31
|
+
already do `app.include_router(gateway.router)`; a multi-tenant one had no
|
|
32
|
+
supported way, so hosts hand-wrote a handful of routes and quietly exposed a
|
|
33
|
+
fraction of the surface — channels, messages, uploads, pairings and the
|
|
34
|
+
external-channel routes simply had no route at all. The documentation
|
|
35
|
+
described this method before it existed.
|
|
36
|
+
- Built-in `gateway_status` and `schedule` settings widgets. Both types were
|
|
37
|
+
named in `SettingsPage`'s union from the start and neither had an
|
|
38
|
+
implementation, so a section declaring either rendered "Unknown widget
|
|
39
|
+
type". An application can still replace either by passing a widget of the
|
|
40
|
+
same name.
|
|
41
|
+
- `examples/grid`: a complete workspace that runs on a free, keyless public API
|
|
42
|
+
the moment a model endpoint is configured. A test walks every shipped example
|
|
43
|
+
and checks the paths its config names exist, its runtime is one the registry
|
|
44
|
+
dispatches, and its README names the command that starts it.
|
|
45
|
+
- Opening suggestions in `workspace.yml`, carried through `/config`, so a
|
|
46
|
+
dialog client shows the workspace's own questions rather than generic ones.
|
|
47
|
+
- `py.typed`. Without it a type checker ignores every annotation in the
|
|
48
|
+
package, so a hundred annotated modules did nothing for a consumer.
|
|
49
|
+
|
|
50
|
+
### Changed
|
|
51
|
+
|
|
52
|
+
- **Breaking: one import root.** The packages moved under `src/runspace/`, so
|
|
53
|
+
everything is imported as `runspace.*`. The distribution previously installed
|
|
54
|
+
`contracts`, `protocols`, `workspace`, `ingestion`, `helpers` and
|
|
55
|
+
`runspace_cli` as top-level names, which would collide with a user's own
|
|
56
|
+
modules. Consumers update with:
|
|
57
|
+
|
|
58
|
+
from protocols import get_store -> from runspace.protocols import get_store
|
|
59
|
+
from workspace.backend import ... -> from runspace.workspace.backend import ...
|
|
60
|
+
|
|
61
|
+
No compatibility shim ships. Aliasing the old names in `sys.modules` made
|
|
62
|
+
submodule imports execute a second time under a second name, giving two
|
|
63
|
+
module objects with separate caches — a worse failure than an ImportError.
|
|
64
|
+
|
|
65
|
+
`workspace/frontend/` stays at the repository root: it is the `@runspace/ui`
|
|
66
|
+
npm package, not part of the Python tree.
|
|
67
|
+
- Zero-configuration defaults. `STORE_BACKEND` defaults to `file` (rooted at
|
|
68
|
+
`./.runspace/store`), `VISION_BACKEND` to `fixture` and `TRANSPORT_BACKEND`
|
|
69
|
+
to `file`, so a fresh install runs with no environment set. Previously the
|
|
70
|
+
store defaulted to `supabase` and raised on import without credentials.
|
|
71
|
+
Deployments relying on the old defaults must set them explicitly.
|
|
72
|
+
- Licence changed from MIT to Apache-2.0. The repository previously declared
|
|
73
|
+
MIT in metadata with no licence file present.
|
|
74
|
+
- Environment variables are no longer named after particular deployments. The
|
|
75
|
+
embeddings and vision adapters read `EMBEDDINGS_*`, `AI_BASE_URL`,
|
|
76
|
+
`AI_API_KEY` and `VISION_API_KEY`.
|
|
77
|
+
- CI runs `ruff`, covers Python 3.10 through 3.13, exercises all six test
|
|
78
|
+
directories rather than one, builds the distribution with a `twine`
|
|
79
|
+
metadata check, and runs the frontend parser tests.
|
|
80
|
+
|
|
81
|
+
### Fixed
|
|
82
|
+
|
|
83
|
+
- The distribution declared a dependency on `agentino`, which on PyPI is an
|
|
84
|
+
unrelated project. Neither package is published to PyPI; install is from git. The agent runtime is now the `[agentino]` extra, pulling
|
|
85
|
+
`agentino-framework` — Runspace routes each turn to whichever runtime an app
|
|
86
|
+
declares and requires none of them, so it does not belong in the core
|
|
87
|
+
requirements.
|
|
88
|
+
- `pip install runspace` produced an install that could not be imported:
|
|
89
|
+
`contracts.scheduling` needs `croniter` and `protocols.config` needs
|
|
90
|
+
`pydantic-settings`, both of which had been arriving transitively through
|
|
91
|
+
agentino. Both are now declared. Verified by installing the wheel into an
|
|
92
|
+
empty virtualenv with no agent runtime present.
|
|
93
|
+
|
|
94
|
+
- `gateway.py` used `Any` in six annotations without importing it, which
|
|
95
|
+
raises under `typing.get_type_hints()`.
|
|
96
|
+
- The multi-tenant isolation property tests shared a single store across every
|
|
97
|
+
hypothesis example. Rows accumulated, so a tenant id generated as `tenant_a`
|
|
98
|
+
in one example could reappear as `tenant_b` in a later one and read as a
|
|
99
|
+
leak. Each example now builds its own store.
|
|
100
|
+
- `tests/test_telegram_render.py` imported a package path that never resolved,
|
|
101
|
+
so the module could not be collected at all.
|
|
102
|
+
- A test fixture repeated the `token` key in one dictionary literal.
|
|
103
|
+
- A test drove its coroutines through `asyncio.get_event_loop()`, which on
|
|
104
|
+
Python 3.12 only works when an earlier test left a loop on the thread, so it
|
|
105
|
+
passed or failed depending on collection order.
|
|
106
|
+
- The `[supabase]` extra was documented but never declared, and `[documents]`
|
|
107
|
+
omitted pymupdf, which the scanned-PDF path imports.
|
|
108
|
+
- The widget-integrity regex covered `chart`, `datatable` and `kpi` but not
|
|
109
|
+
`insight`, which the frontend also renders. An insight block the model
|
|
110
|
+
mangled was never spliced back over — the canonical copy was appended at
|
|
111
|
+
the end instead, so the page showed a parse error above the real card.
|
|
112
|
+
- Seventeen test modules computed a `sys.path` entry from `parents[N]`. The
|
|
113
|
+
indices were wrong after the move, and one of them put `src/runspace` on the
|
|
114
|
+
path, making every subpackage importable a second time as a top-level name.
|
|
115
|
+
Path setup now lives once in the root `conftest.py`.
|
|
116
|
+
- The agent answered twice in a channel. Posting to `/channels/{slug}/messages`
|
|
117
|
+
dispatches `@mentions`, and the channel UI also streams its own turn, so once
|
|
118
|
+
the channel routes were reachable every mention produced two model calls and
|
|
119
|
+
two stored replies. The POST now honours `dispatch=false`.
|
|
120
|
+
- `runspace init` produced a workspace that would not boot. The generated
|
|
121
|
+
config named `tenants.<id>.plugins.health`, which is not an importable module
|
|
122
|
+
path when the id contains a hyphen and assumed a working directory the
|
|
123
|
+
printed instructions do not use. The prompts also raised an unhandled
|
|
124
|
+
`EOFError` when stdin was not a tty, so the command died half-scaffolded in
|
|
125
|
+
CI or a Dockerfile.
|
|
126
|
+
- The `sandbox_lint` CI step ran `python -m protocols.sandbox_lint`, a module
|
|
127
|
+
path the rename removed, so that job could never have passed.
|
|
128
|
+
- The documented development setup produced a checkout whose tests could not
|
|
129
|
+
collect, and `[dev]` named a package that is not on PyPI, so the obvious
|
|
130
|
+
correction failed outright.
|
|
131
|
+
- Eight tests silently skipped because they looked for the frontend inside the
|
|
132
|
+
Python package and named a layer that had been renamed. Two layering rules
|
|
133
|
+
ran green while checking a directory that no longer existed, so a shared
|
|
134
|
+
component importing from `team/` passed the rule forbidding exactly that.
|
|
135
|
+
- Twenty file paths named in the documentation pointed at files that are not
|
|
136
|
+
in the repository, including a package renamed two versions ago.
|
|
137
|
+
- Tests shared one storage root and one adapter registry, so state leaked
|
|
138
|
+
between them. An autouse fixture now gives each test its own roots and
|
|
139
|
+
resets the cached adapters.
|
|
140
|
+
|
|
141
|
+
### Removed
|
|
142
|
+
|
|
143
|
+
- The `packages/` split distributions. `packages/runspace` claimed the same
|
|
144
|
+
PyPI name as the repository root with an older version and a subset of the
|
|
145
|
+
code, so only one of them could ever own that name. Both also produced
|
|
146
|
+
broken source distributions: their `force-include` pointed at `../../src`,
|
|
147
|
+
which does not exist inside an extracted sdist, so a source install failed
|
|
148
|
+
to build a wheel. The root distribution supersedes both.
|
|
149
|
+
|
|
150
|
+
- Product-specific policy from the shared runtime: hardcoded nudge strings in
|
|
151
|
+
one natural language, refusal markers, a datatable row cap naming one
|
|
152
|
+
application's chart tools, and a fixed `max_turns=25` applied to every app.
|
|
153
|
+
- Internal planning documents that tracked a migration through internal
|
|
154
|
+
phases and named host paths, ticket numbers and unshipped projects.
|
|
155
|
+
- Twelve test guards that read a directory which had moved to
|
|
156
|
+
`agentino.tools.std`. The equivalent guards now live in that repository.
|
runspace-0.2.0/CLAUDE.md
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# CLAUDE.md — Runspace
|
|
2
|
+
|
|
3
|
+
Notes for coding agents (and humans) working in this repository.
|
|
4
|
+
|
|
5
|
+
## What this is
|
|
6
|
+
|
|
7
|
+
A workspace runtime for agents: a FastAPI gateway, an app registry, chat with
|
|
8
|
+
streaming and attachments, external channels, scheduled routines, and a React
|
|
9
|
+
frontend. It is runtime-agnostic by construction — the agentino adapter is one
|
|
10
|
+
runtime among several, and `app_registry.py` contains no `from agentino`
|
|
11
|
+
imports.
|
|
12
|
+
|
|
13
|
+
## Setup
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
python -m venv .venv && source .venv/bin/activate
|
|
17
|
+
pip install -e ".[workspace]"
|
|
18
|
+
pip install pytest pytest-asyncio hypothesis ruff
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Agentino is an optional extra, not a dependency — `pip install -e ".[agentino]"`
|
|
22
|
+
if you want the in-process runtime. The test suite exercises it, so install it
|
|
23
|
+
for development.
|
|
24
|
+
|
|
25
|
+
## Commands
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
PYTHONPATH=src pytest -q # default paths
|
|
29
|
+
PYTHONPATH=src pytest src/runspace/contracts src/runspace/protocols \
|
|
30
|
+
src/runspace/workspace/cli/tests scripts/tests -q
|
|
31
|
+
node --experimental-strip-types workspace/frontend/shared/utils/loosePayload.test.mjs
|
|
32
|
+
|
|
33
|
+
ruff check . # must be clean
|
|
34
|
+
ruff format --check . # must be clean
|
|
35
|
+
PYTHONPATH=src python -m runspace.protocols.sandbox_lint <dir> # flag banned imports in agent tools
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
CI runs all of these.
|
|
39
|
+
|
|
40
|
+
## Layout
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
runspace/
|
|
44
|
+
├── src/runspace/ one import root — everything ships as runspace.*
|
|
45
|
+
│ ├── contracts/ wire shapes — chat, runtime, tool, workspace.yml
|
|
46
|
+
│ ├── protocols/ swappable adapters behind Protocols:
|
|
47
|
+
│ │ store, vision, transport, file_storage, embeddings,
|
|
48
|
+
│ │ transcriber, clock, prompt flattening
|
|
49
|
+
│ ├── workspace/backend/ gateway (FastAPI routes), app_registry, runtimes/,
|
|
50
|
+
│ │ messaging, routines, attachments, runners, scoring
|
|
51
|
+
│ ├── ingestion/ inbound channels — Telegram polling, pairing
|
|
52
|
+
│ ├── helpers/ session, messaging and document utilities
|
|
53
|
+
│ └── runspace_cli/ the `runspace` console entry point
|
|
54
|
+
├── workspace/frontend/ React components published as @runspace/ui — an npm
|
|
55
|
+
│ package, deliberately outside the Python tree
|
|
56
|
+
└── templates/ workspace.yml.example
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Conventions that matter here
|
|
60
|
+
|
|
61
|
+
- **No application logic.** This is a shared layer. Tenant behaviour comes
|
|
62
|
+
from configuration — `workspace.yml`, `routines.yml`, `SOUL.md` — never from
|
|
63
|
+
a branch in Python. That includes prompt wording, retry thresholds, tool
|
|
64
|
+
names and natural language. Where an application needs to influence
|
|
65
|
+
behaviour, give it a seam: `response_filter` names a callable the app owns,
|
|
66
|
+
and runspace calls it without knowing what it checks.
|
|
67
|
+
- **No hardcoded prompts.** Agent instructions live in `SOUL.md`. Frontend
|
|
68
|
+
rendering rules live in a partial the SOUL includes, not in a Python
|
|
69
|
+
constant.
|
|
70
|
+
- **No deployment-specific environment variables.** The public names are
|
|
71
|
+
`AI_BASE_URL` / `AI_API_KEY`, `EMBEDDINGS_*` and `VISION_API_KEY`. Use
|
|
72
|
+
`${VAR:-default}` in YAML; `_resolve_env_vars` expands it at load time.
|
|
73
|
+
- **Runtime-agnostic by construction.** Only
|
|
74
|
+
`src/runspace/workspace/backend/runtimes/agentino.py` imports agentino, and it is one of
|
|
75
|
+
five adapters — `codex`, `claude_code`, `pi` and `openclaw` shell out to a
|
|
76
|
+
CLI instead. `app_registry.py` dispatches on `app.type` and imports none of
|
|
77
|
+
them eagerly. A sixth drops in beside them.
|
|
78
|
+
- **One source of truth for prompts.** `protocols.prompt.flatten_soul` is what
|
|
79
|
+
every caller uses to produce a flattened SOUL, so they cannot drift.
|
|
80
|
+
- **Property tests build their own fixtures.** `@given` runs many examples
|
|
81
|
+
against one function-scoped fixture, so shared mutable state leaks between
|
|
82
|
+
examples and looks like a bug in the code under test. Hand back a factory.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our pledge
|
|
4
|
+
|
|
5
|
+
We want participation in this project to be a harassment-free experience for
|
|
6
|
+
everyone, whatever their age, body size, disability, ethnicity, sex
|
|
7
|
+
characteristics, gender identity and expression, level of experience,
|
|
8
|
+
education, socio-economic status, nationality, personal appearance, race,
|
|
9
|
+
religion, or sexual identity and orientation.
|
|
10
|
+
|
|
11
|
+
## Our standards
|
|
12
|
+
|
|
13
|
+
Things that help:
|
|
14
|
+
|
|
15
|
+
- being welcoming and respectful of differing viewpoints
|
|
16
|
+
- accepting constructive criticism gracefully
|
|
17
|
+
- focusing on what is best for the project
|
|
18
|
+
- showing empathy toward other people
|
|
19
|
+
|
|
20
|
+
Things that are not acceptable:
|
|
21
|
+
|
|
22
|
+
- sexualised language or imagery, and unwelcome sexual attention
|
|
23
|
+
- trolling, insults, derogatory comments, and personal or political attacks
|
|
24
|
+
- public or private harassment
|
|
25
|
+
- publishing someone's private information without explicit permission
|
|
26
|
+
|
|
27
|
+
## Enforcement
|
|
28
|
+
|
|
29
|
+
Report unacceptable behaviour by contacting the maintainer,
|
|
30
|
+
[@islavutin-oss](https://github.com/islavutin-oss), through a GitHub private message
|
|
31
|
+
or a private security advisory on this repository. All reports are reviewed
|
|
32
|
+
and investigated, and will be kept confidential.
|
|
33
|
+
|
|
34
|
+
Maintainers may remove comments, commits, code, issues and other
|
|
35
|
+
contributions that violate this Code of Conduct, and may ban contributors
|
|
36
|
+
temporarily or permanently for behaviour they judge inappropriate,
|
|
37
|
+
threatening, offensive or harmful.
|
|
38
|
+
|
|
39
|
+
## Attribution
|
|
40
|
+
|
|
41
|
+
Adapted from the [Contributor Covenant](https://www.contributor-covenant.org),
|
|
42
|
+
version 1.4.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Contributing to Runspace
|
|
2
|
+
|
|
3
|
+
Thanks for taking the time. This is a small project, so the process is short.
|
|
4
|
+
|
|
5
|
+
## Before you start
|
|
6
|
+
|
|
7
|
+
For anything beyond a bug fix or a typo, **open an issue first**. It is much
|
|
8
|
+
less painful to disagree about an approach in an issue than in a finished
|
|
9
|
+
pull request.
|
|
10
|
+
|
|
11
|
+
## Getting set up
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
git clone https://github.com/islavutin-oss/runspace.git
|
|
15
|
+
cd runspace
|
|
16
|
+
python -m venv .venv && source .venv/bin/activate
|
|
17
|
+
pip install -e ".[dev]"
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Run the tests and the linter:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
PYTHONPATH=src pytest -q
|
|
24
|
+
ruff check .
|
|
25
|
+
ruff format --check .
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
CI runs exactly these, on Python 3.10 through 3.13.
|
|
29
|
+
|
|
30
|
+
## What a good pull request looks like
|
|
31
|
+
|
|
32
|
+
- **One change per pull request.** Unrelated fixes bundled together are hard
|
|
33
|
+
to review and harder to revert.
|
|
34
|
+
- **Tests come with the change.** A bug fix should include a test that fails
|
|
35
|
+
before it and passes after.
|
|
36
|
+
- **The suite is green.** Not "green except for a flaky one" — if something
|
|
37
|
+
is flaky, that is worth an issue of its own.
|
|
38
|
+
- **Commit messages say what changed and why.** The subject line is
|
|
39
|
+
imperative and under about 72 characters; the body explains the reasoning
|
|
40
|
+
a reviewer cannot get from the diff.
|
|
41
|
+
|
|
42
|
+
We use [Conventional Commits](https://www.conventionalcommits.org) prefixes:
|
|
43
|
+
`feat:`, `fix:`, `docs:`, `test:`, `refactor:`, `chore:`, `ci:`.
|
|
44
|
+
|
|
45
|
+
## Style
|
|
46
|
+
|
|
47
|
+
The linter settles formatting arguments, so there is nothing to debate:
|
|
48
|
+
`ruff format` owns line width, `ruff check` owns the rest. Type hints on
|
|
49
|
+
public functions. Comments should explain why something is the way it is —
|
|
50
|
+
the code already says what it does.
|
|
51
|
+
|
|
52
|
+
## Licensing
|
|
53
|
+
|
|
54
|
+
Contributions are accepted under the [Apache License 2.0](LICENSE), the same
|
|
55
|
+
licence the project ships under. There is no CLA.
|