@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.
Files changed (3) hide show
  1. package/README.md +15 -6
  2. package/dist/foh.js +94 -1
  3. 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.9`
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 run \
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.9";
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);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@f-o-h/cli",
3
- "version": "0.1.9",
3
+ "version": "0.1.10",
4
4
  "description": "FOH CLI - AI-operator provisioning tool for Front Of House",
5
5
  "license": "UNLICENSED",
6
6
  "bin": {