Skip to content

Commit c55646d

Browse files
cvlaitingsheng
authored andcommitted
chore: add Prettier formatting for root-level JS files (#1200)
## Summary Extends the existing Prettier setup (which only covered `nemoclaw/src/**/*.ts`) to also format the root-level `bin/` and `test/` JavaScript files. ## Changes | File | What | |------|------| | `.prettierrc` | New root config — matches the `nemoclaw/` plugin style (double quotes, semicolons, 100-char print width, trailing commas) | | `.prettierignore` | Ignores `node_modules/`, `dist/`, `coverage/`, blueprint YAML, built docs, and `.md` files | | `package.json` | Added `prettier` devDependency, `format` and `format:check` scripts | | `.pre-commit-config.yaml` | Added `prettier-js` hook at priority 5 for `bin/` and `test/` JS files | | `Makefile` | `make format` now includes a `format-cli` subtarget | | 43 JS files | Reformatted to match project style | ## Validation - `npx prettier --check 'bin/**/*.js' 'test/**/*.js'` — ✅ all clean - `npm test` — ✅ 677 tests pass, 3 skipped - All pre-commit hooks pass (including new `Prettier (JavaScript)` hook) - All pre-push hooks pass (tsc, coverage ratchet) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **Chores** * Added standardized code formatting configuration with Prettier * Introduced npm scripts for code formatting and format verification * Enabled pre-commit hooks to automatically format code * Applied consistent formatting throughout the codebase * **Tests** * Updated test files to adhere to new formatting standards <!-- end of auto-generated comment: release notes by coderabbit.ai -->
1 parent 9afb007 commit c55646d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+2734
-1613
lines changed

.pre-commit-config.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,14 @@ repos:
9191
pass_filenames: true
9292
priority: 5
9393

94+
- id: prettier-js
95+
name: Prettier (JavaScript)
96+
entry: npx prettier --write
97+
language: system
98+
files: ^(bin|test)/.*\.js$
99+
pass_filenames: true
100+
priority: 5
101+
94102
# ── Priority 6: auto-fix after formatting ─────────────────────────────────
95103
- repo: local
96104
hooks:

.prettierignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
node_modules/
2+
dist/
3+
coverage/
4+
nemoclaw/node_modules/
5+
nemoclaw/dist/
6+
nemoclaw-blueprint/
7+
docs/_build/
8+
*.md

.prettierrc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"semi": true,
3+
"singleQuote": false,
4+
"trailingComma": "all",
5+
"printWidth": 100,
6+
"tabWidth": 2
7+
}

Makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ lint: check
1010
lint-ts:
1111
cd nemoclaw && npm run check
1212

13-
format: format-ts
13+
format: format-ts format-cli
14+
15+
format-cli:
16+
npx prettier --write 'bin/**/*.js' 'test/**/*.js'
1417

1518
format-ts:
1619
cd nemoclaw && npm run lint:fix && npm run format

bin/lib/credentials.js

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,25 +14,29 @@ function resolveHomeDir() {
1414
if (!raw) {
1515
throw new Error(
1616
"Cannot determine safe home directory for credential storage. " +
17-
"Set the HOME environment variable to a user-owned directory."
17+
"Set the HOME environment variable to a user-owned directory.",
1818
);
1919
}
2020
const home = path.resolve(raw);
2121
try {
2222
const real = fs.realpathSync(home);
2323
if (UNSAFE_HOME_PATHS.has(real)) {
2424
throw new Error(
25-
"Cannot store credentials: HOME resolves to '" + real + "' which is world-readable. " +
26-
"Set the HOME environment variable to a user-owned directory."
25+
"Cannot store credentials: HOME resolves to '" +
26+
real +
27+
"' which is world-readable. " +
28+
"Set the HOME environment variable to a user-owned directory.",
2729
);
2830
}
2931
} catch (e) {
3032
if (e.code !== "ENOENT") throw e;
3133
}
3234
if (UNSAFE_HOME_PATHS.has(home)) {
3335
throw new Error(
34-
"Cannot store credentials: HOME resolves to '" + home + "' which is world-readable. " +
35-
"Set the HOME environment variable to a user-owned directory."
36+
"Cannot store credentials: HOME resolves to '" +
37+
home +
38+
"' which is world-readable. " +
39+
"Set the HOME environment variable to a user-owned directory.",
3640
);
3741
}
3842
return home;
@@ -57,7 +61,9 @@ function loadCredentials() {
5761
if (fs.existsSync(file)) {
5862
return JSON.parse(fs.readFileSync(file, "utf-8"));
5963
}
60-
} catch { /* ignored */ }
64+
} catch {
65+
/* ignored */
66+
}
6167
return {};
6268
}
6369

@@ -277,7 +283,9 @@ async function ensureGithubToken() {
277283
process.env.GITHUB_TOKEN = token;
278284
return;
279285
}
280-
} catch { /* ignored */ }
286+
} catch {
287+
/* ignored */
288+
}
281289

282290
console.log("");
283291
console.log(" ┌──────────────────────────────────────────────────┐");

bin/lib/local-inference.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ function validateLocalProvider(provider, runCapture) {
7070
case "ollama-local":
7171
return {
7272
ok: false,
73-
message: "Local Ollama was selected, but nothing is responding on http://localhost:11434.",
73+
message:
74+
"Local Ollama was selected, but nothing is responding on http://localhost:11434.",
7475
};
7576
default:
7677
return { ok: false, message: "The selected local inference provider is unavailable." };
@@ -101,7 +102,10 @@ function validateLocalProvider(provider, runCapture) {
101102
"Local Ollama is responding on localhost, but containers cannot reach http://host.openshell.internal:11434. Ensure Ollama listens on 0.0.0.0:11434 instead of 127.0.0.1 so sandboxes can reach it.",
102103
};
103104
default:
104-
return { ok: false, message: "The selected local inference provider is unavailable from containers." };
105+
return {
106+
ok: false,
107+
message: "The selected local inference provider is unavailable from containers.",
108+
};
105109
}
106110
}
107111

@@ -127,7 +131,9 @@ function parseOllamaTags(output) {
127131
}
128132

129133
function getOllamaModelOptions(runCapture) {
130-
const tagsOutput = runCapture("curl -sf http://localhost:11434/api/tags 2>/dev/null", { ignoreError: true });
134+
const tagsOutput = runCapture("curl -sf http://localhost:11434/api/tags 2>/dev/null", {
135+
ignoreError: true,
136+
});
131137
const tagsParsed = parseOllamaTags(tagsOutput);
132138
if (tagsParsed.length > 0) {
133139
return tagsParsed;
@@ -193,7 +199,9 @@ function validateOllamaModel(model, runCapture) {
193199
message: `Selected Ollama model '${model}' failed the local probe: ${parsed.error.trim()}`,
194200
};
195201
}
196-
} catch { /* ignored */ }
202+
} catch {
203+
/* ignored */
204+
}
197205

198206
return { ok: true };
199207
}

bin/lib/nim.js

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,9 @@ function listModels() {
2626
function detectGpu() {
2727
// Try NVIDIA first — query VRAM
2828
try {
29-
const output = runCapture(
30-
"nvidia-smi --query-gpu=memory.total --format=csv,noheader,nounits",
31-
{ ignoreError: true }
32-
);
29+
const output = runCapture("nvidia-smi --query-gpu=memory.total --format=csv,noheader,nounits", {
30+
ignoreError: true,
31+
});
3332
if (output) {
3433
const lines = output.split("\n").filter((l) => l.trim());
3534
const perGpuMB = lines.map((l) => parseInt(l.trim(), 10)).filter((n) => !isNaN(n));
@@ -46,21 +45,24 @@ function detectGpu() {
4645
};
4746
}
4847
}
49-
} catch { /* ignored */ }
48+
} catch {
49+
/* ignored */
50+
}
5051

5152
// Fallback: DGX Spark (GB10) — VRAM not queryable due to unified memory architecture
5253
try {
53-
const nameOutput = runCapture(
54-
"nvidia-smi --query-gpu=name --format=csv,noheader,nounits",
55-
{ ignoreError: true }
56-
);
54+
const nameOutput = runCapture("nvidia-smi --query-gpu=name --format=csv,noheader,nounits", {
55+
ignoreError: true,
56+
});
5757
if (nameOutput && nameOutput.includes("GB10")) {
5858
// GB10 has 128GB unified memory shared with Grace CPU — use system RAM
5959
let totalMemoryMB = 0;
6060
try {
6161
const memLine = runCapture("free -m | awk '/Mem:/ {print $2}'", { ignoreError: true });
6262
if (memLine) totalMemoryMB = parseInt(memLine.trim(), 10) || 0;
63-
} catch { /* ignored */ }
63+
} catch {
64+
/* ignored */
65+
}
6466
return {
6567
type: "nvidia",
6668
count: 1,
@@ -70,15 +72,16 @@ function detectGpu() {
7072
spark: true,
7173
};
7274
}
73-
} catch { /* ignored */ }
75+
} catch {
76+
/* ignored */
77+
}
7478

7579
// macOS: detect Apple Silicon or discrete GPU
7680
if (process.platform === "darwin") {
7781
try {
78-
const spOutput = runCapture(
79-
"system_profiler SPDisplaysDataType 2>/dev/null",
80-
{ ignoreError: true }
81-
);
82+
const spOutput = runCapture("system_profiler SPDisplaysDataType 2>/dev/null", {
83+
ignoreError: true,
84+
});
8285
if (spOutput) {
8386
const chipMatch = spOutput.match(/Chipset Model:\s*(.+)/);
8487
const vramMatch = spOutput.match(/VRAM.*?:\s*(\d+)\s*(MB|GB)/i);
@@ -96,7 +99,9 @@ function detectGpu() {
9699
try {
97100
const memBytes = runCapture("sysctl -n hw.memsize", { ignoreError: true });
98101
if (memBytes) memoryMB = Math.floor(parseInt(memBytes, 10) / 1024 / 1024);
99-
} catch { /* ignored */ }
102+
} catch {
103+
/* ignored */
104+
}
100105
}
101106

102107
return {
@@ -110,7 +115,9 @@ function detectGpu() {
110115
};
111116
}
112117
}
113-
} catch { /* ignored */ }
118+
} catch {
119+
/* ignored */
120+
}
114121
}
115122

116123
return null;
@@ -145,7 +152,7 @@ function startNimContainerByName(name, model, port = 8000) {
145152

146153
console.log(` Starting NIM container: ${name}`);
147154
run(
148-
`docker run -d --gpus all -p ${Number(port)}:8000 --name ${qn} --shm-size 16g ${shellQuote(image)}`
155+
`docker run -d --gpus all -p ${Number(port)}:8000 --name ${qn} --shm-size 16g ${shellQuote(image)}`,
149156
);
150157
return name;
151158
}
@@ -165,7 +172,9 @@ function waitForNimHealth(port = 8000, timeout = 300) {
165172
console.log(" NIM is healthy.");
166173
return true;
167174
}
168-
} catch { /* ignored */ }
175+
} catch {
176+
/* ignored */
177+
}
169178
require("child_process").spawnSync("sleep", [String(intervalSec)]);
170179
}
171180
console.error(` NIM did not become healthy within ${timeout}s.`);
@@ -192,10 +201,9 @@ function nimStatus(sandboxName, port) {
192201
function nimStatusByName(name, port) {
193202
try {
194203
const qn = shellQuote(name);
195-
const state = runCapture(
196-
`docker inspect --format '{{.State.Status}}' ${qn} 2>/dev/null`,
197-
{ ignoreError: true }
198-
);
204+
const state = runCapture(`docker inspect --format '{{.State.Status}}' ${qn} 2>/dev/null`, {
205+
ignoreError: true,
206+
});
199207
if (!state) return { running: false, container: name };
200208

201209
let healthy = false;
@@ -210,7 +218,7 @@ function nimStatusByName(name, port) {
210218
}
211219
const health = runCapture(
212220
`curl -sf http://localhost:${resolvedHostPort}/v1/models 2>/dev/null`,
213-
{ ignoreError: true }
221+
{ ignoreError: true },
214222
);
215223
healthy = !!health;
216224
}

bin/lib/onboard-session.js

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,9 @@ function createSession(overrides = {}) {
5454
credentialEnv: overrides.credentialEnv || null,
5555
preferredInferenceApi: overrides.preferredInferenceApi || null,
5656
nimContainer: overrides.nimContainer || null,
57-
policyPresets: Array.isArray(overrides.policyPresets) ? overrides.policyPresets.filter((value) => typeof value === "string") : null,
57+
policyPresets: Array.isArray(overrides.policyPresets)
58+
? overrides.policyPresets.filter((value) => typeof value === "string")
59+
: null,
5860
metadata: {
5961
gatewayName: overrides.metadata?.gatewayName || "nemoclaw",
6062
},
@@ -72,7 +74,10 @@ function isObject(value) {
7274
function redactSensitiveText(value) {
7375
if (typeof value !== "string") return null;
7476
return value
75-
.replace(/(NVIDIA_API_KEY|OPENAI_API_KEY|ANTHROPIC_API_KEY|GEMINI_API_KEY|COMPATIBLE_API_KEY|COMPATIBLE_ANTHROPIC_API_KEY)=\S+/gi, "$1=<REDACTED>")
77+
.replace(
78+
/(NVIDIA_API_KEY|OPENAI_API_KEY|ANTHROPIC_API_KEY|GEMINI_API_KEY|COMPATIBLE_API_KEY|COMPATIBLE_ANTHROPIC_API_KEY)=\S+/gi,
79+
"$1=<REDACTED>",
80+
)
7681
.replace(/Bearer\s+\S+/gi, "Bearer <REDACTED>")
7782
.replace(/nvapi-[A-Za-z0-9_-]{10,}/g, "<REDACTED>")
7883
.replace(/ghp_[A-Za-z0-9]{20,}/g, "<REDACTED>")
@@ -84,7 +89,8 @@ function sanitizeFailure(input) {
8489
if (!input) return null;
8590
const step = typeof input.step === "string" ? input.step : null;
8691
const message = redactSensitiveText(input.message);
87-
const recordedAt = typeof input.recordedAt === "string" ? input.recordedAt : new Date().toISOString();
92+
const recordedAt =
93+
typeof input.recordedAt === "string" ? input.recordedAt : new Date().toISOString();
8894
return step || message ? { step, message, recordedAt } : null;
8995
}
9096

@@ -127,9 +133,12 @@ function normalizeSession(data) {
127133
model: typeof data.model === "string" ? data.model : null,
128134
endpointUrl: typeof data.endpointUrl === "string" ? redactUrl(data.endpointUrl) : null,
129135
credentialEnv: typeof data.credentialEnv === "string" ? data.credentialEnv : null,
130-
preferredInferenceApi: typeof data.preferredInferenceApi === "string" ? data.preferredInferenceApi : null,
136+
preferredInferenceApi:
137+
typeof data.preferredInferenceApi === "string" ? data.preferredInferenceApi : null,
131138
nimContainer: typeof data.nimContainer === "string" ? data.nimContainer : null,
132-
policyPresets: Array.isArray(data.policyPresets) ? data.policyPresets.filter((value) => typeof value === "string") : null,
139+
policyPresets: Array.isArray(data.policyPresets)
140+
? data.policyPresets.filter((value) => typeof value === "string")
141+
: null,
133142
lastStepStarted: typeof data.lastStepStarted === "string" ? data.lastStepStarted : null,
134143
lastCompletedStep: typeof data.lastCompletedStep === "string" ? data.lastCompletedStep : null,
135144
failure: sanitizeFailure(data.failure),
@@ -172,7 +181,7 @@ function saveSession(session) {
172181
ensureSessionDir();
173182
const tmpFile = path.join(
174183
SESSION_DIR,
175-
`.onboard-session.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2, 8)}.tmp`
184+
`.onboard-session.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2, 8)}.tmp`,
176185
);
177186
fs.writeFileSync(tmpFile, JSON.stringify(normalized, null, 2), { mode: 0o600 });
178187
fs.renameSync(tmpFile, SESSION_FILE);
@@ -222,7 +231,7 @@ function acquireOnboardLock(command = null) {
222231
command: typeof command === "string" ? command : null,
223232
},
224233
null,
225-
2
234+
2,
226235
);
227236

228237
for (let attempt = 0; attempt < 2; attempt++) {
@@ -358,7 +367,8 @@ function filterSafeUpdates(updates) {
358367
if (typeof updates.model === "string") safe.model = updates.model;
359368
if (typeof updates.endpointUrl === "string") safe.endpointUrl = redactUrl(updates.endpointUrl);
360369
if (typeof updates.credentialEnv === "string") safe.credentialEnv = updates.credentialEnv;
361-
if (typeof updates.preferredInferenceApi === "string") safe.preferredInferenceApi = updates.preferredInferenceApi;
370+
if (typeof updates.preferredInferenceApi === "string")
371+
safe.preferredInferenceApi = updates.preferredInferenceApi;
362372
if (typeof updates.nimContainer === "string") safe.nimContainer = updates.nimContainer;
363373
if (Array.isArray(updates.policyPresets)) {
364374
safe.policyPresets = updates.policyPresets.filter((value) => typeof value === "string");
@@ -401,7 +411,7 @@ function summarizeForDebug(session = loadSession()) {
401411
completedAt: step.completedAt,
402412
error: step.error,
403413
},
404-
])
414+
]),
405415
),
406416
};
407417
}

0 commit comments

Comments
 (0)