context-engineering-core 0.12.0__tar.gz → 0.12.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/CHANGELOG.md +15 -1
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/PKG-INFO +1 -1
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/pyproject.toml +1 -1
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/__init__.py +1 -1
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/evaluation/data/freeze.json +2 -2
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/layers/common.py +66 -16
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/pipeline.py +3 -5
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/tokens.py +14 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/.gitignore +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/LICENSE +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/README.md +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/examples/evidence_answer_policy.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/examples/incident-demo.json +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/examples/inspection-input.json +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/examples/rolling_summary.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/examples/sdk_quickstart.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/examples/service-config.example.json +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/examples/structured_answers.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/examples/validated_answer.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/__main__.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/_sqlite.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/_windows_security.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/_windows_storage.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/adapters.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/answers.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/budget.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/cli.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/config.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/context.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/demo.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/errors.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/evaluation/__init__.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/evaluation/commands.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/evaluation/corpus.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/evaluation/data/ground_truth.json +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/evaluation/data/pin_retention.json +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/evaluation/data/protocol.json +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/evaluation/data/scenario.json +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/evaluation/data/summary_fixture.json +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/evaluation/execution.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/evaluation/fixtures.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/evaluation/grading.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/evaluation/harness.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/evaluation/heldout/__init__.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/evaluation/heldout/__main__.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/evaluation/heldout/data/ground_truth.json +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/evaluation/heldout/data/manifest.json +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/evaluation/heldout/data/protocol.json +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/evaluation/heldout/data/scenarios.json +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/evaluation/heldout/data/scoring_manifest.json +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/evaluation/heldout/data/scoring_protocol.json +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/evaluation/heldout/scoring.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/evaluation/protocol.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/evaluation/reporting.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/evaluation/results.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/evaluation/run_commands.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/evaluation/strategies.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/inspection.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/layers/__init__.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/layers/cap.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/layers/pin.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/layers/retrieve.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/layers/summarize.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/layers/window.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/mcp_server.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/memory/__init__.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/memory/codec.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/memory/demo.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/memory/store.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/models.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/providers/__init__.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/providers/client.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/providers/commands.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/providers/contracts.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/providers/credentials.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/providers/memory.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/providers/store.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/providers/transport.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/providers/windows_credentials.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/py.typed +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/service/__init__.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/service/__main__.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/service/app.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/service/auth.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/service/client.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/service/control.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/service/demo.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/service/integrations.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/service/schemas.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/service/worker.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/service/workers.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/summaries.py +0 -0
- {context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/work.py +0 -0
|
@@ -3,7 +3,21 @@
|
|
|
3
3
|
Earlier versions (0.1.0–0.9.6) are documented in `docs/C01_REPORT.md` through
|
|
4
4
|
`docs/C10_STORAGE_ACL_REPORT.md` and preserved as wheels under `archives/`.
|
|
5
5
|
|
|
6
|
-
## 0.12.
|
|
6
|
+
## 0.12.1 — 2026-10-31 (unreleased)
|
|
7
|
+
|
|
8
|
+
### Changed (performance only; output identical)
|
|
9
|
+
- Budget fit checks compute only the request's estimated token count
|
|
10
|
+
(`TiktokenCounter.estimate_tokens`), skipping per-message counts and hashing that
|
|
11
|
+
are only reported. Custom counters keep the full `count_request` path.
|
|
12
|
+
- WINDOW candidates skip their own token count; per-turn JSON is reused.
|
|
13
|
+
- Window planning (run by RETRIEVE, WINDOW and SUMMARIZE) and history digests are
|
|
14
|
+
memoized by value (bounded; built-in counter/serializer only).
|
|
15
|
+
- All-layers median on the 100-turn benchmark: 95 → 67 ms at 900 tokens and
|
|
16
|
+
208 → 80 ms at 3000 tokens. All 310 strategy-benchmark assemblies (31 facts x 5
|
|
17
|
+
strategies x 2 budgets) are byte-identical to 0.12.0. 0.12.0 wheel/freeze archived
|
|
18
|
+
in `archives/c12-latency-0121/`.
|
|
19
|
+
|
|
20
|
+
## 0.12.0 — 2026-10-31 (PyPI)
|
|
7
21
|
|
|
8
22
|
### Added
|
|
9
23
|
- `context_engine.adapters`: `openai_chat`, `anthropic_messages`,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: context-engineering-core
|
|
3
|
-
Version: 0.12.
|
|
3
|
+
Version: 0.12.1
|
|
4
4
|
Summary: Provider-independent context layers, source contracts, and token budget accounting
|
|
5
5
|
Project-URL: Homepage, https://github.com/Nandu1729/Context-Engine
|
|
6
6
|
Project-URL: Repository, https://github.com/Nandu1729/Context-Engine
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "context-engineering-core"
|
|
7
|
-
version = "0.12.
|
|
7
|
+
version = "0.12.1"
|
|
8
8
|
description = "Provider-independent context layers, source contracts, and token budget accounting"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "Apache-2.0"
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"summary_fixture": "b3c1b76bb330b52493e5150647747bad77d5de3a55d05d032bb5703be1c70196"
|
|
8
8
|
},
|
|
9
9
|
"runtime": {
|
|
10
|
-
"code_hash": "
|
|
10
|
+
"code_hash": "c3d4bfbdad58327eb09a763ae398fd97277e33339ce00cfb5395b2615f2d269f",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"certifi": "2026.10.23",
|
|
13
13
|
"charset-normalizer": "3.5.1",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"tiktoken": "0.14.0",
|
|
20
20
|
"urllib3": "2.8.0"
|
|
21
21
|
},
|
|
22
|
-
"package_version": "0.12.
|
|
22
|
+
"package_version": "0.12.1",
|
|
23
23
|
"python": "3.12.13"
|
|
24
24
|
},
|
|
25
25
|
"schema_version": 1
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"""Shared rendering/accounting primitives used by layers and the public pipeline."""
|
|
2
2
|
|
|
3
3
|
import hashlib
|
|
4
|
+
from collections import OrderedDict
|
|
4
5
|
from dataclasses import asdict, replace
|
|
6
|
+
from functools import lru_cache
|
|
5
7
|
|
|
6
8
|
from ..context import ContextCarrier, LayerDiagnostic
|
|
7
9
|
from ..errors import LayerStateError
|
|
@@ -15,7 +17,7 @@ from ..models import (
|
|
|
15
17
|
Turn,
|
|
16
18
|
canonical_json,
|
|
17
19
|
)
|
|
18
|
-
from ..tokens import TokenCounter
|
|
20
|
+
from ..tokens import CanonicalChatSerializer, TiktokenCounter, TokenCounter, estimated_tokens
|
|
19
21
|
from ..work import raise_if_cancelled
|
|
20
22
|
|
|
21
23
|
ORDER = tuple(BlockKind)
|
|
@@ -23,6 +25,12 @@ OPTIONAL = (BlockKind.SUMMARY, BlockKind.WINDOW, BlockKind.RETRIEVED)
|
|
|
23
25
|
|
|
24
26
|
|
|
25
27
|
def history_digest(turns: tuple[Turn, ...]) -> str:
|
|
28
|
+
# Turns are immutable values, so equal histories share one cached digest.
|
|
29
|
+
return _history_digest(tuple(turns))
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@lru_cache(maxsize=256)
|
|
33
|
+
def _history_digest(turns: tuple[Turn, ...]) -> str:
|
|
26
34
|
values = [
|
|
27
35
|
(asdict(t.scope), t.turn_id, t.revision, t.timestamp.isoformat(), t.content_hash)
|
|
28
36
|
for t in turns
|
|
@@ -101,18 +109,21 @@ def set_block(
|
|
|
101
109
|
)
|
|
102
110
|
|
|
103
111
|
|
|
112
|
+
@lru_cache(maxsize=4096)
|
|
113
|
+
def _turn_json(turn) -> str:
|
|
114
|
+
return canonical_json({"turn": turn.turn_id, "messages": [m.to_wire() for m in turn.messages]})
|
|
115
|
+
|
|
116
|
+
|
|
104
117
|
def window_block(
|
|
105
|
-
context: ContextCarrier, ids: tuple[str, ...], counter: TokenCounter
|
|
118
|
+
context: ContextCarrier, ids: tuple[str, ...], counter: TokenCounter, *, count: bool = True
|
|
106
119
|
) -> ContextBlock:
|
|
120
|
+
"""`count=False` skips the block's own token count (planning-only candidates)."""
|
|
107
121
|
selected = [t for t in context.working_turns if t.turn_id in ids]
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
)
|
|
112
|
-
if selected
|
|
113
|
-
else ""
|
|
122
|
+
# Identical to canonical_json of the list: compact separators, per-item sorted keys.
|
|
123
|
+
content = "[" + ",".join(_turn_json(t) for t in selected) + "]" if selected else ""
|
|
124
|
+
return ContextBlock(
|
|
125
|
+
BlockKind.WINDOW, content, text_tokens=counter.count_text(content) if count else None
|
|
114
126
|
)
|
|
115
|
-
return ContextBlock(BlockKind.WINDOW, content, text_tokens=counter.count_text(content))
|
|
116
127
|
|
|
117
128
|
|
|
118
129
|
def incremental_cost(context: ContextCarrier, block: ContextBlock, counter: TokenCounter) -> int:
|
|
@@ -121,8 +132,7 @@ def incremental_cost(context: ContextCarrier, block: ContextBlock, counter: Toke
|
|
|
121
132
|
)
|
|
122
133
|
return max(
|
|
123
134
|
0,
|
|
124
|
-
counter
|
|
125
|
-
- context.plan.required_estimate.estimated_tokens,
|
|
135
|
+
estimated_tokens(counter, request) - context.plan.required_estimate.estimated_tokens,
|
|
126
136
|
)
|
|
127
137
|
|
|
128
138
|
|
|
@@ -135,24 +145,64 @@ def fits_block(
|
|
|
135
145
|
# RETRIEVE runs first but must leave the exact planned WINDOW viable.
|
|
136
146
|
if context.window_planned and block.kind != BlockKind.WINDOW:
|
|
137
147
|
blocks = tuple(b for b in blocks if b.kind != BlockKind.WINDOW) + (
|
|
138
|
-
window_block(context, context.plan.window_turn_ids, counter),
|
|
148
|
+
window_block(context, context.plan.window_turn_ids, counter, count=False),
|
|
139
149
|
)
|
|
140
150
|
request = render_request(blocks, context.question, context.required_request.tools)
|
|
141
|
-
return counter
|
|
151
|
+
return estimated_tokens(counter, request) <= context.plan.input_allowance
|
|
142
152
|
|
|
143
153
|
|
|
144
|
-
|
|
145
|
-
|
|
154
|
+
_WINDOW_MEMO: OrderedDict = OrderedDict()
|
|
155
|
+
_WINDOW_MEMO_SIZE = 64
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def _window_key(context: ContextCarrier, counter: TokenCounter):
|
|
159
|
+
"""Every input the WINDOW scan reads; None (no memo) for custom counters/serializers."""
|
|
160
|
+
if (
|
|
161
|
+
type(counter) is not TiktokenCounter
|
|
162
|
+
or type(counter.serializer) is not CanonicalChatSerializer
|
|
163
|
+
):
|
|
164
|
+
return None
|
|
165
|
+
return (
|
|
166
|
+
counter.config,
|
|
167
|
+
tuple(context.working_turns),
|
|
168
|
+
required_blocks(context),
|
|
169
|
+
context.question,
|
|
170
|
+
context.required_request.tools,
|
|
171
|
+
context.plan.window_tokens,
|
|
172
|
+
context.plan.required_estimate.estimated_tokens,
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def _scan_window(context: ContextCarrier, counter: TokenCounter) -> tuple[str, ...]:
|
|
146
177
|
selected: tuple[str, ...] = ()
|
|
147
178
|
for turn in reversed(context.working_turns):
|
|
148
179
|
raise_if_cancelled(context.cancellation)
|
|
149
180
|
candidate = (turn.turn_id,) + selected
|
|
150
181
|
if (
|
|
151
|
-
incremental_cost(
|
|
182
|
+
incremental_cost(
|
|
183
|
+
context, window_block(context, candidate, counter, count=False), counter
|
|
184
|
+
)
|
|
152
185
|
> context.plan.window_tokens
|
|
153
186
|
):
|
|
154
187
|
break
|
|
155
188
|
selected = candidate
|
|
189
|
+
return selected
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def plan_window(context: ContextCarrier, counter: TokenCounter) -> ContextCarrier:
|
|
193
|
+
require_prepared(context, counter)
|
|
194
|
+
# RETRIEVE, WINDOW and SUMMARIZE each re-plan the same inputs; the scan is pure.
|
|
195
|
+
key = _window_key(context, counter)
|
|
196
|
+
if key is None or key not in _WINDOW_MEMO:
|
|
197
|
+
selected = _scan_window(context, counter)
|
|
198
|
+
if key is not None:
|
|
199
|
+
_WINDOW_MEMO[key] = selected
|
|
200
|
+
if len(_WINDOW_MEMO) > _WINDOW_MEMO_SIZE:
|
|
201
|
+
_WINDOW_MEMO.popitem(last=False)
|
|
202
|
+
else:
|
|
203
|
+
raise_if_cancelled(context.cancellation)
|
|
204
|
+
_WINDOW_MEMO.move_to_end(key)
|
|
205
|
+
selected = _WINDOW_MEMO[key]
|
|
156
206
|
if context.window_planned:
|
|
157
207
|
if selected != context.plan.window_turn_ids:
|
|
158
208
|
raise LayerStateError("Stored WINDOW membership differs from shared planner")
|
{context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/pipeline.py
RENAMED
|
@@ -27,7 +27,7 @@ from .models import (
|
|
|
27
27
|
canonical_json,
|
|
28
28
|
freeze_sequence,
|
|
29
29
|
)
|
|
30
|
-
from .tokens import TiktokenCounter, TokenCounter, TokenEstimate
|
|
30
|
+
from .tokens import TiktokenCounter, TokenCounter, TokenEstimate, estimated_tokens
|
|
31
31
|
from .work import Cancellation, raise_if_cancelled, validate_cancellation
|
|
32
32
|
|
|
33
33
|
|
|
@@ -245,7 +245,7 @@ def _finalize(
|
|
|
245
245
|
def _block_accounting(blocks, question, tools, counter, estimate):
|
|
246
246
|
empty_question = replace(question, content="")
|
|
247
247
|
running: tuple[ContextBlock, ...] = ()
|
|
248
|
-
previous = counter
|
|
248
|
+
previous = estimated_tokens(counter, render_request((), empty_question, tools))
|
|
249
249
|
base = previous
|
|
250
250
|
result = []
|
|
251
251
|
by_kind = {b.kind: b for b in blocks}
|
|
@@ -254,9 +254,7 @@ def _block_accounting(blocks, question, tools, counter, estimate):
|
|
|
254
254
|
current_question = question if kind == BlockKind.QUESTION else empty_question
|
|
255
255
|
if kind != BlockKind.QUESTION:
|
|
256
256
|
running += (item,)
|
|
257
|
-
current = counter
|
|
258
|
-
render_request(running, current_question, tools)
|
|
259
|
-
).estimated_tokens
|
|
257
|
+
current = estimated_tokens(counter, render_request(running, current_question, tools))
|
|
260
258
|
content = question.content if kind == BlockKind.QUESTION else item.content
|
|
261
259
|
result.append(
|
|
262
260
|
BlockUsage(
|
{context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/tokens.py
RENAMED
|
@@ -152,6 +152,14 @@ class TiktokenCounter:
|
|
|
152
152
|
return _cached_count(self.config.encoding_name, text)
|
|
153
153
|
return len(self._encoding.encode_ordinary(text))
|
|
154
154
|
|
|
155
|
+
def estimate_tokens(self, request: ChatRequest) -> int:
|
|
156
|
+
"""`count_request(request).estimated_tokens` without the reporting-only parts."""
|
|
157
|
+
serialized = self.count_text(self.serializer.serialize(request))
|
|
158
|
+
return math.ceil(
|
|
159
|
+
(serialized + self.config.adapter_overhead_tokens)
|
|
160
|
+
* Fraction(str(self.config.calibration_factor))
|
|
161
|
+
)
|
|
162
|
+
|
|
155
163
|
def count_request(self, request: ChatRequest) -> TokenEstimate:
|
|
156
164
|
rendered = self.serializer.serialize(request)
|
|
157
165
|
return TokenEstimate(
|
|
@@ -169,3 +177,9 @@ class TiktokenCounter:
|
|
|
169
177
|
serializer_name=self.serializer.name,
|
|
170
178
|
request_fingerprint=hashlib.sha256(rendered.encode("utf-8")).hexdigest(),
|
|
171
179
|
)
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def estimated_tokens(counter: TokenCounter, request: ChatRequest) -> int:
|
|
183
|
+
"""Budget-check estimate; custom counters without `estimate_tokens` use the full count."""
|
|
184
|
+
fast = getattr(counter, "estimate_tokens", None)
|
|
185
|
+
return fast(request) if fast is not None else counter.count_request(request).estimated_tokens
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/examples/incident-demo.json
RENAMED
|
File without changes
|
{context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/examples/inspection-input.json
RENAMED
|
File without changes
|
{context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/examples/rolling_summary.py
RENAMED
|
File without changes
|
{context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/examples/sdk_quickstart.py
RENAMED
|
File without changes
|
|
File without changes
|
{context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/examples/structured_answers.py
RENAMED
|
File without changes
|
{context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/examples/validated_answer.py
RENAMED
|
File without changes
|
{context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/__main__.py
RENAMED
|
File without changes
|
{context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/_sqlite.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/adapters.py
RENAMED
|
File without changes
|
{context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/answers.py
RENAMED
|
File without changes
|
{context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/budget.py
RENAMED
|
File without changes
|
{context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/cli.py
RENAMED
|
File without changes
|
{context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/config.py
RENAMED
|
File without changes
|
{context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/context.py
RENAMED
|
File without changes
|
{context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/demo.py
RENAMED
|
File without changes
|
{context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/errors.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/inspection.py
RENAMED
|
File without changes
|
|
File without changes
|
{context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/layers/cap.py
RENAMED
|
File without changes
|
{context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/layers/pin.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/mcp_server.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/models.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/py.typed
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/summaries.py
RENAMED
|
File without changes
|
{context_engineering_core-0.12.0 → context_engineering_core-0.12.1}/src/context_engine/work.py
RENAMED
|
File without changes
|