threepp
C++20 기반 크로스플랫폼 3D 라이브러리, 파이썬 바인딩 및 three.js 수준 API 제공
AI 에이전트를 위한 오픈소스 컨텍스트 엔지니어링 라이브러리, 캐시·압축·요약·점진적 감소를 설정 기반으로 관리
Open-source context engineering library for AI agents. Manage caching, compaction, summarization, and graceful degradation. Config-driven, Apache 2.0.
개발 도구PythonGitHub @terminus-labs-ai온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기Context engineering for AI Agents. Manage your LLM's context window with caching, compaction, summarization, and graceful degradation.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다.
README 전문 보기 ↗SR2 manages the full lifecycle of what goes into an LLM's context window: layer assembly, compaction, summarization, memory, token budgeting, KV-cache alignment, and graceful degradation.
Version: 2.0.0-alpha (revamp branch — clean-slate rebuild)
SR2 is not a library you call once, and not a harness. It's a distinct middle tier in the agent stack: a context runtime that sits between your agent harness and the LLM provider.
┌──────────────────────────────────────────────────────────┐
│ HARNESS your agent / Claude Code / LangGraph │
│ owns: I/O, session identity, agent personality, │
│ tool *implementations*, config │
└───────────────────────────┬─────────────────────────────────┘
│ turn(user_input)
▼
┌──────────────────────────────────────────────────────────┐
│ SR2 the context runtime │
│ owns: WHAT fills the window + how it evolves │
│ drives the multi-iteration tool loop: │
│ compile → call LLM → run tools → repeat → post-process │
│ layers · resolvers · transformers · memory · compaction │
│ summarization · budgeting · cache alignment · degradation │
└───────────────────────────┬─────────────────────────────────┘
│ CompletionRequest (injected ↓)
▼
┌──────────────────────────────────────────────────────────┐
│ LLMCallable LiteLLMCallable (default) / your own │
│ owns: the raw provider HTTP call (Anthropic, OpenAI, …) │
└──────────────────────────────────────────────────────────┘
Context management is a closed loop, not a one-shot transform:
compile context → call the model → observe the response → post-process (memory extraction, compaction, summarization, cache tracking)
A pure "compile-only" library forces the harness into a two-call dance — compile, call the LLM yourself, then hand the response back — and every guarantee SR2 makes (cache-stable prefixes, correct conversation-zone transitions, reliable post-processing) depends on the harness getting that dance exactly right. So SR2 owns the turn loop instead.
It does not own the provider HTTP call or tool execution. Both are injected dependencies (inversion of control):
| Dependency | Type | Provided by | SR2's use |
|---|---|---|---|
llm | LLMCallable (complete / stream) | harness | called each LLM iteration |
tool_executor | async (ToolUseBlock) -> ToolResultBlock | harness | called per tool request; SR2 never implements tools |
token_counter | TokenCounter | harness | budget enforcement |
memory_store, memory_extractor, tracer, provenance_store | protocols | harness (optional) | memory, observability |
This is how SR2 owns the lifecycle without becoming a provider client or a harness. The harness supplies adapters + I/O + personality; SR2 drives the turn.
The same SR2 core ships two ways:
LiteLLMCallable, call turn() in-process.
This is the primary mode (see Quick Start).sr2-relay provides; it's a thin wire-format adapter over the
same turn().SR2.turn(user_input) -> AsyncIterator[StreamEvent] is the entry point. Per
turn it:
LLMCallabletool_executor
(concurrently, order-preserving), appends results, and loopsmax_tool_iterations)end event, then awaits post_processCallers see a clean stream: text and usage events, loop-progress events
(tool_use_emitted, tool_result_received, iteration_complete), and exactly
one end. At most one error event may appear per phase, always before end.
import asyncio
from sr2 import SR2
from sr2.config.models import PipelineConfig
from sr2.integrations.litellm import LiteLLMCallable
from sr2.pipeline.token_counting import CharacterTokenCounter
from sr2.models import TextBlock
config = PipelineConfig(
layers=[
{"name": "system", "target": "system",
"resolvers": [{"type": "static",
"config": {"text": "You are a helpful assistant."}}]},
{"name": "conversation", "target": "messages",
"resolvers": [{"type": "session"}, {"type": "input"}]},
]
)
sr2 = SR2(
config,
llm=LiteLLMCallable("anthropic/claude-haiku-4-5-20251001"),
token_counter=CharacterTokenCounter(),
)
async def main():
async for event in sr2.turn([TextBlock(text="Hello")]):
if event.type == "text":
print(event.text, end="")
asyncio.run(main())
Or run a config straight from the CLI:
sr2 configs/minimal.yaml
See QUICKSTART.md for the YAML config shape, tool wiring, and multi-turn sessions.
The pipeline runs on an EventBus, not a fixed sequence. Components subscribe
to event names (turn_start, user_input, assistant_response, …); the engine
drives a drain-process loop each turn until no component produces new work.
A layer is the unit of context. Each layer holds resolvers (produce
content), transformers (reshape content), and optional tool providers
(produce tool definitions). Layers compile to one of three targets — system,
messages, or tools — and enforce a per-layer token budget.
Layer order drives KV-cache efficiency: stable layers (system prompt, project context) go first and stay cached; dynamic layers (conversation) go last.
Four extension points, each a runtime_checkable Protocol, discovered lazily
via Python entry points — nothing activates unless your config names it:
| Group | Protocol | Built-ins |
|---|---|---|
sr2.resolvers | Resolver | static, input, session, event_payload, memory, markdown_file, static_text |
sr2.transformers | Transformer | summarize, memory_extraction, compaction |
sr2.extractors | MemoryExtractor | rule_based |
sr2.tool_providers | ToolProvider | (extension point; no built-ins yet) |
Add a capability by registering an entry point — never by modifying the engine (Open/Closed).
MemoryStore / MemoryExtractor protocols; MemoryResolver
injects relevant memories on input, MemoryExtractionTransformer saves them
from responses. In-memory store ships with core.schema_and_sample,
result_summary) with an optional cost gate (cache-invalidation economics).CircuitBreaker (closed/open/half-open) plus a
5-level DegradationLadder.InMemoryProvenanceStore or durable SQLiteProvenanceStore); Tracer
captures per-component firing records with a human-readable timeline.src/sr2/). The v1 multi-package
monorepo, runtime, bridge, and premium split are gone.InMemoryMemoryStore); async persistence backends can be added via the MemoryStore protocol.The authoritative module map and architecture reference lives in CLAUDE.md. High level:
src/sr2/
__init__.py # public API — `from sr2 import SR2`, plus core models
sr2.py # facade re-export of the SR2 orchestrator
orchestrator.py # SR2 class: the turn loop
models.py # core data models (TextBlock, Message, ToolDefinition, …)
protocols/llm.py # LLMCallable, CompletionRequest/Response, StreamEvent
integrations/ # LiteLLMCallable
config/ # Pydantic config models
pipeline/ # engine, event bus, layers, resolvers, transformers, tracing
memory/ # stores, extractors, resolver
compaction/ # rule engine + cost gate
degradation/ # circuit breaker, ladder
tokenization/ # tiktoken counter
v2.0.0-alpha on revamp. Turn loop, event-driven pipeline, layers,
resolvers/transformers, memory, compaction, degradation, provenance, and tracing
are in place. post_process is a wired no-op pending the extraction/maintenance
hookup.
Apache-2.0. See LICENSE.