diff --git a/Cargo.lock b/Cargo.lock index e2a6ebb9..a096db6b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2242,7 +2242,7 @@ dependencies = [ [[package]] name = "harness-gateway-client" version = "0.3.0" -source = "git+https://github.com/cppalliance/runvil-harness?rev=5bca6f9fd9b398d5f221a5893570b8085bc283da#5bca6f9fd9b398d5f221a5893570b8085bc283da" +source = "git+https://github.com/cppalliance/runvil-harness?rev=7147e709f603b81786fb2d702bf50c4d9a88d62b#7147e709f603b81786fb2d702bf50c4d9a88d62b" dependencies = [ "async-trait", "bytes", @@ -2258,7 +2258,7 @@ dependencies = [ [[package]] name = "harness-plugin-loader" version = "0.3.0" -source = "git+https://github.com/cppalliance/runvil-harness?rev=5bca6f9fd9b398d5f221a5893570b8085bc283da#5bca6f9fd9b398d5f221a5893570b8085bc283da" +source = "git+https://github.com/cppalliance/runvil-harness?rev=7147e709f603b81786fb2d702bf50c4d9a88d62b#7147e709f603b81786fb2d702bf50c4d9a88d62b" dependencies = [ "libloading 0.8.9", "runvil-plugin", @@ -2269,7 +2269,7 @@ dependencies = [ [[package]] name = "harness-runner" version = "0.3.0" -source = "git+https://github.com/cppalliance/runvil-harness?rev=5bca6f9fd9b398d5f221a5893570b8085bc283da#5bca6f9fd9b398d5f221a5893570b8085bc283da" +source = "git+https://github.com/cppalliance/runvil-harness?rev=7147e709f603b81786fb2d702bf50c4d9a88d62b#7147e709f603b81786fb2d702bf50c4d9a88d62b" dependencies = [ "futures-util", "rand 0.9.5", @@ -4064,7 +4064,7 @@ dependencies = [ [[package]] name = "plugin-mcp" version = "0.3.0" -source = "git+https://github.com/cppalliance/runvil-harness?rev=5bca6f9fd9b398d5f221a5893570b8085bc283da#5bca6f9fd9b398d5f221a5893570b8085bc283da" +source = "git+https://github.com/cppalliance/runvil-harness?rev=7147e709f603b81786fb2d702bf50c4d9a88d62b#7147e709f603b81786fb2d702bf50c4d9a88d62b" dependencies = [ "reqwest", "rmcp", @@ -4088,7 +4088,7 @@ dependencies = [ [[package]] name = "plugin-web" version = "0.3.0" -source = "git+https://github.com/cppalliance/runvil-harness?rev=5bca6f9fd9b398d5f221a5893570b8085bc283da#5bca6f9fd9b398d5f221a5893570b8085bc283da" +source = "git+https://github.com/cppalliance/runvil-harness?rev=7147e709f603b81786fb2d702bf50c4d9a88d62b#7147e709f603b81786fb2d702bf50c4d9a88d62b" dependencies = [ "async-trait", "encoding_rs", @@ -4375,9 +4375,9 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.5.15" +version = "0.5.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35a133f956daabe89a61a685c2649f13d82d5aa4bd5d12d1277e1072a21c0694" +checksum = "af66907df18639dcf4db56ca65490cabc4b27a97dbadd96f2926cca73298f016" dependencies = [ "cfg_aliases", "libc", @@ -4734,7 +4734,7 @@ dependencies = [ [[package]] name = "runvil" version = "0.3.0" -source = "git+https://github.com/cppalliance/runvil-harness?rev=5bca6f9fd9b398d5f221a5893570b8085bc283da#5bca6f9fd9b398d5f221a5893570b8085bc283da" +source = "git+https://github.com/cppalliance/runvil-harness?rev=7147e709f603b81786fb2d702bf50c4d9a88d62b#7147e709f603b81786fb2d702bf50c4d9a88d62b" dependencies = [ "harness-plugin-loader", "harness-runner", @@ -4745,7 +4745,7 @@ dependencies = [ [[package]] name = "runvil-engine" version = "0.3.0" -source = "git+https://github.com/cppalliance/runvil-harness?rev=5bca6f9fd9b398d5f221a5893570b8085bc283da#5bca6f9fd9b398d5f221a5893570b8085bc283da" +source = "git+https://github.com/cppalliance/runvil-harness?rev=7147e709f603b81786fb2d702bf50c4d9a88d62b#7147e709f603b81786fb2d702bf50c4d9a88d62b" dependencies = [ "runvil-lua", "runvil-model-client", @@ -4758,7 +4758,7 @@ dependencies = [ [[package]] name = "runvil-lua" version = "0.3.0" -source = "git+https://github.com/cppalliance/runvil-harness?rev=5bca6f9fd9b398d5f221a5893570b8085bc283da#5bca6f9fd9b398d5f221a5893570b8085bc283da" +source = "git+https://github.com/cppalliance/runvil-harness?rev=7147e709f603b81786fb2d702bf50c4d9a88d62b#7147e709f603b81786fb2d702bf50c4d9a88d62b" dependencies = [ "mlua", "runvil-markdown", @@ -4772,7 +4772,7 @@ dependencies = [ [[package]] name = "runvil-markdown" version = "0.3.0" -source = "git+https://github.com/cppalliance/runvil-harness?rev=5bca6f9fd9b398d5f221a5893570b8085bc283da#5bca6f9fd9b398d5f221a5893570b8085bc283da" +source = "git+https://github.com/cppalliance/runvil-harness?rev=7147e709f603b81786fb2d702bf50c4d9a88d62b#7147e709f603b81786fb2d702bf50c4d9a88d62b" dependencies = [ "pulldown-cmark", "serde_json", @@ -4782,7 +4782,7 @@ dependencies = [ [[package]] name = "runvil-model-client" version = "0.3.0" -source = "git+https://github.com/cppalliance/runvil-harness?rev=5bca6f9fd9b398d5f221a5893570b8085bc283da#5bca6f9fd9b398d5f221a5893570b8085bc283da" +source = "git+https://github.com/cppalliance/runvil-harness?rev=7147e709f603b81786fb2d702bf50c4d9a88d62b#7147e709f603b81786fb2d702bf50c4d9a88d62b" dependencies = [ "runvil-types", "serde", @@ -4792,7 +4792,7 @@ dependencies = [ [[package]] name = "runvil-plugin" version = "0.3.0" -source = "git+https://github.com/cppalliance/runvil-harness?rev=5bca6f9fd9b398d5f221a5893570b8085bc283da#5bca6f9fd9b398d5f221a5893570b8085bc283da" +source = "git+https://github.com/cppalliance/runvil-harness?rev=7147e709f603b81786fb2d702bf50c4d9a88d62b#7147e709f603b81786fb2d702bf50c4d9a88d62b" dependencies = [ "runvil-types", "runvil-vfs", @@ -4815,7 +4815,7 @@ source = "git+https://github.com/cppalliance/runvil-plugin-api?rev=03a9fa37d2fe6 [[package]] name = "runvil-prompt" version = "0.3.0" -source = "git+https://github.com/cppalliance/runvil-harness?rev=5bca6f9fd9b398d5f221a5893570b8085bc283da#5bca6f9fd9b398d5f221a5893570b8085bc283da" +source = "git+https://github.com/cppalliance/runvil-harness?rev=7147e709f603b81786fb2d702bf50c4d9a88d62b#7147e709f603b81786fb2d702bf50c4d9a88d62b" dependencies = [ "pulldown-cmark", "runvil-lua", @@ -4827,7 +4827,7 @@ dependencies = [ [[package]] name = "runvil-runtime" version = "0.3.0" -source = "git+https://github.com/cppalliance/runvil-harness?rev=5bca6f9fd9b398d5f221a5893570b8085bc283da#5bca6f9fd9b398d5f221a5893570b8085bc283da" +source = "git+https://github.com/cppalliance/runvil-harness?rev=7147e709f603b81786fb2d702bf50c4d9a88d62b#7147e709f603b81786fb2d702bf50c4d9a88d62b" dependencies = [ "mlua", "regex", @@ -4845,7 +4845,7 @@ dependencies = [ [[package]] name = "runvil-types" version = "0.3.0" -source = "git+https://github.com/cppalliance/runvil-harness?rev=5bca6f9fd9b398d5f221a5893570b8085bc283da#5bca6f9fd9b398d5f221a5893570b8085bc283da" +source = "git+https://github.com/cppalliance/runvil-harness?rev=7147e709f603b81786fb2d702bf50c4d9a88d62b#7147e709f603b81786fb2d702bf50c4d9a88d62b" dependencies = [ "serde", "serde_json", @@ -4855,7 +4855,7 @@ dependencies = [ [[package]] name = "runvil-vfs" version = "0.3.0" -source = "git+https://github.com/cppalliance/runvil-harness?rev=5bca6f9fd9b398d5f221a5893570b8085bc283da#5bca6f9fd9b398d5f221a5893570b8085bc283da" +source = "git+https://github.com/cppalliance/runvil-harness?rev=7147e709f603b81786fb2d702bf50c4d9a88d62b#7147e709f603b81786fb2d702bf50c4d9a88d62b" [[package]] name = "rust-embed" diff --git a/Cargo.toml b/Cargo.toml index 12e109a6..e4cfdb31 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,10 +25,10 @@ repository = "https://github.com/cppalliance/runvil-workshop" # in. All four name one commit, because two commits would be two copies # of every type the crates share. `version` beside `git` keeps cargo-deny's # wildcard check quiet. -runvil = { version = "0.3.0", git = "https://github.com/cppalliance/runvil-harness", rev = "5bca6f9fd9b398d5f221a5893570b8085bc283da" } -harness-gateway-client = { version = "0.3.0", git = "https://github.com/cppalliance/runvil-harness", rev = "5bca6f9fd9b398d5f221a5893570b8085bc283da" } -plugin-web = { version = "0.3.0", git = "https://github.com/cppalliance/runvil-harness", rev = "5bca6f9fd9b398d5f221a5893570b8085bc283da" } -plugin-mcp = { version = "0.3.0", git = "https://github.com/cppalliance/runvil-harness", rev = "5bca6f9fd9b398d5f221a5893570b8085bc283da" } +runvil = { version = "0.3.0", git = "https://github.com/cppalliance/runvil-harness", rev = "7147e709f603b81786fb2d702bf50c4d9a88d62b" } +harness-gateway-client = { version = "0.3.0", git = "https://github.com/cppalliance/runvil-harness", rev = "7147e709f603b81786fb2d702bf50c4d9a88d62b" } +plugin-web = { version = "0.3.0", git = "https://github.com/cppalliance/runvil-harness", rev = "7147e709f603b81786fb2d702bf50c4d9a88d62b" } +plugin-mcp = { version = "0.3.0", git = "https://github.com/cppalliance/runvil-harness", rev = "7147e709f603b81786fb2d702bf50c4d9a88d62b" } # The safe layer over the C Plugin contract, version 0.4, from its own # repository, pinned by commit. Only the library Plugin crates under # `crates/workshop/` name it, for `export_plugin!`. The commit is the one diff --git a/crates/workshop/agents/agents/chat.md b/crates/workshop/agents/agents/chat.md index a3168cd1..7796d176 100644 --- a/crates/workshop/agents/agents/chat.md +++ b/crates/workshop/agents/agents/chat.md @@ -8,8 +8,6 @@ models: min_context: 32768 --- -# Chat - The built-in chat agent: a pass-through between the operator and the selected model, whose one system message says where the Runvil prompting language documentation is mounted. The conversation is the section's `messages` list, retained across turns; the model is the dropdown's selection bound at run launch, so a selection change takes effect on the next run. When the conversation outgrows the model's context window, older turns are summarized so the conversation continues. ## Conversation diff --git a/crates/workshop/agents/tests/it/conversation.rs b/crates/workshop/agents/tests/it/conversation.rs index 527e7eb5..a8d9cc8d 100644 --- a/crates/workshop/agents/tests/it/conversation.rs +++ b/crates/workshop/agents/tests/it/conversation.rs @@ -115,7 +115,7 @@ async fn an_agent_that_fails_to_parse_reports_a_run_failure_and_records_no_run() let conversation = table.open("unclosed"); let recorder = Arc::new(MemoryRecorder::new()); let mut errors = conversation.subscribe_errors(); - let unclosed = "---\nname: unclosed\ndescription: d\nrunvil: 0\n\n# Title\n".to_owned(); + let unclosed = "---\nname: unclosed\ndescription: d\nrunvil: 0\n\n## Only\n".to_owned(); let (host, _setup) = run_for(&conversation, Arc::clone(&recorder), unclosed.clone()); let parse_failure = host .parse(AGENT) @@ -152,7 +152,7 @@ async fn a_completed_report_reports_nothing_and_ends_the_conversation() { let recorder = Arc::new(MemoryRecorder::new()); let mut errors = conversation.subscribe_errors(); - ended(start(&conversation, &recorder, prompt("return 'done'"))).await; + ended(start(&conversation, &recorder, prompt("return 'finished'"))).await; assert!( reports(&mut errors).is_empty(), @@ -160,7 +160,11 @@ async fn a_completed_report_reports_nothing_and_ends_the_conversation() { ); assert_eq!(conversation.state(), SessionState::Closed); let run = conversation.run_id().expect("the recorder began the run"); - assert_eq!(recorder.result(run), Some(Ok("done".to_owned()))); + assert_eq!( + recorder.result(run), + Some(Ok("finished".to_owned())), + "the result is the text the agent's Lua returned, where a run with no text ends as `done`" + ); assert!(table.get(conversation.id()).is_none()); } diff --git a/crates/workshop/agents/tests/it/support.rs b/crates/workshop/agents/tests/it/support.rs index 0a476271..b4f32efd 100644 --- a/crates/workshop/agents/tests/it/support.rs +++ b/crates/workshop/agents/tests/it/support.rs @@ -43,7 +43,7 @@ pub(crate) fn prompt(lua: &str) -> String { format!( "---\nname: fixture\ndescription: a conversation fixture\nrunvil: 0\n\ uses:\n - user\n---\n\n\ - # Fixture\n\n## Conversation\n\n```lua\n{lua}\n```\n" + ## Conversation\n\n```lua\n{lua}\n```\n" ) } diff --git a/crates/workshop/server/src/agents/language_guide/tests.rs b/crates/workshop/server/src/agents/language_guide/tests.rs index 3862e46d..e2731f21 100644 --- a/crates/workshop/server/src/agents/language_guide/tests.rs +++ b/crates/workshop/server/src/agents/language_guide/tests.rs @@ -211,8 +211,6 @@ uses: - std --- -# Sees the mapping - ## Only ```lua @@ -254,8 +252,6 @@ runvil: 0 uses: [bash] --- -# Shells over the mappings - ## Only ```lua diff --git a/crates/workshop/server/src/agents/tests.rs b/crates/workshop/server/src/agents/tests.rs index fb74514e..e7024141 100644 --- a/crates/workshop/server/src/agents/tests.rs +++ b/crates/workshop/server/src/agents/tests.rs @@ -53,7 +53,7 @@ fn requiring(pack: &str) -> String { format!( "---\nname: browses\ndescription: needs {pack}\nrunvil: 0\n\ uses:\n - {pack}\n---\n\n\ - # Browses\n\n## Only\n\n```lua\nreturn 'browsed'\n```\n" + ## Only\n\n```lua\nreturn 'browsed'\n```\n" ) } @@ -142,7 +142,7 @@ fn mcp_file(text: &str) -> (tempfile::TempDir, std::path::PathBuf) { #[tokio::test] async fn every_run_holds_the_packs_the_three_plugins_add_and_the_builtins() { let lists = "---\nname: lists\ndescription: reads its Packs\nrunvil: 0\n---\n\n\ - # Lists\n\n## Only\n\n```lua\n\ + ## Only\n\n```lua\n\ local names = {}\n\ for _, id in ipairs({ 'web', 'subagents', 'mcp', 'std', 'user' }) do\n\ names[#names + 1] = tools.packs.get(id).name\n\ @@ -417,7 +417,7 @@ fn only_a_plugin_directory_with_a_shipped_library_gives_the_host_its_pack() { /// A prompt that declares `std` and returns what `std/read` answers for /// `/notes.md`, then what `std/write` answers. const READS_NOTES: &str = "---\nname: reads\ndescription: reads a file\nrunvil: 0\n\ - uses:\n - std\n---\n\n# Reads\n\n## Only\n\n```lua\n\ + uses:\n - std\n---\n\n## Only\n\n```lua\n\ local read = tools.call('std/read', { path = '/notes.md' })\n\ local write = tools.call('std/write', { path = '/out.md', contents = 'x' })\n\ return read .. '|' .. write\n```\n"; @@ -480,7 +480,7 @@ async fn without_a_plugin_directory_a_prompt_requiring_a_shipped_pack_is_refused /// A prompt that declares `bash` and returns what `bash/shell` answers /// for a command that reads `/notes.md` and then writes a file. const RUNS_A_COMMAND: &str = "---\nname: shells\ndescription: runs a command\nrunvil: 0\n\ - uses:\n - bash\n---\n\n# Shells\n\n## Only\n\n```lua\n\ + uses:\n - bash\n---\n\n## Only\n\n```lua\n\ return tools.call('bash/shell', { command = 'cat /notes.md; echo x > /out.md' })\n```\n"; #[tokio::test] diff --git a/crates/workshop/server/src/routes/prompts-tests.rs b/crates/workshop/server/src/routes/prompts-tests.rs index d738da5c..cdd70a0c 100644 --- a/crates/workshop/server/src/routes/prompts-tests.rs +++ b/crates/workshop/server/src/routes/prompts-tests.rs @@ -64,8 +64,6 @@ models: fast: {} --- -# Full - ## Only Body text. @@ -119,7 +117,7 @@ async fn a_full_frontmatter_prompt_answers_every_contract_section() { #[tokio::test] async fn a_broken_yaml_key_answers_parse_frontmatter_with_the_line() { - let text = "---\nname: [unclosed\ndescription: x\n---\n\n# T\n\n## S\n\np\n"; + let text = "---\nname: [unclosed\ndescription: x\n---\n\n## S\n\np\n"; let body = serde_json::json!({ "name": "broken", "text": text }); let (status, json) = post_contract(body).await; assert_eq!(status, StatusCode::UNPROCESSABLE_ENTITY); @@ -150,7 +148,7 @@ fn an_internal_parse_failure_names_no_prompt_line() { #[tokio::test] async fn a_prompt_without_args_yields_the_implicit_prose_field() { - let text = "---\nname: plain\ndescription: no args\n---\n\n# Plain\n\n## S\n\np\n"; + let text = "---\nname: plain\ndescription: no args\n---\n\n## S\n\np\n"; let body = serde_json::json!({ "name": "plain", "text": text }); let (status, json) = post_contract(body).await; assert_eq!(status, StatusCode::OK); @@ -172,8 +170,7 @@ async fn a_prompt_without_args_yields_the_implicit_prose_field() { #[tokio::test] async fn a_lua_error_answers_parse_lua() { - let text = - "---\nname: badlua\ndescription: bad lua\n---\n\n# Bad\n\n## S\n\n```lua\nreturn (\n```\n"; + let text = "---\nname: badlua\ndescription: bad lua\n---\n\n## S\n\n```lua\nreturn (\n```\n"; let body = serde_json::json!({ "name": "badlua", "text": text }); let (status, json) = post_contract(body).await; assert_eq!(status, StatusCode::UNPROCESSABLE_ENTITY); @@ -193,7 +190,7 @@ async fn the_contract_has_no_tools_section() { #[tokio::test] async fn the_dto_serializes_absent_declarations_as_nulls() { - let text = "---\nname: nulls\ndescription: absent keys\n---\n\n# Nulls\n\n## S\n\np\n"; + let text = "---\nname: nulls\ndescription: absent keys\n---\n\n## S\n\np\n"; let body = serde_json::json!({ "name": "nulls", "text": text }); let (status, json) = post_contract(body).await; assert_eq!(status, StatusCode::OK); diff --git a/crates/workshop/server/tests/it/agents.rs b/crates/workshop/server/tests/it/agents.rs index 2d596e84..b452f7f1 100644 --- a/crates/workshop/server/tests/it/agents.rs +++ b/crates/workshop/server/tests/it/agents.rs @@ -39,8 +39,6 @@ uses: - user --- -# Echo - ## Conversation ```lua diff --git a/crates/workshop/server/tests/it/agents/lifecycle.rs b/crates/workshop/server/tests/it/agents/lifecycle.rs index 184fc10d..4cb7ae9e 100644 --- a/crates/workshop/server/tests/it/agents/lifecycle.rs +++ b/crates/workshop/server/tests/it/agents/lifecycle.rs @@ -153,9 +153,9 @@ async fn a_program_that_returns_frames_run_ended_and_a_later_message_is_refused( json!({ "type": "agent_event", "index": 2, - "event": { "kind": "run_ended", "section": "Echo", "turn": 0, "content": "" }, + "event": { "kind": "run_ended", "section": "echo", "turn": 0, "content": "" }, }), - "the run's end frames right after the message it returned on, under the prompt's title" + "the run's end frames right after the message it returned on, under the prompt's name" ); answer(&mut socket, "too late").await; @@ -184,8 +184,6 @@ uses: - user --- -# Boom - ## Conversation ```lua diff --git a/crates/workshop/server/tests/it/agents/revoke.rs b/crates/workshop/server/tests/it/agents/revoke.rs index fe73fd63..e8eba3bf 100644 --- a/crates/workshop/server/tests/it/agents/revoke.rs +++ b/crates/workshop/server/tests/it/agents/revoke.rs @@ -19,8 +19,6 @@ uses: - user --- -# Roots - ## Conversation ```lua diff --git a/crates/workshop/server/tests/it/agents/turns.rs b/crates/workshop/server/tests/it/agents/turns.rs index 8d543961..1e73453e 100644 --- a/crates/workshop/server/tests/it/agents/turns.rs +++ b/crates/workshop/server/tests/it/agents/turns.rs @@ -22,8 +22,6 @@ uses: - web --- -# Steer - ## Conversation ```lua diff --git a/crates/workshop/server/tests/it/chat_gate/canonical_sequence.rs b/crates/workshop/server/tests/it/chat_gate/canonical_sequence.rs index 5996a4ee..0c3ed767 100644 --- a/crates/workshop/server/tests/it/chat_gate/canonical_sequence.rs +++ b/crates/workshop/server/tests/it/chat_gate/canonical_sequence.rs @@ -203,8 +203,8 @@ async fn gate_a_conversation_round_advertises_the_shell_after_the_file_tools() { /// GATE 12 - web tools. The chat's `## Conversation` section offers the /// `web` Pack, so the rounds its model loop sends advertise the -/// Pack's fetch and search tools; an offer in the H1 would not reach -/// them. +/// Pack's fetch and search tools; an offer above that heading would not +/// reach them. #[tokio::test] async fn gate_a_conversation_round_advertises_the_web_tools() { let server = spawn_chat_server(&["test-model"]).await;