Tags

Tags give the ability to mark specific points in history as being important
  • v0.14.3

    v0.14.3 — mirror, archive and issue-pull CI
  • v0.14.2

    v0.14.2 — CI status badge
  • v0.14.1

    v0.14.1 — README badges
  • v0.14.0

    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

    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

    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

    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

    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

    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

    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

    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

    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

    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

    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

    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

    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

    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

    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

    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

    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.