Tags give the ability to mark specific points in history as being important
-
-
-
-
v0.14.0
88048b8d · ·v0.14.0 — buffered SSE for tool/schema streaming stream=true with tools or response_format no longer returns a 400. A tool call or a schema-validated answer only exists once the full response is computed, so we buffer it and replay it as a single-shot SSE stream (text/event-stream): opening role chunk -> one content or tool_calls delta (streaming tool_calls carry the required index) -> finish chunk -> data: [DONE]. The client's streaming SDK gets a valid stream, just not token-incremental. Plain chat still streams incrementally. Genuine failures still surface as 422/500 rather than a stream. Additive: the v0.13.0 400 on stream+tools / stream+schema is replaced by buffered SSE. 190 tests passing. Ships psyb0t/aicodebox:v0.14.0.
-
v0.13.0
9fb19ba5 · ·v0.13.0 — compose tools + response_format (agentic flow ending in structured JSON) /openai/v1/chat/completions now accepts `tools` and `response_format` in the same request. They describe different turn types, like OpenAI: - tool-call turn -> tool_calls / finish_reason "tool_calls" (never schema-checked); - final answer turn -> schema-validated (with retry) canonical JSON / finish_reason "stop". The tools directive carries the final-answer schema so both exits are stated coherently. Enabled by a new early_accept escape in shared/runner.py:run_with_json_retry that short-circuits a tool-call turn instead of retrying it as a schema failure. tools + stream=true still -> 400 (planned follow-up). Additive: the v0.12.0 400 on tools+response_format is removed; non-combined requests unchanged. 190 tests passing. Ships psyb0t/aicodebox:v0.13.0.
-
v0.12.0
811e64b0 · ·v0.12.0 — OpenAI-style client-executed tool calling /openai/v1/chat/completions now honors the standard `tools` / `tool_choice` body fields. The machine acts as a plain function-calling model: it responds with `tool_calls` + finish_reason "tool_calls" when it wants a tool, the client runs the tool and sends the `role:"tool"` result back, and the loop continues (stateless — full history resent each round, exactly like OpenAI). - tool_choice: auto / none / required / {type:"function",function:{name}}. - Tolerant parsing of the agent's tool-call block (handles prose/fences). - In tool mode the harness's own internal tools default OFF (pure function-caller); x-aicodebox-no-tools: 0 re-enables the hybrid. - tools + response_format/schema -> 400; tools + stream=true -> 400. - Additive: non-tool requests unchanged; the old blanket 400 on tools is gone. Ships psyb0t/aicodebox:v0.12.0. -
v0.11.0
0a872ccc · ·v0.11.0 — surface provider errors as HTTP 400 instead of empty text RunResult gains provider_error: str | None. chat_completions checks it ahead of exit-code / parse-error handling and returns 400 with the provider's message instead of a 200 with empty text. run_with_json_retry stops re-prompting as soon as a provider error appears instead of burning the retry budget against a rejection that will never parse. Breaking for API clients that assumed a 200 always meant a usable (if empty) completion. Adapters that don't set provider_error see no change. 169/169 tests green.
-
v0.10.1
bd44a3c7 · ·v0.10.1 — periodic safety-net purge for ephemeral workspaces v0.10.0's per-request /tmp/aicodebox/<uuid>/ cleanup runs in a `finally` block — covers the normal case but not SIGKILL, container restart with a leftover root, or the cleanup helper itself raising. In those cases orphans leaked forever. v0.10.1 adds purge_stale_workspaces(): iterates EPHEMERAL_WORKSPACE_ROOT, removes dirs older than 1h (TTL covers worst-case schema runs 10x over), skips non-dir entries, returns the purged count, WARN-logs skipped/failed entries. Wired into server._purge_loop which runs every 10 minutes. Bonus: purge_stale_uploads now WARN-logs its silently-swallowed OSError path. 167 tests pass (+3 new for the orphan removal, missing-root no-op, and stray-file skip cases). Migration: none. Existing v0.10.0 deployments accumulate stale dirs until restarted; v0.10.1 sweeps them on first purge tick.
-
v0.10.0
3a6e15d2 · ·v0.10.0 — cheap schema retries via ephemeral workspace + session continue Up through v0.9.1, schema-mode retries on /openai/v1/chat/completions replayed the full original prompt — a 100k-token request needing 3 retries paid 400k input tokens. v0.10.0: - Schema request + no x-aicodebox-workspace → ephemeral /tmp/aicodebox/<uuid>/ workspace (mkdir mode 0o700), cleaned up in `finally` after the request returns. - run_with_json_retry runs retries with no_continue=False + minimal corrective prompt (error + directive + schema, ~500 tokens) instead of replaying the full original input. - Caller-provided workspace → fresh-session retry fallback (v0.9.1 behavior); we can't guarantee isolation in a workspace we don't own. Library-level: run_with_json_retry gains continue_session_on_retry (default False — /run callers unchanged). Safety: _cleanup_ephemeral_workspace refuses paths outside EPHEMERAL_WORKSPACE_ROOT. stream+schema 400 check moved earlier so the rejected path doesn't leak an ephemeral dir. 164 tests pass (+5 new in test_oai_schema.py and test_usage_accumulation.py). Migration: none. Schema requests without a workspace header now cost ~100x less on retries. -
v0.9.1
4b1b2b5e · ·v0.9.1 — retry prompt now carries original task for informed correction Bug fix on the schema-mode retry helper from v0.8.0+. Each retry runs with no_continue=True (fresh session) so the model doesn't double down on its bad answer. But the retry prompt only had the bad output + parse error + schema — NO original task. For schemas where correction needs task context (large enum picks, allowed-values lists, domain identifiers), the retry agent had no idea what it was correcting and either re-picked blindly or fell back to prose. Fix: _json_retry_prompt now takes the original prompt as a parameter and re-states it in the retry body alongside the bad output, the error, and the schema. run_with_json_retry passes spec.prompt through. Fresh-session benefit preserved, task context now present. New layout (delimited sections): - Original task ─── - Your previous (invalid) response ─── - Parse / validation error ─── - Required schema ─── Regression test added: test_retry_prompt_includes_original_task exercises a 4-value enum mismatch and asserts the retry prompt contains the original task verbatim plus the bad output, error, and schema. 159 tests pass (158 from v0.9.0 + 1 new). Migration: none. Retry prompts are longer (carry original task) so each attempt costs slightly more input tokens, but retries should succeed more often — net token usage on retrying schema runs should drop.
-
v0.9.0
06eb6a73 · ·v0.9.0 — OpenAI standard response_format on /openai/v1/chat/completions Support OpenAI's standard `response_format` body field — stock SDKs (LangChain, official openai-python, LlamaIndex, etc.) now drive schema-validated JSON without our custom header. response_format=text → no schema (default) response_format=json_object → permissive — forces parseable JSON response_format=json_schema → uses .json_schema.schema dict as the constraint (OpenAI structured outputs shape) Failure semantics identical to v0.8.x header path: success → canonical JSON in message.content exhaustion → 422 with validation error agent crash → 500 with exit code + stderr stream=true → 400 Body field wins if both body and x-aicodebox-json-schema header are set (OAI standard). INFO log on conflict. Header stays supported as a fallback. Entry log: has_schema=<bool> → schema_via=<source> where source is response_format.json_schema, response_format.json_object, x-aicodebox-json-schema, or none. The old 400 on response_format=json_object is removed — callers relying on it for control flow must update. 158 tests pass (151 from v0.8.3 + 7 new in test_oai_schema.py covering both standard paths, precedence, malformed shapes, and the streaming guard). Migration: fully additive for new callers. Stock OpenAI SDKs work with schema enforcement out of the box. Existing header-using callers unchanged. -
v0.8.3
6c2165dc · ·v0.8.3 — pyproject.toml is the single version source Fix the version-reporting drift v0.8.2 and every prior release shipped with. aicodebox.__version__ reported "0.1.0" regardless of the actual release tag (8 releases of lying), and the docker image only ever tagged :latest. Single canonical source now: - pyproject.toml [project] version — THE one place a release bump happens. - aicodebox/__init__.py reads it via importlib.metadata.version(); falls back to "0.0.0+source" sentinel (NOT a hardcoded number) if dist-info isn't installed. - Makefile derives the docker tag from pyproject via awk; every `make build` tags BOTH :vX.Y.Z AND :latest. New `make version` prints the derived tag. - uv.lock refreshed. Verified end-to-end: `docker run psyb0t/aicodebox:v0.8.3 python3 -c 'import aicodebox; print(aicodebox.__version__)'` → "0.8.3". 151 existing tests pass. No behavior change — version derivation is infrastructure. Migration: none. Anyone scripting against __version__ was already getting "0.1.0" regardless of pull; they'll now get the real number from v0.8.3 onward. -
v0.8.2
94aa41c8 · ·v0.8.2 — backfill logging on schema-mode path Patch release. v0.8.0 / v0.8.1 left four logging gaps: parse_json_response was silent, run_with_json_retry had no terminal summary, oai.chat_completions had no entry/success log, header parse helpers had no rejection warning. Backfilled: - adapters.base.parse_json_response: DEBUG per candidate, DEBUG on winner, INFO summary on all-failed, WARN if jsonschema lib missing. - shared.runner.run_with_json_retry: INFO on entry, DEBUG per attempt, INFO/WARN per retry, INFO terminal summary (outcome=success|exhausted|crashed, attempts, retries, total_usage). - oai.chat_completions: INFO entry (model, stream, msg count, flag presence), INFO on schema/non-schema success, header parsers WARN on rejected values (truncated ≤80 chars). Uses the existing project _JsonFormatter — DEBUG=1 → JSON with ts/level/logger/func/line/file/msg. No new dependency. No secrets / tokens / bodies / env dumps logged. All 151 existing tests pass. No behavior change — observability only. Migration: none — internal change. -
v0.8.1
b7a0b87b · ·v0.8.1 — agent crash 500, sum usage across retries, per-attempt array Three correctness fixes on v0.8.0's schema-mode path + a streaming RunSpec regression-test backfill. 1. Agent crash returns 500, not 422. v0.8.0 lumped "validation exhausted" and "agent process crashed" into one 422. Client retry loops never terminated on real crashes. Now 422 means caller-side (your schema or prompt), 500 means server-side (agent exit code in detail). 2. Usage summed across every retry attempt. Every retry is its own paid LLM call. v0.8.0 reported only the final attempt's tokens — under-counting the provider bill. _accumulate_usage now sums every numeric usage key (input/output/ total/cache_creation_*/cache_read_*/etc.) across attempts. Result is written back to result.usage so downstream payloads see real billable cost. 3. Per-attempt breakdown via response.attempts (/run) and aicodebox_attempts (OAI envelope vendor extension): [{"index": N, "usage": {...}, "exitCode": N, "parseError": "..."}, ...] Callers can render "retry 2/3 cost X tokens" or bill per attempt. 4. Backfilled regression test for the v0.7.0 streaming RunSpec plumbing that shipped without coverage. 151 tests (137 from v0.8.0 + 14 new). README + CHANGELOG synced. Migration: none — strict improvement. Clients with specific 422 handlers should narrow to "validation failed" and add 500 for "agent crashed". -
v0.8.0
72153f8f · ·v0.8.0 — schema validation on /openai/v1 + smart JSON extraction v0.7.0 plumbed x-aicodebox-json-schema through to RunSpec but the OAI route never validated. Schema-set callers got 200 OK on malformed JSON. /openai/v1/chat/completions now runs the same self-correction path /run uses when x-aicodebox-json-schema is set (up to 3 re-prompts on parse / validation failure): Success → message.content = canonical re-serialized JSON (no fences, no prose) regardless of LLM formatting. Exhaustion → HTTP 422 with the validation error in detail. stream=true → HTTP 400 (schema validation needs the complete response; no clean recovery from mid-stream parse failure over SSE). parse_json_response is now tolerant of LLMs that wrap JSON in fences mid-prose: tries clean → edge-fences → each ``` block (LAST first) → balanced-brace {...}/[...] with string-literal + escape handling. With a schema, the loop prefers candidates that BOTH parse AND schema-validate. The retry budget is reserved for actual structural failures. /run benefits too (shared helper). Refactor: _retry_prompt + _run_json_with_retry moved from modes/api/server.py into shared/runner.py as _json_retry_prompt + run_with_json_retry. JSON_RETRY_MAX lives next to it. Tests: 22 new (15 extraction + 7 OAI schema flow). test_api_run_ response patcher updated for the new call site. Docs: README's /v1/chat/completions bullet expanded to list all the x-aicodebox-* headers and the new 422 / 400 failure semantics — backfills the v0.7.0 doc gap. Migration: additive. v0.7.0 callers that silently accepted malformed JSON now get either canonical JSON or HTTP 422 — strict improvement. -
v0.7.0
fb0d5fba · ·v0.7.0 — expose remaining RunSpec knobs on /openai/v1/chat/completions Additive. /openai/v1/chat/completions now accepts six more headers that map one-to-one onto /run body fields, so OAI clients no longer have to drop down to /run for schema validation, session resumes, or tool-allowlist control: x-aicodebox-json-schema JSON object — schema-validates the final assistant turn; flips the run to output_format=json-verbose so the adapter event stream is available end-to-end. x-aicodebox-resume string — adapter session id to resume. x-aicodebox-extra-args JSON array OR comma-separated string. x-aicodebox-timeout-seconds int — per-run timeout. x-aicodebox-tools-allowlist JSON array OR comma-separated string. x-aicodebox-no-tools 1/true/yes — disables tool surface. Malformed header values surface as 400 with the offending header name in the detail. Body-level tools / tool_choice / response_format= json_object remain 400 — those are distinct OAI-protocol concerns from the new tools_allowlist / no_tools / json_schema RunSpec knobs. The streaming path is wired identically — same six knobs flow into the streamed RunSpec. No breaking changes. Existing OAI requests behave the same. Also ships the FUNDING.yml that was committed but untagged on top of v0.6.0, and a backfilled CHANGELOG.md covering every release from v0.1.0. -
v0.6.0
1b38b849 · ·v0.6.0 — kill the verbose flag, jsonSchema is the only dial Breaking change to /run. v0.5.0's two-flag matrix (verbose + jsonSchema) collapses to one — jsonSchema decides everything: no jsonSchema → {runId, workspace, exitCode, text} (lean) jsonSchema → {runId, workspace, exitCode, text, json, (full) events, sessionId, usage} + {parseError, jsonRetries} (replaces json) on schema-validation failure after 3 retries (everything else still surfaces for debugging) Schema mode is always-verbose. Want events without strict validation? Pass "jsonSchema": {"type": "object"} — permissive, just forces JSON output. The verbose field is removed from the request model. Pydantic silently ignores stale verbose=true callers (extra=ignore) — they get the lean text response without a 422. Migration: - drop verbose=true; if you wanted events/sessionId/usage, set jsonSchema (use {"type":"object"} for permissive) - schema-set callers now also receive text + events + sessionId + usage alongside json - SDK regen recommended -
v0.5.0
948e889e · ·v0.5.0 — replace outputFormat dial with verbose flag + rename parsed→json Breaking change to /run. v0.4.0's outputFormat enum conflated LLM output style with response richness; v0.5.0 splits them into two orthogonal request flags: jsonSchema (dict|null) → agent runs in JSON mode, response carries json field. 3-retry self-correction on parse/schema failure. verbose (bool) → response includes events + sessionId + usage alongside text. jsonSchema + verbose=true composes — verbose surface plus json (or parseError + jsonRetries on failure). Field rename: parsed → json. SDK regen recommended. -
v0.4.0
e98dd12e · ·v0.4.0 — /run restructure: outputFormat dial + JSON retry + opt-in raw Breaking change. /run no longer ships raw_stdout / raw_stderr by default and the payload shape is now strictly determined by ``outputFormat``: text → {..., text} json → {..., parsed} on success; {..., text, parseError, jsonRetries} on exhaustion json-verbose → {..., events} Always-when-populated: sessionId, usage. Opt-in via includeRaw=true: stdout + stderr. Auto-included on exitCode != 0: stderr. JSON mode now self-corrects: failed JSON decode / schema validation triggers up to 3 retries where the agent is re-prompted with its prior bad output and the specific error. ``jsonRetries`` reports the count. AgentAdapter gains ``parse_events(stdout, req)`` — invoked only in json-verbose mode. Default returns []; adapters emitting structured streams override to JSON-decode each line. Migration: callers reading result.stdout / result.stderr must either opt into includeRaw or migrate to result.text / result.parsed / result.events. JSON callers who read the raw text on success must move to ``parsed``. SDK regen recommended. -
v0.3.0
cdaf8d18 · ·v0.3.0 — real OAI streaming Replaces the previous single-chunk fake-stream on /openai/v1/chat/completions with stream=true. New components: - StreamEvent + AgentAdapter.parse_stream_event — typed per-line adapter hook for structured streaming. - shared.runner.run_stream — async generator over the agent's stdout. Default behaviour: one text delta per line; adapters override parse_stream_event to decode their native event stream (json-verbose, etc.). - oai.py _stream_response — emits one chat.completion.chunk per delta event, real-time. Subprocess killed on client disconnect. Bonus: oai.py reads usage token counts through alias-aware helper (input_tokens / inputTokens / input — same for output) so adapters don't need to dual-write the key shape. No breaking changes — adapters without a custom parse_stream_event get the default line-per-delta behaviour automatically, which is itself a strict improvement over the old buffered single-chunk path.