@jevitate/cli 0.7.0 → 0.9.0
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/dist/ai-cli.d.ts +3 -1
- package/dist/ai-cli.js +60 -16
- package/dist/ai-cli.js.map +1 -1
- package/dist/approval-provenance.d.ts +136 -0
- package/dist/approval-provenance.js +317 -0
- package/dist/approval-provenance.js.map +1 -0
- package/dist/author-journey-cli.js +4 -2
- package/dist/author-journey-cli.js.map +1 -1
- package/dist/bin.js +30544 -20851
- package/dist/browser-cli.d.ts +10 -0
- package/dist/browser-cli.js +50 -0
- package/dist/browser-cli.js.map +1 -0
- package/dist/build-info.generated.js +2 -2
- package/dist/builtin-analyzers.d.ts +7 -0
- package/dist/builtin-analyzers.js +19 -0
- package/dist/builtin-analyzers.js.map +1 -0
- package/dist/campaign-cli.d.ts +6 -0
- package/dist/campaign-cli.js +9 -4
- package/dist/campaign-cli.js.map +1 -1
- package/dist/catalog-analysis.d.ts +70 -0
- package/dist/catalog-analysis.js +507 -0
- package/dist/catalog-analysis.js.map +1 -0
- package/dist/catalog-api.d.ts +73 -0
- package/dist/catalog-api.js +97 -0
- package/dist/catalog-api.js.map +1 -0
- package/dist/catalog-cli.d.ts +12 -0
- package/dist/catalog-cli.js +224 -0
- package/dist/catalog-cli.js.map +1 -0
- package/dist/catalog-review.d.ts +29 -0
- package/dist/catalog-review.js +290 -0
- package/dist/catalog-review.js.map +1 -0
- package/dist/catalog.d.ts +133 -0
- package/dist/catalog.js +352 -0
- package/dist/catalog.js.map +1 -0
- package/dist/change-context.d.ts +44 -0
- package/dist/change-context.js +203 -0
- package/dist/change-context.js.map +1 -0
- package/dist/check-api.d.ts +1 -1
- package/dist/check-api.js +68 -9
- package/dist/check-api.js.map +1 -1
- package/dist/check-cli.d.ts +5 -1
- package/dist/check-cli.js +64 -10
- package/dist/check-cli.js.map +1 -1
- package/dist/check-execute.d.ts +16 -1
- package/dist/check-execute.js +78 -31
- package/dist/check-execute.js.map +1 -1
- package/dist/check-plan.d.ts +14 -0
- package/dist/check-plan.js +28 -2
- package/dist/check-plan.js.map +1 -1
- package/dist/check-suite.js +6 -3
- package/dist/check-suite.js.map +1 -1
- package/dist/check-types.d.ts +51 -6
- package/dist/check-types.js +8 -0
- package/dist/check-types.js.map +1 -1
- package/dist/cli-output.js +85 -5
- package/dist/cli-output.js.map +1 -1
- package/dist/cli-shared.d.ts +22 -2
- package/dist/cli-shared.js +34 -5
- package/dist/cli-shared.js.map +1 -1
- package/dist/demo-aspect-api.d.ts +15 -0
- package/dist/demo-aspect-api.js +26 -1
- package/dist/demo-aspect-api.js.map +1 -1
- package/dist/demo-aspect-cli.js +64 -5
- package/dist/demo-aspect-cli.js.map +1 -1
- package/dist/exit-codes.d.ts +6 -3
- package/dist/exit-codes.js +13 -3
- package/dist/exit-codes.js.map +1 -1
- package/dist/explore-adversarial.d.ts +3 -1
- package/dist/explore-adversarial.js +4 -4
- package/dist/explore-adversarial.js.map +1 -1
- package/dist/explore-author.js +5 -2
- package/dist/explore-author.js.map +1 -1
- package/dist/explore-cli.js +145 -9
- package/dist/explore-cli.js.map +1 -1
- package/dist/explore-coverage.d.ts +6 -2
- package/dist/explore-coverage.js +7 -6
- package/dist/explore-coverage.js.map +1 -1
- package/dist/explore-feature.d.ts +3 -1
- package/dist/explore-feature.js +5 -5
- package/dist/explore-feature.js.map +1 -1
- package/dist/explore-goal.d.ts +37 -6
- package/dist/explore-goal.js +69 -50
- package/dist/explore-goal.js.map +1 -1
- package/dist/explore-shared.d.ts +12 -7
- package/dist/explore-shared.js +9 -1
- package/dist/explore-shared.js.map +1 -1
- package/dist/findings-filing.d.ts +6 -0
- package/dist/findings-filing.js +15 -1
- package/dist/findings-filing.js.map +1 -1
- package/dist/goal-run-flags.d.ts +2 -0
- package/dist/goal-run-flags.js +8 -1
- package/dist/goal-run-flags.js.map +1 -1
- package/dist/heal-probe-guard.d.ts +9 -0
- package/dist/heal-probe-guard.js +113 -0
- package/dist/heal-probe-guard.js.map +1 -0
- package/dist/host-health-run.d.ts +32 -1
- package/dist/host-health-run.js +38 -1
- package/dist/host-health-run.js.map +1 -1
- package/dist/http-5xx-outcome.d.ts +8 -3
- package/dist/http-5xx-outcome.js +5 -15
- package/dist/http-5xx-outcome.js.map +1 -1
- package/dist/init-cli.d.ts +7 -0
- package/dist/init-cli.js +79 -9
- package/dist/init-cli.js.map +1 -1
- package/dist/init-codeowners.d.ts +39 -0
- package/dist/init-codeowners.js +91 -0
- package/dist/init-codeowners.js.map +1 -0
- package/dist/init-keys.d.ts +3 -1
- package/dist/init-keys.js +20 -8
- package/dist/init-keys.js.map +1 -1
- package/dist/init-skills.d.ts +85 -7
- package/dist/init-skills.js +303 -36
- package/dist/init-skills.js.map +1 -1
- package/dist/jev-advisor.d.ts +72 -0
- package/dist/jev-advisor.js +172 -0
- package/dist/jev-advisor.js.map +1 -0
- package/dist/journey-api.d.ts +76 -5
- package/dist/journey-api.js +238 -29
- package/dist/journey-api.js.map +1 -1
- package/dist/journey-cli.js +257 -23
- package/dist/journey-cli.js.map +1 -1
- package/dist/journey-heal.d.ts +74 -0
- package/dist/journey-heal.js +180 -0
- package/dist/journey-heal.js.map +1 -0
- package/dist/journey-network-checks.d.ts +5 -1
- package/dist/journey-network-checks.js +15 -4
- package/dist/journey-network-checks.js.map +1 -1
- package/dist/journey-prefix.js +2 -2
- package/dist/journey-prefix.js.map +1 -1
- package/dist/journey-proposal-store.d.ts +100 -0
- package/dist/journey-proposal-store.js +342 -0
- package/dist/journey-proposal-store.js.map +1 -0
- package/dist/journey-result-record.d.ts +40 -0
- package/dist/journey-result-record.js +28 -0
- package/dist/journey-result-record.js.map +1 -0
- package/dist/journey-review-api.d.ts +19 -0
- package/dist/journey-review-api.js +53 -0
- package/dist/journey-review-api.js.map +1 -0
- package/dist/journey-review-store.d.ts +16 -0
- package/dist/journey-review-store.js +95 -0
- package/dist/journey-review-store.js.map +1 -0
- package/dist/journey-review.d.ts +54 -0
- package/dist/journey-review.js +538 -0
- package/dist/journey-review.js.map +1 -0
- package/dist/journey-verify.js +14 -1
- package/dist/journey-verify.js.map +1 -1
- package/dist/key-report.d.ts +20 -5
- package/dist/key-report.js +32 -9
- package/dist/key-report.js.map +1 -1
- package/dist/kill-signal.js +10 -2
- package/dist/kill-signal.js.map +1 -1
- package/dist/launch-armed.js +5 -1
- package/dist/launch-armed.js.map +1 -1
- package/dist/load-cli.js +4 -2
- package/dist/load-cli.js.map +1 -1
- package/dist/log-classes.d.ts +73 -0
- package/dist/log-classes.js +167 -0
- package/dist/log-classes.js.map +1 -0
- package/dist/log-correlation.d.ts +29 -10
- package/dist/log-correlation.js +44 -21
- package/dist/log-correlation.js.map +1 -1
- package/dist/login-cli.d.ts +17 -0
- package/dist/login-cli.js +161 -0
- package/dist/login-cli.js.map +1 -0
- package/dist/logs-cli.js +3 -1
- package/dist/logs-cli.js.map +1 -1
- package/dist/mcp-api.d.ts +6 -1
- package/dist/mcp-api.js +110 -16
- package/dist/mcp-api.js.map +1 -1
- package/dist/mcp-cli-runner.d.ts +2 -0
- package/dist/mcp-cli-runner.js +3 -1
- package/dist/mcp-cli-runner.js.map +1 -1
- package/dist/mcp-cli-tools.d.ts +5 -0
- package/dist/mcp-cli-tools.js +178 -23
- package/dist/mcp-cli-tools.js.map +1 -1
- package/dist/mission-cli.js +8 -4
- package/dist/mission-cli.js.map +1 -1
- package/dist/mission-journal.d.ts +4 -1
- package/dist/mission-journal.js +9 -3
- package/dist/mission-journal.js.map +1 -1
- package/dist/mission-queue-cli.js +21 -2
- package/dist/mission-queue-cli.js.map +1 -1
- package/dist/mission-queue-runner.d.ts +6 -0
- package/dist/mission-queue-runner.js +33 -3
- package/dist/mission-queue-runner.js.map +1 -1
- package/dist/multi-run-cli.d.ts +7 -1
- package/dist/multi-run-cli.js +10 -3
- package/dist/multi-run-cli.js.map +1 -1
- package/dist/multi-run.d.ts +44 -8
- package/dist/multi-run.js +118 -25
- package/dist/multi-run.js.map +1 -1
- package/dist/persona-login.d.ts +256 -0
- package/dist/persona-login.js +884 -0
- package/dist/persona-login.js.map +1 -0
- package/dist/pre-approval.d.ts +98 -0
- package/dist/pre-approval.js +175 -0
- package/dist/pre-approval.js.map +1 -0
- package/dist/program.js +12 -0
- package/dist/program.js.map +1 -1
- package/dist/project-dir.d.ts +2 -1
- package/dist/project-dir.js +3 -1
- package/dist/project-dir.js.map +1 -1
- package/dist/readiness.d.ts +29 -0
- package/dist/readiness.js +291 -0
- package/dist/readiness.js.map +1 -0
- package/dist/regression-cli.js +4 -2
- package/dist/regression-cli.js.map +1 -1
- package/dist/report-api.d.ts +25 -2
- package/dist/report-api.js +34 -5
- package/dist/report-api.js.map +1 -1
- package/dist/report-cli.js +8 -1
- package/dist/report-cli.js.map +1 -1
- package/dist/resource-preflight.js +5 -3
- package/dist/resource-preflight.js.map +1 -1
- package/dist/result-schema.d.ts +12 -0
- package/dist/result-schema.js +8 -0
- package/dist/result-schema.js.map +1 -1
- package/dist/run-index.d.ts +4 -2
- package/dist/run-index.js +3 -1
- package/dist/run-index.js.map +1 -1
- package/dist/run-key-preflight.d.ts +2 -1
- package/dist/run-key-preflight.js +3 -2
- package/dist/run-key-preflight.js.map +1 -1
- package/dist/run-metadata.d.ts +29 -0
- package/dist/run-metadata.js +48 -0
- package/dist/run-metadata.js.map +1 -0
- package/dist/run-tags-cli.d.ts +14 -0
- package/dist/run-tags-cli.js +41 -0
- package/dist/run-tags-cli.js.map +1 -0
- package/dist/self-heal-adapter.d.ts +43 -27
- package/dist/self-heal-adapter.js +196 -62
- package/dist/self-heal-adapter.js.map +1 -1
- package/dist/site-cli.d.ts +1 -1
- package/dist/site-cli.js +24 -1
- package/dist/site-cli.js.map +1 -1
- package/dist/source-cli.js +9 -5
- package/dist/source-cli.js.map +1 -1
- package/dist/suite-explore-options.d.ts +14 -0
- package/dist/suite-explore-options.js +8 -0
- package/dist/suite-explore-options.js.map +1 -1
- package/dist/sweep-api.d.ts +289 -0
- package/dist/sweep-api.js +859 -0
- package/dist/sweep-api.js.map +1 -0
- package/dist/sweep-cli.d.ts +9 -0
- package/dist/sweep-cli.js +117 -0
- package/dist/sweep-cli.js.map +1 -0
- package/dist/target-config.d.ts +5 -2
- package/dist/target-config.js +15 -0
- package/dist/target-config.js.map +1 -1
- package/dist/ux-cli.js +3 -1
- package/dist/ux-cli.js.map +1 -1
- package/dist/ux-usability.d.ts +9 -3
- package/dist/ux-usability.js +8 -5
- package/dist/ux-usability.js.map +1 -1
- package/dist/verify-fix-cli.js +4 -2
- package/dist/verify-fix-cli.js.map +1 -1
- package/package.json +9 -9
- package/skills/jevitate-ci-check/SKILL.md +9 -1
- package/skills/jevitate-demo/SKILL.md +5 -2
- package/skills/jevitate-getting-started/SKILL.md +14 -1
- package/skills/jevitate-mission-scope/SKILL.md +2 -2
- package/skills/jevitate-run-journey/SKILL.md +42 -9
- package/skills/jevitate-test-campaign/SKILL.md +26 -5
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { redactUrl } from "@jevitate/ai-core";
|
|
2
|
+
import { normalizeAllowlist } from "@jevitate/explore";
|
|
3
|
+
import { PlaywrightBrowserPort } from "@jevitate/playwright";
|
|
4
|
+
import { fail, ok } from "./envelope.js";
|
|
5
|
+
import { emitCommandResult } from "./cli-shared.js";
|
|
6
|
+
import { positiveIntArg } from "./cli-args.js";
|
|
7
|
+
import { loadPersonasFile, MultiRunArgsError, projectPersonas } from "./multi-run.js";
|
|
8
|
+
import { apiVerifyUrl, checkSaveTarget, LoginArgsError, LoginFailedError, loginFromFlags, mintStorageState, parseAuthCheck } from "./persona-login.js";
|
|
9
|
+
const DEFAULT_TIMEOUT_S = 30;
|
|
10
|
+
const PERSONA_NAME = /^[A-Za-z0-9][A-Za-z0-9_.-]{0,63}$/;
|
|
11
|
+
function formatLoginHuman(data) {
|
|
12
|
+
const r = data;
|
|
13
|
+
return `signed in${r.persona === undefined ? "" : ` as persona ${r.persona}`}${r.method === "api" ? " through the API" : ""} (${r.userEnv}/${r.passwordEnv}) — storage state saved to ${r.saved} (mode 0600)\n`;
|
|
14
|
+
}
|
|
15
|
+
/** The persona's declared login parameters and session, from `--personas` or the project's `.jevitate/personas.json`. */
|
|
16
|
+
function declaredPersona(name, personasFile) {
|
|
17
|
+
const all = personasFile === undefined ? projectPersonas() : loadPersonasFile(personasFile);
|
|
18
|
+
return all.find((p) => p.name === name);
|
|
19
|
+
}
|
|
20
|
+
export function registerLoginCommand(program, deps) {
|
|
21
|
+
program
|
|
22
|
+
.command("login")
|
|
23
|
+
.description("#427: sign in as a persona with credentials from environment variables and save its Playwright storage state (mode 0600) — " +
|
|
24
|
+
"the session `explore --storage-state/--persona` starts from. Credentials are never accepted as values, never printed or recorded")
|
|
25
|
+
.option("--persona <name>", "the persona being signed in (names it in the result); with a declared persona (--personas or .jevitate/personas.json) its login parameters and storage state path are the defaults")
|
|
26
|
+
.option("--personas <file>", "personas JSON to read --persona's login parameters from (default: the project's .jevitate/personas.json)")
|
|
27
|
+
.option("--url <loginUrl>", "the sign-in page (must be an authorized origin: its own, or --allow)")
|
|
28
|
+
.option("--api <url>", "#449: sign in through this HTTP endpoint instead of a form: the credentials are POSTed as JSON (must be an authorized origin; redirects are never followed)")
|
|
29
|
+
.option("--api-user-key <key>", "with --api: the JSON body key the username is sent under (default username)")
|
|
30
|
+
.option("--api-password-key <key>", "with --api: the JSON body key the password is sent under (default password)")
|
|
31
|
+
.option("--token-path <path>", "with --api: a dotted path into the JSON response whose value is the session token (e.g. token, data.accessToken); without it the response's cookies are the session")
|
|
32
|
+
.option("--storage-key <key>", "with --token-path: the localStorage key the token is written under (default: the path's last segment)")
|
|
33
|
+
.option("--storage <where>", "with --token-path: local (the only choice — a Playwright storage state has no sessionStorage)")
|
|
34
|
+
.option("--verify-url <url>", "with --api: the app page the new session is proven on, and whose origin receives the token (default: the endpoint's origin root)")
|
|
35
|
+
.option("--auth-check <check>", "with --api: how --verify-url proves the session: off | auto | urlExcludes:<text> | selector:<css> (default auto)")
|
|
36
|
+
.option("--user-env <VAR>", "environment variable holding the username (its NAME — the value is read from the environment)")
|
|
37
|
+
.option("--password-env <VAR>", "environment variable holding the password (its NAME — the value is read from the environment)")
|
|
38
|
+
.option("--user-field <field>", "the username field: its label, else a CSS selector (default: found by autocomplete/type/name)")
|
|
39
|
+
.option("--password-field <field>", "the password field: its label, else a CSS selector (default: the visible password input)")
|
|
40
|
+
.option("--submit <name>", "the submit button's accessible name (default: the form's submit button, else Enter)")
|
|
41
|
+
.option("--success <check>", "how a successful sign-in is recognised: urlIncludes:<text> | selector:<css> | text:<text> (default: the page leaves the sign-in form — no login-like URL, no password field)")
|
|
42
|
+
.option("--save <file>", "where to write the storage state (parent directory created; mode 0600; never inside a repo's .jevitate/)")
|
|
43
|
+
.option("--allow <origin>", "an origin credentials may be typed into (repeatable; default: the sign-in page's own) — e.g. an SSO provider", (v, prev) => [...prev, v], [])
|
|
44
|
+
.option("--timeout <seconds>", `how long each step of the sign-in may take (default ${DEFAULT_TIMEOUT_S})`, positiveIntArg)
|
|
45
|
+
.option("--json", "emit a JSON envelope")
|
|
46
|
+
.action(async function () {
|
|
47
|
+
const o = this.opts();
|
|
48
|
+
const emit = (envelope) => emitCommandResult(program, envelope, { json: o.json === true, command: "login", human: formatLoginHuman });
|
|
49
|
+
let login;
|
|
50
|
+
let save;
|
|
51
|
+
let warnings;
|
|
52
|
+
let authCheck;
|
|
53
|
+
try {
|
|
54
|
+
if (o.persona !== undefined && !PERSONA_NAME.test(o.persona)) {
|
|
55
|
+
throw new LoginArgsError(`--persona ${JSON.stringify(o.persona)} must be 1-64 of [A-Za-z0-9_.-], starting alphanumeric`);
|
|
56
|
+
}
|
|
57
|
+
const declared = o.persona === undefined ? undefined : declaredPersona(o.persona, o.personas);
|
|
58
|
+
if (o.personas !== undefined && o.persona === undefined)
|
|
59
|
+
throw new LoginArgsError("--personas reads a declared persona's login parameters: pass --persona <name> too");
|
|
60
|
+
if (o.personas !== undefined && declared === undefined)
|
|
61
|
+
throw new LoginArgsError(`persona ${o.persona} is not declared in ${o.personas}`);
|
|
62
|
+
const base = declared?.login;
|
|
63
|
+
const apiFlags = [
|
|
64
|
+
["--api-user-key", o.apiUserKey],
|
|
65
|
+
["--api-password-key", o.apiPasswordKey],
|
|
66
|
+
["--token-path", o.tokenPath],
|
|
67
|
+
["--storage-key", o.storageKey],
|
|
68
|
+
["--storage", o.storage],
|
|
69
|
+
["--verify-url", o.verifyUrl],
|
|
70
|
+
["--auth-check", o.authCheck],
|
|
71
|
+
]
|
|
72
|
+
.filter(([, v]) => v !== undefined)
|
|
73
|
+
.map(([k]) => k);
|
|
74
|
+
if (o.api !== undefined && o.url !== undefined)
|
|
75
|
+
throw new LoginArgsError("--api and --url are two ways to sign in: pass one");
|
|
76
|
+
const viaApi = o.api !== undefined || (o.url === undefined && base?.api !== undefined);
|
|
77
|
+
if (!viaApi && apiFlags.length > 0)
|
|
78
|
+
throw new LoginArgsError(`${apiFlags.join(", ")} ${apiFlags.length === 1 ? "applies" : "apply"} to a sign-in through an HTTP endpoint: pass --api <url> too`);
|
|
79
|
+
authCheck = parseAuthCheck(o.authCheck);
|
|
80
|
+
const url = viaApi ? undefined : (o.url ?? base?.url);
|
|
81
|
+
const apiUrl = viaApi ? (o.api ?? base?.api?.url) : undefined;
|
|
82
|
+
const userEnv = o.userEnv ?? base?.userEnv;
|
|
83
|
+
const passwordEnv = o.passwordEnv ?? base?.passwordEnv;
|
|
84
|
+
const target = o.save ?? declared?.storageState;
|
|
85
|
+
const missing = [url === undefined && apiUrl === undefined ? "--url (or --api)" : null, userEnv === undefined ? "--user-env" : null, passwordEnv === undefined ? "--password-env" : null, target === undefined ? "--save" : null].filter((m) => m !== null);
|
|
86
|
+
if (missing.length > 0) {
|
|
87
|
+
throw new LoginArgsError(`missing ${missing.join(", ")}${o.persona === undefined ? "" : ` (persona ${o.persona} declares no login parameters for ${missing.length === 1 ? "it" : "them"})`}`);
|
|
88
|
+
}
|
|
89
|
+
const b = base?.api;
|
|
90
|
+
login = loginFromFlags({
|
|
91
|
+
...(url === undefined ? {} : { url }),
|
|
92
|
+
...(apiUrl === undefined
|
|
93
|
+
? {}
|
|
94
|
+
: {
|
|
95
|
+
api: {
|
|
96
|
+
url: apiUrl,
|
|
97
|
+
userKey: o.apiUserKey ?? b?.userKey,
|
|
98
|
+
passwordKey: o.apiPasswordKey ?? b?.passwordKey,
|
|
99
|
+
tokenPath: o.tokenPath ?? b?.tokenPath,
|
|
100
|
+
// A declared storage key belongs to the declared token path: a --token-path flag takes its own default.
|
|
101
|
+
storageKey: o.storageKey ?? (o.tokenPath === undefined ? b?.storageKey : undefined),
|
|
102
|
+
storage: o.storage,
|
|
103
|
+
verifyUrl: o.verifyUrl ?? b?.verifyUrl,
|
|
104
|
+
},
|
|
105
|
+
}),
|
|
106
|
+
userEnv: userEnv,
|
|
107
|
+
passwordEnv: passwordEnv,
|
|
108
|
+
...pick("userField", o.userField ?? (viaApi ? undefined : base?.userField)),
|
|
109
|
+
...pick("passwordField", o.passwordField ?? (viaApi ? undefined : base?.passwordField)),
|
|
110
|
+
...pick("submit", o.submit ?? (viaApi ? undefined : base?.submit)),
|
|
111
|
+
...pick("success", o.success ?? (viaApi ? undefined : base?.success)),
|
|
112
|
+
});
|
|
113
|
+
({ path: save, warnings } = checkSaveTarget(target, "--save"));
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
if (err instanceof LoginArgsError || err instanceof MultiRunArgsError) {
|
|
117
|
+
emit(fail("E_LOGIN_ARGS", err.message));
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
throw err;
|
|
121
|
+
}
|
|
122
|
+
const loginUrl = login.api?.url ?? login.url;
|
|
123
|
+
const allowlist = o.allow.length > 0 ? normalizeAllowlist(o.allow) : normalizeAllowlist([loginUrl]);
|
|
124
|
+
for (const w of warnings)
|
|
125
|
+
program.configureOutput().writeErr?.(`warning: ${w}\n`);
|
|
126
|
+
try {
|
|
127
|
+
const minted = await mintStorageState({
|
|
128
|
+
login,
|
|
129
|
+
save,
|
|
130
|
+
allowlist,
|
|
131
|
+
env: deps.explore?.env ?? process.env,
|
|
132
|
+
port: (deps.explore?.browserPortFactory ?? (() => new PlaywrightBrowserPort()))(),
|
|
133
|
+
timeoutMs: (o.timeout ?? DEFAULT_TIMEOUT_S) * 1000,
|
|
134
|
+
...(login.api === undefined ? {} : { verify: { url: apiVerifyUrl(login.api), check: authCheck } }),
|
|
135
|
+
});
|
|
136
|
+
const result = {
|
|
137
|
+
...(o.persona === undefined ? {} : { persona: o.persona }),
|
|
138
|
+
saved: minted.saved,
|
|
139
|
+
loginUrl: redactUrl(loginUrl),
|
|
140
|
+
method: login.api === undefined ? "form" : "api",
|
|
141
|
+
landedUrl: minted.landedUrl,
|
|
142
|
+
userEnv: login.userEnv,
|
|
143
|
+
passwordEnv: login.passwordEnv,
|
|
144
|
+
warnings,
|
|
145
|
+
};
|
|
146
|
+
emit(ok(result));
|
|
147
|
+
}
|
|
148
|
+
catch (err) {
|
|
149
|
+
if (err instanceof LoginArgsError)
|
|
150
|
+
emit(fail("E_LOGIN_ARGS", err.message));
|
|
151
|
+
else if (err instanceof LoginFailedError)
|
|
152
|
+
emit(fail("E_LOGIN_FAILED", err.message));
|
|
153
|
+
else
|
|
154
|
+
throw err;
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
function pick(k, v) {
|
|
159
|
+
return (v === undefined ? {} : { [k]: v });
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=login-cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login-cli.js","sourceRoot":"","sources":["../src/login-cli.ts"],"names":[],"mappings":"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"}
|
package/dist/logs-cli.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { JEV_PROVIDER_FLAG_HELP, jevProviderArg } from "./cli-shared.js";
|
|
1
2
|
import { ok, fail } from "./envelope.js";
|
|
2
3
|
import { LogsConfigError, loadLogsRetention, pruneLogs } from "./logs-retention.js";
|
|
3
4
|
import { logsRoot } from "./project-dir.js";
|
|
@@ -60,6 +61,7 @@ export function registerLogsCommands(program, deps) {
|
|
|
60
61
|
.option("--threshold <p>", "Jev relevance probability at or above which a line is kept (default 0.5)", (v) => Number(v))
|
|
61
62
|
.option("--real", "score relevance with the live Jev gateway (requires keys; log text goes to the judgment model, redacted)", false)
|
|
62
63
|
.option("--fake-ai", "no model: keep the correlated lines and the window's error/warning lines (code only)", false)
|
|
64
|
+
.option("--jev-provider <provider>", JEV_PROVIDER_FLAG_HELP, jevProviderArg)
|
|
63
65
|
.option("--json", "emit a JSON envelope")
|
|
64
66
|
.action(async function () {
|
|
65
67
|
const o = this.opts();
|
|
@@ -87,7 +89,7 @@ export function registerLogsCommands(program, deps) {
|
|
|
87
89
|
const file = JSON.parse(readFileSync(o.result, "utf8"));
|
|
88
90
|
if (typeof file.result !== "object" || file.result === null)
|
|
89
91
|
return emit(fail("E_LOGS_ARGS", `${o.result} is not a jevitate run result`));
|
|
90
|
-
const judge = o.real === true ? (await buildExploreGateways(deps, { real: true, fakeAi: false })).judge : undefined;
|
|
92
|
+
const judge = o.real === true ? (await buildExploreGateways(deps, { real: true, fakeAi: false, jevProvider: o.jevProvider })).judge : undefined;
|
|
91
93
|
const updated = await triageRunResult(file.result, o.result, {
|
|
92
94
|
secrets,
|
|
93
95
|
...(judge === undefined ? {} : { judge }),
|
package/dist/logs-cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logs-cli.js","sourceRoot":"","sources":["../src/logs-cli.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"logs-cli.js","sourceRoot":"","sources":["../src/logs-cli.ts"],"names":[],"mappings":"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"}
|
package/dist/mcp-api.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
|
2
2
|
import { type AiGenerateTextArgs, type AiGenerateTextResult } from "@jevitate/mcp-facade";
|
|
3
3
|
import { type CredentialStore, type GenerationPort, type SetupRequiredResult } from "@jevitate/ai-core";
|
|
4
4
|
import type { JudgmentPort, UsageTracker } from "@jevitate/ai-core";
|
|
5
|
-
import type { SelfHealer } from "@jevitate/runtime";
|
|
5
|
+
import type { ChangeScope, SelfHealer } from "@jevitate/runtime";
|
|
6
6
|
import type { EmulationSpec } from "@jevitate/playwright";
|
|
7
7
|
import { type RunPolicy } from "@jevitate/domain";
|
|
8
8
|
import { type RunVerifyFixOptions, type VerifyFixReport } from "./verify-fix-api.js";
|
|
@@ -46,6 +46,10 @@ export interface McpTool {
|
|
|
46
46
|
export interface McpJourneyRunOptions {
|
|
47
47
|
readonly policy?: RunPolicy;
|
|
48
48
|
readonly selfHealer?: SelfHealer;
|
|
49
|
+
/** #453: the change context a hybrid/full self-heal is explained by (`changes`/`changeNote`). */
|
|
50
|
+
readonly heal?: {
|
|
51
|
+
readonly scope: ChangeScope;
|
|
52
|
+
};
|
|
49
53
|
readonly environment?: ResolvedJourneyEnvironment;
|
|
50
54
|
readonly browser?: BrowserRunOptions;
|
|
51
55
|
readonly emulation?: EmulationSpec;
|
|
@@ -97,6 +101,7 @@ export interface McpApiDeps {
|
|
|
97
101
|
selfHealGateways?: (sel: {
|
|
98
102
|
real: boolean;
|
|
99
103
|
fakeAi: boolean;
|
|
104
|
+
jevProvider?: string | undefined;
|
|
100
105
|
}) => Promise<{
|
|
101
106
|
judge: JudgmentPort;
|
|
102
107
|
gen: GenerationPort;
|
package/dist/mcp-api.js
CHANGED
|
@@ -12,7 +12,8 @@ import { existsSync } from "node:fs";
|
|
|
12
12
|
import { access, readFile } from "node:fs/promises";
|
|
13
13
|
import { join } from "node:path";
|
|
14
14
|
import { ParamValidationError } from "@jevitate/journey";
|
|
15
|
-
import { safeRunPolicy as defaultRunPolicy } from "@jevitate/domain";
|
|
15
|
+
import { RunTagError, JOURNEY_RUN_OUTCOMES, journeyExitCode, safeRunPolicy as defaultRunPolicy, validateRunTags } from "@jevitate/domain";
|
|
16
|
+
import { stampRunMetadata, withRunMetadata } from "./run-metadata.js";
|
|
16
17
|
import { JourneyRequiresAuthError, UnknownJourneyError, runJourneyProgrammatically } from "./journey-api.js";
|
|
17
18
|
import { runVerifyFix } from "./verify-fix-api.js";
|
|
18
19
|
import { ExtensionMismatchError } from "./browser-run-options.js";
|
|
@@ -21,7 +22,9 @@ import { environmentFromFlags, isEnvironmentError } from "./environments.js";
|
|
|
21
22
|
import { buildMissionFixtures, checkSetupRefs } from "./fixture-cli.js";
|
|
22
23
|
import { FixtureSetupError, FixtureSpecError, UnboundSetupRefError } from "./mission-fixtures.js";
|
|
23
24
|
import { parseScreenshotsArg } from "./run-screenshots.js";
|
|
24
|
-
import {
|
|
25
|
+
import { makeEvidenceSelfHealer } from "./self-heal-adapter.js";
|
|
26
|
+
import { JourneyHealArgsError, MCP_HEAL_NAMES, journeyHealBudget, readJourneyChangeScope, validateJourneyHeal } from "./journey-heal.js";
|
|
27
|
+
import { ChangesArgsError, ChangesInputError } from "./change-context.js";
|
|
25
28
|
import { McpArgError, argErrorBody, optBool, optEnum, optInt, optNamedSessions, optPath, optExtensions, optRecordVideo, optScreenshots, optString, optStringArray, optStringMap, optViewport } from "./mcp-args.js";
|
|
26
29
|
import { defaultMcpPathRoots } from "./mcp-paths.js";
|
|
27
30
|
import { CLI_TOOL_SPECS, cliToolInputSchema, runCliTool } from "./mcp-cli-tools.js";
|
|
@@ -49,6 +52,15 @@ function assertAllowlisted(name) {
|
|
|
49
52
|
throw new Error(`refusing to serve non-allowlisted tool '${name}'`);
|
|
50
53
|
}
|
|
51
54
|
}
|
|
55
|
+
/** #453: a Journey run result with the CLI's exit code for its outcome (anything else unchanged). */
|
|
56
|
+
function withJourneyExitCode(result) {
|
|
57
|
+
if (result === null || typeof result !== "object")
|
|
58
|
+
return result;
|
|
59
|
+
const outcome = result.outcome;
|
|
60
|
+
if (typeof outcome !== "string" || !JOURNEY_RUN_OUTCOMES.includes(outcome))
|
|
61
|
+
return result;
|
|
62
|
+
return { ...result, exitCode: journeyExitCode(outcome) };
|
|
63
|
+
}
|
|
52
64
|
function jsonResult(value) {
|
|
53
65
|
return { content: [{ type: "text", text: JSON.stringify(value) }] };
|
|
54
66
|
}
|
|
@@ -64,6 +76,16 @@ function goalOutcomeOf(file) {
|
|
|
64
76
|
const result = file.result;
|
|
65
77
|
return result !== null && typeof result === "object" && "goalOutcome" in result ? result.goalOutcome : undefined;
|
|
66
78
|
}
|
|
79
|
+
/** #423: a persisted result's `defectOutcome.status` (`none`/`defects`), when present. */
|
|
80
|
+
function defectStatusOf(file) {
|
|
81
|
+
const outcome = resultField(file, "defectOutcome");
|
|
82
|
+
return outcome !== null && typeof outcome === "object" && "status" in outcome ? outcome.status : undefined;
|
|
83
|
+
}
|
|
84
|
+
/** One field of a persisted result's `result` object, else undefined. */
|
|
85
|
+
function resultField(file, key) {
|
|
86
|
+
const result = file.result;
|
|
87
|
+
return result !== null && typeof result === "object" && key in result ? result[key] : undefined;
|
|
88
|
+
}
|
|
67
89
|
/** A model-backed option was asked for without usable gateways/keys (typed `setup_required`). */
|
|
68
90
|
class SetupRequired extends Error {
|
|
69
91
|
}
|
|
@@ -99,6 +121,7 @@ export function buildMcpTools(deps) {
|
|
|
99
121
|
...(storageState !== undefined ? { storageState } : {}),
|
|
100
122
|
...(siteGate === undefined ? {} : { siteGate }),
|
|
101
123
|
...(o?.selfHealer === undefined ? {} : { selfHealer: o.selfHealer }),
|
|
124
|
+
...(o?.heal === undefined ? {} : { heal: o.heal }),
|
|
102
125
|
...(o?.environment === undefined ? {} : { environment: o.environment }),
|
|
103
126
|
...(o?.browser === undefined ? {} : { browser: o.browser }),
|
|
104
127
|
...(o?.emulation === undefined ? {} : { emulation: o.emulation }),
|
|
@@ -267,14 +290,21 @@ export function buildMcpTools(deps) {
|
|
|
267
290
|
}
|
|
268
291
|
// #217: `missionOutcome` is canonical; a goal run's own ending rides beside it as `goalOutcome`.
|
|
269
292
|
const parsedOutcome = parsed !== null && typeof parsed === "object" && "missionOutcome" in parsed
|
|
270
|
-
? parseResultOutcome(parsed.missionOutcome, goalOutcomeOf(parsed))
|
|
293
|
+
? parseResultOutcome(parsed.missionOutcome, goalOutcomeOf(parsed), defectStatusOf(parsed))
|
|
271
294
|
: null;
|
|
272
295
|
if (parsedOutcome === null) {
|
|
273
296
|
return errorResult({ error: "corrupt_result", ...ids });
|
|
274
297
|
}
|
|
298
|
+
// #423: the two orthogonal verdicts beside the status — did the goal get reached (goalOutcome +
|
|
299
|
+
// goalReason) and did the app break (defectOutcome, counted by kind) — read from the structured
|
|
300
|
+
// result, never from its `reason` prose.
|
|
301
|
+
const goalReason = resultField(parsed, "goalReason");
|
|
302
|
+
const defectOutcome = resultField(parsed, "defectOutcome");
|
|
275
303
|
const status = {
|
|
276
304
|
...missionStatus(parsedOutcome.outcome),
|
|
277
305
|
...(parsedOutcome.goalOutcome === undefined ? {} : { goalOutcome: parsedOutcome.goalOutcome }),
|
|
306
|
+
...(typeof goalReason === "string" ? { goalReason } : {}),
|
|
307
|
+
...(defectOutcome !== null && typeof defectOutcome === "object" ? { defectOutcome } : {}),
|
|
278
308
|
};
|
|
279
309
|
const result = parsed.result ?? null;
|
|
280
310
|
// An adversarial run's coverage is surfaced next to the status: an `inconclusive` run says what
|
|
@@ -345,6 +375,19 @@ export function buildMcpTools(deps) {
|
|
|
345
375
|
throw new McpArgError(err instanceof Error ? err.message : String(err));
|
|
346
376
|
}
|
|
347
377
|
};
|
|
378
|
+
/** #426: the run tools' `tags` object — validated like `--tag` (an invalid one is invalid_args, never dropped). */
|
|
379
|
+
const tagsArg = (args) => {
|
|
380
|
+
if (args.tags === undefined)
|
|
381
|
+
return { tags: {} };
|
|
382
|
+
try {
|
|
383
|
+
return { tags: validateRunTags(args.tags, "tags") };
|
|
384
|
+
}
|
|
385
|
+
catch (err) {
|
|
386
|
+
if (!(err instanceof RunTagError))
|
|
387
|
+
throw err;
|
|
388
|
+
return { error: { error: "invalid_args", code: err.code, message: err.message } };
|
|
389
|
+
}
|
|
390
|
+
};
|
|
348
391
|
const verifyFixTool = async (args) => {
|
|
349
392
|
if (!deps.recordingsDir) {
|
|
350
393
|
return errorResult({ error: "not_configured", message: "verify_fix requires recordingsDir" });
|
|
@@ -354,6 +397,9 @@ export function buildMcpTools(deps) {
|
|
|
354
397
|
!/^[0-9a-f]{16}$/.test(args.fingerprint)) {
|
|
355
398
|
return errorResult({ error: "invalid_args", message: "verify_fix requires a mission result 'id' (or missionId) and a 16-hex 'fingerprint'" });
|
|
356
399
|
}
|
|
400
|
+
const tagged = tagsArg(args);
|
|
401
|
+
if ("error" in tagged)
|
|
402
|
+
return errorResult(tagged.error);
|
|
357
403
|
let options;
|
|
358
404
|
try {
|
|
359
405
|
options = verifyFixOptions(args);
|
|
@@ -387,13 +433,14 @@ export function buildMcpTools(deps) {
|
|
|
387
433
|
}
|
|
388
434
|
}
|
|
389
435
|
try {
|
|
390
|
-
const
|
|
391
|
-
const
|
|
436
|
+
const fingerprint = args.fingerprint;
|
|
437
|
+
const report = await withRunMetadata({ tags: tagged.tags }, () => verifyFixImpl({ ...options, resultPath, fingerprint }));
|
|
438
|
+
const body = stampRunMetadata({
|
|
392
439
|
id: args.id,
|
|
393
440
|
...(ref.missionId === undefined ? {} : { missionId: ref.missionId, resultId: ref.resultId }),
|
|
394
441
|
status: report.verdict,
|
|
395
442
|
...report,
|
|
396
|
-
};
|
|
443
|
+
}, { tags: tagged.tags });
|
|
397
444
|
// Neither is a pass: `inconclusive` proved nothing either way, `intermittent` (#74) means the
|
|
398
445
|
// signal fired on SOME but not all fresh-context replays — never trustworthy as "fixed".
|
|
399
446
|
return report.verdict === "inconclusive" || report.verdict === "intermittent" ? errorResult(body) : jsonResult(body);
|
|
@@ -460,22 +507,44 @@ export function buildMcpTools(deps) {
|
|
|
460
507
|
const selfHeal = optEnum(args, "selfHeal", ["fail-closed", "hybrid", "full"]) ?? "fail-closed";
|
|
461
508
|
const real = optBool(args, "real") ?? false;
|
|
462
509
|
const fakeAi = optBool(args, "fakeAi") ?? false;
|
|
510
|
+
// #429: the Jev provider for self-heal judgments (typesafe | openrouter), as `--jev-provider`.
|
|
511
|
+
const jevProvider = optEnum(args, "jevProvider", ["typesafe", "openrouter"]);
|
|
512
|
+
// #453 Q1: the same refusals as `journey run` — a heal needs a change context, the change and
|
|
513
|
+
// budget arguments need a heal — before any gateway, Journey lookup or browser.
|
|
514
|
+
const changes = optString(args, "changes");
|
|
515
|
+
const healMaxAttempts = optInt(args, "healMaxAttempts", 1);
|
|
516
|
+
const healMaxModelCalls = optInt(args, "healMaxModelCalls", 1);
|
|
517
|
+
const healMaxMs = optInt(args, "healMaxMs", 1);
|
|
518
|
+
const healMaxRunAttempts = optInt(args, "healMaxRunAttempts", 1);
|
|
519
|
+
const healMaxRunMs = optInt(args, "healMaxRunMs", 1);
|
|
520
|
+
const healRequest = {
|
|
521
|
+
selfHeal,
|
|
522
|
+
...(changes === undefined ? {} : { changes }),
|
|
523
|
+
changeNotes: optStringArray(args, "changeNote") ?? [],
|
|
524
|
+
...(healMaxAttempts === undefined ? {} : { maxAttempts: healMaxAttempts }),
|
|
525
|
+
...(healMaxModelCalls === undefined ? {} : { maxModelCalls: healMaxModelCalls }),
|
|
526
|
+
...(healMaxMs === undefined ? {} : { maxMs: healMaxMs }),
|
|
527
|
+
...(healMaxRunAttempts === undefined ? {} : { maxRunAttempts: healMaxRunAttempts }),
|
|
528
|
+
...(healMaxRunMs === undefined ? {} : { maxRunMs: healMaxRunMs }),
|
|
529
|
+
};
|
|
530
|
+
validateJourneyHeal(healRequest, MCP_HEAL_NAMES);
|
|
531
|
+
const healScope = selfHeal === "fail-closed" ? undefined : await readJourneyChangeScope(healRequest, deps.journeysDir);
|
|
463
532
|
let selfHealer;
|
|
464
533
|
let policy = defaultRunPolicy();
|
|
465
534
|
let usage;
|
|
466
535
|
if (selfHeal !== "fail-closed") {
|
|
467
536
|
if (deps.selfHealGateways === undefined)
|
|
468
537
|
throw new SetupRequired("run_journey selfHeal needs the model gateways, which this server was not given");
|
|
469
|
-
|
|
538
|
+
// #453: the healer is evidence-only — its model is an advisory ranker; judgment never decides a heal.
|
|
470
539
|
let gen;
|
|
471
540
|
try {
|
|
472
|
-
({
|
|
541
|
+
({ gen, usage } = await deps.selfHealGateways({ real, fakeAi, ...(jevProvider === undefined ? {} : { jevProvider }) }));
|
|
473
542
|
}
|
|
474
543
|
catch (err) {
|
|
475
544
|
throw new SetupRequired(redactCredentials(err instanceof Error ? err.message : String(err), credentialStore));
|
|
476
545
|
}
|
|
477
|
-
selfHealer =
|
|
478
|
-
policy = { ...policy, selfHeal: { mode: selfHeal } };
|
|
546
|
+
selfHealer = makeEvidenceSelfHealer(gen, usage === undefined ? {} : { usage });
|
|
547
|
+
policy = { ...policy, selfHeal: { mode: selfHeal, budget: journeyHealBudget(healRequest) } };
|
|
479
548
|
}
|
|
480
549
|
return {
|
|
481
550
|
params,
|
|
@@ -484,6 +553,7 @@ export function buildMcpTools(deps) {
|
|
|
484
553
|
policy,
|
|
485
554
|
fixtures,
|
|
486
555
|
...(selfHealer === undefined ? {} : { selfHealer }),
|
|
556
|
+
...(healScope === undefined ? {} : { heal: { scope: healScope } }),
|
|
487
557
|
...(environment === undefined ? {} : { environment }),
|
|
488
558
|
...(browser === undefined ? {} : { browser }),
|
|
489
559
|
...(emulation === undefined ? {} : { emulation }),
|
|
@@ -498,7 +568,7 @@ export function buildMcpTools(deps) {
|
|
|
498
568
|
description: "Replay a finding's reproduction (by mission result id — or a finished queue_exploration missionId — + fingerprint) N times in fresh browsers (default 3) — `jevitate verify-fix`. status: fixed (signal absent on every replay) | still-reproduces | intermittent (fired on some but not all replays — never a pass) | inconclusive (replay could not reach the step — never a pass). " +
|
|
499
569
|
"#255 (same as the CLI flags): 'replays' (>= 1); 'recordVideo' (true or a directory: the before/after evidence pair — `evidence.before` is the run's own clip, `evidence.after` a captioned replay — plus videoPaths); 'screenshots'; 'headed'/'slowMo'; " +
|
|
500
570
|
"'storageState' (a path inside the project or ~/.jevitate, never a repo's .jevitate/; overrides the mission's session); 'viewport' {width,height} or 'device' (refused when it differs from the finding's recorded emulation unless 'allowEmulationOverride'); 'geolocation' '<lat>,<lng>[,<accuracy m>]' (#329); " +
|
|
501
|
-
"'invariants' (invariant file paths re-checking a declared-invariant defect); 'fixtures' (a fixtures file overriding the mission's saved one); 'fixtureIdentity' (#243: 'name=<storageState path>' entries re-binding a fixture step's auth.identity; default: the identities the mission recorded); 'extension' (#256: unpacked extension directories — refused unless the same build the finding was recorded with); 'actionDeltas' (#303, opt-in: the defect step's replayed delta vs the recorded one, as evidence on each attempt); 'maxBrowsers'/'maxBrowserMemory' (#205: machine-wide browser cap, browser memory ceiling in MiB). Operator-only settings (shell hooks, cmd: log sources, re-sending paid/destructive hang writes) come from targets.json, never an argument.",
|
|
571
|
+
"'invariants' (invariant file paths re-checking a declared-invariant defect); 'fixtures' (a fixtures file overriding the mission's saved one); 'fixtureIdentity' (#243: 'name=<storageState path>' entries re-binding a fixture step's auth.identity; default: the identities the mission recorded); 'extension' (#256: unpacked extension directories — refused unless the same build the finding was recorded with); 'actionDeltas' (#303, opt-in: the defect step's replayed delta vs the recorded one, as evidence on each attempt); 'maxBrowsers'/'maxBrowserMemory' (#205: machine-wide browser cap, browser memory ceiling in MiB); 'tags' (#426: {key: value} run metadata, returned on the result — never a secret). Operator-only settings (shell hooks, cmd: log sources, re-sending paid/destructive hang writes) come from targets.json, never an argument.",
|
|
502
572
|
inputSchema: {
|
|
503
573
|
type: "object",
|
|
504
574
|
properties: {
|
|
@@ -521,6 +591,7 @@ export function buildMcpTools(deps) {
|
|
|
521
591
|
extension: { type: "array", items: { type: "string" } },
|
|
522
592
|
maxBrowsers: { type: "integer", minimum: 1 },
|
|
523
593
|
maxBrowserMemory: { type: "integer", minimum: 1 },
|
|
594
|
+
tags: { type: "object", additionalProperties: { type: "string" } },
|
|
524
595
|
},
|
|
525
596
|
required: ["id", "fingerprint"],
|
|
526
597
|
},
|
|
@@ -544,7 +615,7 @@ export function buildMcpTools(deps) {
|
|
|
544
615
|
"with a clear error when no storageState is given. #255 (same as the CLI flags): 'env' (a named environment in .jevitate/environments.json; its session from ~/.jevitate/targets.json) and/or 'baseUrl'; " +
|
|
545
616
|
"'headed' (needs a display) and 'slowMo'; 'recordVideo' (true, or a directory) → videoPaths; 'screenshots' (true | screens | steps | mode:<dir> | <dir>) → screenshotPaths; " +
|
|
546
617
|
"'viewport' {width,height} or 'device' (mutually exclusive); 'geolocation' '<lat>,<lng>[,<accuracy m>]' (#329); 'fixtures' (a fixtures JSON path: setup before, restore after; 'fixtureIdentity' (#243) 'name=<storageState path>' entries name who a step with auth.identity authenticates as; an environment's shell hooks are never run over MCP — they refuse as the CLI does without --allow-shell-hooks); " +
|
|
547
|
-
"'extension' (#256: unpacked extension directories inside the project or ~/.jevitate; a Journey recorded with extensions needs the same build); 'selfHeal' fail-closed (default) | hybrid | full with 'real' or 'fakeAi' (a write step never self-heals); 'actionDeltas' (#303, opt-in: each replayed step's action delta, compared with the recorded one → actionDeltas); 'maxBrowsers'/'maxBrowserMemory' (#205: machine-wide browser cap, browser memory ceiling in MiB). A site-policy refusal is {error: throttled, retryAfter}.",
|
|
618
|
+
"'extension' (#256: unpacked extension directories inside the project or ~/.jevitate; a Journey recorded with extensions needs the same build); 'selfHeal' fail-closed (default) | hybrid | full with 'real' or 'fakeAi' (a write step never self-heals; 'jevProvider' typesafe | openrouter picks the Jev key with real, #429) — #453: a heal mode needs a change context, 'changes' (a git range such as HEAD~1..HEAD, read-only) and/or 'changeNote' (strings), else it is refused; only a break that change explains is retargeted, one-for-one, and the run ends healed-pending-review (exitCode 5: a proposed revision a person accepts, never a pass); budgets 'healMaxAttempts'/'healMaxModelCalls'/'healMaxMs' (per broken step) and 'healMaxRunAttempts'/'healMaxRunMs' (per run), each >= 1; the result's 'exitCode' is the CLI's (0 ok, 5 pending review, 1 failed); 'actionDeltas' (#303, opt-in: each replayed step's action delta, compared with the recorded one → actionDeltas); 'maxBrowsers'/'maxBrowserMemory' (#205: machine-wide browser cap, browser memory ceiling in MiB); 'tags' (#426: {key: value} run metadata, returned on the result — never a secret). A site-policy refusal is {error: throttled, retryAfter}.",
|
|
548
619
|
inputSchema: {
|
|
549
620
|
type: "object",
|
|
550
621
|
properties: {
|
|
@@ -563,12 +634,21 @@ export function buildMcpTools(deps) {
|
|
|
563
634
|
fixtures: { type: "string" },
|
|
564
635
|
fixtureIdentity: { type: "array", items: { type: "string" } },
|
|
565
636
|
selfHeal: { type: "string", enum: ["fail-closed", "hybrid", "full"] },
|
|
637
|
+
changes: { type: "string" },
|
|
638
|
+
changeNote: { type: "array", items: { type: "string" } },
|
|
639
|
+
healMaxAttempts: { type: "integer", minimum: 1 },
|
|
640
|
+
healMaxModelCalls: { type: "integer", minimum: 1 },
|
|
641
|
+
healMaxMs: { type: "integer", minimum: 1 },
|
|
642
|
+
healMaxRunAttempts: { type: "integer", minimum: 1 },
|
|
643
|
+
healMaxRunMs: { type: "integer", minimum: 1 },
|
|
566
644
|
real: { type: "boolean" },
|
|
567
645
|
fakeAi: { type: "boolean" },
|
|
646
|
+
jevProvider: { type: "string", enum: ["typesafe", "openrouter"] },
|
|
568
647
|
extension: { type: "array", items: { type: "string" } },
|
|
569
648
|
maxBrowsers: { type: "integer", minimum: 1 },
|
|
570
649
|
maxBrowserMemory: { type: "integer", minimum: 1 },
|
|
571
650
|
actionDeltas: { type: "boolean" },
|
|
651
|
+
tags: { type: "object", additionalProperties: { type: "string" } },
|
|
572
652
|
},
|
|
573
653
|
required: ["id"],
|
|
574
654
|
},
|
|
@@ -576,6 +656,9 @@ export function buildMcpTools(deps) {
|
|
|
576
656
|
if (typeof args.id !== "string" || args.id.length === 0) {
|
|
577
657
|
return errorResult({ error: "invalid_args", message: "run_journey requires a non-empty string 'id'" });
|
|
578
658
|
}
|
|
659
|
+
const tagged = tagsArg(args);
|
|
660
|
+
if ("error" in tagged)
|
|
661
|
+
return errorResult(tagged.error);
|
|
579
662
|
// Invariant #5: only id + params (+ a storageState PATH and the run options below) are
|
|
580
663
|
// threaded through — any inline `steps`/`recording` in the arguments is deliberately ignored.
|
|
581
664
|
let resolved;
|
|
@@ -586,6 +669,9 @@ export function buildMcpTools(deps) {
|
|
|
586
669
|
const body = argErrorBody(err) ?? (isEnvironmentError(err) ? { error: "invalid_args", code: err.code, message: err.message } : undefined);
|
|
587
670
|
if (body !== undefined)
|
|
588
671
|
return errorResult(body);
|
|
672
|
+
if (err instanceof JourneyHealArgsError || err instanceof ChangesArgsError || err instanceof ChangesInputError) {
|
|
673
|
+
return errorResult({ error: "invalid_args", code: err.code, message: err.message });
|
|
674
|
+
}
|
|
589
675
|
if (err instanceof SetupRequired)
|
|
590
676
|
return errorResult({ error: "setup_required", message: err.message });
|
|
591
677
|
throw err;
|
|
@@ -595,9 +681,12 @@ export function buildMcpTools(deps) {
|
|
|
595
681
|
if (starved !== null)
|
|
596
682
|
return errorResult({ error: "refused", code: starved.error?.code, message: starved.error?.message });
|
|
597
683
|
try {
|
|
598
|
-
const
|
|
599
|
-
|
|
600
|
-
|
|
684
|
+
const id = args.id;
|
|
685
|
+
const result = await withRunMetadata({ tags: tagged.tags }, () => runJourney(id, resolved.params, resolved.storageState, resolved.options));
|
|
686
|
+
// #163: a self-healing run's model usage lands on its result, as on the CLI. #426: so do its tags.
|
|
687
|
+
const withUsage = resolved.usage === undefined || result === null || typeof result !== "object" ? result : { ...result, usage: resolved.usage.snapshot() };
|
|
688
|
+
// #453: the CLI's exit code for the outcome — 0 ok, 5 healed-pending-review (a proposed revision, never a pass), 1 otherwise.
|
|
689
|
+
return jsonResult(stampRunMetadata(withJourneyExitCode(withUsage), { tags: tagged.tags }));
|
|
601
690
|
}
|
|
602
691
|
catch (err) {
|
|
603
692
|
// A site-policy refusal (throttle, budget, quiet hours) is an answer the agent acts on — when to retry.
|
|
@@ -624,7 +713,7 @@ export function buildMcpTools(deps) {
|
|
|
624
713
|
},
|
|
625
714
|
},
|
|
626
715
|
queue_exploration: {
|
|
627
|
-
description: "Enqueue an exploration mission against a PROMOTED target. Never runs anything — only queues; `jevitate mission run` drains the queue, and get_mission_result {id: missionId} reports its status/result. strategy: goal-based (goal|feature|route + successAssertion) | coverage | exploratory (novelty-first coverage) | adversarial (optional in-scope route glob) | feature (feature name, optional route glob); a usability review is not queueable — use run_exploration {strategy: usability}. The target's authorized origin plus its declared apiOrigins are the only reachable origins. Refuses unknown/unpromoted targets, over-ceiling budgets and invalid declared `invariants` (an optional closed spec checked around every action; probes GET/HEAD on the target origin only). Optional 'viewport' ({width,height}) or 'device' (a Playwright devices registry name, e.g. \"iPhone 13\") — mutually exclusive (#149); default: Playwright's own default viewport. An unknown device is refused before any browser opens. #255: 'recordVideo' / 'evidenceVideo' (booleans) and 'screenshots' (screens | steps) write media next to the result (listed in it) — a queued request never names a path; 'persona' names a persona in the operator's ~/.jevitate/targets.json for the target's origin (its session, never the caller's). Same as `jevitate mission queue`.",
|
|
716
|
+
description: "Enqueue an exploration mission against a PROMOTED target. Never runs anything — only queues; `jevitate mission run` drains the queue, and get_mission_result {id: missionId} reports its status/result. strategy: goal-based (goal|feature|route + successAssertion) | coverage | exploratory (novelty-first coverage) | adversarial (optional in-scope route glob) | feature (feature name, optional route glob); a usability review is not queueable — use run_exploration {strategy: usability}. The target's authorized origin plus its declared apiOrigins are the only reachable origins. Refuses unknown/unpromoted targets, over-ceiling budgets and invalid declared `invariants` (an optional closed spec checked around every action; probes GET/HEAD on the target origin only). Optional 'viewport' ({width,height}) or 'device' (a Playwright devices registry name, e.g. \"iPhone 13\") — mutually exclusive (#149); default: Playwright's own default viewport. An unknown device is refused before any browser opens. #255: 'recordVideo' / 'evidenceVideo' (booleans) and 'screenshots' (screens | steps) write media next to the result (listed in it) — a queued request never names a path; 'persona' names a persona in the operator's ~/.jevitate/targets.json for the target's origin (its session, never the caller's). #424: 'minEffort' {minActions, minDistinctStates} (goal-based only) — the minimum exploration before the model may conclude, capped by the budget. Same as `jevitate mission queue`.",
|
|
628
717
|
inputSchema: {
|
|
629
718
|
type: "object",
|
|
630
719
|
properties: {
|
|
@@ -658,6 +747,11 @@ export function buildMcpTools(deps) {
|
|
|
658
747
|
screenshots: { type: "string", enum: [...QUEUED_SCREENSHOT_MODES] },
|
|
659
748
|
evidenceVideo: { type: "boolean" },
|
|
660
749
|
persona: { type: "string" },
|
|
750
|
+
// #424 (goal-based only): the minimum exploration effort before the model may conclude.
|
|
751
|
+
minEffort: {
|
|
752
|
+
type: "object",
|
|
753
|
+
properties: { minActions: { type: "number" }, minDistinctStates: { type: "number" } },
|
|
754
|
+
},
|
|
661
755
|
},
|
|
662
756
|
required: ["target"],
|
|
663
757
|
},
|