jev-agent-tools 0.1.3 → 0.2.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 +88 -3
- package/CONTRIBUTING.md +40 -0
- package/README.md +64 -9
- package/SECURITY.md +27 -0
- package/dist/adapters/analysis-context.js +75 -0
- package/dist/adapters/ask-files.js +189 -0
- package/dist/adapters/ask-proof.js +144 -0
- package/dist/adapters/ask-syntax.js +385 -0
- package/dist/adapters/canonical-path.js +17 -0
- package/dist/adapters/command.js +181 -0
- package/dist/adapters/docs.js +172 -0
- package/dist/adapters/exec.js +207 -0
- package/dist/adapters/files.js +293 -0
- package/dist/adapters/find.js +122 -0
- package/dist/adapters/git-base.js +26 -0
- package/dist/adapters/git-inventory.js +71 -0
- package/dist/adapters/git.js +439 -0
- package/dist/adapters/locate-file.js +159 -0
- package/dist/adapters/output-lines.js +46 -0
- package/dist/adapters/private-storage.js +98 -0
- package/dist/adapters/risk-callers.js +426 -0
- package/dist/adapters/runner-version.js +78 -0
- package/dist/adapters/shell.js +76 -0
- package/dist/adapters/syntax.js +187 -0
- package/dist/adapters/test-inventory.js +131 -0
- package/dist/adapters/usage.js +20 -0
- package/dist/adapters/utf8.js +47 -0
- package/dist/configuration.js +257 -0
- package/dist/constants.js +119 -0
- package/dist/core/ask-closure.js +282 -0
- package/dist/core/ask-proof.js +1 -0
- package/dist/core/ask-references.js +194 -0
- package/dist/core/asks.js +436 -0
- package/dist/core/batches.js +65 -0
- package/dist/core/command-output.js +224 -0
- package/dist/core/diff.js +178 -0
- package/dist/core/docs.js +302 -0
- package/dist/core/find.js +108 -0
- package/dist/core/git.js +1 -0
- package/dist/core/imports.js +550 -0
- package/dist/core/integrity.js +45 -0
- package/dist/core/lexical.js +132 -0
- package/dist/core/locate.js +169 -0
- package/dist/core/output.js +120 -0
- package/dist/core/pointer.js +29 -0
- package/dist/core/risk-callers.js +851 -0
- package/dist/core/runner-version.js +45 -0
- package/dist/core/sections.js +230 -0
- package/dist/core/state.js +44 -0
- package/dist/core/syntax.js +1 -0
- package/dist/core/test-commands.js +334 -0
- package/dist/core/test-coverage.js +74 -0
- package/dist/core/test-discovery.js +1382 -0
- package/dist/core/test-evidence.js +527 -0
- package/dist/core/test-state.js +81 -0
- package/dist/core/truncate.js +12 -0
- package/dist/core/units.js +349 -0
- package/dist/describe.js +23 -0
- package/dist/guide.js +33 -0
- package/dist/host.js +24 -0
- package/dist/jev/client.js +434 -0
- package/dist/jev/pool.js +54 -0
- package/dist/jev/types.js +1 -0
- package/dist/mcp/main.js +124 -0
- package/dist/mcp/protocol.js +187 -0
- package/dist/mcp/tools.js +116 -0
- package/dist/presets/docs.js +62 -0
- package/dist/presets/risk.js +179 -0
- package/dist/presets/spec.js +81 -0
- package/dist/presets/witnesses.js +249 -0
- package/dist/render.js +42 -0
- package/dist/result.js +3 -0
- package/dist/runtime.js +1 -0
- package/dist/session.js +147 -0
- package/dist/texts/ask-files.js +1 -0
- package/dist/texts/ask.js +2 -0
- package/dist/texts/check-diff.js +17 -0
- package/dist/texts/configuration.js +1 -0
- package/dist/texts/find.js +14 -0
- package/dist/texts/guide.js +16 -0
- package/dist/texts/locate.js +10 -0
- package/dist/texts/select-tests.js +2 -0
- package/dist/tools/ask-files.js +217 -0
- package/dist/tools/ask-schema.js +70 -0
- package/dist/tools/ask.js +686 -0
- package/dist/tools/check-diff.js +402 -0
- package/dist/tools/docs-check.js +299 -0
- package/dist/tools/find.js +389 -0
- package/dist/tools/locate.js +303 -0
- package/dist/tools/select-tests.js +567 -0
- package/dist/tools/spec-check.js +166 -0
- package/docs/adr/0001-strict-typescript-pure-core-offline-tests.md +31 -0
- package/docs/adr/0002-one-http-protocol-across-hosts.md +17 -0
- package/docs/adr/0003-explicit-scope-conservative-automation.md +19 -0
- package/docs/adr/0004-compiled-typed-intents.md +19 -0
- package/docs/adr/0005-evidence-construction-before-judgment.md +19 -0
- package/docs/adr/0006-visible-uncertainty-constrained-controls.md +21 -0
- package/docs/adr/0007-bounded-evidence-visible-limits.md +21 -0
- package/docs/adr/0008-static-test-discovery-conservative-plans.md +19 -0
- package/docs/adr/0009-session-cache-requested-model-identity.md +17 -0
- package/docs/adr/0010-mcp-server-thin-host.md +23 -0
- package/docs/agent-instructions.md +91 -0
- package/docs/design.md +3 -3
- package/docs/mcp.md +231 -0
- package/package.json +19 -4
- package/server.json +57 -0
- package/src/adapters/canonical-path.ts +18 -0
- package/src/adapters/command.ts +7 -4
- package/src/adapters/exec.ts +226 -0
- package/src/adapters/private-storage.ts +143 -0
- package/src/adapters/risk-callers.ts +4 -2
- package/src/adapters/shell.ts +97 -0
- package/src/configuration.ts +294 -0
- package/src/constants.ts +11 -0
- package/src/core/command-output.ts +17 -1
- package/src/host-tui.d.ts +14 -0
- package/src/host.ts +11 -0
- package/src/index.ts +13 -5
- package/src/jev/client.ts +12 -0
- package/src/jev/types.ts +6 -0
- package/src/mcp/main.ts +135 -0
- package/src/mcp/protocol.ts +282 -0
- package/src/mcp/tools.ts +166 -0
- package/src/secret-input.ts +222 -0
- package/src/session.ts +59 -0
- package/src/setup.ts +170 -0
- package/src/texts/configuration.ts +1 -1
- package/src/tools/ask-files.ts +8 -13
- package/src/tools/ask.ts +29 -28
- package/src/tools/check-diff.ts +11 -11
- package/src/tools/docs-check.ts +1 -0
- package/src/tools/find.ts +8 -8
- package/src/tools/locate.ts +8 -9
- package/src/tools/select-tests.ts +10 -10
- package/src/tools/spec-check.ts +1 -0
package/src/tools/ask.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
import { resolve } from "node:path";
|
|
2
|
+
import { isAbsolute, relative, resolve } from "node:path";
|
|
3
3
|
import type { ToolDefinition } from "@earendil-works/pi-coding-agent";
|
|
4
4
|
import { type Static, Type } from "@sinclair/typebox";
|
|
5
5
|
import { createAnalysisContext } from "../adapters/analysis-context.ts";
|
|
6
6
|
import { collectAskRepository, repositoryPath } from "../adapters/ask-proof.ts";
|
|
7
7
|
import { collectProofSyntax } from "../adapters/ask-syntax.ts";
|
|
8
|
+
import { canonicalPath } from "../adapters/canonical-path.ts";
|
|
8
9
|
import { captureCommand } from "../adapters/command.ts";
|
|
9
10
|
import { collectFiles } from "../adapters/files.ts";
|
|
10
11
|
import { shareGitInventory } from "../adapters/git-inventory.ts";
|
|
@@ -67,12 +68,8 @@ export const askParameters = Type.Object(
|
|
|
67
68
|
);
|
|
68
69
|
export type AskArgs = Static<typeof askParameters>;
|
|
69
70
|
|
|
70
|
-
export function createAskTool({
|
|
71
|
-
|
|
72
|
-
host,
|
|
73
|
-
runtime,
|
|
74
|
-
exec: execute,
|
|
75
|
-
}: ToolDependencies) {
|
|
71
|
+
export function createAskTool(dependencies: ToolDependencies) {
|
|
72
|
+
const { host, runtime, exec: execute } = dependencies;
|
|
76
73
|
const { isOmp, names } = host;
|
|
77
74
|
const allowCommand = process.env.JEV_TOOLS_ALLOW_COMMAND !== "0";
|
|
78
75
|
const parameters = allowCommand
|
|
@@ -120,6 +117,8 @@ export function createAskTool({
|
|
|
120
117
|
};
|
|
121
118
|
};
|
|
122
119
|
}> {
|
|
120
|
+
const client = dependencies.client;
|
|
121
|
+
const cwd = await canonicalPath(ctx.cwd);
|
|
123
122
|
const started = performance.now();
|
|
124
123
|
const exec = shareGitInventory(execute);
|
|
125
124
|
const finish = (
|
|
@@ -162,7 +161,7 @@ export function createAskTool({
|
|
|
162
161
|
return textResult("Provide state, command or at least one path.");
|
|
163
162
|
const asks = compileAsks(args.asks, { surface: "ask" });
|
|
164
163
|
if (!asks.ok) return textResult(asks.error);
|
|
165
|
-
const files = await collectFiles(
|
|
164
|
+
const files = await collectFiles(cwd, args.paths ?? [], signal, {
|
|
166
165
|
exec,
|
|
167
166
|
allowEmpty: true,
|
|
168
167
|
skipInvalidUtf8: true,
|
|
@@ -181,12 +180,7 @@ export function createAskTool({
|
|
|
181
180
|
fact,
|
|
182
181
|
next: "Provide this file as UTF-8 text if the judgment needs it.",
|
|
183
182
|
}));
|
|
184
|
-
let repository = await collectAskRepository(
|
|
185
|
-
exec,
|
|
186
|
-
ctx.cwd,
|
|
187
|
-
args.base,
|
|
188
|
-
signal,
|
|
189
|
-
);
|
|
183
|
+
let repository = await collectAskRepository(exec, cwd, args.base, signal);
|
|
190
184
|
if (!repository.ok && args.base) return textResult(repository.error);
|
|
191
185
|
if (!repository.ok)
|
|
192
186
|
proofLimitations.push({
|
|
@@ -196,7 +190,7 @@ export function createAskTool({
|
|
|
196
190
|
const command = args.command
|
|
197
191
|
? await captureCommand(
|
|
198
192
|
exec,
|
|
199
|
-
repository.ok ? repository.root :
|
|
193
|
+
repository.ok ? repository.root : cwd,
|
|
200
194
|
args.command,
|
|
201
195
|
args.timeout_s,
|
|
202
196
|
signal,
|
|
@@ -204,12 +198,7 @@ export function createAskTool({
|
|
|
204
198
|
: undefined;
|
|
205
199
|
if (command && !command.ok) return textResult(command.error);
|
|
206
200
|
if (command?.ok) {
|
|
207
|
-
repository = await collectAskRepository(
|
|
208
|
-
exec,
|
|
209
|
-
ctx.cwd,
|
|
210
|
-
args.base,
|
|
211
|
-
signal,
|
|
212
|
-
);
|
|
201
|
+
repository = await collectAskRepository(exec, cwd, args.base, signal);
|
|
213
202
|
if (!repository.ok && args.base) return textResult(repository.error);
|
|
214
203
|
}
|
|
215
204
|
const initialState = assembleState(args.state, files.files);
|
|
@@ -223,6 +212,17 @@ export function createAskTool({
|
|
|
223
212
|
for (const target of command.targets) {
|
|
224
213
|
if (target.path.startsWith(`${repository.root}/`))
|
|
225
214
|
target.path = target.path.slice(repository.root.length + 1);
|
|
215
|
+
else if (isAbsolute(target.path)) {
|
|
216
|
+
// Windows reports C:/... or short 8.3 forms; compare canonically.
|
|
217
|
+
const local = relative(
|
|
218
|
+
repository.root,
|
|
219
|
+
await canonicalPath(target.path),
|
|
220
|
+
)
|
|
221
|
+
.split("\\")
|
|
222
|
+
.join("/");
|
|
223
|
+
if (local && !local.startsWith("../") && !isAbsolute(local))
|
|
224
|
+
target.path = local;
|
|
225
|
+
}
|
|
226
226
|
let matches = [...repository.known].filter(
|
|
227
227
|
(path) => path === target.path || path.endsWith(`/${target.path}`),
|
|
228
228
|
);
|
|
@@ -255,7 +255,7 @@ export function createAskTool({
|
|
|
255
255
|
}
|
|
256
256
|
const path = matches[0];
|
|
257
257
|
if (!path) continue;
|
|
258
|
-
const local = repositoryPath(
|
|
258
|
+
const local = repositoryPath(cwd, repository.root, path);
|
|
259
259
|
if (!Object.hasOwn(files.files, local)) {
|
|
260
260
|
const added = await collectFiles(repository.root, [path], signal, {
|
|
261
261
|
exec,
|
|
@@ -351,7 +351,7 @@ export function createAskTool({
|
|
|
351
351
|
if (repository?.ok) {
|
|
352
352
|
const canonical = Object.fromEntries(
|
|
353
353
|
Object.entries(files.files).map(([path, text]) => [
|
|
354
|
-
repositoryPath(repository.root,
|
|
354
|
+
repositoryPath(repository.root, cwd, path),
|
|
355
355
|
text,
|
|
356
356
|
]),
|
|
357
357
|
);
|
|
@@ -373,7 +373,7 @@ export function createAskTool({
|
|
|
373
373
|
const canonicalPath =
|
|
374
374
|
references.additions.find(
|
|
375
375
|
(addition) => addition.reference === path,
|
|
376
|
-
)?.path ?? repositoryPath(repository.root,
|
|
376
|
+
)?.path ?? repositoryPath(repository.root, cwd, path);
|
|
377
377
|
return [path, before[canonicalPath] ?? null];
|
|
378
378
|
}),
|
|
379
379
|
);
|
|
@@ -515,11 +515,11 @@ export function createAskTool({
|
|
|
515
515
|
const identities = files.identities.map((file) => {
|
|
516
516
|
const content = inserted[file.requestedPath];
|
|
517
517
|
const insertedPath = Object.keys(inserted).find(
|
|
518
|
-
(path) => resolve(
|
|
518
|
+
(path) => resolve(cwd, path) === file.resolvedPath,
|
|
519
519
|
);
|
|
520
520
|
return {
|
|
521
521
|
...file,
|
|
522
|
-
insertedPath: insertedPath ? resolve(
|
|
522
|
+
insertedPath: insertedPath ? resolve(cwd, insertedPath) : "",
|
|
523
523
|
content: typeof content === "string" ? content : "",
|
|
524
524
|
insertedSha256: createHash("sha256")
|
|
525
525
|
.update(typeof content === "string" ? content : "")
|
|
@@ -547,6 +547,7 @@ export function createAskTool({
|
|
|
547
547
|
const options = {
|
|
548
548
|
signal,
|
|
549
549
|
cache: !args.command,
|
|
550
|
+
...runtime.session.requestGate(),
|
|
550
551
|
beforeRequest: (questionCount: number) => {
|
|
551
552
|
if (args.max_calls !== undefined && sent >= args.max_calls) {
|
|
552
553
|
refusal = {
|
|
@@ -790,14 +791,14 @@ export function createAskTool({
|
|
|
790
791
|
const selectedPath = repository?.ok
|
|
791
792
|
? (references.additions.find(
|
|
792
793
|
(addition) => addition.reference === selected,
|
|
793
|
-
)?.path ?? repositoryPath(repository.root,
|
|
794
|
+
)?.path ?? repositoryPath(repository.root, cwd, selected))
|
|
794
795
|
: selected;
|
|
795
796
|
const retained = (path: string) => {
|
|
796
797
|
if (!repository?.ok) return path !== selected;
|
|
797
798
|
return (
|
|
798
799
|
(references.additions.find(
|
|
799
800
|
(addition) => addition.reference === path,
|
|
800
|
-
)?.path ?? repositoryPath(repository.root,
|
|
801
|
+
)?.path ?? repositoryPath(repository.root, cwd, path)) !==
|
|
801
802
|
selectedPath
|
|
802
803
|
);
|
|
803
804
|
};
|
package/src/tools/check-diff.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { type Static, Type } from "@sinclair/typebox";
|
|
3
3
|
import { createAnalysisContext } from "../adapters/analysis-context.ts";
|
|
4
|
+
import { canonicalPath } from "../adapters/canonical-path.ts";
|
|
4
5
|
import { collectUnits } from "../adapters/git.ts";
|
|
5
6
|
import { resolveBase } from "../adapters/git-base.ts";
|
|
6
7
|
import { shareGitInventory } from "../adapters/git-inventory.ts";
|
|
@@ -83,12 +84,8 @@ function unitLabel(unit: EvidenceUnit): string {
|
|
|
83
84
|
.slice(0, 8);
|
|
84
85
|
return `${unit.file}${range ? `:${range.start}-${range.end}` : ""} ${unit.name} [${fingerprint}]`;
|
|
85
86
|
}
|
|
86
|
-
export function createCheckDiffTool({
|
|
87
|
-
|
|
88
|
-
host,
|
|
89
|
-
runtime,
|
|
90
|
-
exec: execute,
|
|
91
|
-
}: ToolDependencies) {
|
|
87
|
+
export function createCheckDiffTool(dependencies: ToolDependencies) {
|
|
88
|
+
const { host, runtime, exec: execute } = dependencies;
|
|
92
89
|
return {
|
|
93
90
|
name: "jev_check_diff",
|
|
94
91
|
label: "Jev check diff",
|
|
@@ -110,19 +107,21 @@ export function createCheckDiffTool({
|
|
|
110
107
|
_update: unknown,
|
|
111
108
|
ctx: { cwd: string } & GuideContext,
|
|
112
109
|
) {
|
|
110
|
+
const client = dependencies.client;
|
|
111
|
+
const cwd = await canonicalPath(ctx.cwd);
|
|
113
112
|
const exec = shareGitInventory(execute);
|
|
114
113
|
if (args.check === "docs" || args.check === "spec") {
|
|
115
114
|
const deps = { client, host, runtime, exec };
|
|
116
115
|
const result =
|
|
117
116
|
args.check === "docs"
|
|
118
117
|
? await runDocsCheck(deps, {
|
|
119
|
-
cwd:
|
|
118
|
+
cwd: cwd,
|
|
120
119
|
base: args.base,
|
|
121
120
|
signal,
|
|
122
121
|
maxCalls: args.max_calls,
|
|
123
122
|
})
|
|
124
123
|
: await runSpecCheck(deps, {
|
|
125
|
-
cwd:
|
|
124
|
+
cwd: cwd,
|
|
126
125
|
base: args.base,
|
|
127
126
|
specPath: args.spec_path,
|
|
128
127
|
signal,
|
|
@@ -226,14 +225,14 @@ export function createCheckDiffTool({
|
|
|
226
225
|
};
|
|
227
226
|
};
|
|
228
227
|
if (!client) return finish(NOT_CONFIGURED);
|
|
229
|
-
const comparison = await resolveBase(exec,
|
|
228
|
+
const comparison = await resolveBase(exec, cwd, args.base, signal);
|
|
230
229
|
if (!comparison.ok) return finish(comparison.error);
|
|
231
230
|
const base = comparison.base;
|
|
232
231
|
const analysis = await createAnalysisContext();
|
|
233
232
|
const collected = await collectUnits(
|
|
234
233
|
exec,
|
|
235
234
|
{
|
|
236
|
-
cwd:
|
|
235
|
+
cwd: cwd,
|
|
237
236
|
base,
|
|
238
237
|
signal,
|
|
239
238
|
},
|
|
@@ -274,6 +273,7 @@ export function createCheckDiffTool({
|
|
|
274
273
|
let reservedMatrixCalls = batches.batches.length;
|
|
275
274
|
const optionsFor = (matrixRequest = false): JudgmentOptions => ({
|
|
276
275
|
signal,
|
|
276
|
+
...runtime.session.requestGate(),
|
|
277
277
|
beforeRequest(questionCount) {
|
|
278
278
|
if (matrixRequest && reservedMatrixCalls > 0) reservedMatrixCalls--;
|
|
279
279
|
const limit =
|
|
@@ -315,7 +315,7 @@ export function createCheckDiffTool({
|
|
|
315
315
|
)
|
|
316
316
|
? await collectRiskCallers(
|
|
317
317
|
exec,
|
|
318
|
-
{ cwd:
|
|
318
|
+
{ cwd: cwd, base, signal },
|
|
319
319
|
collected.units,
|
|
320
320
|
collected.files,
|
|
321
321
|
analysis.parser,
|
package/src/tools/docs-check.ts
CHANGED
package/src/tools/find.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type Static, Type } from "@sinclair/typebox";
|
|
2
|
+
import { canonicalPath } from "../adapters/canonical-path.ts";
|
|
2
3
|
import { collectSearchExcerpts } from "../adapters/files.ts";
|
|
3
4
|
import { prefilter } from "../adapters/find.ts";
|
|
4
5
|
import { shareGitInventory } from "../adapters/git-inventory.ts";
|
|
@@ -46,12 +47,8 @@ export const findParameters = Type.Object(
|
|
|
46
47
|
{ additionalProperties: false },
|
|
47
48
|
);
|
|
48
49
|
export type FindArgs = Static<typeof findParameters>;
|
|
49
|
-
export function createFindFilesTool({
|
|
50
|
-
|
|
51
|
-
host,
|
|
52
|
-
runtime,
|
|
53
|
-
exec: execute,
|
|
54
|
-
}: ToolDependencies) {
|
|
50
|
+
export function createFindFilesTool(dependencies: ToolDependencies) {
|
|
51
|
+
const { host, runtime, exec: execute } = dependencies;
|
|
55
52
|
return {
|
|
56
53
|
name: "jev_find_files",
|
|
57
54
|
label: "Jev find files",
|
|
@@ -77,6 +74,8 @@ export function createFindFilesTool({
|
|
|
77
74
|
_update: unknown,
|
|
78
75
|
ctx: { cwd: string } & GuideContext,
|
|
79
76
|
) {
|
|
77
|
+
const client = dependencies.client;
|
|
78
|
+
const cwd = await canonicalPath(ctx.cwd);
|
|
80
79
|
const started = performance.now();
|
|
81
80
|
const exec = shareGitInventory(execute);
|
|
82
81
|
const totals = {
|
|
@@ -133,7 +132,7 @@ export function createFindFilesTool({
|
|
|
133
132
|
: C.FIND_FILES_READ;
|
|
134
133
|
const candidates = await prefilter(
|
|
135
134
|
exec,
|
|
136
|
-
|
|
135
|
+
cwd,
|
|
137
136
|
keywords,
|
|
138
137
|
candidateLimit,
|
|
139
138
|
args.scope,
|
|
@@ -193,6 +192,7 @@ export function createFindFilesTool({
|
|
|
193
192
|
): Promise<Judgment> => {
|
|
194
193
|
const result = await client.judge(state, questions, {
|
|
195
194
|
signal,
|
|
195
|
+
...runtime.session.requestGate(),
|
|
196
196
|
beforeRequest: (count) => {
|
|
197
197
|
if (args.max_calls !== undefined && sent >= args.max_calls) {
|
|
198
198
|
budget = {
|
|
@@ -311,7 +311,7 @@ export function createFindFilesTool({
|
|
|
311
311
|
const contentResults = await Promise.all(
|
|
312
312
|
contentBatches.map(async (paths) => {
|
|
313
313
|
const read = await collectSearchExcerpts(
|
|
314
|
-
|
|
314
|
+
cwd,
|
|
315
315
|
paths,
|
|
316
316
|
keywords,
|
|
317
317
|
signal,
|
package/src/tools/locate.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ToolDefinition } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import { type Static, Type } from "@sinclair/typebox";
|
|
3
|
+
import { canonicalPath } from "../adapters/canonical-path.ts";
|
|
3
4
|
import { shareGitInventory } from "../adapters/git-inventory.ts";
|
|
4
5
|
import { readLocateFile, scanRange } from "../adapters/locate-file.ts";
|
|
5
6
|
import { loadSyntaxParser } from "../adapters/syntax.ts";
|
|
@@ -43,9 +44,10 @@ const parameters = Type.Object(
|
|
|
43
44
|
type LocateArgs = Static<typeof parameters>;
|
|
44
45
|
|
|
45
46
|
export function createLocateTool(
|
|
46
|
-
|
|
47
|
+
dependencies: ToolDependencies,
|
|
47
48
|
loadParser: () => Promise<SyntaxParser | undefined> = loadSyntaxParser,
|
|
48
49
|
) {
|
|
50
|
+
const { host, runtime, exec: execute } = dependencies;
|
|
49
51
|
return {
|
|
50
52
|
name: "jev_locate_in_file",
|
|
51
53
|
label: "Jev locate in file",
|
|
@@ -72,6 +74,8 @@ export function createLocateTool(
|
|
|
72
74
|
_update: unknown,
|
|
73
75
|
ctx: { cwd: string } & GuideContext,
|
|
74
76
|
) {
|
|
77
|
+
const client = dependencies.client;
|
|
78
|
+
const cwd = await canonicalPath(ctx.cwd);
|
|
75
79
|
const started = performance.now();
|
|
76
80
|
const exec = shareGitInventory(execute);
|
|
77
81
|
const results: Judgment[] = [];
|
|
@@ -116,7 +120,7 @@ export function createLocateTool(
|
|
|
116
120
|
),
|
|
117
121
|
};
|
|
118
122
|
};
|
|
119
|
-
const file = await readLocateFile(
|
|
123
|
+
const file = await readLocateFile(cwd, args.path, signal, exec);
|
|
120
124
|
if (!file.ok) return finish({ refusal: file.error });
|
|
121
125
|
if (file.bytes < LOCATE_MIN_KB * 1000)
|
|
122
126
|
return finish({
|
|
@@ -180,6 +184,7 @@ export function createLocateTool(
|
|
|
180
184
|
},
|
|
181
185
|
{
|
|
182
186
|
signal,
|
|
187
|
+
...runtime.session.requestGate(),
|
|
183
188
|
beforeRequest: (n) => runtime.session.admit(n),
|
|
184
189
|
onUsage: (usage) => runtime.session.recordUsage(usage),
|
|
185
190
|
},
|
|
@@ -268,13 +273,7 @@ export function createLocateTool(
|
|
|
268
273
|
});
|
|
269
274
|
}
|
|
270
275
|
if (file.kind === "outline") {
|
|
271
|
-
const selected = await scanRange(
|
|
272
|
-
ctx.cwd,
|
|
273
|
-
args.path,
|
|
274
|
-
block,
|
|
275
|
-
signal,
|
|
276
|
-
exec,
|
|
277
|
-
);
|
|
276
|
+
const selected = await scanRange(cwd, args.path, block, signal, exec);
|
|
278
277
|
if (!selected.ok) return finish({ refusal: selected.error });
|
|
279
278
|
const lines = selected.text.split("\n");
|
|
280
279
|
sections = sections
|
|
@@ -2,6 +2,7 @@ import { matchesGlob, relative, resolve } from "node:path";
|
|
|
2
2
|
import type { ToolDefinition } from "@earendil-works/pi-coding-agent";
|
|
3
3
|
import { type Static, Type } from "@sinclair/typebox";
|
|
4
4
|
import { createAnalysisContext } from "../adapters/analysis-context.ts";
|
|
5
|
+
import { canonicalPath } from "../adapters/canonical-path.ts";
|
|
5
6
|
import { collectUnits } from "../adapters/git.ts";
|
|
6
7
|
import { resolveBase } from "../adapters/git-base.ts";
|
|
7
8
|
import { shareGitInventory } from "../adapters/git-inventory.ts";
|
|
@@ -104,12 +105,8 @@ function makeCandidate(
|
|
|
104
105
|
};
|
|
105
106
|
}
|
|
106
107
|
|
|
107
|
-
export function createSelectTestsTool({
|
|
108
|
-
|
|
109
|
-
host,
|
|
110
|
-
runtime,
|
|
111
|
-
exec: execute,
|
|
112
|
-
}: ToolDependencies) {
|
|
108
|
+
export function createSelectTestsTool(dependencies: ToolDependencies) {
|
|
109
|
+
const { host, runtime, exec: execute } = dependencies;
|
|
113
110
|
return {
|
|
114
111
|
name: "jev_select_tests",
|
|
115
112
|
label: "Jev select tests",
|
|
@@ -128,6 +125,8 @@ export function createSelectTestsTool({
|
|
|
128
125
|
_update: unknown,
|
|
129
126
|
ctx: { cwd: string } & GuideContext,
|
|
130
127
|
) {
|
|
128
|
+
const client = dependencies.client;
|
|
129
|
+
const cwd = await canonicalPath(ctx.cwd);
|
|
131
130
|
const started = performance.now();
|
|
132
131
|
const exec = shareGitInventory(execute);
|
|
133
132
|
const totals = {
|
|
@@ -171,14 +170,14 @@ export function createSelectTestsTool({
|
|
|
171
170
|
...hostUsage(host.isOmp, costKnown ? totals.usage : undefined),
|
|
172
171
|
};
|
|
173
172
|
};
|
|
174
|
-
const comparison = await resolveBase(exec,
|
|
173
|
+
const comparison = await resolveBase(exec, cwd, args.base, signal);
|
|
175
174
|
if (!comparison.ok) return finish({ refusal: comparison.error });
|
|
176
175
|
const analysis = await createAnalysisContext();
|
|
177
176
|
const [inventory, diff] = await Promise.all([
|
|
178
|
-
collectTestInventory(exec,
|
|
177
|
+
collectTestInventory(exec, cwd, signal),
|
|
179
178
|
collectUnits(
|
|
180
179
|
exec,
|
|
181
|
-
{ cwd:
|
|
180
|
+
{ cwd: cwd, base: comparison.base, signal },
|
|
182
181
|
analysis.parser,
|
|
183
182
|
),
|
|
184
183
|
]);
|
|
@@ -390,6 +389,7 @@ export function createSelectTestsTool({
|
|
|
390
389
|
const result = await client.judge(state, questions, {
|
|
391
390
|
signal,
|
|
392
391
|
witnesses: witnessIds,
|
|
392
|
+
...runtime.session.requestGate(),
|
|
393
393
|
beforeRequest: (questionCount) => {
|
|
394
394
|
if (args.max_calls !== undefined && sent >= args.max_calls) {
|
|
395
395
|
budget = {
|
|
@@ -738,7 +738,7 @@ export function createSelectTestsTool({
|
|
|
738
738
|
lines: commands.commands.map((command) => ({
|
|
739
739
|
type: "command" as const,
|
|
740
740
|
...command,
|
|
741
|
-
cwd: relative(
|
|
741
|
+
cwd: relative(cwd, resolve(inventory.cwd, command.cwd)) || ".",
|
|
742
742
|
})),
|
|
743
743
|
});
|
|
744
744
|
},
|
package/src/tools/spec-check.ts
CHANGED
|
@@ -175,6 +175,7 @@ export async function runSpecCheck(
|
|
|
175
175
|
if (!units.length) return finish();
|
|
176
176
|
const judgment = await deps.client.judge(prepared.state, prepared.questions, {
|
|
177
177
|
signal: input.signal,
|
|
178
|
+
...deps.runtime.session.requestGate(),
|
|
178
179
|
beforeRequest(questionCount) {
|
|
179
180
|
if (input.maxCalls !== undefined && sent >= input.maxCalls) {
|
|
180
181
|
budget = {
|