@f-o-h/cli 0.1.45 → 0.1.47
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 +38 -38
- package/dist/foh.js +82 -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.47`
|
|
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.
|
|
@@ -61,7 +61,7 @@ foh auth login --web --json
|
|
|
61
61
|
foh auth login --email "$FOH_EMAIL" --password "$FOH_PASSWORD" --json
|
|
62
62
|
foh org list --json
|
|
63
63
|
foh org use --org <org-id> --json
|
|
64
|
-
FOH_CLI_SPEND_POLICY=no_spend foh setup --org <org-id> --agent-template <template-id> --agent-name "Demo Agent" --phone-mode observe --json
|
|
64
|
+
FOH_CLI_SPEND_POLICY=no_spend foh setup --org <org-id> --agent-template <template-id> --agent-name "Demo Agent" --phone-mode observe --json
|
|
65
65
|
foh prove --agent <agent-id> --json --out foh-proof.json
|
|
66
66
|
foh test run --suite ./suite.yml --agent <agent-id> --json --out foh-test-report.json
|
|
67
67
|
foh agent replay --file ./transcript-export.json --json
|
|
@@ -80,35 +80,35 @@ prints the fallback URL. `auth login --web` starts browser device
|
|
|
80
80
|
authorization, opens `/cli-auth`, waits for console approval, and stores the
|
|
81
81
|
returned short-lived token. Credential auth remains available as fallback.
|
|
82
82
|
|
|
83
|
-
`foh prove` produces a compact signed proof report across auth, org context,
|
|
84
|
-
agent validation, contact phone readiness, voice provider health, widget
|
|
85
|
-
channel/embed readiness, widget smoke, and simulation certification. It is
|
|
86
|
-
read-only by default; pass `--mutation-mode ensure` or `--repair` only when you
|
|
87
|
-
explicitly want proof to ensure missing widget state. Use `--strict` in
|
|
88
|
-
automation when holds should fail the command, and `--mission voice` or
|
|
89
|
-
`--require-phone` when a voice/contact number is mandatory for the demo.
|
|
90
|
-
Use `--contact-path byon` when the proof is meant to validate a
|
|
91
|
-
customer-owned/BYON phone route; missing BYON config then reports
|
|
92
|
-
`byon_voice_number_not_configured` instead of suggesting FOH number purchase.
|
|
93
|
-
For repeated or parallel proof missions in AI-agent evals, pass
|
|
94
|
-
`--proof-cache-dir .foh/proof-cache` so simulation certification runs once and
|
|
95
|
-
sibling proofs reuse the same signed certification detail.
|
|
96
|
-
|
|
97
|
-
For mass AI-agent evals and repeated demo rehearsals, keep setup on the free
|
|
98
|
-
scaffold lane:
|
|
99
|
-
|
|
100
|
-
```bash
|
|
101
|
-
FOH_CLI_SPEND_POLICY=no_spend foh setup --org <org-id> --agent-template <template-id> --agent-name "Demo Agent" --phone-mode observe --json
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
`--phone-mode observe` checks whether a contact phone already exists without
|
|
105
|
-
buying one. `--phone-mode skip` bypasses the phone step. `--phone-mode purchase`
|
|
106
|
-
is the explicit paid contact path and is fail-closed when
|
|
107
|
-
`FOH_CLI_SPEND_POLICY=no_spend` is set.
|
|
108
|
-
|
|
109
|
-
If managed-number provisioning is blocked by account/provider capacity or empty
|
|
110
|
-
reserve inventory, proof reports `provider_capacity_blocked`; fix capacity or
|
|
111
|
-
switch to BYON rather than retrying blindly.
|
|
83
|
+
`foh prove` produces a compact signed proof report across auth, org context,
|
|
84
|
+
agent validation, contact phone readiness, voice provider health, widget
|
|
85
|
+
channel/embed readiness, widget smoke, and simulation certification. It is
|
|
86
|
+
read-only by default; pass `--mutation-mode ensure` or `--repair` only when you
|
|
87
|
+
explicitly want proof to ensure missing widget state. Use `--strict` in
|
|
88
|
+
automation when holds should fail the command, and `--mission voice` or
|
|
89
|
+
`--require-phone` when a voice/contact number is mandatory for the demo.
|
|
90
|
+
Use `--contact-path byon` when the proof is meant to validate a
|
|
91
|
+
customer-owned/BYON phone route; missing BYON config then reports
|
|
92
|
+
`byon_voice_number_not_configured` instead of suggesting FOH number purchase.
|
|
93
|
+
For repeated or parallel proof missions in AI-agent evals, pass
|
|
94
|
+
`--proof-cache-dir .foh/proof-cache` so simulation certification runs once and
|
|
95
|
+
sibling proofs reuse the same signed certification detail.
|
|
96
|
+
|
|
97
|
+
For mass AI-agent evals and repeated demo rehearsals, keep setup on the free
|
|
98
|
+
scaffold lane:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
FOH_CLI_SPEND_POLICY=no_spend foh setup --org <org-id> --agent-template <template-id> --agent-name "Demo Agent" --phone-mode observe --json
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
`--phone-mode observe` checks whether a contact phone already exists without
|
|
105
|
+
buying one. `--phone-mode skip` bypasses the phone step. `--phone-mode purchase`
|
|
106
|
+
is the explicit paid contact path and is fail-closed when
|
|
107
|
+
`FOH_CLI_SPEND_POLICY=no_spend` is set.
|
|
108
|
+
|
|
109
|
+
If managed-number provisioning is blocked by account/provider capacity or empty
|
|
110
|
+
reserve inventory, proof reports `provider_capacity_blocked`; fix capacity or
|
|
111
|
+
switch to BYON rather than retrying blindly.
|
|
112
112
|
|
|
113
113
|
The CLI defaults to the production API at `https://api.frontofhouse.okii.uk`.
|
|
114
114
|
|
|
@@ -133,13 +133,13 @@ foh eval external-agent run \
|
|
|
133
133
|
--prompt-version blank-setup.v1
|
|
134
134
|
```
|
|
135
135
|
|
|
136
|
-
The command writes a versioned prompt, launches an instrumented shell, captures
|
|
137
|
-
FOH CLI commands into `commands.ndjson`, and finalizes `run.json` as an
|
|
138
|
-
`external_agent_run.v1` artifact when the shell exits.
|
|
139
|
-
|
|
140
|
-
Run artifacts include `eval_state` so repeated benchmark runs make reuse
|
|
141
|
-
explicit: org, agent, and widget reuse are expected; fresh paid phone-number
|
|
142
|
-
creation is not expected.
|
|
136
|
+
The command writes a versioned prompt, launches an instrumented shell, captures
|
|
137
|
+
FOH CLI commands into `commands.ndjson`, and finalizes `run.json` as an
|
|
138
|
+
`external_agent_run.v1` artifact when the shell exits.
|
|
139
|
+
|
|
140
|
+
Run artifacts include `eval_state` so repeated benchmark runs make reuse
|
|
141
|
+
explicit: org, agent, and widget reuse are expected; fresh paid phone-number
|
|
142
|
+
creation is not expected.
|
|
143
143
|
|
|
144
144
|
For guarded programmable-runner planning:
|
|
145
145
|
|
package/dist/foh.js
CHANGED
|
@@ -32801,7 +32801,7 @@ var StdioServerTransport = class {
|
|
|
32801
32801
|
};
|
|
32802
32802
|
|
|
32803
32803
|
// src/lib/cli-version.ts
|
|
32804
|
-
var CLI_VERSION = "0.1.
|
|
32804
|
+
var CLI_VERSION = "0.1.47";
|
|
32805
32805
|
|
|
32806
32806
|
// src/commands/mcp-serve.ts
|
|
32807
32807
|
var DEFAULT_TIMEOUT_MS = 12e4;
|
|
@@ -39181,6 +39181,7 @@ var EXTERNAL_AGENT_EVAL_AUTH_ENV_MAP = {
|
|
|
39181
39181
|
FOH_EXTERNAL_AGENT_EVAL_API_URL: "FOH_API_URL",
|
|
39182
39182
|
FOH_EXTERNAL_AGENT_EVAL_TOKEN_EXPIRES_AT: "FOH_TOKEN_EXPIRES_AT"
|
|
39183
39183
|
};
|
|
39184
|
+
var DEFAULT_FOH_API_URL2 = "https://api.frontofhouse.okii.uk";
|
|
39184
39185
|
var ExternalAgentExecutorError = class extends Error {
|
|
39185
39186
|
reasonCode;
|
|
39186
39187
|
constructor(reasonCode, message) {
|
|
@@ -39219,6 +39220,61 @@ function buildCodexExecutorEnv(input) {
|
|
|
39219
39220
|
env.FOH_CLI_SUPPRESS_BANNER = "1";
|
|
39220
39221
|
return env;
|
|
39221
39222
|
}
|
|
39223
|
+
function readExternalAgentEvalAuthEnv(env = process.env) {
|
|
39224
|
+
return {
|
|
39225
|
+
token: String(env.FOH_EXTERNAL_AGENT_EVAL_TOKEN || "").trim(),
|
|
39226
|
+
orgId: String(env.FOH_EXTERNAL_AGENT_EVAL_ORG_ID || "").trim(),
|
|
39227
|
+
apiUrl: String(env.FOH_EXTERNAL_AGENT_EVAL_API_URL || env.FOH_API_URL || DEFAULT_FOH_API_URL2).trim() || DEFAULT_FOH_API_URL2,
|
|
39228
|
+
expiresAt: String(env.FOH_EXTERNAL_AGENT_EVAL_TOKEN_EXPIRES_AT || "").trim()
|
|
39229
|
+
};
|
|
39230
|
+
}
|
|
39231
|
+
function shouldRunExternalAgentEvalAuthPreflight(env = process.env) {
|
|
39232
|
+
return Boolean(
|
|
39233
|
+
env.FOH_EXTERNAL_AGENT_EVAL_TOKEN || env.FOH_EXTERNAL_AGENT_EVAL_ORG_ID || env.FOH_EXTERNAL_AGENT_EVAL_API_URL || env.FOH_EXTERNAL_AGENT_EVAL_TOKEN_EXPIRES_AT || env.FOH_SERVICE_TOKEN || env.FOH_ORG_ID || env.FOH_API_URL || env.FOH_TOKEN_EXPIRES_AT
|
|
39234
|
+
);
|
|
39235
|
+
}
|
|
39236
|
+
async function runExternalAgentEvalAuthPreflight(env = process.env) {
|
|
39237
|
+
if (!shouldRunExternalAgentEvalAuthPreflight(env)) return null;
|
|
39238
|
+
const checkedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
39239
|
+
const auth = readExternalAgentEvalAuthEnv(env);
|
|
39240
|
+
const base = {
|
|
39241
|
+
api_url: auth.apiUrl,
|
|
39242
|
+
org_id: auth.orgId || null,
|
|
39243
|
+
checked_at: checkedAt,
|
|
39244
|
+
token_present: Boolean(auth.token),
|
|
39245
|
+
expires_at: auth.expiresAt || null,
|
|
39246
|
+
matched_org: null
|
|
39247
|
+
};
|
|
39248
|
+
if (!auth.token || !auth.orgId) {
|
|
39249
|
+
return { ...base, ok: false, reason_code: "eval_auth_missing" };
|
|
39250
|
+
}
|
|
39251
|
+
if (auth.expiresAt) {
|
|
39252
|
+
const expiresMs = Date.parse(auth.expiresAt);
|
|
39253
|
+
if (Number.isFinite(expiresMs) && expiresMs <= Date.now()) {
|
|
39254
|
+
return { ...base, ok: false, reason_code: "eval_auth_expired" };
|
|
39255
|
+
}
|
|
39256
|
+
}
|
|
39257
|
+
const res = await fetch(`${auth.apiUrl.replace(/\/$/, "")}/v1/console/auth/my-orgs`, {
|
|
39258
|
+
headers: {
|
|
39259
|
+
Authorization: `Bearer ${auth.token}`
|
|
39260
|
+
}
|
|
39261
|
+
}).catch(() => null);
|
|
39262
|
+
if (!res || res.status === 401) {
|
|
39263
|
+
return { ...base, ok: false, reason_code: "eval_auth_expired" };
|
|
39264
|
+
}
|
|
39265
|
+
if (!res.ok) {
|
|
39266
|
+
return { ...base, ok: false, reason_code: "eval_auth_wrong_org" };
|
|
39267
|
+
}
|
|
39268
|
+
const body = await res.json().catch(() => ({}));
|
|
39269
|
+
const orgs = Array.isArray(body.orgs) ? body.orgs : [];
|
|
39270
|
+
const matchedOrg = orgs.some((org) => String(org?.org_id || "").trim() === auth.orgId);
|
|
39271
|
+
return {
|
|
39272
|
+
...base,
|
|
39273
|
+
ok: matchedOrg,
|
|
39274
|
+
reason_code: matchedOrg ? "eval_auth_ok" : "eval_auth_wrong_org",
|
|
39275
|
+
matched_org: matchedOrg
|
|
39276
|
+
};
|
|
39277
|
+
}
|
|
39222
39278
|
function normalizeForCompare(path2) {
|
|
39223
39279
|
const resolved = (0, import_path13.resolve)(path2);
|
|
39224
39280
|
return process.platform === "win32" ? resolved.toLowerCase() : resolved;
|
|
@@ -39823,6 +39879,30 @@ async function executeExternalAgentExecutorPlan(plan, options = {}) {
|
|
|
39823
39879
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
39824
39880
|
const results = [];
|
|
39825
39881
|
const runnerCommand = options.runnerCommand || resolveCodexExecutionCommand();
|
|
39882
|
+
const authPreflight = await runExternalAgentEvalAuthPreflight(options.env);
|
|
39883
|
+
if (authPreflight && !authPreflight.ok) {
|
|
39884
|
+
const endedAt2 = (/* @__PURE__ */ new Date()).toISOString();
|
|
39885
|
+
return {
|
|
39886
|
+
schema_version: "external_agent_execution_batch_result.v1",
|
|
39887
|
+
ok: false,
|
|
39888
|
+
status: "hold",
|
|
39889
|
+
reason_code: authPreflight.reason_code,
|
|
39890
|
+
auth_preflight: authPreflight,
|
|
39891
|
+
started_at: startedAt,
|
|
39892
|
+
ended_at: endedAt2,
|
|
39893
|
+
runner: plan.runner,
|
|
39894
|
+
run_count: plan.runs.length,
|
|
39895
|
+
results: plan.runs.map((run) => ({
|
|
39896
|
+
run_id: run.run_id,
|
|
39897
|
+
status: "hold",
|
|
39898
|
+
failure_reason_code: authPreflight.reason_code,
|
|
39899
|
+
exit_code: null,
|
|
39900
|
+
timed_out: false,
|
|
39901
|
+
duration_ms: 0,
|
|
39902
|
+
artifacts: run.outputs
|
|
39903
|
+
}))
|
|
39904
|
+
};
|
|
39905
|
+
}
|
|
39826
39906
|
for (const run of plan.runs) {
|
|
39827
39907
|
const runStartedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
39828
39908
|
const commandCaptureDir = (0, import_path13.join)(run.workspace_dir, ".foh-capture");
|
|
@@ -39890,6 +39970,7 @@ async function executeExternalAgentExecutorPlan(plan, options = {}) {
|
|
|
39890
39970
|
ok: status === "pass",
|
|
39891
39971
|
status,
|
|
39892
39972
|
reason_code: status === "pass" ? "external_agent_execution_passed" : "external_agent_execution_needs_review",
|
|
39973
|
+
...authPreflight ? { auth_preflight: authPreflight } : {},
|
|
39893
39974
|
started_at: startedAt,
|
|
39894
39975
|
ended_at: endedAt,
|
|
39895
39976
|
runner: plan.runner,
|