Metadata-Version: 2.4
Name: wormhole-core
Version: 0.13.0
Summary: Wormhole core engine.
Author: Wormhole Team
License-Expression: AGPL-3.0-or-later
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: loopgraph<0.4.0,>=0.3.0
Provides-Extra: test
Requires-Dist: pytest>=7.4.0; extra == "test"
Requires-Dist: pytest-asyncio>=0.21.0; extra == "test"
Requires-Dist: pytest-cov>=5.0.0; extra == "test"
Requires-Dist: pytest-benchmark>=5.2.3; extra == "test"
Provides-Extra: lint
Requires-Dist: ruff>=0.6.4; extra == "lint"
Requires-Dist: mypy>=1.11.0; extra == "lint"
Dynamic: license-file

# Wormhole Core

## Purpose
Wormhole Core is a deterministic, event-driven loop built to be embedded by the
SDK. It does not perform direct I/O; the SDK (and other clients) provide adapters
and tools.

## External Engine Dependency (loopgraph)
Core depends on the published `loopgraph>=0.3.0` package for graph execution.
Integration is done by constructing loopgraph Graphs and executing them via
Scheduler. Pin updates by editing `pyproject.toml`.

## Module Overview
- `graph/`: Graph construction helpers, scheduler runtime, and per-session registry wrappers.
- `events/`: event types and `EventStream` for emitting structured core events.
- `hooks/`: Hook registry and lifecycle hook types (prompt, tool gate, telemetry, compaction).
- `backpressure.py`: bounded queue configuration and metrics.
- `retry.py`: retry policy and idempotency helpers used by the SDK.
- `loop/`: session lifecycle (`start`, `step`, `stop`), compaction decisions, and
  resume helpers.
- `storage/`: Async storage protocols plus file-based stores for sessions, snapshots, event logs, and compaction.
- `schemas/`: session, message, and tool schemas.
- `tools/`: tool registry, schema validation, and permission gating.
- `logging.py`: structured debug logging helpers with redaction support.
- `errors.py`: stable error taxonomy.

## Tool Implementations (SDK)
Core defines tool schemas, permission policy, and registries only. Concrete
OS-facing tool implementations live in the SDK under `wormhole_sdk.tools`
(bash, file_read, file_edit, file_write, binary handlers). Use
`wormhole_sdk.tools.create_default_tools()` to register the default tool set
with a `ToolRegistry`.

## Schemas

### Messages and Parts
Messages are sequences of typed parts.

- Part types: `text`, `tool_call`, `tool_output`, `cost`, `metadata`
- Roles: `user`, `assistant`, `system`

### Tools
Tools are registered with:

- `tool_id`, `name`, `schema`, `permission_kind`, `enabled`
- `capabilities` (read_only, concurrency_safe, approval_required)
- `default_retry_policy` (optional SDK override)

Capability notes:
- `read_only` is informational only.
- `concurrency_safe` controls scheduler parallelism.
- `approval_required` is advisory; the SDK ApprovalManager uses it to request approval.
- Permission kinds are advisory; core only enforces the allowlist.
  - `allowlist_only`: intended for allowlist-only tools
  - `user_approval`: intended for tools that should prompt for approval

### Sessions
Session config defaults:

- `retention_days=30`
- `compaction_ratio=0.7`
- `auto_compaction_enabled=True`
- `allowlisted_tools=[]`
- `max_concurrent_tools=1`
- `backpressure=None` (SDK defaults to bounded queues)
- `model_retry_policy` / `tool_retry_policy` (SDK executes retries)
- `approval_timeout_seconds=60`

Execution state and resume:

- `graph_id` and `execution_state_id` track the latest loopgraph snapshot.
- `ExecutionStateSnapshot` stores opaque loopgraph state for resume.

Loop termination enums:

- `FinishReason`: `end_turn`, `tool_use`, `max_tokens`, `stop`
- `ContinuationMode`: `automatic`, `force_continue`, `force_stop`

## Persistence and Compaction
- `SessionStore` persists session records, execution state, and history.
- `CompactionStore` stores snapshots used to load the latest compressed prompt
  state.
- Auto-compaction triggers when context ratio exceeds the configured threshold;
  it can be disabled.
- Compaction is two-stage: prune old `tool_output` payloads into short placeholder
  tool results (keeping the last N rounds), then summarize if the context still
  exceeds the prune target.
- Successful compaction appends a SYSTEM message with metadata
  `{"compaction": true, "snapshot_id": "..."}`; full history remains immutable.
- Context reconstruction uses the last compaction-tagged message plus all later
  messages, replacing old tool outputs with compact placeholders while preserving
  valid tool call/result sequencing.

### Compaction (Core API)

```python
from wormhole_core.compaction.strategies import NoOpSummarizationStrategy
from wormhole_core.loop.compaction import compact_session
from wormhole_core.schemas.session import CompactionConfig
from wormhole_core.storage.compaction_store import CompactionStore

result = await compact_session(
    session_id="session-1",
    messages=message_history,
    compaction_store=CompactionStore(root_dir),
    summarization_strategy=NoOpSummarizationStrategy(),
    config=CompactionConfig(),
    context_limit=8192,
)
```

### Forking and Lineage

```python
from wormhole_core.session.fork import fork_session
from wormhole_core.session.types import ForkRequest
from wormhole_core.storage.compaction_store import CompactionStore
from wormhole_core.storage.session_store import SessionStore

result = await fork_session(
    ForkRequest(parent_session_id="session-1", new_session_id="child-1"),
    session_store=SessionStore(root_dir / "sessions"),
    compaction_store=CompactionStore(root_dir / "compactions"),
)
```

Sessions track lineage with `parent_session_id`. Use
`SessionStore.list(parent_session_id=...)` to query children.

## Storage Protocols
Core defines async `Protocol` interfaces for persistence backends:

- `SessionStoreProtocol`
- `ExecutionStateStoreProtocol`
- `EventLogStoreProtocol`
- `CompactionStoreProtocol`

File-based stores in `wormhole_core.storage` implement these protocols and use
atomic write-then-rename plus file locking. The session list operation returns
`SessionSummary` (`session_id`, `created_at`, `updated_at`) without reading
session file contents.

## Error Codes
Stable errors are emitted as `WormholeError` with codes:

- `WH-CORE-001`: validation error
- `WH-CORE-002`: permission denied
- `WH-CORE-003`: not found
- `WH-CORE-004`: session expired
- `WH-CORE-005`: persistence error
- `WH-CORE-006`: tool execution error
- `WH-CORE-007`: invalid state transition
- `WH-CORE-008`: engine error
- `WH-CORE-009`: config error
- `WH-CORE-100`: loopgraph unavailable
- `WH-CORE-101`: scheduler execution error
- `WH-CORE-102`: snapshot error
- `WH-CORE-103`: handler not found
- `WH-CORE-104`: graph cycle error
- `WH-CORE-110`: snapshot version mismatch
- `WH-CORE-120`: duplicate tool registration
- `WH-CORE-121`: tool schema error
- `WH-CORE-130`: hook error
- `WH-CORE-131`: backpressure error
- `WH-CORE-132`: capability violation
- `WH-CORE-133`: retry exhausted
- `WH-CORE-134`: approval denied
- `WH-CORE-135`: approval timeout
- `WH-CORE-136`: approval persistence error

## Quick Start (Async)

```python
import asyncio
from wormhole_core.loop.session_api import SessionManager
from wormhole_core.schemas.session import SessionConfig

async def main() -> None:
    manager = SessionManager()
    handle = await manager.start_session(SessionConfig(max_concurrent_tools=2))
    await manager.step_session(handle.session.session_id, input="hello")
    await manager.stop_session(handle.session.session_id)

asyncio.run(main())
```

## Doctest Coverage
Run doctests for core modules:

```bash
python -m pytest --doctest-modules packages/core/
```

## Debug Logging Gate
Debug logs must be structured and disabled in release mode.

- `WORMHOLE_DEBUG=1` enables debug logs.
- `WORMHOLE_RELEASE=1` forces debug logs off.

CI should include a release-mode run that fails on debug output, for example:

```bash
WORMHOLE_RELEASE=1 python -m pytest --doctest-modules 2>&1 | rg -n "DEBUG" && exit 1 || exit 0
```

## Version History

`wormhole-core` follows pre-1.0 SemVer: in `0.x`, MINOR bumps mark new
release milestones (and breaking changes); PATCH covers fixes within a
milestone. Versions are tracked independently of `wormhole-sdk`.

| Version | Milestone | Notes |
|---|---|---|
| 0.1.0 | Initial scaffold | SDK-ready core package layout. |
| 0.2.0 | Eventflow graph engine | Graph/Scheduler/EventBus/ExecutionState/FunctionRegistry integration; LoopEngine removed. |
| 0.3.0 | Event log persistence + runtime safeguards | EventLogStore, structured runtime checks. |
| 0.4.0 | Hook + backpressure + retry contracts | HookRegistry, BackpressureConfig, RetryPolicy, ToolCapabilities. |
| 0.5.0 | Tool execution timeout + tool-results-as-messages | Per-tool timeout enforcement; tool outputs flow as user-message parts. |
| 0.6.0 | OS-tool boundary + storage protocols | Concrete OS tools moved to SDK; protocol-based persistence (Session/ExecutionState/EventLog/Compaction). |
| 0.7.0 | Two-stage compaction + fork lineage | Prune-then-summarize compaction; `parent_session_id` lineage; reconstructed-context helpers. |
| 0.8.0 | Tool registration formalization | Strict typing for the registration flow. |
| 0.9.0 | TaskTool delegation schema + prompt locks | DelegationContext, prompt-layer lock APIs, child-session storage linkage. |
| 0.10.0 | Unified graph loop migration | Multi-turn conversation runs in one `step_session` call via the graph runtime; staged-message queue. |
| 0.11.0 | **BREAKING**: approval unification | Removed `ApprovalHook`; all approval flows go through `ApprovalManager`. Pre-approval paths must be normalized. |
| 0.12.0 | **BREAKING**: rename engine dep to `loopgraph` | `eventflow2` → `loopgraph>=0.3.0,<0.4.0`. Renames: `EventflowError`→`LoopgraphError`, `EVENTFLOW_UNAVAILABLE`→`LOOPGRAPH_UNAVAILABLE`, `EventflowSnapshotStore`→`LoopgraphSnapshotStore`, `EventflowEvent`/`EventType` aliases→`Loopgraph*`, `ensure_eventflow_available`→`ensure_loopgraph_available`. |
| 0.13.0 | First public release | License relicensed from proprietary "All Rights Reserved" to **AGPL-3.0-or-later**; `Private :: Do Not Upload` classifier removed. No source-API changes from 0.12.0. |

## License

`wormhole-core` is distributed under the **GNU Affero General Public License
v3.0 or later** (AGPL-3.0-or-later). See [LICENSE](./LICENSE) for the full
text.

The AGPL extends the GNU GPL by requiring that anyone who runs a modified
version of the software as a network service must make the source code of
that modified version available to the service's users. If you embed
`wormhole-core` in a hosted product, that obligation applies. For commercial
licensing terms outside the AGPL, contact the maintainers.
