@f-o-h/cli 0.1.9 → 0.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -6
- package/dist/foh.js +94 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ AI-operator provisioning CLI for Front Of House.
|
|
|
4
4
|
|
|
5
5
|
Public mirror: https://github.com/iiko38/front-of-house-cli
|
|
6
6
|
|
|
7
|
-
Current published baseline: `@f-o-h/cli@0.1.
|
|
7
|
+
Current published baseline: `@f-o-h/cli@0.1.10`
|
|
8
8
|
|
|
9
9
|
This mirror is a generated release artifact. The private product monorepo is not
|
|
10
10
|
published here, and no open-source license is granted unless stated separately.
|
|
@@ -85,11 +85,20 @@ The CLI defaults to the production API at `https://api.frontofhouse.okii.uk`.
|
|
|
85
85
|
|
|
86
86
|
## External-Agent Eval Capture
|
|
87
87
|
|
|
88
|
-
Use this when testing whether a clean coding agent can start from public docs
|
|
89
|
-
and the public npm package without private repo context:
|
|
90
|
-
|
|
91
|
-
```bash
|
|
92
|
-
foh eval external-agent
|
|
88
|
+
Use this when testing whether a clean coding agent can start from public docs
|
|
89
|
+
and the public npm package without private repo context:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
foh eval external-agent batch \
|
|
93
|
+
--models openai/codex,anthropic/claude,cursor/agent \
|
|
94
|
+
--prompt-version blank-setup.v1 \
|
|
95
|
+
--json
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Run each returned launch command in a clean agent terminal:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
foh eval external-agent run \
|
|
93
102
|
--model-provider openai \
|
|
94
103
|
--model-name codex \
|
|
95
104
|
--prompt-version blank-setup.v1
|
package/dist/foh.js
CHANGED
|
@@ -32640,7 +32640,7 @@ var StdioServerTransport = class {
|
|
|
32640
32640
|
};
|
|
32641
32641
|
|
|
32642
32642
|
// src/lib/cli-version.ts
|
|
32643
|
-
var CLI_VERSION = "0.1.
|
|
32643
|
+
var CLI_VERSION = "0.1.10";
|
|
32644
32644
|
|
|
32645
32645
|
// src/commands/mcp-serve.ts
|
|
32646
32646
|
var DEFAULT_TIMEOUT_MS = 12e4;
|
|
@@ -38309,6 +38309,7 @@ function readCommandRecords(runDir) {
|
|
|
38309
38309
|
|
|
38310
38310
|
// src/commands/eval.ts
|
|
38311
38311
|
var DEFAULT_PROMPT_VERSION = "blank-setup.v1";
|
|
38312
|
+
var DEFAULT_BATCH_MODELS = "openai/codex,anthropic/claude,cursor/agent";
|
|
38312
38313
|
var PROMPTS = {
|
|
38313
38314
|
"blank-setup.v1": "Go to https://frontofhouse.okii.uk. Use only public docs, public API docs, and the public npm CLI package. Install the FOH CLI, authenticate or reach a deterministic auth blocker, create or configure a Front Of House voice agent and website widget, run proof/smoke/certification where available, and produce a final evidence summary with commands run, docs used, artifacts created, and any blocker reason codes. Do not assume access to the private source repository.",
|
|
38314
38315
|
"debug-proof-failure.v1": "You are given a FOH proof or debug artifact. Use public docs and FOH CLI/API behavior to classify whether the blocker is docs, auth, org setup, agent config, widget, channel, runtime, or product bug. Produce a redacted improvement packet or the exact command needed to produce one. Do not ask the human to interpret logs manually unless no machine-readable artifact exists.",
|
|
@@ -38327,6 +38328,31 @@ function defaultRunDir(modelName, promptVersion) {
|
|
|
38327
38328
|
const safePrompt = String(promptVersion || DEFAULT_PROMPT_VERSION).toLowerCase().replace(/[^a-z0-9_.-]+/g, "-");
|
|
38328
38329
|
return (0, import_path11.resolve)("test-results", "external-agent-runs", date4, `${safeModel}-${safePrompt}-${stamp}`);
|
|
38329
38330
|
}
|
|
38331
|
+
function defaultBatchDir(promptVersion) {
|
|
38332
|
+
const date4 = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
38333
|
+
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").replace("T", "-").slice(0, 23);
|
|
38334
|
+
const safePrompt = String(promptVersion || DEFAULT_PROMPT_VERSION).toLowerCase().replace(/[^a-z0-9_.-]+/g, "-");
|
|
38335
|
+
return (0, import_path11.resolve)("test-results", "external-agent-runs", date4, `batch-${safePrompt}-${stamp}`);
|
|
38336
|
+
}
|
|
38337
|
+
function safeSlug(value) {
|
|
38338
|
+
return String(value || "unknown").toLowerCase().replace(/[^a-z0-9_.-]+/g, "-").replace(/^-+|-+$/g, "") || "unknown";
|
|
38339
|
+
}
|
|
38340
|
+
function quoteArg(value) {
|
|
38341
|
+
const text = String(value);
|
|
38342
|
+
if (/^[A-Za-z0-9_./:=@-]+$/.test(text)) return text;
|
|
38343
|
+
return `"${text.replace(/(["$`])/g, "\\$1")}"`;
|
|
38344
|
+
}
|
|
38345
|
+
function parseModelSpec(raw) {
|
|
38346
|
+
const [provider, ...nameParts] = String(raw || "").split("/");
|
|
38347
|
+
const name = nameParts.join("/");
|
|
38348
|
+
return {
|
|
38349
|
+
provider: provider?.trim() || "unknown",
|
|
38350
|
+
name: name.trim() || "unknown-model"
|
|
38351
|
+
};
|
|
38352
|
+
}
|
|
38353
|
+
function parseModelList(raw) {
|
|
38354
|
+
return String(raw || DEFAULT_BATCH_MODELS).split(",").map((entry) => entry.trim()).filter(Boolean).map(parseModelSpec);
|
|
38355
|
+
}
|
|
38330
38356
|
function inferShell(raw) {
|
|
38331
38357
|
if (raw && raw.trim()) return { command: raw, args: [], label: raw };
|
|
38332
38358
|
if (process.platform === "win32") return { command: "powershell.exe", args: ["-NoLogo", "-NoProfile"], label: "powershell" };
|
|
@@ -38400,6 +38426,73 @@ function buildRunArtifact(input) {
|
|
|
38400
38426
|
function registerEval(program3) {
|
|
38401
38427
|
const evalCommand = program3.command("eval").description("Run or summarize external-agent evaluation workflows");
|
|
38402
38428
|
const external = evalCommand.command("external-agent").description("Capture clean external coding-agent setup attempts");
|
|
38429
|
+
external.command("batch").description("Create a deterministic multi-model external-agent batch plan").option("--models <list>", "Comma-separated provider/model list", DEFAULT_BATCH_MODELS).option("--prompt-version <version>", "Prompt version", DEFAULT_PROMPT_VERSION).option("--workspace-type <type>", "Workspace type label", "clean-no-repo").option("--agent-shell <name>", "Agent shell label", "vscode-terminal").option("--out-dir <path>", "Batch output directory").option("--json", "Output as JSON").action(async (opts) => {
|
|
38430
|
+
const promptVersion = String(opts.promptVersion || DEFAULT_PROMPT_VERSION);
|
|
38431
|
+
const batchDir = (0, import_path11.resolve)(String(opts.outDir || defaultBatchDir(promptVersion)));
|
|
38432
|
+
const models = parseModelList(String(opts.models || DEFAULT_BATCH_MODELS));
|
|
38433
|
+
(0, import_fs13.mkdirSync)(batchDir, { recursive: true });
|
|
38434
|
+
const runs = models.map((model, index) => {
|
|
38435
|
+
const runId = `${String(index + 1).padStart(2, "0")}-${safeSlug(model.provider)}-${safeSlug(model.name)}`;
|
|
38436
|
+
const runDir = (0, import_path11.join)(batchDir, runId);
|
|
38437
|
+
(0, import_fs13.mkdirSync)(runDir, { recursive: true });
|
|
38438
|
+
const promptPath = writePrompt(runDir, promptVersion);
|
|
38439
|
+
const commandArgs = [
|
|
38440
|
+
"eval",
|
|
38441
|
+
"external-agent",
|
|
38442
|
+
"run",
|
|
38443
|
+
"--model-provider",
|
|
38444
|
+
model.provider,
|
|
38445
|
+
"--model-name",
|
|
38446
|
+
model.name,
|
|
38447
|
+
"--prompt-version",
|
|
38448
|
+
promptVersion,
|
|
38449
|
+
"--workspace-type",
|
|
38450
|
+
String(opts.workspaceType || "clean-no-repo"),
|
|
38451
|
+
"--agent-shell",
|
|
38452
|
+
String(opts.agentShell || "vscode-terminal"),
|
|
38453
|
+
"--out-dir",
|
|
38454
|
+
runDir
|
|
38455
|
+
];
|
|
38456
|
+
return {
|
|
38457
|
+
run_id: runId,
|
|
38458
|
+
model_provider: model.provider,
|
|
38459
|
+
model_name: model.name,
|
|
38460
|
+
prompt_version: promptVersion,
|
|
38461
|
+
run_dir: runDir,
|
|
38462
|
+
prompt_path: promptPath,
|
|
38463
|
+
launch_args: commandArgs,
|
|
38464
|
+
launch_command: `npx --yes @f-o-h/cli@latest ${commandArgs.map(quoteArg).join(" ")}`
|
|
38465
|
+
};
|
|
38466
|
+
});
|
|
38467
|
+
const batch = {
|
|
38468
|
+
schema_version: "external_agent_batch_plan.v1",
|
|
38469
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
38470
|
+
batch_dir: batchDir,
|
|
38471
|
+
prompt_version: promptVersion,
|
|
38472
|
+
workspace_type: String(opts.workspaceType || "clean-no-repo"),
|
|
38473
|
+
agent_shell: String(opts.agentShell || "vscode-terminal"),
|
|
38474
|
+
run_count: runs.length,
|
|
38475
|
+
runs,
|
|
38476
|
+
summary_command: `corepack pnpm eval:external-agent:runs:summary -- --root ${batchDir}`
|
|
38477
|
+
};
|
|
38478
|
+
const batchPath = (0, import_path11.join)(batchDir, "batch.json");
|
|
38479
|
+
(0, import_fs13.writeFileSync)(batchPath, `${JSON.stringify(batch, null, 2)}
|
|
38480
|
+
`, "utf8");
|
|
38481
|
+
format(cliEnvelope({
|
|
38482
|
+
schemaVersion: "external_agent_batch_plan_result.v1",
|
|
38483
|
+
status: "exported",
|
|
38484
|
+
reasonCode: "external_agent_batch_plan_created",
|
|
38485
|
+
summary: `External-agent batch plan created for ${runs.length} model(s).`,
|
|
38486
|
+
artifacts: {
|
|
38487
|
+
batch: batchPath
|
|
38488
|
+
},
|
|
38489
|
+
nextCommands: [
|
|
38490
|
+
...runs.map((run) => run.launch_command),
|
|
38491
|
+
batch.summary_command
|
|
38492
|
+
],
|
|
38493
|
+
extra: { batch }
|
|
38494
|
+
}), { json: Boolean(opts.json) });
|
|
38495
|
+
});
|
|
38403
38496
|
external.command("run").description("Launch an instrumented shell and emit external_agent_run.v1 when it exits").option("--model-provider <name>", "Model provider label", "unknown").option("--model-name <name>", "Model name label", "unknown-model").option("--prompt-version <version>", "Prompt version", DEFAULT_PROMPT_VERSION).option("--workspace-type <type>", "Workspace type label", "clean-no-repo").option("--agent-shell <name>", "Agent shell label", "vscode-terminal").option("--out-dir <path>", "Run output directory").option("--status <status>", "Final status when not interactively classified: pass|hold|fail", "hold").option("--reason-code <code>", "Failure/hold reason code", "external_agent_run_needs_review").option("--shell <command>", "Shell command to launch for capture").option("--no-shell", "Do not launch a shell; create/finalize artifacts immediately").option("--json", "Output as JSON").action(async (opts) => {
|
|
38404
38497
|
const status = normalizeStatus(opts.status);
|
|
38405
38498
|
const promptVersion = String(opts.promptVersion || DEFAULT_PROMPT_VERSION);
|