@f-o-h/cli 0.1.7 → 0.1.9
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 +174 -156
- package/dist/foh.js +263 -47
- package/package.json +1 -1
- package/schemas/improvement-packet.schema.json +77 -78
package/README.md
CHANGED
|
@@ -1,157 +1,175 @@
|
|
|
1
|
-
# Front Of House CLI
|
|
2
|
-
|
|
3
|
-
AI-operator provisioning CLI for Front Of House.
|
|
4
|
-
|
|
5
|
-
Public mirror: https://github.com/iiko38/front-of-house-cli
|
|
6
|
-
|
|
7
|
-
Current published baseline: `@f-o-h/cli@0.1.
|
|
8
|
-
|
|
9
|
-
This mirror is a generated release artifact. The private product monorepo is not
|
|
10
|
-
published here, and no open-source license is granted unless stated separately.
|
|
11
|
-
|
|
12
|
-
Package-local examples and schemas ship with the npm artifact:
|
|
13
|
-
|
|
14
|
-
- `examples/scenario-suite.viewing.yml`
|
|
15
|
-
- `examples/proof-report.example.json`
|
|
16
|
-
- `examples/transcript-export.example.json`
|
|
17
|
-
- `examples/improvement-packet.example.json`
|
|
18
|
-
- `
|
|
19
|
-
- `schemas/
|
|
20
|
-
- `schemas/
|
|
21
|
-
- `schemas/
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
foh auth
|
|
48
|
-
foh
|
|
49
|
-
foh
|
|
50
|
-
foh
|
|
51
|
-
foh
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
foh auth
|
|
60
|
-
foh
|
|
61
|
-
foh
|
|
62
|
-
foh
|
|
63
|
-
foh
|
|
64
|
-
foh
|
|
65
|
-
foh agent
|
|
66
|
-
foh
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
```yaml
|
|
111
|
-
agent: agent_123
|
|
112
|
-
scenarios:
|
|
113
|
-
- id:
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
1
|
+
# Front Of House CLI
|
|
2
|
+
|
|
3
|
+
AI-operator provisioning CLI for Front Of House.
|
|
4
|
+
|
|
5
|
+
Public mirror: https://github.com/iiko38/front-of-house-cli
|
|
6
|
+
|
|
7
|
+
Current published baseline: `@f-o-h/cli@0.1.9`
|
|
8
|
+
|
|
9
|
+
This mirror is a generated release artifact. The private product monorepo is not
|
|
10
|
+
published here, and no open-source license is granted unless stated separately.
|
|
11
|
+
|
|
12
|
+
Package-local examples and schemas ship with the npm artifact:
|
|
13
|
+
|
|
14
|
+
- `examples/scenario-suite.viewing.yml`
|
|
15
|
+
- `examples/proof-report.example.json`
|
|
16
|
+
- `examples/transcript-export.example.json`
|
|
17
|
+
- `examples/improvement-packet.example.json`
|
|
18
|
+
- `examples/external-agent-run.example.json`
|
|
19
|
+
- `schemas/cli-envelope.schema.json`
|
|
20
|
+
- `schemas/scenario-suite.schema.json`
|
|
21
|
+
- `schemas/transcript-export.schema.json`
|
|
22
|
+
- `schemas/improvement-packet.schema.json`
|
|
23
|
+
- `schemas/external-agent-run.schema.json`
|
|
24
|
+
|
|
25
|
+
## Install
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npx @f-o-h/cli setup
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Or install globally:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npm install -g @f-o-h/cli
|
|
35
|
+
foh --help
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Verify the package version:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npx @f-o-h/cli --version
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## First Run
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
foh auth signup --web
|
|
48
|
+
foh auth login --web
|
|
49
|
+
foh auth login
|
|
50
|
+
foh org list
|
|
51
|
+
foh org use --org <org-id>
|
|
52
|
+
foh setup
|
|
53
|
+
foh prove --agent <agent-id> --json
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
For AI agents and text-only terminals:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
foh auth signup --web --json
|
|
60
|
+
foh auth login --web --json
|
|
61
|
+
foh auth login --email "$FOH_EMAIL" --password "$FOH_PASSWORD" --json
|
|
62
|
+
foh org list --json
|
|
63
|
+
foh org use --org <org-id> --json
|
|
64
|
+
foh setup --org <org-id> --agent-template <template-id> --agent-name "Demo Agent" --json
|
|
65
|
+
foh prove --agent <agent-id> --json --out foh-proof.json
|
|
66
|
+
foh test run --suite ./suite.yml --agent <agent-id> --json --out foh-test-report.json
|
|
67
|
+
foh agent replay --file ./transcript-export.json --json
|
|
68
|
+
foh bug improve --from-file foh-proof.json --out foh-improvement.json --json
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
`auth signup --web` opens the console signup page when possible and always
|
|
72
|
+
prints the fallback URL. `auth login --web` starts browser device
|
|
73
|
+
authorization, opens `/cli-auth`, waits for console approval, and stores the
|
|
74
|
+
returned short-lived token. Credential auth remains available as fallback.
|
|
75
|
+
|
|
76
|
+
`foh prove` produces a compact signed proof report across auth, org context,
|
|
77
|
+
agent validation, contact phone readiness, voice provider health, widget
|
|
78
|
+
channel/embed readiness, widget smoke, and simulation certification. It is
|
|
79
|
+
read-only by default; pass `--mutation-mode ensure` or `--repair` only when you
|
|
80
|
+
explicitly want proof to ensure missing widget state. Use `--strict` in
|
|
81
|
+
automation when holds should fail the command, and `--mission voice` or
|
|
82
|
+
`--require-phone` when a voice/contact number is mandatory for the demo.
|
|
83
|
+
|
|
84
|
+
The CLI defaults to the production API at `https://api.frontofhouse.okii.uk`.
|
|
85
|
+
|
|
86
|
+
## External-Agent Eval Capture
|
|
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 \
|
|
93
|
+
--model-provider openai \
|
|
94
|
+
--model-name codex \
|
|
95
|
+
--prompt-version blank-setup.v1
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
The command writes a versioned prompt, launches an instrumented shell, captures
|
|
99
|
+
FOH CLI commands into `commands.ndjson`, and finalizes `run.json` as an
|
|
100
|
+
`external_agent_run.v1` artifact when the shell exits.
|
|
101
|
+
|
|
102
|
+
## Local Scenario Suites
|
|
103
|
+
|
|
104
|
+
`foh test run --suite <file>` runs deterministic widget-runtime checks for a
|
|
105
|
+
specific agent. The suite format supports reply text checks plus structured
|
|
106
|
+
runtime assertions for trace/correlation IDs, action or terminal state, latency,
|
|
107
|
+
variables, tool calls, escalation/handoff, lead capture, and exact response
|
|
108
|
+
field paths.
|
|
109
|
+
|
|
110
|
+
```yaml
|
|
111
|
+
agent: agent_123
|
|
112
|
+
scenarios:
|
|
113
|
+
- id: viewing
|
|
114
|
+
turns:
|
|
115
|
+
- user: Can I book a viewing this week?
|
|
116
|
+
expect:
|
|
117
|
+
contains: viewing
|
|
118
|
+
trace_present: true
|
|
119
|
+
correlation_present: true
|
|
120
|
+
action: text
|
|
121
|
+
latency_ms:
|
|
122
|
+
max: 3000
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Use transcript fixtures when turning real user conversations into regression
|
|
126
|
+
tests:
|
|
127
|
+
|
|
128
|
+
```yaml
|
|
129
|
+
agent: agent_123
|
|
130
|
+
scenarios:
|
|
131
|
+
- id: replay-viewing
|
|
132
|
+
fixture_transcript: ./fixtures/viewing-transcript.json
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Transcript Export
|
|
136
|
+
|
|
137
|
+
Use hydrated transcript export to turn real behavior into replay/debug artifacts:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
foh transcripts export \
|
|
141
|
+
--agent <agent-id> \
|
|
142
|
+
--hydrate \
|
|
143
|
+
--include-traces \
|
|
144
|
+
--format json \
|
|
145
|
+
--out foh-transcripts.json \
|
|
146
|
+
--json
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Exports redact obvious emails, phone numbers, and secret-like tokens by default.
|
|
150
|
+
Each exported conversation includes a `replay_command` and `test_fixture` seed
|
|
151
|
+
so operators or AI agents can move from observed failure to replay or scenario
|
|
152
|
+
regression without opening the console.
|
|
153
|
+
|
|
154
|
+
Replay a local export without API access:
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
foh agent replay --file foh-transcripts.json --json
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Improvement Packets
|
|
161
|
+
|
|
162
|
+
Use `foh bug improve` when a setup, proof, replay, knowledge, runtime, or
|
|
163
|
+
live-proof failure should become actionable backlog/test/config/docs work:
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
foh bug improve \
|
|
167
|
+
--from-file test-results/proof-or-replay-failure.json \
|
|
168
|
+
--out test-results/improvement-packet.json \
|
|
169
|
+
--json
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
The command emits a redacted `foh_improvement_packet.v1` with stable IDs,
|
|
173
|
+
reason code, promotion decision, evidence summary, and deterministic next
|
|
174
|
+
commands.
|
|
157
175
|
|
package/dist/foh.js
CHANGED
|
@@ -6046,7 +6046,7 @@ var require_compile = __commonJS({
|
|
|
6046
6046
|
const schOrFunc = root.refs[ref];
|
|
6047
6047
|
if (schOrFunc)
|
|
6048
6048
|
return schOrFunc;
|
|
6049
|
-
let _sch =
|
|
6049
|
+
let _sch = resolve10.call(this, root, ref);
|
|
6050
6050
|
if (_sch === void 0) {
|
|
6051
6051
|
const schema2 = (_a2 = root.localRefs) === null || _a2 === void 0 ? void 0 : _a2[ref];
|
|
6052
6052
|
const { schemaId } = this.opts;
|
|
@@ -6073,7 +6073,7 @@ var require_compile = __commonJS({
|
|
|
6073
6073
|
function sameSchemaEnv(s1, s2) {
|
|
6074
6074
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
6075
6075
|
}
|
|
6076
|
-
function
|
|
6076
|
+
function resolve10(root, ref) {
|
|
6077
6077
|
let sch;
|
|
6078
6078
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
6079
6079
|
ref = sch;
|
|
@@ -6648,7 +6648,7 @@ var require_fast_uri = __commonJS({
|
|
|
6648
6648
|
}
|
|
6649
6649
|
return uri;
|
|
6650
6650
|
}
|
|
6651
|
-
function
|
|
6651
|
+
function resolve10(baseURI, relativeURI, options) {
|
|
6652
6652
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
6653
6653
|
const resolved = resolveComponent(parse3(baseURI, schemelessOptions), parse3(relativeURI, schemelessOptions), schemelessOptions, true);
|
|
6654
6654
|
schemelessOptions.skipEscape = true;
|
|
@@ -6875,7 +6875,7 @@ var require_fast_uri = __commonJS({
|
|
|
6875
6875
|
var fastUri = {
|
|
6876
6876
|
SCHEMES,
|
|
6877
6877
|
normalize,
|
|
6878
|
-
resolve:
|
|
6878
|
+
resolve: resolve10,
|
|
6879
6879
|
resolveComponent,
|
|
6880
6880
|
equal,
|
|
6881
6881
|
serialize,
|
|
@@ -10105,21 +10105,21 @@ async function promptLine(label, {
|
|
|
10105
10105
|
allowEmpty = false,
|
|
10106
10106
|
defaultValue
|
|
10107
10107
|
} = {}) {
|
|
10108
|
-
return await new Promise((
|
|
10108
|
+
return await new Promise((resolve10) => {
|
|
10109
10109
|
const suffix = defaultValue ? ` [${defaultValue}]` : "";
|
|
10110
10110
|
const rl = (0, import_readline.createInterface)({ input: process.stdin, output: process.stdout, terminal: true });
|
|
10111
10111
|
rl.question(`${label}${suffix}: `, (answer) => {
|
|
10112
10112
|
rl.close();
|
|
10113
10113
|
const value = String(answer ?? "").trim();
|
|
10114
10114
|
if (!value && typeof defaultValue === "string") {
|
|
10115
|
-
|
|
10115
|
+
resolve10(defaultValue);
|
|
10116
10116
|
return;
|
|
10117
10117
|
}
|
|
10118
10118
|
if (!value && !allowEmpty) {
|
|
10119
|
-
|
|
10119
|
+
resolve10("");
|
|
10120
10120
|
return;
|
|
10121
10121
|
}
|
|
10122
|
-
|
|
10122
|
+
resolve10(value);
|
|
10123
10123
|
});
|
|
10124
10124
|
});
|
|
10125
10125
|
}
|
|
@@ -10127,7 +10127,7 @@ async function promptSecret(label) {
|
|
|
10127
10127
|
if (!process.stdin.isTTY || !process.stdout.isTTY || typeof process.stdin.setRawMode !== "function") {
|
|
10128
10128
|
return await promptLine(label);
|
|
10129
10129
|
}
|
|
10130
|
-
return await new Promise((
|
|
10130
|
+
return await new Promise((resolve10) => {
|
|
10131
10131
|
const stdin = process.stdin;
|
|
10132
10132
|
const stdout = process.stdout;
|
|
10133
10133
|
const wasRaw = Boolean(stdin.isRaw);
|
|
@@ -10141,7 +10141,7 @@ async function promptSecret(label) {
|
|
|
10141
10141
|
const finish = () => {
|
|
10142
10142
|
cleanup();
|
|
10143
10143
|
stdout.write("\n");
|
|
10144
|
-
|
|
10144
|
+
resolve10(value);
|
|
10145
10145
|
};
|
|
10146
10146
|
const onData = (chunk) => {
|
|
10147
10147
|
const text = typeof chunk === "string" ? chunk : chunk.toString("utf8");
|
|
@@ -10150,7 +10150,7 @@ async function promptSecret(label) {
|
|
|
10150
10150
|
cleanup();
|
|
10151
10151
|
process.exitCode = 130;
|
|
10152
10152
|
stdout.write("\n");
|
|
10153
|
-
return
|
|
10153
|
+
return resolve10("");
|
|
10154
10154
|
}
|
|
10155
10155
|
if (char === "\r" || char === "\n") {
|
|
10156
10156
|
finish();
|
|
@@ -10419,7 +10419,7 @@ async function storeAuthenticatedSession(params) {
|
|
|
10419
10419
|
return output;
|
|
10420
10420
|
}
|
|
10421
10421
|
function sleep(ms) {
|
|
10422
|
-
return new Promise((
|
|
10422
|
+
return new Promise((resolve10) => setTimeout(resolve10, ms));
|
|
10423
10423
|
}
|
|
10424
10424
|
async function runDeviceLogin(opts) {
|
|
10425
10425
|
const jsonMode = Boolean(opts.json);
|
|
@@ -10957,7 +10957,7 @@ async function pollUntil(check2, opts) {
|
|
|
10957
10957
|
}
|
|
10958
10958
|
}
|
|
10959
10959
|
function sleep2(ms) {
|
|
10960
|
-
return new Promise((
|
|
10960
|
+
return new Promise((resolve10) => setTimeout(resolve10, ms));
|
|
10961
10961
|
}
|
|
10962
10962
|
|
|
10963
10963
|
// src/commands/compliance.ts
|
|
@@ -13995,8 +13995,8 @@ function registerAgentGuardrailCommands(agent) {
|
|
|
13995
13995
|
try {
|
|
13996
13996
|
rule = JSON.parse(opts.rule);
|
|
13997
13997
|
} catch {
|
|
13998
|
-
const { readFileSync:
|
|
13999
|
-
rule = JSON.parse(
|
|
13998
|
+
const { readFileSync: readFileSync10 } = await import("fs");
|
|
13999
|
+
rule = JSON.parse(readFileSync10(opts.rule, "utf-8"));
|
|
14000
14000
|
}
|
|
14001
14001
|
const data = await apiFetch(`/v1/console/agents/${opts.agent}/guardrails`, {
|
|
14002
14002
|
method: "POST",
|
|
@@ -14596,9 +14596,9 @@ function registerAgent(program3) {
|
|
|
14596
14596
|
process.stdout.write(yaml);
|
|
14597
14597
|
return;
|
|
14598
14598
|
}
|
|
14599
|
-
const { writeFileSync:
|
|
14599
|
+
const { writeFileSync: writeFileSync7 } = await import("fs");
|
|
14600
14600
|
const outputPath = opts.output ?? "tenant.yaml";
|
|
14601
|
-
|
|
14601
|
+
writeFileSync7(
|
|
14602
14602
|
outputPath,
|
|
14603
14603
|
`# tenant.yaml - Front Of House agent manifest
|
|
14604
14604
|
# Edit this file and run: foh plan tenant.yaml
|
|
@@ -16033,11 +16033,11 @@ function registerVoice(program3) {
|
|
|
16033
16033
|
}
|
|
16034
16034
|
const outputPath = String(opts.out || `foh-voice-preview-${provider}-${voiceId}.mp3`).trim();
|
|
16035
16035
|
const audio = Buffer.from(await res.arrayBuffer());
|
|
16036
|
-
const { mkdirSync:
|
|
16037
|
-
const { dirname: dirname5, resolve:
|
|
16038
|
-
const absolutePath =
|
|
16039
|
-
|
|
16040
|
-
|
|
16036
|
+
const { mkdirSync: mkdirSync6, writeFileSync: writeFileSync7 } = await import("fs");
|
|
16037
|
+
const { dirname: dirname5, resolve: resolve10 } = await import("path");
|
|
16038
|
+
const absolutePath = resolve10(outputPath);
|
|
16039
|
+
mkdirSync6(dirname5(absolutePath), { recursive: true });
|
|
16040
|
+
writeFileSync7(absolutePath, audio);
|
|
16041
16041
|
format({
|
|
16042
16042
|
status: "ok",
|
|
16043
16043
|
provider,
|
|
@@ -30518,7 +30518,7 @@ var Protocol = class {
|
|
|
30518
30518
|
return;
|
|
30519
30519
|
}
|
|
30520
30520
|
const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
|
|
30521
|
-
await new Promise((
|
|
30521
|
+
await new Promise((resolve10) => setTimeout(resolve10, pollInterval));
|
|
30522
30522
|
options?.signal?.throwIfAborted();
|
|
30523
30523
|
}
|
|
30524
30524
|
} catch (error2) {
|
|
@@ -30535,7 +30535,7 @@ var Protocol = class {
|
|
|
30535
30535
|
*/
|
|
30536
30536
|
request(request, resultSchema, options) {
|
|
30537
30537
|
const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
|
|
30538
|
-
return new Promise((
|
|
30538
|
+
return new Promise((resolve10, reject) => {
|
|
30539
30539
|
const earlyReject = (error2) => {
|
|
30540
30540
|
reject(error2);
|
|
30541
30541
|
};
|
|
@@ -30613,7 +30613,7 @@ var Protocol = class {
|
|
|
30613
30613
|
if (!parseResult.success) {
|
|
30614
30614
|
reject(parseResult.error);
|
|
30615
30615
|
} else {
|
|
30616
|
-
|
|
30616
|
+
resolve10(parseResult.data);
|
|
30617
30617
|
}
|
|
30618
30618
|
} catch (error2) {
|
|
30619
30619
|
reject(error2);
|
|
@@ -30874,12 +30874,12 @@ var Protocol = class {
|
|
|
30874
30874
|
}
|
|
30875
30875
|
} catch {
|
|
30876
30876
|
}
|
|
30877
|
-
return new Promise((
|
|
30877
|
+
return new Promise((resolve10, reject) => {
|
|
30878
30878
|
if (signal.aborted) {
|
|
30879
30879
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
30880
30880
|
return;
|
|
30881
30881
|
}
|
|
30882
|
-
const timeoutId = setTimeout(
|
|
30882
|
+
const timeoutId = setTimeout(resolve10, interval);
|
|
30883
30883
|
signal.addEventListener("abort", () => {
|
|
30884
30884
|
clearTimeout(timeoutId);
|
|
30885
30885
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
@@ -31979,7 +31979,7 @@ var McpServer = class {
|
|
|
31979
31979
|
let task = createTaskResult.task;
|
|
31980
31980
|
const pollInterval = task.pollInterval ?? 5e3;
|
|
31981
31981
|
while (task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled") {
|
|
31982
|
-
await new Promise((
|
|
31982
|
+
await new Promise((resolve10) => setTimeout(resolve10, pollInterval));
|
|
31983
31983
|
const updatedTask = await extra.taskStore.getTask(taskId);
|
|
31984
31984
|
if (!updatedTask) {
|
|
31985
31985
|
throw new McpError(ErrorCode.InternalError, `Task ${taskId} not found during polling`);
|
|
@@ -32628,19 +32628,19 @@ var StdioServerTransport = class {
|
|
|
32628
32628
|
this.onclose?.();
|
|
32629
32629
|
}
|
|
32630
32630
|
send(message) {
|
|
32631
|
-
return new Promise((
|
|
32631
|
+
return new Promise((resolve10) => {
|
|
32632
32632
|
const json3 = serializeMessage(message);
|
|
32633
32633
|
if (this._stdout.write(json3)) {
|
|
32634
|
-
|
|
32634
|
+
resolve10();
|
|
32635
32635
|
} else {
|
|
32636
|
-
this._stdout.once("drain",
|
|
32636
|
+
this._stdout.once("drain", resolve10);
|
|
32637
32637
|
}
|
|
32638
32638
|
});
|
|
32639
32639
|
}
|
|
32640
32640
|
};
|
|
32641
32641
|
|
|
32642
32642
|
// src/lib/cli-version.ts
|
|
32643
|
-
var CLI_VERSION = "0.1.
|
|
32643
|
+
var CLI_VERSION = "0.1.9";
|
|
32644
32644
|
|
|
32645
32645
|
// src/commands/mcp-serve.ts
|
|
32646
32646
|
var DEFAULT_TIMEOUT_MS = 12e4;
|
|
@@ -32825,7 +32825,7 @@ async function runFohCli(params) {
|
|
|
32825
32825
|
effectiveArgv.push("--json");
|
|
32826
32826
|
}
|
|
32827
32827
|
const command = `foh ${effectiveArgv.join(" ")}`;
|
|
32828
|
-
return await new Promise((
|
|
32828
|
+
return await new Promise((resolve10) => {
|
|
32829
32829
|
const child = (0, import_node_child_process.spawn)(process.execPath, [cliEntry, ...effectiveArgv], {
|
|
32830
32830
|
stdio: ["ignore", "pipe", "pipe"],
|
|
32831
32831
|
env: {
|
|
@@ -32850,7 +32850,7 @@ async function runFohCli(params) {
|
|
|
32850
32850
|
});
|
|
32851
32851
|
child.once("error", (error2) => {
|
|
32852
32852
|
clearTimeout(timeoutHandle);
|
|
32853
|
-
|
|
32853
|
+
resolve10({
|
|
32854
32854
|
ok: false,
|
|
32855
32855
|
command,
|
|
32856
32856
|
argv: effectiveArgv,
|
|
@@ -32866,7 +32866,7 @@ async function runFohCli(params) {
|
|
|
32866
32866
|
const stderrText = finalizeBoundedText(stderrBuffer);
|
|
32867
32867
|
const exitCode = Number.isFinite(code ?? NaN) ? Number(code) : 1;
|
|
32868
32868
|
const stdoutJson = tryParseJson(stdoutText);
|
|
32869
|
-
|
|
32869
|
+
resolve10({
|
|
32870
32870
|
ok: !timedOut && exitCode === 0,
|
|
32871
32871
|
command,
|
|
32872
32872
|
argv: effectiveArgv,
|
|
@@ -34775,8 +34775,8 @@ function registerSetup(program3) {
|
|
|
34775
34775
|
}
|
|
34776
34776
|
try {
|
|
34777
34777
|
const manifest = await agentExport(resolvedAgentId, { apiUrlOverride: opts.apiUrl });
|
|
34778
|
-
const { writeFileSync:
|
|
34779
|
-
|
|
34778
|
+
const { writeFileSync: writeFileSync7 } = await import("fs");
|
|
34779
|
+
writeFileSync7(
|
|
34780
34780
|
"tenant.yaml",
|
|
34781
34781
|
`# tenant.yaml - Front Of House agent manifest
|
|
34782
34782
|
# Edit this file and run: foh plan tenant.yaml
|
|
@@ -34944,8 +34944,8 @@ function registerSim(program3) {
|
|
|
34944
34944
|
}
|
|
34945
34945
|
const cert = response.certificate;
|
|
34946
34946
|
if (opts.out) {
|
|
34947
|
-
const { writeFileSync:
|
|
34948
|
-
|
|
34947
|
+
const { writeFileSync: writeFileSync7 } = await import("fs");
|
|
34948
|
+
writeFileSync7(opts.out, JSON.stringify(cert, null, 2) + "\n", "utf-8");
|
|
34949
34949
|
process.stderr.write(` Certificate written to ${opts.out}
|
|
34950
34950
|
`);
|
|
34951
34951
|
}
|
|
@@ -34995,8 +34995,8 @@ function registerSim(program3) {
|
|
|
34995
34995
|
});
|
|
34996
34996
|
}
|
|
34997
34997
|
if (opts.out) {
|
|
34998
|
-
const { writeFileSync:
|
|
34999
|
-
|
|
34998
|
+
const { writeFileSync: writeFileSync7 } = await import("fs");
|
|
34999
|
+
writeFileSync7(opts.out, JSON.stringify(response.certificate, null, 2) + "\n", "utf-8");
|
|
35000
35000
|
process.stderr.write(` Final certificate written to ${opts.out}
|
|
35001
35001
|
`);
|
|
35002
35002
|
}
|
|
@@ -37710,7 +37710,7 @@ async function runSelf(args, apiUrlOverride) {
|
|
|
37710
37710
|
if (apiUrlOverride && !spawnArgs.includes("--api-url")) {
|
|
37711
37711
|
spawnArgs.push("--api-url", apiUrlOverride);
|
|
37712
37712
|
}
|
|
37713
|
-
return await new Promise((
|
|
37713
|
+
return await new Promise((resolve10, reject) => {
|
|
37714
37714
|
const child = (0, import_child_process2.spawn)(process.execPath, [process.argv[1], ...spawnArgs], {
|
|
37715
37715
|
stdio: "inherit",
|
|
37716
37716
|
env: {
|
|
@@ -37720,7 +37720,7 @@ async function runSelf(args, apiUrlOverride) {
|
|
|
37720
37720
|
}
|
|
37721
37721
|
});
|
|
37722
37722
|
child.once("error", reject);
|
|
37723
|
-
child.once("close", (code) =>
|
|
37723
|
+
child.once("close", (code) => resolve10(typeof code === "number" ? code : 1));
|
|
37724
37724
|
});
|
|
37725
37725
|
}
|
|
37726
37726
|
function shouldUseInteractiveHome(argv) {
|
|
@@ -38098,17 +38098,17 @@ function detectUpdateAvailability(currentVersion, cwd = process.cwd()) {
|
|
|
38098
38098
|
async function applyRepoUpdate(repoRoot) {
|
|
38099
38099
|
const scriptPath = (0, import_path9.join)(repoRoot, "scripts", "Install-FohCli.ps1");
|
|
38100
38100
|
if (process.platform === "win32") {
|
|
38101
|
-
return await new Promise((
|
|
38101
|
+
return await new Promise((resolve10, reject) => {
|
|
38102
38102
|
const child = (0, import_child_process3.spawn)(
|
|
38103
38103
|
"powershell",
|
|
38104
38104
|
["-ExecutionPolicy", "Bypass", "-File", scriptPath],
|
|
38105
38105
|
{ stdio: "inherit" }
|
|
38106
38106
|
);
|
|
38107
38107
|
child.once("error", reject);
|
|
38108
|
-
child.once("close", (code) =>
|
|
38108
|
+
child.once("close", (code) => resolve10(typeof code === "number" ? code : 1));
|
|
38109
38109
|
});
|
|
38110
38110
|
}
|
|
38111
|
-
return await new Promise((
|
|
38111
|
+
return await new Promise((resolve10, reject) => {
|
|
38112
38112
|
const child = (0, import_child_process3.spawn)(
|
|
38113
38113
|
"corepack",
|
|
38114
38114
|
["pnpm", "cli:install:global"],
|
|
@@ -38118,7 +38118,7 @@ async function applyRepoUpdate(repoRoot) {
|
|
|
38118
38118
|
}
|
|
38119
38119
|
);
|
|
38120
38120
|
child.once("error", reject);
|
|
38121
|
-
child.once("close", (code) =>
|
|
38121
|
+
child.once("close", (code) => resolve10(typeof code === "number" ? code : 1));
|
|
38122
38122
|
});
|
|
38123
38123
|
}
|
|
38124
38124
|
function shouldShowUpdateNotice(argv = process.argv) {
|
|
@@ -38253,6 +38253,220 @@ function registerUpdate(program3) {
|
|
|
38253
38253
|
});
|
|
38254
38254
|
}
|
|
38255
38255
|
|
|
38256
|
+
// src/commands/eval.ts
|
|
38257
|
+
var import_fs13 = require("fs");
|
|
38258
|
+
var import_path11 = require("path");
|
|
38259
|
+
var import_child_process4 = require("child_process");
|
|
38260
|
+
|
|
38261
|
+
// src/lib/external-agent-capture.ts
|
|
38262
|
+
var import_fs12 = require("fs");
|
|
38263
|
+
var import_path10 = require("path");
|
|
38264
|
+
var EXTERNAL_AGENT_RUN_DIR_ENV = "FOH_EXTERNAL_AGENT_RUN_DIR";
|
|
38265
|
+
var EXTERNAL_AGENT_PROMPT_VERSION_ENV = "FOH_EXTERNAL_AGENT_PROMPT_VERSION";
|
|
38266
|
+
var SECRET_RE2 = /\b(?:Bearer\s+)?(?:sk|pk|xai|whsec|EAAN|ghp|gho|github_pat|npm_)[A-Za-z0-9_\-.]{12,}\b/gi;
|
|
38267
|
+
function redactText(value) {
|
|
38268
|
+
return value.replace(SECRET_RE2, "[redacted_secret]");
|
|
38269
|
+
}
|
|
38270
|
+
function redactPath(value) {
|
|
38271
|
+
let redacted = redactText(value);
|
|
38272
|
+
const home = process.env.USERPROFILE || process.env.HOME;
|
|
38273
|
+
if (home) redacted = redacted.replace(home, "~");
|
|
38274
|
+
return redacted;
|
|
38275
|
+
}
|
|
38276
|
+
function safeJsonLine(value) {
|
|
38277
|
+
return JSON.stringify(value).replace(/\r?\n/g, " ") + "\n";
|
|
38278
|
+
}
|
|
38279
|
+
function getExternalAgentRunDir() {
|
|
38280
|
+
const raw = process.env[EXTERNAL_AGENT_RUN_DIR_ENV];
|
|
38281
|
+
if (!raw || !raw.trim()) return null;
|
|
38282
|
+
return (0, import_path10.resolve)(raw);
|
|
38283
|
+
}
|
|
38284
|
+
function recordExternalAgentCliInvocation(input) {
|
|
38285
|
+
const runDir = getExternalAgentRunDir();
|
|
38286
|
+
if (!runDir) return;
|
|
38287
|
+
try {
|
|
38288
|
+
(0, import_fs12.mkdirSync)(runDir, { recursive: true });
|
|
38289
|
+
const args = input.argv.slice(2).map((arg) => redactText(String(arg)));
|
|
38290
|
+
const record2 = {
|
|
38291
|
+
schema_version: "external_agent_cli_command.v1",
|
|
38292
|
+
recorded_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
38293
|
+
cli_version: input.cliVersion,
|
|
38294
|
+
cwd: redactPath(process.cwd()),
|
|
38295
|
+
argv: args,
|
|
38296
|
+
command: args.join(" "),
|
|
38297
|
+
json_requested: args.includes("--json"),
|
|
38298
|
+
prompt_version: process.env[EXTERNAL_AGENT_PROMPT_VERSION_ENV] || null
|
|
38299
|
+
};
|
|
38300
|
+
(0, import_fs12.appendFileSync)((0, import_path10.join)(runDir, "commands.ndjson"), safeJsonLine(record2), "utf8");
|
|
38301
|
+
} catch {
|
|
38302
|
+
}
|
|
38303
|
+
}
|
|
38304
|
+
function readCommandRecords(runDir) {
|
|
38305
|
+
const commandLogPath = (0, import_path10.join)(runDir, "commands.ndjson");
|
|
38306
|
+
if (!(0, import_fs12.existsSync)(commandLogPath)) return [];
|
|
38307
|
+
return (0, import_fs12.readFileSync)(commandLogPath, "utf8").split(/\r?\n/).map((line) => line.trim()).filter(Boolean).map((line) => JSON.parse(line));
|
|
38308
|
+
}
|
|
38309
|
+
|
|
38310
|
+
// src/commands/eval.ts
|
|
38311
|
+
var DEFAULT_PROMPT_VERSION = "blank-setup.v1";
|
|
38312
|
+
var PROMPTS = {
|
|
38313
|
+
"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
|
+
"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.",
|
|
38315
|
+
"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.",
|
|
38316
|
+
"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."
|
|
38317
|
+
};
|
|
38318
|
+
function normalizeStatus(raw) {
|
|
38319
|
+
const value = String(raw ?? "hold").trim().toLowerCase();
|
|
38320
|
+
if (value === "pass" || value === "hold" || value === "fail") return value;
|
|
38321
|
+
throw new Error("Invalid --status. Use pass, hold, or fail.");
|
|
38322
|
+
}
|
|
38323
|
+
function defaultRunDir(modelName, promptVersion) {
|
|
38324
|
+
const date4 = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
38325
|
+
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").replace("T", "-").slice(0, 23);
|
|
38326
|
+
const safeModel = String(modelName || "unknown-model").toLowerCase().replace(/[^a-z0-9_-]+/g, "-");
|
|
38327
|
+
const safePrompt = String(promptVersion || DEFAULT_PROMPT_VERSION).toLowerCase().replace(/[^a-z0-9_.-]+/g, "-");
|
|
38328
|
+
return (0, import_path11.resolve)("test-results", "external-agent-runs", date4, `${safeModel}-${safePrompt}-${stamp}`);
|
|
38329
|
+
}
|
|
38330
|
+
function inferShell(raw) {
|
|
38331
|
+
if (raw && raw.trim()) return { command: raw, args: [], label: raw };
|
|
38332
|
+
if (process.platform === "win32") return { command: "powershell.exe", args: ["-NoLogo", "-NoProfile"], label: "powershell" };
|
|
38333
|
+
return { command: process.env.SHELL || "sh", args: [], label: process.env.SHELL || "sh" };
|
|
38334
|
+
}
|
|
38335
|
+
function writePrompt(runDir, promptVersion) {
|
|
38336
|
+
const prompt = PROMPTS[promptVersion] ?? PROMPTS[DEFAULT_PROMPT_VERSION];
|
|
38337
|
+
const path2 = (0, import_path11.join)(runDir, "prompt.txt");
|
|
38338
|
+
(0, import_fs13.writeFileSync)(path2, `${prompt}
|
|
38339
|
+
`, "utf8");
|
|
38340
|
+
return path2;
|
|
38341
|
+
}
|
|
38342
|
+
function writeSession(runDir, session) {
|
|
38343
|
+
const path2 = (0, import_path11.join)(runDir, "session.json");
|
|
38344
|
+
(0, import_fs13.writeFileSync)(path2, `${JSON.stringify(session, null, 2)}
|
|
38345
|
+
`, "utf8");
|
|
38346
|
+
return path2;
|
|
38347
|
+
}
|
|
38348
|
+
function buildRunArtifact(input) {
|
|
38349
|
+
const commands = readCommandRecords(input.runDir);
|
|
38350
|
+
const startedAt = String(input.session.started_at);
|
|
38351
|
+
const endedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
38352
|
+
const status = input.status;
|
|
38353
|
+
const reasonCode = status === "pass" ? null : String(input.reasonCode || "external_agent_run_needs_review");
|
|
38354
|
+
return {
|
|
38355
|
+
schema_version: "external_agent_run.v1",
|
|
38356
|
+
run_id: input.session.run_id,
|
|
38357
|
+
status,
|
|
38358
|
+
failure_reason_code: reasonCode,
|
|
38359
|
+
model_provider: input.session.model_provider,
|
|
38360
|
+
model_name: input.session.model_name,
|
|
38361
|
+
agent_shell: input.session.agent_shell,
|
|
38362
|
+
workspace_type: input.session.workspace_type,
|
|
38363
|
+
prompt_version: input.session.prompt_version,
|
|
38364
|
+
prompt_path: "prompt.txt",
|
|
38365
|
+
started_at: startedAt,
|
|
38366
|
+
ended_at: endedAt,
|
|
38367
|
+
manual_intervention_count: Number(input.session.manual_intervention_count || 0),
|
|
38368
|
+
manual_interventions: [],
|
|
38369
|
+
environment: {
|
|
38370
|
+
os: process.platform,
|
|
38371
|
+
node_version: process.version,
|
|
38372
|
+
npm_version: null,
|
|
38373
|
+
foh_cli_version: CLI_VERSION,
|
|
38374
|
+
shell_exit_code: input.shellExitCode ?? null
|
|
38375
|
+
},
|
|
38376
|
+
public_entrypoints: [
|
|
38377
|
+
"https://frontofhouse.okii.uk",
|
|
38378
|
+
"https://frontofhouse.okii.uk/llms.txt",
|
|
38379
|
+
"https://frontofhouse.okii.uk/openapi.yaml",
|
|
38380
|
+
"npx --yes @f-o-h/cli@latest"
|
|
38381
|
+
],
|
|
38382
|
+
commands_run: commands.map((command) => command.command),
|
|
38383
|
+
docs_pages_used: [],
|
|
38384
|
+
artifacts: {
|
|
38385
|
+
terminal_transcript: null,
|
|
38386
|
+
command_log: "commands.ndjson",
|
|
38387
|
+
proof_bundle: null,
|
|
38388
|
+
replay_packet: null,
|
|
38389
|
+
knowledge_packet: null,
|
|
38390
|
+
improvement_packet: status === "pass" ? null : "improvement-packet.json",
|
|
38391
|
+
notes: "notes.md"
|
|
38392
|
+
},
|
|
38393
|
+
summary: status === "pass" ? "External-agent capture session completed and was marked pass." : `External-agent capture session completed with ${commands.length} captured FOH command(s); classify and improve reason ${reasonCode}.`,
|
|
38394
|
+
next_commands: status === "pass" ? ["corepack pnpm eval:external-agent:runs:summary"] : [
|
|
38395
|
+
`foh bug improve --from external-agent-run --file ${(0, import_path11.join)(input.runDir, "run.json")} --out ${(0, import_path11.join)(input.runDir, "improvement-packet.json")} --json`,
|
|
38396
|
+
"corepack pnpm eval:external-agent:runs:summary"
|
|
38397
|
+
]
|
|
38398
|
+
};
|
|
38399
|
+
}
|
|
38400
|
+
function registerEval(program3) {
|
|
38401
|
+
const evalCommand = program3.command("eval").description("Run or summarize external-agent evaluation workflows");
|
|
38402
|
+
const external = evalCommand.command("external-agent").description("Capture clean external coding-agent setup attempts");
|
|
38403
|
+
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
|
+
const status = normalizeStatus(opts.status);
|
|
38405
|
+
const promptVersion = String(opts.promptVersion || DEFAULT_PROMPT_VERSION);
|
|
38406
|
+
const runDir = (0, import_path11.resolve)(String(opts.outDir || defaultRunDir(opts.modelName, promptVersion)));
|
|
38407
|
+
(0, import_fs13.mkdirSync)(runDir, { recursive: true });
|
|
38408
|
+
const runId = runDir.split(/[\\/]/).filter(Boolean).slice(-1)[0];
|
|
38409
|
+
const promptPath = writePrompt(runDir, promptVersion);
|
|
38410
|
+
const shell = inferShell(opts.shell);
|
|
38411
|
+
const session = {
|
|
38412
|
+
schema_version: "external_agent_capture_session.v1",
|
|
38413
|
+
run_id: runId,
|
|
38414
|
+
started_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
38415
|
+
model_provider: String(opts.modelProvider || "unknown"),
|
|
38416
|
+
model_name: String(opts.modelName || "unknown-model"),
|
|
38417
|
+
prompt_version: promptVersion,
|
|
38418
|
+
workspace_type: String(opts.workspaceType || "clean-no-repo"),
|
|
38419
|
+
agent_shell: String(opts.agentShell || shell.label),
|
|
38420
|
+
manual_intervention_count: 0,
|
|
38421
|
+
run_dir: runDir,
|
|
38422
|
+
prompt_path: promptPath,
|
|
38423
|
+
capture_env: {
|
|
38424
|
+
[EXTERNAL_AGENT_RUN_DIR_ENV]: runDir,
|
|
38425
|
+
[EXTERNAL_AGENT_PROMPT_VERSION_ENV]: promptVersion
|
|
38426
|
+
}
|
|
38427
|
+
};
|
|
38428
|
+
writeSession(runDir, session);
|
|
38429
|
+
(0, import_fs13.writeFileSync)((0, import_path11.join)(runDir, "notes.md"), "# External Agent Run Notes\n\n", "utf8");
|
|
38430
|
+
let shellExitCode = null;
|
|
38431
|
+
if (opts.shell !== false) {
|
|
38432
|
+
process.stdout.write(`
|
|
38433
|
+
External-agent capture is active.
|
|
38434
|
+
Run dir: ${runDir}
|
|
38435
|
+
Prompt: ${promptPath}
|
|
38436
|
+
Exit the shell to finalize run.json.
|
|
38437
|
+
|
|
38438
|
+
`);
|
|
38439
|
+
const result = (0, import_child_process4.spawnSync)(shell.command, shell.args, {
|
|
38440
|
+
stdio: "inherit",
|
|
38441
|
+
env: {
|
|
38442
|
+
...process.env,
|
|
38443
|
+
[EXTERNAL_AGENT_RUN_DIR_ENV]: runDir,
|
|
38444
|
+
[EXTERNAL_AGENT_PROMPT_VERSION_ENV]: promptVersion,
|
|
38445
|
+
FOH_CLI_SUPPRESS_BANNER: process.env.FOH_CLI_SUPPRESS_BANNER ?? "1"
|
|
38446
|
+
}
|
|
38447
|
+
});
|
|
38448
|
+
shellExitCode = typeof result.status === "number" ? result.status : null;
|
|
38449
|
+
}
|
|
38450
|
+
const artifact = buildRunArtifact({ runDir, session, status, reasonCode: opts.reasonCode, shellExitCode });
|
|
38451
|
+
const runPath = (0, import_path11.join)(runDir, "run.json");
|
|
38452
|
+
(0, import_fs13.writeFileSync)(runPath, `${JSON.stringify(artifact, null, 2)}
|
|
38453
|
+
`, "utf8");
|
|
38454
|
+
format(cliEnvelope({
|
|
38455
|
+
schemaVersion: "external_agent_capture_result.v1",
|
|
38456
|
+
status: "exported",
|
|
38457
|
+
reasonCode: "external_agent_run_created",
|
|
38458
|
+
summary: "External-agent run artifact created.",
|
|
38459
|
+
artifacts: {
|
|
38460
|
+
run: runPath,
|
|
38461
|
+
prompt: promptPath,
|
|
38462
|
+
commands: (0, import_path11.join)(runDir, "commands.ndjson")
|
|
38463
|
+
},
|
|
38464
|
+
nextCommands: artifact.next_commands,
|
|
38465
|
+
extra: { run: artifact }
|
|
38466
|
+
}), { json: Boolean(opts.json) });
|
|
38467
|
+
});
|
|
38468
|
+
}
|
|
38469
|
+
|
|
38256
38470
|
// src/lib/banner.ts
|
|
38257
38471
|
var import_picocolors6 = __toESM(require_picocolors());
|
|
38258
38472
|
var BANNER_LINES = [
|
|
@@ -38323,6 +38537,7 @@ function installSoftExitTrap() {
|
|
|
38323
38537
|
|
|
38324
38538
|
// src/index.ts
|
|
38325
38539
|
installSoftExitTrap();
|
|
38540
|
+
recordExternalAgentCliInvocation({ argv: process.argv, cliVersion: CLI_VERSION });
|
|
38326
38541
|
var program2 = new Command();
|
|
38327
38542
|
var BUG_REPORT_URL = process.env.FOH_BUG_REPORT_URL ?? "https://github.com/iiko38/front-of-house/issues";
|
|
38328
38543
|
function shouldRenderBanner2(argv) {
|
|
@@ -38404,6 +38619,7 @@ registerSim(program2);
|
|
|
38404
38619
|
registerDiag(program2);
|
|
38405
38620
|
registerBug(program2);
|
|
38406
38621
|
registerProve(program2);
|
|
38622
|
+
registerEval(program2);
|
|
38407
38623
|
registerUpdate(program2);
|
|
38408
38624
|
registerHome(program2);
|
|
38409
38625
|
hideInternalApiUrlOptions(program2);
|
package/package.json
CHANGED
|
@@ -1,78 +1,77 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
-
"$id": "https://frontofhouse.okii.uk/schemas/improvement-packet.schema.json",
|
|
4
|
-
"title": "FOH Improvement Packet",
|
|
5
|
-
"type": "object",
|
|
6
|
-
"required": [
|
|
7
|
-
"schema_version",
|
|
8
|
-
"created_at",
|
|
9
|
-
"source_type",
|
|
10
|
-
"reason_code",
|
|
11
|
-
"promotion_decision",
|
|
12
|
-
"ids",
|
|
13
|
-
"evidence",
|
|
14
|
-
"next_commands"
|
|
15
|
-
],
|
|
16
|
-
"properties": {
|
|
17
|
-
"schema_version": { "const": "foh_improvement_packet.v1" },
|
|
18
|
-
"created_at": { "type": "string" },
|
|
19
|
-
"source_type": {
|
|
20
|
-
"type": "string",
|
|
21
|
-
"enum": [
|
|
22
|
-
"external_agent_run",
|
|
23
|
-
"setup_failure",
|
|
24
|
-
"proof_failure",
|
|
25
|
-
"replay_failure",
|
|
26
|
-
"knowledge_miss",
|
|
27
|
-
"runtime_miss",
|
|
28
|
-
"live_proof_failure"
|
|
29
|
-
]
|
|
30
|
-
},
|
|
31
|
-
"reason_code": { "type": "string", "minLength": 1 },
|
|
32
|
-
"promotion_decision": {
|
|
33
|
-
"type": "string",
|
|
34
|
-
"enum": ["ignore", "fix_docs", "fix_config", "fix_cli", "fix_api", "fix_runtime", "add_test"]
|
|
35
|
-
},
|
|
36
|
-
"ids": {
|
|
37
|
-
"type": "object",
|
|
38
|
-
"properties": {
|
|
39
|
-
"org_id": { "type": "string" },
|
|
40
|
-
"agent_id": { "type": "string" },
|
|
41
|
-
"conversation_id": { "type": "string" },
|
|
42
|
-
"trace_id": { "type": "string" },
|
|
43
|
-
"correlation_id": { "type": "string" },
|
|
44
|
-
"proof_artifact": { "type": "string" }
|
|
45
|
-
},
|
|
46
|
-
"additionalProperties": false
|
|
47
|
-
},
|
|
48
|
-
"evidence": {
|
|
49
|
-
"type": "object",
|
|
50
|
-
"required": ["summary", "redaction"],
|
|
51
|
-
"properties": {
|
|
52
|
-
"summary": { "type": "string", "minLength": 1 },
|
|
53
|
-
"source_artifact_path": { "type": ["string", "null"] },
|
|
54
|
-
"source_command": { "type": ["string", "null"] },
|
|
55
|
-
"redaction": {
|
|
56
|
-
"type": "object",
|
|
57
|
-
"required": ["enabled", "fields"],
|
|
58
|
-
"properties": {
|
|
59
|
-
"enabled": { "const": true },
|
|
60
|
-
"fields": {
|
|
61
|
-
"type": "array",
|
|
62
|
-
"items": { "type": "string" }
|
|
63
|
-
}
|
|
64
|
-
},
|
|
65
|
-
"additionalProperties": false
|
|
66
|
-
},
|
|
67
|
-
"redacted_source": {}
|
|
68
|
-
},
|
|
69
|
-
"additionalProperties": false
|
|
70
|
-
},
|
|
71
|
-
"next_commands": {
|
|
72
|
-
"type": "array",
|
|
73
|
-
"items": { "type": "string", "minLength": 1 }
|
|
74
|
-
}
|
|
75
|
-
},
|
|
76
|
-
"additionalProperties": false
|
|
77
|
-
}
|
|
78
|
-
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://frontofhouse.okii.uk/schemas/improvement-packet.schema.json",
|
|
4
|
+
"title": "FOH Improvement Packet",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"required": [
|
|
7
|
+
"schema_version",
|
|
8
|
+
"created_at",
|
|
9
|
+
"source_type",
|
|
10
|
+
"reason_code",
|
|
11
|
+
"promotion_decision",
|
|
12
|
+
"ids",
|
|
13
|
+
"evidence",
|
|
14
|
+
"next_commands"
|
|
15
|
+
],
|
|
16
|
+
"properties": {
|
|
17
|
+
"schema_version": { "const": "foh_improvement_packet.v1" },
|
|
18
|
+
"created_at": { "type": "string" },
|
|
19
|
+
"source_type": {
|
|
20
|
+
"type": "string",
|
|
21
|
+
"enum": [
|
|
22
|
+
"external_agent_run",
|
|
23
|
+
"setup_failure",
|
|
24
|
+
"proof_failure",
|
|
25
|
+
"replay_failure",
|
|
26
|
+
"knowledge_miss",
|
|
27
|
+
"runtime_miss",
|
|
28
|
+
"live_proof_failure"
|
|
29
|
+
]
|
|
30
|
+
},
|
|
31
|
+
"reason_code": { "type": "string", "minLength": 1 },
|
|
32
|
+
"promotion_decision": {
|
|
33
|
+
"type": "string",
|
|
34
|
+
"enum": ["ignore", "fix_docs", "fix_config", "fix_cli", "fix_api", "fix_runtime", "add_test"]
|
|
35
|
+
},
|
|
36
|
+
"ids": {
|
|
37
|
+
"type": "object",
|
|
38
|
+
"properties": {
|
|
39
|
+
"org_id": { "type": "string" },
|
|
40
|
+
"agent_id": { "type": "string" },
|
|
41
|
+
"conversation_id": { "type": "string" },
|
|
42
|
+
"trace_id": { "type": "string" },
|
|
43
|
+
"correlation_id": { "type": "string" },
|
|
44
|
+
"proof_artifact": { "type": "string" }
|
|
45
|
+
},
|
|
46
|
+
"additionalProperties": false
|
|
47
|
+
},
|
|
48
|
+
"evidence": {
|
|
49
|
+
"type": "object",
|
|
50
|
+
"required": ["summary", "redaction"],
|
|
51
|
+
"properties": {
|
|
52
|
+
"summary": { "type": "string", "minLength": 1 },
|
|
53
|
+
"source_artifact_path": { "type": ["string", "null"] },
|
|
54
|
+
"source_command": { "type": ["string", "null"] },
|
|
55
|
+
"redaction": {
|
|
56
|
+
"type": "object",
|
|
57
|
+
"required": ["enabled", "fields"],
|
|
58
|
+
"properties": {
|
|
59
|
+
"enabled": { "const": true },
|
|
60
|
+
"fields": {
|
|
61
|
+
"type": "array",
|
|
62
|
+
"items": { "type": "string" }
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
"additionalProperties": false
|
|
66
|
+
},
|
|
67
|
+
"redacted_source": {}
|
|
68
|
+
},
|
|
69
|
+
"additionalProperties": false
|
|
70
|
+
},
|
|
71
|
+
"next_commands": {
|
|
72
|
+
"type": "array",
|
|
73
|
+
"items": { "type": "string", "minLength": 1 }
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
"additionalProperties": false
|
|
77
|
+
}
|