Commit graph

83 commits

Author SHA1 Message Date
Yiorgis Gozadinos
fdb5710491
Ask and analyze across several databases
Chunk 2 gave search a configured set to fan out over. ask and analyze
covered one database still: the RAG capability had no way to be told which
databases a question spanned, and the analysis sandbox mounted one
document tree.

The selection travels as sources on EvidenceState, beside the filter it
scopes with, so both capabilities read it the same way. clients_covering
is the one rule that turns a selection into clients, used by search, the
sandbox mount and the cite fallback, so a question scoped to some
databases cannot search, mount or cite another. Citations carry the
database they came from, and format_for_agent names it, so the model can
attribute evidence while it answers rather than only afterwards.

The sandbox keeps one flat /documents/{id}/ namespace and resolves each id
to the client holding it, which rests on ids being UUID4. A database
copied from another breaks that, so an id held twice is refused rather
than resolved to whichever arrived last.

On the CLI, search, ask and analyze cover the configured set and label
each result with its database. Every other command works on one, named
with --database NAME (a name reaches a database behind a URI, which --db
cannot) or --db PATH, and refuses a set it cannot choose from instead of
silently reading the default database. Cold databases open together, so a
first query costs the slowest open rather than their sum.
2026-08-24 10:03:46 +03:00
Yiorgis Gozadinos
4967765878
Delete comments that restate the line below them
Sixty-three comments said what the next statement already said: # Connect to
LanceDB above connect_lancedb, # Path object above isinstance(source, Path),
# Get page numbers from provenance above the prov loop, # Clear and populate
results above list_view.clear(). They cost a read and carry nothing.

The line is whether a comment restates one statement or labels a phase. Phase
labels stay: the migrations keep # Create staging table with new schema and
# Copy from staging to final table in batches, each heading ten lines of a
long procedure. So do comments carrying a fact the code cannot: the
merge_insert update-only note on document_meta, why the poller builds sources
eagerly, why create_document_from_source returns a list for directories, that
indexes need training data, the field-group markers in the config models, and
the file:// URL-encoding note in create_document_from_source.

capabilities/ is untouched. Its docstrings sit next to prompt surface, and
changing them needs an eval to back it.

The cassette-recording docs were wrong three ways. They named
tests/test_qa.py::test_qa_anthropic, which no longer exists; they targeted
whole modules, so a rewrite would re-record cassettes for services the
recorder is not running; and they used COHERE_API_KEY where the SDK reads
CO_API_KEY. docs/development.md now names exact tests with -n0, and the keyed
example is test_cohere_reranker, which owns the one cassette recording
api.cohere.com.
2026-08-20 15:22:33 +03:00
Yiorgis Gozadinos
cab510d0d5
Give the evidence capabilities one typed state
RAGState and AnalysisState each declared the same five fields, so the generic
base could not name them: StateT was bound to BaseModel, and every access
went through cast(Any, state), a getattr by string, or a loop clearing fields
by name so it could skip the one only AnalysisState has.

EvidenceState declares them once. RAGState adds nothing, AnalysisState adds
executions and overrides begin_invocation to clear them. StateT binds to
EvidenceState, which removes all ten casts and both state-shape getattrs; the
three getattr(ctx.deps, "state") probes stay, since those check a
host-supplied object rather than our own state.

discover_evidence reached into capability.state for two fields. It now asks
through evidence_record() and citation_index(), alongside the
evidence_tool_names() and cite_available accessors it already used. The eval
runner's _RagLikeState protocol and the chat app's getattr reads described
this shape from outside and are gone.

Compatibility is semantic JSON-object equivalence, not bytes: field names and
nesting are unchanged, so a dict stored by 0.75.0 loads and re-dumps equal,
but deriving from a shared base reorders AnalysisState's keys. Nothing
serializes, hashes or string-compares this state — every carry point
re-validates by key.
2026-08-19 17:08:44 +03:00
Yiorgis Gozadinos
11b1bfbc94
Give the capsule to one return, and the run its own copy of state
A request can carry several of this capability's returns — a model can call search
twice in one response — and the carrier was identified by message alone, so each of
them received the whole capsule. It is selected by message and part now, so exactly
one carries it however many share the request.

The chat TUI passed its persisted state into the run, so tool synchronisation mutated
it in place while the message history was promoted only on success. A cancelled or
failed run therefore kept the evidence the tools had recorded and discarded the
messages that justified it, and the next question derived its identity from the
shorter history: behind the recorded epoch, refused as non-append-only, the
conversation unusable until cleared. The run gets a copy, promoted with the messages
or not at all.

Five decorators had been left attached to a helper by an earlier extraction, which
pytest does not collect, so the resume case they carried was silently untested. The
wire test covers both resume shapes again, no prompt and deferred results.
2026-08-13 13:00:02 +03:00
Yiorgis Gozadinos
2cd568847e
Move the wire rewrite into the compaction capability
`_compact_old_tool_returns`, `PRIOR_TURN_NOTICE` and `turn_start` leave
`RAGCapabilityBase`, along with its `wrap_model_request` hook. The evidence
capabilities now retrieve and validate, and nothing else. Registering the compaction
capability is what rewrites a request; leaving it out sends the transcript untouched,
which was never a choice a host could make before.

The boundary is the recorded question identity rather than message shape, so a
resumption compacts what lies below the question in progress instead of switching
compaction off for the whole run. The newest earlier evidence return carries the
capsule and every other becomes a receipt, so one capsule exists by construction and
every return stays paired with its call.

Pictures of cited evidence are fetched through the capability that retrieved them and
re-attached beside the capsule with fresh labels. Ownership of a picture on the wire
requires the machine tag we write and an image directly after it, since neither
position nor prose is proof: several tools' results can arrive in one request, and a
user quoting our wording above their own picture had it removed. A picture that cannot
be fetched or decoded is emitted with neither its image nor its label.

The chat TUI and the example backend register the compactor, being multi-turn.
`client.ask`, `client.analyze` and the MCP tools do not: a single-shot question has
nothing earlier to compact.
2026-08-13 13:00:02 +03:00
Yiorgis Gozadinos
cdaeaa94e6
Constrain the chat prompt container height 2026-07-25 14:40:40 +03:00
Yiorgis Gozadinos
93824cdee5
Surface database-open errors in the TUIs
ChatApp and InspectorApp assigned self.client before __aenter__
completed, so a failed open was masked by an AttributeError from
on_unmount tearing down the never-opened client.
2026-07-25 11:27:29 +03:00
Yiorgis Gozadinos
5f4c73f89f
Add image attachment to the chat TUI 2026-07-25 10:58:08 +03:00
Yiorgis Gozadinos
f87fabe556
Make the capability image-attachment gate a vision bool 2026-07-24 16:00:01 +03:00
Yiorgis Gozadinos
6c5bc0aae1
Gate combined-chat capability vision on the driving model 2026-07-24 15:27:20 +03:00
Yiorgis Gozadinos
597808c56e
Fix chat analysis-model selection, AG-UI example state, and chat docs
Drive analysis-only chat with analysis.model (falling back to qa.model) so
the running model matches the one the analysis capability configures,
including its vision flag; RAG-bearing chats still run on qa.model.

Give the AG-UI example state-bearing deps and a final STATE_SNAPSHOT so
registered citations reach the client, mirroring the app backend.

Update chat docs: haiku-rag chat uses --capability/-c, and drop the removed
"View state" command-palette entry.
2026-07-24 15:27:20 +03:00
Yiorgis Gozadinos
77585ef26a
fix per-question capability limits and tool isolation 2026-07-24 15:26:18 +03:00
Yiorgis Gozadinos
43c17a6777
fix capability execution limits and chat loading 2026-07-24 15:26:17 +03:00
Yiorgis Gozadinos
9e7db72997
Load capabilities eagerly for dedicated single-agent consumers 2026-07-24 15:26:17 +03:00
Yiorgis Gozadinos
9deb1f2bd4
replace haiku.skills with native Pydantic AI capabilities 2026-07-24 15:26:17 +03:00
Yiorgis Gozadinos
0e271eaf4b
Remove --before/--at time travel 2026-07-16 13:11:33 +03:00
Yiorgis Gozadinos
0813a1c980
Add tag CLI commands and history tag annotations 2026-07-16 13:11:27 +03:00
Yiorgis Gozadinos
da79f92af1
Honor OTEL_SERVICE_NAME and set service name/version for all processes 2026-07-10 11:11:46 +03:00
Yiorgis Gozadinos
995d081aa1
Visualize the exact context the model saw via Citation.doc_item_refs
visualize_chunk re-expanded chunks from scratch to recover their refs,
which could not faithfully reproduce the original merge, scores, and
clip — so a visualization could highlight different pages than the
citation covered. Carry the cited items on Citation.doc_item_refs and
resolve bounding boxes from them directly; re-expansion remains only as
the fallback for callers with no stored context (CLI, inspector). Chat,
inspector, the app endpoint, and the frontend pass the refs through.
2026-07-09 11:51:37 +03:00
Yiorgis Gozadinos
494f774473
Visualize all constituent chunks of a merged citation 2026-07-09 11:05:41 +03:00
Yiorgis Gozadinos
73f8349a00
Use haiku.rag as telemtry scope 2026-05-26 11:44:47 +03:00
Yiorgis Gozadinos
188d35023f
rotate chat TUI conversation id per launch / clear-chat 2026-05-21 14:21:51 +03:00
Yiorgis Gozadinos
8c57a3ca99
Drop the multi-agent research workflow 2026-05-20 12:46:48 +03:00
Yiorgis Gozadinos
f13461cdca
route figures through cite, drop show_image 2026-05-18 16:48:34 +03:00
Yiorgis Gozadinos
1df6530d03
Bump pydantic-ai, prepare for 2.* 2026-05-18 15:14:29 +03:00
Yiorgis Gozadinos
674b80e8c9
Support streaming for markdown 2026-05-12 16:01:42 +03:00
Yiorgis Gozadinos
7685a592c2
bump haiku.skills to 0.16.0 2026-04-28 12:03:14 +03:00
Yiorgis Gozadinos
cb9360ef7b
fix chat TUI citation rendering after state flattening 2026-04-24 13:48:57 +03:00
Yiorgis Gozadinos
eb4e1721ce
remove dead code, add tool descriptions in frontend, update changelog 2026-04-20 15:38:17 +03:00
Yiorgis Gozadinos
d52f453c44
flatten skill architecture: replace ask/analyze/research with direct tools 2026-04-17 18:35:17 +03:00
Yiorgis Gozadinos
20e40d75f9
add collapsible program display to chat TUI
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-17 18:35:17 +03:00
Yiorgis Gozadinos
7d98d0ec57
add citation support to analysis agent 2026-04-17 18:35:16 +03:00
Yiorgis Gozadinos
cf89ff55cd
When setting --model, set all subagents as well 2026-04-17 18:35:16 +03:00
Yiorgis Gozadinos
2a0e89bbe7
add --skill flag to chat TUI for rag and analysis skills 2026-04-17 18:35:16 +03:00
Yiorgis Gozadinos
e16c819e83
Adapt to new haiku.skills 2026-04-16 11:50:55 +03:00
Yiorgis Gozadinos
e4dc60c4f1
Update core dependencies 2026-04-03 10:14:27 +03:00
Yiorgis Gozadinos
c4c90b3930
Propagate domain_preamble to skill instructions and main agent preamble 2026-04-01 13:13:36 +03:00
Yiorgis Gozadinos
5eb250af05
Fix broken textual detection in chat & inspect 2026-03-26 17:42:38 +02:00
Yiorgis Gozadinos
1d108b42ec
handle ActivitySnapshotEvent for skill sub-agent tool calls 2026-03-13 11:37:24 +02:00
Yiorgis Gozadinos
2566bf1a61
Adapt to haiku.skills streaming sub-agent ag-ui events 2026-03-03 11:16:44 +02:00
Yiorgis Gozadinos
52ef983e75
Fix default chat model, default to config.qa.model 2026-02-28 14:00:40 +02:00
Yiorgis Gozadinos
27a71c7e01
Adapt skill usage to haiku.skills prompt builder. Closes #289 2026-02-28 13:34:54 +02:00
Yiorgis Gozadinos
c61ded1271
Replace Docker sandbox with pydantic-monty 2026-02-24 09:55:40 +02:00
Yiorgis Gozadinos
cb5935a6fa
Show in tui and nextjs app what is being requested from a skill 2026-02-20 18:14:44 +02:00
Yiorgis Gozadinos
69083c8cb4
Fix stale docs 2026-02-20 16:59:58 +02:00
Yiorgis Gozadinos
5dd8a82d1f
Exclude TUI apps from coverage 2026-02-20 16:37:16 +02:00
Yiorgis Gozadinos
eb9436eb2a
Remove unused conversational output mode from research graph 2026-02-20 16:36:50 +02:00
Yiorgis Gozadinos
c567842420
Rewire document filter 2026-02-20 16:36:50 +02:00
Yiorgis Gozadinos
a7850e2210
Assign stable index to citations. Use a strong prompt preamble for our app agents 2026-02-20 16:36:48 +02:00
Yiorgis Gozadinos
643ed20d6f
Rewrite chat TUI and app backend with haiku.skills 2026-02-20 16:36:48 +02:00