jevctl 0.1.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.
Files changed (63) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/LICENSE +21 -0
  3. package/NOTICE +5 -0
  4. package/README.md +430 -0
  5. package/SECURITY.md +21 -0
  6. package/dist/cli.d.ts +4 -0
  7. package/dist/cli.js +78 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/commands/ask.d.ts +15 -0
  10. package/dist/commands/ask.js +96 -0
  11. package/dist/commands/ask.js.map +1 -0
  12. package/dist/commands/config.d.ts +13 -0
  13. package/dist/commands/config.js +125 -0
  14. package/dist/commands/config.js.map +1 -0
  15. package/dist/commands/find.d.ts +16 -0
  16. package/dist/commands/find.js +97 -0
  17. package/dist/commands/find.js.map +1 -0
  18. package/dist/commands/models.d.ts +4 -0
  19. package/dist/commands/models.js +35 -0
  20. package/dist/commands/models.js.map +1 -0
  21. package/dist/commands/screen.d.ts +13 -0
  22. package/dist/commands/screen.js +64 -0
  23. package/dist/commands/screen.js.map +1 -0
  24. package/dist/commands/verify.d.ts +18 -0
  25. package/dist/commands/verify.js +97 -0
  26. package/dist/commands/verify.js.map +1 -0
  27. package/dist/config.d.ts +81 -0
  28. package/dist/config.js +147 -0
  29. package/dist/config.js.map +1 -0
  30. package/dist/context.d.ts +29 -0
  31. package/dist/context.js +54 -0
  32. package/dist/context.js.map +1 -0
  33. package/dist/core/ask.d.ts +59 -0
  34. package/dist/core/ask.js +103 -0
  35. package/dist/core/ask.js.map +1 -0
  36. package/dist/core/find.d.ts +48 -0
  37. package/dist/core/find.js +50 -0
  38. package/dist/core/find.js.map +1 -0
  39. package/dist/core/screen.d.ts +38 -0
  40. package/dist/core/screen.js +55 -0
  41. package/dist/core/screen.js.map +1 -0
  42. package/dist/core/verify.d.ts +55 -0
  43. package/dist/core/verify.js +74 -0
  44. package/dist/core/verify.js.map +1 -0
  45. package/dist/errors.d.ts +16 -0
  46. package/dist/errors.js +29 -0
  47. package/dist/errors.js.map +1 -0
  48. package/dist/index.d.ts +8 -0
  49. package/dist/index.js +12 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/input.d.ts +34 -0
  52. package/dist/input.js +116 -0
  53. package/dist/input.js.map +1 -0
  54. package/dist/lib.d.ts +63 -0
  55. package/dist/lib.js +123 -0
  56. package/dist/lib.js.map +1 -0
  57. package/dist/output.d.ts +26 -0
  58. package/dist/output.js +59 -0
  59. package/dist/output.js.map +1 -0
  60. package/dist/provider.d.ts +30 -0
  61. package/dist/provider.js +157 -0
  62. package/dist/provider.js.map +1 -0
  63. package/package.json +78 -0
@@ -0,0 +1,96 @@
1
+ import { parseQuestions, questionsFromFlags, runAsk, } from "../core/ask.js";
2
+ import { CliError, EXIT } from "../errors.js";
3
+ import { parseJson, readInput, readStdin } from "../input.js";
4
+ import { emit, formatProbability, paint, usageLine } from "../output.js";
5
+ export function resolveState(positional, flags) {
6
+ let raw;
7
+ if (positional !== undefined)
8
+ raw = readInput(positional, "state");
9
+ else if (!process.stdin.isTTY)
10
+ raw = readStdin("state");
11
+ else
12
+ throw new CliError("Provide state as an argument, @file, or pipe it on stdin.");
13
+ return flags.stateJson ? parseJson(raw, "state") : raw;
14
+ }
15
+ export function resolveQuestions(flags) {
16
+ const fromFlags = (flags.noul?.length ?? 0) + (flags.choice?.length ?? 0) + (flags.score?.length ?? 0) > 0;
17
+ if (flags.questions && fromFlags) {
18
+ throw new CliError("Use either --questions or the --noul/--choice/--score shorthands, not both.");
19
+ }
20
+ try {
21
+ if (flags.questions)
22
+ return parseQuestions(parseJson(readInput(flags.questions, "questions"), "questions"));
23
+ if (fromFlags)
24
+ return questionsFromFlags(flags);
25
+ }
26
+ catch (err) {
27
+ if (err instanceof CliError)
28
+ throw err;
29
+ throw new CliError(err.message);
30
+ }
31
+ throw new CliError("Provide questions with --questions <ref> or one or more --noul/--choice/--score flags.");
32
+ }
33
+ export async function askAction(positional, flags, ctx) {
34
+ const state = resolveState(positional, flags);
35
+ const questions = resolveQuestions(flags);
36
+ if (ctx.dryRun) {
37
+ emit({ ...ctx.output, format: "json" }, { model: ctx.config.model, state, questions }, () => "");
38
+ return EXIT.OK;
39
+ }
40
+ const output = await runAsk(ctx.ask(), { state, questions });
41
+ emit(ctx.output, output, () => renderAsk(output, ctx));
42
+ return EXIT.OK;
43
+ }
44
+ export function renderAsk(out, ctx) {
45
+ const c = ctx.output.color;
46
+ const lines = [];
47
+ for (const [id, answer] of Object.entries(out.answers)) {
48
+ const a = answer;
49
+ if (a?.type === "noul") {
50
+ lines.push(`${paint(c, "bold", id)}: ${formatProbability(a.noul)}`);
51
+ }
52
+ else if (a?.type === "choice") {
53
+ const dist = Object.entries(a.probabilities ?? {})
54
+ .sort(([, x], [, y]) => y - x)
55
+ .map(([k, v]) => `${k} ${formatProbability(v)}`)
56
+ .join(", ");
57
+ lines.push(`${paint(c, "bold", id)}: ${paint(c, "green", String(a.choice))} conf ${formatProbability(a.confidence)} [${dist}]`);
58
+ }
59
+ else if (a?.type === "score") {
60
+ const levels = Object.entries(a.probabilities ?? {})
61
+ .map(([k, v]) => `${k} ${formatProbability(v)}`)
62
+ .join(", ");
63
+ lines.push(`${paint(c, "bold", id)}: ${paint(c, "green", Number(a.score).toFixed(2))} conf ${formatProbability(a.confidence)} [${levels}]`);
64
+ }
65
+ else {
66
+ lines.push(`${paint(c, "bold", id)}: ${JSON.stringify(answer)}`);
67
+ }
68
+ }
69
+ if (!ctx.output.quiet)
70
+ lines.push(paint(c, "dim", usageLine(out.usage, out.model, out.provider)));
71
+ return lines.join("\n");
72
+ }
73
+ export function registerAsk(program, run) {
74
+ program
75
+ .command("ask")
76
+ .description("Ask raw System One questions (noul, choice, score) about any state. Answers come back typed.")
77
+ .argument("[state]", "state text, @file, or - for stdin (default: stdin)")
78
+ .option("--state-json", "parse the state as JSON instead of treating it as text")
79
+ .option("-q, --questions <ref>", "JSON questions map (@file or -), same shape as the TypeSafe API")
80
+ .option("--noul <id=instructions>", "yes/no question (repeatable)", collect, [])
81
+ .option("--choice <id=instructions|a,b:desc,c>", "pick-one question with options (repeatable)", collect, [])
82
+ .option("--score <id=instructions|low,mid,high>", "ordered rubric question (repeatable)", collect, [])
83
+ .addHelpText("after", `
84
+ Examples:
85
+ jev ask "I was charged twice, fix it now" --noul urgent="Does this convey urgency?"
86
+ jev ask @ticket.txt --choice team="Which team handles this?|billing:refunds and invoices,technical:bugs,sales"
87
+ jev ask @review.txt --score tone="How harsh is the tone?|gentle,direct,harsh"
88
+ jev ask @record.json --state-json --questions @questions.json --json`)
89
+ .action(async (state, flags, cmd) => {
90
+ await run((ctx) => askAction(state, flags, ctx), cmd);
91
+ });
92
+ }
93
+ function collect(value, previous) {
94
+ return [...previous, value];
95
+ }
96
+ //# sourceMappingURL=ask.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ask.js","sourceRoot":"","sources":["../../src/commands/ask.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { Command } from "commander";
2
+ import type { CommandContext } from "../context.js";
3
+ /** Mask a secret to its first four and last two characters. */
4
+ export declare function mask(secret: string | undefined): string | null;
5
+ export declare function credentialReport(env: NodeJS.ProcessEnv): {
6
+ TYPESAFE_API_KEY: string | null;
7
+ OPENROUTER_API_KEY: string | null;
8
+ CLOUDFLARE_API_TOKEN: string | null;
9
+ CLOUDFLARE_ACCOUNT_ID: string | null;
10
+ TYPESAFE_BASE_URL: string | null;
11
+ };
12
+ export declare function configShow(ctx: CommandContext, env: NodeJS.ProcessEnv): Promise<number>;
13
+ export declare function registerConfig(program: Command, run: (fn: (ctx: CommandContext) => Promise<number>, cmd: Command) => Promise<void>): void;
@@ -0,0 +1,125 @@
1
+ import { existsSync, unlinkSync } from "node:fs";
2
+ import { configPath, DEFAULT_CONFIG, readConfigFile, setConfigValue, writeConfigFile } from "../config.js";
3
+ import { CliError, EXIT } from "../errors.js";
4
+ import { emit, paint, table } from "../output.js";
5
+ import { resolveProvider } from "../provider.js";
6
+ /** Mask a secret to its first four and last two characters. */
7
+ export function mask(secret) {
8
+ if (!secret)
9
+ return null;
10
+ if (secret.length <= 8)
11
+ return "*".repeat(secret.length);
12
+ return `${secret.slice(0, 4)}…${secret.slice(-2)}`;
13
+ }
14
+ export function credentialReport(env) {
15
+ return {
16
+ TYPESAFE_API_KEY: mask(env.TYPESAFE_API_KEY),
17
+ OPENROUTER_API_KEY: mask(env.OPENROUTER_API_KEY),
18
+ CLOUDFLARE_API_TOKEN: mask(env.JEV_CLOUDFLARE_API_TOKEN || env.CLOUDFLARE_API_TOKEN),
19
+ CLOUDFLARE_ACCOUNT_ID: mask(env.CLOUDFLARE_ACCOUNT_ID),
20
+ TYPESAFE_BASE_URL: env.TYPESAFE_BASE_URL ?? null,
21
+ };
22
+ }
23
+ export async function configShow(ctx, env) {
24
+ const path = configPath(env);
25
+ let resolved = null;
26
+ let problem = null;
27
+ try {
28
+ resolved = resolveProvider(env, ctx.config.provider);
29
+ }
30
+ catch (err) {
31
+ problem = err.message;
32
+ }
33
+ const payload = {
34
+ config_file: path,
35
+ config_file_exists: existsSync(path),
36
+ config: ctx.config,
37
+ credentials: credentialReport(env),
38
+ resolved_provider: resolved,
39
+ problem,
40
+ };
41
+ emit(ctx.output, payload, () => {
42
+ const c = ctx.output.color;
43
+ const rows = [
44
+ ["Key", "Value"],
45
+ ["config file", `${path}${payload.config_file_exists ? "" : paint(c, "dim", " (not present)")}`],
46
+ ["provider", `${ctx.config.provider}${resolved ? paint(c, "dim", ` → ${resolved}`) : ""}`],
47
+ ["model", ctx.config.model],
48
+ ["timeoutMs", String(ctx.config.timeoutMs)],
49
+ ["format", ctx.config.format],
50
+ ["verify.autoAccept", String(ctx.config.verify.autoAccept)],
51
+ ["screen.blockAt / reviewAt", `${ctx.config.screen.blockAt} / ${ctx.config.screen.reviewAt}`],
52
+ [
53
+ "find.topK / found / absent",
54
+ `${ctx.config.find.topK} / ${ctx.config.find.found} / ${ctx.config.find.absent}`,
55
+ ],
56
+ ];
57
+ for (const [k, v] of Object.entries(payload.credentials))
58
+ rows.push([k, v ?? paint(c, "dim", "unset")]);
59
+ const lines = [table(rows, { color: c })];
60
+ if (problem)
61
+ lines.push("", paint(c, "yellow", problem));
62
+ return lines.join("\n");
63
+ });
64
+ return problem ? EXIT.ERROR : EXIT.OK;
65
+ }
66
+ export function registerConfig(program, run) {
67
+ const config = program.command("config").description("Show or edit the jev configuration file.");
68
+ config
69
+ .command("show", { isDefault: true })
70
+ .description("Show the effective configuration, detected credentials (masked), and the resolved provider.")
71
+ .action(async (_flags, cmd) => {
72
+ await run((ctx) => configShow(ctx, process.env), cmd);
73
+ });
74
+ config
75
+ .command("path")
76
+ .description("Print the config file path.")
77
+ .action(() => {
78
+ process.stdout.write(`${configPath(process.env)}\n`);
79
+ });
80
+ config
81
+ .command("set")
82
+ .description("Set a value, e.g. `jev config set model jev-1.13.0` or `jev config set screen.blockAt 0.6`.")
83
+ .argument("<key>", "dotted key: provider, model, timeoutMs, format, verify.autoAccept, screen.blockAt, ...")
84
+ .argument("<value>", "value to set")
85
+ .action((key, value) => {
86
+ const path = configPath(process.env);
87
+ const next = setConfigValue(readConfigFile(path), key, value);
88
+ writeConfigFile(path, next);
89
+ process.stdout.write(`Set ${key} in ${path}\n`);
90
+ });
91
+ config
92
+ .command("unset")
93
+ .description("Remove a top-level key from the config file.")
94
+ .argument("<key>", "top-level key to remove")
95
+ .action((key) => {
96
+ const path = configPath(process.env);
97
+ const current = readConfigFile(path);
98
+ if (!(key in current))
99
+ throw new CliError(`${key} is not set in ${path}.`);
100
+ delete current[key];
101
+ writeConfigFile(path, current);
102
+ process.stdout.write(`Removed ${key} from ${path}\n`);
103
+ });
104
+ config
105
+ .command("init")
106
+ .description("Write a config file with the default values (does not overwrite an existing file).")
107
+ .action(() => {
108
+ const path = configPath(process.env);
109
+ if (existsSync(path))
110
+ throw new CliError(`${path} already exists. Edit it or use \`jev config set\`.`);
111
+ writeConfigFile(path, DEFAULT_CONFIG);
112
+ process.stdout.write(`Wrote defaults to ${path}\n`);
113
+ });
114
+ config
115
+ .command("reset")
116
+ .description("Delete the config file.")
117
+ .action(() => {
118
+ const path = configPath(process.env);
119
+ if (!existsSync(path))
120
+ throw new CliError(`${path} does not exist.`);
121
+ unlinkSync(path);
122
+ process.stdout.write(`Deleted ${path}\n`);
123
+ });
124
+ }
125
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { Command } from "commander";
2
+ import type { CommandContext } from "../context.js";
3
+ import { type CandidateInput, type FindOutput } from "../core/find.js";
4
+ export interface FindFlags {
5
+ candidates?: string;
6
+ files?: string[];
7
+ lines?: string;
8
+ topK?: string;
9
+ found?: string;
10
+ absent?: string;
11
+ failOn?: string;
12
+ }
13
+ export declare function collectCandidates(flags: FindFlags): CandidateInput[];
14
+ export declare function findAction(query: string, flags: FindFlags, ctx: CommandContext): Promise<number>;
15
+ export declare function renderFind(out: FindOutput, ctx: CommandContext): string;
16
+ export declare function registerFind(program: Command, run: (fn: (ctx: CommandContext) => Promise<number>, cmd: Command) => Promise<void>): void;
@@ -0,0 +1,97 @@
1
+ import { statSync } from "node:fs";
2
+ import { buildFindRequest, FIND_FAIL_CONDITIONS, findFailed, runFind, } from "../core/find.js";
3
+ import { CliError, EXIT } from "../errors.js";
4
+ import { nonEmptyLines, parseItems, readFile, readInput } from "../input.js";
5
+ import { MAX_CANDIDATES, parseFailOn, parseProbability } from "../lib.js";
6
+ import { clip, emit, formatProbability, paint, table, usageLine } from "../output.js";
7
+ export function collectCandidates(flags) {
8
+ const items = [];
9
+ if (flags.candidates)
10
+ items.push(...parseItems(readInput(flags.candidates, "candidates"), "candidates"));
11
+ for (const path of flags.files ?? []) {
12
+ let isDir = false;
13
+ try {
14
+ isDir = statSync(path).isDirectory();
15
+ }
16
+ catch (err) {
17
+ throw new CliError(`Cannot read file ${path}: ${err.message}`);
18
+ }
19
+ if (isDir)
20
+ throw new CliError(`${path} is a directory. Pass files, e.g. --files docs/*.md`);
21
+ items.push({ id: path, text: readFile(path, "candidate file") });
22
+ }
23
+ if (flags.lines) {
24
+ const lines = nonEmptyLines(readInput(flags.lines, "lines"));
25
+ lines.forEach((line, i) => {
26
+ items.push({ id: `L${i + 1}`, text: line });
27
+ });
28
+ }
29
+ if (items.length === 0) {
30
+ throw new CliError("Provide candidates with --candidates <ref>, --files <paths...>, or --lines <ref>.");
31
+ }
32
+ if (items.length > MAX_CANDIDATES) {
33
+ throw new CliError(`Too many candidates (${items.length}); the limit is ${MAX_CANDIDATES} per call.`);
34
+ }
35
+ return items;
36
+ }
37
+ export async function findAction(query, flags, ctx) {
38
+ const candidates = collectCandidates(flags);
39
+ const topK = flags.topK === undefined ? ctx.config.find.topK : Number(flags.topK);
40
+ if (!Number.isInteger(topK) || topK < 1 || topK > 50)
41
+ throw new CliError("--top-k must be an integer from 1 to 50.");
42
+ const found = parseProbability("--found", flags.found, ctx.config.find.found);
43
+ const absent = parseProbability("--absent", flags.absent, ctx.config.find.absent);
44
+ const failOn = parseFailOn(flags.failOn, FIND_FAIL_CONDITIONS, []);
45
+ if (ctx.dryRun) {
46
+ const { state, questions } = buildFindRequest({ query, candidates });
47
+ emit({ ...ctx.output, format: "json" }, { model: ctx.config.model, state, questions }, () => "");
48
+ return EXIT.OK;
49
+ }
50
+ const output = await runFind(ctx.ask(), { query, candidates, topK, found, absent });
51
+ emit(ctx.output, output, () => renderFind(output, ctx));
52
+ return findFailed(output, failOn) ? EXIT.JUDGMENT : EXIT.OK;
53
+ }
54
+ export function renderFind(out, ctx) {
55
+ const c = ctx.output.color;
56
+ const verdict = out.exists_verdict === "answered"
57
+ ? paint(c, "green", out.exists_verdict)
58
+ : out.exists_verdict === "absent"
59
+ ? paint(c, "red", out.exists_verdict)
60
+ : paint(c, "yellow", out.exists_verdict);
61
+ const rows = out.top.map((hit, i) => [
62
+ String(i + 1),
63
+ formatProbability(hit.probability),
64
+ hit.id,
65
+ clip(hit.text, 60),
66
+ ]);
67
+ const lines = [
68
+ `${verdict} (exists ${formatProbability(out.exists)}) ${paint(c, "dim", out.query)}`,
69
+ "",
70
+ table([["#", "Prob", "Id", "Text"], ...rows], { color: c }),
71
+ ];
72
+ if (!ctx.output.quiet)
73
+ lines.push("", paint(c, "dim", usageLine(out.usage, out.model, out.provider)));
74
+ return lines.join("\n");
75
+ }
76
+ export function registerFind(program, run) {
77
+ program
78
+ .command("find")
79
+ .description(`Rank candidates against a plain-language query. No embeddings; up to ${MAX_CANDIDATES} candidates per call.`)
80
+ .argument("<query>", "what you are looking for")
81
+ .option("-c, --candidates <ref>", "JSON candidates (@file or -): array of strings, array of {id,text}, or {id: text}")
82
+ .option("-f, --files <paths...>", "treat each file as a candidate (id = path)")
83
+ .option("-l, --lines <ref>", "treat each non-empty line of @file or - as a candidate (id = L<n>)")
84
+ .option("-k, --top-k <n>", "how many ranked results to return (default 5)")
85
+ .option("--found <p>", "exists probability at or above which the verdict is 'answered' (default 0.7)")
86
+ .option("--absent <p>", "exists probability below which the verdict is 'absent' (default 0.35)")
87
+ .option("--fail-on <list>", `exit 2 when the exists verdict is one of: ${FIND_FAIL_CONDITIONS.join(", ")}, none (default none)`)
88
+ .addHelpText("after", `
89
+ Examples:
90
+ jev find "how do I rotate API keys" --files docs/*.md
91
+ jev find "refund policy" --lines @terms.txt -k 3
92
+ jev find "caching and infra cost" --candidates @notes.json --fail-on absent`)
93
+ .action(async (query, flags, cmd) => {
94
+ await run((ctx) => findAction(query, flags, ctx), cmd);
95
+ });
96
+ }
97
+ //# sourceMappingURL=find.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"find.js","sourceRoot":"","sources":["../../src/commands/find.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { Command } from "commander";
2
+ import type { CommandContext } from "../context.js";
3
+ export declare function modelsAction(ctx: CommandContext, env: NodeJS.ProcessEnv): Promise<number>;
4
+ export declare function registerModels(program: Command, run: (fn: (ctx: CommandContext) => Promise<number>, cmd: Command) => Promise<void>): void;
@@ -0,0 +1,35 @@
1
+ import { TypeSafeClient } from "@typesafe-ai/sdk";
2
+ import { CliError, EXIT } from "../errors.js";
3
+ import { emit, paint, table } from "../output.js";
4
+ import { resolveProvider } from "../provider.js";
5
+ export async function modelsAction(ctx, env) {
6
+ const provider = resolveProvider(env, ctx.config.provider);
7
+ if (provider !== "typesafe") {
8
+ throw new CliError(`Listing models requires the typesafe provider (resolved: ${provider}). Set TYPESAFE_API_KEY.`);
9
+ }
10
+ const client = new TypeSafeClient({
11
+ apiKey: env.TYPESAFE_API_KEY,
12
+ baseURL: env.TYPESAFE_BASE_URL || undefined,
13
+ timeout: ctx.config.timeoutMs,
14
+ });
15
+ const models = await client.models.list();
16
+ const payload = { command: "models", provider, models, default: ctx.config.model };
17
+ emit(ctx.output, payload, () => {
18
+ const rows = models.map((m) => [
19
+ m.name === ctx.config.model ? paint(ctx.output.color, "green", m.name) : m.name,
20
+ m.release_date,
21
+ m.description,
22
+ ]);
23
+ return table([["Name", "Released", "Description"], ...rows], { color: ctx.output.color });
24
+ });
25
+ return EXIT.OK;
26
+ }
27
+ export function registerModels(program, run) {
28
+ program
29
+ .command("models")
30
+ .description("List the models available to your TypeSafe account.")
31
+ .action(async (_flags, cmd) => {
32
+ await run((ctx) => modelsAction(ctx, process.env), cmd);
33
+ });
34
+ }
35
+ //# sourceMappingURL=models.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.js","sourceRoot":"","sources":["../../src/commands/models.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAGlD,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,GAAmB,EAAE,GAAsB;IAC5E,MAAM,QAAQ,GAAG,eAAe,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC3D,IAAI,QAAQ,KAAK,UAAU,EAAE,CAAC;QAC5B,MAAM,IAAI,QAAQ,CAChB,4DAA4D,QAAQ,0BAA0B,CAC/F,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,cAAc,CAAC;QAChC,MAAM,EAAE,GAAG,CAAC,gBAAgB;QAC5B,OAAO,EAAE,GAAG,CAAC,iBAAiB,IAAI,SAAS;QAC3C,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS;KAC9B,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IAC1C,MAAM,OAAO,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IACnF,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE;QAC7B,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;YAC7B,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI;YAC/E,CAAC,CAAC,YAAY;YACd,CAAC,CAAC,WAAW;SACd,CAAC,CAAC;QACH,OAAO,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,UAAU,EAAE,aAAa,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;IAC5F,CAAC,CAAC,CAAC;IACH,OAAO,IAAI,CAAC,EAAE,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,OAAgB,EAChB,GAAkF;IAElF,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,qDAAqD,CAAC;SAClE,MAAM,CAAC,KAAK,EAAE,MAAe,EAAE,GAAY,EAAE,EAAE;QAC9C,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { Command } from "commander";
2
+ import type { CommandContext } from "../context.js";
3
+ import { type ScreenOutput } from "../core/screen.js";
4
+ export interface ScreenFlags {
5
+ purpose?: string;
6
+ blockAt?: string;
7
+ reviewAt?: string;
8
+ failOn?: string;
9
+ }
10
+ export declare function resolveScreenText(positional: string | undefined): string;
11
+ export declare function screenAction(positional: string | undefined, flags: ScreenFlags, ctx: CommandContext): Promise<number>;
12
+ export declare function renderScreen(out: ScreenOutput, ctx: CommandContext): string;
13
+ export declare function registerScreen(program: Command, run: (fn: (ctx: CommandContext) => Promise<number>, cmd: Command) => Promise<void>): void;
@@ -0,0 +1,64 @@
1
+ import { buildScreenRequest, runScreen, SCREEN_FAIL_CONDITIONS, screenFailed, } from "../core/screen.js";
2
+ import { CliError, EXIT } from "../errors.js";
3
+ import { readInput, readStdin } from "../input.js";
4
+ import { parseFailOn, parseProbability } from "../lib.js";
5
+ import { emit, formatProbability, paint, usageLine } from "../output.js";
6
+ export function resolveScreenText(positional) {
7
+ if (positional !== undefined)
8
+ return readInput(positional, "text");
9
+ if (process.stdin.isTTY)
10
+ throw new CliError("Provide text as an argument, @file, or pipe it on stdin.");
11
+ return readStdin("text");
12
+ }
13
+ export async function screenAction(positional, flags, ctx) {
14
+ const text = resolveScreenText(positional);
15
+ const blockAt = parseProbability("--block-at", flags.blockAt, ctx.config.screen.blockAt);
16
+ const reviewAt = parseProbability("--review-at", flags.reviewAt, ctx.config.screen.reviewAt);
17
+ const failOn = parseFailOn(flags.failOn, SCREEN_FAIL_CONDITIONS, ["block"]);
18
+ if (ctx.dryRun) {
19
+ const { state, questions } = buildScreenRequest({ text, purpose: flags.purpose });
20
+ emit({ ...ctx.output, format: "json" }, { model: ctx.config.model, state, questions }, () => "");
21
+ return EXIT.OK;
22
+ }
23
+ const output = await runScreen(ctx.ask(), { text, purpose: flags.purpose, blockAt, reviewAt });
24
+ emit(ctx.output, output, () => renderScreen(output, ctx));
25
+ return screenFailed(output, failOn) ? EXIT.JUDGMENT : EXIT.OK;
26
+ }
27
+ export function renderScreen(out, ctx) {
28
+ const c = ctx.output.color;
29
+ const action = out.recommendation.action;
30
+ const styled = action === "block"
31
+ ? paint(c, ["bold", "red"], action.toUpperCase())
32
+ : action === "review"
33
+ ? paint(c, ["bold", "yellow"], action.toUpperCase())
34
+ : action === "skip"
35
+ ? paint(c, ["bold", "dim"], action.toUpperCase())
36
+ : paint(c, ["bold", "green"], action.toUpperCase());
37
+ const p = out.probabilities;
38
+ const lines = [
39
+ `${styled} ${out.recommendation.reason}`,
40
+ `injection ${formatProbability(p.injection)} · substance ${formatProbability(p.substance)} · relevance ${formatProbability(p.relevance)}`,
41
+ paint(c, "dim", `thresholds: block ≥ ${out.thresholds.block_at}, review ≥ ${out.thresholds.review_at}`),
42
+ ];
43
+ if (!ctx.output.quiet)
44
+ lines.push(paint(c, "dim", usageLine(out.usage, out.model, out.provider)));
45
+ return lines.join("\n");
46
+ }
47
+ export function registerScreen(program, run) {
48
+ program
49
+ .command("screen")
50
+ .description("Screen text for prompt injection, substance, and relevance before an agent reads it.")
51
+ .argument("[text]", "text to screen, @file, or - for stdin (default: stdin)")
52
+ .option("-p, --purpose <text>", "what the consuming agent is trying to do; enables the relevance check and 'skip'")
53
+ .option("--block-at <p>", "injection probability at or above which to block (default 0.75)")
54
+ .option("--review-at <p>", "injection probability at or above which to flag for review (default 0.25)")
55
+ .option("--fail-on <list>", `exit 2 when the recommendation is one of: ${SCREEN_FAIL_CONDITIONS.join(", ")}, none (default block)`)
56
+ .addHelpText("after", `
57
+ Examples:
58
+ curl -s https://example.com/pricing | jev screen --purpose "extract pricing tiers"
59
+ jev screen @email.txt --fail-on block,review && cat email.txt`)
60
+ .action(async (text, flags, cmd) => {
61
+ await run((ctx) => screenAction(text, flags, ctx), cmd);
62
+ });
63
+ }
64
+ //# sourceMappingURL=screen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"screen.js","sourceRoot":"","sources":["../../src/commands/screen.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { Command } from "commander";
2
+ import type { CommandContext } from "../context.js";
3
+ import { type VerifyOutput } from "../core/verify.js";
4
+ export interface VerifyFlags {
5
+ evidence?: string[];
6
+ evidenceJson?: string;
7
+ claims?: string;
8
+ autoAccept?: string;
9
+ failOn?: string;
10
+ }
11
+ export declare function collectEvidence(flags: VerifyFlags): {
12
+ id?: string;
13
+ text: string;
14
+ }[];
15
+ export declare function collectClaims(positional: string[], flags: VerifyFlags): string[];
16
+ export declare function verifyAction(positional: string[], flags: VerifyFlags, ctx: CommandContext): Promise<number>;
17
+ export declare function renderVerify(out: VerifyOutput, ctx: CommandContext): string;
18
+ export declare function registerVerify(program: Command, run: (fn: (ctx: CommandContext) => Promise<number>, cmd: Command) => Promise<void>): void;
@@ -0,0 +1,97 @@
1
+ import { buildVerifyRequest, runVerify, VERIFY_FAIL_CONDITIONS, verifyFailed, } from "../core/verify.js";
2
+ import { CliError, EXIT } from "../errors.js";
3
+ import { parseItems, parseList, readInput, referenceId } from "../input.js";
4
+ import { parseFailOn, parseProbability } from "../lib.js";
5
+ import { clip, emit, formatProbability, paint, table, usageLine } from "../output.js";
6
+ export function collectEvidence(flags) {
7
+ const items = [];
8
+ for (const ref of flags.evidence ?? []) {
9
+ const id = referenceId(ref);
10
+ items.push(id ? { id, text: readInput(ref, "evidence") } : { text: readInput(ref, "evidence") });
11
+ }
12
+ if (flags.evidenceJson)
13
+ items.push(...parseItems(readInput(flags.evidenceJson, "evidence JSON"), "evidence"));
14
+ if (items.length === 0)
15
+ throw new CliError("Provide evidence with --evidence <text|@file|-> or --evidence-json <ref>.");
16
+ return items;
17
+ }
18
+ export function collectClaims(positional, flags) {
19
+ const claims = [...positional];
20
+ if (flags.claims)
21
+ claims.push(...parseList(readInput(flags.claims, "claims"), "claims"));
22
+ if (claims.length === 0)
23
+ throw new CliError("Provide at least one claim as an argument or with --claims <@file|->.");
24
+ return claims;
25
+ }
26
+ export async function verifyAction(positional, flags, ctx) {
27
+ const claims = collectClaims(positional, flags);
28
+ const evidence = collectEvidence(flags);
29
+ const autoAccept = parseProbability("--auto-accept", flags.autoAccept, ctx.config.verify.autoAccept);
30
+ const failOn = parseFailOn(flags.failOn, VERIFY_FAIL_CONDITIONS, ["contradicted"]);
31
+ if (ctx.dryRun) {
32
+ const { state, questions } = buildVerifyRequest({ claims, evidence });
33
+ emit({ ...ctx.output, format: "json" }, { model: ctx.config.model, state, questions }, () => "");
34
+ return EXIT.OK;
35
+ }
36
+ const output = await runVerify(ctx.ask(), { claims, evidence, autoAccept });
37
+ emit(ctx.output, output, () => renderVerify(output, ctx));
38
+ return verifyFailed(output, failOn) ? EXIT.JUDGMENT : EXIT.OK;
39
+ }
40
+ export function renderVerify(out, ctx) {
41
+ const c = ctx.output.color;
42
+ const verdictStyle = (v) => v === "verified"
43
+ ? paint(c, "green", v)
44
+ : v === "contradicted"
45
+ ? paint(c, "red", v)
46
+ : v === "unsupported"
47
+ ? paint(c, "yellow", v)
48
+ : paint(c, "dim", v);
49
+ const multiSource = out.results.some((r) => r.supporting_evidence !== null);
50
+ const header = ["#", "Verdict", "Conf", "Action", "Claim"];
51
+ if (multiSource)
52
+ header.push("Source");
53
+ const rows = out.results.map((r, i) => {
54
+ const row = [
55
+ String(i + 1),
56
+ verdictStyle(r.verdict),
57
+ formatProbability(r.confidence),
58
+ r.action === "review" ? paint(c, "yellow", "review") : "auto",
59
+ clip(r.claim, 70),
60
+ ];
61
+ if (multiSource)
62
+ row.push(r.supporting_evidence ?? "-");
63
+ return row;
64
+ });
65
+ const s = out.summary;
66
+ const lines = [
67
+ table([header, ...rows], { color: c }),
68
+ "",
69
+ `${s.verified} verified · ${s.contradicted} contradicted · ${s.unsupported} unsupported · ${s.needs_review} need review (auto-accept ≥ ${out.auto_accept})`,
70
+ ];
71
+ if (!ctx.output.quiet)
72
+ lines.push(paint(c, "dim", usageLine(out.usage, out.model, out.provider)));
73
+ return lines.join("\n");
74
+ }
75
+ export function registerVerify(program, run) {
76
+ program
77
+ .command("verify")
78
+ .description("Check claims against evidence. Each claim gets a verdict, probability distribution, and confidence.")
79
+ .argument("[claims...]", "claims to verify (or use --claims)")
80
+ .option("-e, --evidence <ref>", "evidence text, @file, or - for stdin (repeatable)", collect, [])
81
+ .option("--evidence-json <ref>", "JSON evidence: array of strings, array of {id,text}, or {id: text} map")
82
+ .option("-c, --claims <ref>", "claims from @file or - (one per line, or a JSON array)")
83
+ .option("--auto-accept <p>", "confidence at or above which a verdict stands (default 0.8)")
84
+ .option("--fail-on <list>", `exit 2 when any result matches: ${VERIFY_FAIL_CONDITIONS.join(", ")}, none (default contradicted)`)
85
+ .addHelpText("after", `
86
+ Examples:
87
+ jev verify "Helmets are optional for adults" --evidence @ordinance.txt
88
+ jev verify --claims @claims.txt --evidence @spec.md --evidence @rfc.txt --fail-on contradicted,unsupported
89
+ git diff | jev verify "This PR only touches tests" --evidence - --json`)
90
+ .action(async (claims, flags, cmd) => {
91
+ await run((ctx) => verifyAction(claims, flags, ctx), cmd);
92
+ });
93
+ }
94
+ function collect(value, previous) {
95
+ return [...previous, value];
96
+ }
97
+ //# sourceMappingURL=verify.js.map