@agentwares/agentguard 0.1.7 → 0.1.10
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/CHANGELOG.md +108 -0
- package/README.md +223 -16
- package/dist/audit-5LUDXZLG.js +18 -0
- package/dist/audit-5LUDXZLG.js.map +1 -0
- package/dist/chunk-2QDPPTPY.js +179 -0
- package/dist/chunk-2QDPPTPY.js.map +1 -0
- package/dist/chunk-4WTFMFRY.js +1270 -0
- package/dist/chunk-4WTFMFRY.js.map +1 -0
- package/dist/chunk-5WRI5ZAA.js +31 -0
- package/dist/chunk-5WRI5ZAA.js.map +1 -0
- package/dist/chunk-DEVXG3IB.js +113 -0
- package/dist/chunk-DEVXG3IB.js.map +1 -0
- package/dist/chunk-F73VDY3W.js +202 -0
- package/dist/chunk-F73VDY3W.js.map +1 -0
- package/dist/chunk-IEJK7N3B.js +275 -0
- package/dist/chunk-IEJK7N3B.js.map +1 -0
- package/dist/chunk-IS3DAHZI.js +1698 -0
- package/dist/chunk-IS3DAHZI.js.map +1 -0
- package/dist/chunk-JSELR4SG.js +780 -0
- package/dist/chunk-JSELR4SG.js.map +1 -0
- package/dist/chunk-OM5L7A32.js +199 -0
- package/dist/chunk-OM5L7A32.js.map +1 -0
- package/dist/chunk-SWZQMPDG.js +206 -0
- package/dist/chunk-SWZQMPDG.js.map +1 -0
- package/dist/chunk-TJXZBOHL.js +529 -0
- package/dist/chunk-TJXZBOHL.js.map +1 -0
- package/dist/chunk-XOBFANL4.js +119 -0
- package/dist/chunk-XOBFANL4.js.map +1 -0
- package/dist/chunk-XPNBYSIN.js +23 -0
- package/dist/chunk-XPNBYSIN.js.map +1 -0
- package/dist/chunk-YBVD6HTT.js +1036 -0
- package/dist/chunk-YBVD6HTT.js.map +1 -0
- package/dist/chunk-ZG4LGUJE.js +847 -0
- package/dist/chunk-ZG4LGUJE.js.map +1 -0
- package/dist/cli.js +10 -4775
- package/dist/cli.js.map +1 -1
- package/dist/fixtures/crm-server.js +6 -1272
- package/dist/fixtures/crm-server.js.map +1 -1
- package/dist/fixtures/demo-agent.js +4 -115
- package/dist/fixtures/demo-agent.js.map +1 -1
- package/dist/index.d.ts +73 -14
- package/dist/index.js +247 -5138
- package/dist/index.js.map +1 -1
- package/dist/init-MKPQU2JG.js +17 -0
- package/dist/init-MKPQU2JG.js.map +1 -0
- package/dist/proxy-6GP63TLD.js +146 -0
- package/dist/proxy-6GP63TLD.js.map +1 -0
- package/dist/tools-XS7PMTLT.js +15 -0
- package/dist/tools-XS7PMTLT.js.map +1 -0
- package/llms.txt +10 -4
- package/package.json +16 -4
- package/server.json +9 -9
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/hooks/clients.ts"],"sourcesContent":["/**\n * Where each coding agent reads its pre-execution hooks, and the entry okgate writes there.\n * Verified 7 October 2026 against:\n *\n * - Claude Code: https://code.claude.com/docs/en/hooks — `hooks.PreToolUse[]` in\n * `.claude/settings.json` (project) or `~/.claude/settings.json` (user); a matcher with\n * characters beyond letters, digits, `_`, `-`, `,` and `|` is an unanchored regex; `timeout`\n * in seconds.\n * - Codex CLI: https://developers.openai.com/codex/hooks — `hooks.PreToolUse[]` in\n * `.codex/hooks.json` or `~/.codex/hooks.json`; the matcher is a regex over the tool name\n * (`Bash`, `apply_patch`, `mcp__…`); `timeout` in seconds; a new hook runs only after the user\n * trusts it in `/hooks`.\n * - Gemini CLI: https://github.com/google-gemini/gemini-cli/blob/main/docs/hooks/reference.md —\n * `hooks.BeforeTool[]` in `.gemini/settings.json` or `~/.gemini/settings.json`; regex matcher\n * over `run_shell_command`, `write_file`, `replace`, `mcp_…`; `timeout` in milliseconds.\n */\nimport { copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport {\n LEGACY_POLICY_FILE,\n LEGACY_STATE_DIR,\n POLICY_FILE,\n STATE_DIR,\n type HookClient,\n} from \"@agentwares/agentguard-core\";\n\nexport type InstallScope = \"project\" | \"user\";\n\nexport interface HookTarget {\n client: HookClient;\n label: string;\n scope: InstallScope;\n settingsPath: string;\n event: \"PreToolUse\" | \"BeforeTool\";\n matcher: string;\n handler: Record<string, unknown>;\n /** what the user has to do in the client before the hook runs */\n note?: string;\n}\n\n/** Tools worth a check: the shell, file writes and MCP tools. Reads are left alone. */\nexport const MATCHERS: Record<HookClient, string> = {\n \"claude-code\": \"^(Bash|PowerShell|Write|Edit|MultiEdit|NotebookEdit)$|^mcp__\",\n codex: \"^(Bash|apply_patch)$|^mcp__\",\n \"gemini-cli\": \"^(run_shell_command|write_file|replace)$|^mcp_\",\n};\n\nexport const CLIENT_ALIASES: Record<string, HookClient> = {\n claude: \"claude-code\",\n \"claude-code\": \"claude-code\",\n codex: \"codex\",\n gemini: \"gemini-cli\",\n \"gemini-cli\": \"gemini-cli\",\n};\n\nexport function hookTarget(\n client: HookClient,\n scope: InstallScope,\n where: { cwd: string; home: string },\n command: string,\n timeoutS = 30,\n): HookTarget {\n const root = scope === \"project\" ? where.cwd : where.home;\n if (client === \"claude-code\")\n return {\n client,\n label: \"Claude Code\",\n scope,\n settingsPath: join(root, \".claude\", \"settings.json\"),\n event: \"PreToolUse\",\n matcher: MATCHERS[client],\n handler: { type: \"command\", command, timeout: timeoutS, statusMessage: \"okgate\" },\n };\n if (client === \"codex\")\n return {\n client,\n label: \"Codex CLI\",\n scope,\n settingsPath: join(root, \".codex\", \"hooks.json\"),\n event: \"PreToolUse\",\n matcher: MATCHERS[client],\n handler: { type: \"command\", command, timeout: timeoutS, statusMessage: \"okgate\" },\n note: \"Codex runs a new hook only after you trust it: open /hooks in Codex and trust the okgate entry.\",\n };\n return {\n client,\n label: \"Gemini CLI\",\n scope,\n settingsPath: join(root, \".gemini\", \"settings.json\"),\n event: \"BeforeTool\",\n matcher: MATCHERS[client],\n handler: {\n name: \"okgate\",\n type: \"command\",\n command,\n timeout: timeoutS * 1000,\n description: \"okgate: one rulebook for shell commands and file edits\",\n },\n note:\n scope === \"project\"\n ? \"Gemini CLI fingerprints project hooks: confirm the okgate hook the first time it asks.\"\n : undefined,\n };\n}\n\n/** Is this hook command one okgate wrote, under either name (agentguard before the rename)? */\nexport function isGuardHookCommand(command: unknown): boolean {\n return (\n typeof command === \"string\" &&\n /okgate|agentguard/.test(command) &&\n /\\bhook\\s+pre-tool-use\\b/.test(command)\n );\n}\n\n/**\n * The backup of a file okgate rewrites: `<file>.okgate-backup`, or the `<file>.agentguard-backup`\n * an okgate-era install left, which holds the older original and so wins.\n */\nexport function backupFor(path: string): { existing?: string; next: string } {\n const legacy = `${path}.agentguard-backup`;\n const next = `${path}.okgate-backup`;\n return { existing: [legacy, next].find((b) => existsSync(b)), next };\n}\n\ntype Json = Record<string, unknown>;\ninterface MatcherGroup {\n matcher?: string;\n hooks?: Json[];\n [k: string]: unknown;\n}\n\nfunction readSettings(path: string): Json {\n if (!existsSync(path)) return {};\n const text = readFileSync(path, \"utf8\");\n if (!text.trim()) return {};\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch (err) {\n throw new Error(\n `${path} is not valid JSON (${err instanceof Error ? err.message : String(err)}); fix it or move it aside — okgate will not overwrite it`,\n { cause: err },\n );\n }\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed))\n throw new Error(`${path} is not a JSON object; okgate will not overwrite it`);\n return parsed as Json;\n}\n\nfunction groupsOf(settings: Json, event: string): MatcherGroup[] {\n const hooks = settings.hooks;\n if (!hooks || typeof hooks !== \"object\") return [];\n const groups = (hooks as Json)[event];\n return Array.isArray(groups) ? (groups as MatcherGroup[]) : [];\n}\n\n/** The okgate handlers currently in a settings file. */\nexport function installedHandlers(target: HookTarget): Json[] {\n const settings = readSettings(target.settingsPath);\n return groupsOf(settings, target.event).flatMap((g) =>\n (g.hooks ?? []).filter((h) => isGuardHookCommand(h.command)),\n );\n}\n\n/**\n * Write (or update in place) the okgate entry, keeping every other setting and hook. The\n * first change to an existing file leaves a `*.okgate-backup` next to it (or keeps an agentguard-era `*.agentguard-backup`).\n */\nexport function installHook(target: HookTarget): {\n status: \"added\" | \"updated\" | \"unchanged\";\n backup?: string;\n} {\n const existed = existsSync(target.settingsPath);\n const settings = readSettings(target.settingsPath);\n const hooks = (\n settings.hooks && typeof settings.hooks === \"object\" ? settings.hooks : {}\n ) as Json;\n const groups = groupsOf(settings, target.event);\n const isOurs = (h: Json): boolean => isGuardHookCommand(h.command);\n const ours = groups.flatMap((g) => (g.hooks ?? []).filter(isOurs));\n const exact = groups.some(\n (g) =>\n g.matcher === target.matcher &&\n g.hooks?.length === 1 &&\n JSON.stringify(g.hooks[0]) === JSON.stringify(target.handler),\n );\n if (exact && ours.length === 1) return { status: \"unchanged\" };\n const kept: MatcherGroup[] = [];\n for (const group of groups) {\n if (!(group.hooks ?? []).some(isOurs)) {\n kept.push(group);\n continue;\n }\n const others = (group.hooks ?? []).filter((h) => !isOurs(h));\n if (others.length > 0) kept.push({ ...group, hooks: others });\n }\n kept.push({ matcher: target.matcher, hooks: [target.handler] });\n const status = ours.length > 0 ? \"updated\" : \"added\";\n hooks[target.event] = kept;\n settings.hooks = hooks;\n let backup: string | undefined;\n if (existed) {\n const { existing, next } = backupFor(target.settingsPath);\n backup = existing ?? next;\n if (!existing) copyFileSync(target.settingsPath, backup);\n }\n mkdirSync(dirname(target.settingsPath), { recursive: true });\n writeFileSync(target.settingsPath, JSON.stringify(settings, null, 2) + \"\\n\");\n return { status, backup };\n}\n\n/** Remove okgate's entries; other hooks and settings stay. Returns how many were removed. */\nexport function uninstallHook(target: HookTarget): number {\n if (!existsSync(target.settingsPath)) return 0;\n const settings = readSettings(target.settingsPath);\n const groups = groupsOf(settings, target.event);\n let removed = 0;\n const kept: MatcherGroup[] = [];\n for (const group of groups) {\n const others = (group.hooks ?? []).filter((h) => !isGuardHookCommand(h.command));\n removed += (group.hooks ?? []).length - others.length;\n if (others.length > 0) kept.push({ ...group, hooks: others });\n }\n if (removed === 0) return 0;\n const hooks = settings.hooks as Json;\n if (kept.length > 0) hooks[target.event] = kept;\n else delete hooks[target.event];\n if (Object.keys(hooks).length === 0) delete settings.hooks;\n writeFileSync(target.settingsPath, JSON.stringify(settings, null, 2) + \"\\n\");\n return removed;\n}\n\n/** Every settings file that can hold a hook, project and user level: edits to them are guard-config. */\nexport function hookSettingsFiles(where: { cwd: string; home: string }): string[] {\n const out: string[] = [];\n for (const root of [where.cwd, where.home]) {\n out.push(\n join(root, \".claude\", \"settings.json\"),\n join(root, \".claude\", \"settings.local.json\"),\n join(root, \".codex\", \"hooks.json\"),\n join(root, \".codex\", \"config.toml\"),\n join(root, \".gemini\", \"settings.json\"),\n );\n }\n out.push(\n join(where.home, STATE_DIR, POLICY_FILE),\n join(where.home, LEGACY_STATE_DIR, LEGACY_POLICY_FILE),\n );\n return out;\n}\n"],"mappings":"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","names":[]}
|