Files
gnome-jarvis/vendor/agent-harness/agent/policy.js
T
snxraven 5317576087
Rolling release / release (push) Successful in 8m2s
Allow to change the agents name + Workspace files
2026-09-12 15:30:11 -04:00

90 lines
2.5 KiB
JavaScript

/** Permission + shell policy with no Bare imports (unit-testable on Node). */
const WRITE_TOOLS = new Set(['search_replace', 'write_file', 'run_terminal_cmd', 'use_tool']);
const ASK_TOOLS = new Set(['run_terminal_cmd', 'use_tool']);
// web_fetch, fetch_page, google_search, web_search, wiki_search, hn_search, and code_search are public reads; they do not prompt.
const SHELL_ALLOW = new Set([
'git', 'rg', 'grep', 'ls', 'cat', 'head', 'tail', 'pwd', 'echo', 'node', 'npm', 'npx',
'python3', 'python', 'cargo', 'go', 'make', 'bare', 'wc', 'sort', 'uniq', 'find', 'sed', 'awk',
]);
const SHELL_UNSAFE = /[;|`$()<>\n]|&&|\|\|/;
const SHELL_REMEMBER_PREFIXES = ['git status', 'git diff'];
const IDENTITY_FILES = new Set([
'soul.md',
'identity.md',
'agents.md',
'user.md',
'memory.md',
'bootstrap.md',
'heartbeat.md',
'tools.md',
]);
function isIdentityPath(filePath) {
const rel = String(filePath || '').replace(/\\/g, '/');
const base = rel.split('/').pop().toLowerCase();
if (IDENTITY_FILES.has(base)) return true;
return /(^|\/)memory\/\d{4}-\d{2}-\d{2}\.md$/i.test(rel);
}
function needsPermission(toolName, mode) {
if (mode === 'always-approve') return false;
if (mode === 'allowlist') return ASK_TOOLS.has(toolName);
return WRITE_TOOLS.has(toolName) || ASK_TOOLS.has(toolName);
}
function shellName(command) {
const c = String(command || '').trim();
const first = c.split(/\s+/)[0] || '';
return first.replace(/^["']|["']$/g, '').split(/[/\\]/).pop();
}
function shellAllowlisted(command) {
return SHELL_ALLOW.has(shellName(command));
}
function shellSafe(command) {
const c = String(command || '');
if (!c.trim()) return false;
if (SHELL_UNSAFE.test(c)) return false;
return shellAllowlisted(c);
}
function shellPrefix(command, n) {
return String(command || '')
.trim()
.split(/\s+/)
.slice(0, n || 2)
.join(' ');
}
function matchesCommandPrefix(command, pattern) {
const c = String(command || '').trim();
const p = String(pattern || '').trim();
if (!p) return false;
if (c === p) return true;
if (c.indexOf(p + ' ') === 0) return true;
return false;
}
function isRememberableShell(command) {
return SHELL_REMEMBER_PREFIXES.some((p) => matchesCommandPrefix(command, p));
}
module.exports = {
WRITE_TOOLS,
ASK_TOOLS,
SHELL_ALLOW,
SHELL_REMEMBER_PREFIXES,
IDENTITY_FILES,
isIdentityPath,
needsPermission,
shellName,
shellAllowlisted,
shellSafe,
shellPrefix,
matchesCommandPrefix,
isRememberableShell,
};