Components overview
CLI entrypoint
main.py — parses arguments, selects a subcommand, and hands off to the appropriate runtime path.PortRuntime
runtime.py — routes prompts against the command/tool inventory, builds sessions, runs turn loops, and infers permission denials.QueryEnginePort
query_engine.py — the stateful orchestration layer. Holds session ID, conversation messages, usage tracking, and the transcript store.Commands inventory
commands.py — loads PORTED_COMMANDS from a JSON snapshot; exposes lookup, filtering, and execution shims.Tools inventory
tools.py — loads PORTED_TOOLS from a JSON snapshot; supports simple mode, MCP filtering, and permission-context filtering.Session store
session_store.py — serialises StoredSession objects to .port_sessions/<id>.json and reloads them on demand.TranscriptStore
transcript.py — an in-memory ordered log of conversation entries that supports compaction and flush.PortContext
context.py — captures workspace paths (source, tests, assets, archive) and file counts at bootstrap time.Module structure
Request/response cycle
CLI dispatch
main() in main.py parses the subcommand (bootstrap, turn-loop, route, etc.) and instantiates PortRuntime.Context and workspace bootstrap
PortRuntime.bootstrap_session() calls build_port_context() to snapshot workspace paths and run_setup() to gather platform details. A HistoryLog is created to record events through the lifecycle.Prompt routing
PortRuntime.route_prompt() tokenises the prompt and scores every entry in PORTED_COMMANDS and PORTED_TOOLS against the name, source_hint, and responsibility fields. The top-scoring command and tool are selected first, then remaining slots are filled by score.Permission inference
_infer_permission_denials() inspects the matched tools and gates any whose name contains bash, appending a PermissionDenial with the reason "destructive shell execution remains gated in the Python port".Streaming and turn submission
QueryEnginePort.stream_submit_message() emits structured SSE-style events (message_start, command_match, tool_match, permission_denial, message_delta, message_stop) before calling submit_message() to produce a TurnResult.Bootstrap graph
TheBootstrapGraph in bootstrap_graph.py documents the ordered startup stages that mirror the original TypeScript harness:
Command graph
CommandGraph (in command_graph.py) segments the full command inventory into three buckets:
| Bucket | Source hint criterion |
|---|---|
builtins | No plugin or skills in source_hint |
plugin_like | plugin appears in source_hint |
skill_like | skills appears in source_hint |
Python port vs. TypeScript original
The Python port is a structural mirror, not a line-for-line translation. It preserves the same component boundaries and data shapes while using idiomatic Python constructs (dataclasses,
lru_cache, argparse) in place of TypeScript classes and Zod schemas.| TypeScript concept | Python equivalent |
|---|---|
QueryEngine class | QueryEnginePort dataclass |
| Tool registry object | PORTED_TOOLS tuple + ToolPool |
| Command registry | PORTED_COMMANDS tuple + CommandGraph |
| Session storage | StoredSession + save_session() / load_session() |
| Stream events | stream_submit_message() generator |
| Permission callbacks | ToolPermissionContext.blocks() |