vent-hq 0.7.4 → 0.7.6
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/LICENSE +21 -0
- package/dist/index.mjs +55 -56
- package/dist/package-GMLASC6S.mjs +51 -0
- package/dist/package-HCBRPLMU.mjs +51 -0
- package/package.json +9 -9
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Stephan Gazarov
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.mjs
CHANGED
|
@@ -400,7 +400,6 @@ async function startRelay(relayConfig) {
|
|
|
400
400
|
process.stderr.write(`${msg}
|
|
401
401
|
`);
|
|
402
402
|
});
|
|
403
|
-
await client.activate();
|
|
404
403
|
await client.connect();
|
|
405
404
|
let agentProcess = null;
|
|
406
405
|
if (relayConfig.start_command) {
|
|
@@ -418,6 +417,7 @@ async function startRelay(relayConfig) {
|
|
|
418
417
|
if (relayConfig.start_command) {
|
|
419
418
|
await waitForHealth(relayConfig.agent_port, relayConfig.health_endpoint);
|
|
420
419
|
}
|
|
420
|
+
await client.activate();
|
|
421
421
|
const cleanup = async () => {
|
|
422
422
|
if (agentProcess && !agentProcess.killed) {
|
|
423
423
|
agentProcess.kill("SIGTERM");
|
|
@@ -453,7 +453,15 @@ function printEvent(event, jsonMode) {
|
|
|
453
453
|
return;
|
|
454
454
|
}
|
|
455
455
|
if (!isTTY) {
|
|
456
|
-
|
|
456
|
+
const meta2 = event.metadata_json ?? {};
|
|
457
|
+
if (event.event_type === "test_completed") {
|
|
458
|
+
const name = meta2.test_name ?? "test";
|
|
459
|
+
const status = meta2.status ?? "unknown";
|
|
460
|
+
const durationMs = meta2.duration_ms;
|
|
461
|
+
const duration = durationMs != null ? (durationMs / 1e3).toFixed(1) + "s" : "";
|
|
462
|
+
process.stderr.write(` ${status === "completed" || status === "pass" ? "\u2714" : "\u2718"} ${name} ${duration}
|
|
463
|
+
`);
|
|
464
|
+
}
|
|
457
465
|
return;
|
|
458
466
|
}
|
|
459
467
|
const meta = event.metadata_json ?? {};
|
|
@@ -512,58 +520,41 @@ function printRunComplete(meta) {
|
|
|
512
520
|
}
|
|
513
521
|
}
|
|
514
522
|
function printSummary(testResults, runComplete, runId, jsonMode) {
|
|
515
|
-
|
|
516
|
-
const failedTests = testResults.filter((e) => {
|
|
517
|
-
const meta = e.metadata_json ?? {};
|
|
518
|
-
const r = meta.result;
|
|
519
|
-
const status = r?.status ?? meta.status;
|
|
520
|
-
return status && status !== "completed" && status !== "pass";
|
|
521
|
-
}).map((e) => {
|
|
522
|
-
const meta = e.metadata_json ?? {};
|
|
523
|
-
const r = meta.result;
|
|
524
|
-
return {
|
|
525
|
-
name: r?.name ?? meta.test_name ?? "test",
|
|
526
|
-
status: r?.status ?? meta.status,
|
|
527
|
-
duration_ms: r?.duration_ms ?? meta.duration_ms,
|
|
528
|
-
intent_accuracy: r?.behavior?.intent_accuracy?.score,
|
|
529
|
-
p50_ttfw_ms: r?.latency?.p50_ttfw_ms
|
|
530
|
-
};
|
|
531
|
-
});
|
|
532
|
-
const agg = runComplete.aggregate;
|
|
533
|
-
const counts = agg?.red_team_tests ?? agg?.conversation_tests;
|
|
534
|
-
process.stdout.write(
|
|
535
|
-
JSON.stringify({
|
|
536
|
-
event_type: "summary",
|
|
537
|
-
data: {
|
|
538
|
-
run_id: runId,
|
|
539
|
-
status: runComplete.status,
|
|
540
|
-
total: runComplete.total_tests ?? counts?.total,
|
|
541
|
-
passed: runComplete.passed_tests ?? counts?.passed,
|
|
542
|
-
failed: runComplete.failed_tests ?? counts?.failed,
|
|
543
|
-
failed_tests: failedTests,
|
|
544
|
-
check: `npx vent-hq status ${runId} --json`
|
|
545
|
-
}
|
|
546
|
-
}) + "\n"
|
|
547
|
-
);
|
|
548
|
-
return;
|
|
549
|
-
}
|
|
550
|
-
const failures = testResults.filter((e) => {
|
|
523
|
+
const allTests = testResults.map((e) => {
|
|
551
524
|
const meta = e.metadata_json ?? {};
|
|
552
525
|
const r = meta.result;
|
|
553
|
-
|
|
554
|
-
|
|
526
|
+
return {
|
|
527
|
+
name: r?.name ?? meta.test_name ?? "test",
|
|
528
|
+
status: r?.status ?? meta.status,
|
|
529
|
+
duration_ms: r?.duration_ms ?? meta.duration_ms,
|
|
530
|
+
intent_accuracy: r?.behavior?.intent_accuracy?.score,
|
|
531
|
+
p50_ttfw_ms: r?.latency?.p50_ttfw_ms,
|
|
532
|
+
error: r?.error ?? void 0
|
|
533
|
+
};
|
|
555
534
|
});
|
|
535
|
+
const agg = runComplete.aggregate;
|
|
536
|
+
const counts = agg?.red_team_tests ?? agg?.conversation_tests;
|
|
537
|
+
const summaryData = {
|
|
538
|
+
run_id: runId,
|
|
539
|
+
status: runComplete.status,
|
|
540
|
+
total: runComplete.total_tests ?? counts?.total,
|
|
541
|
+
passed: runComplete.passed_tests ?? counts?.passed,
|
|
542
|
+
failed: runComplete.failed_tests ?? counts?.failed,
|
|
543
|
+
tests: allTests,
|
|
544
|
+
check: `npx vent-hq status ${runId} --json`
|
|
545
|
+
};
|
|
546
|
+
if (jsonMode || !isTTY) {
|
|
547
|
+
process.stdout.write(JSON.stringify(summaryData) + "\n");
|
|
548
|
+
return;
|
|
549
|
+
}
|
|
550
|
+
const failures = allTests.filter((t2) => t2.status && t2.status !== "completed" && t2.status !== "pass");
|
|
556
551
|
if (failures.length > 0) {
|
|
557
552
|
process.stdout.write("\n" + bold("Failed tests:") + "\n");
|
|
558
|
-
for (const
|
|
559
|
-
const
|
|
560
|
-
const
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
const duration = durationMs != null ? (durationMs / 1e3).toFixed(1) + "s" : "\u2014";
|
|
564
|
-
const parts = [red("\u2718"), bold(name), dim(duration)];
|
|
565
|
-
if (r?.behavior?.intent_accuracy) {
|
|
566
|
-
parts.push(`intent: ${r.behavior.intent_accuracy.score}`);
|
|
553
|
+
for (const t2 of failures) {
|
|
554
|
+
const duration = t2.duration_ms != null ? (t2.duration_ms / 1e3).toFixed(1) + "s" : "\u2014";
|
|
555
|
+
const parts = [red("\u2718"), bold(t2.name), dim(duration)];
|
|
556
|
+
if (t2.intent_accuracy != null) {
|
|
557
|
+
parts.push(`intent: ${t2.intent_accuracy}`);
|
|
567
558
|
}
|
|
568
559
|
process.stdout.write(" " + parts.join(" ") + "\n");
|
|
569
560
|
}
|
|
@@ -588,6 +579,7 @@ function printSuccess(message) {
|
|
|
588
579
|
}
|
|
589
580
|
|
|
590
581
|
// src/commands/run.ts
|
|
582
|
+
var isTTY2 = process.stdout.isTTY;
|
|
591
583
|
function log2(msg) {
|
|
592
584
|
const ts = (/* @__PURE__ */ new Date()).toISOString().slice(11, 23);
|
|
593
585
|
process.stderr.write(`[vent ${ts}] ${msg}
|
|
@@ -760,8 +752,15 @@ async function runCommand(args) {
|
|
|
760
752
|
}
|
|
761
753
|
}
|
|
762
754
|
log2(`summary: testResults=${testResults.length} runComplete=${!!runCompleteData} exitCode=${exitCode}`);
|
|
763
|
-
if (runCompleteData
|
|
755
|
+
if (runCompleteData) {
|
|
764
756
|
printSummary(testResults, runCompleteData, run_id, args.json);
|
|
757
|
+
} else if (!isTTY2) {
|
|
758
|
+
process.stdout.write(JSON.stringify({
|
|
759
|
+
run_id,
|
|
760
|
+
status: exitCode === 0 ? "pass" : "error",
|
|
761
|
+
error: "Stream ended without run_complete event",
|
|
762
|
+
check: `npx vent-hq status ${run_id} --json`
|
|
763
|
+
}) + "\n");
|
|
765
764
|
}
|
|
766
765
|
log2(`exiting with code ${exitCode}`);
|
|
767
766
|
return exitCode;
|
|
@@ -5371,11 +5370,11 @@ async function statusCommand(args) {
|
|
|
5371
5370
|
if (status2 === "running" || status2 === "queued") {
|
|
5372
5371
|
printInfo(`Run ${args.runId}: ${status2} (${testCount} tests completed so far)`);
|
|
5373
5372
|
} else {
|
|
5374
|
-
const
|
|
5375
|
-
const bold2 = (s) =>
|
|
5376
|
-
const dim2 = (s) =>
|
|
5377
|
-
const green2 = (s) =>
|
|
5378
|
-
const red2 = (s) =>
|
|
5373
|
+
const isTTY3 = process.stdout.isTTY;
|
|
5374
|
+
const bold2 = (s) => isTTY3 ? `\x1B[1m${s}\x1B[0m` : s;
|
|
5375
|
+
const dim2 = (s) => isTTY3 ? `\x1B[2m${s}\x1B[0m` : s;
|
|
5376
|
+
const green2 = (s) => isTTY3 ? `\x1B[32m${s}\x1B[0m` : s;
|
|
5377
|
+
const red2 = (s) => isTTY3 ? `\x1B[31m${s}\x1B[0m` : s;
|
|
5379
5378
|
if (status2 === "pass") {
|
|
5380
5379
|
process.stdout.write(green2(bold2("Run passed")) + "\n");
|
|
5381
5380
|
} else {
|
|
@@ -6814,7 +6813,7 @@ async function main() {
|
|
|
6814
6813
|
return 0;
|
|
6815
6814
|
}
|
|
6816
6815
|
if (command === "--version" || command === "-v") {
|
|
6817
|
-
const pkg = await import("./package-
|
|
6816
|
+
const pkg = await import("./package-GMLASC6S.mjs");
|
|
6818
6817
|
console.log(`vent-hq ${pkg.default.version}`);
|
|
6819
6818
|
return 0;
|
|
6820
6819
|
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import "./chunk-U4M3XDTH.mjs";
|
|
3
|
+
|
|
4
|
+
// package.json
|
|
5
|
+
var package_default = {
|
|
6
|
+
name: "vent-hq",
|
|
7
|
+
version: "0.7.6",
|
|
8
|
+
type: "module",
|
|
9
|
+
description: "Vent CLI \u2014 CI/CD for voice AI agents",
|
|
10
|
+
bin: {
|
|
11
|
+
"vent-hq": "dist/index.mjs"
|
|
12
|
+
},
|
|
13
|
+
files: [
|
|
14
|
+
"dist"
|
|
15
|
+
],
|
|
16
|
+
scripts: {
|
|
17
|
+
build: "node scripts/bundle.mjs",
|
|
18
|
+
clean: "rm -rf dist"
|
|
19
|
+
},
|
|
20
|
+
keywords: [
|
|
21
|
+
"vent",
|
|
22
|
+
"cli",
|
|
23
|
+
"voice",
|
|
24
|
+
"agent",
|
|
25
|
+
"testing",
|
|
26
|
+
"ci-cd"
|
|
27
|
+
],
|
|
28
|
+
license: "MIT",
|
|
29
|
+
publishConfig: {
|
|
30
|
+
access: "public"
|
|
31
|
+
},
|
|
32
|
+
repository: {
|
|
33
|
+
type: "git",
|
|
34
|
+
url: "https://github.com/vent-hq/vent",
|
|
35
|
+
directory: "packages/cli"
|
|
36
|
+
},
|
|
37
|
+
homepage: "https://ventmcp.dev",
|
|
38
|
+
dependencies: {
|
|
39
|
+
"@clack/prompts": "^1.1.0",
|
|
40
|
+
ws: "^8.18.0"
|
|
41
|
+
},
|
|
42
|
+
devDependencies: {
|
|
43
|
+
"@types/ws": "^8.5.0",
|
|
44
|
+
"@vent/relay-client": "workspace:*",
|
|
45
|
+
"@vent/shared": "workspace:*",
|
|
46
|
+
esbuild: "^0.24.0"
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
export {
|
|
50
|
+
package_default as default
|
|
51
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import "./chunk-U4M3XDTH.mjs";
|
|
3
|
+
|
|
4
|
+
// package.json
|
|
5
|
+
var package_default = {
|
|
6
|
+
name: "vent-hq",
|
|
7
|
+
version: "0.7.5",
|
|
8
|
+
type: "module",
|
|
9
|
+
description: "Vent CLI \u2014 CI/CD for voice AI agents",
|
|
10
|
+
bin: {
|
|
11
|
+
"vent-hq": "dist/index.mjs"
|
|
12
|
+
},
|
|
13
|
+
files: [
|
|
14
|
+
"dist"
|
|
15
|
+
],
|
|
16
|
+
scripts: {
|
|
17
|
+
build: "node scripts/bundle.mjs",
|
|
18
|
+
clean: "rm -rf dist"
|
|
19
|
+
},
|
|
20
|
+
keywords: [
|
|
21
|
+
"vent",
|
|
22
|
+
"cli",
|
|
23
|
+
"voice",
|
|
24
|
+
"agent",
|
|
25
|
+
"testing",
|
|
26
|
+
"ci-cd"
|
|
27
|
+
],
|
|
28
|
+
license: "MIT",
|
|
29
|
+
publishConfig: {
|
|
30
|
+
access: "public"
|
|
31
|
+
},
|
|
32
|
+
repository: {
|
|
33
|
+
type: "git",
|
|
34
|
+
url: "https://github.com/vent-hq/vent",
|
|
35
|
+
directory: "packages/cli"
|
|
36
|
+
},
|
|
37
|
+
homepage: "https://ventmcp.dev",
|
|
38
|
+
dependencies: {
|
|
39
|
+
"@clack/prompts": "^1.1.0",
|
|
40
|
+
ws: "^8.18.0"
|
|
41
|
+
},
|
|
42
|
+
devDependencies: {
|
|
43
|
+
"@types/ws": "^8.5.0",
|
|
44
|
+
"@vent/relay-client": "workspace:*",
|
|
45
|
+
"@vent/shared": "workspace:*",
|
|
46
|
+
esbuild: "^0.24.0"
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
export {
|
|
50
|
+
package_default as default
|
|
51
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vent-hq",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.6",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Vent CLI — CI/CD for voice AI agents",
|
|
6
6
|
"bin": {
|
|
@@ -9,10 +9,6 @@
|
|
|
9
9
|
"files": [
|
|
10
10
|
"dist"
|
|
11
11
|
],
|
|
12
|
-
"scripts": {
|
|
13
|
-
"build": "node scripts/bundle.mjs",
|
|
14
|
-
"clean": "rm -rf dist"
|
|
15
|
-
},
|
|
16
12
|
"keywords": [
|
|
17
13
|
"vent",
|
|
18
14
|
"cli",
|
|
@@ -37,8 +33,12 @@
|
|
|
37
33
|
},
|
|
38
34
|
"devDependencies": {
|
|
39
35
|
"@types/ws": "^8.5.0",
|
|
40
|
-
"
|
|
41
|
-
"@vent/
|
|
42
|
-
"
|
|
36
|
+
"esbuild": "^0.24.0",
|
|
37
|
+
"@vent/relay-client": "0.1.0",
|
|
38
|
+
"@vent/shared": "0.0.1"
|
|
39
|
+
},
|
|
40
|
+
"scripts": {
|
|
41
|
+
"build": "node scripts/bundle.mjs",
|
|
42
|
+
"clean": "rm -rf dist"
|
|
43
43
|
}
|
|
44
|
-
}
|
|
44
|
+
}
|