diff --git a/openclaw.plugin.json b/openclaw.plugin.json index cda899e..125240f 100644 --- a/openclaw.plugin.json +++ b/openclaw.plugin.json @@ -178,9 +178,25 @@ "camofox_scroll", "camofox_screenshot", "camofox_close_tab", + "camofox_evaluate", "camofox_list_tabs", "camofox_import_cookies" ], + "contracts": { + "tools": [ + "camofox_create_tab", + "camofox_snapshot", + "camofox_click", + "camofox_type", + "camofox_navigate", + "camofox_scroll", + "camofox_screenshot", + "camofox_close_tab", + "camofox_evaluate", + "camofox_list_tabs", + "camofox_import_cookies" + ] + }, "runtimeDependencies": { "camoufox": { "description": "Camoufox anti-detection browser (Firefox fork). Downloaded at install time by camoufox-js unless CAMOUFOX_EXECUTABLE points to an external bundle.", diff --git a/package.json b/package.json index 8dcb617..272c923 100644 --- a/package.json +++ b/package.json @@ -100,6 +100,10 @@ "name": "camofox_close_tab", "description": "Close a browser tab" }, + { + "name": "camofox_evaluate", + "description": "Execute JavaScript in a Camoufox tab page context" + }, { "name": "camofox_list_tabs", "description": "List open tabs for a user" diff --git a/tests/unit/openclawManifest.test.js b/tests/unit/openclawManifest.test.js new file mode 100644 index 0000000..5e5ab5f --- /dev/null +++ b/tests/unit/openclawManifest.test.js @@ -0,0 +1,23 @@ +import { describe, test, expect } from '@jest/globals'; +import fs from 'fs'; + +const RUNTIME_TOOL_RE = /name:\s*["'](camofox_[^"']+)["']/g; + +function runtimeToolNames() { + const plugin = fs.readFileSync(new URL('../../plugin.js', import.meta.url), 'utf8'); + return [...plugin.matchAll(RUNTIME_TOOL_RE)].map(match => match[1]); +} + +describe('OpenClaw manifest', () => { + test('declares ownership contracts for every runtime tool', () => { + const manifest = JSON.parse(fs.readFileSync(new URL('../../openclaw.plugin.json', import.meta.url), 'utf8')); + const pkg = JSON.parse(fs.readFileSync(new URL('../../package.json', import.meta.url), 'utf8')); + const runtimeTools = runtimeToolNames(); + const packageTools = pkg.openclaw.tools.map(tool => tool.name); + + expect(manifest.contracts).toBeDefined(); + expect(manifest.contracts.tools).toEqual(runtimeTools); + expect(manifest.tools).toEqual(runtimeTools); + expect(packageTools).toEqual(runtimeTools); + }); +});