jev-agent-tools 0.2.0 → 0.3.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/CHANGELOG.md +37 -1
- package/CONTRIBUTING.md +3 -0
- package/README.md +22 -14
- package/SECURITY.md +17 -1
- package/dist/adapters/ask-files.js +11 -2
- package/dist/adapters/ask-proof.js +63 -7
- package/dist/adapters/command.js +82 -29
- package/dist/adapters/docs.js +30 -10
- package/dist/adapters/evidence-context.js +119 -0
- package/dist/adapters/files.js +141 -16
- package/dist/adapters/find.js +34 -6
- package/dist/adapters/git-base.js +7 -1
- package/dist/adapters/git.js +51 -7
- package/dist/adapters/locate-file.js +47 -9
- package/dist/adapters/private-storage.js +14 -6
- package/dist/adapters/risk-callers.js +3 -0
- package/dist/adapters/shell.js +23 -7
- package/dist/adapters/test-inventory.js +10 -2
- package/dist/configuration.js +17 -7
- package/dist/constants.js +26 -5
- package/dist/core/ask-references.js +193 -109
- package/dist/core/asks.js +78 -7
- package/dist/core/locate.js +8 -8
- package/dist/core/output.js +17 -0
- package/dist/core/result-report.js +302 -0
- package/dist/core/secret-path.js +34 -0
- package/dist/core/state.js +8 -1
- package/dist/core/units.js +1 -1
- package/dist/jev/client.js +34 -12
- package/dist/mcp/protocol.js +50 -27
- package/dist/mcp/tools.js +20 -7
- package/dist/render.js +72 -0
- package/dist/report-schema.js +1356 -0
- package/dist/result-types.js +1 -0
- package/dist/texts/ask-files.js +3 -1
- package/dist/texts/ask.js +3 -1
- package/dist/texts/check-diff.js +7 -4
- package/dist/texts/find.js +7 -2
- package/dist/texts/guide.js +3 -16
- package/dist/texts/instructions.js +72 -0
- package/dist/texts/locate.js +7 -2
- package/dist/texts/select-tests.js +3 -1
- package/dist/tools/ask-files.js +248 -15
- package/dist/tools/ask.js +523 -62
- package/dist/tools/check-diff.js +222 -30
- package/dist/tools/docs-check.js +122 -13
- package/dist/tools/find.js +320 -27
- package/dist/tools/locate.js +317 -18
- package/dist/tools/review-report.js +230 -0
- package/dist/tools/select-tests.js +273 -19
- package/dist/tools/spec-check.js +119 -22
- package/docs/adr/0001-strict-typescript-pure-core-offline-tests.md +3 -3
- package/docs/agent-instructions.md +59 -30
- package/docs/design.md +13 -1
- package/docs/mcp.md +8 -6
- package/docs/tools/jev_ask.md +8 -5
- package/docs/tools/jev_ask_files.md +2 -1
- package/docs/tools/jev_check_diff.md +4 -1
- package/docs/tools/jev_find_files.md +2 -1
- package/docs/tools/jev_locate_in_file.md +5 -0
- package/docs/tools/jev_select_tests.md +4 -1
- package/package.json +1 -1
- package/rules/jev-ask.md +22 -1
- package/server.json +2 -2
- package/src/adapters/ask-files.ts +11 -3
- package/src/adapters/ask-proof.ts +69 -11
- package/src/adapters/command.ts +96 -33
- package/src/adapters/docs.ts +33 -14
- package/src/adapters/evidence-context.ts +169 -0
- package/src/adapters/files.ts +146 -16
- package/src/adapters/find.ts +37 -7
- package/src/adapters/git-base.ts +7 -1
- package/src/adapters/git.ts +61 -8
- package/src/adapters/locate-file.ts +51 -9
- package/src/adapters/private-storage.ts +17 -5
- package/src/adapters/risk-callers.ts +3 -0
- package/src/adapters/shell.ts +23 -7
- package/src/adapters/test-inventory.ts +12 -4
- package/src/configuration.ts +16 -2
- package/src/constants.ts +26 -5
- package/src/core/ask-references.ts +262 -146
- package/src/core/asks.ts +79 -7
- package/src/core/import-boundaries.ts +8 -3
- package/src/core/locate.ts +8 -5
- package/src/core/output.ts +34 -0
- package/src/core/result-report.ts +410 -0
- package/src/core/secret-path.ts +37 -0
- package/src/core/state.ts +8 -1
- package/src/core/units.ts +3 -2
- package/src/index.ts +3 -0
- package/src/jev/client.ts +54 -16
- package/src/jev/types.ts +18 -3
- package/src/mcp/protocol.ts +91 -41
- package/src/mcp/tools.ts +26 -13
- package/src/render.ts +109 -0
- package/src/report-schema.ts +1380 -0
- package/src/result-types.ts +234 -0
- package/src/result.ts +4 -1
- package/src/runtime.ts +6 -0
- package/src/texts/ask-files.ts +4 -1
- package/src/texts/ask.ts +8 -1
- package/src/texts/check-diff.ts +7 -4
- package/src/texts/find.ts +8 -2
- package/src/texts/guide.ts +8 -16
- package/src/texts/instructions.ts +98 -0
- package/src/texts/locate.ts +8 -2
- package/src/texts/run-end.ts +2 -2
- package/src/texts/select-tests.ts +4 -1
- package/src/tools/ask-files.ts +309 -14
- package/src/tools/ask.ts +700 -77
- package/src/tools/check-diff.ts +331 -28
- package/src/tools/docs-check.ts +241 -39
- package/src/tools/find.ts +386 -29
- package/src/tools/locate.ts +384 -19
- package/src/tools/review-report.ts +308 -0
- package/src/tools/select-tests.ts +479 -21
- package/src/tools/spec-check.ts +193 -19
package/dist/mcp/tools.js
CHANGED
|
@@ -2,15 +2,19 @@ import { Value } from "@sinclair/typebox/value";
|
|
|
2
2
|
import { spawnExec } from "../adapters/exec.js";
|
|
3
3
|
import { ConfigController } from "../configuration.js";
|
|
4
4
|
import { MCP_VALIDATION_MAX_ERRORS } from "../constants.js";
|
|
5
|
+
import { resultIsError } from "../core/result-report.js";
|
|
5
6
|
import { Guide } from "../guide.js";
|
|
6
7
|
import { mcpHost } from "../host.js";
|
|
8
|
+
import { mcpStructuredResultSchema } from "../report-schema.js";
|
|
7
9
|
import { readSessionLimits, Session } from "../session.js";
|
|
10
|
+
import { renderAgentInstructions } from "../texts/instructions.js";
|
|
8
11
|
import { createAskTool } from "../tools/ask.js";
|
|
9
12
|
import { createAskFilesTool } from "../tools/ask-files.js";
|
|
10
13
|
import { createCheckDiffTool } from "../tools/check-diff.js";
|
|
11
14
|
import { createFindFilesTool } from "../tools/find.js";
|
|
12
15
|
import { createLocateTool } from "../tools/locate.js";
|
|
13
16
|
import { createSelectTestsTool } from "../tools/select-tests.js";
|
|
17
|
+
import { McpInvalidParams } from "./protocol.js";
|
|
14
18
|
function validationError(schema, value) {
|
|
15
19
|
if (Value.Check(schema, value))
|
|
16
20
|
return undefined;
|
|
@@ -34,17 +38,20 @@ export async function loadMcpClient(env, configDirectory) {
|
|
|
34
38
|
env,
|
|
35
39
|
...(configDirectory ? { directory: configDirectory } : {}),
|
|
36
40
|
});
|
|
41
|
+
const configured = () => controller.client
|
|
42
|
+
? { client: controller.client, apiKey: controller.values().apiKey }
|
|
43
|
+
: {};
|
|
37
44
|
try {
|
|
38
45
|
await controller.initialize({});
|
|
39
46
|
}
|
|
40
47
|
catch (error) {
|
|
41
48
|
// Saved storage unusable: environment configuration (if any) still applies.
|
|
42
49
|
return {
|
|
43
|
-
...(
|
|
50
|
+
...configured(),
|
|
44
51
|
warning: error instanceof Error ? error.message : String(error),
|
|
45
52
|
};
|
|
46
53
|
}
|
|
47
|
-
return
|
|
54
|
+
return configured();
|
|
48
55
|
}
|
|
49
56
|
catch (error) {
|
|
50
57
|
return { warning: error instanceof Error ? error.message : String(error) };
|
|
@@ -58,12 +65,14 @@ export async function createMcpTools(options) {
|
|
|
58
65
|
const env = options.env ?? process.env;
|
|
59
66
|
const host = mcpHost();
|
|
60
67
|
const loaded = options.client
|
|
61
|
-
? { client: options.client }
|
|
68
|
+
? { client: options.client, apiKey: env.JEV_TOOLS_API_KEY }
|
|
62
69
|
: await loadMcpClient(env, options.configDirectory);
|
|
63
70
|
const client = loaded.client;
|
|
64
71
|
const dependencies = {
|
|
65
72
|
client,
|
|
73
|
+
apiKey: loaded.apiKey,
|
|
66
74
|
host,
|
|
75
|
+
evidenceOrigin: "server",
|
|
67
76
|
runtime: {
|
|
68
77
|
session: new Session(readSessionLimits(env)),
|
|
69
78
|
guide: new Guide(host),
|
|
@@ -96,17 +105,21 @@ export async function createMcpTools(options) {
|
|
|
96
105
|
// Evidence is sent to the configured judgment endpoint.
|
|
97
106
|
openWorldHint: true,
|
|
98
107
|
},
|
|
108
|
+
outputSchema: mcpStructuredResultSchema,
|
|
99
109
|
async call(args, signal) {
|
|
100
110
|
const invalid = validationError(tool.parameters, args);
|
|
101
111
|
if (invalid)
|
|
102
|
-
|
|
112
|
+
throw new McpInvalidParams(invalid);
|
|
103
113
|
const result = await tool.execute(`mcp-${++id}`, args, signal, undefined, { cwd: options.root });
|
|
104
|
-
return {
|
|
114
|
+
return {
|
|
115
|
+
content: result.content,
|
|
116
|
+
structuredContent: { result: result.details.result },
|
|
117
|
+
...(resultIsError(result.details.result) ? { isError: true } : {}),
|
|
118
|
+
};
|
|
105
119
|
},
|
|
106
120
|
};
|
|
107
121
|
});
|
|
108
|
-
const
|
|
109
|
-
const instructions = [dependencies.runtime.guide.text, ...guidelines].join("\n\n");
|
|
122
|
+
const instructions = renderAgentInstructions("mcp", host.names);
|
|
110
123
|
return {
|
|
111
124
|
tools,
|
|
112
125
|
instructions,
|
package/dist/render.js
CHANGED
|
@@ -40,3 +40,75 @@ function renderLine(line) {
|
|
|
40
40
|
export function renderEnvelope(envelope) {
|
|
41
41
|
return envelope.lines.map(renderLine).join("\n");
|
|
42
42
|
}
|
|
43
|
+
function knowledge(value, format = String) {
|
|
44
|
+
return value.status === "known"
|
|
45
|
+
? format(value.value)
|
|
46
|
+
: `${value.status} (${value.reason})`;
|
|
47
|
+
}
|
|
48
|
+
function scopeLabel(scope) {
|
|
49
|
+
return scope.kind === "call"
|
|
50
|
+
? "call"
|
|
51
|
+
: scope.kind === "item"
|
|
52
|
+
? `items ${scope.itemIds.join(", ")}`
|
|
53
|
+
: scope.kind === "group"
|
|
54
|
+
? `groups ${scope.groupIds.join(", ")}`
|
|
55
|
+
: `inventory ${scope.inventoryIds.join(", ")}`;
|
|
56
|
+
}
|
|
57
|
+
/** Human projection uses the same typed facts as structured transport, never prose inference. */
|
|
58
|
+
export function renderResultReport(report, options = {}) {
|
|
59
|
+
const { context: c, accounting: a } = report;
|
|
60
|
+
const counts = a.requestedResults;
|
|
61
|
+
const mode = counts.fresh + counts.cache
|
|
62
|
+
? `${counts.fresh} fresh / ${counts.cache} cache Jev results`
|
|
63
|
+
: counts.static
|
|
64
|
+
? "static selection; no Jev judgment"
|
|
65
|
+
: report.items.some((item) => item.selection?.selected)
|
|
66
|
+
? "conservative fallback selection; no Jev judgment"
|
|
67
|
+
: "no admissible judgment";
|
|
68
|
+
const lines = [
|
|
69
|
+
`${report.execution} — ${mode}${counts.notJudged ? `; ${counts.notJudged} not judged` : ""}`,
|
|
70
|
+
`context: authority ${knowledge(c.authority, (v) => `${v.path} (${v.origin})`)} · requested root ${knowledge(c.requestedRoot)} · effective root ${knowledge(c.effectiveRoot, (v) => `${v.path} (${v.origin}); common-dir ${knowledge(v.commonDir)}`)} · base ${knowledge(c.requestedBase)} → ${knowledge(c.resolvedBase)}`,
|
|
71
|
+
];
|
|
72
|
+
for (const inv of c.inventories) {
|
|
73
|
+
lines.push(`inventory ${inv.id} (${inv.kind}): discovered ${knowledge(inv.discovered)} · considered ${knowledge(inv.considered)} · scopeRestricted ${inv.scopeRestricted} · rules ${inv.rules.join("; ")} · restrictions ${inv.restrictions.join("; ") || "none"}`);
|
|
74
|
+
for (const criterion of inv.criteria)
|
|
75
|
+
lines.push(`criterion ${JSON.stringify(criterion.criterion)}: ${criterion.outcome}; matches ${knowledge(criterion.matches)}`);
|
|
76
|
+
}
|
|
77
|
+
if (c.command.execution !== "not_requested")
|
|
78
|
+
lines.push(`command: ${c.command.execution} · cwd ${knowledge(c.command.cwd)} · exit ${knowledge(c.command.exitCode)} · timedOut ${knowledge(c.command.timedOut)}`);
|
|
79
|
+
for (const item of report.items) {
|
|
80
|
+
if (item.treatment === "judged") {
|
|
81
|
+
const j = item.judgment;
|
|
82
|
+
lines.push(`${j.band === "verdict" ? "" : `${j.band} `}${j.uncalibrated ? "uncalibrated " : ""}${item.label} = ${String(j.result)} (${j.measure.kind} ${knowledge(j.measure.value)}) [${item.source}]${j.reason ? ` — ${j.reason}` : ""}`);
|
|
83
|
+
for (const raw of j.rawValues)
|
|
84
|
+
lines.push(` raw ${raw.label} = ${String(raw.value)}; probability ${knowledge(raw.probability)}`);
|
|
85
|
+
for (const control of j.controls) {
|
|
86
|
+
lines.push(` control ${control.id} (${control.kind}, ${control.source}): ${control.outcome}`);
|
|
87
|
+
for (const raw of control.rawValues)
|
|
88
|
+
lines.push(` raw ${raw.label} = ${String(raw.value)}; probability ${knowledge(raw.probability)}`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
else
|
|
92
|
+
lines.push(`${item.treatment === "static" ? "static" : "unjudged"} ${item.label}${item.treatment === "static" ? ` — ${item.staticReason}` : ""}`);
|
|
93
|
+
for (const evidence of item.evidence)
|
|
94
|
+
lines.push(` evidence ${evidence.target} (${evidence.side}): ${knowledge(evidence.canonicalPath)} · aliases ${evidence.aliases.join(", ") || "none"} · revision ${knowledge(evidence.revision)}`);
|
|
95
|
+
if (item.selection)
|
|
96
|
+
lines.push(` selection: ${item.selection.selected ? "selected" : "not selected"} — ${item.selection.reason}`);
|
|
97
|
+
if (item.diagnosticIds.length)
|
|
98
|
+
lines.push(` diagnostics ${item.diagnosticIds.join(", ")}`);
|
|
99
|
+
if (item.actionIds.length)
|
|
100
|
+
lines.push(` actions ${item.actionIds.join(", ")}`);
|
|
101
|
+
}
|
|
102
|
+
// Complete diagnostic lists keep legacy text-only clients self-contained.
|
|
103
|
+
for (const d of report.diagnostics)
|
|
104
|
+
lines.push(`${d.material ? "material " : ""}${d.effect} ${d.id} — ${d.cause}: ${d.fact} · target ${knowledge(d.target)} · origin ${d.origin} · scope ${scopeLabel(d.scope)} · members ${knowledge(d.memberCount)}${d.omittedMembers.length ? ` · omitted ${d.omittedMembers.join(", ")}` : ""} · actions ${d.actionIds.join(", ") || "none"}`);
|
|
105
|
+
for (const action of report.actions)
|
|
106
|
+
lines.push(`next ${action.id} (${action.code}; ${scopeLabel(action.scope)}; target ${knowledge(action.target)}): ${action.condition} — ${action.instruction}`);
|
|
107
|
+
if (options.details) {
|
|
108
|
+
const detailLines = options.details.lines.filter((line) => line.type === "command" || line.type === "list");
|
|
109
|
+
if (detailLines.length)
|
|
110
|
+
lines.push("details:", renderEnvelope({ lines: detailLines }));
|
|
111
|
+
}
|
|
112
|
+
lines.push(`HTTP attempts ${a.httpAttempts} · questions sent ${a.questionsSent} · requested results total ${knowledge(counts.total)} / fresh ${counts.fresh} / cache ${counts.cache} / not judged ${counts.notJudged} / static ${counts.static} · cache probes ${a.cacheHits}/${a.cacheRequests} · auxiliary controls fresh ${a.auxiliary.controls.fresh} / cache ${a.auxiliary.controls.cache} / not judged ${a.auxiliary.controls.notJudged} / static ${a.auxiliary.controls.static} · passages fresh ${a.auxiliary.passages.fresh} / cache ${a.auxiliary.passages.cache} / not judged ${a.auxiliary.passages.notJudged} · current cost USD ${knowledge(a.costUsd)} · elapsed ${a.elapsedMs} ms`);
|
|
113
|
+
return lines.join("\n");
|
|
114
|
+
}
|