Update roster fixtures and redact live provider keys (T90)
This commit is contained in:
@@ -38402,7 +38402,6 @@ async function readTestConfig(fs2) {
|
||||
}
|
||||
async function writeTestConfig(fs2, value2) {
|
||||
const { roster, ...config } = value2;
|
||||
await fs2.mkdir(directory);
|
||||
for (const entry2 of await fs2.list(directory)) if (entry2.name.endsWith(".md")) await fs2.remove(`${directory}/${entry2.name}`);
|
||||
for (const entry2 of roster) {
|
||||
const { name, prompt, path: _path, ...fields } = entry2;
|
||||
|
||||
@@ -38360,7 +38360,7 @@ async function openStorage(path) {
|
||||
var textOf = (content) => typeof content === "string" ? content : (content ?? []).filter((part) => part.type === "text").map((part) => part.text).join("\n");
|
||||
function answerFor(rules, transcript) {
|
||||
const system = JSON.stringify(transcript.messages.filter((message) => message.role === "system"));
|
||||
const role = /P3 role:([a-z]+)/.exec(system)?.[1];
|
||||
const role = /P3 role:([a-zA-Z0-9_-]+)/.exec(system)?.[1];
|
||||
const last = transcript.messages.findLast((message) => message.role !== "system");
|
||||
const rule = rules.find((rule2) => rule2.role === role && (!rule2.match.kind || rule2.match.kind === last?.role) && textOf(last?.content).includes(rule2.match.text));
|
||||
if (!rule) throw new Error(`No scripted rule for ${role}: ${JSON.stringify(last)}`);
|
||||
|
||||
@@ -15,7 +15,6 @@ export async function readTestConfig(fs:any) {
|
||||
}
|
||||
export async function writeTestConfig(fs:any, value:any) {
|
||||
const {roster,...config}=value;
|
||||
await fs.mkdir(directory);
|
||||
for (const entry of await fs.list(directory)) if (entry.name.endsWith('.md')) await fs.remove(`${directory}/${entry.name}`);
|
||||
for (const entry of roster) {
|
||||
const {name,prompt,path: _path,...fields}=entry;
|
||||
|
||||
@@ -5,7 +5,7 @@ export type Rule = { id: string; role: string; match: { kind?: string; text: str
|
||||
export const textOf = (content: any): string => typeof content === 'string' ? content : (content ?? []).filter((part: any) => part.type === 'text').map((part: any) => part.text).join('\n');
|
||||
export function answerFor(rules: Rule[], transcript: any) {
|
||||
const system = JSON.stringify(transcript.messages.filter((message: any) => message.role === 'system'));
|
||||
const role = /P3 role:([a-z]+)/.exec(system)?.[1];
|
||||
const role = /P3 role:([a-zA-Z0-9_-]+)/.exec(system)?.[1];
|
||||
const last = transcript.messages.findLast((message: any) => message.role !== 'system');
|
||||
const rule = rules.find(rule => rule.role === role && (!rule.match.kind || rule.match.kind === last?.role) && textOf(last?.content).includes(rule.match.text));
|
||||
if (!rule) throw new Error(`No scripted rule for ${role}: ${JSON.stringify(last)}`);
|
||||
|
||||
@@ -37462,7 +37462,6 @@ async function readTestConfig(fs2) {
|
||||
}
|
||||
async function writeTestConfig(fs2, value2) {
|
||||
const { roster, ...config } = value2;
|
||||
await fs2.mkdir(directory);
|
||||
for (const entry2 of await fs2.list(directory)) if (entry2.name.endsWith(".md")) await fs2.remove(`${directory}/${entry2.name}`);
|
||||
for (const entry2 of roster) {
|
||||
const { name, prompt, path: _path, ...fields } = entry2;
|
||||
|
||||
@@ -148,7 +148,8 @@ pub async fn run_module_with_input(
|
||||
receiver: input::Receiver,
|
||||
source: &str,
|
||||
) -> anyhow::Result<()> {
|
||||
let provider_config = config::Config::read(&world.root).await?;
|
||||
let config_root = world.root.clone();
|
||||
let provider_config = config::Config::read(&config_root).await?;
|
||||
let loader = std::rc::Rc::new(loader::Loader {
|
||||
root: world.root.clone(),
|
||||
modules: Default::default(),
|
||||
@@ -232,9 +233,14 @@ pub async fn run_module_with_input(
|
||||
Ok::<_, anyhow::Error>(())
|
||||
}
|
||||
.await;
|
||||
let current_config = config::Config::read(&config_root).await.unwrap_or_default();
|
||||
result.map_err(|error| {
|
||||
let mut text = error.to_string();
|
||||
for provider in provider_config.providers.values() {
|
||||
for provider in provider_config
|
||||
.providers
|
||||
.values()
|
||||
.chain(current_config.providers.values())
|
||||
{
|
||||
if !provider.api_key.is_empty() {
|
||||
text = text.replace(&provider.api_key, "[redacted]");
|
||||
}
|
||||
|
||||
+6
-12
@@ -50,23 +50,17 @@ fn prepare(dir: &Path) -> anyhow::Result<()> {
|
||||
repo.join("extensions/probe/server.ts"),
|
||||
"export default host => { globalThis.dreamHost=host; globalThis.dreamService=host.need({name:'dream'}); globalThis.dreamSubagents=host.need({name:'subagents'}); globalThis.dreamAutomations=host.need({name:'automations'}); return {name:'probe'}; }",
|
||||
)?;
|
||||
let mut roster: Vec<serde_json::Value> = ["mainAgent", "coordinator", "worker", "reviewer"].into_iter().map(|role| serde_json::json!({
|
||||
let roster: Vec<serde_json::Value> = ["mainAgent", "coordinator", "worker", "reviewer"].into_iter().map(|role| serde_json::json!({
|
||||
"name":role, "description":format!("P3 {role}"), "model":"faux/faux-1",
|
||||
"isolate":"none", "resident":role == "mainAgent", "prompt":format!("P3 role:{role}"),
|
||||
"denyTools":if role == "worker" || role == "reviewer" {vec!["subagent"]} else {vec![]}
|
||||
})).collect();
|
||||
let defaults: serde_json::Value =
|
||||
serde_yaml_ng::from_str(include_str!("../../../config/config.yaml"))?;
|
||||
let mut pass = defaults["roster"]
|
||||
.as_array()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.find(|entry| entry["name"] == "dream-pass")
|
||||
.unwrap()
|
||||
.clone();
|
||||
pass["model"] = serde_json::json!("faux/faux-1");
|
||||
roster.push(pass);
|
||||
crate::common::write_config(dir, "mainAgent", serde_json::json!(roster))?;
|
||||
std::fs::write(
|
||||
disk.join("etc/sausage/roster/dream-pass.md"),
|
||||
include_str!("../../../config/roster/dream-pass.md")
|
||||
.replace("openai/gpt-6.1-sol", "faux/faux-1"),
|
||||
)?;
|
||||
let demo = disk.join("src/demo");
|
||||
std::fs::create_dir_all(&demo)?;
|
||||
std::fs::write(demo.join("README.md"), "P3 demo\n")?;
|
||||
|
||||
+13
-15
@@ -146,7 +146,7 @@ async fn provider_child() -> anyhow::Result<()> {
|
||||
};
|
||||
let dir = std::path::Path::new(&dir);
|
||||
let source = format!(
|
||||
"globalThis.providerOnly = true; const provider = (await Deno.core.ops.op_model_providers()).test; if (provider.base_url !== 'https://provider.invalid' || provider.api_key !== 'faux-private-token') throw new Error('Wrong provider config');\n{}",
|
||||
"globalThis.providerOnly = true; const configuredTestProvider = (await Deno.core.ops.op_model_providers()).test; if (configuredTestProvider.base_url !== 'https://provider.invalid' || configuredTestProvider.api_key !== 'faux-private-token') throw new Error('Wrong provider config');\n{}",
|
||||
include_str!("../../js/durable-test-bundle.js")
|
||||
);
|
||||
run_module(
|
||||
@@ -158,11 +158,15 @@ async fn provider_child() -> anyhow::Result<()> {
|
||||
let error = run_module(
|
||||
World::open(dir)?,
|
||||
sausage::process::exec(World::open(dir)?)?,
|
||||
"throw new Error((await Deno.core.ops.op_model_providers()).test.api_key)",
|
||||
r#"const changedProviderConfig = await Deno.core.ops.op_model_providers();
|
||||
changedProviderConfig.test.api_key = 'next-private-token';
|
||||
await Deno.core.ops.op_file('write', '/etc/sausage/config.yaml', [...new TextEncoder().encode(JSON.stringify({providers:changedProviderConfig}))], null);
|
||||
throw new Error(changedProviderConfig.test.api_key + ' faux-private-token')"#,
|
||||
)
|
||||
.await
|
||||
.unwrap_err();
|
||||
assert!(!error.to_string().contains("faux-private-token"));
|
||||
assert!(!error.to_string().contains("next-private-token"));
|
||||
assert!(error.to_string().contains("[redacted]"));
|
||||
Ok(())
|
||||
}
|
||||
@@ -172,16 +176,16 @@ fn provider_config_ignores_environment() -> anyhow::Result<()> {
|
||||
let dir = std::env::temp_dir().join(format!("sausage-durable-provider-{}", std::process::id()));
|
||||
let settings = dir.join("world/etc/sausage");
|
||||
std::fs::create_dir_all(&settings)?;
|
||||
std::fs::write(
|
||||
settings.join("config.yaml"),
|
||||
"providers:\n test:\n base_url: https://provider.invalid\n api_key: faux-private-token\n",
|
||||
)?;
|
||||
for start in 0..2 {
|
||||
std::fs::write(
|
||||
settings.join("config.yaml"),
|
||||
"providers:\n test:\n base_url: https://provider.invalid\n api_key: faux-private-token\n",
|
||||
)?;
|
||||
let status = std::process::Command::new(std::env::current_exe()?)
|
||||
.args(["--exact", "durable::provider_child", "--nocapture"])
|
||||
.env("DURABLE_PROVIDER_DIR", &dir)
|
||||
.env(
|
||||
"PI_PROVIDER_BASE_URL",
|
||||
"OPENAI_BASE_URL",
|
||||
if start == 0 {
|
||||
"https://provider.invalid"
|
||||
} else {
|
||||
@@ -189,7 +193,7 @@ fn provider_config_ignores_environment() -> anyhow::Result<()> {
|
||||
},
|
||||
)
|
||||
.env(
|
||||
"PI_PROVIDER_API_KEY",
|
||||
"OPENAI_API_KEY",
|
||||
if start == 0 {
|
||||
"faux-private-token"
|
||||
} else {
|
||||
@@ -200,13 +204,7 @@ fn provider_config_ignores_environment() -> anyhow::Result<()> {
|
||||
assert!(status.success());
|
||||
}
|
||||
let cred = Cred::open(&dir.join("host"))?;
|
||||
assert_eq!(
|
||||
cred.item_list()?
|
||||
.iter()
|
||||
.filter(|i| i.name == "llm-provider")
|
||||
.count(),
|
||||
0
|
||||
);
|
||||
assert!(cred.item_list()?.is_empty());
|
||||
for file in [
|
||||
"host/cred.sqlite",
|
||||
"host/cred.sqlite-wal",
|
||||
|
||||
Reference in New Issue
Block a user