Identifiers
sessionId
sessionId
session_index.id. The UI/sidebar identifier shown in the sessions list. Used for fork/merge lineage (parent_session_id), cross-table joins, and the active-session state. Generated as a UUID at session creation.conversationId
conversationId
sdkSessionId in Orion’s DB — separate column from session_index.id. Used for SDK resume (projects/<conversationId>/ on disk) and as the cache key for Pi’s AgentSession (in-memory map keyed by conversationId).sessionId ≠ conversationId. They map 1:1 today but they are conceptually different identifiers. The handoff finding “Pi maps conversationId to disk-backed SessionManager files” refers to conversationId.sdkSessionId
sdkSessionId
session_index table for the SDK’s conversationId. Used during resume to pass back to query({ resume: sdkSessionId }).firebase_uid
firebase_uid
auth Mutex in Rust and forwarded as env var to subprocesses. See env-var-forwarding.md for why this is a Mutex+env pair.rootConversationId
rootConversationId
conversationId of the top-level conversation (not the immediate parent). Used by SubagentJsonlWriter for the path <vault>/.orion/subagent-events/<rootConversationId>/events.jsonl.toolUseId / parentToolUseId
toolUseId / parentToolUseId
toolUseId: the id of a tool_use block emitted by an agent. parentToolUseId: when an agent spawns a subagent via Task (Claude) or spawn_subagent (Pi), the subagent’s events carry the parent’s toolUseId so the frontend can nest them correctly.Engines
Claude SDK (engine: 'claude')
Claude SDK (engine: 'claude')
sdk-runner.mjs → SDK internally spawns cli.js). Communicates with the sidecar via stdin/stdout JSON-line.Pi (engine: 'pi')
Pi (engine: 'pi')
piAgentQuery(). Built on @mariozechner/pi-coding-agent. Supports OpenAI, Google, OpenRouter, Anthropic-via-Pi, and other providers.routeModel
routeModel
model-router.mjs:23-54 that parses a model string into {engine, provider, model}. Decides which engine handles a turn.isOpenAiResponsesModel
isOpenAiResponsesModel
model-router.mjs:96-123 — returns true for openai, openai-codex, azure-openai-responses providers. Gates Pi’s MCP proxy mode vs legacy bridged mode.AgentSession
AgentSession
conversationId in handler.mjs. Reused on follow-up turns to skip setup phase. See GAP-A1 for the frozen-prompt implication.MCP & permissions
internalServers
internalServers
canUseTool closure. Populated by trackingCreateServer() for the 5 internal servers (orion, orion-tools, canvas, terminal, codexlens) plus any plugin-namespaced servers.BAKED_IN_TRUSTED_SERVERS
BAKED_IN_TRUSTED_SERVERS
config/constants.mjs:7-12. Values: ['shadcn', 'docs', 'claude-code-docs', 'orion']. Separate from internalServers — these are “permanently trusted” regardless of per-query state.proxy mode (Pi)
proxy mode (Pi)
mcp__server__tool Pi ToolDefinitions, registers a single mcp proxy tool that brokers search → describe → call against InternalMcpManager + CombinedMcpManager.legacy bridged mode (Pi)
legacy bridged mode (Pi)
mcp__server__tool. The 37-tool surface.denyWrite
denyWrite
policy-loader.mjs:82-127. User cannot remove built-ins. Includes .env, *.pem, **/.ssh/**, **/.aws/**, **/orion.db, **/.orion/mcp-oauth/**, etc.lookupToolPermission
lookupToolPermission
canUseTool.mjs:81-100 that queries the mcp_tool_permissions DB table for user-configured block/allow/ask. Only called on Claude SDK path, not Pi — see GAP-B1.Canvas
CanvasMode vs widget
CanvasMode vs widget
CanvasMode is a string union for file-backed surfaces: document, plaintext, code, spreadsheet, pdf, htmlpreview, presentation, fallback. widget is also in the union — but conceptually different: it’s the widget track, activated by setWidget() not by openFile(). Mutually exclusive: setting one clears the other.Spec / WidgetSpec
Spec / WidgetSpec
@json-render/core: { root: string; elements: Record<string, UIElement> }. The “flat” format means children are referenced by id, not nested.orionRegistry / orionCatalog
orionRegistry / orionCatalog
orionCatalog is the Zod-typed component catalog at widget-catalog.ts. orionRegistry is the runtime wiring of catalog → React components at registry/index.ts. The catalog feeds catalog.prompt() (system prompt for AI); the registry feeds <Renderer registry={...}/>.WidgetCanvas
WidgetCanvas
src/components/canvas/editors/WidgetCanvas.tsx that renders a widget spec via @json-render/react’s Renderer against orionRegistry. Used when mode === 'widget'.EXTENSION_MAP / DIRECT_OPEN_EXTENSIONS
EXTENSION_MAP / DIRECT_OPEN_EXTENSIONS
EXTENSION_MAP (file-router.ts:20-75) maps known extensions to a CanvasMode. DIRECT_OPEN_EXTENSIONS (constants.ts:19-28) are binary formats that bypass canvas entirely and open in the system default app via shell.open().Background work
Recipe mode
Recipe mode
payload.executionMode === 'recipe') that forces Claude SDK regardless of payload.model. Used for legacy Composio recipe execution. Setting model: 'google/gemini-2.5-flash' on a recipe job is silently overridden.Autopilot
Autopilot
autopilots (what), autopilot_triggers (when), autopilot_runs (proposal+run). Three-layer enforcement (DDL CHECK + runtime JS branch + Rust command guard) on acceptance_mode: 'suggest' | 'auto'.acceptance_mode
acceptance_mode
autopilots table. 'suggest' (default) → autopilot fires create proposals only; user must accept. 'auto' → autopilot fires create para_tasks atomically without user prompt. 'auto' requires explicit_user_opt_in=true at create time (Rust guard).BACKGROUND_MODEL_DEFAULTS / FALLBACKS
BACKGROUND_MODEL_DEFAULTS / FALLBACKS
config/constants.mjs:80-97. Five keys: heartbeat_model, enrichment_model, consolidation_model, dream_model, cron_default_model. Defaults Pi (Gemini Flash), fallbacks Claude Haiku.resolveBackgroundModel
resolveBackgroundModel
lib/preferences.mjs:69. Three-tier resolution: payload.model → user_preferences[key] → BACKGROUND_MODEL_DEFAULTS[key].delegate_to_cli vs execute_cli_inprocess
delegate_to_cli vs execute_cli_inprocess
mcp__orion-tools that spawn external CLIs (Gemini, Codex, Claude CLI, Qwen, opencode). delegate_to_cli is fire-and-forget (returns delegation id immediately). execute_cli_inprocess blocks until CLI exits. Neither applies OS sandboxing — see GAP-D1.Agents & subagents
Agent (folder layout)
Agent (folder layout)
<dir>/<slug>/AGENTS.md (required) + config.yaml (required) + SOUL.md (optional persona) + MEMORY.md (optional seed memory). Two layers: bundle (prompts/agents/<slug>/) and vault (<vault>/agents/<slug>/). Vault overrides bundle.D9 body filter
D9 body filter
spawn_subagent or Claude Agent/Task), the body sent to the model is AGENTS.md only. SOUL.md and MEMORY.md are stripped. Enforced via getAgentDefForSubagent in agents/loader.mjs. Top-level chat sessions get the full bootstrap.DB is a derived index (D7)
DB is a derived index (D7)
agents SQLite table is a query-time index derived from config.yaml files. Boot reconcile (initLoader) and auth-change re-populate it via INSERT OR REPLACE. CRUD writes round-trip through config.yaml. The filesystem folder is authoritative; the DB is rebuildable.spawn_subagent (Pi)
spawn_subagent (Pi)
single / chain / parallel. Depth-guarded via _depthMap. Model fallback loop. See Subagents.PARA & vault
PARA
PARA
Projects/ (active work with deadlines), Areas/ (ongoing responsibilities), Resources/ (reference material), Archive/ (completed/inactive), Inbox/ (unprocessed capture). All five are uppercase on disk. See vault-directory-conventions.md.vault root
vault root
~/Orion/vaults/<firebase_uid>/. Per-user content directory. Travels with backup/sync. Contains PARA dirs + .orion/ (per-user app data) + agents/ (user agents) + skills/ (user skills) + .git/ (SDK isolation boundary)..orion/ directory
.orion/ directory
mcp-oauth/, subagent-events/, memory/, ccw/, agents/.migrated, etc. Auto-created on first write.ORION_APP_DATA_DIR
ORION_APP_DATA_DIR
~/Library/Application Support/com.orion.butler/. App-managed data (not user-owned vault content). Per-user profile DB lives at profiles/<firebase_uid>/orion.db. Sidecar sessions at pi-sessions/, sdk-sessions/, etc.IPC
SidecarEvent
SidecarEvent
text, thinking, toolStart, toolComplete, complete, error, pong, usageUpdate, subagentStart, subagentComplete, etc. See Event Layer.camelCase IPC convention
camelCase IPC convention
tool_start instead of toolStart) causes Rust serde to fail with unknown variant. See sdk-ipc-naming-convention.md.canUseTool
canUseTool
canUseTool.mjs. createCanUseTool(ctx) returns a closure-bound permission function per query. Three modes: default / bypassPermissions / plan.