indusagi 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.
- indusagi-0.1.0/.gitignore +8 -0
- indusagi-0.1.0/CHANGELOG.md +101 -0
- indusagi-0.1.0/CREDITS.md +23 -0
- indusagi-0.1.0/NOTICE +17 -0
- indusagi-0.1.0/PARITY_REPORT.md +173 -0
- indusagi-0.1.0/PKG-INFO +158 -0
- indusagi-0.1.0/README.md +117 -0
- indusagi-0.1.0/examples/01_basic_agent.py +87 -0
- indusagi-0.1.0/examples/02_streaming_events.py +92 -0
- indusagi-0.1.0/examples/03_custom_tool_agent.py +138 -0
- indusagi-0.1.0/examples/04_steering_and_abort.py +454 -0
- indusagi-0.1.0/examples/05_coding_agent.py +107 -0
- indusagi-0.1.0/examples/06_readonly_researcher.py +113 -0
- indusagi-0.1.0/examples/07_mcp_agent.py +211 -0
- indusagi-0.1.0/examples/08_traced_agent.py +130 -0
- indusagi-0.1.0/examples/09_orchestrator_workers.py +128 -0
- indusagi-0.1.0/examples/10_pipeline_agents.py +115 -0
- indusagi-0.1.0/examples/11_debate_judge.py +136 -0
- indusagi-0.1.0/examples/12_swarm_crew.py +257 -0
- indusagi-0.1.0/examples/13_large_swarm_mapreduce.py +168 -0
- indusagi-0.1.0/examples/14_smithy_agent_builder.py +155 -0
- indusagi-0.1.0/examples/15_gateway_direct.py +126 -0
- indusagi-0.1.0/examples/README.md +54 -0
- indusagi-0.1.0/examples/calc.py +4 -0
- indusagi-0.1.0/examples/run_all.py +64 -0
- indusagi-0.1.0/pyproject.toml +57 -0
- indusagi-0.1.0/pyrightconfig.json +27 -0
- indusagi-0.1.0/scripts/lineage_scan.py +109 -0
- indusagi-0.1.0/scripts/refresh_models_data.py +736 -0
- indusagi-0.1.0/src/indusagi/__init__.py +34 -0
- indusagi-0.1.0/src/indusagi/_internal/__init__.py +5 -0
- indusagi-0.1.0/src/indusagi/_internal/cancel.py +96 -0
- indusagi-0.1.0/src/indusagi/_internal/env.py +41 -0
- indusagi-0.1.0/src/indusagi/agent/__init__.py +249 -0
- indusagi-0.1.0/src/indusagi/agent/agent.py +1456 -0
- indusagi-0.1.0/src/indusagi/agent/registry.py +440 -0
- indusagi-0.1.0/src/indusagi/agent/sessions.py +1328 -0
- indusagi-0.1.0/src/indusagi/agent/tools.py +518 -0
- indusagi-0.1.0/src/indusagi/ai/__init__.py +288 -0
- indusagi-0.1.0/src/indusagi/ai/env_keys.py +275 -0
- indusagi-0.1.0/src/indusagi/ai/events.py +401 -0
- indusagi-0.1.0/src/indusagi/ai/registry.py +647 -0
- indusagi-0.1.0/src/indusagi/ai/stream.py +1057 -0
- indusagi-0.1.0/src/indusagi/ai/types.py +866 -0
- indusagi-0.1.0/src/indusagi/capabilities/__init__.py +127 -0
- indusagi-0.1.0/src/indusagi/capabilities/backends/__init__.py +22 -0
- indusagi-0.1.0/src/indusagi/capabilities/backends/local.py +658 -0
- indusagi-0.1.0/src/indusagi/capabilities/files/__init__.py +32 -0
- indusagi-0.1.0/src/indusagi/capabilities/files/diff.py +292 -0
- indusagi-0.1.0/src/indusagi/capabilities/files/edit.py +292 -0
- indusagi-0.1.0/src/indusagi/capabilities/files/ls.py +284 -0
- indusagi-0.1.0/src/indusagi/capabilities/files/read.py +266 -0
- indusagi-0.1.0/src/indusagi/capabilities/files/write.py +129 -0
- indusagi-0.1.0/src/indusagi/capabilities/kernel/__init__.py +87 -0
- indusagi-0.1.0/src/indusagi/capabilities/kernel/backends.py +180 -0
- indusagi-0.1.0/src/indusagi/capabilities/kernel/context.py +94 -0
- indusagi-0.1.0/src/indusagi/capabilities/kernel/output.py +131 -0
- indusagi-0.1.0/src/indusagi/capabilities/kernel/registry.py +163 -0
- indusagi-0.1.0/src/indusagi/capabilities/kernel/spec.py +299 -0
- indusagi-0.1.0/src/indusagi/capabilities/planning/__init__.py +30 -0
- indusagi-0.1.0/src/indusagi/capabilities/planning/todo.py +302 -0
- indusagi-0.1.0/src/indusagi/capabilities/registry.py +134 -0
- indusagi-0.1.0/src/indusagi/capabilities/search/__init__.py +16 -0
- indusagi-0.1.0/src/indusagi/capabilities/search/find.py +301 -0
- indusagi-0.1.0/src/indusagi/capabilities/search/grep.py +360 -0
- indusagi-0.1.0/src/indusagi/capabilities/shell/__init__.py +23 -0
- indusagi-0.1.0/src/indusagi/capabilities/shell/bash.py +212 -0
- indusagi-0.1.0/src/indusagi/capabilities/shell/process.py +543 -0
- indusagi-0.1.0/src/indusagi/capabilities/web/__init__.py +16 -0
- indusagi-0.1.0/src/indusagi/capabilities/web/webfetch.py +477 -0
- indusagi-0.1.0/src/indusagi/capabilities/web/websearch.py +371 -0
- indusagi-0.1.0/src/indusagi/connectors/__init__.py +76 -0
- indusagi-0.1.0/src/indusagi/connectors/adapter/__init__.py +20 -0
- indusagi-0.1.0/src/indusagi/connectors/adapter/composio_backend.py +407 -0
- indusagi-0.1.0/src/indusagi/connectors/control/__init__.py +60 -0
- indusagi-0.1.0/src/indusagi/connectors/control/connect.py +269 -0
- indusagi-0.1.0/src/indusagi/connectors/control/tools.py +343 -0
- indusagi-0.1.0/src/indusagi/connectors/core/__init__.py +78 -0
- indusagi-0.1.0/src/indusagi/connectors/core/builder.py +346 -0
- indusagi-0.1.0/src/indusagi/connectors/core/cache.py +129 -0
- indusagi-0.1.0/src/indusagi/connectors/core/port.py +210 -0
- indusagi-0.1.0/src/indusagi/connectors/core/scope_planner.py +130 -0
- indusagi-0.1.0/src/indusagi/connectors/gateway.py +477 -0
- indusagi-0.1.0/src/indusagi/connectors/render/__init__.py +50 -0
- indusagi-0.1.0/src/indusagi/connectors/render/format.py +135 -0
- indusagi-0.1.0/src/indusagi/connectors/render/summarizers.py +229 -0
- indusagi-0.1.0/src/indusagi/interop/__init__.py +95 -0
- indusagi-0.1.0/src/indusagi/interop/protocol_bridge/__init__.py +81 -0
- indusagi-0.1.0/src/indusagi/interop/protocol_bridge/bridge.py +248 -0
- indusagi-0.1.0/src/indusagi/interop/protocol_bridge/contract.py +378 -0
- indusagi-0.1.0/src/indusagi/interop/protocol_bridge/endpoint.py +486 -0
- indusagi-0.1.0/src/indusagi/interop/protocol_bridge/fleet.py +166 -0
- indusagi-0.1.0/src/indusagi/interop/protocol_bridge/host.py +205 -0
- indusagi-0.1.0/src/indusagi/interop/protocol_bridge/schema.py +218 -0
- indusagi-0.1.0/src/indusagi/llmgateway/__init__.py +137 -0
- indusagi-0.1.0/src/indusagi/llmgateway/catalog/__init__.py +41 -0
- indusagi-0.1.0/src/indusagi/llmgateway/catalog/bridge.py +163 -0
- indusagi-0.1.0/src/indusagi/llmgateway/catalog/cards.py +463 -0
- indusagi-0.1.0/src/indusagi/llmgateway/catalog/cost.py +35 -0
- indusagi-0.1.0/src/indusagi/llmgateway/catalog/fallback.py +265 -0
- indusagi-0.1.0/src/indusagi/llmgateway/catalog/full.py +254 -0
- indusagi-0.1.0/src/indusagi/llmgateway/catalog/models_data.json +16806 -0
- indusagi-0.1.0/src/indusagi/llmgateway/catalog/query.py +101 -0
- indusagi-0.1.0/src/indusagi/llmgateway/connectors/__init__.py +72 -0
- indusagi-0.1.0/src/indusagi/llmgateway/connectors/anthropic.py +454 -0
- indusagi-0.1.0/src/indusagi/llmgateway/connectors/azure_openai.py +206 -0
- indusagi-0.1.0/src/indusagi/llmgateway/connectors/bedrock.py +577 -0
- indusagi-0.1.0/src/indusagi/llmgateway/connectors/google.py +444 -0
- indusagi-0.1.0/src/indusagi/llmgateway/connectors/google_vertex.py +541 -0
- indusagi-0.1.0/src/indusagi/llmgateway/connectors/kimi.py +165 -0
- indusagi-0.1.0/src/indusagi/llmgateway/connectors/mock.py +212 -0
- indusagi-0.1.0/src/indusagi/llmgateway/connectors/nvidia.py +175 -0
- indusagi-0.1.0/src/indusagi/llmgateway/connectors/ollama.py +447 -0
- indusagi-0.1.0/src/indusagi/llmgateway/connectors/openai_chat.py +164 -0
- indusagi-0.1.0/src/indusagi/llmgateway/connectors/openai_responses.py +500 -0
- indusagi-0.1.0/src/indusagi/llmgateway/contract/__init__.py +91 -0
- indusagi-0.1.0/src/indusagi/llmgateway/contract/connector.py +62 -0
- indusagi-0.1.0/src/indusagi/llmgateway/contract/conversation.py +138 -0
- indusagi-0.1.0/src/indusagi/llmgateway/contract/emission.py +99 -0
- indusagi-0.1.0/src/indusagi/llmgateway/contract/errors.py +85 -0
- indusagi-0.1.0/src/indusagi/llmgateway/contract/model_card.py +95 -0
- indusagi-0.1.0/src/indusagi/llmgateway/contract/options.py +40 -0
- indusagi-0.1.0/src/indusagi/llmgateway/contract/reply.py +51 -0
- indusagi-0.1.0/src/indusagi/llmgateway/conversion/mappers.py +515 -0
- indusagi-0.1.0/src/indusagi/llmgateway/conversion/openai_compatible.py +386 -0
- indusagi-0.1.0/src/indusagi/llmgateway/conversion/reduce.py +144 -0
- indusagi-0.1.0/src/indusagi/llmgateway/credentials/__init__.py +67 -0
- indusagi-0.1.0/src/indusagi/llmgateway/credentials/oauth.py +226 -0
- indusagi-0.1.0/src/indusagi/llmgateway/credentials/pkce.py +95 -0
- indusagi-0.1.0/src/indusagi/llmgateway/credentials/secrets.py +206 -0
- indusagi-0.1.0/src/indusagi/llmgateway/gateway.py +93 -0
- indusagi-0.1.0/src/indusagi/llmgateway/streaming/__init__.py +19 -0
- indusagi-0.1.0/src/indusagi/llmgateway/streaming/channel.py +77 -0
- indusagi-0.1.0/src/indusagi/llmgateway/streaming/ndjson.py +144 -0
- indusagi-0.1.0/src/indusagi/llmgateway/streaming/sse.py +229 -0
- indusagi-0.1.0/src/indusagi/mcp/__init__.py +174 -0
- indusagi-0.1.0/src/indusagi/mcp/client.py +2135 -0
- indusagi-0.1.0/src/indusagi/memory.py +17 -0
- indusagi-0.1.0/src/indusagi/py.typed +0 -0
- indusagi-0.1.0/src/indusagi/react_host/__init__.py +199 -0
- indusagi-0.1.0/src/indusagi/react_ink/__init__.py +617 -0
- indusagi-0.1.0/src/indusagi/react_ink/components/__init__.py +56 -0
- indusagi-0.1.0/src/indusagi/react_ink/components/changelog.py +187 -0
- indusagi-0.1.0/src/indusagi/react_ink/components/dialogs/__init__.py +103 -0
- indusagi-0.1.0/src/indusagi/react_ink/components/dialogs/frame.py +159 -0
- indusagi-0.1.0/src/indusagi/react_ink/components/dialogs/login.py +285 -0
- indusagi-0.1.0/src/indusagi/react_ink/components/dialogs/model.py +100 -0
- indusagi-0.1.0/src/indusagi/react_ink/components/dialogs/oauth.py +320 -0
- indusagi-0.1.0/src/indusagi/react_ink/components/dialogs/scoped_models.py +312 -0
- indusagi-0.1.0/src/indusagi/react_ink/components/dialogs/selectable.py +370 -0
- indusagi-0.1.0/src/indusagi/react_ink/components/dialogs/session.py +543 -0
- indusagi-0.1.0/src/indusagi/react_ink/components/dialogs/settings.py +212 -0
- indusagi-0.1.0/src/indusagi/react_ink/components/dialogs/startup_picker.py +302 -0
- indusagi-0.1.0/src/indusagi/react_ink/components/dialogs/theme.py +130 -0
- indusagi-0.1.0/src/indusagi/react_ink/components/dialogs/tree.py +153 -0
- indusagi-0.1.0/src/indusagi/react_ink/components/dialogs/user_message.py +193 -0
- indusagi-0.1.0/src/indusagi/react_ink/components/display_block.py +119 -0
- indusagi-0.1.0/src/indusagi/react_ink/components/editor.py +722 -0
- indusagi-0.1.0/src/indusagi/react_ink/components/footer.py +325 -0
- indusagi-0.1.0/src/indusagi/react_ink/components/messages/__init__.py +44 -0
- indusagi-0.1.0/src/indusagi/react_ink/components/messages/assistant.py +218 -0
- indusagi-0.1.0/src/indusagi/react_ink/components/messages/bash.py +109 -0
- indusagi-0.1.0/src/indusagi/react_ink/components/messages/branch_summary.py +74 -0
- indusagi-0.1.0/src/indusagi/react_ink/components/messages/compaction.py +75 -0
- indusagi-0.1.0/src/indusagi/react_ink/components/messages/custom.py +92 -0
- indusagi-0.1.0/src/indusagi/react_ink/components/messages/list.py +329 -0
- indusagi-0.1.0/src/indusagi/react_ink/components/messages/row.py +117 -0
- indusagi-0.1.0/src/indusagi/react_ink/components/messages/skill_invocation.py +105 -0
- indusagi-0.1.0/src/indusagi/react_ink/components/messages/tool_call.py +56 -0
- indusagi-0.1.0/src/indusagi/react_ink/components/messages/tool_result.py +142 -0
- indusagi-0.1.0/src/indusagi/react_ink/components/messages/user.py +90 -0
- indusagi-0.1.0/src/indusagi/react_ink/components/status_line.py +129 -0
- indusagi-0.1.0/src/indusagi/react_ink/components/task_panel.py +344 -0
- indusagi-0.1.0/src/indusagi/react_ink/components/tool_event.py +284 -0
- indusagi-0.1.0/src/indusagi/react_ink/diff/__init__.py +28 -0
- indusagi-0.1.0/src/indusagi/react_ink/diff/structured.py +333 -0
- indusagi-0.1.0/src/indusagi/react_ink/diff/view.py +203 -0
- indusagi-0.1.0/src/indusagi/react_ink/diff/word_diff.py +157 -0
- indusagi-0.1.0/src/indusagi/react_ink/markdown/__init__.py +75 -0
- indusagi-0.1.0/src/indusagi/react_ink/markdown/format_token.py +236 -0
- indusagi-0.1.0/src/indusagi/react_ink/markdown/highlight.py +263 -0
- indusagi-0.1.0/src/indusagi/react_ink/markdown/streaming.py +130 -0
- indusagi-0.1.0/src/indusagi/react_ink/markdown/table.py +127 -0
- indusagi-0.1.0/src/indusagi/react_ink/markdown/view.py +137 -0
- indusagi-0.1.0/src/indusagi/react_ink/theme_adapter.py +496 -0
- indusagi-0.1.0/src/indusagi/react_ink/types.py +291 -0
- indusagi-0.1.0/src/indusagi/react_ink/utils/__init__.py +92 -0
- indusagi-0.1.0/src/indusagi/react_ink/utils/message_groups.py +436 -0
- indusagi-0.1.0/src/indusagi/react_ink/utils/selection_dialog.py +40 -0
- indusagi-0.1.0/src/indusagi/react_ink/utils/session_browser.py +322 -0
- indusagi-0.1.0/src/indusagi/react_ink/utils/tool_display.py +679 -0
- indusagi-0.1.0/src/indusagi/runtime/__init__.py +74 -0
- indusagi-0.1.0/src/indusagi/runtime/cadence/__init__.py +36 -0
- indusagi-0.1.0/src/indusagi/runtime/cadence/fold.py +192 -0
- indusagi-0.1.0/src/indusagi/runtime/cadence/reducer.py +439 -0
- indusagi-0.1.0/src/indusagi/runtime/conductor/__init__.py +17 -0
- indusagi-0.1.0/src/indusagi/runtime/conductor/agent.py +696 -0
- indusagi-0.1.0/src/indusagi/runtime/contract/__init__.py +94 -0
- indusagi-0.1.0/src/indusagi/runtime/contract/config.py +51 -0
- indusagi-0.1.0/src/indusagi/runtime/contract/effect.py +69 -0
- indusagi-0.1.0/src/indusagi/runtime/contract/errors.py +45 -0
- indusagi-0.1.0/src/indusagi/runtime/contract/events.py +100 -0
- indusagi-0.1.0/src/indusagi/runtime/contract/run_state.py +75 -0
- indusagi-0.1.0/src/indusagi/runtime/contract/session.py +58 -0
- indusagi-0.1.0/src/indusagi/runtime/contract/signal.py +88 -0
- indusagi-0.1.0/src/indusagi/runtime/contract/tools.py +65 -0
- indusagi-0.1.0/src/indusagi/runtime/dispatch/__init__.py +11 -0
- indusagi-0.1.0/src/indusagi/runtime/dispatch/scheduler.py +295 -0
- indusagi-0.1.0/src/indusagi/runtime/ledger/__init__.py +19 -0
- indusagi-0.1.0/src/indusagi/runtime/ledger/accumulator.py +85 -0
- indusagi-0.1.0/src/indusagi/runtime/ledger/bus.py +84 -0
- indusagi-0.1.0/src/indusagi/runtime/memory/__init__.py +23 -0
- indusagi-0.1.0/src/indusagi/runtime/memory/compactor.py +229 -0
- indusagi-0.1.0/src/indusagi/runtime/memory/estimate.py +91 -0
- indusagi-0.1.0/src/indusagi/runtime/store/__init__.py +18 -0
- indusagi-0.1.0/src/indusagi/runtime/store/dag.py +141 -0
- indusagi-0.1.0/src/indusagi/runtime/store/hash.py +281 -0
- indusagi-0.1.0/src/indusagi/runtime/store/persist.py +193 -0
- indusagi-0.1.0/src/indusagi/runtime/turn/__init__.py +10 -0
- indusagi-0.1.0/src/indusagi/runtime/turn/driver.py +76 -0
- indusagi-0.1.0/src/indusagi/runtime/wire/__init__.py +18 -0
- indusagi-0.1.0/src/indusagi/runtime/wire/projectors.py +119 -0
- indusagi-0.1.0/src/indusagi/shell_app/__init__.py +115 -0
- indusagi-0.1.0/src/indusagi/shell_app/auth_cli/__init__.py +16 -0
- indusagi-0.1.0/src/indusagi/shell_app/auth_cli/oauth_cli.py +723 -0
- indusagi-0.1.0/src/indusagi/shell_app/boot/__init__.py +34 -0
- indusagi-0.1.0/src/indusagi/shell_app/boot/context.py +172 -0
- indusagi-0.1.0/src/indusagi/shell_app/boot/pipeline.py +94 -0
- indusagi-0.1.0/src/indusagi/shell_app/boot/stages.py +613 -0
- indusagi-0.1.0/src/indusagi/shell_app/cli.py +404 -0
- indusagi-0.1.0/src/indusagi/shell_app/config/__init__.py +47 -0
- indusagi-0.1.0/src/indusagi/shell_app/config/settings.py +327 -0
- indusagi-0.1.0/src/indusagi/shell_app/invocation/__init__.py +48 -0
- indusagi-0.1.0/src/indusagi/shell_app/invocation/flags.py +209 -0
- indusagi-0.1.0/src/indusagi/shell_app/invocation/parse.py +389 -0
- indusagi-0.1.0/src/indusagi/shell_app/locate/__init__.py +24 -0
- indusagi-0.1.0/src/indusagi/shell_app/locate/brand.py +130 -0
- indusagi-0.1.0/src/indusagi/shell_app/locate/locator.py +270 -0
- indusagi-0.1.0/src/indusagi/shell_app/runners/__init__.py +56 -0
- indusagi-0.1.0/src/indusagi/shell_app/runners/contract.py +197 -0
- indusagi-0.1.0/src/indusagi/shell_app/runners/one_shot.py +90 -0
- indusagi-0.1.0/src/indusagi/shell_app/runners/registry.py +54 -0
- indusagi-0.1.0/src/indusagi/shell_app/runners/repl.py +240 -0
- indusagi-0.1.0/src/indusagi/shell_app/runners/wire.py +480 -0
- indusagi-0.1.0/src/indusagi/shell_app/upgrade/__init__.py +10 -0
- indusagi-0.1.0/src/indusagi/shell_app/upgrade/upgrades.py +162 -0
- indusagi-0.1.0/src/indusagi/smithy/__init__.py +165 -0
- indusagi-0.1.0/src/indusagi/smithy/config/__init__.py +27 -0
- indusagi-0.1.0/src/indusagi/smithy/config/flag_reader.py +265 -0
- indusagi-0.1.0/src/indusagi/smithy/forge.py +350 -0
- indusagi-0.1.0/src/indusagi/smithy/knowledge/__init__.py +25 -0
- indusagi-0.1.0/src/indusagi/smithy/knowledge/guides/authoring-an-agent.md +53 -0
- indusagi-0.1.0/src/indusagi/smithy/knowledge/guides/choosing-tools.md +49 -0
- indusagi-0.1.0/src/indusagi/smithy/knowledge/guides/model-selection.md +51 -0
- indusagi-0.1.0/src/indusagi/smithy/knowledge/guides/writing-system-prompts.md +53 -0
- indusagi-0.1.0/src/indusagi/smithy/knowledge/loader.py +227 -0
- indusagi-0.1.0/src/indusagi/smithy/knowledge/manifest.json +29 -0
- indusagi-0.1.0/src/indusagi/smithy/persona/__init__.py +52 -0
- indusagi-0.1.0/src/indusagi/smithy/persona/blueprint.py +265 -0
- indusagi-0.1.0/src/indusagi/smithy/persona/define_agent.py +178 -0
- indusagi-0.1.0/src/indusagi/smithy/persona/profiles.py +148 -0
- indusagi-0.1.0/src/indusagi/smithy/runtime/__init__.py +22 -0
- indusagi-0.1.0/src/indusagi/smithy/runtime/tool_ledger.py +222 -0
- indusagi-0.1.0/src/indusagi/smithy/ui/__init__.py +45 -0
- indusagi-0.1.0/src/indusagi/smithy/ui/transcript.py +578 -0
- indusagi-0.1.0/src/indusagi/swarm/__init__.py +150 -0
- indusagi-0.1.0/src/indusagi/swarm/coordinator.py +512 -0
- indusagi-0.1.0/src/indusagi/swarm/isolation/__init__.py +32 -0
- indusagi-0.1.0/src/indusagi/swarm/isolation/runner.py +115 -0
- indusagi-0.1.0/src/indusagi/swarm/isolation/worktree.py +296 -0
- indusagi-0.1.0/src/indusagi/swarm/kernel/__init__.py +36 -0
- indusagi-0.1.0/src/indusagi/swarm/kernel/faults.py +91 -0
- indusagi-0.1.0/src/indusagi/swarm/kernel/ids.py +34 -0
- indusagi-0.1.0/src/indusagi/swarm/kernel/json_cell.py +378 -0
- indusagi-0.1.0/src/indusagi/swarm/kernel/jsonl_log.py +197 -0
- indusagi-0.1.0/src/indusagi/swarm/postbox/__init__.py +38 -0
- indusagi-0.1.0/src/indusagi/swarm/postbox/channel.py +220 -0
- indusagi-0.1.0/src/indusagi/swarm/postbox/codecs.py +328 -0
- indusagi-0.1.0/src/indusagi/swarm/roster/__init__.py +34 -0
- indusagi-0.1.0/src/indusagi/swarm/roster/manifest.py +370 -0
- indusagi-0.1.0/src/indusagi/swarm/telemetry/__init__.py +29 -0
- indusagi-0.1.0/src/indusagi/swarm/telemetry/activity.py +283 -0
- indusagi-0.1.0/src/indusagi/swarm/workboard/__init__.py +31 -0
- indusagi-0.1.0/src/indusagi/swarm/workboard/board.py +464 -0
- indusagi-0.1.0/src/indusagi/swarm/workboard/dep_graph.py +160 -0
- indusagi-0.1.0/src/indusagi/tracing/__init__.py +46 -0
- indusagi-0.1.0/src/indusagi/tracing/adapter/__init__.py +11 -0
- indusagi-0.1.0/src/indusagi/tracing/adapter/runtime_trace.py +196 -0
- indusagi-0.1.0/src/indusagi/tracing/channel/__init__.py +22 -0
- indusagi-0.1.0/src/indusagi/tracing/channel/signal.py +145 -0
- indusagi-0.1.0/src/indusagi/tracing/recorder/__init__.py +19 -0
- indusagi-0.1.0/src/indusagi/tracing/recorder/recorder.py +137 -0
- indusagi-0.1.0/src/indusagi/tracing/recorder/sampling.py +112 -0
- indusagi-0.1.0/src/indusagi/tracing/redaction/__init__.py +20 -0
- indusagi-0.1.0/src/indusagi/tracing/redaction/secret_scrubber.py +228 -0
- indusagi-0.1.0/src/indusagi/tracing/registry/__init__.py +9 -0
- indusagi-0.1.0/src/indusagi/tracing/registry/hub.py +100 -0
- indusagi-0.1.0/src/indusagi/tracing/signal/__init__.py +50 -0
- indusagi-0.1.0/src/indusagi/tracing/signal/handle.py +219 -0
- indusagi-0.1.0/src/indusagi/tracing/signal/segment.py +182 -0
- indusagi-0.1.0/src/indusagi/tracing/sinks/__init__.py +23 -0
- indusagi-0.1.0/src/indusagi/tracing/sinks/base.py +89 -0
- indusagi-0.1.0/src/indusagi/tracing/sinks/console.py +95 -0
- indusagi-0.1.0/src/indusagi/tracing/sinks/file.py +87 -0
- indusagi-0.1.0/src/indusagi/tracing/sinks/stream.py +99 -0
- indusagi-0.1.0/src/indusagi/tui/__init__.py +99 -0
- indusagi-0.1.0/src/indusagi/tui/autocomplete.py +657 -0
- indusagi-0.1.0/src/indusagi/tui/contracts.py +140 -0
- indusagi-0.1.0/src/indusagi/tui/editor.py +1630 -0
- indusagi-0.1.0/src/indusagi/tui/fuzzy.py +282 -0
- indusagi-0.1.0/src/indusagi/tui/keybindings.py +412 -0
- indusagi-0.1.0/src/indusagi/tui/keys.py +1437 -0
- indusagi-0.1.0/src/indusagi/tui/theme_types.py +75 -0
- indusagi-0.1.0/src/indusagi/tui/utils.py +1174 -0
- indusagi-0.1.0/src/indusagi/ui_bridge/__init__.py +118 -0
- indusagi-0.1.0/src/indusagi/ui_bridge/adapter.py +558 -0
- indusagi-0.1.0/src/indusagi/ui_bridge/app.py +788 -0
- indusagi-0.1.0/src/indusagi/ui_bridge/facade_types.py +51 -0
- indusagi-0.1.0/tests/agent/agent_suite_helpers.py +248 -0
- indusagi-0.1.0/tests/agent/test_agent_abort_salvage.py +135 -0
- indusagi-0.1.0/tests/agent/test_agent_prompt.py +217 -0
- indusagi-0.1.0/tests/agent/test_agent_steering.py +219 -0
- indusagi-0.1.0/tests/agent/test_agent_stream_framing.py +178 -0
- indusagi-0.1.0/tests/agent/test_agent_tools.py +271 -0
- indusagi-0.1.0/tests/agent/test_session_manager.py +315 -0
- indusagi-0.1.0/tests/ai/test_complete.py +96 -0
- indusagi-0.1.0/tests/ai/test_env_keys.py +225 -0
- indusagi-0.1.0/tests/ai/test_event_framing.py +237 -0
- indusagi-0.1.0/tests/ai/test_event_stream.py +270 -0
- indusagi-0.1.0/tests/ai/test_model_registry.py +132 -0
- indusagi-0.1.0/tests/capabilities/test_capabilities.py +670 -0
- indusagi-0.1.0/tests/connectors/test_connectors_saas.py +304 -0
- indusagi-0.1.0/tests/fixtures/ts_session_v3.jsonl +9 -0
- indusagi-0.1.0/tests/interop/test_interop.py +269 -0
- indusagi-0.1.0/tests/llmgateway/test_catalog.py +141 -0
- indusagi-0.1.0/tests/llmgateway/test_catalog_fallback.py +365 -0
- indusagi-0.1.0/tests/llmgateway/test_gateway.py +222 -0
- indusagi-0.1.0/tests/llmgateway/test_streaming.py +308 -0
- indusagi-0.1.0/tests/mcp/conftest.py +259 -0
- indusagi-0.1.0/tests/mcp/test_client.py +298 -0
- indusagi-0.1.0/tests/mcp/test_memory_parity.py +43 -0
- indusagi-0.1.0/tests/mcp/test_pool.py +262 -0
- indusagi-0.1.0/tests/react_ink/test_diff.py +186 -0
- indusagi-0.1.0/tests/runtime/test_cadence.py +267 -0
- indusagi-0.1.0/tests/runtime/test_runtime.py +463 -0
- indusagi-0.1.0/tests/shell_app/test_auth_cli.py +205 -0
- indusagi-0.1.0/tests/shell_app/test_boot_flags.py +358 -0
- indusagi-0.1.0/tests/shell_app/test_shell_app.py +296 -0
- indusagi-0.1.0/tests/smithy/test_smithy.py +416 -0
- indusagi-0.1.0/tests/swarm/test_swarm.py +447 -0
- indusagi-0.1.0/tests/test_public_api.py +184 -0
- indusagi-0.1.0/tests/test_scaffold.py +86 -0
- indusagi-0.1.0/tests/tracing/test_tracing.py +287 -0
- indusagi-0.1.0/tests/tui/test_fuzzy.py +202 -0
- indusagi-0.1.0/tests/tui/test_keys.py +629 -0
- indusagi-0.1.0/tests/tui/test_text_width.py +449 -0
- indusagi-0.1.0/tests/ui_bridge/test_exit_transcript.py +322 -0
- indusagi-0.1.0/tests/ui_bridge/test_interactive_app.py +466 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0 — 2026-06-10
|
|
4
|
+
|
|
5
|
+
First release of the Python rebuild of **indusagi**, ported from the
|
|
6
|
+
TypeScript implementation in `../indus-rebuild/` (npm `indusagi` 0.12.x)
|
|
7
|
+
following `../indus-rebuild/PYTHON_PORT_PLAN/PLAN.md` (milestones M0-M8).
|
|
8
|
+
Single distribution `indusagi`, Python >= 3.11, console script `indusagi`.
|
|
9
|
+
|
|
10
|
+
### Subsystems
|
|
11
|
+
|
|
12
|
+
- **`indusagi.llmgateway`** — zero-SDK LLM gateway on httpx: 11 wire
|
|
13
|
+
connectors (anthropic, openai-chat, openai-responses, google, google-vertex,
|
|
14
|
+
azure-openai, nvidia, kimi, ollama, mock; bedrock as the deliberate
|
|
15
|
+
fail-fast `unsupported` stub), unified 8-variant `Emission` protocol with
|
|
16
|
+
error-as-terminal-emission, re-iterable channels, WHATWG SSE + NDJSON
|
|
17
|
+
framers, 13-card model catalog with fluent `models()` query and
|
|
18
|
+
`estimate_cost`, env `SECRET_TABLE`, OAuth 2.0 + PKCE S256.
|
|
19
|
+
- **`indusagi.tracing`** — segments, signal channels, console/file/stream
|
|
20
|
+
sinks, FNV-1a sampling gate, secret scrubbing.
|
|
21
|
+
- **`indusagi.runtime`** — pure-FSM agent core: `cadence()` reducer
|
|
22
|
+
(7 phases, 7 signals, 5 effects, 7 run events), conductor with steering
|
|
23
|
+
into in-flight runs, abort, 64-turn budget, compaction that never orphans
|
|
24
|
+
tool results, content-addressed session DAG + append-only JSONL store with
|
|
25
|
+
resume/branch, run ledger pub/sub.
|
|
26
|
+
- **`indusagi.capabilities`** — 12 built-in tools (read, write, edit, ls,
|
|
27
|
+
grep, find, bash, process, todo_set, todo_read, websearch, webfetch) over
|
|
28
|
+
abstract Fs/Shell seams: UTF-8 byte-budget clamp, verbatim Myers diff,
|
|
29
|
+
background process table, JS-regex-dialect grep; read-only/coding/all
|
|
30
|
+
collections and one-call `tool_box()`.
|
|
31
|
+
- **`indusagi.interop`** — MCP both ways on the official `mcp` SDK: client
|
|
32
|
+
endpoints (stdio + SSE) with `server__tool` namespacing, schema
|
|
33
|
+
normalization and fleet fault isolation; provider host publishing a ToolBox
|
|
34
|
+
over `tools/list` / `tools/call`.
|
|
35
|
+
- **`indusagi.connectors`** — Composio SaaS layer: enable/execute/connect/
|
|
36
|
+
status control tools, OAuth polling state machine, identity-stable
|
|
37
|
+
hydration cache.
|
|
38
|
+
- **`indusagi.swarm`** — file-backed multi-agent crew: JsonCell (mkdir lock,
|
|
39
|
+
atomic `os.replace` publish) + JsonlLog kernel, ULID ids, dep-gated
|
|
40
|
+
TicketBoard with cycle rejection, cursor-exact mailboxes, git-worktree
|
|
41
|
+
isolation, `run_round` coordinator.
|
|
42
|
+
- **`indusagi.smithy`** — agent-builder meta-tool: 4-step interview,
|
|
43
|
+
profiles, pydantic blueprint validation, knowledge pack shipped as package
|
|
44
|
+
data (manifest + 4 guides), transcript secret redaction.
|
|
45
|
+
- **`indusagi.shell_app`** — CLI: hand-ported table-driven flag parser with
|
|
46
|
+
TS-byte-identical error strings, help/version/print/NDJSON-wire/REPL modes,
|
|
47
|
+
3-layer settings merge, idempotent upgrades, `INDUSAGI_HOME` override,
|
|
48
|
+
`auth login/refresh/status` storing a TS-format `auth.json` under the
|
|
49
|
+
build's own `~/.pindusagi` state dir (deliberate owner-requested
|
|
50
|
+
divergence 2026-06-10: auth no longer shared with TS installs; TS state
|
|
51
|
+
`~/.indusagi` untouched).
|
|
52
|
+
- **`indusagi.tui` / `indusagi.react_ink` / `indusagi.ui_bridge` /
|
|
53
|
+
`indusagi.react_host`** — Textual TUI: flicker-free streaming markdown
|
|
54
|
+
(tables, highlighted fences), structured diffs with 0.4-threshold word
|
|
55
|
+
emphasis, tool cards with clamp/expand, all 12 dialogs as ModalScreens
|
|
56
|
+
(model, scoped models, session browser, startup picker, settings, theme
|
|
57
|
+
with live preview, login, OAuth, tree, fork-from-message), footer
|
|
58
|
+
token/cost/context stats (70/90% thresholds), Esc abort / Ctrl-C exit,
|
|
59
|
+
queued-message restore; `react_host` collapsed to a backend-pinning shim.
|
|
60
|
+
`tui/keys.py` is a full pure port of the Kitty/legacy key decoder, kept
|
|
61
|
+
for vocabulary and tests (Textual drives live input).
|
|
62
|
+
- **`indusagi.ai` / `.agent` / `.mcp` / `.memory`** — compat facades as thin
|
|
63
|
+
shims over the core (106/97/65 exported names; `memory` intentionally
|
|
64
|
+
empty); single model catalog shared with `llmgateway` via a drift-gated
|
|
65
|
+
JSON data file; TS v3 session JSONL files remain readable.
|
|
66
|
+
- **`indusagi._internal`** — framework-wide `CancelToken` (the AbortSignal
|
|
67
|
+
replacement, honored through streams, tool runners, web tools) and the
|
|
68
|
+
single env-var registry.
|
|
69
|
+
|
|
70
|
+
### Tests and gates
|
|
71
|
+
|
|
72
|
+
- 749 tests passing (pytest + pytest-asyncio, network-free: mock connector,
|
|
73
|
+
respx, Textual Pilot). By area: tui 444, ai 68, mcp 43, llmgateway 41,
|
|
74
|
+
agent 31, capabilities 23, smithy 23, runtime 15, react_ink 12,
|
|
75
|
+
scaffold 9, connectors 8, shell_app 8, swarm 8, tracing 7, interop 5,
|
|
76
|
+
ui_bridge 4.
|
|
77
|
+
- pyright 1.1.405 strict over `src/indusagi`: 0 errors, 0 warnings (ad-hoc
|
|
78
|
+
config; not yet checked in).
|
|
79
|
+
- Packaging: hatchling sdist + wheel (`dist/indusagi-0.1.0*`); wheel ships
|
|
80
|
+
`py.typed`, the model-catalog JSON, the smithy knowledge pack, and
|
|
81
|
+
NOTICE/CREDITS under `dist-info/licenses/`; fresh-venv install gate passed
|
|
82
|
+
(`indusagi --help`/`--version`, all subsystem imports). PyPI publish
|
|
83
|
+
pending.
|
|
84
|
+
|
|
85
|
+
### Key decisions (from the port plan)
|
|
86
|
+
|
|
87
|
+
- Clean-room core ported **once**; the ~40k-LOC TS facade surface ships as
|
|
88
|
+
thin shims over it (PLAN.md §1, R-1).
|
|
89
|
+
- No provider SDKs: the gateway speaks raw wire dialects over httpx.
|
|
90
|
+
- TUI is a Textual **rewrite**, not an Ink transliteration (03_TUI_MIGRATION).
|
|
91
|
+
- `AbortSignal` → custom `CancelToken`; connector generators never raise —
|
|
92
|
+
errors are terminal emissions.
|
|
93
|
+
- On-disk state: own `~/.pindusagi` state dir (deliberate owner-requested
|
|
94
|
+
divergence 2026-06-10 — separate from, and never touching, the TS installs'
|
|
95
|
+
`~/.indusagi`); `auth.json` keeps the byte-compatible TS *format* but is no
|
|
96
|
+
longer a shared store; session store format is port-local (documented in
|
|
97
|
+
PLAN.md M0).
|
|
98
|
+
- Bedrock connector stays a fail-fast `unsupported` stub, matching TS.
|
|
99
|
+
|
|
100
|
+
Full audit: see [PARITY_REPORT.md](PARITY_REPORT.md) (26 checklist items:
|
|
101
|
+
23 done, 3 partial, 0 missing).
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Credits & Acknowledgements
|
|
2
|
+
|
|
3
|
+
Indusagi (Python rebuild) is an independent implementation, designed and written from scratch. It
|
|
4
|
+
reuses no third-party application source code.
|
|
5
|
+
|
|
6
|
+
## Standards & specifications implemented from primary sources
|
|
7
|
+
|
|
8
|
+
Indusagi implements these open, public standards directly from their specifications:
|
|
9
|
+
|
|
10
|
+
- OAuth 2.0 PKCE — **RFC 7636**
|
|
11
|
+
- Server-Sent Events framing — **WHATWG HTML / EventSource spec**
|
|
12
|
+
- Model Context Protocol — **modelcontextprotocol.io** spec + the official `mcp` Python SDK
|
|
13
|
+
- JSON Schema — **json-schema.org**
|
|
14
|
+
- VT/ANSI/Kitty terminal escape grammars — vendor terminal specs
|
|
15
|
+
|
|
16
|
+
Provider HTTP request/response field names follow each provider's public API documentation and are
|
|
17
|
+
used as functional, interoperable interfaces.
|
|
18
|
+
|
|
19
|
+
## Dependencies
|
|
20
|
+
|
|
21
|
+
Runtime dependencies are declared in `pyproject.toml` and used under their own licenses — including
|
|
22
|
+
`httpx`, `pydantic`, `wcwidth`, `python-ulid`, and `regex`, plus the optional `mcp` SDK, `textual`,
|
|
23
|
+
`pygments`, and `markdown-it-py`.
|
indusagi-0.1.0/NOTICE
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Indusagi (Python rebuild)
|
|
2
|
+
Copyright (c) 2026 the Indusagi authors
|
|
3
|
+
|
|
4
|
+
This product is an independent implementation, designed and written from scratch.
|
|
5
|
+
It reuses no third-party application source code.
|
|
6
|
+
|
|
7
|
+
------------------------------------------------------------------------------
|
|
8
|
+
Standards & specifications implemented from primary sources
|
|
9
|
+
------------------------------------------------------------------------------
|
|
10
|
+
|
|
11
|
+
- OAuth 2.0 PKCE ....................... RFC 7636
|
|
12
|
+
- Server-Sent Events framing .......... WHATWG HTML / EventSource
|
|
13
|
+
- Model Context Protocol .............. modelcontextprotocol.io + SDK
|
|
14
|
+
- JSON Schema ......................... json-schema.org
|
|
15
|
+
- Provider HTTP APIs .................. each provider's public documentation
|
|
16
|
+
|
|
17
|
+
See CREDITS.md for the fuller acknowledgement.
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# Parity report — indusagi Python rebuild vs TypeScript `indus-rebuild`
|
|
2
|
+
|
|
3
|
+
**Date:** 2026-06-10
|
|
4
|
+
**Scope:** the M8 feature-parity checklist from
|
|
5
|
+
`../indus-rebuild/PYTHON_PORT_PLAN/PLAN.md` §5, walked item-by-item against this
|
|
6
|
+
tree (`src/indusagi/`, `tests/`, `dist/`).
|
|
7
|
+
**Ground truth:** the TypeScript implementation in `../indus-rebuild/src/`.
|
|
8
|
+
|
|
9
|
+
## Summary
|
|
10
|
+
|
|
11
|
+
| | count |
|
|
12
|
+
|---|---:|
|
|
13
|
+
| Checklist items | **26** |
|
|
14
|
+
| Done | **26** |
|
|
15
|
+
| Partial | **0** |
|
|
16
|
+
| Missing | **0** |
|
|
17
|
+
|
|
18
|
+
**Test suite:** 755 passed (pytest, network-free; mock connector + respx;
|
|
19
|
+
re-verified 2026-06-10).
|
|
20
|
+
**Typecheck:** `pyrightconfig.json` checked in at the repo root (pyright
|
|
21
|
+
1.1.405, standard mode) as a coverage ratchet over the packages that check
|
|
22
|
+
clean today (`__init__.py`, `memory.py`, `_internal`, `interop`, `react_host`,
|
|
23
|
+
`runtime`); the config's own note corrects the earlier ad-hoc "strict 0 errors
|
|
24
|
+
over all of src" claim, which did not reproduce (the ad-hoc run had analyzed
|
|
25
|
+
0 files).
|
|
26
|
+
**Lineage:** `scripts/lineage_scan.py` exits 0 — "LINEAGE GATE PASSED: no
|
|
27
|
+
pi-mono lineage markers in src/indusagi" (re-verified 2026-06-10).
|
|
28
|
+
**Packaging:** `python -m build` produces `dist/indusagi-0.1.0-py3-none-any.whl`
|
|
29
|
+
and `dist/indusagi-0.1.0.tar.gz`; fresh-venv install gate (python3.13,
|
|
30
|
+
`[mcp,tui]` extras) passed: `indusagi --help` / `--version` exit 0, all
|
|
31
|
+
subsystem imports succeed (CLI boot + subsystem imports re-verified
|
|
32
|
+
2026-06-10).
|
|
33
|
+
|
|
34
|
+
**Overall verdict: parity achieved.** All 26 checklist rows are done. The three
|
|
35
|
+
formerly-partial rows (exit-transcript print, `AWS_REGION` registry routing,
|
|
36
|
+
lineage scan + checked-in pyright config) have been closed with the evidence in
|
|
37
|
+
their rows below. PyPI publish itself has not been executed (wheel is built and
|
|
38
|
+
verified locally; see follow-ups).
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Checklist
|
|
43
|
+
|
|
44
|
+
Status legend: **done** — implemented and evidenced. (No rows are currently
|
|
45
|
+
partial.)
|
|
46
|
+
|
|
47
|
+
### Gateway (M1)
|
|
48
|
+
|
|
49
|
+
| Item | Status | Evidence |
|
|
50
|
+
|---|---|---|
|
|
51
|
+
| 11 connectors: anthropic, openai-chat, openai-responses, google, google-vertex, azure-openai, nvidia, kimi, ollama, mock; bedrock = fail-fast `unsupported` stub | done | `src/indusagi/llmgateway/connectors/__init__.py` `CONNECTOR_REGISTRY` maps all 11 ApiKinds (runtime check: 11/11, missing=∅). `bedrock.py:508-513` raises `gateway_error("unsupported", "bedrock streaming requires SigV4 (todo)")` after assembling body/region — matches the TS stub. `tests/llmgateway/`: 41 passed. |
|
|
52
|
+
| Unified `Emission` protocol incl. error-as-terminal-emission; re-iterable `Channel`; `fold_reply` ordering (thinking → text → tool calls, JSON arg reassembly) | done | `contract/emission.py` 8-variant union incl. `ErrorEmission`/`DoneEmission`; `streaming/channel.py` `GeneratorChannel` re-invokes its factory per `__aiter__` (`test_stream_channel_is_re_iterable`); `conversion/reduce.py` fold verified live: blocks = [Thinking, Text, ToolCall], split args `'{"a"' + ': 1}'` → `{"a": 1}`. |
|
|
53
|
+
| `MODEL_CARDS` (14) + fluent `models()` query + `estimate_cost`; env `SECRET_TABLE`; OAuth 2.0 + PKCE S256 | done | `catalog/cards.py` has **13** cards — TS ground truth `cards.ts` also has 13 with identical ids (the plan's "14" is a miscount; parity holds — see waiver W-5). `catalog/query.py:66` `models()`; cost tests in `tests/llmgateway/test_catalog.py`; `credentials/secrets.py:58` `SECRET_TABLE`; `pkce.py` S256 verified live (challenge == b64url(sha256)); `oauth.py` `exchange_code`/`refresh_token`. |
|
|
54
|
+
| SSE (WHATWG edge cases) + NDJSON framers; HTTP status → error-kind mapping (401/403 auth, 429 rate_limit) | done | `streaming/sse.py` + `ndjson.py`; `tests/llmgateway/test_streaming.py` has 29 tests (CR/LF/CRLF splits, multi-line data, comments, mid-UTF-8 chunk splits, cancellation, httpx integration). `_classify_status` in `connectors/anthropic.py:277-282` and `conversion/openai_compatible.py:185-187`: 401/403 → `auth`, 429 → `rate_limit` (verified by reading; no dedicated unit test for the status map). |
|
|
55
|
+
|
|
56
|
+
### Runtime + tools (M2)
|
|
57
|
+
|
|
58
|
+
| Item | Status | Evidence |
|
|
59
|
+
|---|---|---|
|
|
60
|
+
| Pure FSM phases idle→invoking→streaming→dispatching→compacting→settled/faulted; 7 signals, 5 effects, 7 run events | done | `runtime/contract/run_state.py` `RunPhase` = exactly those 7 literals; `signal.py` 7 signal classes; `effect.py` 5 effect classes; `events.py` 7 RunEvent classes. Reducer purity: `tests/runtime/test_cadence.py::test_never_mutates_the_input_snapshot`; 15 runtime tests pass. |
|
|
61
|
+
| Steering into in-flight runs; abort; 64-turn budget; compaction (triggerRatio/keepRecent, cut-point never orphans tool_result) | done | `conductor/agent.py:600-612` folds submit into a live run (`tests/agent/test_agent_steering.py`, 3 passed); abort: `TestRuntimeAbort`; `agent.py:529-583` faults `turn_budget` at default `max_turns=64` (code-verified; no dedicated test); `memory/compactor.py` `find_cut_point` advances past tool_result-carrying turns (code-verified) + `TestRuntimeCompaction` passes trigger_ratio/keep_recent end-to-end. |
|
|
62
|
+
| Content-addressed session DAG + JSONL store + resume + branch; ledger pub/sub | done | `store/hash.py` SHA-256 over JS-canonical JSON `{parent,turn,createdAt}`; `store/dag.py` `branch_from`/`resume`/`path_to` (`branch_from` verified by direct execution — leaf moves to branch point); `store/persist.py` append-only `.jsonl` SessionStore with migrators; `ledger/bus.py` `RunLedger` subscribe/publish. `tests/runtime/` `TestRuntimeBranchResume` covers persist+resume; `branch_from` itself has no suite test. |
|
|
63
|
+
| 11 tools (read/write/edit/ls/grep/find/bash/process/todo_set/todo_read/websearch/webfetch) with byte-budget clamp, Myers diffs, background process table, JS-regex-flag mapping in grep descriptor | done | `capabilities/registry.py` `_all_tools` registers exactly the **12** listed names (the row says "11" but lists 12 — plan miscount, see waiver W-6). `kernel/output.py` UTF-8 byte-budget clamp snapping to char boundaries; `files/diff.py` Myers O(ND); `shell/process.py` `ProcessTable` for background jobs; `search/grep.py:314-348` descriptor documents the JS regex dialect + flag letters g/i/m/s/u/y. `tests/capabilities/`: 23 passed covering every tool. |
|
|
64
|
+
| read-only / coding / all collections; `tool_box()` one-call assembly | done | `capabilities/registry.py`: `collection("read-only")` = 6 names, `"coding"` = read-only + 6 mutating, `"all"` = `registry.names()`; `tool_box(collection, cwd)` mints a local ToolContext per dispatch. Tests: `test_builtin_registry_exposes_the_three_named_collections`, `test_tool_box_coding_descriptors_lists_every_coding_tool`, `test_all_collection_boxes_every_registered_tool` — all pass. |
|
|
65
|
+
|
|
66
|
+
### Bridges (M3)
|
|
67
|
+
|
|
68
|
+
| Item | Status | Evidence |
|
|
69
|
+
|---|---|---|
|
|
70
|
+
| MCP client: stdio + SSE endpoints, `server__tool` namespacing, schema normalization, fleet isolation | done | `src/indusagi/interop/protocol_bridge/endpoint.py` (`stdio_client`+`sse_client`, lines 303-322), `contract.py:217` `QUALIFIER="__"`, `schema.py` `normalize_schema`, `fleet.py` `_settle_all` isolation. `tests/interop/test_interop.py` asserts `"echo__ping"`; `tests/mcp/test_pool.py` covers per-server fault isolation. 48 passed across interop/mcp. |
|
|
71
|
+
| MCP provider host publishing the agent's ToolBox; in-memory round-trip tests | done | `interop/protocol_bridge/host.py` `create_provider_host(box)` maps `box.descriptors()` to `tools/list` and routes `tools/call` into `box.runner.run`. `tests/interop/test_interop.py` round-trips `list_tools`/`invoke("ping") → "pong"` over `mcp.shared.memory.create_client_server_memory_streams`; 6 tests pass. |
|
|
72
|
+
| Composio: enable/execute/connect/status control tools, OAuth polling state machine, identity-stable hydration cache | done | `src/indusagi/connectors/control/tools.py` `CONTROL_SPECS` = saas_enable/execute/connect/status; `control/connect.py` `CONNECT_RULES` + `plan_connect` + `initiate_and_await` poll loop; `core/cache.py` `HashCache` (content-hash, task-memoizing). `tests/connectors/test_connectors_saas.py` asserts `second[i] IS first[i]` on re-enable; 8 passed. |
|
|
73
|
+
|
|
74
|
+
### Crew + builder (M4)
|
|
75
|
+
|
|
76
|
+
| Item | Status | Evidence |
|
|
77
|
+
|---|---|---|
|
|
78
|
+
| JsonCell/JsonlLog kernel (locking, atomic publish), ULID ids, SwarmFault kinds | done | `src/indusagi/swarm/kernel/json_cell.py` (mkdir-lock with stale reclaim + backoff, `os.replace` atomic publish), `jsonl_log.py` (O_APPEND single-write), `ids.py` `new_id` via ulid, `faults.py` 6 kinds (lock_timeout/validation/not_found/conflict/isolation/spawn). `tests/swarm/test_swarm.py` `TestJsonCell`: parallel-mutate no lost update + validation fault. |
|
|
79
|
+
| TicketBoard dep-gated `ready()` + cycle rejection; cursor-exact mailbox; git-worktree isolation; `run_round` | done | `swarm/workboard/board.py` `ready()` gates on deps all `"done"`, `add()` rejects cycles via `DepGraph.first_cycle`; `postbox/channel.py` per-reader JsonCell cursor advanced inside `mutate`; `isolation/worktree.py` `Workspace` create/list/remove; `coordinator.py` `run_round`. `tests/swarm/test_swarm.py` 8 passed (worktree test exercised real git, no skip). |
|
|
80
|
+
| Smithy interview + profiles + blueprint validation + knowledge pack + transcript redaction | done | `src/indusagi/smithy/forge.py` `_INTERVIEW` 4-step script + `build_interactive`/`build_from_config`; `persona/profiles.py` `get_profile`; `persona/blueprint.py` `validate_blueprint`/`BlueprintError`; `knowledge/loader.py` + `manifest.json` + 4 guide `.md` files (shipped in the wheel); `ui/transcript.py` `_mask_secrets` + length-cap redaction. `tests/smithy/test_smithy.py` 23 passed. |
|
|
81
|
+
|
|
82
|
+
### CLI (M5)
|
|
83
|
+
|
|
84
|
+
| Item | Status | Evidence |
|
|
85
|
+
|---|---|---|
|
|
86
|
+
| Flag grammar byte-compatible (incl. error strings); modes help/version/print/wire/repl with TS precedence | done | `src/indusagi/shell_app/invocation/{flags.py,parse.py}`: 10-flag table + all 4 error strings byte-identical to `indus-rebuild/src/shell-app/invocation/parse.ts`; `_derive_mode` precedence verbatim. Smoke: `--help`/`--version` exit 0; `--bogus` → `unrecognised flag "--bogus".` exit 2. `tests/shell_app/`: 8/8 pass. |
|
|
87
|
+
| NDJSON wire protocol compatible with existing hosts; `auth login/refresh/status` over a TS-format auth.json — deliberate owner-requested divergence 2026-06-10: separate `~/.pindusagi` state dir, auth no longer shared; TS state (`~/.indusagi`) untouched | done | `runners/wire.py` pins `JSON.stringify` byte-compat (verified: `{"a":5,"b":1e-7,"c":null}`; camelCase keys in TS RunSnapshot order). `auth_cli/oauth_cli.py` login/refresh/status over PKCE, store `<profile>/auth.json` (`brand.py` `.pindusagi`); smoke: `auth status` read a TS-format auth.json, exit 0. Wire test passes. |
|
|
88
|
+
| Settings 3-layer merge; idempotent upgrades; `INDUSAGI_HOME` override; exit codes via return (never `process.exit` analogue) | done | `config/settings.py` `load_settings` merges DEFAULT_SETTINGS ← global ← project (tested); `upgrade/upgrades.py` marker idempotency (2nd pass returns `[]`, tested); `locate/locator.py` honors `INDUSAGI_HOME` (`$INDUSAGI_HOME` *is* the state dir — re-documented per plan); `cli.py` returns codes, `sys.exit` only in the `run()` shim. |
|
|
89
|
+
|
|
90
|
+
### TUI (M6)
|
|
91
|
+
|
|
92
|
+
| Item | Status | Evidence |
|
|
93
|
+
|---|---|---|
|
|
94
|
+
| Streaming flicker-free markdown (tables, fences w/ highlighting, `~` literal); structured diffs with word emphasis; tool cards with clamp/expand | done | `react_ink/markdown/`: `streaming.py` wraps Textual `MarkdownStream`; `table.py`, `highlight.py`, `view.py` `highlight_code` toggle; `format_token.py` keeps `~` literal. `diff/word_diff.py` `CHANGE_THRESHOLD=0.4` (12 tests pass). `tool_event.py` `clamp_content_lines` + `"... N more"` clamp; Textual Pilot test renders streamed markdown + tool card. |
|
|
95
|
+
| All 12 dialogs (model, scoped-models multi-select, session browser w/ rename+delete+scope+sort, startup picker, settings, theme w/ live preview, login, OAuth, tree, fork-from-message) | done | `react_ink/components/dialogs/` has 12 `.py` ModalScreens mapping 1:1 to the 12 TS `.tsx` files (89-543 LOC each): `session.py` binds Tab scope / Ctrl+S sort / Ctrl+R rename / Ctrl+D delete; `theme.py` live-previews via `self.app.theme` (Pilot-tested); `scoped_models.py` uses `SelectionList` multi-select; `user_message.py` = fork-from-message. |
|
|
96
|
+
| Footer stats (tokens/cost/context % thresholds 70/90), TaskPanel, StatusLine; Esc abort / Ctrl-C exit; queued-message restore | done | `react_ink/components/footer.py:274-276`: percent > 90 → error, > 70 → warning; TaskPanel/StatusLine mounted in `ui_bridge/app.py` `compose()`; Esc → `agent.abort()` Pilot-tested (`test_escape_aborts_hung_stream_and_app_stays_alive`), Ctrl-C → exit(0); `_submit_draft` restores a queued draft via `set_text` when a run is active. |
|
|
97
|
+
| Theme switching live; session scrollback persistence strategy from 03 (alternate-screen + exit transcript print) | done | Live theme: `ThemeDialog` sets `self.app.theme` per highlight, `test_theme_dialog_opens_live_previews_and_esc_dismisses` passes. Alternate screen + `VerticalScroll` scrollback: `messages/list.py` `MessageList(VerticalScroll)`. Exit transcript print (03 §10.1): `ui_bridge/app.py` `exit_transcript_text` (line 303) + `InteractiveApp.exit_transcript()` (line 729); `mount_interactive` renders it via Rich `Console` after `run_async` returns (lines 784-787; `transcript_file` injectable, default stdout; empty session prints nothing). `tests/ui_bridge/test_exit_transcript.py`: 6 passed, incl. headless-Pilot end-to-end asserting prompt, streamed assistant text, and tool summaries reach stdout in conversation order. |
|
|
98
|
+
|
|
99
|
+
### Compat surface (M7)
|
|
100
|
+
|
|
101
|
+
| Item | Status | Evidence |
|
|
102
|
+
|---|---|---|
|
|
103
|
+
| `indusagi.ai`/`.agent`/`.mcp` shims pass their new test suite; `indusagi.memory` ships empty; single model catalog; TS v3 session JSONL readable | done | `src/indusagi/{ai,agent,mcp}/__init__.py` export 106/97/65 TS-vocabulary names; `pytest tests/ai tests/agent tests/mcp` = 142 passed. `memory.py` `__all__ = []` + `tests/mcp/test_memory_parity.py`. `ai/registry.py:493` seeds from `llmgateway.catalog.full_catalog` with a drift-gate test. `tests/agent/test_session_manager.py` reads `tests/fixtures/ts_session_v3.jsonl`. |
|
|
104
|
+
|
|
105
|
+
### Cross-cutting (all milestones)
|
|
106
|
+
|
|
107
|
+
| Item | Status | Evidence |
|
|
108
|
+
|---|---|---|
|
|
109
|
+
| `CancelToken` honored end-to-end (model stream, tool runners, web tools, MCP invokes) | done | `sse.py`/`ndjson.py` race reads vs token (`test_streaming.py:187-198`); gateway aborted-stop test (`test_gateway.py:131`); `scheduler.py` chains per-call child tokens → `registry.py:66` ctx; bash kill-on-cancel tested (`test_capabilities.py` ~345); `web/webfetch.py:353`; MCP invokes do a pre-flight cancel check only — TS parity (`tool-factory.ts:75`). |
|
|
110
|
+
| Single env-var registry (`INDUSAGI_HOME`, `INDUSAGI_REACT_HOST_ROOT` re-documented, provider key probes one module, `AWS_REGION`, Vertex project/location) | done | `_internal/env.py` is the registry; `INDUSAGI_HOME` ok (`locate/locator.py:155`, `test_shell_app.py:72`); react-host root drop documented (`react_host/__init__.py`); key probes + Vertex go through `read_raw` (`credentials/secrets.py`, `ai/env_keys.py`, `google_vertex.py:137-144`). `AWS_REGION` now routes through the registry too: `bedrock.py:33` imports `read_raw` from `_internal/env`, and lines 101-105 resolve `AWS_REGION` → `AWS_DEFAULT_REGION` → `AWS_BEDROCK_REGION` via `read_raw`; `env.py:26` names `AWS_REGION` as the canonical escape-hatch example. No config read probes `os.environ` outside `_internal/env.py` (the only remaining direct use, `capabilities/backends/local.py:360`, spreads the full environ into a child-process env — process spawning, not a config read). |
|
|
111
|
+
| `py.typed` shipped; pyright strict clean; lineage scan green; NOTICE/CREDITS in the wheel | done | Wheel `dist/indusagi-0.1.0-py3-none-any.whl` contains `indusagi/py.typed` + `dist-info/licenses/{NOTICE,CREDITS.md}` (via `license-files` in `pyproject.toml`). `scripts/lineage_scan.py` is ported and green: exit 0, "LINEAGE GATE PASSED: no pi-mono lineage markers in src/indusagi" (re-verified 2026-06-10; required by 02_MODULE_CONVERSION_GUIDE.md:1008 and 05_PYPI_PACKAGING.md:82). `pyrightconfig.json` is checked in at the repo root (pyright 1.1.405, standard mode) as a documented coverage ratchet over the packages that check clean (`__init__.py`, `memory.py`, `_internal`, `interop`, `react_host`, `runtime`) — the config records that the audit-era "strict 0 errors over all of src" claim did not reproduce, and its ratchet policy (expand includes, never add per-rule ignores, never remove entries) makes the gate reproducible. |
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Follow-ups
|
|
116
|
+
|
|
117
|
+
The three former partial items (P-1 exit-transcript print, P-2 `AWS_REGION`
|
|
118
|
+
registry routing, P-3 lineage scan + checked-in pyright config) are resolved —
|
|
119
|
+
evidence lives in their checklist rows above.
|
|
120
|
+
|
|
121
|
+
**Still outstanding (not a checklist row):** the actual PyPI publish (TestPyPI
|
|
122
|
+
rehearsal + `uv publish` via a CI release workflow, M8 deliverable) has not been
|
|
123
|
+
executed. The wheel/sdist in `dist/` passed the fresh-venv install gate; the
|
|
124
|
+
release gates (pytest, lineage scan, pyright ratchet) should run in CI before
|
|
125
|
+
any `uv publish`.
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## Deliberate waivers
|
|
130
|
+
|
|
131
|
+
These are intentional deviations or plan corrections, each anchored to a
|
|
132
|
+
recorded plan decision — not gaps.
|
|
133
|
+
|
|
134
|
+
- **W-1 · Bedrock is a fail-fast `unsupported` stub.** `bedrock.py:508-513`
|
|
135
|
+
raises after assembling body/region, exactly like the TS connector. Required
|
|
136
|
+
by PLAN.md §5 ("bedrock = fail-fast `unsupported` stub (parity with TS)") and
|
|
137
|
+
the M1 deliverables ("Bedrock keeps the deliberate `unsupported` fail-fast
|
|
138
|
+
stub").
|
|
139
|
+
- **W-2 · On-disk state is fully port-local.** Deliberate owner-requested
|
|
140
|
+
divergence 2026-06-10: the Python build uses its own separate `~/.pindusagi`
|
|
141
|
+
state dir (override: `INDUSAGI_HOME`) and never reads or writes the TS
|
|
142
|
+
installs' `~/.indusagi`; TS state untouched. The auth.json *format* stays
|
|
143
|
+
byte-compatible with TS, but the store is no longer shared; the runtime
|
|
144
|
+
session JSONL/hash format carries no cross-language round-trip guarantee
|
|
145
|
+
(PLAN.md M0 on-disk state policy, convention (3) — "documented, not
|
|
146
|
+
accidental"). Read-compatibility with TS v3 session files is still provided
|
|
147
|
+
at the facade layer (`tests/agent/test_session_manager.py` +
|
|
148
|
+
`tests/fixtures/ts_session_v3.jsonl`).
|
|
149
|
+
- **W-3 · `react_host` collapses to a backend-pinning shim.** Loader probing and
|
|
150
|
+
the jsx-runtime subpath are deleted; `INDUSAGI_REACT_HOST_ROOT` semantics are
|
|
151
|
+
re-documented in `src/indusagi/react_host/__init__.py` (199 lines). PLAN.md §2
|
|
152
|
+
export-mapping table ("jsx-runtime deleted") and M6 deliverables.
|
|
153
|
+
- **W-4 · `indusagi.memory` ships intentionally empty.** `src/indusagi/memory.py`
|
|
154
|
+
with `__all__ = []`, guarded by `tests/mcp/test_memory_parity.py`. PLAN.md §2
|
|
155
|
+
("intentionally empty phantom module (kept)") and M7.
|
|
156
|
+
- **W-5 · `MODEL_CARDS` count is 13, not 14.** The TS ground truth
|
|
157
|
+
(`indus-rebuild/src/llmgateway/catalog/cards.ts`) has 13 cards; the plan's
|
|
158
|
+
"14" is a miscount. The Python `catalog/cards.py` carries 13 cards with
|
|
159
|
+
identical ids — parity with the actual source holds.
|
|
160
|
+
- **W-6 · Tool count is 12, not 11.** The checklist row says "11 tools" but
|
|
161
|
+
itself lists 12 names (read, write, edit, ls, grep, find, bash, process,
|
|
162
|
+
todo_set, todo_read, websearch, webfetch); the TS registry has the same 12.
|
|
163
|
+
`capabilities/registry.py` registers exactly those names.
|
|
164
|
+
- **W-7 · MCP invoke cancellation is pre-flight-only.** A CancelToken is checked
|
|
165
|
+
before dispatch but in-flight MCP calls are not interrupted — this mirrors the
|
|
166
|
+
TS behavior (`indus-rebuild/src/interop/protocol_bridge/tool-factory.ts:75`)
|
|
167
|
+
and is parity, not a regression.
|
|
168
|
+
- **W-8 · TUI key decoding at runtime is Textual's.** Per
|
|
169
|
+
03_TUI_MIGRATION.md / 07_RISKS C3, the running app uses Textual's input
|
|
170
|
+
driver; `src/indusagi/tui/keys.py` (1,437 lines) is nevertheless a full pure
|
|
171
|
+
port of `src/ui/keys.ts` (Kitty + legacy tables, press/repeat/release,
|
|
172
|
+
bracketed-paste guards) kept for the key-id vocabulary, keybinding tables,
|
|
173
|
+
and test corpus — it just is not in the live input path.
|
indusagi-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: indusagi
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Indusagi — a terminal-first AI coding agent framework. Python rebuild.
|
|
5
|
+
Project-URL: Homepage, https://github.com/varunisrani/indusagi-ts
|
|
6
|
+
Project-URL: Repository, https://github.com/varunisrani/indusagi-ts
|
|
7
|
+
Project-URL: Issues, https://github.com/varunisrani/indusagi-ts/issues
|
|
8
|
+
Author: Varun Israni
|
|
9
|
+
Author-email: IndusAGI Team <team@indusagi.ai>
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: CREDITS.md
|
|
12
|
+
License-File: NOTICE
|
|
13
|
+
Keywords: agent,ai,cli,framework,llm,mcp,tui
|
|
14
|
+
Classifier: Development Status :: 4 - Beta
|
|
15
|
+
Classifier: Environment :: Console
|
|
16
|
+
Classifier: Intended Audience :: Developers
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
22
|
+
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
23
|
+
Classifier: Typing :: Typed
|
|
24
|
+
Requires-Python: >=3.11
|
|
25
|
+
Requires-Dist: httpx>=0.27
|
|
26
|
+
Requires-Dist: pydantic>=2.7
|
|
27
|
+
Requires-Dist: python-ulid>=2.7
|
|
28
|
+
Requires-Dist: regex>=2024.4.16
|
|
29
|
+
Requires-Dist: wcwidth>=0.2.13
|
|
30
|
+
Provides-Extra: dev
|
|
31
|
+
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
|
|
32
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
33
|
+
Requires-Dist: respx>=0.21; extra == 'dev'
|
|
34
|
+
Provides-Extra: mcp
|
|
35
|
+
Requires-Dist: mcp>=1.0; extra == 'mcp'
|
|
36
|
+
Provides-Extra: tui
|
|
37
|
+
Requires-Dist: markdown-it-py>=3.0; extra == 'tui'
|
|
38
|
+
Requires-Dist: pygments>=2.18; extra == 'tui'
|
|
39
|
+
Requires-Dist: textual>=0.80; extra == 'tui'
|
|
40
|
+
Description-Content-Type: text/markdown
|
|
41
|
+
|
|
42
|
+
# indusagi (Python rebuild)
|
|
43
|
+
|
|
44
|
+
Python rebuild of **indusagi** — a terminal-first AI coding agent framework.
|
|
45
|
+
Ported from the TypeScript implementation in `../indus-rebuild/` following the
|
|
46
|
+
conversion plan in `../indus-rebuild/PYTHON_PORT_PLAN/`.
|
|
47
|
+
|
|
48
|
+
Status: 0.1.0 — all plan milestones (M0-M8) built; 749 tests passing.
|
|
49
|
+
See [PARITY_REPORT.md](PARITY_REPORT.md) for the item-by-item audit against the
|
|
50
|
+
TypeScript build and [CHANGELOG.md](CHANGELOG.md) for the release summary.
|
|
51
|
+
|
|
52
|
+
## Layout
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
src/indusagi/
|
|
56
|
+
├── _internal/ # CancelToken (AbortSignal replacement), env registry
|
|
57
|
+
├── llmgateway/ # zero-SDK LLM provider gateway (httpx wire connectors)
|
|
58
|
+
├── tracing/ # observability: segments, sinks, redaction, sampling
|
|
59
|
+
├── runtime/ # pure-FSM agent runtime: reducer, conductor, sessions
|
|
60
|
+
├── capabilities/ # built-in tool suite over Fs/Shell seams
|
|
61
|
+
├── interop/ # MCP bridge (official `mcp` SDK)
|
|
62
|
+
├── connectors/ # Composio SaaS connectors
|
|
63
|
+
├── swarm/ # file-backed multi-agent crew layer
|
|
64
|
+
├── smithy/ # agent-builder meta-tool
|
|
65
|
+
├── shell_app/ # CLI: print / NDJSON wire / REPL runners, OAuth login
|
|
66
|
+
├── tui/ # terminal primitives: keys, text width, fuzzy, bindings
|
|
67
|
+
├── react_ink/ # Textual widgets (markdown stream, diff view, dialogs)
|
|
68
|
+
├── ui_bridge/ # runtime ↔ TUI projection + interactive Textual app
|
|
69
|
+
├── react_host/ # backend-pinning shim (TS react-host collapsed)
|
|
70
|
+
└── ai/ agent/ mcp/ memory.py # compat facades (thin shims over the core)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Install
|
|
74
|
+
|
|
75
|
+
Not yet on PyPI (publish pending). Install from the built wheel:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
pip install dist/indusagi-0.1.0-py3-none-any.whl
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Extras:
|
|
82
|
+
|
|
83
|
+
- `indusagi[tui]` — Textual + Pygments + markdown-it-py; required for the
|
|
84
|
+
interactive terminal UI.
|
|
85
|
+
- `indusagi[mcp]` — official `mcp` SDK; required for `--mcp` server mounting
|
|
86
|
+
and the `indusagi.interop` / `indusagi.mcp` surfaces.
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
pip install "dist/indusagi-0.1.0-py3-none-any.whl[mcp,tui]"
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
The core (gateway, runtime, tools, CLI print/wire modes) needs only
|
|
93
|
+
httpx, pydantic, wcwidth, python-ulid, and regex.
|
|
94
|
+
|
|
95
|
+
## Development
|
|
96
|
+
|
|
97
|
+
Python >= 3.11 (developed and verified on 3.13).
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
python3.13 -m venv .venv
|
|
101
|
+
.venv/bin/pip install -e ".[dev,mcp,tui]"
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Test:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
.venv/bin/pytest # 749 tests; network-free (mock connector, respx, Textual Pilot)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Gates (run from the repo root; both must pass before publishing):
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
.venv/bin/python scripts/lineage_scan.py # lineage gate: exits 1 if any pi-mono lineage marker survives in src/indusagi (compat shims excluded)
|
|
114
|
+
npx -y pyright@1.1.405 # typecheck gate: 0 errors/0 warnings over the pyrightconfig.json ratchet scope (expand include as packages come clean)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Build sdist + wheel (hatchling):
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
.venv/bin/pip install build
|
|
121
|
+
.venv/bin/python -m build # → dist/indusagi-0.1.0.tar.gz + .whl
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
The wheel ships `py.typed`, the model-catalog data
|
|
125
|
+
(`llmgateway/catalog/models_data.json`), the smithy knowledge pack
|
|
126
|
+
(`smithy/knowledge/manifest.json` + guides), and NOTICE/CREDITS under
|
|
127
|
+
`dist-info/licenses/`.
|
|
128
|
+
|
|
129
|
+
## Run
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
indusagi --help # usage; exit 0
|
|
133
|
+
indusagi --version # "indusagi 0.1.0"
|
|
134
|
+
indusagi -p "explain this repo" # one-shot print mode to stdout
|
|
135
|
+
indusagi --json # NDJSON wire mode over stdio (for hosts)
|
|
136
|
+
indusagi # interactive TUI in a terminal (needs [tui] extra)
|
|
137
|
+
indusagi auth login # OAuth + PKCE; writes ~/.pindusagi/auth.json
|
|
138
|
+
indusagi auth status # reads this build's own auth.json
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Flags also include `--model/-m`, `--interactive/-i`, `--cwd`, `--system`,
|
|
142
|
+
`--no-tools`, and repeatable `--mcp <server>` — see `indusagi --help`. With a
|
|
143
|
+
prompt and no TTY it answers once and exits; attended with no prompt it opens
|
|
144
|
+
the interactive loop.
|
|
145
|
+
|
|
146
|
+
The TUI (Textual, alternate screen) provides streaming markdown, structured
|
|
147
|
+
diff and tool cards, twelve dialogs (model/session/theme/login/...), footer
|
|
148
|
+
token/cost/context stats, Esc to abort a run and Ctrl-C to exit. API keys are
|
|
149
|
+
read from the usual provider env vars (e.g. `ANTHROPIC_API_KEY`); state lives
|
|
150
|
+
under `~/.pindusagi/` (override with `INDUSAGI_HOME`). This is the Python
|
|
151
|
+
build's own state directory — deliberately separate from the TypeScript
|
|
152
|
+
installs' `~/.indusagi`, which this build never reads or writes (owner
|
|
153
|
+
decision, 2026-06-10).
|
|
154
|
+
|
|
155
|
+
## Licensing
|
|
156
|
+
|
|
157
|
+
MIT. See [NOTICE](NOTICE) and [CREDITS.md](CREDITS.md) (both included in the
|
|
158
|
+
wheel).
|
indusagi-0.1.0/README.md
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# indusagi (Python rebuild)
|
|
2
|
+
|
|
3
|
+
Python rebuild of **indusagi** — a terminal-first AI coding agent framework.
|
|
4
|
+
Ported from the TypeScript implementation in `../indus-rebuild/` following the
|
|
5
|
+
conversion plan in `../indus-rebuild/PYTHON_PORT_PLAN/`.
|
|
6
|
+
|
|
7
|
+
Status: 0.1.0 — all plan milestones (M0-M8) built; 749 tests passing.
|
|
8
|
+
See [PARITY_REPORT.md](PARITY_REPORT.md) for the item-by-item audit against the
|
|
9
|
+
TypeScript build and [CHANGELOG.md](CHANGELOG.md) for the release summary.
|
|
10
|
+
|
|
11
|
+
## Layout
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
src/indusagi/
|
|
15
|
+
├── _internal/ # CancelToken (AbortSignal replacement), env registry
|
|
16
|
+
├── llmgateway/ # zero-SDK LLM provider gateway (httpx wire connectors)
|
|
17
|
+
├── tracing/ # observability: segments, sinks, redaction, sampling
|
|
18
|
+
├── runtime/ # pure-FSM agent runtime: reducer, conductor, sessions
|
|
19
|
+
├── capabilities/ # built-in tool suite over Fs/Shell seams
|
|
20
|
+
├── interop/ # MCP bridge (official `mcp` SDK)
|
|
21
|
+
├── connectors/ # Composio SaaS connectors
|
|
22
|
+
├── swarm/ # file-backed multi-agent crew layer
|
|
23
|
+
├── smithy/ # agent-builder meta-tool
|
|
24
|
+
├── shell_app/ # CLI: print / NDJSON wire / REPL runners, OAuth login
|
|
25
|
+
├── tui/ # terminal primitives: keys, text width, fuzzy, bindings
|
|
26
|
+
├── react_ink/ # Textual widgets (markdown stream, diff view, dialogs)
|
|
27
|
+
├── ui_bridge/ # runtime ↔ TUI projection + interactive Textual app
|
|
28
|
+
├── react_host/ # backend-pinning shim (TS react-host collapsed)
|
|
29
|
+
└── ai/ agent/ mcp/ memory.py # compat facades (thin shims over the core)
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Install
|
|
33
|
+
|
|
34
|
+
Not yet on PyPI (publish pending). Install from the built wheel:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pip install dist/indusagi-0.1.0-py3-none-any.whl
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Extras:
|
|
41
|
+
|
|
42
|
+
- `indusagi[tui]` — Textual + Pygments + markdown-it-py; required for the
|
|
43
|
+
interactive terminal UI.
|
|
44
|
+
- `indusagi[mcp]` — official `mcp` SDK; required for `--mcp` server mounting
|
|
45
|
+
and the `indusagi.interop` / `indusagi.mcp` surfaces.
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pip install "dist/indusagi-0.1.0-py3-none-any.whl[mcp,tui]"
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The core (gateway, runtime, tools, CLI print/wire modes) needs only
|
|
52
|
+
httpx, pydantic, wcwidth, python-ulid, and regex.
|
|
53
|
+
|
|
54
|
+
## Development
|
|
55
|
+
|
|
56
|
+
Python >= 3.11 (developed and verified on 3.13).
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
python3.13 -m venv .venv
|
|
60
|
+
.venv/bin/pip install -e ".[dev,mcp,tui]"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Test:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
.venv/bin/pytest # 749 tests; network-free (mock connector, respx, Textual Pilot)
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Gates (run from the repo root; both must pass before publishing):
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
.venv/bin/python scripts/lineage_scan.py # lineage gate: exits 1 if any pi-mono lineage marker survives in src/indusagi (compat shims excluded)
|
|
73
|
+
npx -y pyright@1.1.405 # typecheck gate: 0 errors/0 warnings over the pyrightconfig.json ratchet scope (expand include as packages come clean)
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Build sdist + wheel (hatchling):
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
.venv/bin/pip install build
|
|
80
|
+
.venv/bin/python -m build # → dist/indusagi-0.1.0.tar.gz + .whl
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
The wheel ships `py.typed`, the model-catalog data
|
|
84
|
+
(`llmgateway/catalog/models_data.json`), the smithy knowledge pack
|
|
85
|
+
(`smithy/knowledge/manifest.json` + guides), and NOTICE/CREDITS under
|
|
86
|
+
`dist-info/licenses/`.
|
|
87
|
+
|
|
88
|
+
## Run
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
indusagi --help # usage; exit 0
|
|
92
|
+
indusagi --version # "indusagi 0.1.0"
|
|
93
|
+
indusagi -p "explain this repo" # one-shot print mode to stdout
|
|
94
|
+
indusagi --json # NDJSON wire mode over stdio (for hosts)
|
|
95
|
+
indusagi # interactive TUI in a terminal (needs [tui] extra)
|
|
96
|
+
indusagi auth login # OAuth + PKCE; writes ~/.pindusagi/auth.json
|
|
97
|
+
indusagi auth status # reads this build's own auth.json
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Flags also include `--model/-m`, `--interactive/-i`, `--cwd`, `--system`,
|
|
101
|
+
`--no-tools`, and repeatable `--mcp <server>` — see `indusagi --help`. With a
|
|
102
|
+
prompt and no TTY it answers once and exits; attended with no prompt it opens
|
|
103
|
+
the interactive loop.
|
|
104
|
+
|
|
105
|
+
The TUI (Textual, alternate screen) provides streaming markdown, structured
|
|
106
|
+
diff and tool cards, twelve dialogs (model/session/theme/login/...), footer
|
|
107
|
+
token/cost/context stats, Esc to abort a run and Ctrl-C to exit. API keys are
|
|
108
|
+
read from the usual provider env vars (e.g. `ANTHROPIC_API_KEY`); state lives
|
|
109
|
+
under `~/.pindusagi/` (override with `INDUSAGI_HOME`). This is the Python
|
|
110
|
+
build's own state directory — deliberately separate from the TypeScript
|
|
111
|
+
installs' `~/.indusagi`, which this build never reads or writes (owner
|
|
112
|
+
decision, 2026-06-10).
|
|
113
|
+
|
|
114
|
+
## Licensing
|
|
115
|
+
|
|
116
|
+
MIT. See [NOTICE](NOTICE) and [CREDITS.md](CREDITS.md) (both included in the
|
|
117
|
+
wheel).
|