jev-agent-tools 0.1.4 → 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 +106 -1
- package/CONTRIBUTING.md +43 -0
- package/README.md +58 -17
- package/SECURITY.md +43 -0
- package/dist/adapters/analysis-context.js +75 -0
- package/dist/adapters/ask-files.js +198 -0
- package/dist/adapters/ask-proof.js +200 -0
- package/dist/adapters/ask-syntax.js +385 -0
- package/dist/adapters/canonical-path.js +17 -0
- package/dist/adapters/command.js +234 -0
- package/dist/adapters/docs.js +192 -0
- package/dist/adapters/evidence-context.js +119 -0
- package/dist/adapters/exec.js +207 -0
- package/dist/adapters/files.js +418 -0
- package/dist/adapters/find.js +150 -0
- package/dist/adapters/git-base.js +32 -0
- package/dist/adapters/git-inventory.js +71 -0
- package/dist/adapters/git.js +483 -0
- package/dist/adapters/locate-file.js +197 -0
- package/dist/adapters/output-lines.js +46 -0
- package/dist/adapters/private-storage.js +106 -0
- package/dist/adapters/risk-callers.js +429 -0
- package/dist/adapters/runner-version.js +78 -0
- package/dist/adapters/shell.js +92 -0
- package/dist/adapters/syntax.js +187 -0
- package/dist/adapters/test-inventory.js +139 -0
- package/dist/adapters/usage.js +20 -0
- package/dist/adapters/utf8.js +47 -0
- package/dist/configuration.js +267 -0
- package/dist/constants.js +140 -0
- package/dist/core/ask-closure.js +282 -0
- package/dist/core/ask-proof.js +1 -0
- package/dist/core/ask-references.js +278 -0
- package/dist/core/asks.js +507 -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 +137 -0
- package/dist/core/pointer.js +29 -0
- package/dist/core/result-report.js +302 -0
- package/dist/core/risk-callers.js +851 -0
- package/dist/core/runner-version.js +45 -0
- package/dist/core/secret-path.js +34 -0
- package/dist/core/sections.js +230 -0
- package/dist/core/state.js +51 -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 +456 -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 +210 -0
- package/dist/mcp/tools.js +129 -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 +114 -0
- package/dist/report-schema.js +1356 -0
- package/dist/result-types.js +1 -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 +3 -0
- package/dist/texts/ask.js +4 -0
- package/dist/texts/check-diff.js +20 -0
- package/dist/texts/configuration.js +1 -0
- package/dist/texts/find.js +19 -0
- package/dist/texts/guide.js +3 -0
- package/dist/texts/instructions.js +72 -0
- package/dist/texts/locate.js +15 -0
- package/dist/texts/select-tests.js +4 -0
- package/dist/tools/ask-files.js +450 -0
- package/dist/tools/ask-schema.js +70 -0
- package/dist/tools/ask.js +1147 -0
- package/dist/tools/check-diff.js +594 -0
- package/dist/tools/docs-check.js +408 -0
- package/dist/tools/find.js +682 -0
- package/dist/tools/locate.js +602 -0
- package/dist/tools/review-report.js +230 -0
- package/dist/tools/select-tests.js +821 -0
- package/dist/tools/spec-check.js +263 -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 +120 -0
- package/docs/design.md +16 -4
- package/docs/mcp.md +233 -0
- 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 +19 -4
- package/rules/jev-ask.md +22 -1
- package/server.json +57 -0
- package/src/adapters/ask-files.ts +11 -3
- package/src/adapters/ask-proof.ts +69 -11
- package/src/adapters/canonical-path.ts +18 -0
- package/src/adapters/command.ts +102 -36
- package/src/adapters/docs.ts +33 -14
- package/src/adapters/evidence-context.ts +169 -0
- package/src/adapters/exec.ts +226 -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 +155 -0
- package/src/adapters/risk-callers.ts +7 -2
- package/src/adapters/shell.ts +113 -0
- package/src/adapters/test-inventory.ts +12 -4
- package/src/configuration.ts +55 -14
- package/src/constants.ts +37 -5
- package/src/core/ask-references.ts +262 -146
- package/src/core/asks.ts +79 -7
- package/src/core/command-output.ts +17 -1
- 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/host.ts +11 -0
- package/src/index.ts +3 -0
- package/src/jev/client.ts +66 -16
- package/src/jev/types.ts +24 -3
- package/src/mcp/main.ts +135 -0
- package/src/mcp/protocol.ts +332 -0
- package/src/mcp/tools.ts +179 -0
- 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/session.ts +59 -0
- package/src/setup.ts +13 -5
- 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 +311 -18
- package/src/tools/ask.ts +722 -95
- package/src/tools/check-diff.ts +337 -31
- package/src/tools/docs-check.ts +241 -38
- package/src/tools/find.ts +389 -29
- package/src/tools/locate.ts +387 -25
- package/src/tools/review-report.ts +308 -0
- package/src/tools/select-tests.ts +484 -23
- package/src/tools/spec-check.ts +194 -19
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,109 @@ modules are not a stable library API.
|
|
|
9
9
|
|
|
10
10
|
## [Unreleased]
|
|
11
11
|
|
|
12
|
+
## [0.3.0] - 2026-10-05
|
|
13
|
+
|
|
14
|
+
### Breaking
|
|
15
|
+
|
|
16
|
+
- `JEV_TOOLS_URL` (and saved or flag URLs) with plain `http:` is refused unless the host is `127.0.0.1`, `::1` or `localhost`; use `https:`. The configuration error shows neither the URL nor the key and occurs before any request.
|
|
17
|
+
- Files whose base name matches `.env`, `.env.*`, `*.pem`, `id_rsa*`, `*.p12`, `credentials*` or `secrets*` (any depth, case-insensitive; `.env.example`, `.env.sample` and `.env.template` excepted) are refused before reading on every evidence path, including diff units, test inventory, find, locate, ask-files and the pi/omp documentation hook. Each refusal is a named exclusion with the new cause `secret_pattern`; a question that explicitly requires such a file stays unjudged. There is no override.
|
|
18
|
+
|
|
19
|
+
### Security
|
|
20
|
+
|
|
21
|
+
- `jev_ask` commands and the Windows PowerShell ACL helper no longer inherit `JEV_TOOLS_API_KEY`. The configured key value (environment or saved configuration) is replaced with `[redacted]` in command output before state assembly, including a key prefix left where a long output line is cut, and the number of replacements is reported as a limitation.
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
|
|
25
|
+
- Optional `root` on all six tools, limited to the initial repository's exact Git root or registered live worktrees with the same common directory; invalid overrides refuse before evidence, commands, cache or judgments.
|
|
26
|
+
- Versioned typed reports for every tool outcome, including refused and unjudged work: evidence context, item provenance, scoped diagnostics/actions and separate requested-result, HTTP, cache, control, passage and cost accounting.
|
|
27
|
+
- MCP output schema and structured results from protocol 2025-06-18 onward, with self-contained text for older clients and per-request version isolation.
|
|
28
|
+
|
|
29
|
+
### Changed
|
|
30
|
+
|
|
31
|
+
- Explicit evidence selectors, rather than ordinary lexical mentions, govern missing-evidence exclusions. Canonical file versions are serialized once with alias metadata; before/current evidence remains distinct and missing requirements affect their own question group unless global.
|
|
32
|
+
- Host guidance now makes Jev discretionary, shares versioned canonical fragments across pi/omp/MCP, and reports current conclusions with evidence provenance and material reservations. The pi/omp opt-out documentation hook remains; MCP requires no manual replacement call.
|
|
33
|
+
- Human output is a projection of the typed report. Static/fallback selection and unavailable judgments never acquire fabricated probabilities; cached results are distinct from fresh requests and unknown cost is not zero.
|
|
34
|
+
|
|
35
|
+
### Fixed
|
|
36
|
+
|
|
37
|
+
- Historical-only and deleted-file evidence resolution, supplied-file basename precedence and canonical file-count admission without duplicated alias content.
|
|
38
|
+
- Command output reaches bounded passage selection before immutable-evidence budget refusal, including base snapshots and import closure; reports preserve actual command execution/cwd even when later collection fails.
|
|
39
|
+
- Selection reports distinguish unmatched candidate criteria, partial matches, excluded inventory and named conservative-widening triggers from absence of affected tests.
|
|
40
|
+
- Review reports retain documentation completeness/collection reservations and risk/coverage witness diagnostics. Residual absence summaries remain derived observations within the considered inventory, not extra judgments or global coverage claims.
|
|
41
|
+
- Recovery actions preserve the actual evidence/control limitation instructions rather than generic repetition advice.
|
|
42
|
+
- Local-caller reports preserve their independent unsure/abstain bands and matching probabilities; specification drift remains one pointer decision rather than duplicated judgments for every candidate unit.
|
|
43
|
+
- MCP malformed tool arguments remain JSON-RPC invalid-parameter errors, separate from well-formed calls refused by evidence admission.
|
|
44
|
+
- Every judgment stage binds cache identity and serialized admission to its admitted root/base context, including auxiliary command passages. Locate planning reserves that metadata capacity before allocating evidence.
|
|
45
|
+
- Historical selectors use protected base reads for ignored paths, symlinks, non-text content and deleted files; current/base versions share the distinct-file ceiling without bypassing rejected admissions.
|
|
46
|
+
|
|
47
|
+
## [0.2.0] - 2026-10-03
|
|
48
|
+
|
|
49
|
+
### Added
|
|
50
|
+
|
|
51
|
+
- `jev-agent-tools-mcp`: a dependency-free MCP stdio server exposing the same six
|
|
52
|
+
tools to any MCP client. It reuses the existing tool factories, session limits,
|
|
53
|
+
HTTP client and saved configuration; the binary ships as compiled JavaScript built
|
|
54
|
+
by `npm run build`.
|
|
55
|
+
- MCP setup guide (`docs/mcp.md`) and a project instruction template for MCP agents
|
|
56
|
+
(`docs/agent-instructions.md`, for `CLAUDE.md`, `AGENTS.md` or Kiro steering).
|
|
57
|
+
- `JEV_TOOLS_BASH` and `JEV_TOOLS_ROOT` settings (Windows bash path; MCP root).
|
|
58
|
+
- MCP Registry publication: `server.json` (`io.github.NomenAK/jev-agent-tools`) and
|
|
59
|
+
`mcpName` in `package.json`. After the npm publish, the release workflow waits for the
|
|
60
|
+
approved version and its `mcpName` on npm, then publishes with a pinned, checksum-verified
|
|
61
|
+
`mcp-publisher` over GitHub OIDC; an existing registry version is skipped only
|
|
62
|
+
when its server definition matches the approved tarball's metadata.
|
|
63
|
+
- `scripts/check-mcp-package.ts`: CI and release gate that installs the packed
|
|
64
|
+
tarball, checks modern discovery and all advertised legacy handshakes, and
|
|
65
|
+
exercises `jev_ask` against a local synthetic HTTP endpoint.
|
|
66
|
+
- Native Windows and macOS CI for MCP, managed process termination, private
|
|
67
|
+
configuration, platform paths and the installed package; Linux retains the
|
|
68
|
+
complete offline suite.
|
|
69
|
+
|
|
70
|
+
### Changed
|
|
71
|
+
|
|
72
|
+
- The npm package now includes `SECURITY.md` and `docs/adr/`, which shipped
|
|
73
|
+
documentation already linked to.
|
|
74
|
+
|
|
75
|
+
### Fixed
|
|
76
|
+
|
|
77
|
+
- MCP command cancellation and timeout now finish process-group escalation even
|
|
78
|
+
when the parent shell exits first. Closing stdin, SIGTERM and SIGINT drain
|
|
79
|
+
outstanding tool calls before the server exits; cancelled calls stay silent.
|
|
80
|
+
- Windows command cleanup maps MSYS descendants before forced termination, so
|
|
81
|
+
Git Bash fork/exec no longer hides ordinary descendants from `taskkill /T`.
|
|
82
|
+
- Package checks use local archive paths on Windows and macOS; private-storage
|
|
83
|
+
test fixtures use canonical macOS temporary paths without relaxing symlink checks.
|
|
84
|
+
- Modern MCP discovery now includes server identity in result metadata, and
|
|
85
|
+
tool lists declare immediately stale, private caching as required by the
|
|
86
|
+
2026-07-28 protocol.
|
|
87
|
+
- MCP Registry reruns skip only an identical server definition. Divergent,
|
|
88
|
+
malformed or inconclusive responses fail; registry metadata is checked
|
|
89
|
+
against `server.json` inside the approved tarball before lookup.
|
|
90
|
+
|
|
91
|
+
- In omp, first-launch Jev setup no longer waits for credential entry inside the
|
|
92
|
+
bounded `session_start` handler. The offer and input dialogs stay open while
|
|
93
|
+
users find their endpoint and key, rather than closing after the host's
|
|
94
|
+
30-second event deadline.
|
|
95
|
+
- `JEV_TOOLS_MAX_USD` could be overshot by up to seven requests: concurrent batches
|
|
96
|
+
were all admitted before any cost was reported. Under a USD limit, requests are
|
|
97
|
+
now admitted one at a time, so only the final admitted request can exceed it.
|
|
98
|
+
- Windows: `jev_ask` commands ran `env CI=1 bash`, which fails without `env` and
|
|
99
|
+
resolves to the WSL launcher. Git for Windows bash is now used.
|
|
100
|
+
- Windows: imported providers were never found for `jev_check_diff` risk callers
|
|
101
|
+
because a repository path was resolved with platform path semantics.
|
|
102
|
+
- Windows: node:test `file:///C:/...` failure locations (including `%20`) were not
|
|
103
|
+
mapped back to repository files.
|
|
104
|
+
- Windows: an 8.3 short working directory (for example `C:\Users\NAME~1`) did not
|
|
105
|
+
relate to the Git root, which emptied import closures and file references.
|
|
106
|
+
- Line endings are pinned to LF via `.gitattributes`, so lint and the rule/guideline
|
|
107
|
+
parity check pass on Windows checkouts with `core.autocrlf=true`.
|
|
108
|
+
- Windows: saving or loading `/jev-setup` configuration always failed, because the
|
|
109
|
+
privacy check read POSIX mode bits, which Windows reports as `0o666` for every file.
|
|
110
|
+
Windows now checks the folder and file access lists (allow entries limited to the
|
|
111
|
+
current user, SYSTEM and Administrators) and restricts a new folder when saving.
|
|
112
|
+
- Tests: `secret-input` passed a `C:\` path to `import()`; the risk-caller latency
|
|
113
|
+
test compared one run with a fixed 250 ms and now checks 250- to 1000-line scaling.
|
|
114
|
+
|
|
12
115
|
## [0.1.4] - 2026-10-02
|
|
13
116
|
|
|
14
117
|
### Added
|
|
@@ -74,7 +177,9 @@ Tagged but never published to npm: the unscoped package name was rejected.
|
|
|
74
177
|
|
|
75
178
|
Tagged but never published to npm: the publish workflow failed before upload.
|
|
76
179
|
|
|
77
|
-
[Unreleased]: https://github.com/NomenAK/jev-tools/compare/v0.
|
|
180
|
+
[Unreleased]: https://github.com/NomenAK/jev-tools/compare/v0.3.0...HEAD
|
|
181
|
+
[0.3.0]: https://github.com/NomenAK/jev-tools/compare/v0.2.0...v0.3.0
|
|
182
|
+
[0.2.0]: https://github.com/NomenAK/jev-tools/compare/v0.1.4...v0.2.0
|
|
78
183
|
[0.1.4]: https://github.com/NomenAK/jev-tools/compare/v0.1.3...v0.1.4
|
|
79
184
|
[0.1.3]: https://github.com/NomenAK/jev-tools/compare/v0.1.0...v0.1.3
|
|
80
185
|
[0.1.2]: https://github.com/NomenAK/jev-tools/tree/v0.1.2
|
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Issues and external pull requests are welcome. Use English for issues, pull requests, documentation, comments, and test descriptions; keep non-English fixtures when they test language or encoding behavior. For vulnerabilities, follow [SECURITY.md](SECURITY.md).
|
|
4
|
+
|
|
5
|
+
## Issues or pull requests?
|
|
6
|
+
|
|
7
|
+
Open an issue for a reproducible product bug or a feature request. Include the package and host versions, expected and actual behavior, and a minimal sanitized reproduction. Small, focused fixes or documentation corrections can go straight to a pull request. Discuss new tools, contract changes, and research-dependent features in an issue before implementing them.
|
|
8
|
+
|
|
9
|
+
An issue may describe an unmet need without claiming that a method already works. Features such as co-change suggestions are not accepted for implementation without a new, validated method. Propose the method, its evaluation protocol, and reproducible evidence in an issue first; an unvalidated heuristic or a renamed version of it is not enough.
|
|
10
|
+
|
|
11
|
+
## Local checks
|
|
12
|
+
|
|
13
|
+
Use Node.js 24 or newer and npm. From a checkout, with development dependencies enabled:
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
npm ci --include=optional
|
|
17
|
+
npm run typecheck
|
|
18
|
+
npm run build
|
|
19
|
+
npm run check:imports
|
|
20
|
+
npm run lint
|
|
21
|
+
node scripts/generate-instructions.ts --check
|
|
22
|
+
npm test
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
`npm run build` compiles only the MCP server into `dist/` (git-ignored); `npm pack` runs it automatically. To try the server against a checkout, see [From a clone](docs/mcp.md#from-a-clone). CI packs the package and runs `node scripts/check-mcp-package.ts <tarball>`: it installs the tarball into an empty directory, checks modern discovery and all advertised legacy handshakes, lists the six tools with their schemas and caching fields, and runs `jev_ask` through a local synthetic HTTP endpoint. This verifies installed integration, not live model accuracy. Linux runs the full offline suite; native Windows and macOS jobs run targeted MCP, process, configuration and packaging checks.
|
|
26
|
+
|
|
27
|
+
Agent policy and result-reading guidance are versioned in `src/texts/instructions.ts`. After changing them, run `node scripts/generate-instructions.ts` to update the checked-in omp rule and MCP project block; `--check` verifies that those copies remain synchronized. Keep host differences explicit rather than maintaining independent policy text.
|
|
28
|
+
|
|
29
|
+
## Releases
|
|
30
|
+
|
|
31
|
+
Maintainers release by pushing a `vX.Y.Z` tag on reviewed `main`. Before tagging, set the same version in `package.json`, in both `version` fields of `server.json`, and in a `CHANGELOG.md` section; `test/server-json.test.ts` fails if they drift. [`publish.yml`](.github/workflows/publish.yml) then packs once, checks the packed MCP server, publishes the approved tarball to npm with trusted publishing, publishes `server.json` to the MCP Registry with GitHub OIDC, and creates a draft GitHub Release. Each publication step skips a version that already exists with the same content and fails on anything inconclusive.
|
|
32
|
+
|
|
33
|
+
Keep optional native dependencies enabled for development. These checks make no Jev API calls and need no Jev key. Dependency installation may use the network. Some runner-identity tests skip when additional runners are unavailable locally; CI provisions those runners in [.github/workflows/ci.yml](.github/workflows/ci.yml).
|
|
34
|
+
|
|
35
|
+
Maintainers run a private regression probe on reviewed release candidates before release and on the published package before announcing it. Contributors do not need access to that probe or its credentials.
|
|
36
|
+
|
|
37
|
+
## Pull request expectations
|
|
38
|
+
|
|
39
|
+
Keep changes focused. Explain the user-visible behavior, link the relevant issue when there is one, and report the checks you actually ran, including skips or limitations. Add or update deterministic tests for changed behavior and regressions, and update affected documentation. Public CI must pass without service credentials.
|
|
40
|
+
|
|
41
|
+
Do not make accuracy, recall, speed, or other measurement claims without describing the method, baseline, data, and limitations sufficiently to reproduce and review them. Do not include credentials, raw service responses, private data, or personal configuration in issues, patches, or logs. Use synthetic or sanitized examples.
|
|
42
|
+
|
|
43
|
+
Check the name and email attached to your commits before submitting; GitHub's noreply email is an option if you do not want to publish a personal email address.
|
package/README.md
CHANGED
|
@@ -1,28 +1,55 @@
|
|
|
1
1
|
# jev-agent-tools
|
|
2
2
|
|
|
3
|
-
Six evidence-oriented tools for pi and
|
|
3
|
+
Six evidence-oriented tools for pi, omp and any MCP client, compatible with the Jev API format. Use them to navigate unfamiliar code, ask typed questions about repository evidence, review completed changes and select existing tests. They complement reading, searching and execution; they do not replace them.
|
|
4
|
+
|
|
5
|
+
[](docs/media/jev-agent-tools-launch.mp4)
|
|
6
|
+
|
|
7
|
+
[Watch the launch video](docs/media/jev-agent-tools-launch.mp4) (74 s, MP4).
|
|
4
8
|
|
|
5
9
|
## Install
|
|
6
10
|
|
|
7
|
-
Install through your host's package manager. The npm package is `jev-agent-tools`.
|
|
11
|
+
Install through your host's package manager, or register the MCP server with an MCP client. The npm package is `jev-agent-tools`. pi and omp load its TypeScript sources directly; the MCP server ships prebuilt.
|
|
8
12
|
|
|
9
13
|
### pi
|
|
10
14
|
|
|
11
15
|
```sh
|
|
12
|
-
pi install npm:jev-agent-tools@0.
|
|
16
|
+
pi install npm:jev-agent-tools@0.3.0
|
|
13
17
|
# Project-local installation:
|
|
14
|
-
pi install -l npm:jev-agent-tools@0.
|
|
18
|
+
pi install -l npm:jev-agent-tools@0.3.0
|
|
15
19
|
```
|
|
16
20
|
|
|
17
21
|
### omp
|
|
18
22
|
|
|
19
23
|
```sh
|
|
20
|
-
omp plugin install jev-agent-tools@0.
|
|
24
|
+
omp plugin install jev-agent-tools@0.3.0
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Any MCP client
|
|
28
|
+
|
|
29
|
+
Since version 0.2.0, the package also ships `jev-agent-tools-mcp`, a stdio MCP server that exposes the same six tools to any MCP client: Claude Code, Claude Desktop, Kiro, Cursor, VS Code, Codex CLI and others. A typical `mcpServers` entry:
|
|
30
|
+
|
|
31
|
+
```json
|
|
32
|
+
{
|
|
33
|
+
"mcpServers": {
|
|
34
|
+
"jev": {
|
|
35
|
+
"command": "npx",
|
|
36
|
+
"args": ["-y", "-p", "jev-agent-tools", "jev-agent-tools-mcp", "--root", "/path/to/repository"],
|
|
37
|
+
"env": {
|
|
38
|
+
"JEV_TOOLS_URL": "${JEV_TOOLS_URL}",
|
|
39
|
+
"JEV_TOOLS_API_KEY": "${JEV_TOOLS_API_KEY}"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
21
44
|
```
|
|
22
45
|
|
|
46
|
+
On Windows most clients start commands without a shell, so use `"command": "cmd"` with `"/c", "npx"` at the start of `args`. The [MCP setup guide](docs/mcp.md) has per-client files, CLI commands, variable interpolation, verification and troubleshooting. Releases are also listed in the official MCP Registry as `io.github.NomenAK/jev-agent-tools`. Add the [agent instructions](docs/agent-instructions.md) to `CLAUDE.md`, `AGENTS.md` or a Kiro steering file so the agent uses and reads the tools correctly.
|
|
47
|
+
|
|
48
|
+
The server reads the same environment variables as pi and omp and the configuration saved by `/jev-setup`. One server process is one session. MCP has no automatic run-end documentation hook; its absence does not require manual replacement calls. `jev_ask` is marked as not read-only while commands are enabled; set `JEV_TOOLS_ALLOW_COMMAND=0` to remove `command` from its schema.
|
|
49
|
+
|
|
23
50
|
### Requirements and compatibility
|
|
24
51
|
|
|
25
|
-
Requires Node.js 24 or later. Supported host baselines are pi 0.87.1 and omp 18.4.10. These are support baselines, not claims that every later version has been individually validated. omp uses its Bun runtime; Node.js is also required for Node-based project checks. Git and, for optional command evidence, Bash must be available. Optional native parsers and file-search acceleration may be unavailable on some platforms; affected tools report their limitations.
|
|
52
|
+
Requires Node.js 24 or later. Supported host baselines are pi 0.87.1 and omp 18.4.10. These are support baselines, not claims that every later version has been individually validated. omp uses its Bun runtime; Node.js is also required for Node-based project checks. Git and, for optional command evidence, Bash must be available. On Windows, command evidence uses Git for Windows bash (found next to `git` on `PATH` or under Program Files); the WSL `bash.exe` launchers are never used. Set `JEV_TOOLS_BASH` to the full path of another bash. Optional native parsers and file-search acceleration may be unavailable on some platforms; affected tools report their limitations.
|
|
26
53
|
|
|
27
54
|
The published `jev-agent-tools@0.1.3` package was also checked with **pi 1.0.0** on Linux under Node.js 24.15.0: npm installation, TypeScript checking against the host types, all six tools in the actual CLI, and reading-guide injection passed. The CLI smoke used a simulated conversation provider and Jev endpoint; it verifies host integration, not live model accuracy or every tool scenario.
|
|
28
55
|
|
|
@@ -42,9 +69,11 @@ In the main interactive terminal of pi or omp, a first launch without configurat
|
|
|
42
69
|
|
|
43
70
|
No dialog appears in print, JSON or RPC modes, or in sub-agents; configure those with the environment variables below. Changes apply immediately, without restarting the host.
|
|
44
71
|
|
|
72
|
+
Interactive setup waits for submission or cancellation, without a credential-entry timeout. The first-launch offer does not keep the host's startup event handler open while you find the endpoint or key.
|
|
73
|
+
|
|
45
74
|
**Precedence per field:** environment variable, then launch flag, then this session's setup, then saved configuration, then the default model `openjev`. A field set by the environment or a flag is shown as controlled and is never saved.
|
|
46
75
|
|
|
47
|
-
**Saved configuration** lives outside the repository at `$XDG_CONFIG_HOME/jev-agent-tools/config.json` (default `~/.config/jev-agent-tools/config.json`), in a private directory (`0700`) with a private file (`0600`). **The key is stored in plaintext, not encrypted.** Storage that is a symlink,
|
|
76
|
+
**Saved configuration** lives outside the repository at `$XDG_CONFIG_HOME/jev-agent-tools/config.json` (default `~/.config/jev-agent-tools/config.json`), in a private directory (`0700`) with a private file (`0600`). On Windows, where mode bits do not exist, privacy is the folder's access list: saving restricts it to you, SYSTEM and Administrators, and loading refuses any other account with access. **The key is stored in plaintext, not encrypted.** Storage that is a symlink, accessible to other users, not owned by you or malformed is refused rather than overwritten. The MCP server also reads this file, after environment variables.
|
|
48
77
|
|
|
49
78
|
### Environment variables
|
|
50
79
|
|
|
@@ -61,13 +90,15 @@ export JEV_TOOLS_MODEL="openjev"
|
|
|
61
90
|
|
|
62
91
|
| Variable | Meaning |
|
|
63
92
|
|---|---|
|
|
64
|
-
| `JEV_TOOLS_URL` | Required complete endpoint URL compatible with the Jev API format. |
|
|
65
|
-
| `JEV_TOOLS_API_KEY` | Required Bearer credential; configuration values are not printed in tool output. |
|
|
93
|
+
| `JEV_TOOLS_URL` | Required complete endpoint URL compatible with the Jev API format. Must be `https:`; plain `http:` is accepted only for `127.0.0.1`, `::1` or `localhost`. |
|
|
94
|
+
| `JEV_TOOLS_API_KEY` | Required Bearer credential; configuration values are not printed in tool output, and command children never receive it. |
|
|
66
95
|
| `JEV_TOOLS_MODEL` | Requested model string, default `openjev`; a moving alias, not a guarantee of served-model identity. |
|
|
67
96
|
| `JEV_TOOLS_MAX_CALLS` | Session-wide non-negative safe-integer call limit; absent or empty means unlimited. Invalid values refuse requests. |
|
|
68
97
|
| `JEV_TOOLS_MAX_USD` | Session-wide finite non-negative cost limit, including fractions; absent or empty means unlimited. Invalid values refuse requests. |
|
|
69
98
|
| `JEV_TOOLS_ALLOW_COMMAND` | `0` disables `command` in `jev_ask`; otherwise commands run with ordinary shell permissions, without an additional sandbox. |
|
|
70
99
|
| `JEV_TOOLS_AUTO_DOCS` | `0` disables the automatic run-end documentation check. |
|
|
100
|
+
| `JEV_TOOLS_BASH` | Optional full path of the bash used for `jev_ask` commands on Windows. |
|
|
101
|
+
| `JEV_TOOLS_ROOT` | MCP server only: repository directory when `--root` is not given. |
|
|
71
102
|
|
|
72
103
|
Without the endpoint or key, tools remain registered and explain the missing configuration; the automatic documentation check is disabled. There is no fallback to a chat model. Per-tool `max_calls` is separate from session limits. A model name echoed by the response does not establish which model was actually served.
|
|
73
104
|
|
|
@@ -84,39 +115,49 @@ Without the endpoint or key, tools remain registered and explain the missing con
|
|
|
84
115
|
|
|
85
116
|
Use native read/search tools or code for exact source text, known symbols, filenames, line numbers, counts and arithmetic. Run commands yourself when you need their full output. Tool reference examples use fictional repository paths and are illustrative calls, not recorded executions.
|
|
86
117
|
|
|
118
|
+
### Evidence root
|
|
119
|
+
|
|
120
|
+
All six tools accept optional `root: string`. Without it, the host's current directory or configured MCP server directory retains its existing behavior. An override must name exactly the initial repository's Git top-level or a registered live worktree with the same canonical Git common directory. Relative overrides resolve against the initial directory; absolute paths are accepted only for this parameter. Subdirectories, other clones/repositories, parent traversal and symlink components are refused before evidence collection, command execution, cache access or judgment. There is no fallback to a different checkout.
|
|
121
|
+
|
|
122
|
+
The admitted root governs files, base/diff, inventories, specification paths, runner plans and command cwd for that call only. It does not change another call or the automatic documentation hook. File arguments remain repository-relative and confined. A command still has ordinary shell permissions, not a sandbox. Check the reported authority, requested/effective root and resolved base before using a result.
|
|
123
|
+
|
|
87
124
|
## Read the results
|
|
88
125
|
|
|
89
|
-
|
|
126
|
+
Each result begins with execution state: **complete**, **partial**, **not_judged** or **refused**. This describes processing, not correctness, safety or coverage. Items distinguish fresh or cached Jev judgments, static treatment and work never judged. Static selection and conservative fallback carry no invented probability. A judged line without an uncertainty mark is a **verdict**: a lead to check, not proof beyond the supplied evidence.
|
|
90
127
|
|
|
91
128
|
| Mark | Meaning and next action |
|
|
92
129
|
|---|---|
|
|
93
130
|
| `unsure` | The answer is ambiguous or a control failed. Read the indicated passage or add the specific evidence that would settle it. Do not merely reword the question. |
|
|
94
|
-
| `abstain` | A necessary piece is missing.
|
|
131
|
+
| `abstain` | A necessary piece is missing. Obtain the named evidence or leave the conclusion open; another Jev call is optional when the changed evidence makes it useful. |
|
|
95
132
|
| `no (not shown)` / `not addressed` | The supplied evidence does not show the statement; that does not make it false. |
|
|
96
133
|
| `uncalibrated` | No established error-rate calibration applies to this ask; treat it as a hint even if its probability is high. |
|
|
97
|
-
|
|
|
134
|
+
| Diagnostics and next actions | Typed cause, origin, affected scope, materiality and recovery instructions; distinguish uncertain judgments from work never judged. |
|
|
98
135
|
|
|
99
136
|
Ordinary boolean verdict bands are at or below 0.20 and at or above 0.80; category/level verdicts require a leading-option probability of at least 0.85 after applicable controls. Fixed checks and navigation tools have their own thresholds, described in their references and [design](docs/design.md).
|
|
100
137
|
|
|
101
|
-
|
|
138
|
+
Accounting separates **HTTP attempts**, **questions sent**, **requested results** (fresh/cache/static/not judged), **cache probes**, auxiliary controls and passage selection, current reported USD cost and elapsed time. These counts are not interchangeable. A cached judgment can have zero HTTP attempts; zero attempts can also mean static work or no judgment. Unknown cost is unreported, not free. Context values distinguish known, unknown, not collected and not applicable.
|
|
139
|
+
|
|
140
|
+
pi and omp expose the versioned report as `details.result`. MCP versions from 2025-06-18 expose the same report under `structuredContent.result` with an advertised output schema; older versions receive self-contained text from the same report. Text preserves material limitations, evidence provenance and useful read/runner commands.
|
|
102
141
|
|
|
103
|
-
|
|
142
|
+
Report current conclusions, decisive evidence with origin and scope, and material reservations. If native reading or execution settles an earlier `unsure` or `abstain` on the same context, attribute the current conclusion to that native evidence, not Jev. If uncertainty returned by Jev remains material, explicitly say Jev did not confirm the conclusion and name the missing evidence and impact. Independent limits, stale evidence and conflicting contexts remain visible. Reported checks are not observed execution; no exhaustive history block or new persistent register is required.
|
|
104
143
|
|
|
105
144
|
## Usage guidance for pi and omp
|
|
106
145
|
|
|
107
146
|
The extension supplies the shared reading guide in both hosts. omp discovers enabled npm plugin rules during normal startup; pi does not automatically discover the package's `rules/` directory. In pi, the same decision policy is part of the `jev_ask` tool guidelines, so it is present whenever `jev_ask` is active. A forced opaque prompt override may bypass this integration; disabled tools or disabled omp rules are not covered. This README block is recommended usage guidance, not itself an installed instruction:
|
|
108
147
|
|
|
109
|
-
>
|
|
148
|
+
> Use Jev for a bounded semantic judgment when it can change an open decision or focus inspection. Use decisive native reading, search or authorized execution directly. A Jev call is not a prerequisite for a conclusion, review or completion. When choosing a call, supply both sides of a comparison and the evidence that distinguishes explanations. Revisit only when changed evidence, context or a useful new question warrants it; repeating unchanged evidence is not a recovery action.
|
|
149
|
+
|
|
150
|
+
MCP clients receive the guide as server `instructions`, which some clients ignore. Add the [agent instructions](docs/agent-instructions.md) to the project's `CLAUDE.md`, `AGENTS.md` or Kiro steering file.
|
|
110
151
|
|
|
111
152
|
## Data and command safety
|
|
112
153
|
|
|
113
154
|
Repository evidence, notes and optional command output are sent to your configured endpoint. Review its data-handling policy before using confidential repositories. See [security guidance](SECURITY.md).
|
|
114
155
|
|
|
115
|
-
File collection is confined to the repository: absolute paths, parent traversal, escaping symlinks, Git metadata and internal URLs are not file inputs. Build output, binaries, lockfiles and oversized files are skipped or refused with visible limits; evidence is not silently truncated into a verdict. This confinement does **not** sandbox a command. `jev_ask` commands can read, write or access the network with the host's shell permissions. omp uses execution approval for commands; pi does not supply an additional per-tool command approval. Set `JEV_TOOLS_ALLOW_COMMAND=0` to disable them.
|
|
156
|
+
File collection is confined to the repository: absolute paths, parent traversal, escaping symlinks, Git metadata and internal URLs are not file inputs. Files named like secrets (`.env`, `.env.*` except `.env.example`/`.env.sample`/`.env.template`, `*.pem`, `id_rsa*`, `*.p12`, `credentials*`, `secrets*`, any depth, any case) are refused before reading and named with cause `secret_pattern`. Build output, binaries, lockfiles and oversized files are skipped or refused with visible limits; evidence is not silently truncated into a verdict. This confinement does **not** sandbox a command. `jev_ask` commands can read, write or access the network with the host's shell permissions; they run without `JEV_TOOLS_API_KEY`, and the configured key is replaced with `[redacted]` in their output. omp uses execution approval for commands; pi does not supply an additional per-tool command approval; MCP clients apply their own tool approval, and the server marks `jev_ask` as not read-only. Set `JEV_TOOLS_ALLOW_COMMAND=0` to disable them.
|
|
116
157
|
|
|
117
158
|
## Automatic documentation check
|
|
118
159
|
|
|
119
|
-
On a dirty tree, the extension can check existing Markdown documentation once at run end against changes from `HEAD`, including untracked files. A flagged existing sentence can request one additional turn to update it or explain why it remains correct. Merely unsure sections do not trigger another turn.
|
|
160
|
+
On a dirty tree, the extension can check existing Markdown documentation once at run end against changes from `HEAD`, including admitted untracked files (not gitignored, not secret-named), which are sent to the endpoint without an explicit tool call. A flagged existing sentence can request one additional turn to inspect and update it or explain with evidence why it remains correct; a flag does not itself establish falsehood or require a second call. Merely unsure sections do not trigger another turn. `JEV_TOOLS_AUTO_DOCS=0`, missing configuration, invalid/exhausted session budgets or a clean tree skip the check. Errors and timeout do not block the host. This opt-out host feature does not certify documentation completeness. MCP has no hook and requires no manual replacement ritual.
|
|
120
161
|
|
|
121
162
|
## Known limits
|
|
122
163
|
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Security policy
|
|
2
|
+
|
|
3
|
+
## Supported versions
|
|
4
|
+
|
|
5
|
+
Security fixes target the latest patch release in the 0.1.x series. Older 0.1.x patches should be upgraded; 0.0.x and unreleased snapshots are not supported releases.
|
|
6
|
+
|
|
7
|
+
## Report privately
|
|
8
|
+
|
|
9
|
+
Use GitHub's [Report a vulnerability](https://github.com/NomenAK/jev-tools/security/advisories/new) form. Do not disclose vulnerabilities in public issues or pull requests. If the form is unavailable, open an issue asking to restore private reporting, without vulnerability details. There is no email reporting channel.
|
|
10
|
+
|
|
11
|
+
Include the affected version, impact, and a minimal reproduction using synthetic data. Never include live credentials, private repository contents, or personal configuration. If a credential may have been exposed, revoke or rotate it independently of this report.
|
|
12
|
+
|
|
13
|
+
This is a solo-maintained project. Reports are reviewed on a best-effort basis; there is no guaranteed acknowledgement or fix deadline. Follow-up and disclosure coordination take place in the private report. Please coordinate public disclosure there.
|
|
14
|
+
|
|
15
|
+
## Scope and trust boundaries
|
|
16
|
+
|
|
17
|
+
Report repository-confinement escapes in file evidence collection, including reads outside the selected repository; unintended secret exposure caused by jev-tools; and unintended command execution or bypasses of disabled command execution.
|
|
18
|
+
|
|
19
|
+
File evidence collection is confined to the repository, but optional commands are not sandboxed: they run with the host's permissions and may read or modify files or access the network. `JEV_TOOLS_ALLOW_COMMAND=0` disables this command path. Selected repository evidence and requested command output are sent to the configured API endpoint. Review the data and endpoint before use.
|
|
20
|
+
|
|
21
|
+
### Secret-named files are refused
|
|
22
|
+
|
|
23
|
+
Every evidence admission path (`jev_ask` paths and import closure, `jev_ask_files`, `jev_find_files`, `jev_locate_in_file`, `jev_check_diff` diff units and local callers, `jev_select_tests` inventory and the automatic pi/omp documentation check) refuses a file whose base name matches `.env`, `.env.*`, `*.pem`, `id_rsa*`, `*.p12`, `credentials*` or `secrets*`, at any depth and case-insensitively, whatever its Git status (tracked, untracked or added). `.env.example`, `.env.sample` and `.env.template` remain admitted. The refusal happens before the content is read: the result names the path with cause `secret_pattern`, and a question that explicitly requires that file stays unjudged. There is no per-call or environment override. Files with other names are not inspected for secrets.
|
|
24
|
+
|
|
25
|
+
### Commands never receive the API key
|
|
26
|
+
|
|
27
|
+
`jev_ask` commands and the Windows PowerShell ACL helper run with the host environment minus `JEV_TOOLS_API_KEY`. Before command output enters a state, every occurrence of the configured key value, whether it came from the environment or the saved configuration, is replaced with `[redacted]` in stdout, stderr and the echoed command line; the result reports how many replacements were made. Detection of other secrets in command output is not promised.
|
|
28
|
+
|
|
29
|
+
### The key travels only over HTTPS or loopback
|
|
30
|
+
|
|
31
|
+
`JEV_TOOLS_URL` must use `https:`. Plain `http:` is accepted only for `127.0.0.1`, `::1` or `localhost`; any other `http:` URL is a configuration error, reported without the URL or key and before any request, so the Bearer key is never sent in clear text over a network.
|
|
32
|
+
|
|
33
|
+
### Automatic documentation check
|
|
34
|
+
|
|
35
|
+
On pi and omp, the run-end documentation check (disable with `JEV_TOOLS_AUTO_DOCS=0`) sends changed units from a dirty tree to the endpoint without an explicit tool call, including admitted untracked files that are not gitignored. Secret-named files are refused as above; anything else untracked and not ignored can be sent. Keep sensitive scratch files gitignored or outside the repository.
|
|
36
|
+
|
|
37
|
+
Saved interactive configuration stores the API key in plaintext in a private user-level file (`~/.config/jev-agent-tools/config.json` by default). Privacy uses each operating system's own model: owner-only mode bits on POSIX; on Windows, an access list whose allow entries are only the current user, SYSTEM and Administrators, read by SID through the system Windows PowerShell. Protect the account and back-ups accordingly, or use environment variables from a secret manager instead.
|
|
38
|
+
|
|
39
|
+
The MCP server (`jev-agent-tools-mcp`) has the same boundaries. It talks to its client only over stdio and opens no network listener. MCP client configuration files that contain a literal API key are as sensitive as the saved configuration; prefer the client's environment-variable interpolation and do not commit such files. Tool approval is the MCP client's responsibility; the server marks `jev_ask` as not read-only while commands are enabled.
|
|
40
|
+
|
|
41
|
+
Command cancellation and timeout, and MCP connection shutdown, complete bounded termination of the managed process group on POSIX or await the system process-tree termination operation on Windows. This is cleanup, not containment: deliberately detached descendants or processes that escape that tree are not tracked, and previously completed side effects are not undone.
|
|
42
|
+
|
|
43
|
+
Expected execution of an explicitly supplied command, intentional submission of evidence, inaccurate judgments, and ordinary bugs or feature requests are not by themselves security vulnerabilities. Report ordinary product problems through issues; report host or API-service vulnerabilities to their respective maintainers. If unsure about a jev-tools security impact, use the private form.
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { tokenize, } from "../core/lexical.js";
|
|
3
|
+
import { loadSyntaxRootParser } from "./syntax.js";
|
|
4
|
+
/** Owns one invocation's source versions; never retains repository data across calls. */
|
|
5
|
+
export async function createAnalysisContext(counter, sourceParser) {
|
|
6
|
+
const fingerprints = new Map();
|
|
7
|
+
const fingerprint = (text) => {
|
|
8
|
+
let value = fingerprints.get(text);
|
|
9
|
+
if (value === undefined) {
|
|
10
|
+
value = createHash("sha256").update(text).digest("hex");
|
|
11
|
+
fingerprints.set(text, value);
|
|
12
|
+
}
|
|
13
|
+
return value;
|
|
14
|
+
};
|
|
15
|
+
const lexical = new Map();
|
|
16
|
+
const tokenizeSource = (path, text, python = false) => {
|
|
17
|
+
const version = fingerprint(text);
|
|
18
|
+
let versions = lexical.get(path);
|
|
19
|
+
if (!versions) {
|
|
20
|
+
versions = new Map();
|
|
21
|
+
lexical.set(path, versions);
|
|
22
|
+
}
|
|
23
|
+
const key = `${version}:${python}`;
|
|
24
|
+
let tokens = versions.get(key);
|
|
25
|
+
if (!tokens) {
|
|
26
|
+
counter?.tokenized(path, version);
|
|
27
|
+
tokens = tokenize(text, python);
|
|
28
|
+
versions.set(key, tokens);
|
|
29
|
+
}
|
|
30
|
+
return tokens;
|
|
31
|
+
};
|
|
32
|
+
const source = sourceParser ?? (await loadSyntaxRootParser());
|
|
33
|
+
if (!source)
|
|
34
|
+
return {
|
|
35
|
+
parser: undefined,
|
|
36
|
+
fingerprint,
|
|
37
|
+
counter,
|
|
38
|
+
tokenize: tokenizeSource,
|
|
39
|
+
};
|
|
40
|
+
const roots = new Map();
|
|
41
|
+
const parser = {
|
|
42
|
+
supports: source.supports,
|
|
43
|
+
parseRaw(path, text) {
|
|
44
|
+
const version = fingerprint(text);
|
|
45
|
+
let versions = roots.get(path);
|
|
46
|
+
if (!versions) {
|
|
47
|
+
versions = new Map();
|
|
48
|
+
roots.set(path, versions);
|
|
49
|
+
}
|
|
50
|
+
let parsed = versions.get(version);
|
|
51
|
+
if (!parsed) {
|
|
52
|
+
counter?.parsed(path, version);
|
|
53
|
+
parsed = source.parseRaw(path, text);
|
|
54
|
+
versions.set(version, parsed);
|
|
55
|
+
}
|
|
56
|
+
return parsed;
|
|
57
|
+
},
|
|
58
|
+
parse(path, text) {
|
|
59
|
+
const parsed = this.parseRaw(path, text);
|
|
60
|
+
if (!parsed.ok)
|
|
61
|
+
return parsed;
|
|
62
|
+
return parsed.root.find({ rule: { kind: "ERROR" } })
|
|
63
|
+
? { ok: false, error: "Source syntax incomplete" }
|
|
64
|
+
: parsed;
|
|
65
|
+
},
|
|
66
|
+
declarations: source.declarations,
|
|
67
|
+
};
|
|
68
|
+
return {
|
|
69
|
+
parser,
|
|
70
|
+
fingerprint,
|
|
71
|
+
counter,
|
|
72
|
+
tokenize: tokenizeSource,
|
|
73
|
+
resolved: (path, text) => counter?.resolved(path, fingerprint(text)),
|
|
74
|
+
};
|
|
75
|
+
}
|