mirror of
https://github.com/JuliusBrussee/caveman.git
synced 2026-08-11 13:21:09 +02:00
Marketplace fix (#712, #705): Claude Desktop rejects plugins containing a top-level bin/ directory, and .claude-plugin/marketplace.json packages the repo root, so the installer directory is now cli/. Every reference updated (package.json bin entry + files, shims, docs, tests, caveman-init require path). Supersedes PR #726. Security (PR #717 verified): quoteWinArg only quoted on whitespace/quotes, leaving cmd.exe metacharacters (& | ^ < > % parens) unescaped on the shell:true Windows spawn path. Attacker-influenced arguments (--with-init cwd, --with-mcp-shrink value) could chain commands. Trigger regex now covers the metacharacter set; quoting logic split into a platform- independent, unit-tested helper. Also: - uninstall removes .caveman-active.prev, .caveman-mode-log.jsonl, .caveman-statusline-suffix, .caveman-nudge-shown; keeps .caveman-history.jsonl with a printed note; dry-run now says 'would remove' instead of lying (#635, supersedes PRs #693 #636) - Array.isArray guard in rewriteLegacyManagedHookCommands — malformed hook event no longer crashes the installer mid-run (supersedes PR #646) - gemini extensions install --consent: the security prompt hung every piped/non-interactive install forever (#676, part of PR #664) - OpenClaw skill stamps the real PINNED_REF version instead of hardcoded 1.0.0; new --no-always flag for load-on-demand installs (supersedes PR #720) - shims scope NPM_CONFIG_ALLOW_GIT=all to the npx call — npm >=12 defaults allow-git to none and EALLOWGITs github: installs (#698) - .codex/config.toml ships hooks + codex_hooks keys so auto-activation works on both sides of the codex-cli rename (#617) - caveman-help card shows the Windows config path (%APPDATA%) (#723) - caveman-parse.js added to HOOK_FILES, opencode payload (.cjs), and the regenerated checksums.sha256; manifest now matches shipped hook contents — release must bump PINNED_REF to a tag containing these files Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016ySX6TBWZuvFze4ajf7Hpf
43 lines
1.5 KiB
JavaScript
43 lines
1.5 KiB
JavaScript
'use strict';
|
|
|
|
// Strip the `tools:` field from a Claude-Code-style subagent frontmatter so
|
|
// the file is valid for opencode, whose schema rejects the YAML array form
|
|
// (`tools: [Read, Grep, Bash]`) with:
|
|
//
|
|
// Configuration is invalid at .../agents/cavecrew-reviewer.md
|
|
// ↳ Expected object | undefined, got ["Read","Grep","Bash"] tools
|
|
//
|
|
// opencode allows `tools` to be a map (`{read: true, grep: true}`) or
|
|
// omitted entirely. Omitting falls back to opencode's default tool set,
|
|
// which is what the cavecrew subagent prompts already self-restrict against
|
|
// in their body ("Read-only locator", "No `Bash` available", etc.), so
|
|
// dropping the array form is safe.
|
|
|
|
const TOOLS_FIELD_RE = /^tools[ \t]*:/;
|
|
const CONTINUATION_RE = /^[ \t]/;
|
|
const FRONTMATTER_FENCE = '---\n';
|
|
|
|
function stripOpencodeAgentTools(content) {
|
|
if (typeof content !== 'string' || !content.startsWith(FRONTMATTER_FENCE)) return content;
|
|
const fmEnd = content.indexOf('\n---', FRONTMATTER_FENCE.length);
|
|
if (fmEnd < 0) return content;
|
|
|
|
const fm = content.slice(FRONTMATTER_FENCE.length, fmEnd);
|
|
const rest = content.slice(fmEnd);
|
|
|
|
const out = [];
|
|
let dropping = false;
|
|
for (const line of fm.split('\n')) {
|
|
if (dropping) {
|
|
if (CONTINUATION_RE.test(line)) continue;
|
|
dropping = false;
|
|
}
|
|
if (TOOLS_FIELD_RE.test(line)) { dropping = true; continue; }
|
|
out.push(line);
|
|
}
|
|
|
|
return FRONTMATTER_FENCE + out.join('\n') + rest;
|
|
}
|
|
|
|
module.exports = { stripOpencodeAgentTools };
|