@f-o-h/cli 0.1.34 → 0.1.35
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 +21 -9
- package/dist/foh.js +161 -5
- 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
|
|
7
|
+
Current candidate baseline: `@f-o-h/cli@0.1.35`
|
|
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 setup --org <org-id> --agent-template <template-id> --agent-name "Demo Agent" --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,13 +80,25 @@ 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.
|
|
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
|
+
|
|
91
|
+
For mass AI-agent evals and repeated demo rehearsals, keep setup on the free
|
|
92
|
+
scaffold lane:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
FOH_CLI_SPEND_POLICY=no_spend foh setup --org <org-id> --agent-template <template-id> --agent-name "Demo Agent" --phone-mode observe --json
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
`--phone-mode observe` checks whether a contact phone already exists without
|
|
99
|
+
buying one. `--phone-mode skip` bypasses the phone step. `--phone-mode purchase`
|
|
100
|
+
is the explicit paid contact path and is fail-closed when
|
|
101
|
+
`FOH_CLI_SPEND_POLICY=no_spend` is set.
|
|
90
102
|
|
|
91
103
|
The CLI defaults to the production API at `https://api.frontofhouse.okii.uk`.
|
|
92
104
|
|
package/dist/foh.js
CHANGED
|
@@ -11055,6 +11055,47 @@ function registerCompliance(program3) {
|
|
|
11055
11055
|
|
|
11056
11056
|
// src/commands/provision.ts
|
|
11057
11057
|
var import_crypto = require("crypto");
|
|
11058
|
+
|
|
11059
|
+
// src/lib/spend-policy.ts
|
|
11060
|
+
var FOH_CLI_SPEND_POLICY_ENV = "FOH_CLI_SPEND_POLICY";
|
|
11061
|
+
var NO_SPEND_POLICY = "no_spend";
|
|
11062
|
+
var PAID_RESOURCE_BLOCKED_REASON_CODE = "paid_resource_blocked_by_spend_policy";
|
|
11063
|
+
function resolveCliSpendPolicy(env = process.env) {
|
|
11064
|
+
const value = String(env[FOH_CLI_SPEND_POLICY_ENV] || "").trim().toLowerCase();
|
|
11065
|
+
return value === NO_SPEND_POLICY ? NO_SPEND_POLICY : "default";
|
|
11066
|
+
}
|
|
11067
|
+
function isNoSpendPolicy(env = process.env) {
|
|
11068
|
+
return resolveCliSpendPolicy(env) === NO_SPEND_POLICY;
|
|
11069
|
+
}
|
|
11070
|
+
function buildPaidResourceBlockedEnvelope(input) {
|
|
11071
|
+
return cliEnvelope({
|
|
11072
|
+
status: "blocked",
|
|
11073
|
+
reasonCode: PAID_RESOURCE_BLOCKED_REASON_CODE,
|
|
11074
|
+
summary: "Paid or scarce resource mutation blocked by the active no-spend CLI policy.",
|
|
11075
|
+
ids: { org_id: input.orgId ?? null },
|
|
11076
|
+
checks: [
|
|
11077
|
+
{
|
|
11078
|
+
name: "spend_policy",
|
|
11079
|
+
status: "blocked",
|
|
11080
|
+
reason_code: PAID_RESOURCE_BLOCKED_REASON_CODE,
|
|
11081
|
+
spend_policy: NO_SPEND_POLICY,
|
|
11082
|
+
spend_class: "paid_foh",
|
|
11083
|
+
resource: input.resource
|
|
11084
|
+
}
|
|
11085
|
+
],
|
|
11086
|
+
nextCommands: input.nextCommands,
|
|
11087
|
+
extra: {
|
|
11088
|
+
spend_policy: NO_SPEND_POLICY,
|
|
11089
|
+
spend_class: "paid_foh",
|
|
11090
|
+
safe_to_retry: false,
|
|
11091
|
+
resource: input.resource,
|
|
11092
|
+
command: input.command,
|
|
11093
|
+
operator_note: "No-spend eval mode allows setup and proof work, but blocks FOH-owned phone-number purchasing. Use an existing/BYON phone path or rerun outside no-spend eval mode with explicit operator approval."
|
|
11094
|
+
}
|
|
11095
|
+
});
|
|
11096
|
+
}
|
|
11097
|
+
|
|
11098
|
+
// src/commands/provision.ts
|
|
11058
11099
|
function requiredOrg2(opts, step) {
|
|
11059
11100
|
return resolveRequiredOrgId(opts.org, {
|
|
11060
11101
|
apiUrl: opts.apiUrl,
|
|
@@ -11089,6 +11130,22 @@ function registerProvision(program3) {
|
|
|
11089
11130
|
format({ status: "skipped", reason: "already_provisioned", phone_number: onboarding.phone_number }, { json: opts.json ?? false });
|
|
11090
11131
|
return;
|
|
11091
11132
|
}
|
|
11133
|
+
if (isNoSpendPolicy()) {
|
|
11134
|
+
format(
|
|
11135
|
+
buildPaidResourceBlockedEnvelope({
|
|
11136
|
+
resource: "foh_twilio_phone_number",
|
|
11137
|
+
command: "foh provision buy",
|
|
11138
|
+
orgId: resolvedOrg,
|
|
11139
|
+
nextCommands: [
|
|
11140
|
+
`foh provision status --org ${resolvedOrg} --json`,
|
|
11141
|
+
`foh prove --mission voice --require-phone --org ${resolvedOrg} --json`
|
|
11142
|
+
]
|
|
11143
|
+
}),
|
|
11144
|
+
{ json: opts.json ?? false }
|
|
11145
|
+
);
|
|
11146
|
+
markCommandFailed(1);
|
|
11147
|
+
return;
|
|
11148
|
+
}
|
|
11092
11149
|
const data = await apiFetch("/v1/console/org/twilio/provision", {
|
|
11093
11150
|
method: "POST",
|
|
11094
11151
|
body: JSON.stringify({ country: opts.country, area_code: opts.areaCode }),
|
|
@@ -32698,7 +32755,7 @@ var StdioServerTransport = class {
|
|
|
32698
32755
|
};
|
|
32699
32756
|
|
|
32700
32757
|
// src/lib/cli-version.ts
|
|
32701
|
-
var CLI_VERSION = "0.1.
|
|
32758
|
+
var CLI_VERSION = "0.1.35";
|
|
32702
32759
|
|
|
32703
32760
|
// src/commands/mcp-serve.ts
|
|
32704
32761
|
var DEFAULT_TIMEOUT_MS = 12e4;
|
|
@@ -34331,6 +34388,16 @@ function timedStepResult(result, startedAtIso, startedAtMs) {
|
|
|
34331
34388
|
function optionNameToFlag(key) {
|
|
34332
34389
|
return "--" + key.replace(/([A-Z])/g, "-$1").toLowerCase();
|
|
34333
34390
|
}
|
|
34391
|
+
function normalizeSetupPhoneMode(raw) {
|
|
34392
|
+
const value = String(raw || "purchase").trim().toLowerCase();
|
|
34393
|
+
if (value === "observe" || value === "skip" || value === "purchase") return value;
|
|
34394
|
+
throw new FohError({
|
|
34395
|
+
step: "setup.phone_mode",
|
|
34396
|
+
error: `Invalid --phone-mode "${String(raw)}"`,
|
|
34397
|
+
remediation: "Use one of: observe, skip, purchase.",
|
|
34398
|
+
reasonCode: "setup_invalid_phone_mode"
|
|
34399
|
+
});
|
|
34400
|
+
}
|
|
34334
34401
|
function buildMissingOptionsPlan(missing, opts) {
|
|
34335
34402
|
const missingFlags = missing.map(optionNameToFlag);
|
|
34336
34403
|
const signInUrl = buildConsoleSignInUrl(resolveConsoleBaseUrl(opts.consoleUrl));
|
|
@@ -34381,7 +34448,7 @@ function emitMissingOptionsPlan(missing, opts) {
|
|
|
34381
34448
|
}
|
|
34382
34449
|
}
|
|
34383
34450
|
function registerSetup(program3) {
|
|
34384
|
-
program3.command("setup").description("Fully provision a new agency customer in one command").option("--org <id>", "Org ID (default: stored org from foh org use)").option("--agent-template <id>", "Agent template ID (e.g. viewing-request)").option("--agent-name <name>", "Name for the new agent").option("--phone-country <cc>", "Phone number country code", "GB").option("--phone-area-code <code>", "Phone area code preference").option("--widget-domains <domains>", "Comma-separated widget domain allowlist").option("--voice-provider <p>", "TTS provider: openai, azure, twilio").option("--voice-id <id>", "Voice ID").option("--skip-compliance", "Skip compliance submission and wait").option("--skip-voice", "Skip voice configuration").option("--skip-tests", "Skip smoke tests").option("--cert-mode <m>", "Simulation cert mode: quick, full, stress", "quick").option("--cert-adaptive-runs <n>", "Adaptive run count for certification loop", "30").option("--cert-max-improvement-rounds <n>", "Max instruction improvement rounds in cert loop (0-5)", "1").option("--resume-from <step>", `Resume from a setup step (${SETUP_STEP_ORDER.join(", ")})`).option("--report-out <path>", "Optional path to write signed setup run report JSON").option("--dry-run", "Print all steps that would run without making any API calls").option("--api-url <url>", "API base URL override").option("--console-url <url>", "Console sign-in URL override").option("--json", "Output as JSON").action(async (opts) => {
|
|
34451
|
+
program3.command("setup").description("Fully provision a new agency customer in one command").option("--org <id>", "Org ID (default: stored org from foh org use)").option("--agent-template <id>", "Agent template ID (e.g. viewing-request)").option("--agent-name <name>", "Name for the new agent").option("--phone-country <cc>", "Phone number country code", "GB").option("--phone-area-code <code>", "Phone area code preference").option("--phone-mode <mode>", "Phone path: observe, skip, or purchase", "purchase").option("--widget-domains <domains>", "Comma-separated widget domain allowlist").option("--voice-provider <p>", "TTS provider: openai, azure, twilio").option("--voice-id <id>", "Voice ID").option("--skip-compliance", "Skip compliance submission and wait").option("--skip-voice", "Skip voice configuration").option("--skip-tests", "Skip smoke tests").option("--cert-mode <m>", "Simulation cert mode: quick, full, stress", "quick").option("--cert-adaptive-runs <n>", "Adaptive run count for certification loop", "30").option("--cert-max-improvement-rounds <n>", "Max instruction improvement rounds in cert loop (0-5)", "1").option("--resume-from <step>", `Resume from a setup step (${SETUP_STEP_ORDER.join(", ")})`).option("--report-out <path>", "Optional path to write signed setup run report JSON").option("--dry-run", "Print all steps that would run without making any API calls").option("--api-url <url>", "API base URL override").option("--console-url <url>", "Console sign-in URL override").option("--json", "Output as JSON").action(async (opts) => {
|
|
34385
34452
|
if (!opts.org) {
|
|
34386
34453
|
try {
|
|
34387
34454
|
opts.org = loadCredentials(opts.apiUrl).orgId;
|
|
@@ -34425,6 +34492,17 @@ function registerSetup(program3) {
|
|
|
34425
34492
|
}
|
|
34426
34493
|
const certAdaptiveRuns = Math.max(1, Math.min(120, Number(opts.certAdaptiveRuns ?? 30) || 30));
|
|
34427
34494
|
const certMaxImprovementRounds = Math.max(0, Math.min(5, Number(opts.certMaxImprovementRounds ?? 1) || 1));
|
|
34495
|
+
let phoneMode;
|
|
34496
|
+
try {
|
|
34497
|
+
phoneMode = normalizeSetupPhoneMode(opts.phoneMode);
|
|
34498
|
+
} catch (error2) {
|
|
34499
|
+
if (error2 instanceof FohError) {
|
|
34500
|
+
formatError(error2);
|
|
34501
|
+
markCommandFailed(1);
|
|
34502
|
+
return;
|
|
34503
|
+
}
|
|
34504
|
+
throw error2;
|
|
34505
|
+
}
|
|
34428
34506
|
const emitSetupReport = (status, failure) => {
|
|
34429
34507
|
const reportPayload = {
|
|
34430
34508
|
schema_version: "foh_cli_setup_run.v1",
|
|
@@ -34435,6 +34513,8 @@ function registerSetup(program3) {
|
|
|
34435
34513
|
completed_at: nowIso(),
|
|
34436
34514
|
dry_run: Boolean(opts.dryRun),
|
|
34437
34515
|
resume_from: resumeState.resumeFrom,
|
|
34516
|
+
phone_mode: phoneMode,
|
|
34517
|
+
spend_policy: resolveCliSpendPolicy(),
|
|
34438
34518
|
org_id: opts.org,
|
|
34439
34519
|
agent_template: opts.agentTemplate,
|
|
34440
34520
|
agent_name: opts.agentName,
|
|
@@ -34591,6 +34671,20 @@ function registerSetup(program3) {
|
|
|
34591
34671
|
return { step: "wait_compliance", status: "done" };
|
|
34592
34672
|
});
|
|
34593
34673
|
await step("provision_phone", "Buy a Twilio phone number", async () => {
|
|
34674
|
+
if (phoneMode === "skip") {
|
|
34675
|
+
return {
|
|
34676
|
+
step: "provision_phone",
|
|
34677
|
+
status: "skipped",
|
|
34678
|
+
detail: {
|
|
34679
|
+
reason_code: "phone_mode_skip",
|
|
34680
|
+
phone_mode: phoneMode,
|
|
34681
|
+
spend_policy: resolveCliSpendPolicy(),
|
|
34682
|
+
spend_class: "free",
|
|
34683
|
+
safe_to_retry: true,
|
|
34684
|
+
operator_note: "Phone provisioning was skipped by explicit setup phone mode."
|
|
34685
|
+
}
|
|
34686
|
+
};
|
|
34687
|
+
}
|
|
34594
34688
|
const onboarding = await apiFetch(`/v1/console/org/${opts.org}/onboarding`, {
|
|
34595
34689
|
orgId: opts.org,
|
|
34596
34690
|
apiUrlOverride: opts.apiUrl
|
|
@@ -34599,6 +34693,42 @@ function registerSetup(program3) {
|
|
|
34599
34693
|
phoneNumber = onboarding.phone_number;
|
|
34600
34694
|
return { step: "provision_phone", status: "skipped", detail: "already provisioned" };
|
|
34601
34695
|
}
|
|
34696
|
+
if (phoneMode === "observe") {
|
|
34697
|
+
return {
|
|
34698
|
+
step: "provision_phone",
|
|
34699
|
+
status: "skipped",
|
|
34700
|
+
detail: {
|
|
34701
|
+
reason_code: isNoSpendPolicy() ? "voice_contact_expected_no_spend_hold" : "contact_phone_missing",
|
|
34702
|
+
phone_mode: phoneMode,
|
|
34703
|
+
spend_policy: resolveCliSpendPolicy(),
|
|
34704
|
+
spend_class: "free",
|
|
34705
|
+
safe_to_retry: true,
|
|
34706
|
+
next_commands: [
|
|
34707
|
+
`foh provision status --org ${opts.org} --json`,
|
|
34708
|
+
`foh prove --mission voice --require-phone --org ${opts.org} --json`
|
|
34709
|
+
],
|
|
34710
|
+
operator_note: "Setup observed phone readiness only; no phone number was purchased."
|
|
34711
|
+
}
|
|
34712
|
+
};
|
|
34713
|
+
}
|
|
34714
|
+
if (isNoSpendPolicy()) {
|
|
34715
|
+
return {
|
|
34716
|
+
step: "provision_phone",
|
|
34717
|
+
status: "skipped",
|
|
34718
|
+
detail: {
|
|
34719
|
+
reason_code: PAID_RESOURCE_BLOCKED_REASON_CODE,
|
|
34720
|
+
spend_policy: NO_SPEND_POLICY,
|
|
34721
|
+
spend_class: "paid_foh",
|
|
34722
|
+
safe_to_retry: false,
|
|
34723
|
+
resource: "foh_twilio_phone_number",
|
|
34724
|
+
next_commands: [
|
|
34725
|
+
`foh provision status --org ${opts.org} --json`,
|
|
34726
|
+
`foh prove --mission voice --require-phone --org ${opts.org} --json`
|
|
34727
|
+
],
|
|
34728
|
+
operator_note: "Setup continued without buying a FOH-owned phone number because no-spend eval mode is active."
|
|
34729
|
+
}
|
|
34730
|
+
};
|
|
34731
|
+
}
|
|
34602
34732
|
const result = await apiFetch("/v1/console/org/twilio/provision", {
|
|
34603
34733
|
method: "POST",
|
|
34604
34734
|
body: JSON.stringify({ country: opts.phoneCountry ?? "GB", area_code: opts.phoneAreaCode }),
|
|
@@ -34861,6 +34991,8 @@ ${serialiseManifest(manifest)}`,
|
|
|
34861
34991
|
org_id: opts.org,
|
|
34862
34992
|
agent_id: agentId ?? null
|
|
34863
34993
|
},
|
|
34994
|
+
phone_mode: phoneMode,
|
|
34995
|
+
spend_policy: resolveCliSpendPolicy(),
|
|
34864
34996
|
org_id: opts.org,
|
|
34865
34997
|
agent_id: agentId,
|
|
34866
34998
|
phone_number: phoneNumber,
|
|
@@ -37164,12 +37296,23 @@ function registerProve(program3) {
|
|
|
37164
37296
|
} else if (provisioningStatus === "failed" && (opts.requirePhone || mission === "voice")) {
|
|
37165
37297
|
checks.push(hold("contact_channel", "contact_phone_provisioning_failed", "Phone/contact provisioning failed for this org.", `foh provision status --org ${ctx.orgId} --json`, {
|
|
37166
37298
|
provisioning_status: provisioningStatus,
|
|
37167
|
-
mission
|
|
37299
|
+
mission,
|
|
37300
|
+
spend_policy: resolveCliSpendPolicy()
|
|
37301
|
+
}));
|
|
37302
|
+
} else if (isNoSpendPolicy() && (opts.requirePhone || mission === "voice")) {
|
|
37303
|
+
checks.push(hold("contact_channel", "voice_contact_expected_no_spend_hold", "No phone/contact number is provisioned; this is expected in no-spend eval mode unless a BYON/customer-approved phone path exists.", `foh provision status --org ${ctx.orgId} --json`, {
|
|
37304
|
+
provisioning_status: provisioningStatus,
|
|
37305
|
+
mission,
|
|
37306
|
+
spend_policy: resolveCliSpendPolicy(),
|
|
37307
|
+
spend_class: "free",
|
|
37308
|
+
safe_to_retry: true,
|
|
37309
|
+
operator_note: "No-spend proof observes contact readiness only. Do not buy a FOH-owned number during mass evals."
|
|
37168
37310
|
}));
|
|
37169
37311
|
} else if (opts.requirePhone || mission === "voice") {
|
|
37170
37312
|
checks.push(hold("contact_channel", "contact_phone_missing", "No phone/contact number is provisioned for this org.", `foh provision buy --org ${ctx.orgId} --json`, {
|
|
37171
37313
|
provisioning_status: provisioningStatus,
|
|
37172
|
-
mission
|
|
37314
|
+
mission,
|
|
37315
|
+
spend_policy: resolveCliSpendPolicy()
|
|
37173
37316
|
}));
|
|
37174
37317
|
} else {
|
|
37175
37318
|
checks.push(skipped("contact_channel", "contact_phone_not_required", "No phone/contact number is provisioned; pass --require-phone to make this a blocker.", `foh provision buy --org ${ctx.orgId} --json`));
|
|
@@ -38741,6 +38884,7 @@ function buildCodexExecutorEnv(input) {
|
|
|
38741
38884
|
env.npm_config_yes = "true";
|
|
38742
38885
|
env[EXTERNAL_AGENT_RUN_DIR_ENV] = input.runDir;
|
|
38743
38886
|
env[EXTERNAL_AGENT_PROMPT_VERSION_ENV] = input.promptVersion;
|
|
38887
|
+
env[FOH_CLI_SPEND_POLICY_ENV] = NO_SPEND_POLICY;
|
|
38744
38888
|
env.FOH_CLI_SUPPRESS_BANNER = "1";
|
|
38745
38889
|
return env;
|
|
38746
38890
|
}
|
|
@@ -39049,9 +39193,15 @@ function classifyRun(input) {
|
|
|
39049
39193
|
...Array.isArray(record2.check_reason_codes) ? record2.check_reason_codes.map((code) => String(code || "")) : []
|
|
39050
39194
|
]).filter(Boolean);
|
|
39051
39195
|
const hasCommandReason = (pattern) => commandReasonCodes.some((reason) => pattern.test(reason));
|
|
39196
|
+
if (hasCommandReason(new RegExp(PAID_RESOURCE_BLOCKED_REASON_CODE, "i"))) {
|
|
39197
|
+
return { status: "hold", reasonCode: PAID_RESOURCE_BLOCKED_REASON_CODE };
|
|
39198
|
+
}
|
|
39052
39199
|
if (hasCommandReason(/contact_phone_provisioning_failed/i)) {
|
|
39053
39200
|
return { status: "hold", reasonCode: "voice_contact_phone_provisioning_failed" };
|
|
39054
39201
|
}
|
|
39202
|
+
if (hasCommandReason(/voice_contact_expected_no_spend_hold/i)) {
|
|
39203
|
+
return { status: "hold", reasonCode: "voice_contact_expected_no_spend_hold" };
|
|
39204
|
+
}
|
|
39055
39205
|
if (hasCommandReason(/contact_phone_missing/i)) {
|
|
39056
39206
|
return { status: "hold", reasonCode: "voice_contact_phone_missing" };
|
|
39057
39207
|
}
|
|
@@ -39083,6 +39233,12 @@ ${stderr}`;
|
|
|
39083
39233
|
if (/contact_phone_provisioning_failed/i.test(combined)) {
|
|
39084
39234
|
return { status: "hold", reasonCode: "voice_contact_phone_provisioning_failed" };
|
|
39085
39235
|
}
|
|
39236
|
+
if (new RegExp(PAID_RESOURCE_BLOCKED_REASON_CODE, "i").test(combined)) {
|
|
39237
|
+
return { status: "hold", reasonCode: PAID_RESOURCE_BLOCKED_REASON_CODE };
|
|
39238
|
+
}
|
|
39239
|
+
if (/voice_contact_expected_no_spend_hold/i.test(combined)) {
|
|
39240
|
+
return { status: "hold", reasonCode: "voice_contact_expected_no_spend_hold" };
|
|
39241
|
+
}
|
|
39086
39242
|
if (/contact_phone_missing/i.test(combined)) {
|
|
39087
39243
|
return { status: "hold", reasonCode: "voice_contact_phone_missing" };
|
|
39088
39244
|
}
|
|
@@ -39293,7 +39449,7 @@ async function executeExternalAgentExecutorPlan(plan, options = {}) {
|
|
|
39293
39449
|
var DEFAULT_PROMPT_VERSION = "blank-setup.v1";
|
|
39294
39450
|
var DEFAULT_BATCH_MODELS = "openai/codex,anthropic/claude,cursor/agent";
|
|
39295
39451
|
var PROMPTS = {
|
|
39296
|
-
"blank-setup.v1": "Go to https://frontofhouse.okii.uk. Use only public docs, public API docs, and the public npm CLI package. Always invoke the CLI with `npx --yes @f-o-h/cli@latest ...`; do not use unpinned `npx @f-o-h/cli ...`, because cached older packages can produce invalid evidence. Install or verify the FOH CLI, authenticate or reach a deterministic auth blocker, then create or configure a Front Of House voice agent and website widget. Prefer the certification-oriented buyer templates: run `npx --yes @f-o-h/cli@latest templates list --category buyer --json` and use `UK Buyer Qualification` or `Viewing Booking` when available; do not use a greeting-only template for proof/certification. Prefer `npx --yes @f-o-h/cli@latest setup
|
|
39452
|
+
"blank-setup.v1": "Go to https://frontofhouse.okii.uk. Use only public docs, public API docs, and the public npm CLI package. Always invoke the CLI with `npx --yes @f-o-h/cli@latest ...`; do not use unpinned `npx @f-o-h/cli ...`, because cached older packages can produce invalid evidence. Install or verify the FOH CLI, authenticate or reach a deterministic auth blocker, then create or configure a Front Of House voice agent and website widget. Prefer the certification-oriented buyer templates: run `npx --yes @f-o-h/cli@latest templates list --category buyer --json` and use `UK Buyer Qualification` or `Viewing Booking` when available; do not use a greeting-only template for proof/certification. Prefer `npx --yes @f-o-h/cli@latest setup --phone-mode observe` for the free scaffold path: agent, widget, voice config, smoke test, certification, and publish readiness together. Treat phone-number purchasing as an explicit paid/scarce contact-path step, not part of high-volume eval setup. If `FOH_CLI_SPEND_POLICY=no_spend` is active and a command returns `paid_resource_blocked_by_spend_policy`, do not try to bypass it; continue widget/setup proof and report that exact reason code for the phone path. Run proof/smoke/certification where available, including widget proof and voice proof. If voice proof returns `contact_phone_missing` or `voice_contact_expected_no_spend_hold`, report that exact reason code unless a BYON/customer-approved phone path already exists. 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.",
|
|
39297
39453
|
"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.",
|
|
39298
39454
|
"knowledge-miss.v1": "A FOH agent failed to answer a business question. Use CLI/API/docs to determine whether this is a knowledge-ingestion issue, retrieval issue, config issue, prompt/behavior issue, or runtime issue. Prefer foh knowledge query, transcript export, replay, and foh bug improve artifacts over screenshots.",
|
|
39299
39455
|
"replay-failure.v1": "You are given a FOH transcript or replay artifact. Use CLI/API/docs to replay or inspect the failed interaction, identify expected vs actual behavior, and produce a scenario-test or improvement-packet candidate."
|