Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
e71a96c
Add StepPersistence capability for step-event durability across deleg…
dsfaccini May 24, 2026
4bf6216
Address pydanty review + ergonomics: tighten correctness and identity…
dsfaccini May 24, 2026
37ae4c7
Address pydanty round-2 review: retry validity, list ordering, effect…
dsfaccini May 24, 2026
9160f7f
docs(step_persistence): align FileStepStore docstring with seq-counte…
dsfaccini May 24, 2026
0dafedb
docs(step_persistence): fix broken README examples + clarify run_id s…
dsfaccini May 24, 2026
eb5b334
docs(step_persistence): align run_id semantics with pydantic_ai (per-…
dsfaccini May 24, 2026
675633e
docs(step_persistence): explain why for_run uses a local ContextVar
dsfaccini May 24, 2026
ece83eb
feat(step_persistence): enforce explicit-run_id reuse with ValueError
dsfaccini May 24, 2026
7f741c7
chore: gitignore branch-context skill artifacts + AGENTS.local.md
dsfaccini May 24, 2026
0cc038e
feat(step_persistence): add SqliteStepStore + MediaStore externalization
dsfaccini May 25, 2026
a98820f
test(media): VCR cassettes for S3MediaStore against R2
dsfaccini May 25, 2026
f62fe6e
feat(media): public_url resolver — protocol method + per-store callable
dsfaccini May 25, 2026
92d3997
refactor(media): introduce MediaContext + key_strategy for extensible…
dsfaccini May 25, 2026
277eeaa
feat(media): close metadata round-trip; drop vestigial sqlite key_str…
dsfaccini May 25, 2026
3dafb96
fix(media): reject absolute paths from DiskMediaStore key_strategy
dsfaccini May 25, 2026
39d8691
Merge remote-tracking branch 'origin/main' into step-persistence
Jun 2, 2026
e3eb5e4
fix(step_persistence): dedupe terminal snapshot; document sqlite thre…
Jun 2, 2026
2459980
fix(media): SigV4 wire path matches signed path; walker preserves unk…
Jun 2, 2026
a20d446
Merge remote-tracking branch 'origin/main' into step-persistence
Jun 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
.mcp.json
.DS_Store
.agents/settings.local.json
.agents/skills/branch-context/
AGENTS.local.md
CLAUDE.local.md
LOCAL_WORKTREES.md

Expand Down
63 changes: 61 additions & 2 deletions pydantic_ai_harness/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Pydantic AI capability library."""
"""The batteries for your Pydantic AI agent -- the official capability library."""

from typing import TYPE_CHECKING

Expand All @@ -7,8 +7,63 @@
from .filesystem import FileSystem
from .logfire import ManagedPrompt
from .shell import Shell
from .step_persistence import (
ContinuableSnapshot,
EventKind,
FileStepStore,
InMemoryStepStore,
RunRecord,
SqliteStepStore,
StepEvent,
StepPersistence,
StepStore,
ToolEffectRecord,
ToolEffectStatus,
annotate_tool_effect,
continue_run,
fork_run,
is_provider_valid,
)

__all__ = ['CodeMode', 'FileSystem', 'ManagedPrompt', 'Shell']
__all__ = [
'CodeMode',
'ContinuableSnapshot',
'EventKind',
'FileStepStore',
'FileSystem',
'InMemoryStepStore',
'ManagedPrompt',
'RunRecord',
'Shell',
'SqliteStepStore',
'StepEvent',
'StepPersistence',
'StepStore',
'ToolEffectRecord',
'ToolEffectStatus',
'annotate_tool_effect',
'continue_run',
'fork_run',
'is_provider_valid',
]

_STEP_PERSISTENCE_NAMES = {
'ContinuableSnapshot',
'EventKind',
'FileStepStore',
'InMemoryStepStore',
'RunRecord',
'SqliteStepStore',
'StepEvent',
'StepPersistence',
'StepStore',
'ToolEffectRecord',
'ToolEffectStatus',
'annotate_tool_effect',
'continue_run',
'fork_run',
'is_provider_valid',
}


def __getattr__(name: str) -> object:
Expand All @@ -28,4 +83,8 @@ def __getattr__(name: str) -> object:
from .shell import Shell

return Shell
if name in _STEP_PERSISTENCE_NAMES:
from . import step_persistence

return getattr(step_persistence, name)
raise AttributeError(f'module {__name__!r} has no attribute {name!r}')
39 changes: 39 additions & 0 deletions pydantic_ai_harness/media/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"""Content-addressed media stores for offloading large binary parts.

Used by `pydantic_ai_harness.step_persistence` to keep snapshots small when
messages carry `BinaryContent` payloads. Public API is intentionally small
and stable; a forthcoming `MediaExternalizer` capability will reuse these
stores for in-flight wire-payload reduction (rewriting `BinaryContent` to
URL parts before the model sees them).
"""

from pydantic_ai_harness.media._s3 import S3MediaStore
from pydantic_ai_harness.media._store import (
DiskMediaStore,
KeyStrategy,
MediaContext,
MediaStore,
PublicUrlResolver,
SqliteMediaStore,
default_key_strategy,
make_static_public_url,
media_uri_for,
parse_media_uri,
)
from pydantic_ai_harness.media._walker import externalize_media, restore_media

__all__ = [
'DiskMediaStore',
'KeyStrategy',
'MediaContext',
'MediaStore',
'PublicUrlResolver',
'S3MediaStore',
'SqliteMediaStore',
'default_key_strategy',
'externalize_media',
'make_static_public_url',
'media_uri_for',
'parse_media_uri',
'restore_media',
]
Loading
Loading