@nurix/nustack 0.26.8 → 0.27.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.
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { closeSync, openSync, readSync, statSync } from "node:fs";
|
|
1
|
+
import { closeSync, openSync, readSync, realpathSync, statSync } from "node:fs";
|
|
2
|
+
import os from "node:os";
|
|
2
3
|
import path from "node:path";
|
|
3
4
|
export const GATE_BYTES_PER_TOKEN = 4;
|
|
4
5
|
export const READ_DEFAULT_LINE_LIMIT = 2_000;
|
|
@@ -6,6 +7,18 @@ export const READ_LINE_PREFIX_BYTES = 7;
|
|
|
6
7
|
export const BINARY_PROBE_BYTES = 8_192;
|
|
7
8
|
export const GATE_SKIPPED_EXTENSIONS = ["png", "jpg", "jpeg", "gif", "webp", "bmp", "ico", "pdf", "ipynb"];
|
|
8
9
|
const READ_CHUNK_BYTES = 64 * 1024;
|
|
10
|
+
function realDirectory(directory) {
|
|
11
|
+
try {
|
|
12
|
+
return realpathSync(directory);
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return directory;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export function isExemptPath(realPath, env = process.env) {
|
|
19
|
+
const projects = path.join(realDirectory(env.CLAUDE_CONFIG_DIR ?? path.join(os.homedir(), ".claude")), "projects");
|
|
20
|
+
return realPath.startsWith(`${projects}${path.sep}`) && realPath.split(path.sep).includes("tool-results");
|
|
21
|
+
}
|
|
9
22
|
export function tokensOfLength(length) {
|
|
10
23
|
return Math.ceil(length / GATE_BYTES_PER_TOKEN);
|
|
11
24
|
}
|
package/dist/lib/gate/outline.js
CHANGED
|
@@ -64,7 +64,7 @@ function headOf(source) {
|
|
|
64
64
|
.map((line) => (line.length > HEAD_LINE_MAX_CHARS ? `${line.slice(0, HEAD_LINE_MAX_CHARS)}…` : line));
|
|
65
65
|
}
|
|
66
66
|
function waysForward(entries, lineCount, tool) {
|
|
67
|
-
const ranged = entries.filter((entry) => entry.endLine !== undefined);
|
|
67
|
+
const ranged = entries.filter((entry) => entry.endLine !== undefined && entry.endLine - entry.startLine + 1 < lineCount);
|
|
68
68
|
const largest = ranged.reduce((best, entry) => (best === undefined || entry.endLine - entry.startLine > best.endLine - best.startLine ? entry : best), undefined);
|
|
69
69
|
const example = largest === undefined
|
|
70
70
|
? `offset=1 limit=${Math.min(lineCount, 200)}`
|
|
@@ -3,7 +3,7 @@ import { closeSync, openSync, readFileSync, readSync, realpathSync } from "node:
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { performance } from "node:perf_hooks";
|
|
5
5
|
import { assessBashRead, assessBashReadByCoin, classifyBashRead } from "./bashRead.js";
|
|
6
|
-
import { assessFullRead, assessFullReadByCoin, readLeadingLines, regularFileSize, tokensOfLength } from "./estimate.js";
|
|
6
|
+
import { assessFullRead, assessFullReadByCoin, isExemptPath, readLeadingLines, regularFileSize, tokensOfLength } from "./estimate.js";
|
|
7
7
|
import { assessRedirect, redirectHandler } from "./redirect.js";
|
|
8
8
|
import { GATE_MIN_THRESHOLD_TOKENS, isCoinSelected, isGateOff, resolveCoin, resolveThreshold } from "./settings.js";
|
|
9
9
|
export class GateInputError extends Error {
|
|
@@ -36,9 +36,11 @@ export async function gateReadCall(call, env = process.env, deps = {}, coin = re
|
|
|
36
36
|
const filePath = call.toolInput.file_path;
|
|
37
37
|
if (typeof filePath !== "string" || filePath === "")
|
|
38
38
|
throw new GateInputError("tool_input.file_path is missing");
|
|
39
|
-
if (call.toolInput.offset != null || call.toolInput.limit != null)
|
|
39
|
+
if (call.toolInput.offset != null || call.toolInput.limit != null || call.toolInput.allow_large === true)
|
|
40
40
|
return PASS;
|
|
41
41
|
const resolved = resolvePath(call.cwd, filePath);
|
|
42
|
+
if (isExemptPath(realPathOf(resolved), env))
|
|
43
|
+
return PASS;
|
|
42
44
|
const redirect = await assessRedirect(resolved, call.cwd, env, deps);
|
|
43
45
|
const assessment = coin === null
|
|
44
46
|
? assessFullRead(resolved, () => resolveThreshold(env).thresholdTokens, GATE_MIN_THRESHOLD_TOKENS)
|
|
@@ -55,9 +57,11 @@ export async function gateBashCall(call, env = process.env, coin = resolveCoin(e
|
|
|
55
57
|
if (typeof command !== "string")
|
|
56
58
|
throw new GateInputError("tool_input.command is missing");
|
|
57
59
|
const read = classifyBashRead(command);
|
|
58
|
-
if (read === null)
|
|
60
|
+
if (read === null || read.range.kind !== "whole")
|
|
59
61
|
return PASS;
|
|
60
62
|
const resolved = resolvePath(call.cwd, read.path);
|
|
63
|
+
if (isExemptPath(realPathOf(resolved), env))
|
|
64
|
+
return PASS;
|
|
61
65
|
const assessment = coin === null
|
|
62
66
|
? assessBashRead(resolved, read.range, () => resolveThreshold(env).thresholdTokens, GATE_MIN_THRESHOLD_TOKENS, env)
|
|
63
67
|
: assessBashReadByCoin(resolved, read.range, coinSelects(coin, call, resolved), env);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nurix/nustack",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.27.1",
|
|
4
4
|
"description": "The nustack CLI — bootstrap NuStack services into a repo via the NuStack discovery plane.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
@@ -34,10 +34,10 @@
|
|
|
34
34
|
"@types/node": "^22.19.20",
|
|
35
35
|
"typescript": "^5.7.2",
|
|
36
36
|
"vitest": "^4.1.11",
|
|
37
|
-
"@nurix/contracts": "3.0.2",
|
|
38
37
|
"@nurix/harness": "0.0.0",
|
|
39
|
-
"@nurix/
|
|
40
|
-
"@nurix/nustack.ui": "0.0.0"
|
|
38
|
+
"@nurix/contracts": "3.0.2",
|
|
39
|
+
"@nurix/nustack.ui": "0.0.0",
|
|
40
|
+
"@nurix/nustack.studio": "0.0.0"
|
|
41
41
|
},
|
|
42
42
|
"publishConfig": {
|
|
43
43
|
"access": "public"
|