@nettoolskit/det 0.0.1-preview.1
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/LICENSE +21 -0
- package/README.md +253 -0
- package/npm/cli/det.js +59 -0
- package/npm/native/.gitkeep +0 -0
- package/npm/runtime/bootstrap.js +135 -0
- package/package.json +42 -0
- package/scripts/npm/postinstall.js +211 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 NetToolsKit
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
# NetToolsKit DET
|
|
2
|
+
|
|
3
|
+
> Semantic execution runtime for governed AI.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Introduction
|
|
8
|
+
|
|
9
|
+
DET — Decision, Execution & Traceability — is the NetToolsKit semantic
|
|
10
|
+
execution runtime for governed AI. It orchestrates, optimizes, and governs AI
|
|
11
|
+
task execution through meaning, memory, verification, and metacognitive
|
|
12
|
+
control.
|
|
13
|
+
|
|
14
|
+
DET coordinates AI models, MEVRA, Meaning Memory, tools, retrieval,
|
|
15
|
+
verification, evaluation, policy, and metacognitive awareness so AI tasks can
|
|
16
|
+
run with semantic grounding, traceability, safety, and measurable performance.
|
|
17
|
+
It is not an agent framework and it does not own provider execution, memory
|
|
18
|
+
storage, machine control, or downstream product orchestration.
|
|
19
|
+
|
|
20
|
+
MEVRA proposes operational meaning. Meaning Memory validates and persists
|
|
21
|
+
meaning. Metacognition monitors objective, focus, uncertainty, conflict, and
|
|
22
|
+
risk. Verification validates. Anti-Deception protects. The LLM verbalizes. DET
|
|
23
|
+
arbitrates and executes.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Features
|
|
28
|
+
|
|
29
|
+
- ✅ Semantic execution runtime for governed AI task planning and execution.
|
|
30
|
+
- ✅ Decision, execution, verification, traceability, and policy arbitration contracts.
|
|
31
|
+
- ✅ Meaning Memory integration boundaries for global, catalog, project-registry, and project-local memory layers.
|
|
32
|
+
- ✅ Agent and Codegen consumption boundaries that avoid duplicating deterministic function implementations.
|
|
33
|
+
- ✅ Operational `det run --task` dry-run entrypoint for governed route planning and traceability.
|
|
34
|
+
- ✅ Harness-derived evidence, benchmark, and effectiveness contracts inside the DET workspace.
|
|
35
|
+
- ✅ River-first validation model for Rust quality, package validation, and CI/CD governance.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Contents
|
|
40
|
+
|
|
41
|
+
- [Introduction](#introduction)
|
|
42
|
+
- [Features](#features)
|
|
43
|
+
- [Architecture](#architecture)
|
|
44
|
+
- [Architecture](#architecture-1)
|
|
45
|
+
- [Agentic Surfaces](#agentic-surfaces)
|
|
46
|
+
- [Crates](#crates)
|
|
47
|
+
- [Compatibility and Support](#compatibility-and-support)
|
|
48
|
+
- [Operations](#operations)
|
|
49
|
+
- [Planning](#planning)
|
|
50
|
+
- [Governance and Security](#governance-and-security)
|
|
51
|
+
- [Build and Tests](#build-and-tests)
|
|
52
|
+
- [Contributing](#contributing)
|
|
53
|
+
- [Dependencies](#dependencies)
|
|
54
|
+
- [References](#references)
|
|
55
|
+
- [License](#license)
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Architecture
|
|
60
|
+
|
|
61
|
+
### Architecture
|
|
62
|
+
|
|
63
|
+
```mermaid
|
|
64
|
+
flowchart LR
|
|
65
|
+
User[Operator or host application] --> DET[DET runtime\nDecision, Execution & Traceability]
|
|
66
|
+
DET --> MEVRA[MEVRA\nMeaning proposal]
|
|
67
|
+
DET --> Memory[nettoolskit-memory\nMeaning Memory]
|
|
68
|
+
DET --> Agent[nettoolskit-agent\nDeterministic functions]
|
|
69
|
+
DET --> Codegen[nettoolskit-codegen\nComplex deterministic code architecture functions]
|
|
70
|
+
DET --> Analytics[nettoolskit-analytics\nEvaluation and effectiveness signals]
|
|
71
|
+
DET --> Harness[DET harness contracts\nEvidence and benchmark reproducibility]
|
|
72
|
+
DET --> Rust[nettoolskit-rust\nShared Rust foundation]
|
|
73
|
+
Copilot[nettoolskit-copilot] --> DET
|
|
74
|
+
Copilot --> Control[nettoolskit-control\nRemote machine control]
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
DET owns semantic arbitration, execution planning, traceability, governance,
|
|
78
|
+
and verification boundaries. It consumes `nettoolskit-agent` and
|
|
79
|
+
`nettoolskit-codegen` deterministic functions without duplicating their code.
|
|
80
|
+
It integrates with `nettoolskit-memory` through Meaning Memory contracts and
|
|
81
|
+
keeps storage, indexing, retrieval, and persistence in Memory.
|
|
82
|
+
|
|
83
|
+
`nettoolskit-copilot` is a product surface that can use DET and remote control
|
|
84
|
+
services. DET does not depend on Copilot or Control.
|
|
85
|
+
|
|
86
|
+
### Agentic Surfaces
|
|
87
|
+
|
|
88
|
+
DET uses agentic ecosystem components through explicit boundaries:
|
|
89
|
+
|
|
90
|
+
- `nettoolskit-agent` owns canonical deterministic function catalogs,
|
|
91
|
+
commands, instruction contracts, and runtime guidance.
|
|
92
|
+
- `nettoolskit-codegen` owns complex deterministic architecture/code-generation
|
|
93
|
+
functions that DET can select and orchestrate.
|
|
94
|
+
- `nettoolskit-memory` owns Meaning Memory storage, retrieval, validation,
|
|
95
|
+
persistence, and project-local memory.
|
|
96
|
+
- `nettoolskit-analytics` owns analytics and evaluation signals that DET can
|
|
97
|
+
use for measured effectiveness.
|
|
98
|
+
- `nettoolskit-copilot` owns user-facing product orchestration and can call DET.
|
|
99
|
+
- `nettoolskit-control` owns remote machine command execution and is not called
|
|
100
|
+
directly by DET.
|
|
101
|
+
|
|
102
|
+
Detailed architecture is maintained in [ARCHITECTURE.md](ARCHITECTURE.md) and
|
|
103
|
+
[docs/architecture-overview.md](docs/architecture-overview.md).
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Crates
|
|
108
|
+
|
|
109
|
+
The DET workspace is organized by owned crates under `crates/*`.
|
|
110
|
+
|
|
111
|
+
| Crate | Purpose | README |
|
|
112
|
+
| --- | --- | --- |
|
|
113
|
+
| `agentic-rag` | Agentic RAG planning and policy contracts. | [README](crates/agentic-rag/README.md) |
|
|
114
|
+
| `cli` | Public CLI and compatibility facade. | [README](crates/cli/README.md) |
|
|
115
|
+
| `core` | Core semantic execution and repository profile contracts. | [README](crates/core/README.md) |
|
|
116
|
+
| `harness` | Harness-derived evidence and reproducibility contracts. | [README](crates/harness/README.md) |
|
|
117
|
+
| `integrations` | Agent, Memory, analytics, and ecosystem integration boundaries. | [README](crates/integrations/README.md) |
|
|
118
|
+
| `language` | DET language parsing and runtime-language contracts. | [README](crates/language/README.md) |
|
|
119
|
+
| `runtime` | Runtime admission, DET home, wrapper, benchmark, and registry contracts. | [README](crates/runtime/README.md) |
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Compatibility and Support
|
|
124
|
+
|
|
125
|
+
DET is in MVP implementation and should be consumed through committed Rust
|
|
126
|
+
contracts, documented CLI surfaces, and explicit JSON request/response shapes.
|
|
127
|
+
Distribution targets npm/npx, Docker, GitHub Releases, and Winget; Cargo
|
|
128
|
+
publication is not the preferred operator install path for this product stage.
|
|
129
|
+
|
|
130
|
+
Supported operator paths and release-readiness details live in
|
|
131
|
+
[docs/install.md](docs/install.md), [docs/release.md](docs/release.md).
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Operations
|
|
136
|
+
|
|
137
|
+
Operational details are intentionally kept out of the root README:
|
|
138
|
+
|
|
139
|
+
- Basic usage: [docs/getting-started/basic-usage.md](docs/getting-started/basic-usage.md)
|
|
140
|
+
- Operational task runtime: `det run --task --json <run-task-request.json>`
|
|
141
|
+
- DET home and Meaning Memory layers: [docs/det-home-memory.md](docs/det-home-memory.md)
|
|
142
|
+
- Local validation and CI/CD routing: [docs/operations/local-validation.md](docs/operations/local-validation.md)
|
|
143
|
+
- River CI policy: [docs/operations/river-ci.md](docs/operations/river-ci.md)
|
|
144
|
+
- Runtime wrapper: [docs/runtime-wrapper.md](docs/runtime-wrapper.md)
|
|
145
|
+
- Benchmark evidence: [docs/local-det-vs-baseline-benchmark.md](docs/local-det-vs-baseline-benchmark.md)
|
|
146
|
+
- Guarded DET dogfood with Agent and Meaning Memory: [docs/guarded-det-dogfood.md](docs/guarded-det-dogfood.md)
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## Planning
|
|
151
|
+
|
|
152
|
+
Planning state is kept under `planning/` and should remain tied to concrete
|
|
153
|
+
workstreams, validation evidence, and PR closeout.
|
|
154
|
+
|
|
155
|
+
Useful entry points:
|
|
156
|
+
|
|
157
|
+
- [Planning index](planning/README.md)
|
|
158
|
+
- [Active DET semantic execution spec](planning/specs/active/202605272037-spec-nettoolskit-det-semantic-execution-engine.md)
|
|
159
|
+
- [Memory and model evaluation plan](planning/plans/completed/2026-06/202606081130-plan-det-memory-as-model-evaluation.md)
|
|
160
|
+
- [Benchmark artifact manifest plan](planning/plans/completed/2026-06/202606091205-plan-det-benchmark-artifact-manifest.md)
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## Governance and Security
|
|
165
|
+
|
|
166
|
+
DET keeps execution ownership explicit:
|
|
167
|
+
|
|
168
|
+
- DET arbitrates and plans; it does not duplicate provider, Agent, Codegen,
|
|
169
|
+
Memory, Control, Copilot, DevOps, Assurance, or Analytics implementation code.
|
|
170
|
+
- Memory owns retrieval, validation, persistence, indexing, and storage.
|
|
171
|
+
- Agent owns deterministic function catalogs and command contracts.
|
|
172
|
+
- Codegen owns complex deterministic architecture/code-generation functions.
|
|
173
|
+
- Control owns remote machine command execution and is not a DET dependency.
|
|
174
|
+
- Provider calls, MCP invocation, shell execution, persistence, and runtime IO
|
|
175
|
+
require explicit host-owned boundaries.
|
|
176
|
+
|
|
177
|
+
See [docs/det-ecosystem-ownership-model.md](docs/det-ecosystem-ownership-model.md)
|
|
178
|
+
and [docs/ci-gitriver.md](docs/ci-gitriver.md) for the detailed governance
|
|
179
|
+
model.
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## Build and Tests
|
|
184
|
+
|
|
185
|
+
Local validation should mirror the River Rust quality gate:
|
|
186
|
+
|
|
187
|
+
```powershell
|
|
188
|
+
cargo fmt --all --check
|
|
189
|
+
cargo test --all-targets --locked
|
|
190
|
+
cargo clippy --all-targets --locked -- -D warnings
|
|
191
|
+
cargo doc --no-deps --locked
|
|
192
|
+
git diff --check
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Package/security validation is separate from Rust quality. PR runs should keep
|
|
196
|
+
package security bounded by auditing dependencies, building docs, listing Cargo
|
|
197
|
+
package contents, and generating allowlisted tarballs without repeating full
|
|
198
|
+
workspace package verification. Full Cargo package verification is reserved for
|
|
199
|
+
explicit release or manual proof.
|
|
200
|
+
|
|
201
|
+
The source-owned River validation path is documented in
|
|
202
|
+
[docs/operations/local-validation.md](docs/operations/local-validation.md) and
|
|
203
|
+
[docs/operations/river-ci.md](docs/operations/river-ci.md).
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## Contributing
|
|
208
|
+
|
|
209
|
+
Use a dedicated branch or worktree for each change-bearing workstream. Keep
|
|
210
|
+
changes scoped to the active plan, update README/manifest/changelog only when
|
|
211
|
+
the implemented behavior changes, and record validation evidence before opening
|
|
212
|
+
or updating a pull request.
|
|
213
|
+
|
|
214
|
+
Every completed workstream should leave the local worktree clean, planning
|
|
215
|
+
state updated, and validation results reproducible from committed source.
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## Dependencies
|
|
220
|
+
|
|
221
|
+
Runtime dependencies are intentionally small:
|
|
222
|
+
|
|
223
|
+
| Dependency | Purpose |
|
|
224
|
+
| --- | --- |
|
|
225
|
+
| `serde` | Public contract serialization and deserialization. |
|
|
226
|
+
| `serde_json` | JSON registry, manifest, and test serialization support. |
|
|
227
|
+
|
|
228
|
+
Development and validation depend on the Rust toolchain, Cargo, `cargo audit`,
|
|
229
|
+
and Git.
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
## References
|
|
234
|
+
|
|
235
|
+
- [Changelog](CHANGELOG.md)
|
|
236
|
+
- [Architecture](ARCHITECTURE.md)
|
|
237
|
+
- [Documentation index](docs/README.md)
|
|
238
|
+
- [Planning](planning/README.md)
|
|
239
|
+
- [Service manifest](nettoolskit.manifest.json)
|
|
240
|
+
- [River CI gates](scripts/ci/river/README.md)
|
|
241
|
+
- [GitHub repository](https://github.com/NetToolsKit/nettoolskit-det)
|
|
242
|
+
- [Apache DataFusion Query Optimizer](https://datafusion.apache.org/library-user-guide/query-optimizer.html)
|
|
243
|
+
- [Qdrant Indexing](https://qdrant.tech/documentation/concepts/indexing/)
|
|
244
|
+
- [OpenTelemetry](https://opentelemetry.io/docs/)
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## License
|
|
249
|
+
|
|
250
|
+
This project is licensed under the MIT License. See the LICENSE file at the
|
|
251
|
+
repository root for details.
|
|
252
|
+
|
|
253
|
+
---
|
package/npm/cli/det.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { spawnSync } = require("node:child_process");
|
|
4
|
+
const fs = require("node:fs");
|
|
5
|
+
const path = require("node:path");
|
|
6
|
+
const { initializeRuntimeHome } = require("../runtime/bootstrap");
|
|
7
|
+
|
|
8
|
+
const repoRoot = path.resolve(__dirname, "..", "..");
|
|
9
|
+
const nativeName = process.platform === "win32" ? "det.exe" : "det";
|
|
10
|
+
const bundledBinary = path.join(repoRoot, "npm", "native", nativeName);
|
|
11
|
+
const explicitBinary = process.env.NTK_DET_BINARY || process.env.NETTOOLSKIT_DET_BINARY;
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
initializeRuntimeHome();
|
|
15
|
+
} catch (error) {
|
|
16
|
+
console.error(`DET runtime bootstrap failed: ${error.message}`);
|
|
17
|
+
process.exit(126);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function executableExists(candidate) {
|
|
21
|
+
return Boolean(candidate) && fs.existsSync(candidate);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function failMissingBinary(detail) {
|
|
25
|
+
console.error("DET binary was not found.");
|
|
26
|
+
if (detail) {
|
|
27
|
+
console.error(detail);
|
|
28
|
+
}
|
|
29
|
+
console.error("Set NTK_DET_BINARY to a GitHub Release binary or reinstall @nettoolskit/det.");
|
|
30
|
+
process.exit(127);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
let binary;
|
|
34
|
+
if (explicitBinary) {
|
|
35
|
+
if (!executableExists(explicitBinary)) {
|
|
36
|
+
failMissingBinary(`Configured DET binary does not exist: ${explicitBinary}`);
|
|
37
|
+
}
|
|
38
|
+
binary = explicitBinary;
|
|
39
|
+
} else if (executableExists(bundledBinary)) {
|
|
40
|
+
binary = bundledBinary;
|
|
41
|
+
} else {
|
|
42
|
+
failMissingBinary(`Expected bundled binary at: ${bundledBinary}`);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const executableBinary = process.platform === "win32" ? path.toNamespacedPath(binary) : binary;
|
|
46
|
+
const result = spawnSync(executableBinary, process.argv.slice(2), {
|
|
47
|
+
stdio: "inherit",
|
|
48
|
+
windowsHide: true,
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
if (result.error) {
|
|
52
|
+
failMissingBinary(result.error.message);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (typeof result.status === "number") {
|
|
56
|
+
process.exit(result.status);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
process.exit(1);
|
|
File without changes
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const fs = require("node:fs");
|
|
4
|
+
const os = require("node:os");
|
|
5
|
+
const path = require("node:path");
|
|
6
|
+
|
|
7
|
+
const SCHEMA_VERSION = "det.runtime_install_bootstrap.v1";
|
|
8
|
+
const DET_HOME_DIR_NAME = ".det";
|
|
9
|
+
const MEMORY_DIR_NAME = "memory";
|
|
10
|
+
const PROJECT_MEMORY_DIR = path.join(".det", "project-memory");
|
|
11
|
+
const SKIP_ENV_VARS = [
|
|
12
|
+
"NETTOOLSKIT_DET_SKIP_RUNTIME_BOOTSTRAP",
|
|
13
|
+
"NTK_DET_SKIP_RUNTIME_BOOTSTRAP",
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
function shouldSkipRuntimeBootstrap(env = process.env) {
|
|
17
|
+
return SKIP_ENV_VARS.some((name) => env[name] === "1" || env[name] === "true");
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function initializeRuntimeHome(options = {}) {
|
|
21
|
+
const env = options.env || process.env;
|
|
22
|
+
|
|
23
|
+
if (options.allowSkip !== false && shouldSkipRuntimeBootstrap(env)) {
|
|
24
|
+
return {
|
|
25
|
+
schemaVersion: SCHEMA_VERSION,
|
|
26
|
+
status: "skipped",
|
|
27
|
+
skipped: true,
|
|
28
|
+
reason: "runtime bootstrap disabled by environment",
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const detHome = resolveDetHome(options.detHome || env.DET_HOME);
|
|
33
|
+
assertSafeRuntimePath(detHome, "DET_HOME");
|
|
34
|
+
|
|
35
|
+
const memoryRoot = path.join(detHome, MEMORY_DIR_NAME);
|
|
36
|
+
const memoryLayers = [
|
|
37
|
+
layer("global", path.join(memoryRoot, "global")),
|
|
38
|
+
layer("global_catalogs", path.join(memoryRoot, "catalogs")),
|
|
39
|
+
layer("global_projects", path.join(memoryRoot, "projects")),
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
ensureDirectory(detHome);
|
|
43
|
+
ensureDirectory(memoryRoot);
|
|
44
|
+
for (const memoryLayer of memoryLayers) {
|
|
45
|
+
ensureDirectory(memoryLayer.path);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
let projectMemory = null;
|
|
49
|
+
const projectRoot = options.projectRoot || env.DET_PROJECT_ROOT;
|
|
50
|
+
if (projectRoot) {
|
|
51
|
+
const resolvedProjectRoot = path.resolve(projectRoot);
|
|
52
|
+
assertSafeRuntimePath(resolvedProjectRoot, "DET_PROJECT_ROOT");
|
|
53
|
+
projectMemory = path.join(resolvedProjectRoot, PROJECT_MEMORY_DIR);
|
|
54
|
+
ensureDirectory(projectMemory);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const report = {
|
|
58
|
+
schemaVersion: SCHEMA_VERSION,
|
|
59
|
+
status: "ready",
|
|
60
|
+
detHome,
|
|
61
|
+
memoryRoot,
|
|
62
|
+
memoryLayers,
|
|
63
|
+
projectMemory,
|
|
64
|
+
memoryExecutable: env.DET_NTK_MEMORY_EXECUTABLE || "ntk-memory",
|
|
65
|
+
storageOwner: "nettoolskit-memory",
|
|
66
|
+
createdBy: "@nettoolskit/det",
|
|
67
|
+
writesProviderPayloads: false,
|
|
68
|
+
writesSecrets: false,
|
|
69
|
+
mutatesShellProfiles: false,
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
if (options.writeState !== false) {
|
|
73
|
+
fs.writeFileSync(
|
|
74
|
+
path.join(detHome, "install-state.json"),
|
|
75
|
+
`${JSON.stringify(report, null, 2)}\n`,
|
|
76
|
+
"utf8",
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return report;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function resolveDetHome(configuredHome) {
|
|
84
|
+
if (configuredHome && configuredHome.trim()) {
|
|
85
|
+
return path.resolve(configuredHome.trim());
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const home = os.homedir();
|
|
89
|
+
if (!home) {
|
|
90
|
+
throw new Error("DET_HOME could not be resolved because the user home directory is unavailable");
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return path.join(home, DET_HOME_DIR_NAME);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function layer(scope, layerPath) {
|
|
97
|
+
return {
|
|
98
|
+
scope,
|
|
99
|
+
path: layerPath,
|
|
100
|
+
global: true,
|
|
101
|
+
projectLocal: false,
|
|
102
|
+
versioned: false,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function ensureDirectory(directory) {
|
|
107
|
+
fs.mkdirSync(directory, { recursive: true });
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function assertSafeRuntimePath(candidate, label) {
|
|
111
|
+
const normalized = candidate.replace(/\\/g, "/").toLowerCase();
|
|
112
|
+
if (
|
|
113
|
+
!normalized ||
|
|
114
|
+
normalized.includes("/../") ||
|
|
115
|
+
normalized.endsWith("/..") ||
|
|
116
|
+
normalized.startsWith("../") ||
|
|
117
|
+
normalized.includes("raw_prompt") ||
|
|
118
|
+
normalized.includes("provider_payload") ||
|
|
119
|
+
normalized.includes("secret") ||
|
|
120
|
+
normalized.includes("token")
|
|
121
|
+
) {
|
|
122
|
+
throw new Error(`${label} is not safe for DET runtime bootstrap`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (require.main === module) {
|
|
127
|
+
const report = initializeRuntimeHome();
|
|
128
|
+
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
module.exports = {
|
|
132
|
+
SCHEMA_VERSION,
|
|
133
|
+
initializeRuntimeHome,
|
|
134
|
+
shouldSkipRuntimeBootstrap,
|
|
135
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nettoolskit/det",
|
|
3
|
+
"version": "0.0.1-preview.1",
|
|
4
|
+
"description": "NetToolsKit DET command-line wrapper.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"nettoolskit",
|
|
8
|
+
"det",
|
|
9
|
+
"cli",
|
|
10
|
+
"semantic-runtime"
|
|
11
|
+
],
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "git+https://github.com/NetToolsKit/nettoolskit-det.git"
|
|
15
|
+
},
|
|
16
|
+
"homepage": "https://github.com/NetToolsKit/nettoolskit-det#readme",
|
|
17
|
+
"bugs": {
|
|
18
|
+
"url": "https://github.com/NetToolsKit/nettoolskit-det/issues"
|
|
19
|
+
},
|
|
20
|
+
"bin": {
|
|
21
|
+
"det": "npm/cli/det.js",
|
|
22
|
+
"ntk-det": "npm/cli/det.js"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"LICENSE",
|
|
26
|
+
"README.md",
|
|
27
|
+
"npm/cli/det.js",
|
|
28
|
+
"npm/native/",
|
|
29
|
+
"npm/runtime/bootstrap.js",
|
|
30
|
+
"scripts/npm/postinstall.js"
|
|
31
|
+
],
|
|
32
|
+
"scripts": {
|
|
33
|
+
"test:postinstall-integrity": "node scripts/npm/test-postinstall-integrity.js",
|
|
34
|
+
"postinstall": "node scripts/npm/postinstall.js"
|
|
35
|
+
},
|
|
36
|
+
"publishConfig": {
|
|
37
|
+
"access": "public"
|
|
38
|
+
},
|
|
39
|
+
"engines": {
|
|
40
|
+
"node": ">=18"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const crypto = require("node:crypto");
|
|
4
|
+
const fs = require("node:fs");
|
|
5
|
+
const path = require("node:path");
|
|
6
|
+
|
|
7
|
+
const packageJson = require("../../package.json");
|
|
8
|
+
const { initializeRuntimeHome } = require("../../npm/runtime/bootstrap");
|
|
9
|
+
const metadataAsset = "det-distribution-artifact-metadata.json";
|
|
10
|
+
|
|
11
|
+
class DetBinaryIntegrityError extends Error {
|
|
12
|
+
constructor(message) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.name = "DetBinaryIntegrityError";
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (require.main === module) {
|
|
19
|
+
main().catch(handlePostinstallFailure);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async function main() {
|
|
23
|
+
try {
|
|
24
|
+
initializeRuntimeHome();
|
|
25
|
+
} catch (error) {
|
|
26
|
+
console.warn(`DET runtime bootstrap failed: ${error.message}`);
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (process.env.NETTOOLSKIT_DET_SKIP_DOWNLOAD === "1" || process.env.NTK_DET_SKIP_DOWNLOAD === "1") {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const target = releaseTarget();
|
|
35
|
+
if (target && target.unsupported) {
|
|
36
|
+
console.warn(target.message);
|
|
37
|
+
console.warn("Use Docker, a Windows/Linux GitHub Release binary, or set NTK_DET_BINARY to a compatible locally built binary.");
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (!target) {
|
|
41
|
+
console.warn(`No DET GitHub Release binary is declared for ${process.platform}/${process.arch}.`);
|
|
42
|
+
console.warn("Set NTK_DET_BINARY to a local binary before running det.");
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const nativeDir = path.resolve(__dirname, "..", "..", "npm", "native");
|
|
47
|
+
const binaryPath = path.join(nativeDir, process.platform === "win32" ? "det.exe" : "det");
|
|
48
|
+
const releaseVersion = `v${packageJson.version}`;
|
|
49
|
+
fs.mkdirSync(nativeDir, { recursive: true });
|
|
50
|
+
|
|
51
|
+
const expectedSha256 = await resolveExpectedSha256(releaseVersion, target.asset);
|
|
52
|
+
|
|
53
|
+
if (fs.existsSync(binaryPath)) {
|
|
54
|
+
const existingSha256 = sha256File(binaryPath);
|
|
55
|
+
if (existingSha256 === expectedSha256) {
|
|
56
|
+
if (process.platform !== "win32") {
|
|
57
|
+
fs.chmodSync(binaryPath, 0o755);
|
|
58
|
+
}
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
fs.rmSync(binaryPath, { force: true });
|
|
62
|
+
console.warn("Existing DET binary was removed because release checksum verification failed.");
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const url = `https://github.com/NetToolsKit/nettoolskit-det/releases/download/${releaseVersion}/${target.asset}`;
|
|
66
|
+
|
|
67
|
+
await downloadVerified(url, binaryPath, expectedSha256);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async function download(url, destination) {
|
|
71
|
+
assertTrustedReleaseUrl(url);
|
|
72
|
+
const timeoutMs = Number.parseInt(process.env.NTK_DET_DOWNLOAD_TIMEOUT_MS || "120000", 10);
|
|
73
|
+
const controller = new AbortController();
|
|
74
|
+
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
75
|
+
const temporaryDestination = `${destination}.tmp-${process.pid}`;
|
|
76
|
+
|
|
77
|
+
try {
|
|
78
|
+
const response = await fetch(url, { redirect: "follow", signal: controller.signal });
|
|
79
|
+
if (!response.ok) {
|
|
80
|
+
throw new Error(`HTTP ${response.status}`);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const body = Buffer.from(await response.arrayBuffer());
|
|
84
|
+
fs.writeFileSync(temporaryDestination, body);
|
|
85
|
+
fs.renameSync(temporaryDestination, destination);
|
|
86
|
+
if (process.platform !== "win32") {
|
|
87
|
+
fs.chmodSync(destination, 0o755);
|
|
88
|
+
}
|
|
89
|
+
} finally {
|
|
90
|
+
clearTimeout(timeout);
|
|
91
|
+
fs.rmSync(temporaryDestination, { force: true });
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async function downloadVerified(url, destination, expectedSha256) {
|
|
96
|
+
await download(url, destination);
|
|
97
|
+
const actualSha256 = sha256File(destination);
|
|
98
|
+
|
|
99
|
+
if (actualSha256 !== expectedSha256) {
|
|
100
|
+
fs.rmSync(destination, { force: true });
|
|
101
|
+
throw new DetBinaryIntegrityError(
|
|
102
|
+
`DET binary checksum mismatch for ${path.basename(destination)}; expected ${expectedSha256}, got ${actualSha256}`
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async function resolveExpectedSha256(releaseVersion, assetName) {
|
|
108
|
+
const metadataUrl = `https://github.com/NetToolsKit/nettoolskit-det/releases/download/${releaseVersion}/${metadataAsset}`;
|
|
109
|
+
const metadata = await downloadJson(metadataUrl);
|
|
110
|
+
return findReleaseAssetSha256(metadata, releaseVersion, assetName);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
async function downloadJson(url) {
|
|
114
|
+
const temporaryDestination = path.join(
|
|
115
|
+
path.resolve(__dirname, "..", "..", "npm", "native"),
|
|
116
|
+
`${metadataAsset}.tmp-${process.pid}`
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
await download(url, temporaryDestination);
|
|
120
|
+
|
|
121
|
+
try {
|
|
122
|
+
return JSON.parse(fs.readFileSync(temporaryDestination, "utf8"));
|
|
123
|
+
} catch (error) {
|
|
124
|
+
throw new DetBinaryIntegrityError(`Invalid DET release metadata JSON: ${error.message}`);
|
|
125
|
+
} finally {
|
|
126
|
+
fs.rmSync(temporaryDestination, { force: true });
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function findReleaseAssetSha256(metadata, releaseVersion, assetName) {
|
|
131
|
+
if (!metadata || typeof metadata !== "object") {
|
|
132
|
+
throw new DetBinaryIntegrityError("DET release metadata is empty or invalid.");
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (metadata.releaseTag !== releaseVersion) {
|
|
136
|
+
throw new DetBinaryIntegrityError(
|
|
137
|
+
`DET release metadata tag mismatch; expected ${releaseVersion}, got ${metadata.releaseTag || "<missing>"}`
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const channels = Array.isArray(metadata.channels) ? metadata.channels : [];
|
|
142
|
+
const githubRelease = channels.find((channel) => channel && channel.id === "github_release_binary");
|
|
143
|
+
|
|
144
|
+
if (!githubRelease || !Array.isArray(githubRelease.assets)) {
|
|
145
|
+
throw new DetBinaryIntegrityError("DET release metadata does not contain github_release_binary assets.");
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const asset = githubRelease.assets.find((candidate) => candidate && candidate.name === assetName);
|
|
149
|
+
if (!asset || typeof asset.sha256 !== "string") {
|
|
150
|
+
throw new DetBinaryIntegrityError(`DET release metadata does not contain SHA-256 for ${assetName}.`);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const sha256 = asset.sha256.toLowerCase();
|
|
154
|
+
if (!/^[a-f0-9]{64}$/.test(sha256)) {
|
|
155
|
+
throw new DetBinaryIntegrityError(`DET release metadata contains an invalid SHA-256 for ${assetName}.`);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return sha256;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function assertTrustedReleaseUrl(url) {
|
|
162
|
+
const parsed = new URL(url);
|
|
163
|
+
if (parsed.protocol !== "https:" || parsed.hostname !== "github.com") {
|
|
164
|
+
throw new DetBinaryIntegrityError(`Untrusted DET release URL: ${url}`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function sha256File(filePath) {
|
|
169
|
+
return sha256Buffer(fs.readFileSync(filePath));
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function sha256Buffer(buffer) {
|
|
173
|
+
return crypto.createHash("sha256").update(buffer).digest("hex");
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function handlePostinstallFailure(error) {
|
|
177
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
178
|
+
console.warn(`DET binary download failed: ${message}`);
|
|
179
|
+
console.warn("Set NTK_DET_BINARY to a local binary or install from a GitHub Release asset.");
|
|
180
|
+
|
|
181
|
+
if (error instanceof DetBinaryIntegrityError) {
|
|
182
|
+
process.exitCode = 1;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function releaseTarget() {
|
|
187
|
+
const platform = process.platform;
|
|
188
|
+
const arch = process.arch;
|
|
189
|
+
|
|
190
|
+
if (platform === "win32" && arch === "x64") {
|
|
191
|
+
return { asset: "det-x86_64-pc-windows-msvc.exe" };
|
|
192
|
+
}
|
|
193
|
+
if (platform === "linux" && arch === "x64") {
|
|
194
|
+
return { asset: "det-x86_64-unknown-linux-gnu" };
|
|
195
|
+
}
|
|
196
|
+
if (platform === "darwin") {
|
|
197
|
+
return {
|
|
198
|
+
unsupported: true,
|
|
199
|
+
message: `macOS GitHub Release binary assets are pending for DET v${packageJson.version}.`,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return null;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
module.exports = {
|
|
207
|
+
DetBinaryIntegrityError,
|
|
208
|
+
findReleaseAssetSha256,
|
|
209
|
+
releaseTarget,
|
|
210
|
+
sha256Buffer,
|
|
211
|
+
};
|