Skip to content

Releases: weftgo/weft

weft v0.13.0

Choose a tag to compare

@wajihtba wajihtba released this 10 Oct 10:17

see CHANGELOG.md, 0.13.0 — 2026-10-10

core v0.13.0

Choose a tag to compare

@wajihtba wajihtba released this 10 Oct 10:17

see CHANGELOG.md, 0.13.0 — 2026-10-10

weft v0.12.0 — phase 3 of the devtools plan: the panel, @weftgo/devtools, the scope header, the live grant

Choose a tag to compare

@wajihtba wajihtba released this 09 Oct 10:14

0.12.0 — 2026-10-09

Phase 3 of the devtools plan (the panel): @weftgo/devtools on npm,
scope detection (explicit, response headers through weft/scope, DOM
markers, the page URL, the fallback), the panel's host API, layout,
theme, keyed renderer, views, honesty and the Request tab, Studio's
Request pane, and the live grant. Tags core/v0.12.0 (the
weft.version literal only; core's API is unchanged since 0.10.1) and
v0.12.0 — a minor bump, as ?token= is refused and mount() may
return null (Changed — breaking, Changed — migration).

Added

  • The panel's size: studio/dist/panel/panel.js ships at 62,591 B
    gzip (61.1 KiB, 18.9 KiB of headroom under the 80 KiB cap), the last
    row of the append-only ledger studio/web/panel-budget.json; every
    panel build prints the per-item table from it. The KiB figures in the
    entries below are each item's delta, or the panel's size when that
    item landed — intermediate, not the release's.
  • Review fixes (panel): the size table and budget.test.ts measure
    panel.js with its version stamp normalized to the fixed-length
    placeholder "v0.00.0" (normalizeStamp), so a version bump moves no
    ledger byte; the panel finds its own <script> tag by data-weft,
    else by the src that resolves to the bundle's import.meta.url —
    never by a generic data-endpoint/data-token word, so a
    third-party widget's tag ahead of it no longer becomes its
    configuration; nothing renders after a disconnect (the tree's filter
    debounce and "copied" timer are cleared, no observer on a detached
    sentinel); the turn filter's prompts, the reported parked calls and
    failures and the header rung's paths are cleared on every start and
    capped (oldest first); the server's overflow frame reopens a live
    lane on its own bounded backoff (1 s, doubling while overflows repeat
    within a minute, a minute at most) instead of at once; viewport
    resizes are coalesced to one redraw per animation frame; with two
    panels on a page only one (the global's, else the first connected)
    answers Alt+W; external keys are looked up as own properties only
    (weft.content: "constructor" is no mode, an unknown cause no
    cause); a data-weft-scope marker on or inside a
    data-weft-untrusted element is ignored, and the README says markers
    must not appear in untrusted HTML.
  • Review fixes (npm): @weftgo/devtools publishes public
    (publishConfig.access), with prepublishOnly running
    npm-package.ts --check, which now also fails on a missing exports
    or types target, an unguarded panel import, or a README naming
    another version (the README no longer hard-codes one); engines
    (node >= 18), homepage, bugs, keywords, and types for
    ./panel.js. mount() waits for <body> (called from <head> it
    returns the element and appends it on DOMContentLoaded), is
    idempotent (a second call reuses the element it made and applies the
    new options) and returns null with enabled: false or on a server;
    the root entry is import-safe without a DOM (ssr-guard.js /
    ssr-unguard.js around the panel.js import; every export a no-op);
    enabled on mount() and the React/Vue/Svelte helpers; Position
    is the panel's whole placement union (left-dock, top-dock,
    bottom-dock added) and mount() takes mode, push and zIndex
    (written as data-mode, data-push, data-z-index). Breaking:
    mount() returns WeftDevtoolsElement | null.
  • Review fixes (Studio UI): make devtools-vite-check is pinned
    — examples/devtools-vite names vite 8.3.4 and jsdom 30.1.2 exactly
    and commits its package-lock.json (installed by npm ci; the packed
    tarball goes in after, --offline --no-save, and stays out of
    package.json and the lockfile) — and runs in CI (job
    devtools-vite, after studio); check.ts waits for the panel's
    /api/meta request with a deadline instead of a fixed 300 ms and
    gives the bundle's import.meta the built module's URL. The run page
    re-reads a finished run's spans for the invoke_agent span only after
    a running→finished transition it saw (a run opened cold reads them
    once). While a run runs, a request row ahead of its transcript batch
    says "bytes when the transcript is read" (no_transcript), not the
    gap badge (messagesSent's new optional running). The result-cap
    badge shows the bytes cut (truncated · 2.0 KiB cut) and an unrun
    call's max_tokens · call never executed. A badge's reason and fix
    are its accessible description (aria-describedby to a hidden
    element), said once; its name is the label. The Studio suites' real
    sleeps are fake timers advanced past the 2 s poll or deadline-polled
    conditions.
  • Review fixes (verification): imported through @weftgo/devtools
    (bundled into an app's chunk) the panel no longer takes the app's
    entry <script> for its own tag — its import.meta.url is the
    chunk's — so the endpoint default stays the page's directory (it was
    /assets/, with a panel-config.json asked there and the app tag's
    data-* read as configuration): the package's ssr-guard.js marks
    the import before panel.js evaluates (ssr-unguard.js removes the
    mark) and the element class's npmEntry keeps it, and under it rung 4
    is data-weft alone; the standalone panel.js still matches its own
    src. make devtools-vite-check keeps the app's entry tag in a
    second variant (page /app/) and asserts the endpoint. The panel's
    Request tab passes running to messagesSent, so it draws the
    neutral no_transcript where the run page does (a parity fixture
    pins it). A badge's reason and fix are inline visually hidden text
    after the label on both surfaces (the panel's .weft-sr, the run
    page's sr-only) — part of its accessible name, replacing the
    aria-describedby above; title stays for the pointer. The overflow
    backoff measures calm from the reopen, so a sustained overflow holds
    at the minute cap. Alt+W prefers a live, page-mounted panel (the
    global's if it is one, else the first connected one; the dormant or
    self-mounted docks only when there is none), so markup a page adds
    later can be toggled. A run opened cold within 30 s of its end (the
    row's finished) polls its spans for the invoke_agent span inside
    that window.
  • The devtools panel's Request tab (plan E1.2): the run page's
    Request pane in the panel, one step at a time (J/K, the tab's step
    buttons, a step card; ⤢ carries it) — the chips "changed by
    PrepareStep", "prompt changed at this step", "overridden by
    experiment" and "catalog changed at this step" from the request
    record's hashes, the system prompt with its bounded diff (vs the
    previous step; at the first step vs the registered instructions when
    the panel can read /api/manifest), the messages sent (count · bytes,
    the last three inline, the rest in a D4 JSON tree inside the tab), the tool
    catalog (description, policy chips, schema tree), params with "adapter
    default", tool choice, thinking, the attempts, a subagent call's child
    request and the compaction marker. Every absent block is a badge; a
    read-scoped token sees hidden and nothing else, and asks for no
    prompt. The panel gate checks the studio-local trim's chip and diff
    live. +5.5 KiB gzip (estimate +4 KiB). Review fixes: a derived
    prompt or catalog record (a body that did not parse) is badged
    derived and never diffed over, on both surfaces (promptText says
    undefined for it); the manifest is read per endpoint and token, asked
    again 30 s after a failure and once when it does not list the run's
    manifest hash (a redeploy); a subagent's "read its turn" says when the
    child's history is unreachable and hands off to Studio; the tab's step
    is the one ⤢ carries and J/K start from, walking the steps the record
    names too; a Studio that serves no request record is not_recorded
    with the new obsdb cause not_served (/api/meta's
    capabilities_off.requests words first); the panes share their words
    through lib/requests.ts and the stripped words of the tools route
    (+0.6 KiB: the tab is +6.1 KiB, 0.1 KiB past half again its estimate).
  • The devtools panel's honesty (plan D5): every badge the panel
    draws comes from the A3 table through one module,
    src/panel/badges.ts (<span class="weft-badge" data-hole="…">, the
    table's label, the reason and fix as its title — the run page's span;
    badge(hole, note) is what the Request tab calls): on the turn's
    header, step cards, tool calls (a result cap's cut is truncated,
    cause result_cap; an unrun call of a max_tokens step is
    max_tokens), compaction markers and request lines. The table's
    causes (log_cap, result_cap, no_public_id, no_spans,
    dev_token_only) join lib/honesty.ts as CAUSES, checked against
    the golden. The footer's content line ("content on · 2 events
    shortened (24.6 KiB cut)", "content off · weft.Content(false)" /
    "· otel.NoContent()") replaces the "content is stripped" suffix; turn
    rows carry "scripted (0 tokens)", "fork of s_…#e_…" and "experiment
    of t3" chips from the run row (its model, weft.session.forked_from,
    weft.forked_from). parity.test.ts proves every hole of the table
    shows on both the panel and the run page for the same run; a grep test
    keeps hole words out of every other panel source. The panel's badge
    attribute is now data-hole (was data-weft-hole), as the run page's. Review fixes: a
    finished step no request row names is gap on both surfaces (one
    reason, lib/requests.ts); the run page's result-cap badge is the
    table's (truncated/result_cap, max_tokens with no fix for an
    unrun call; HoleBadge takes a cause); a badge's reason and fix
    ride in its accessible text on both surfaces; the content line is said
    only on evidence, and none reads "captured none (weft.Content(false),
    or no destination takes cont...
Read more

core v0.12.0 — the weft.version literal moves to v0.12.0

Choose a tag to compare

@wajihtba wajihtba released this 09 Oct 10:14

The loop module at v0.12.0: the version literal only; no API change (apidiff: no incompatible changes vs core/v0.11.0). See the framework release v0.12.0 and CHANGELOG 0.12.0.

weft v0.11.0 — phase 2 of the devtools plan: the weft command, weft dev, discovery, doctor

Choose a tag to compare

@wajihtba wajihtba released this 08 Oct 15:11

weft v0.11.0

Phase 2 of the devtools plan (start and find): the weft command,
weft dev, the port policy, discovery, the stable dev token, the
Agents page from runtime registrations, weft doctor, and the panel's
configuration ladder. Tags core/v0.11.0 (the weft.version literal
only; core's API is unchanged since 0.10.1) and v0.11.0 — a minor
bump, as studio/cmd is removed (Changed — breaking).

Added

  • Agents from runtime registrations (plan B4): Studio remembers
    each runtime's registration manifest by (service, manifest hash), in
    memory; /api/manifest serves it when no weft.json is configured
    (the file still wins) and lists every source in sources[] with
    live; two services registering one agent name in different versions
    both appear. /api/meta gains manifest_sources, capabilities_off
    (why an option left a capability off) and manifest_check.source /
    differs; the Agents page, playground and debugger empty states show
    the reason.

  • The weft command (plan B1, cmd/weft): go install github.com/weftgo/weft/cmd/weft@latest yields a weft binary.
    weft studio [--addr] [--db] [--token] [--manifest] [--open] [--no-playground] is setup B (what studio/cmd served) with the
    playground on (studio.Playground(true), inert until an app's
    runtime connects; --no-playground turns it off), the manifest from
    --manifest / WEFT_MANIFEST else the nearest weft.json from the
    working directory upward (one line says which, or that none was
    found), and --open (default on when stdout is a terminal) opening
    the UI with the token in the URL fragment. The Studio API over a
    terminal: weft runs [--agent] [--since] [--failed] [--limit] [--json] (GET /api/runs; --limit 50 by default, and a limit
    that hid runs says so on stderr), weft open <run id> [--open] [--with-token] (prints the bare <url>/runs/<id>; the token goes
    only to the browser, or to stdout on --with-token), weft export <run id> [--format json|jsonl|otlp] to stdout and weft export <run id> --wefttest <dir> [--test name] [--force] (the wefttest fixtures
    unzipped into <dir>/<name>/, where wefttest.Replay(t, dir) reads
    them; a non-empty target needs --force, which replaces its *.json
    fixtures); weft doctor; weft version. The API clients never
    follow a redirect. The API clients take
    --url (WEFT_STUDIO_URL, default http://127.0.0.1:7331) and
    --token (WEFT_STUDIO_TOKEN). Exit codes: 0, 1 a failure, 2 a
    usage error.

  • weft dev (plan B1.2, FEATURES D7): weft dev [studio's flags] [--no-watch] [--watch dir] [-- command…] (default go run .)
    starts Studio in-process as weft studio does (same flags and port
    policy) and runs the app with WEFT_ENV=dev (kept when already set
    non-empty), WEFT_STUDIO_URL, WEFT_STUDIO_TOKEN and WEFT_DB (the
    Studio's SQLite file) set — plain variables the app can set itself.
    The app runs in its own process group and restarts on a .go save
    (fsnotify, 300 ms debounce; SIGTERM, 5 s, SIGKILL); a build failure
    waits for the next save; --no-watch exits with the app's code
    (127 when it cannot start); a directory arriving with .go files
    restarts too. Ctrl-C, SIGTERM and SIGHUP stop the app, then Studio
    (Linux adds Pdeathsig for go run; a SIGKILL of weft dev can
    still orphan the app's binary). Each start prints one line:
    studio <url>[#token=…] · app pid <n> · runtime rt_… registered
    (the token only when generated; "no runtime registered yet" after
    5 s, then a later line). Reuse follows the port policy: without a
    fixed token a running token-walled Studio is skipped for the next
    port (plan B3's stable token changes this). The
    discovery file is plan B3's. examples/studio-local runs under it:
    with WEFT_STUDIO_URL set it listens on 8080, keeps its local sink
    (otel.Local(""), explicit) and registers its runtime with that
    Studio.

  • make studio-bin builds ./weft from ./cmd/weft (ignored by
    git).

  • Studio's port policy (plan B2, internal/listen, wired into
    weft studio): 127.0.0.1:7331 is the one default. On a busy port
    the binary asks GET /api/meta there (bearer: --token /
    WEFT_STUDIO_TOKEN when set): a Studio on the same database file is
    reused — studio already running at http://127.0.0.1:7331 (pid 1234), reusing, exit 0, no database or listener opened — and anything else (another
    program, a Studio on another database, one whose meta this token
    cannot read) moves Studio to the next free port in 7331–7340 with
    one line naming the skipped address and why; the banner prints the
    real address. All ten busy is exit 1 naming the range. studio.New
    is unchanged: an embedded Studio is the app's own listener.

  • WEFT_STUDIO_ADDR, the --addr mirror. Either pins the
    address: busy is exit 1 with the address in the error — no probe, no
    fallback.

  • /api/meta pid: the serving process's id, under db.path's
    guard (loopback with no Token, or the server token; never a panel
    token).

  • weft doctor [--url URL] [--token TOK] (plan B5): checks a
    running Studio and prints one line per check — reachable, token
    accepted, the database's path and size, the content it stores,
    connected runtimes (and, when none, what this shell's WEFT_ENV and
    WEFT_STUDIO_URL say about why), the panel bundle's version, and
    whether weft.json is stale against the latest runs. Every line
    reads a field of GET /api/meta (internal/doctor.Lines is the
    table); the flags mirror WEFT_STUDIO_URL / WEFT_STUDIO_TOKEN. An
    unreachable Studio is the first line within a 5 s timeout and exit 1;
    a redirect is reported, never followed.

  • weft studio --manifest path (default $WEFT_MANIFEST; the flag
    wins): the app's weft.json, read once at start and served as
    studio.Manifest — /api/manifest and the doctor's weft.json check
    in setup B. An unreadable file is a start error.

  • /api/meta explains itself: content (Studio's ingest policy,
    "as_received", and the latest run's content mark — full,
    stripped, none or unmarked — with a note and the fix naming
    otel.NoContent() or weft.Content(false)), pricing (false
    until a pricing table exists), retention (null: none
    configured), runtimes (runtimes holding a command stream now),
    panel_version (the embedded /panel.js stamp) and
    manifest_check ({agents, checked, stale}: each manifest agent's
    hash against its latest run's weft.manifest.hash; null without a
    manifest or for a panel token), and auth_required (whether a
    studio.Token is configured). content.error and
    manifest_check.error (omitted when empty) report a read that
    failed or a manifest that does not parse — logged through the
    process's slog default too — instead of reading as an empty
    database.

  • obsdb/sqlite: (*DB).Path() — the database file's absolute
    path ("" for :memory:).

  • The discovery file (plan B3, internal/discovery): weft studio
    and weft dev write studio.json — {url, token, db, pid, started, version}, mode 0600, the bound port in it — to ./.weft/ when it
    exists, else $XDG_RUNTIME_DIR/weft/, else os.UserCacheDir()/weft/,
    and remove it on a clean exit. otel.Install/otel.Start and
    runtime.Install read it when WEFT_STUDIO_URL is unset: an app
    with defer otel.Install()() exports to the running Studio (and its
    runtime dials it) with no configuration, one INFO line naming the
    Studio joined. The file is trusted only when its url is loopback, it
    is fresh (pid alive, under 24 h) and, on unix, it is 0600 and the
    reading user's; anything else is ignored at Debug and removed by the
    next writer. A second Studio's exit restores the first's file; the
    writer drops .weft/.gitignore (*) when there is none. An explicit
    otel.Studio(...) or WEFT_STUDIO_URL switches the read off;
    WEFT_DISCOVERY=off turns it off; otel.NoEnv() ignores it with
    the rest of the environment.

  • A stable dev token per database: <db>.token beside the SQLite
    file (.weft/weft.db.token), 32 random bytes base64url, 0600,
    created on the first start and served by every later one, so the
    token survives a restart and a second bare start's probe reuses the
    running Studio (the probe sends it only to an address the user's
    discovery file names). --rotate-token (weft studio, weft dev;
    an action, no environment mirror) writes a new one.

  • GET <base>/panel-config.json (studio): {endpoint, version, capabilities} for the devtools panel, answered to a loopback (or
    AllowOrigins) Host and a same-origin, AllowOrigins or loopback
    Origin only (loopback by the Host's rule — localhost,
    *.localhost, 127.0.0.0/8, [::1] — even with AllowOrigins set) —
    a 404 otherwise; /api/meta lists the new panel-config capability.

  • The devtools panel's configuration ladder (plan C2): each field
    (endpoint, public-id, token, position, open, auto)
    resolves on its own through mount(opts) → the <weft-devtools>
    element's attributes → <meta name="weft:endpoint|public-id|token| position|open|auto"> → the panel's <script> tag (the running
    classic script, else the first with data-weft, any src) →
    panel-config.json beside the script (endpoint only, same origin
    only, never a token; asked only when nothing above named an endpoint)
    → the script's own directory. A <weft-devtools> element, a
    mount(opts) or data-auto="false" with no Studio answering shows
    one line, Studio not reachable at <endpoint> · retry; the dock the
    script mounted by itself still removes itself silently. The rung
    table is in studio/README.md.

Dependencies

  • github.com/fsnotify/fsnotify v1.9.0 (framework module only, for
    weft dev's watcher; core is untouched).

Changed

  • runtime/examples/local serv...
Read more

weft v0.10.1 — the panel release asset script reads the one version

Choose a tag to compare

@wajihtba wajihtba released this 08 Oct 10:22

Fixed

  • studio: make studio-panel-asset (the devtools panel as a release
    asset) read the studio.Version literal that 0.10.0 removed and
    failed; it reads the one version from version/version.go through
    the same helper the panel build stamps from. Tags core/v0.10.1 (the
    weft.version literal only) and v0.10.1.

The full 0.10.0 notes (the request record, the step and export routes, the honesty table) are on the v0.10.0 release; this patch only fixes the panel asset build and carries the same panel bytes.

weft v0.10.0 — the request record, Studio's step and export routes, the honesty table, one version from the module

Choose a tag to compare

@wajihtba wajihtba released this 08 Oct 10:18

The request record (ADR 0028): every model call's system prompt, tool
catalog, parameters and attempts recorded beside the transcript, read
back by Studio and the devtools panel with a closed table of honesty
badges; app logs, the step route, the export in four formats; one
version from the module. Tags core/v0.10.0 (compatible additions
only) and v0.10.0 (breaking in the pre-freeze layers listed below).

Changed — breaking

  • One version, the module's. The new github.com/weftgo/weft/version
    package (standard library only) holds it: version.Version is the
    release tag, version.Runtime() reads the framework module's version
    from the build info (the main module or the github.com/weftgo/weft
    dependency, honouring replace) and falls back to Version under
    (devel). studio.Version is now version.Version — v0.4.1 →
    v0.9.0 — so /api/meta's studio_version and the devtools panel's
    embedded version (stamped from version/version.go at build) move
    with the module. A panel built for v0.4.1 refuses a Studio that
    reports v0.9.0 as newer.
  • /api/meta's weft_version is the framework module's build-info
    version
    (version.Runtime()), no longer the core dependency's;
    inside the workspace it reads the tag instead of (devel).
  • obsdb.DB gains TranscriptBatches (ADR 0028 §8): a run's
    messages records with what each stored — index, step
    (weft.step.index, -1 when absent), input flag. A third-party DB
    reads pos, step, body and the weft.messages.input attribute per
    messages record, returns them through obsdb.DedupBatches, and
    implements Transcript as obsdb.TranscriptBodies(batches). A
    backend with no attribute column infers the input flag on index 0 and
    sets TranscriptBatch.InputDerived.
  • /api/runs/{id}/transcript rows carry what the record stored: the
    stored index, the stored step (or -1 with "badge": "not_recorded") and the stored input ("badge": "derived" where
    the backend inferred it) — no longer derived from assistant-message
    order. Playground transcript_edits / from_step validation and the
    web client read the same stored step; only a batch without one is
    placed by inference, marked derived.
  • obsdb.DB gains Requests, Prompt, Tools and Catalogs
    (ADR 0028 §10, the request record's read side). A third-party DB
    reads its request, prompt and tools records (stored under
    (run, kind, index)) as obsdb.StoredRecords through
    obsdb.RequestRecordOf, obsdb.PromptRecordOf and
    obsdb.ToolsRecordOf, returns one tools record per hash (the lowest
    index) from Catalogs, and answers a missing hash with
    obsdb.ExplainMissing. obsdb.RunRow gains InstructionsHash,
    CatalogHash and RequestCount, which a backend fills with the
    larger of run_start's and the invoke_agent span's
    weft.instructions.hash, request index 0's weft.catalog.hash and
    max weft.request.index + 1.
  • obsdb/clickhouse's unreleased migration 0004 gained
    weft_records.Input, Content, TruncatedBytes, SystemHash and
    CatalogHash
    : a database
    that applied 0004's earlier text (only a development build wrote one)
    lacks them and must be recreated. ClickHouse now reads the transcript
    input flag as stored; only rows written before the column read
    TranscriptBatch.InputDerived.
  • obsdb.DB gains Compactions (ADR 0028 §8, plan A9): a run's
    compactions as obsdb.Compaction — each run-scope view in index
    order with its step, half-open range, hash and body, then thread's
    session markers in emission order. A third-party DB builds each through
    obsdb.CompactionOf (from a messages record whose
    weft.messages.reason is set, or a record of kind compaction) and
    orders them with obsdb.SortCompactions. Its Transcript and
    TranscriptBatches must skip every messages record whose
    weft.messages.reason is set, and its messages count must not count
    them (obsdb.Weft.Reason carries the attribute).
  • obsdb.DB gains OtherLogs (plan A7): a run's app log records —
    the non-weft records (no weft.run.id) the writers keep beside
    weft's, attributed to the run through the span they were emitted
    under (its own spans and the non-weft spans below them, never another
    run's) — as an obsdb.LogPage of obsdb.OtherLogs, paged by
    obsdb.LogQuery (From inclusive, Limit 0 = 100 max 1000,
    MinSeverity filtering without renumbering), with Partial (the run
    is running: lines under in-flight spans appear when those spans end,
    and indexes may shift), Gap (lines naming a span never stored) and
    Truncated (more than obsdb.MaxLogCandidates lines in the run's
    traces, counted before attribution). A third-party DB implements it as
    obsdb.ReadOtherLogs(ctx, db, runID, q, candidates), where
    candidates returns the first limit non-weft records of the run's
    traces within a time window, in time order. obsdb.HoleError.Kind gains "logs": a finished run
    with no span has nothing to attribute through and answers
    HoleNotRecorded.

Changed

  • The system prompt and the tool catalog now reach content-on
    destinations
    (otel.Local, otel.Studio) under the content policy:
    Redact-able, capped with weft.content.truncated_bytes, dropped by
    content-off destinations. ADR 0028 reverses the old stance that no
    record carries the instructions text. An application whose prompt must
    not leave the process redacts it (core.ContentPrompt) or turns
    content off for that destination.

Added

  • The compaction marker on the run page and in the panel (plan
    A9.2, ADR 0028 §8).
    GET /api/runs/{id} gains compactions: each
    compaction the run's records name, counts and hash only, never a
    message body — a run-scope view {scope: "run", index, step, from_seq, to_seq, hash, replaced, entries} and thread's session
    marker {scope: "session", hash, replaced, entries, tokens_before?, tokens_after?, reason}; [] for a run that never compacted or was
    written before A9 (the record is optional: no badge). A read-scoped
    panel token reads it. The run page's step card whose request saw a
    view draws "2 messages rewritten into 1 by PrepareStep" ("1 message
    inserted by PrepareStep" when nothing was replaced) with the
    compacted badge; a session marker sits at the top of the run it is
    filed under — "12 messages compacted into 2 · 8.1k → 1.2k tokens".
    "show original" (collapsed, no fetch) expands a view's replaced range
    [from_seq, to_seq) from the transcript route's growth records the
    page already holds (seq = position in their concatenation); a range
    that cannot be placed is the gap badge. The replacement shows its
    count — and, once the step route is loaded, the request's message
    count — and says where its body is (the export's
    compactions[].messages). The devtools panel draws the same marker:
    session markers at the top of the turn, views on their step line.

  • A run's app logs and its delta count in Studio (plan A7).
    GET /api/runs/{id}/logs?from=&limit=&severity=, under a new logs
    capability in /api/meta, pages the app's own log lines (an slog
    bridge or the OTel Logs API on the pipeline's LoggerProvider) that
    were emitted under the run's spans — a tool handler's lines are the
    run's — in time order: {logs: [{index, time, severity, severity_number, body, attrs, span_id?}], next_from?}; severity
    keeps a level and above (trace…fatal, or 1–24). holes lists
    every hole of the page (badge/reason/fix repeat the first):
    not_recorded for a run recorded without a tracer, truncated when
    the run's traces hold more than 10 000 log lines in its window (the
    cap applies before attribution: later lines of this run may be
    missing), gap for lines in the run's trace naming a span that is
    not stored (they may be another run's). A running run's page carries
    partial: true and a partial_reason (lines under in-flight spans
    appear once those spans end; indexes may shift) — not a hole.
    App logs may carry anything the app logged, prompts included, so a
    read-scoped panel token is refused them (403, badge: "hidden"); a
    playground-scoped token, the server token and loopback read them. The
    run row (runs, runs/{id}, sessions, the export) gains
    delta_count, the streamed deltas counted and never stored. The web
    client gains fetchLogs and the types (no UI yet).

  • Subagents on the page (plan A10). GET /api/runs takes all=1
    (every run, subagent children included — the same as parent=*; a
    parent=<run id> beside it wins; a malformed value is a 400) beside
    the existing parent= filter, whose absence keeps the list top-level
    only. On the run page a step whose tool call started a child run
    shows it as a nested row — agent, status, usage, its holes, a link to
    its own page (from the run document's children, or the step route's
    children[] when cached) — and opening it folds the child's steps
    with the child's own request record, read by the child's id
    (/api/runs/<child id>/requests, under the requests capability:
    the child's prompt, never the parent's; a read-scoped token sees
    hidden). A call joins its child by the child's id, which names the
    step (<parent>/<step>/<call id> — call ids may repeat across steps),
    in the story and the trace view's call detail alike; a child id of
    another form falls back to the first unlinked call with its
    parent_call_id. The run document's children[] rows carry each
    child's own holes; a child's usage shows once it ended ("usage at
    finish" while it runs, "—" beside the interrupted badge). The runs table is "top-level only" by default with a toggle
    (?subagents=all) and a ?parent= filter chip; a child row links its
    parent. The devtools panel's subagent badge opens the child inline,
    one level: its row (agent, status, usage),...

Read more

core v0.11.0 — the weft.version literal moves to v0.11.0

Choose a tag to compare

@wajihtba wajihtba released this 08 Oct 15:11

The weft.version literal only; core's API is unchanged since core/v0.10.1. Released with weft v0.11.0 (phase 2 of the devtools plan).

core v0.10.1 — the weft.version literal moves to v0.10.1

Choose a tag to compare

@wajihtba wajihtba released this 08 Oct 10:21

No API change over core/v0.10.0: only the weft.version literal every run stamps moves to v0.10.1, in lockstep with the framework's v0.10.1 (the panel release asset script fix).

core v0.10.0 — the reporting hook, the request record, compaction views, TTFT and latency

Choose a tag to compare

@wajihtba wajihtba released this 08 Oct 10:17

Compatible additions over core/v0.9.0 (the apidiff gate reports no incompatible changes): ReportFromContext/Reporter/AttemptInfo/RawPair (the reporting hook, ADR 0016's A8 note; mw.Retry and mw.Fallback report every attempt as an attempt span); the request record (ADR 0028: request, prompt and tools records with weft.instructions.hash on RunStart, weft.system.hash, weft.catalog.hash; ContentPrompt, ContentStop; Origin(name) for a tool's source); the run-scope compaction view record and (*Agent).LoggerProvider(); StepFinish.LatencyMS and TTFTMS with the answering model on the chat span. Nothing the model sees changes with recording on or off. Full notes: CHANGELOG.md, 0.10.0.