Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/actions/basic-checks/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ runs:
shell: bash
run: npm run build:cli

- name: Validate config schemas
shell: bash
run: npm run validate:configs

- name: Run checks
shell: bash
run: npx prek run --all-files --stage pre-push
10 changes: 10 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,16 @@ repos:
- id: check-shebang-scripts-are-executable
priority: 10

- repo: local
hooks:
- id: validate-config-schemas
name: Validate config files against JSON schemas
entry: npx tsx scripts/validate-configs.ts
language: system
pass_filenames: false
files: ^(nemoclaw-blueprint/.*\.yaml$|nemoclaw/openclaw\.plugin\.json$|schemas/.*\.json$)
priority: 10

- repo: https://github.com/shellcheck-py/shellcheck-py
rev: v0.11.0.1
hooks:
Expand Down
2 changes: 1 addition & 1 deletion nemoclaw-blueprint/blueprint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,4 @@ components:
endpoints:
- host: "nim-service.local"
port: 8000
protocol: rest
access: full
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"typecheck": "tsc -p jsconfig.json",
"build:cli": "tsc -p tsconfig.src.json",
"typecheck:cli": "tsc -p tsconfig.cli.json",
"validate:configs": "tsx scripts/validate-configs.ts",
"migrate:js-to-ts": "tsx scripts/migrate-js-to-ts.ts",
"ts-migration:assist": "tsx scripts/ts-migration-assist.ts",
"ts-migration:bulk-fix-prs": "tsx scripts/ts-migration-bulk-fix-prs.ts",
Expand Down Expand Up @@ -54,6 +55,7 @@
"@j178/prek": "^0.3.6",
"@types/node": "^25.5.0",
"@typescript-eslint/parser": "^8.58.1",
"ajv": "^8.17.0",
"@vitest/coverage-v8": "^4.1.0",
"eslint": "^10.1.0",
"execa": "^9.6.1",
Expand Down
172 changes: 172 additions & 0 deletions schemas/blueprint.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://github.com/NVIDIA/NemoClaw/schemas/blueprint.schema.json",
"title": "NemoClaw Blueprint",
"description": "Schema for nemoclaw-blueprint/blueprint.yaml — defines sandbox orchestration, inference profiles, and policy configuration.",
"type": "object",
"required": ["version", "profiles", "components"],
"additionalProperties": false,
"properties": {
"version": {
"type": "string",
"pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$",
"description": "Semver version of the blueprint."
},
"min_openshell_version": {
"type": "string",
"pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$",
"description": "Minimum compatible OpenShell version."
},
"min_openclaw_version": {
"type": "string",
"pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$",
"description": "Minimum compatible OpenClaw version."
},
Comment thread
coderabbitai[bot] marked this conversation as resolved.
"digest": {
"type": "string",
"description": "Computed at release time."
},
"profiles": {
"type": "array",
"items": { "type": "string" },
"minItems": 1,
"uniqueItems": true,
"description": "Declared inference profile names."
},
"description": {
"type": "string"
},
"components": {
"type": "object",
"required": ["sandbox", "inference"],
"additionalProperties": false,
"properties": {
"sandbox": {
"type": "object",
"required": ["image", "name"],
"additionalProperties": false,
"properties": {
"image": {
"type": "string",
"description": "Container image for the sandbox."
},
"name": {
"type": "string",
"description": "Default sandbox name."
},
"forward_ports": {
"type": "array",
"items": { "type": "integer", "minimum": 1, "maximum": 65535 }
}
}
},
"inference": {
"type": "object",
"required": ["profiles"],
"additionalProperties": false,
"properties": {
"profiles": {
"type": "object",
"minProperties": 1,
"additionalProperties": {
"$ref": "#/$defs/inferenceProfile"
}
}
}
},
"policy": {
"type": "object",
"required": ["base"],
"additionalProperties": false,
"properties": {
"base": {
"type": "string",
"description": "Path to the base sandbox policy file."
},
"additions": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/policyAddition"
}
}
}
}
}
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
},
"$defs": {
"inferenceProfile": {
"type": "object",
"required": ["provider_type", "endpoint"],
"additionalProperties": false,
"properties": {
"provider_type": { "type": "string" },
"provider_name": { "type": "string" },
"endpoint": { "type": "string" },
"model": { "type": "string" },
"credential_env": { "type": "string" },
"credential_default": { "type": "string" },
"timeout_secs": { "type": "integer", "minimum": 1 },
"dynamic_endpoint": { "type": "boolean" }
}
},
"policyAddition": {
"type": "object",
"required": ["name", "endpoints"],
"additionalProperties": false,
"properties": {
"name": { "type": "string" },
"endpoints": {
"type": "array",
"items": { "$ref": "#/$defs/endpoint" },
"minItems": 1
}
}
},
"endpoint": {
"type": "object",
"required": ["host", "port"],
"additionalProperties": false,
"properties": {
"host": { "type": "string" },
"port": { "type": "integer", "minimum": 1, "maximum": 65535 },
"protocol": { "type": "string", "enum": ["rest"] },
"enforcement": { "type": "string", "enum": ["enforce", "audit"] },
"tls": { "type": "string", "enum": ["terminate", "passthrough"] },
"access": { "type": "string", "enum": ["full"] },
"rules": {
"type": "array",
"items": { "$ref": "#/$defs/rule" },
"minItems": 1
}
},
"if": {
"properties": { "protocol": { "const": "rest" } },
"required": ["protocol"]
},
"then": { "required": ["rules"] }
},
"rule": {
"type": "object",
"required": ["allow"],
"additionalProperties": false,
"properties": {
"allow": {
"type": "object",
"required": ["method", "path"],
"additionalProperties": false,
"properties": {
"method": {
"type": "string",
"enum": ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]
},
"path": {
"type": "string",
"pattern": "^/"
}
}
}
}
}
}
}
Empty file.
35 changes: 35 additions & 0 deletions schemas/openclaw-plugin.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://github.com/NVIDIA/NemoClaw/schemas/openclaw-plugin.schema.json",
"title": "NemoClaw OpenClaw Plugin Manifest",
"description": "Schema for nemoclaw/openclaw.plugin.json — the OpenClaw plugin manifest that declares the plugin identity and its configuration schema.",
"type": "object",
"required": ["id", "name", "version", "description", "configSchema"],
"additionalProperties": false,
"properties": {
"id": {
"type": "string",
"minLength": 1,
"description": "Unique plugin identifier."
},
"name": {
"type": "string",
"minLength": 1,
"description": "Human-readable plugin name."
},
"version": {
"type": "string",
"pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$",
"description": "Semver version of the plugin."
},
"description": {
"type": "string",
"minLength": 1,
"description": "Short description of the plugin."
},
"configSchema": {
"type": "object",
"description": "JSON Schema object describing the plugin's configuration fields."
}
}
}
100 changes: 100 additions & 0 deletions schemas/policy-preset.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://github.com/NVIDIA/NemoClaw/schemas/policy-preset.schema.json",
"title": "NemoClaw Policy Preset",
"description": "Schema for policy presets (nemoclaw-blueprint/policies/presets/*.yaml) — named network policy bundles that can be merged into the base sandbox policy.",
"type": "object",
"required": ["preset", "network_policies"],
"additionalProperties": false,
"properties": {
"preset": {
"type": "object",
"required": ["name", "description"],
"additionalProperties": false,
"properties": {
"name": { "type": "string", "minLength": 1 },
"description": { "type": "string", "minLength": 1 }
}
},
"network_policies": {
"type": "object",
"minProperties": 1,
"additionalProperties": {
"$ref": "#/$defs/networkPolicyEntry"
}
}
},
"$defs": {
"networkPolicyEntry": {
"type": "object",
"required": ["name", "endpoints"],
"properties": {
"name": { "type": "string" },
"endpoints": {
"type": "array",
"items": { "$ref": "#/$defs/endpoint" },
"minItems": 1
},
"binaries": {
"type": "array",
"items": { "$ref": "#/$defs/binary" }
}
}
},
"endpoint": {
"type": "object",
"required": ["host", "port"],
"properties": {
"host": { "type": "string" },
"port": { "type": "integer", "minimum": 1, "maximum": 65535 },
"protocol": { "type": "string", "enum": ["rest"] },
"enforcement": { "type": "string", "enum": ["enforce", "audit"] },
"tls": { "type": "string", "enum": ["terminate", "passthrough"] },
"access": { "type": "string", "enum": ["full"] },
"rules": {
"type": "array",
"items": { "$ref": "#/$defs/rule" },
"minItems": 1
}
},
"if": {
"properties": { "protocol": { "const": "rest" } },
"required": ["protocol"]
},
"then": { "required": ["rules"] }
},
"rule": {
"type": "object",
"required": ["allow"],
"additionalProperties": false,
"properties": {
"allow": {
"type": "object",
"required": ["method", "path"],
"additionalProperties": false,
"properties": {
"method": {
"type": "string",
"enum": ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]
},
"path": {
"type": "string",
"pattern": "^/"
}
}
}
}
},
"binary": {
"type": "object",
"required": ["path"],
"additionalProperties": false,
"properties": {
"path": {
"type": "string",
"pattern": "^/"
}
}
}
}
}
Loading
Loading