Commit Graph

37 Commits

Author SHA1 Message Date
BFlat 5ea84a8f4c Cached prompt tokens from OpenAI-style APIs are counted once (#337)
OpenAI-style APIs report `prompt_tokens` including the cached part (`prompt_tokens_details.cached_tokens`). We stored the whole `prompt_tokens` as `input_tokens` and the cached part again as `cache_read_tokens`. The context budget and the cost meter add the two, so cached tokens counted twice: a 100,000-token prompt with 65,536 cached read as 165,536, crossing the 150k budget and summarising early, and it was charged both rates.

`input_tokens` is now `prompt_tokens` minus the cached tokens, as Anthropic reports it, so every consumer counts each token once.

**Verified:** a new stream test with the reporter's numbers (100,000 prompt, 65,536 cached, 10 output): input 34,464, cache reads 65,536. `cargo test -p craft-anything-ai` (186), clippy and fmt pass.

Fixes #252
2026-11-02 15:19:45 +07:00
BFlat 5b138b88a4 An ACP chat starts the agent's session again after a failed start, and Stop ends a waiting message (#320)
When an ACP agent answered `initialize` with an error (for example, not signed in) and kept running, the error was shown and the turn ended. But the agent's session was never started, and nothing started it later. The next message was queued for a session that never came, so the chat stayed busy. Stop cleared the queue without ending the turn, so every later message was refused as "still working".

- A message sent when the start has failed and nothing is under way now starts the handshake again (`initialize`, then the session). Another failure is reported and ends that message's turn like the first.
- Stop now ends the turn of a message still waiting for the session.

**Verified:** a new test of the protocol core: after a failed `initialize`, the next message sends `initialize` again, a second failure ends its turn, and Stop ends a waiting message. A late answer then sends no prompt. `cargo test -p craft-anything-ai` (184), clippy and fmt pass.

**Not verified:** a live run against an agent that refuses `initialize`.

Fixes #271
2026-11-02 14:53:22 +07:00
BFlat 10fb3cfc8d Changing AI settings never saves over ones that couldn't be read (#295)
`AiHub` read the `[ai]` settings with a fallback: when they couldn't be parsed (for example, a price override missing `output_per_mtok`), they counted as empty. Adding a backend, choosing a role, renaming a model, turning a backend on or off or removing one then saved that empty configuration plus the one change over the person's backends, roles, fallbacks and prices.

Every change now reads the `[ai]` section strictly (`config_to_change`). If it can't be read, the change stops with the existing BadSettings error ("The [ai] settings couldn't be read: … Fix or remove the [ai] section in config.toml") and nothing is saved. Adding a backend reads the settings before storing its key, so a refused add stores no key either. Displaying the configuration still falls back as before.

**Verified:** a new test with two backends, a chosen builder and a broken price override. Adding a backend, clearing a role, turning one off and removing one all fail with BadSettings; the settings file stays byte for byte the same, and the refused add stored no key. `cargo test -p craft-anything-ai` (184), clippy and fmt pass.

Fixes #261
2026-11-02 14:20:30 +07:00
BFlat e6e48e131d Saving a key never replaces a key file it couldn't read (#293)
The fallback key file (`ai-keys.toml`, used when there's no keychain) was read leniently: a file that couldn't be read or parsed counted as empty. The next save then wrote back only the new key, so a stray quote or a bad byte cost every other key in it, while the save reported success.

Saving and deleting a key now read the file strictly. A missing file is still empty. A file that can't be read, isn't UTF-8 or isn't valid TOML stops the save with "Couldn't read the key file …: <why>" and "Fix or move that file (it was left untouched)". Reading a key (`get`) is lenient as before. After a keychain save, the stale-copy cleanup skips a file it can't read instead of replacing it.

**Verified:** a new test with the reporter's two cases (an unclosed quote, and a trailing invalid byte): the set and the delete both fail and the file stays byte for byte the same; a valid file keeps its other key after a save. `cargo test -p craft-anything-ai keys`, clippy and fmt pass.

Fixes #262
2026-11-02 14:14:39 +07:00
vietanh210304 233556ed1d Hermes Agent builds and chats through its own adapter, and over ACP (#16)
Hermes Agent gets its own adapter: it runs as `hermes [-m <model>] [args] -z <prompt>`, never falls back to a plain `hermes <prompt>` (which opens its interactive session), and can run over ACP (`hermes acp`) when ACP is turned on.
2026-11-02 13:17:02 +07:00
muraa-p b36007cf8b A plain HTML and CSS request builds a static site instead of a Rust app (#225)
A request for a plain HTML and CSS site ("no frameworks", "no build step", "static html") now picks a Plain HTML and CSS stack: index.html and a stylesheet in app/, with nothing to build. Before, the request named no stack and the builder chose Rust + egui.

Fixes #161
2026-11-02 13:16:51 +07:00
Brandon Thomas da83b81be2 A build stops with a plain message when craft-anything-cli is missing (#226)
A local build by Claude Code, Codex or an ACP agent now checks that craft-anything-cli starts before studying or starting the agent. When it is missing or won't start, the build stops with a plain message and what to do, instead of Claude Code's "MCP tool not found" error. A check that times out lets the build go ahead, and stopping the build ends the check.

Refs #91, #64, #113.
2026-11-02 13:16:39 +07:00
BFlat 145d65c96c Codex is never run as plain text, which opened its interactive mode (#200)
When the check of codex exec --help didn't find --json, the run fell back to the plain adapter, codex <prompt>, which is Codex's interactive TUI and fails with "stdin is not a terminal". An adapter can now say its plain form doesn't work; Codex keeps its own adapter and the run says the check couldn't confirm the flag.

Fixes #199
2026-11-02 08:57:54 +07:00
X-EON d0c341739b Antigravity (agy) works as an agent program, in setup and the doctor (#89)
Adds an Antigravity adapter (stream-json output, resume by conversation, builder permissions) and lets setup and the doctor connect and check it under `antigravity` or `agy`.
2026-11-02 05:59:23 +07:00
BFlat 7776b97d2b A question answered outside a build stays in the project's conversation (#180)
Callers take the question before answering, and record_answer adds it with its answer when the saved conversation doesn't have it, once. Fixes #176.
2026-11-02 05:35:28 +07:00
BFlat 706f250c1c A failed build check says where it looked, not app/ for an app edited in place (#178)
The build check's messages name where the app is (Workspace::app_place): app/, or the project folder for an app edited in place. Fixes #174.
2026-11-02 05:26:27 +07:00
BFlat b9905c63a4 An out-of-date Claude Code says so, and how to update it (#169)
Claude Code's "does not support this model" error says Claude Code is too old, with the fix (claude update for the command-line tool, or another model in Settings → AI), and isn't retried. Fixes #165.
2026-11-02 04:41:07 +07:00
BFlat aae724f14b A rate-limited AI service is waited for as long as it asks (#148)
The builder reads the wait a busy or rate-limited service asked for (at most 15 minutes), says so plainly, and tries again then, instead of a fixed 30/60/90 s with the raw error. For #142.
2026-11-02 03:24:04 +07:00
BFlat e4d43abe14 Choose the model an AI uses in Settings → AI (#145)
Settings → AI shows each AI's model with Change…, listing the API's own models or Claude's models for Claude Code; craft-anything-cli ai model <name> [model] lists or sets it. Fixes #123 and #127.
2026-11-02 03:06:40 +07:00
BFlat 8ea06bb6fb Add an AI by its address in Settings → AI (#137)
Settings → AI gets an Add an AI by its address form; AiHub::add_server asks the server for its models before adding it and picks one that can chat when none is named; ai add --kind openai_compatible --base-url without --model does the same. Fixes #54, #98 and #128.
2026-11-02 02:32:11 +07:00
BFlat 12d7bc14d6 Look for AI picks a model that can chat, not an embedding model (#134)
Detection picks the first listed model that isn't named for embedding, ranking or speech, and falls back to the first only when that's all there is. Fixes the cause of #127.
2026-11-02 02:08:49 +07:00
才倾梦华V d55523e6cd Add Simplified and Traditional Chinese UI translations (R2.9) (#115)
Adds Simplified and Traditional Chinese UI catalogs, picks the UI language from the system when Language is System, makes prices and a few labels translatable, recognises Chinese words for games and websites in requests, and adds cargo xtask i18n-coverage and docs/localization.md.
2026-11-02 00:34:31 +07:00
BFlat 1a199ec531 Choose an agent app's program in Settings → AI (#117)
Each local agent app in Settings → AI shows which program runs it, with Choose… and Find it automatically; craft-anything-cli ai program <name> [path] does the same. The not-installed errors point there instead of a setting that didn't exist.
2026-11-02 00:32:39 +07:00
BFlat ca706dc980 Look for AI offers local servers already set up in OpenCode (#111)
Look for AI reads provider baseURLs from OpenCode's settings and probes those on this computer or its network, so LM Studio on another port or a server on another machine is offered. The JSONC reader moves from setup to formats so ai can use it. Fixes #83.
2026-11-01 23:56:28 +07:00
WadahBadawi 3973cbfcdd Scope test structs FlakyKind and FlakyCheck to unix (#52)
FlakyKind and FlakyCheck move into the unix-only test module that uses them, so clippy -D warnings passes on Windows.
2026-11-01 23:05:11 +07:00
BFlat 600ddb5aa4 Codex runs in project folders that aren't git repositories (#101)
codex exec refuses to run outside a git repository or a folder it trusts unless it gets --skip-git-repo-check, and project folders aren't repositories, so every Codex build failed at once. The adapter passes the flag, once, even when the backend's own args already have it.
2026-11-01 23:03:07 +07:00
BFlat 34adf21094 Testing a coding agent says it only checked the program's version (#49)
`ai test` on a coding agent only runs its `--version` and showed that line as the reply, so it
looked like a working answer while every real message could still fail (not signed in, no model,
no quota). The report now carries a typed `version_only` field (true for coding agents, false for
backends that answered a real request), and the doc comment says what the test does.

Fixes #48
2026-11-01 16:19:12 +07:00
BFlat d0d42f4fd1 An agent set up by its program and a model runs that agent with that model (#46)
An agent CLI's `model` names the agent (opencode) and the model it should use goes in cli_model,
which nothing in the app shows. People write the program in `command` and the model in `model`
instead (command = "opencode", model = "deepseek/deepseek-flash"), which ran the plain adapter
with the agent's own default model until its free quota ran out. Settings read that way now run the
agent the command names, asked for that model (OpenCode gets --model). A model that names an
agent, a cli_model already set, and unknown programs are left as they are.

Fixes #34
2026-11-01 15:56:54 +07:00
BFlat 9fc20b129d Doctor says a local AI server is reachable only when it answers with its models (#45)
Doctor checked a local (OpenAI-compatible) AI server by its open port alone, so any program on
that port, such as a plain web server on 8080, was reported "ok" while every chat with it failed.
It now asks the server for its model list, as it already does for every other kind of AI, and
reports what came back ("answered 404: 404 page not found") when that fails.

Fixes #37
2026-11-01 15:56:43 +07:00
BFlat 142eb05de8 Another program on a model server's port is no longer offered as an AI (#39)
Local model servers were found by an open port alone, so any program listening on 8080 (a common
port for local web servers) was offered as "llama.cpp server (local)" with no model, and chatting
with it failed with "answered 404: 404 page not found". A local server is now offered only when
its model list answers; one that answers with an error or a page that isn't JSON is something
else. A server that doesn't answer in time is still offered, as before, since it may be loading.

Fixes #30
2026-11-01 15:20:13 +07:00
BFlat f831e062cd OpenCode runs its task with opencode run instead of reading the prompt as a folder (#35)
OpenCode had no adapter of its own, so it got the plain one: the prompt as its only argument.
OpenCode reads its first argument as the folder to open, so every chat and build stopped at once
with exit code 1. It now runs `opencode run [--auto] [--model …] <prompt>`; builds pass `--auto`
so what OpenCode would stop to ask is allowed unless its own settings deny it, as Codex builds get
a workspace-write sandbox. Flags checked against OpenCode's own `run` command.

Fixes #32
Fixes #15
2026-11-01 15:06:49 +07:00
BFlat a70843145c LM Studio and other local servers accept our tools: boolean sub-schemas are sent as objects (#25)
schemars writes `"items": true` for a list of any JSON (app_call_path_find's `functions`), which
JSON Schema allows but LM Studio refuses ("JSON schema error at #/properties/functions/items:
schema must be an object"), so every chat with it stopped. Tool schemas sent to a model now write
`true` as `{}` and `false` as `{"not": {}}` wherever a schema sits (to a bounded depth, since
run-time tools bring their own); `additionalProperties` keeps its boolean.

Fixes #17
2026-11-01 14:36:45 +07:00
Brandon Thomas 4756633f89 Show what a build is on now, and open up into its activity as it arrives (#10)
The status row names the command or file under way instead of only counting
actions. "More detail" opens the latest lines: stages, every command and file
with how it ended, what the builder said, and what programs printed outside the
conversation. Everything is kept in build-activity.log, with secrets hidden, and
the rebuild_activity_show tool and the CLI read the same.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 21:12:56 -04:00
Brandon Thomas e244159c17 Call a coding agent's cost an estimate, not the bill (#9)
Claude Code's figure is its own guess at API prices, which a subscription
isn't charged. The project page now says "AI cost (estimate)" with a note
saying so, and the title bar says "(estimate)". What an API key was charged
is kept apart in usage.json; older files count as estimates.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 21:04:01 -04:00
Brandon Thomas 7ecce402f9 Try again picks up where a build stopped instead of starting over (#8)
A run with no message was read as a first build, so Try again studied the
original again and gave the builder the first brief, even with its session
saved. A run now carries on when the builder has already worked, and only
runs the check when the builder had finished (awaiting_check in craft.json).

A check that returns an error couldn't look at the build at all, so it gets a
second go, and then the run says the build is finished but couldn't be checked.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 21:01:22 -04:00
Brandon Thomas 8c0d7b0a38 Point links and release metadata at the renamed storytold/craft-anything repository (#7)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 20:30:51 -04:00
Brandon Thomas 6fe3d7f158 Show what a build is doing now and how long it has been quiet (#6)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 20:28:49 -04:00
Brandon Thomas 292d5af06e Stop deadlocks as they form and watch every lock for one that never lets go (#5)
* Stop deadlocks as they form and watch every lock for one that never lets go

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Give the stuck-lock banner's test a program of its own

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 20:28:16 -04:00
Brandon Thomas 6a120011a1 Explain failed agent runs, keep a log to open, and stop offering git servers as computers (#3)
* Explain failed agent runs, keep a log to open, and stop offering git servers as computers

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fix a lock-up: the build's agent setup took the session lock twice in one statement

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 20:27:44 -04:00
BFlat 62700f5c69 Built by no longer offers a GitHub SSH key as a computer, and finds Claude Code on a Mac opened from the Dock (#4)
SSH hosts that point at a git server (named after one, or with its HostName or User git) are left out of the AIs found on the computer and the remote-machine picker. Programs are looked up and started with PATH plus the usual install folders (~/.local/bin, Homebrew, npm, bun, volta, cargo), which a Mac app opened from the Dock doesn't get.
2026-10-31 23:48:53 +07:00
Brandon Thomas c316051c9e Point links and release metadata at the storytold/craftanything repository (#1)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 11:01:25 -04:00
Brandon Thomas f64ae3bf3c Craft Anything
A native, pure-Rust app that shows anyone how a piece of software works, with
evidence-backed answers, then helps them rebuild it. It ships a desktop app, a
CLI and an MCP server, all driven by one engine.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 10:52:14 -04:00