mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-24 10:09:32 -06:00
Docs: agents.md lists every MCP tool and argument, checked by a test (#137)
The Tools table gains history and script_ui, get_layer's depth, add_keyframe's comp and the bridge screenshot's max_side and path. agents_doc_tools_table_is_current (effectcraft-automation) fails when a tool or an argument of its input schema is missing from the table, as effects_doc_is_current guards docs/effects.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
fd533fdb6d
commit
eb5e72cdfa
@@ -421,3 +421,41 @@ fn trained_models_over_mcp() {
|
||||
assert!(err && c[0]["text"].as_str().unwrap().contains("unknown model"), "{c:?}");
|
||||
}
|
||||
}
|
||||
|
||||
/// docs/agents.md's Tools table lists every tool, and an entry that lists arguments lists every
|
||||
/// argument the tool's input schema accepts (#137).
|
||||
#[test]
|
||||
fn agents_doc_tools_table_is_current() {
|
||||
// (Checkouts may have CRLF line endings.)
|
||||
let doc = include_str!("../../../docs/agents.md").replace("\r\n", "\n");
|
||||
let table: String = doc
|
||||
.split("### Tools")
|
||||
.nth(1)
|
||||
.and_then(|t| t.split("\n\n").nth(1))
|
||||
.unwrap_or_default()
|
||||
.to_string();
|
||||
assert!(table.starts_with("| Tool |"), "no Tools table");
|
||||
let mut missing = vec![];
|
||||
for t in crate::tools::catalogue() {
|
||||
// `name` (no arguments) or `name {a, b?, …}`.
|
||||
let Some(at) = table.find(&format!("`{}", t.name)).filter(|i| {
|
||||
let rest = &table[i + 1 + t.name.len()..];
|
||||
rest.starts_with('`') || rest.starts_with(" {")
|
||||
}) else {
|
||||
missing.push(format!("{}: no entry", t.name));
|
||||
continue;
|
||||
};
|
||||
let rest = &table[at + 1 + t.name.len()..];
|
||||
if !rest.starts_with(" {") {
|
||||
continue;
|
||||
}
|
||||
let args = rest.split("}`").next().unwrap_or_default();
|
||||
let schema = t.input_schema();
|
||||
for prop in schema["properties"].as_object().into_iter().flat_map(|p| p.keys()) {
|
||||
if !args.split(|c: char| !(c.is_alphanumeric() || c == '_')).any(|w| w == prop) {
|
||||
missing.push(format!("{}: argument `{prop}`", t.name));
|
||||
}
|
||||
}
|
||||
}
|
||||
assert!(missing.is_empty(), "docs/agents.md's Tools table is missing: {missing:#?}");
|
||||
}
|
||||
|
||||
+5
-3
@@ -53,18 +53,20 @@ The server speaks JSON-RPC 2.0 over stdio, one message per line, and supports MC
|
||||
| `get_state` | Editor state (active comp, time, selections, tool) plus `app`: version, command and effect counts, export formats, parity summary. |
|
||||
| `run_script {code, name?}` | Run JavaScript with the After Effects-style scripting object model (`app.project`, `comp.layers.addText(…)`, `layer.property("ADBE Transform Group").property("ADBE Position").setValueAtTime(…)`…). Returns `{ok, result, output, error: {message, line, column}}`; edits are undoable. |
|
||||
| `get_project` / `get_comp {comp?}` | Project items, comp settings and layers. |
|
||||
| `get_layer {layer, comp?, time?, flat?}` | A layer's property tree. Every node has a `path`. |
|
||||
| `get_layer {layer, comp?, time?, depth?, flat?}` | A layer's property tree (`depth` limits how many group levels expand). Every node has a `path`. |
|
||||
| `get_property {layer, path, comp?, time?}` | Value at a time, keyframes and expression. |
|
||||
| `set_property {layer, path, value?, time?, expression?, comp?}` | Sets a static value. With `time` it sets a keyframe; with `expression` it sets an expression. |
|
||||
| `add_keyframe {layer, path, time+value \| keys:[...], interpolation?}` | Adds keys, then optionally applies linear/bezier/hold/easyEase. |
|
||||
| `add_keyframe {layer, path, time+value \| keys:[...], interpolation?, comp?}` | Adds keys, then optionally applies linear/bezier/hold/easyEase. |
|
||||
| `list_effects {filter?}` | Effect ids, names, categories, GPU / 32-bpc support and parameters. |
|
||||
| `list_fonts {query?, rescan?}` | Font families text layers can use, bundled and installed, with their styles, origin and own-language name; `rescan` picks up fonts installed since launch. |
|
||||
| `add_effect {layer, effect, values?, comp?}` | Apply an effect and set its parameters in one call; returns the instance path (`effects/#n`) and its parameter paths. |
|
||||
| `render_frame {comp?, time?, max_side?, path?, inline?, transparent?}` | Returns a PNG image of a frame; `transparent: true` keeps the alpha (as an RGB + Alpha render writes it) instead of compositing over the comp background. |
|
||||
| `open_project {path \| demo \| new}` / `save_project {path?}` | Open and save files. |
|
||||
| `undo {steps?}` / `redo {steps?}` | History. |
|
||||
| `history {goto?}` | The branching undo history (History panel): every state with its index, id, label, branch depth and whether it's current; `goto` (an index or id) jumps to any state, on any branch, without losing the others. |
|
||||
| `script_ui {action?, window?, widget?, value?, result?}` | Drive ScriptUI windows that scripts opened: `list` (default) the open windows, `get` a window's control tree, `click` a button / checkbox / radio button, `set` text, a slider or a list item, `close` a window (`result`: what a dialog's `show()` returns, default 2 = Cancel). |
|
||||
| `batch {steps: [{command, params}], label?, atomic?}` | Several commands in one call and one undo step (`engine.batch`); `"$N.key"` in a param is step N's result (`"$1.layer"`). A failing step rolls the batch back and names the step. |
|
||||
| *(bridge)* `screenshot {panel?, id?}`, `ui_inspect`, `ui_elements {prefix?}`, `ui_click`, `ui_drag`, `ui_key`, `ui_type`, `ui_set`, `control {method, params}` | Look at and operate the live window. |
|
||||
| *(bridge)* `screenshot {panel?, id?, max_side?, path?}`, `ui_inspect`, `ui_elements {prefix?}`, `ui_click`, `ui_drag`, `ui_key`, `ui_type`, `ui_set`, `control {method, params}` | Look at and operate the live window. |
|
||||
|
||||
Layers are referenced by id (from `get_comp`), `"#n"` (1-based index from the top) or name. Comps are
|
||||
referenced by id or name, and default to the active comp. Property paths come from `get_layer`, for
|
||||
|
||||
Reference in New Issue
Block a user