@kenhkl/agent-moss 0.12.7 → 0.12.8
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/dist/agents/__pycache__/base.cpython-312.pyc +0 -0
- package/dist/agents/base.py +41 -4
- package/dist/cli.js +3382 -449
- package/dist/cli.js.map +1 -1
- package/dist/engine/coordinator.d.ts +13 -5
- package/dist/engine/coordinator.js +2387 -318
- package/dist/engine/coordinator.js.map +1 -1
- package/dist/rules/l2_rules.json +136 -1
- package/dist/scenarios/__init__.py +119 -0
- package/dist/scenarios/__pycache__/__init__.cpython-312.pyc +0 -0
- package/dist/scenarios/bank/rules.json +23 -0
- package/dist/server.js +4045 -1202
- package/dist/server.js.map +1 -1
- package/dist/static/index.html +119 -1
- package/package.json +2 -1
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../node_modules/tsup/assets/esm_shims.js","../src/infra/paths.ts","../src/config.ts","../src/engine/inline-analyzer.ts","../src/infra/rules-loader.ts","../src/engine/logic-rules.ts","../src/engine/skill-loader.ts","../src/infra/runtime-config.ts","../src/agents/index.ts","../src/engine/heuristic.ts","../src/engine/token-stats.ts","../node_modules/better-sqlite3/lib/util.js","../node_modules/better-sqlite3/lib/sqlite-error.js","../node_modules/file-uri-to-path/index.js","../node_modules/bindings/bindings.js","../node_modules/better-sqlite3/lib/methods/wrappers.js","../node_modules/better-sqlite3/lib/methods/transaction.js","../node_modules/better-sqlite3/lib/methods/pragma.js","../node_modules/better-sqlite3/lib/methods/backup.js","../node_modules/better-sqlite3/lib/methods/serialize.js","../node_modules/better-sqlite3/lib/methods/function.js","../node_modules/better-sqlite3/lib/methods/aggregate.js","../node_modules/better-sqlite3/lib/methods/table.js","../node_modules/better-sqlite3/lib/methods/inspect.js","../node_modules/better-sqlite3/lib/database.js","../node_modules/better-sqlite3/lib/index.js","../src/server.ts","../src/routes.ts","../src/models.ts","../src/package-json.ts","../src/engine/coordinator.ts","../src/engine/llm-analyzer.ts","../src/engine/template-loader.ts","../src/engine/script-analyzer.ts","../src/engine/script-content-analyzer.ts","../src/brain/index.ts","../src/brain/rule-store.ts","../src/brain/pattern-extractor.ts","../src/brain/reviewer.ts","../src/actrail.ts","../src/console/index.ts","../src/console/router.ts"],"sourcesContent":["// Shim globals in esm bundle\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","/**\n * Path resolution — unified data root + multi-instance (instance) isolation.\n *\n * Mirrors Python agent_moss/infra/paths.py.\n *\n * Solves two problems:\n * 1. Data-owner user directory: even when the service runs as root/systemd\n * (started via `sudo systemctl`), AGENT_MOSS_DATA_DIR can point it at the\n * \"current user\"'s data dir, so config / runtime / token all land in that\n * user's directory instead of root's /root. Falls back to\n * ~/.config/agentmoss (legacy behavior) when unset.\n *\n * 2. Token isolation by instance: services started by different agents\n * (AGENT_MOSS_INSTANCE) don't share token-usage files. With an instance,\n * tokens go to <data_root>/<instance>/agent_moss_token_stats.json; without\n * one, to <data_root>/agent_moss_token_stats.json (default location).\n *\n * config / runtime are NOT split by instance (rules/config are shared); they\n * only follow the data root.\n */\n\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport { readFileSync } from 'fs';\n\nconst ENV_DATA_ROOT = 'AGENT_MOSS_DATA_DIR';\nconst ENV_INSTANCE = 'AGENT_MOSS_INSTANCE';\n\nconst DEFAULT_DATA_ROOT = join(homedir(), '.config', 'agentmoss');\n\n/** True when the process runs as root (systemd `sudo systemctl`). */\nexport function isRoot(): boolean {\n const getuid = (process as any).getuid;\n return typeof getuid === 'function' && getuid() === 0;\n}\n\n/** Resolve the \"real user\"'s home when running as root.\n * Priority: SUDO_USER (sudo invoker) > LOGNAME/USER (login user) >\n * first UID>=1000 ordinary user in /etc/passwd. Returns null if none found. */\nexport function resolveOwnerHome(): string | null {\n for (const name of [process.env.SUDO_USER, process.env.LOGNAME, process.env.USER]) {\n if (name && name !== 'root' && name !== '') {\n const home = homeOf(name);\n if (home) return home;\n }\n }\n // /etc/passwd fallback: first UID>=1000 ordinary user\n try {\n const passwd = readFileSync('/etc/passwd', 'utf-8');\n for (const line of passwd.split('\\n')) {\n if (!line || line.startsWith('#')) continue;\n const parts = line.split(':');\n if (parts.length < 6) continue;\n const uid = parseInt(parts[2], 10);\n const name = parts[0];\n if (uid >= 1000 && name && !name.startsWith('_')) {\n return parts[5];\n }\n }\n } catch { /* ignore */ }\n return null;\n}\n\nfunction homeOf(name: string): string | null {\n try {\n const passwd = readFileSync('/etc/passwd', 'utf-8');\n for (const line of passwd.split('\\n')) {\n if (!line || line.startsWith('#')) continue;\n const parts = line.split(':');\n if (parts.length >= 6 && parts[0] === name) {\n return parts[5];\n }\n }\n } catch { /* ignore */ }\n return null;\n}\n\n/** Data root directory.\n * Priority: env AGENT_MOSS_DATA_DIR > ~/.config/agentmoss.\n * BUT when running as root (any `sudo systemctl` service), automatically\n * redirects to the real user's dir so config/runtime/token land there\n * instead of /root. */\nexport function getDataRoot(): string {\n const envPath = process.env[ENV_DATA_ROOT];\n if (envPath) return envPath;\n if (isRoot()) {\n const ownerHome = resolveOwnerHome();\n if (ownerHome) {\n return join(ownerHome, '.config', 'agentmoss');\n }\n }\n return DEFAULT_DATA_ROOT;\n}\n\n/** Instance identifier (empty string when unset). */\nexport function getInstance(): string {\n const v = process.env[ENV_INSTANCE] || '';\n return v.trim().replace(/^[/\\\\]+|[/\\\\]+$/g, '');\n}\n\n/** Config file directory (config.json). Not split by instance; follows data root. */\nexport function getConfigDir(): string {\n return getDataRoot();\n}\n\n/** Runtime config directory (agent_moss_runtime.json + skills dir). Not split by instance. */\nexport function getRuntimeConfigDir(): string {\n return getDataRoot();\n}\n\n/**\n * Token stats file path.\n * With instance → <data_root>/<instance>/agent_moss_token_stats.json\n * Without → <data_root>/agent_moss_token_stats.json\n */\nexport function getTokenStatsPath(): string {\n const instance = getInstance();\n if (instance) {\n return join(getDataRoot(), instance, 'agent_moss_token_stats.json');\n }\n return join(getDataRoot(), 'agent_moss_token_stats.json');\n}","import fs from 'fs';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\nimport type { LLMConfig, TimeoutConfig, RetryConfig } from './engine/types';\nimport { getConfigDir } from './infra/paths';\n\n/** Custom rule from user config */\nexport interface CustomRule {\n pattern: string;\n action: 'Allow' | 'Deny';\n severity: string;\n description?: string;\n}\n\n/** Read config from file (JSON), returns parsed object or null */\nfunction loadConfigFile(filePath: string): Record<string, any> | null {\n try {\n const raw = fs.readFileSync(filePath, 'utf-8');\n return JSON.parse(raw);\n } catch {\n return null;\n }\n}\n\n/** Determine config file path with priority:\n * 1. AGENT_MOSS_CONFIG_PATH env var\n * 2. ~/.config/agentmoss/config.json (auto-create if missing)\n * 3. Package default (relative to __dirname)\n */\nfunction resolveConfigPath(): string {\n const envPath = process.env.AGENT_MOSS_CONFIG_PATH;\n if (envPath) return envPath;\n\n const userConfig = path.join(getConfigDir(), 'config.json');\n if (fs.existsSync(userConfig)) return userConfig;\n\n // Auto-create from package default\n const defaultConfig = path.join(__dirname, '..', '..', 'agent_moss', 'infra', 'config.json.example');\n if (fs.existsSync(defaultConfig)) {\n const configDir = path.dirname(userConfig);\n fs.mkdirSync(configDir, { recursive: true });\n // Read the default config and filter out the api_key for safety\n const pkgConfig = loadConfigFile(defaultConfig);\n const safeConfig = pkgConfig ? { ...pkgConfig, llm: { ...pkgConfig.llm, api_key: '' } } : {};\n fs.writeFileSync(userConfig, JSON.stringify(safeConfig, null, 4), 'utf-8');\n console.log(`[AgentMoss] 已创建用户配置文件: ${userConfig}`);\n console.log(`[AgentMoss] 请编辑该文件配置你的 LLM API Key`);\n }\n return userConfig;\n}\n\n/** Load LLM config from file, merged with environment variables (env wins) */\nfunction loadLLMConfigFromFile(configPath: string): Partial<LLMConfig> {\n const data = loadConfigFile(configPath);\n if (!data?.llm) return {};\n\n const llm = data.llm;\n return {\n provider: llm.provider || '',\n baseUrl: llm.base_url || '',\n apiKey: llm.api_key || '',\n model: llm.model || '',\n temperature: llm.temperature ?? 0.1,\n maxTokens: llm.max_tokens ?? 4096,\n timeout: llm.timeout ?? 40,\n };\n}\n\n/** Load timeout/retry config from file (对齐 Python TimeoutConfig / RetryConfig) */\nfunction loadTimeoutRetryFromFile(configPath: string): { timeout: TimeoutConfig; retry: RetryConfig } {\n const data = loadConfigFile(configPath);\n const t = data?.timeout ?? {};\n const r = data?.retry ?? {};\n return {\n timeout: {\n totalTimeout: Number(t.total_timeout ?? 90),\n prompt1Timeout: Number(t.prompt1_timeout ?? 40),\n prompt2Timeout: Number(t.prompt2_timeout ?? 20),\n stepInterval: Number(t.step_interval ?? 0),\n },\n retry: {\n maxRetries: Number(r.max_retries ?? 2),\n retryInterval: Number(r.retry_interval ?? 2),\n },\n };\n}\n\n/** Global timeout/retry configuration (对齐 Python TimeoutConfig / RetryConfig) */\nlet timeoutConfig: TimeoutConfig;\nlet retryConfig: RetryConfig;\n\n/** Global LLM configuration, initialized from file + env vars (env wins) */\nlet llmConfig: LLMConfig = (() => {\n const configPath = resolveConfigPath();\n const fileConfig = fs.existsSync(configPath) ? loadLLMConfigFromFile(configPath) : {};\n const tr = loadTimeoutRetryFromFile(configPath);\n timeoutConfig = tr.timeout;\n retryConfig = tr.retry;\n\n return {\n provider: process.env.AGENT_MOSS_LLM_PROVIDER || fileConfig.provider || 'openai',\n baseUrl: process.env.AGENT_MOSS_LLM_BASE_URL || fileConfig.baseUrl || 'https://api.openai.com/v1',\n apiKey: process.env.AGENT_MOSS_LLM_API_KEY || process.env.OPENAI_API_KEY || fileConfig.apiKey || '',\n model: process.env.AGENT_MOSS_LLM_MODEL || fileConfig.model || 'gpt-4o',\n temperature: parseFloat(process.env.AGENT_MOSS_LLM_TEMPERATURE || String(fileConfig.temperature ?? '0.1')),\n maxTokens: parseInt(process.env.AGENT_MOSS_LLM_MAX_TOKENS || String(fileConfig.maxTokens ?? '4096'), 10),\n // 优先用 env,否则用 timeout 块的 prompt1Timeout(对齐 py)\n timeout: parseInt(process.env.AGENT_MOSS_LLM_TIMEOUT || String(fileConfig.timeout ?? String(tr.timeout.prompt1Timeout)), 10),\n };\n})();\n\nexport function getTimeoutConfig(): Readonly<TimeoutConfig> {\n return timeoutConfig;\n}\n\nexport function getRetryConfig(): Readonly<RetryConfig> {\n return retryConfig;\n}\n\n// 打包内 user_rules.json 路径(npm 安装自包含)+ dev 回退到仓库根 agent_moss/rules。\n// 对齐 skill-loader.ts 的 fileURLToPath(import.meta.url) 双路径解析:\n// - tsup 打包后 config.ts 被内联进 dist/{cli,server,engine/coordinator}.js,\n// import.meta.url 指向该 chunk(dist/engine/coordinator.js → __dirname=dist/engine/),\n// 故 dist 内 rules 在 ../rules(即 dist/rules/user_rules.json,copy-assets.cjs 复制)。\n// - dev(vitest) 模式 config.ts 源文件 __dirname=ts/src/,仓库根 agent_moss/rules\n// 在 ../../agent_moss/rules。三条候选路径覆盖 dist 与 dev 两种形态,命中即用。\nconst __configModuleDir = (() => {\n try { return path.dirname(fileURLToPath(import.meta.url)); }\n catch { return typeof __dirname !== 'undefined' ? __dirname : process.cwd(); }\n})();\nconst USER_RULES_PATHS = [\n path.join(__configModuleDir, 'rules', 'user_rules.json'), // 源在 ts/src/rules(一般不存在)\n path.join(__configModuleDir, '..', 'rules', 'user_rules.json'), // dist: dist/engine/../rules = dist/rules ✅\n path.join(__configModuleDir, '..', '..', 'agent_moss', 'rules', 'user_rules.json'), // dev src: ts/src/../../agent_moss\n];\n\nfunction wildcardToRegExp(pattern: string): string {\n // 对齐 Python UserRuleMatcher: re.escape(pattern).replace(r\"\\*\", \".*\")\n // JS 无 re.escape,手动转义所有正则元字符,再把转义后的 \\* 还原为 .*\n return pattern.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&').replace(/\\\\\\*/g, '.*');\n}\n\nfunction loadCustomRules(): CustomRule[] {\n const rules: CustomRule[] = [];\n // 1. AGENT_MOSS_CUSTOM_RULES env var(运行时注入,最高优先)\n try {\n const raw = process.env.AGENT_MOSS_CUSTOM_RULES;\n if (raw) {\n const parsed = JSON.parse(raw);\n if (Array.isArray(parsed)) {\n for (const r of parsed) {\n if (r && r.pattern && r.action) rules.push({ pattern: r.pattern, action: r.action, severity: r.severity || 'high' });\n }\n }\n }\n } catch { /* ignore env parse error */ }\n\n // 2. 打包内 agent_moss/rules/user_rules.json 的 sensitive_actions(通配符规则)。\n // 对齐 Python UserRuleMatcher(DEFAULT_RULES_PATH = agent_moss/rules/user_rules.json),\n // 含 crontab -e / crontab -r / * | crontab / iptables - 等用户敏感规则。\n // TS 此前只读 env 不读该文件,导致 crontab -e 等 L1 漏检(FN-2)。wildcard → RegExp。\n for (const rulesPath of USER_RULES_PATHS) {\n try {\n if (!fs.existsSync(rulesPath)) continue;\n const data = JSON.parse(fs.readFileSync(rulesPath, 'utf-8'));\n const actions = Array.isArray(data?.sensitive_actions) ? data.sensitive_actions : [];\n for (const r of actions) {\n const p = r?.pattern;\n if (!p) continue;\n rules.push({ pattern: wildcardToRegExp(p), action: 'Deny', severity: 'high' });\n }\n break; // 命中第一个存在的文件即可\n } catch { /* ignore user_rules.json read/parse error */ }\n }\n return rules;\n}\n\n/** Custom rules loaded from AGENT_MOSS_CUSTOM_RULES env var + packaged user_rules.json */\nlet customRules: CustomRule[] = loadCustomRules();\n\nexport function getLLMConfig(): Readonly<LLMConfig> {\n return llmConfig;\n}\n\nexport function updateLLMConfig(partial: Partial<LLMConfig>): void {\n llmConfig = { ...llmConfig, ...partial };\n}\n\nexport function getCustomRules(): Readonly<CustomRule[]> {\n return customRules;\n}\n\n/** Check if LLM analysis is available (API key configured + not disabled) */\nexport function isLLMAvailable(): boolean {\n if (process.env.AGENT_MOSS_DISABLE_LLM === '1') return false;\n return llmConfig.apiKey.length > 0;\n}\n\n/**\n * Probe LLM connectivity with a minimal max_tokens=1 request.\n * Mirrors Python _probe_llm (tests/conftest.py): same source of truth\n * (getLLMConfig / get_default_config), so a passing probe means the actual\n * L3 call in tests uses the same key/endpoint and will succeed.\n *\n * Returns true on any successful response (finish_reason length/stop both ok);\n * false on timeout / 401 / network error. Used by L3 tests to skip rather than\n * let a dead key fail-open and false-pass.\n */\nexport async function probeLLMConnection(timeoutMs: number = 8000): Promise<boolean> {\n if (!isLLMAvailable()) return false;\n const OpenAI = (await import('openai')).default;\n const config = getLLMConfig();\n const provider = detectProvider(config.baseUrl, config.provider);\n const extraHeaders = getProviderHeaders(provider);\n const client = new OpenAI({\n baseURL: config.baseUrl,\n apiKey: config.apiKey,\n timeout: timeoutMs,\n maxRetries: 0,\n defaultHeaders: Object.keys(extraHeaders).length > 0 ? extraHeaders : undefined,\n });\n try {\n const resp = await client.chat.completions.create({\n model: config.model,\n messages: [{ role: 'user', content: 'ping' } as any],\n max_tokens: 1,\n } as any);\n return !!(resp && resp.choices && resp.choices[0]);\n } catch {\n return false;\n }\n}\n\n/**\n * LLM analysis failure mode (mirrors Python get_llm_fail_mode).\n *\n * - \"fail_open\" (default): when L3 LLM fails and prior layers did NOT block,\n * Allow + warning log (availability-first)\n * - \"fail_closed\": LLM failure -> Deny (safety-first)\n *\n * Priority: env AGENT_MOSS_LLM_FAIL_MODE > default fail_open.\n */\nexport function getLLMFailMode(): 'fail_open' | 'fail_closed' {\n const val = (process.env.AGENT_MOSS_LLM_FAIL_MODE || 'fail_open').toLowerCase();\n return val === 'fail_closed' ? 'fail_closed' : 'fail_open';\n}\n\n// ========== Provider detection & headers ==========\n\nconst PROVIDER_HEADERS: Record<string, Record<string, string>> = {\n 'openrouter': {\n 'HTTP-Referer': 'shturl.cc/LlVD5pyWViHjM',\n 'X-OpenRouter-Title': 'AgentMoss',\n },\n 'xai': {\n 'HTTP-Referer': 'shturl.cc/LlVD5pyWViHjM',\n },\n};\n\n/** Detect provider from base URL or explicit hint (mirrors Python detect_provider) */\nexport function detectProvider(baseUrl: string, providerHint: string = ''): string {\n if (providerHint) {\n const hint = providerHint.toLowerCase();\n if (['claude', 'anthropic'].includes(hint)) return 'anthropic';\n if (['google', 'gemini'].includes(hint)) return 'gemini';\n if (['zai-coding-plan', 'zhipu-coding-plan', 'zhipuai-coding-plan'].includes(hint)) return 'zai-coding-plan';\n if (['zai', 'z-ai', 'z.ai', 'zai-cn', 'zai-china', 'zhipu', 'glm-cn', 'bigmodel'].includes(hint)) return 'zhipu';\n if (['xai', 'xai-grok'].includes(hint)) return 'xai';\n if (['minimax', 'minimax-openai'].includes(hint)) return 'minimax';\n if (['minimax-anthropic'].includes(hint)) return 'minimax-anthropic';\n if (['other', 'custom', 'local'].includes(hint)) return 'openai-compatible';\n return hint;\n }\n\n const url = baseUrl.toLowerCase();\n if (url.includes('openrouter.ai')) return 'openrouter';\n if (url.includes('api.openai.com')) return 'openai';\n if (url.includes('anthropic.com') || url.includes('api.anthropic.com')) return 'anthropic';\n if (url.includes('generativelanguage.googleapis.com') || url.includes('gemini')) return 'gemini';\n if (url.includes('api.deepseek.com')) return 'deepseek';\n if (url.includes('api.groq.com')) return 'groq';\n if (url.includes('api.mistral.ai')) return 'mistral';\n if (url.includes('api.together.xyz')) return 'together';\n if (url.includes('api.x.ai')) return 'xai';\n if (url.includes('api.minimaxi.com')) return 'minimax';\n if (url.includes('api-ai.gitcode.com')) return 'gitcode';\n if (url.includes('api.z.ai')) return 'zai-coding-plan';\n if (url.includes('open.bigmodel.cn') || url.includes('bigmodel')) return 'zhipu';\n if (url.includes(':11434')) return 'ollama';\n return 'openai-compatible';\n}\n\n/** Get provider-specific headers (mirrors Python get_provider_headers) */\nexport function getProviderHeaders(provider: string): Record<string, string> {\n return PROVIDER_HEADERS[provider] || {};\n}\n\n/** Per-layer enable/disable (matches Python SecurityConfig) */\nexport function isHeuristicEnabled(): boolean {\n return process.env.AGENT_MOSS_DISABLE_HEURISTIC !== '1';\n}\n\n/**\n * Brain 自学习机制是否启用。默认关闭(开发中,避免污染 L1/L2 判定与 L3 prompt),\n * 仅当显式设置 AGENT_MOSS_BRAIN_ENABLED=1 时启用(镜像 Python is_brain_enabled)。\n */\nexport function isBrainEnabled(): boolean {\n return process.env.AGENT_MOSS_BRAIN_ENABLED === '1';\n}\n\nexport function isLogicRulesEnabled(): boolean {\n return process.env.AGENT_MOSS_DISABLE_LOGIC_RULES !== '1';\n}\n","/**\n * 内联脚本静态语义判定 — 区分敏感路径是\"被当作文本\"还是\"被当作读写目标\"。\n *\n * 对内联脚本(python -c / perl -e / ruby -e / php -r / node -e / lua / echo / printf)\n * 里出现非凭据敏感路径的场景,做静态判定(不依赖 LLM):\n *\n * 1. 写入+执行绕过链 → Deny(echo \"cat /etc/shadow\" > x.sh && bash x.sh / printf | bash)\n * 2. 重定向写入敏感路径 → Deny(echo '...' >> /etc/hosts)\n * 3. 含读写调用词 + 敏感路径共存 → Deny(open('/etc/shadow')、os.system('cat /etc/shadow'))\n * 注意:仅对 python -c 等真正的内联脚本代码做读写调用词检测;\n * echo/printf 的字符串参数是自然语言文本,跳过此检测(不可能触发真实读写)。\n * 4. 否则(敏感路径在代码里但无读写调用词,如 print('/etc/shadow')) → Allow\n * 5. 目录遍历 + 文件读写组合 → Deny(os.listdir + open() 动态发现并读写文件,绕过静态路径检测)\n * 注意:仅对 python -c 等真正的内联脚本代码做此检测。\n * 6. 否则(无目录遍历读写组合) → Allow\n *\n * 凭据文件不进此判定(coordinator 层 isCredential 直接 Deny)。\n */\n\nexport interface InlineAnalysisResult {\n /** 是否命中本判定器可处理的内联脚本场景;false 时回退原逻辑 */\n actionable: boolean;\n allowed: boolean;\n reason: string;\n riskLevel: 'low' | 'medium' | 'high' | 'critical';\n riskType: string;\n}\n\n// 内联脚本解释器 + 代码标志:python -c / perl -e / ruby -e / php -r / node -e / lua -e\n// 捕获 -c/-e/-r 后的代码内容(双引号组 1 / 单引号组 2,支持转义)\nconst INLINE_CODE_RE = /(?:python|python3|perl|perl5|ruby|jruby|mruby|node|php|lua)\\s+(?:-[a-zA-Z]*[cera][a-zA-Z]*\\s+)\"([^\"\\\\]*(?:\\\\.[^\"\\\\]*)*)\"|'([^'\\\\]*(?:\\\\.[^'\\\\]*)*)'/gi;\n\n// echo / printf 的字符串参数(双引号组 1 / 单引号组 2)\nconst ECHO_STRING_RE = /\\b(?:echo|printf)\\s+\"([^\"\\\\]*(?:\\\\.[^\"\\\\]*)*)\"|\\b(?:echo|printf)\\s+'([^'\\\\]*(?:\\\\.[^'\\\\]*)*)'/gi;\n\n// echo / printf 命令本身(用于 isLiteralTextCommand 门控)\nconst ECHO_CMD_RE = /(?:^|\\s|;|&&|\\|\\|)(?:echo|printf)\\s/gi;\n\n/** 判断命令是否为 echo/printf 等纯文本输出命令(敏感路径可能作为字符串字面量出现)。\n\n echo/printf 含真实文件重定向(> /path,非 /dev/null 丢弃、非 >& fd)时返回 false——\n 重定向目标是真实写文件,路径不是字面量,不当文本命令(否则 echo x > '~/.bashrc'\n 被当文本命令 → inline_analyzer 把引号内路径当字面量 → 漏报敏感路径写)。 */\nexport function isLiteralTextCommand(command: string): boolean {\n ECHO_CMD_RE.lastIndex = 0;\n if (!ECHO_CMD_RE.test(command)) return false;\n // 含真实文件重定向 → 不是纯文本输出\n if (command.includes('>')) {\n let d = command.replace(/<=>|>=|<=|<>|=>/g, ' ');\n d = d.replace(/(?:2|&|1)?\\s*>\\s*\\/dev\\/null\\b/g, '');\n // 摘引号重定向目标(去引号保留路径,支持 / 或 ~ 开头)\n d = d.replace(new RegExp(\">{1,2}\\\\s*(['\\\"])([~./][^'\\\"]+)\\\\1\", \"g\"), (_m, _q, p) => '>' + p);\n d = d.replace(/'[^']*'|\"[^\"]*\"/g, '');\n if (/>{1,2}\\s*(?!&)\\S/.test(d)) {\n return false;\n }\n }\n return true;\n}\n\n// 读写调用词:仅用于 python -c 等真正的内联脚本代码(不对 echo/printf 的字符串生效)。\n// 出现这些词 + 敏感路径共存 → 判为真实读写。\n//\n// 全部采用组合/函数调用形态,避免自然语言误触发:\n// - 函数调用形态:open(, read(, write(, system(, exec(, eval( 等(后跟 '(')\n// - 组合关键词:os.system, import os, shell=True 等(自带足够区分度)\n// - 不再包含裸短词(open, read, system, exec 等),因 \\b 无法区分编程调用与自然语言\nconst READ_WRITE_KEYWORDS = [\n // 函数调用形态(关键词后跟 '(')\n 'open(', 'read(', 'write(', 'fopen(', 'system(', 'exec(', 'eval(',\n 'popen(', 'load(', 'dump(',\n // 文件读写(组合形态)\n 'readline', 'readlines', 'writelines', 'getpass',\n 'pickle.load', 'yaml.load', 'json.load', 'json.read', 'configparser',\n 'fread', 'fwrite', 'fgets',\n // 子进程执行(组合形态)\n 'os.system', 'os.popen', 'subprocess', 'os.exec', 'os.spawn',\n 'import os', 'import subprocess',\n 'shell=true', 'check_output', 'check_call', 'run(',\n // 绕过变体检测\n 'getattr(', '__builtins__', 'globals(', 'locals(',\n // PHP\n 'file_get_contents', 'file_put_contents', 'passthru', 'shell_exec', 'proc_open',\n // Perl-Ruby\n '<stdin>', 'open my',\n];\n\n// 写入+执行绕过链\nconst WRITE_EXEC_CHAIN_PATTERNS: RegExp[] = [\n // echo/cat/printf \"...\" > file && bash/sh/python file\n /(?:echo|cat|printf)\\b.*?>\\s*\\S+.*(?:&&|;|\\|)\\s*(?:bash|sh|zsh|python\\d?|perl|ruby|node|php)\\s/gis,\n // ... | bash / | sh / | python(管道喂解释器执行)\n /\\|\\s*(?:bash|sh|zsh|python\\d?|perl|ruby|node|php)\\b/gi,\n // eval \"$(cat ...)\" / eval \"$(echo ...)\"\n /eval\\s+\"\\$\\(/gi,\n // xargs bash / xargs sh\n /\\|\\s*xargs\\s+(?:bash|sh|zsh)/gi,\n];\n\n// 重定向写入敏感路径:> / >> 后跟敏感路径 = 真实写入(不是字符串字面量)\n// 敏感路径片段(非凭据,凭据已在 coordinator 层直接 Deny 不进此判定)\n// 对齐 Python inline_analyzer._build_redirect_to_sensitive_re(profile):Python 按\n// profile.sensitive_paths 动态编译(其中含 ~/.bashrc)。TS 无 profile 运行时注入,\n// 故在 ROOT/HOME/CREDENTIAL 静态列表基础上,额外补 shell rc 文件名片段,\n// 让 `echo 'x' >> ~/.bashrc`、`echo 'x' >> /storage/Users/currentUser/.bashrc`\n//(鸿蒙 home 形态)都能被识别为真实重定向写入 → Deny,而非落到\"文本字面量\"放行。\n// 注意:shell rc 片段用文件名匹配(不带 ~ 前缀),可命中任意 home 绝对路径下的 rc 文件。\nconst SHELL_RC_FRAGMENTS = [\n '.bashrc', '.zshrc', '.profile', '.bash_profile', '.zprofile',\n];\nconst SENSITIVE_PATH_FRAGMENTS = [\n '/etc/shadow', '/etc/gshadow', '/etc/passwd', '/etc/sudoers', '/etc/hosts',\n '/etc/crontab', '/etc/systemd/', '/etc/ssh/sshd_config', '/boot/', '/proc/sys/',\n '/sys/', '/dev/mem', '/dev/kmsg', '.ssh/id_rsa', '.ssh/id_ed25519',\n '.ssh/authorized_keys',\n ...SHELL_RC_FRAGMENTS,\n];\nconst REDIRECT_TO_SENSITIVE_RE = new RegExp(`>{1,2}\\\\s*(?:\\\\S*/)?(${SENSITIVE_PATH_FRAGMENTS.map((p) => p.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')).join('|')})(?:\\\\s|$)`, 'i');\n\nexport function extractInlineCode(command: string): string {\n const parts: string[] = [];\n let m: RegExpExecArray | null;\n INLINE_CODE_RE.lastIndex = 0;\n while ((m = INLINE_CODE_RE.exec(command)) !== null) {\n const code = m[1] ?? m[2];\n if (code) parts.push(code);\n }\n ECHO_STRING_RE.lastIndex = 0;\n while ((m = ECHO_STRING_RE.exec(command)) !== null) {\n const code = m[1] ?? m[2];\n if (code) parts.push(code);\n }\n return parts.join('\\n');\n}\n\nfunction hasWriteExecChain(command: string): boolean {\n return WRITE_EXEC_CHAIN_PATTERNS.some((p) => {\n p.lastIndex = 0;\n return p.test(command);\n });\n}\n\n// 目录遍历关键词:用于检测通过动态发现文件路径绕过静态路径匹配的行为\n// 仅对 python -c 等真正的内联脚本代码生效\nconst DIR_TRAVERSAL_KEYWORDS = [\n // Python 目录遍历\n 'os.listdir', 'os.walk', 'os.scandir',\n 'glob.glob', 'glob.iglob', 'pathlib.', 'iterdir', 'rglob',\n 'scandir(', 'listdir(',\n];\n\nfunction hasDirTraversal(code: string): boolean {\n /** 检测代码中是否含目录遍历函数(用于识别动态文件发现绕过行为)。 */\n const lower = code.toLowerCase();\n return DIR_TRAVERSAL_KEYWORDS.some((kw) => lower.includes(kw));\n}\n\nexport function hasReadWriteKeyword(code: string): boolean {\n /** 检测代码中是否含读写调用词(仅用于 python -c 等真正的内联脚本代码)。\n * 全部关键词为组合/函数调用形态(open(, os.system, import os 等),\n * 不会在自然语言文本里误触发。 */\n const lower = code.toLowerCase();\n return READ_WRITE_KEYWORDS.some((kw) => lower.includes(kw));\n}\n\n/**\n * 对内联脚本做静态语义判定。\n * 调用前提:coordinator 已确认是 inline 脚本 + 命中非凭据敏感路径。\n */\nexport function analyzeInlineScript(command: string): InlineAnalysisResult {\n const code = extractInlineCode(command);\n if (!code) {\n // 提取不到代码(命令结构不匹配已知 inline 模式)→ 不处理,回退保守\n return { actionable: false, allowed: true, reason: '', riskLevel: 'low', riskType: '' };\n }\n\n // 1. 写入+执行绕过链 → Deny\n if (hasWriteExecChain(command)) {\n return {\n actionable: true,\n allowed: false,\n reason: '内联脚本含写入文件后执行的模式,疑似绕过敏感路径检测',\n riskLevel: 'critical',\n riskType: 'script_execution',\n };\n }\n\n // 1.5 重定向写入敏感路径(echo '...' >> /etc/hosts 等)→ 真实写入 → Deny\n const redirMatch = command.match(REDIRECT_TO_SENSITIVE_RE);\n if (redirMatch) {\n return {\n actionable: true,\n allowed: false,\n reason: `重定向写入敏感路径: ${redirMatch[1]}`,\n riskLevel: 'critical',\n riskType: 'file_access',\n };\n }\n\n // 1.6 目录遍历 + 文件读写组合 → 不自行判定,回退 coordinator 走层3 LLM 分析\n // 检测 os.listdir/glob/pathlib 等目录遍历函数 + open()/write()/read() 等读写调用,\n // 用于识别\"通过动态发现文件路径绕过静态路径匹配\"的行为。\n // 仅对 python -c 等真正的内联脚本代码做此检测(echo/printf 无此能力)。\n // 注意:此处返回 actionable: false,让 coordinator 回退到正常逻辑,\n // 由层2 的 _checkIndirectFileAccess 规则触发层3 LLM 语义判断。\n const isEchoOrPrintf1 = isLiteralTextCommand(command);\n if (!isEchoOrPrintf1 && hasDirTraversal(code) && hasReadWriteKeyword(code)) {\n return { actionable: false, allowed: true, reason: '', riskLevel: 'low', riskType: '' };\n }\n\n // 2. 含读写调用词 → 判为真实读写 → Deny\n // 注意:仅对 python -c 等真正的内联脚本代码做此检测。\n // echo/printf 的字符串参数是自然语言文本,不可能触发真实文件读写;\n // 重定向(>> /etc/hosts)和管道执行(| bash)已在步骤 1/1.5 覆盖。\n const isEchoOrPrintf = isLiteralTextCommand(command);\n if (!isEchoOrPrintf && hasReadWriteKeyword(code)) {\n return {\n actionable: true,\n allowed: false,\n reason: '内联脚本含敏感路径且含文件读写/命令执行调用,判为真实访问',\n riskLevel: 'critical',\n riskType: 'file_access',\n };\n }\n\n // 3. 敏感路径在代码里但无读写调用词 → 文本字面量 → Allow\n return {\n actionable: true,\n allowed: true,\n reason: '敏感路径仅作为文本字面量出现,未伴随读写操作',\n riskLevel: 'low',\n riskType: 'file_access',\n };\n}\n","/**\n * 归一化规则加载器(单一事实源,与 Python rules_loader.py 对齐)。\n *\n * L1/L2/L3 的正则规则数据统一存放在 agent_moss/rules/ 下:\n * - l1_rules.json: 危险命令 / 注入关键词 / 敏感路径\n * - l2_rules.json: 意图偏离 / 密码修改授权 / 用户删除授权\n * - l3_rules.json: skill 关键词映射\n *\n * Python 与 TS 两端都从这些 JSON 读取,消除双端规则漂移。\n *\n * 路径解析(健壮多候选):\n * 本模块可能被 tsup 内联进不同入口 bundle,`__dirname` 随打包产物而异:\n * - dist/cli.js / dist/server.js → __dirname = dist/\n * - dist/engine/coordinator.js → __dirname = dist/engine/\n * - dev (vitest 源文件) ts/src/infra/ → __dirname = ts/src/infra/\n * 因此枚举所有可能的 rules 目录候选,命中即用(首个存在者)。\n */\nimport { readFileSync, existsSync } from 'fs';\nimport { resolve, dirname } from 'path';\nimport { fileURLToPath } from 'url';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n// 候选 rules 目录(覆盖 dist / dist/engine / dev 源 三种 __dirname 形态)。\n// 从 __dirname 出发尝试若干相对深度,命中 agent_moss/rules 或 dist/rules 即用。\nconst RULES_DIR_CANDS = (() => {\n const cands: string[] = [\n // dist: __dirname=dist/ → dist/rules;__dirname=dist/engine/ → dist/engine/../rules=dist/rules\n resolve(__dirname, '../rules'),\n resolve(__dirname, 'rules'),\n // dev src: __dirname=ts/src/infra/ → ts/src/infra/../../../agent_moss/rules = 仓库根 agent_moss/rules\n resolve(__dirname, '../../../agent_moss/rules'),\n // dist 但 __dirname 指向 dist/engine 再往上两级的仓库根 agent_moss/rules\n resolve(__dirname, '../../../../agent_moss/rules'),\n // 相对当前工作目录的仓库根(兜底,兼容以仓库根为 cwd 运行)\n resolve(process.cwd(), 'agent_moss/rules'),\n ];\n return cands.filter((c) => existsSync(c));\n})();\n\nfunction findRulesFile(name: string): string | null {\n for (const dir of RULES_DIR_CANDS) {\n const p = resolve(dir, name);\n if (existsSync(p)) return p;\n }\n return null;\n}\n\nfunction loadJson(name: string): Record<string, any> {\n const p = findRulesFile(name);\n if (!p) return {};\n try {\n return JSON.parse(readFileSync(p, 'utf-8')) || {};\n } catch {\n return {};\n }\n}\n\n/** L1 规则数据:{dangerous_commands, injection_detection, sensitive_path_access} */\nexport function loadL1(): Record<string, any> {\n return loadJson('l1_rules.json');\n}\n\n/** L2 规则数据:{intent_consistency, password_modify_consent, user_deletion_consent} */\nexport function loadL2(): Record<string, any> {\n return loadJson('l2_rules.json');\n}\n\n/** L3 规则数据:{category: {skill_id: [keywords]}} */\nexport function loadL3(): Record<string, any> {\n return loadJson('l3_rules.json');\n}","import * as fs from 'fs';\nimport { SecurityJudgment } from './types';\nimport type { AnalysisInput } from './coordinator';\nimport { extractInlineCode } from './inline-analyzer.js';\nimport { getAgentExtensions } from '../agents';\nimport type { AgentExtensions } from '../agents';\nimport { loadL1, loadL2 } from '../infra/rules-loader';\n\n/**\n * Layer 2: Logic rule detection.\n * Checks behavioral patterns: read-before-write, intent consistency,\n * sensitive path access, privilege escalation, and lateral movement.\n * Runs in < 1ms, no LLM cost.\n */\n\n// Sensitive paths with per-path risk levels (unified Python + TS)\n\ninterface SensitivePathEntry { path: string; riskLevel: string; desc: string; credential?: boolean; }\n\nfunction _loadSensitivePathScope(scope: 'root' | 'home' | 'credential'): SensitivePathEntry[] {\n // 归一化自 agent_moss/rules/l1_rules.json(单一事实源,与 Python 共用)。\n // 每条含 scope(root/home/credential) + deny_mode;deny_mode=deny_both 视为 credential。\n const sps = (loadL1().sensitive_path_access || []) as any[];\n return sps\n .filter((sp) => sp.scope === scope)\n .map((sp) => ({\n path: sp.path,\n riskLevel: sp.risk_level,\n desc: sp.desc,\n credential: sp.deny_mode === 'deny_both' ? true : undefined,\n }));\n}\n\nexport const ROOT_SENSITIVE_PATHS: { path: string; riskLevel: string; desc: string; credential?: boolean }[] = _loadSensitivePathScope('root');\n\nexport const HOME_SENSITIVE_PATHS: { path: string; riskLevel: string; desc: string; credential?: boolean }[] = _loadSensitivePathScope('home');\n\n// Credential files: intercept on both read and write (reading credentials is equally dangerous)\n// credential=true 使 seed 推导出 deny_mode=deny_both,与 Python 一致(对齐单一事实源)。\nexport const CREDENTIAL_PATHS: { path: string; riskLevel: string; desc: string; credential?: boolean }[] = _loadSensitivePathScope('credential').map(({ path, riskLevel, desc }) => ({ path, riskLevel, desc, credential: true }));\n\n// 只读工具精确名(豁免 read_before_write;与 coordinator READONLY_SENSITIVE_TOOLS/FULLY_SAFE_TOOLS 对齐)。\n// 注意:不含 filemgr-writefile/filemgr-editfile/filemgr-searchreplace(这些是真写)。\nconst NON_WRITE_TOOLS = new Set([\n 'ask_user_question', 'glob', 'grep', 'list_dir', 'count_text_length', 'search',\n // filemgr 只读三件套(globfiles 在 coordinator FULLY_SAFE_TOOLS 提前放行,此处兜底防御非 coordinator 入口)\n 'filemgr-globfiles', 'filemgr-readfile', 'filemgr-grepfiles',\n // 通用只读工具名\n 'read', 'read_file', 'file_read', 'head', 'tail', 'cat',\n]);\n\n// 非 bash/terminal 类工具前缀豁免 read_before_write。\n// 仅保留通用基线前缀(与 EXCLUDED_PREFIXES / SENSITIVE_EXCLUDED_PREFIXES 一致):\n// memory-/skill-manager-/mailbox-/app- 是数据/编排/通信工具,read_before_write(写文件前先读)对其\n// 无意义,且工具名含 remove/update(memory-removeMemory/memory-updateUserPortrait)会命中\n// WRITE_KEYWORDS 子串 → 误判为写。L2 层独立豁免,不再仅依赖 coordinator opendesk 白名单。\n// 不含 skill-(任意能力,coordinator 故意保留 L3)、todomgr-/planning-(opendesk 专属命名空间,\n// 经 opendesk/rules.json builtin_safe_action_types 在 coordinator 层豁免 L2+L3,不到 L2)。\n// mailbox-sendEmail/replyEmail 的外传风险由 L3 LLM 管,不归 L2 read_before_write。\nconst NON_WRITE_TOOL_PREFIXES = ['memory-', 'skill-manager-', 'mailbox-', 'app-'];\n\n// Read-only commands that use > for output redirection (not write intent)\nconst READ_ONLY_REDIR_CMDS = new Set(['cat', 'head', 'tail', 'less', 'more', 'grep', 'find', 'awk', 'sed', 'sort', 'uniq', 'wc', 'cut', 'strings', 'od', 'xxd', 'hexdump']);\n\n// Write keywords for read-before-write detection (also used by L1 SensitivePathChecker)\nexport const WRITE_KEYWORDS = ['write', '写入', 'save', '保存', 'modify', '修改', 'update', '更新', 'delete', '删除', 'remove', '移除', 'create', '创建', 'append', '追加', 'truncate', '截断', 'overwrite', '覆盖', 'replace', '替换', 'edit'];\n\n// 写/删命令词边界正则(对齐 Python _WRITE_COMMAND_RES)。\n// 子串匹配无法可靠识别 rm/cp/dd(\"rm\" 误命中 arm/form),故用词边界。\nexport const WRITE_COMMAND_RES: RegExp[] = [\n /\\brm\\b/, /\\bunlink\\b/, /\\brmdir\\b/, /\\bshred\\b/, /\\bcp\\b/, /\\bmv\\b/,\n /\\binstall\\b/, /\\btee\\b/, /\\bdd\\b/, /\\bmkfs\\b/,\n /\\b(fdisk|parted|cfdisk|sfdisk)\\b/, /\\bchmod\\b/, /\\bchown\\b/, /\\btruncate\\b/,\n];\n\n// 只读命令集合(重定向写判定用,对齐 Python READ_ONLY_COMMANDS)。\n// 这些命令带 > 也是输出重定向非写文件意图(如 cat file > /dev/null)。\nexport const READ_ONLY_COMMANDS = new Set([\n 'cat', 'head', 'tail', 'less', 'more', 'grep', 'find', 'awk', 'sed',\n 'sort', 'uniq', 'wc', 'cut', 'strings', 'od', 'xxd', 'hexdump', 'tr',\n 'file', 'stat', 'du', 'df', 'ls', 'dir', 'tree', 'nl', 'tac', 'rev',\n // NEW-FP-I: echo/printf 是文本输出命令,参数是字面量非写目标。加入此集让\n // read_before_write 的 echo 段走只读命令分支(只提取重定向目标,不提取参数路径),\n // 避免 echo \"cat /etc/shadow\" > /tmp/x.sh 的引号内 /etc/shadow 被当写目标误报。\n // echo \"x\" > /tmp/x.sh 的重定向目标 /tmp/x.sh 仍被提取(真实写不漏报)。\n 'echo', 'printf',\n 'lsblk', 'blockdev', 'smartctl', 'udevadm', 'dmidecode', 'lscpu', 'lspci',\n 'lsusb', 'lsmem', 'lsns', 'lsof', 'hwinfo', 'inxi', 'fdisk', 'parted',\n 'dmesg', 'journalctl', 'systemctl', 'hostnamectl', 'localectl', 'timedatectl',\n 'ps', 'top', 'free', 'vmstat', 'iostat', 'mpstat', 'pidof', 'pgrep',\n 'ip', 'ifconfig', 'route', 'ss', 'netstat', 'arp', 'ethtool', 'nmcli',\n 'uname', 'arch', 'nproc', 'getconf', 'getent', 'id', 'whoami', 'who',\n 'w', 'last', 'uptime', 'lsmod', 'modinfo', 'sysctl',\n]);\n\n// 重定向到 /dev/null 的丢弃写法(对齐 Python _DEVNULL_REDIRECT_RE)。\n// 注意带 g 标志:一条诊断命令常含多个 2>/dev/null(cd ... && ls ... 2>/dev/null; find ... 2>/dev/null),\n// JS String.replace 无 g 只替换首个,残留的 2>/dev/null 仍带 `>` 会触发重定向写误判(FP)。\n// Python 端用 re.sub 全局替换,此处对齐之。\nconst DEVNULL_REDIRECT_RE = /(?:2|&|1)?\\s*>\\s*\\/dev\\/null\\b/g;\n\n/**\n * 综合判定是否为写/删操作(对齐 Python _is_write_operation,单一事实源)。\n * 供 L2 read_before_write 与 L1 sensitive_path 共用,避免手写复刻漂移。\n *\n * 1. WRITE_KEYWORDS 子串匹配 actionType+actionDetail(与 Python 一致,不加词边界以保持双端同步)\n * 2. WRITE_COMMAND_RES 词边界正则(rm/cp/dd/tee/truncate/...)\n * 3. sed -i 原地编辑\n * 4. 重定向写入:剥 devnull 后有 `>` 且首词非只读命令\n */\nexport function isWriteOperation(actionType: string, actionDetail: string, writeKeywords: string[] = WRITE_KEYWORDS): boolean {\n // 1. 关键词子串匹配(actionType 或 actionDetail)\n if (writeKeywords.some(kw => actionType.includes(kw) || actionDetail.includes(kw))) return true;\n // 2. 写/删命令词边界\n if (WRITE_COMMAND_RES.some(rx => rx.test(actionDetail))) return true;\n // 3. sed -i 原地编辑\n if (/\\bsed\\s+-[a-zA-Z]*i/i.test(actionDetail)) return true;\n // 3b. wget/curl + -O/-o/--output 下载写入(无 > 重定向,漏判 → 漏报,且可写 shell 后门绕过敏感路径)\n // 3c. rsync 同步写 dest(非 --list-only/--dry-run/-n 只读模式)\n // 两类都按命令段判定首词(排除 echo/printf 字面量)\n for (const seg of actionDetail.split(/&&|\\|\\||;|\\n/)) {\n const trimmed = seg.trim();\n if (!trimmed) continue;\n const parts = trimmed.split(/\\s+/);\n const fw = parts[0]?.toLowerCase() || '';\n if (fw === 'wget' || fw === 'curl') {\n // NEW-FP-C: -O- / -o- / --output-document=- / --output=- 是 stdout(值为 -),不算文件写\n const isStdout = /\\s(?:-O|-o)-(?:\\s|$)/.test(trimmed) ||\n /\\s--output-document=-(?:\\s|$)/i.test(trimmed) ||\n /\\s--output=-(?:\\s|$)/i.test(trimmed);\n if (isStdout) continue;\n // NEW-FP-N: -o /dev/null / --output=/dev/null 是丢弃响应体只测状态码,非真实写文件\n const isDevnull = /\\s(?:-O|--output-document|--output)\\s*\\/dev\\/null(?:\\s|$)/i.test(trimmed) ||\n /\\s(?:-O|--output-document|--output)=[/]?dev\\/null(?:\\s|$)/i.test(trimmed);\n if (isDevnull) continue;\n if (/\\s(?:-O|--output-document|--output)(?:=|\\s|$)/i.test(trimmed) || /\\s-O\\S/.test(trimmed)) {\n return true;\n }\n }\n if (fw === 'rsync' && !/--list-only|--dry-run/i.test(trimmed) && !/(^|[^a-zA-Z])-n([^a-zA-Z]|$)/.test(trimmed)) {\n return true;\n }\n }\n // 4. 重定向写入:先排除 /dev/null 丢弃和比较运算符,再看是否还有真实文件重定向。\n // NEW-FN-D 修复:不再用「整条命令首词是否只读」判断——`cat in > out` 里 cat 是\n // 只读命令但其重定向目标 out 是真实写文件(覆写/追加),应判写。只读命令的「安全\n // 重定向」只指 `> /dev/null`(丢弃输出,已剥)。改为只读命令带真实文件重定向也算写。\n // fd 重定向(>&N / N>&M / 2>&1)不是写文件,用「> 后紧跟 &」排除。\n // grep/awk 搜索模式里的 > 字面量(如 grep \"a>b\" file)不是重定向——剥引号内容后再判。\n if (actionDetail.includes('>')) {\n // 先剥掉比较运算符(>=, <=, <>, <=>, =>),避免 Python 代码里的 `r.get('seq',0) >= 28`\n // 被当成重定向写(`>=` 含 `>`)。这些是表达式而非重定向,不应计入写判定。\n const detailWithoutCompare = actionDetail.replace(/<=>|>=|<=|<>|=>/g, ' ');\n const detailWithoutDevnull = detailWithoutCompare.replace(DEVNULL_REDIRECT_RE, '');\n // 先摘「> '引号路径'」为裸路径(支持引号包裹的重定向目标,如 echo x > '/tmp/file'),\n // 否则下一步剥引号内容会把重定向目标路径也删掉 → 漏判写(漏报)。\n const detailUnquotedRedirect = detailWithoutDevnull.replace(\n />{1,2}\\s*(['\"])([~./][^'\"]+)\\1/g,\n (_m, _q, p) => '>' + p,\n );\n // 剥掉剩余引号内内容(grep/awk 搜索模式、python -c 代码里的 > 字面量),只看引号外\n // 是否还有真实文件重定向。\n const detailWithoutQuotes = detailUnquotedRedirect.replace(/'[^']*'|\"[^\"]*\"/g, '');\n // 真实文件重定向:> 或 >> 后紧跟非空白、非 & 的文件目标字符。\n // `>{1,2}\\s*(?!&)\\S` 匹配 echo x > /file、cat in >file、sort in >> /file;\n // 排除 ls 2>&1、echo >&2(>& 紧邻或 > 后 & 是 fd 合并,非写文件)。\n if (/>{1,2}\\s*(?!&)\\S/.test(detailWithoutQuotes)) {\n return true;\n }\n }\n return false;\n}\n\n// Read keywords for read-before-write detection\nconst READ_KEYWORDS = ['read', '读取', 'cat', 'head', 'tail', 'less', 'more', 'view', '查看', 'open', '打开', 'load', '加载', 'grep', 'search', '搜索', 'find', '查找'];\n\n// Create-action exception keywords\nconst CREATE_KEYWORDS = ['创建', '新建', 'create', 'new file', 'touch'];\n\n// Non-interactive password modification patterns\nexport const PASSWORD_MODIFY_PATTERNS: RegExp[] = (() => {\n // 归一化自 agent_moss/rules/l2_rules.json(单一事实源,与 Python 共用)。\n const pats = (loadL2().password_modify_consent || []) as any[];\n return pats.map((p) => new RegExp(p.pattern, 'i'));\n})();\n\n// Non-interactive user/group deletion patterns\nexport const USER_DELETION_PATTERNS: RegExp[] = (() => {\n // 归一化自 agent_moss/rules/l2_rules.json(单一事实源,与 Python 共用)。\n const pats = (loadL2().user_deletion_consent || []) as any[];\n return pats.map((p) => new RegExp(p.pattern, 'i'));\n})();\n\n// Intent deviation patterns (synced with Python linux.py IntentDeviationPattern)\nexport const INTENT_DEVIATION_PATTERNS: { intentKeywords: string[]; dangerousActions: string[]; reason: string }[] = (() => {\n // 归一化自 agent_moss/rules/l2_rules.json(单一事实源,与 Python 共用)。\n const pats = (loadL2().intent_consistency || []) as any[];\n return pats.map((p) => ({\n intentKeywords: p.intent_keywords,\n dangerousActions: p.dangerous_actions,\n reason: p.reason,\n }));\n})();\n\n/**\n * 匹配危险动作词。中文用子串(无词边界歧义),英文用词边界正则。\n *\n * 裸 includes() 会在 actionDetail 参数/搜索模式里误报:\n * - `git log --format=` 含 \"format\" → 误判\"格式化磁盘\"\n * - grep 搜索模式 `NON_WRITE|non_write` 含 \"write\" → 误判\"修改\"\n * - `pip install --update` 含 \"update\" → 误判\"修改\"\n * 英文词用 `(?<!-)\\bWORD\\b`:\n * - 前面不是 `-`(排除 --format / --update / -delete 等参数形态)\n * - 词边界(排除 NON_WRITE 里的 write、arm 里的 rm 等)\n */\nfunction matchDangerousAction(actionDetail: string, action: string): boolean {\n // 中文词(含非 ASCII)走子串匹配\n if (/[^\\x00-\\x7f]/.test(action)) {\n return actionDetail.includes(action);\n }\n // 英文词走词边界 + 排除参数前缀\n const escaped = action.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const re = new RegExp(`(?<![-\\\\w])${escaped}\\\\b`, 'i');\n return re.test(actionDetail);\n}\n\n/** 按时间序收集本次会话的全部意图文本(含历史 prompt,去空、去重、lower 化)。\n * 兼容 dict {text, actions} 与纯文本 string 两种元素(后者为 AgentGate v3 旧格式)。 */\nfunction collectIntentTexts(\n promptSession: string,\n promptHistory?: AnalysisInput['promptHistory'],\n): string[] {\n const texts: string[] = [];\n if (promptHistory) {\n for (const turn of promptHistory) {\n if (typeof turn === 'string') {\n const t = turn.trim();\n if (t) texts.push(t.toLowerCase());\n continue;\n }\n const t = (turn?.text || '').trim();\n if (t) texts.push(t.toLowerCase());\n }\n }\n if (promptSession && promptSession.trim()) {\n texts.push(promptSession.toLowerCase());\n }\n // 去重保序\n const seen = new Set<string>();\n const deduped: string[] = [];\n for (const t of texts) {\n if (!seen.has(t)) {\n seen.add(t);\n deduped.push(t);\n }\n }\n return deduped;\n}\n\nexport function runLogicCheck(input: AnalysisInput): SecurityJudgment | null {\n const { actionHistory, aNext, cwd } = input;\n const actionDetail = aNext.actionDetail.toLowerCase();\n const actionType = aNext.actionType.toLowerCase();\n const resolvedCwd = cwd || '/';\n\n // 非 shell/文件类操作跳过意图一致性和敏感路径检查\n const EXCLUDED_PREFIXES = ['memory-', 'skill-', 'skill-manager-', 'mailbox-', 'app-'];\n const isExcludedType = EXCLUDED_PREFIXES.some(p => actionType.startsWith(p));\n\n // Rule 1: Read-before-write principle\n const rbwResult = checkReadBeforeWrite(actionType, actionDetail, actionHistory, input.reason, resolvedCwd);\n if (rbwResult) return rbwResult;\n\n // Rule 2: Intent deviation detection\n // 只对 shell/文件类操作执行意图一致性检查\n if (!isExcludedType) {\n // 内联脚本命令(python -c / perl -e 等)跳过 intent 的 dangerousAction 词匹配。\n // 内联脚本代码内容里的英文词(print(delete this) 的 delete)是字符串字面量,\n // 不是真实动作;词边界 (?<![-\\w])delete\\b 能挡 print 里的 rm(短词),但挡不住\n // delete(长词独立词)→ intent 误报(Bug4)。内联脚本的「危险」由 L1.2\n // inline-analyzer 专门管(区分字面量 vs 真实调用),intent 不重复管。\n if (!INLINE_SCRIPT_RE.test(actionDetail)) {\n // 收集本次会话的全部意图文本(含历史 prompt,按时间序去重)。\n // 避免多轮会话里 \"continue/继续\" 等最近输入覆盖掉最初的读取/搜索意图而漏报。\n const intentTexts = collectIntentTexts(input.promptSession, input.promptHistory);\n for (const pattern of INTENT_DEVIATION_PATTERNS) {\n // 任一历史 prompt 命中意图词即视为\"存在该意图\"(防\"继续\"覆盖漏报)\n const intentMatched = intentTexts.some(text =>\n pattern.intentKeywords.some(kw => text.includes(kw))\n );\n const dangerousMatched = pattern.dangerousActions.some(kw => matchDangerousAction(actionDetail, kw));\n if (intentMatched && dangerousMatched) {\n return {\n allowed: false,\n reason: pattern.reason,\n riskLevel: 'high',\n riskType: 'intent_deviation',\n confidence: 85,\n source: 'logic_rule',\n violatedLayers: ['2'],\n };\n }\n }\n }\n }\n\n // 注:敏感路径访问检测 (checkSensitivePath) / 危险操作模式检测 / 横向移动检测\n // 已按\"L1 只看这一步\"原则搬至 heuristic.ts 的 runHeuristicCheck。\n // 本函数仅保留需要 action_history / prompt_session / cwd 的 L2 规则。\n\n // Rule 4.5: Indirect file access — inline script with dir traversal + file read/write\n // Uses cwd to list actual files and check against sensitive paths directly\n const indirectResult = checkIndirectFileAccess(actionType, actionDetail, resolvedCwd);\n if (indirectResult) return indirectResult;\n\n // Rule 5: Privilege escalation detection\n // 判据:sudo 后跟的命令本身是包管理/服务管理(apt/systemctl/yum/...)→ 合法运维\n // 直接放行,不要求历史先有一次 admin(新会话首次 sudo apt install 是合法高频运维)。\n // sudo + 非运维命令才查历史有无 admin 上下文;历史也无则视为异常提权。\n // 注意:剥掉 sudo 前缀再匹配 admin 关键词,否则 actionDetail 必含 sudo 导致永远放行。\n // 注:admin 关键词曾尝试词边界 \\b,但 grep apt / pip apt 里 apt 是独立词,\\bapt\\b 仍命中,\n // 词边界无法区分\"命令位置\"vs\"参数位置\",故暂保留子串匹配。提权漏检(grep apt 误当 admin\n // 上下文放行 sudo cat)是已知问题,待用命令位置匹配专项处理。\n // 内联脚本命令(python -c / perl -e 等)跳过提权词匹配:代码内容里的词\n // (print(\"chmod u+s\") 的 chmod u+s)是字符串字面量,不是真实动作,提权子串匹配\n // 会误报(FP-2 变体)。内联脚本的「危险」由 inline-analyzer 管,提权检测不重复管。\n if (INLINE_SCRIPT_RE.test(actionDetail)) {\n // fall through to next rule, skip privilege escalation\n // NEW-FP-J: 提权关键词改为「命令位置」判定。旧逻辑对整个 actionDetail 做子串匹配,\n // grep -rn \"sudo\" file、awk '/sudo/'、echo \"sudo make install\" 里参数/搜索模式/字面量\n // 位置的 sudo 被误判为真实提权。仅当段首词是提权命令(sudo/su/setuid,或 chmod+u+s)\n // 才认为存在提权意图。\n } else if (containsPrivilegeEscalation(actionDetail)) {\n const detailAfterSudo = actionDetail.replace(/(^|\\|\\||&&|\\s)sudo\\s+/g, ' ');\n const isAdminCmd = ['apt', 'systemctl', 'yum', 'dnf', 'pacman', 'zypper', 'apk'].some(kw => detailAfterSudo.includes(kw));\n if (!isAdminCmd) {\n const adminContext = actionHistory.some(h =>\n h.actionDetail.includes('sudo') || h.actionDetail.includes('apt') || h.actionDetail.includes('systemctl') ||\n h.actionDetail.includes('yum') || h.actionDetail.includes('dnf') || h.actionDetail.includes('pacman') ||\n h.actionDetail.includes('zypper') || h.actionDetail.includes('apk')\n );\n if (!adminContext) {\n return {\n allowed: false,\n reason: '检测到提权操作,未发现合法管理上下文',\n riskLevel: 'high',\n riskType: 'privilege_escalation',\n confidence: 85,\n source: 'logic_rule',\n violatedLayers: ['2'],\n };\n }\n }\n }\n\n // 注:横向移动检测已搬至 heuristic.ts (runHeuristicCheck)。\n // Rule 6: Non-interactive password modification consent check\n const pwdResult = checkPasswordConsent(actionType, actionDetail, actionHistory);\n if (pwdResult) return pwdResult;\n\n // Rule 7: User/group deletion consent check\n const userDelResult = checkUserDeletionConsent(actionType, actionDetail, actionHistory);\n if (userDelResult) return userDelResult;\n\n return null; // Pass to next layer\n}\n\n// Extract file paths from text (mirrors Python extract_file_paths)\nexport function extractFilePaths(text: string): string[] {\n const paths: string[] = [];\n // Unix paths starting with /(路径前是行首或空白)\n const unixPaths = text.match(/(?:^|\\s)(\\/[^\\s;|&><'\"]+)/g);\n if (unixPaths) paths.push(...unixPaths.map(p => p.trim()));\n // key=value 语法的路径:of=/path、if=/path、--output=/path 等。\n // 现有 unixPaths 正则要求路径前是行首或空白,`of=/tmp/x` 里 / 前是 = 不匹配 →\n // dd of=/path 等漏报(NEW-FN-A)。此正则匹配 `=` 后紧跟的 / 路径。\n // NEW-FP-H: 先剥掉引号内容,避免 echo \"of=/dev/null done\" 这类输出文本里的\n // of=/dev/null 被误当真实写目标。引号内纯路径(dd of=\"/tmp/file\")由下方\n // quotedPaths 独立提取(要求引号内以 / 开头),故剥引号不会漏报真实写。\n const textNoQuotes = text.replace(/'[^']*'|\"[^\"]*\"/g, '');\n const kvPaths = textNoQuotes.match(/(?:=)(\\/[^\\s;|&><'\"]+)/g);\n if (kvPaths) paths.push(...kvPaths.map(p => p.replace(/^=/, '')));\n // Quoted paths\n const quotedPaths = text.match(/[\"']\\/([^\"']+)[\"']/g);\n if (quotedPaths) paths.push(...quotedPaths.map(p => p.replace(/[\"']/g, '')));\n return [...new Set(paths)];\n}\n\nfunction checkReadBeforeWrite(\n actionType: string, actionDetail: string,\n actionHistory: { actionType: string; actionDetail: string }[],\n reason: string, cwd: string\n): SecurityJudgment | null {\n // 豁免非文件类工具前缀(memory-/skill-/mailbox-/todomgr-...)与只读工具,\n // 避免 memory-removeMemory(工具名含 remove)/ filemgr-grepfiles(搜索模式含 write)等误判为写。\n // L2 层独立保护,不再仅依赖 coordinator opendesk 白名单(非 opendesk agent / 单测直调也安全)。\n if (NON_WRITE_TOOL_PREFIXES.some(p => actionType.startsWith(p))) return null;\n if (NON_WRITE_TOOLS.has(actionType)) return null;\n\n // 写判定按工具类型分流:\n // - bash/executebash/terminal-executebash:用 isWriteOperation(对齐 Python\n // _is_write_operation 单一事实源:WRITE_KEYWORDS 子串 + WRITE_COMMAND_RES 词边界\n // rm/cp/dd + sed -i + 重定向(剥 devnull+只读首词保护))。比手写 WRITE_KEYWORDS.includes\n // 多了词边界命令识别,能抓 `rm`/`cp`/`dd` 等;重定向/2>/dev/null 由它统一处理。\n // - 其他工具:只匹配 actionType,不看 actionDetail 内容。\n // 理由:非 shell 工具的写意图只能从工具名体现(filemgr-writefile/write/edit),\n // 参数内容里的中文\"更新\"\"移除\"是业务语义不是文件写语义;\n // grep 搜索模式里的 write/update/remove 子串绝不能算写意图(误报根因)。\n const isBashLike = actionType === 'bash' || actionType === 'executebash' || actionType === 'terminal-executebash';\n const isWrite = isBashLike\n ? isWriteOperation(actionType, actionDetail)\n : WRITE_KEYWORDS.some(kw => actionType.includes(kw));\n\n if (!isWrite) return null;\n\n // 删除/安全命令复合(无真正写命令)不触发 read_before_write。\n // read_before_write 的语义是「写文件前先读内容」,对删除不适用——删除不需要读文件字节,\n // 且删除的元数据预检(rm -rf /etc 等敏感路径、递归)由 L1 命令模式负责(/tmp 清理 L1\n // 判定安全放行,rm -rf /etc L1 拦截)。这是「rm 豁免狭义读内容」而非「跳过 RBW」——\n // 广义元数据预检仍由 L1 完成。判定:命令链无「写命令段」即跳过。写命令段 = 段首词是\n // 写命令(cp/mv/install/tee/dd/truncate/mkfs/sed -i)或含真实重定向写。\n // 注意:chmod/chown 不在此列——改元数据不改文件内容,「写前先读」对其无意义,\n // `chmod 644 /tmp/已有未读` 不应误报。危险 chmod 形态(777/u+s/4755 提权、chmod /敏感路径)\n // 由 L1 专门模式和 sensitive_path 检测负责(WRITE_COMMAND_RES 仍保留 chmod/chown 供敏感路径写判定)。\n // `rm ... && echo done` 豁免,`rm /a && echo x > /b` 仍走 rbw,\n // `chmod 644 /tmp/x`(普通)豁免,`chmod u+s /tmp/x`(提权)由 L1 拦。\n const WRITE_CMDS = new Set(['cp', 'mv', 'install', 'tee', 'dd', 'truncate', 'mkfs', 'fdisk', 'parted']);\n if (isBashLike) {\n const detailNoCompare = actionDetail.replace(/<=>|>=|<=|<>|=>/g, ' ');\n const detailNoDevnull = detailNoCompare.replace(DEVNULL_REDIRECT_RE, '');\n // 先摘「> '引号路径'」为裸路径(支持引号包裹重定向目标),再剥剩余引号内容,\n // 与 isWriteOperation 的重定向判定保持一致(避免两处漂移)。\n const detailUnquotedRedirect = detailNoDevnull.replace(\n />{1,2}\\s*(['\"])([~./][^'\"]+)\\1/g,\n (_m, _q, p) => '>' + p,\n );\n const detailNoQuotes = detailUnquotedRedirect.replace(/'[^']*'|\"[^\"]*\"/g, '');\n const hasRedirectWrite = />{1,2}\\s*(?!&)\\S/.test(detailNoQuotes);\n let hasWriteSeg = hasRedirectWrite;\n if (!hasWriteSeg) {\n for (const seg of actionDetail.split(/&&|\\|\\||;|\\n/)) {\n const trimmed = seg.trim();\n if (!trimmed) continue;\n const fw = trimmed.split(/\\s+/)[0]?.toLowerCase() || '';\n if (WRITE_CMDS.has(fw) || /\\bsed\\s+-[a-zA-Z]*i/i.test(trimmed)) {\n hasWriteSeg = true;\n break;\n }\n // wget/curl + -O/-o/--output 下载写入\n if ((fw === 'wget' || fw === 'curl') &&\n (/\\s(?:-O|--output-document|--output)(?:=|\\s|$)/i.test(trimmed) || /\\s-O\\S/.test(trimmed))) {\n hasWriteSeg = true;\n break;\n }\n // rsync 同步写 dest(非 --list-only/--dry-run/-n 只读模式)\n if (fw === 'rsync' && !/--list-only|--dry-run/i.test(trimmed) && !/(^|[^a-zA-Z])-n([^a-zA-Z]|$)/.test(trimmed)) {\n hasWriteSeg = true;\n break;\n }\n }\n }\n if (!hasWriteSeg) return null;\n }\n\n // Extract target file paths,过滤掉非写目标的参数路径。\n // - cd 是目录切换不是写操作,cd /path 的 /path 不应作为写目标(否则 `cd /敏感 && ls` 误报)。\n // - 读命令(cat/head/tail/grep/find/less/more/wc/cut 等 READ_ONLY_COMMANDS)的文件参数是\n // 读取目标不是写目标,`echo x > /tmp/t1; cat /tmp/t2` 里 t2 是 cat 的读目标却会被\n // extractFilePaths 当写目标提取 → read_before_write 误报(Bug5)。过滤之。\n // - 写命令的源文件参数(cp/mv/install 的首个路径参数)是读取目标不是写目标,\n // `cp /src /dst` 里 /src 是读目标不是写目标 → 误报(NEW-FP-1)。过滤首个路径参数。\n // - dd 的 if=/path 是输入源(读目标),of=/path 才是输出目标(写目标)。\n // `dd if=/dev/zero of=/tmp/x` 里 if= 的 /dev/zero 是读源,必须排除否则误报;\n // of= 的 /tmp/x 是写目标保留(NEW-FN-A:此前 of= 路径根本提取不到 → 漏报)。\n // 逐段法(per-segment):按 &&/||/;/换行 拆命令段,每段独立计算写目标——\n // cd → 无写目标(切目录);\n // 只读命令(cat/grep/sort/head 等)→ 命令参数是读目标,但重定向目标(> /path)\n // 是写目标,需提取(NEW-FN-D:此前整段排除把重定向目标也丢了 → `cat in > out` 漏检 out);\n // cp/mv/install → 排除首个路径(源文件),其余为写目标;\n // dd → 排除 if= 路径(输入源),of= 为写目标;\n // 其他段 → 所有路径为写目标。\n // 关键:排除是 per-segment 局部的,不是全局——否则 `cp /a /b && cp /b /c` 里\n // /b 既是第一段 dest(写目标)又是第二段 source(读目标),全局排除会让第一段\n // 对 /b 的覆写漏检(NEW-FN-B)。逐段计算确保 /b 在第一段仍被作为写目标检查。\n const SOURCE_ARG_CMDS = new Set(['cp', 'mv', 'install', 'rsync']);\n // 重定向写目标正则:> 或 >> 后紧跟文件路径(裸路径或引号包裹,排除 >& fd)。\n // 用 RegExp 构造避免正则字面量里 / 与路径分隔符冲突。\n const REDIRECT_TARGET_RE = new RegExp(\">{1,2}\\\\s*(?!&)(?:'(/[^']+)'|\\\"(/[^\\\\\\\"]+)\\\"|(/[^\\\\s;|&><'\\\\\\\"]+))\");\n const targetPaths: string[] = [];\n for (const seg of actionDetail.split(/&&|\\|\\||;|\\n/)) {\n const trimmed = seg.trim();\n if (!trimmed) continue;\n const firstWord = trimmed.split(/\\s+/)[0]?.toLowerCase() || '';\n if (firstWord === 'cd') {\n continue;\n }\n if (READ_ONLY_COMMANDS.has(firstWord)) {\n // 只读命令:文件参数是读目标,但重定向目标是写目标(NEW-FN-D)。\n // 先摘引号重定向目标(去引号保留路径),再剥剩余引号内容(grep 模式),再提取目标。\n // NEW-FP-M: 先剥 /dev/null 重定向(cat f 2>/dev/null 的 /dev/null 是 stderr 丢弃\n // 非写目标),否则 REDIRECT_TARGET_RE 把 2>/dev/null 提取为写目标误报。\n const segUnquoted = trimmed.replace(new RegExp(\">{1,2}\\\\s*(['\\\"])([~./][^'\\\"]+)\\\\1\", \"g\"), (_m, _q: string, p: string) => '>' + p);\n const segNoDevnull = segUnquoted.replace(DEVNULL_REDIRECT_RE, '');\n const segNoQuotes = segNoDevnull.replace(/'[^']*'|\"[^\"]*\"/g, '');\n const m = segNoQuotes.match(REDIRECT_TARGET_RE);\n if (m) targetPaths.push(m[1] || m[2] || m[3]);\n continue;\n }\n const segPaths = extractFilePaths(trimmed);\n // NEW-FP-N: curl/wget 的 -o /dev/null 是丢弃响应体非真实写文件,排除 /dev/null\n // 路径(extractFilePaths 会把 -o /dev/null 的 /dev/null 提取为写目标 → 误报)。\n const segPathsFiltered = (firstWord === 'wget' || firstWord === 'curl')\n ? segPaths.filter(p => p !== '/dev/null')\n : segPaths;\n if (SOURCE_ARG_CMDS.has(firstWord)) {\n // 排除首个路径(源文件),其余为写目标\n if (segPathsFiltered.length > 1) targetPaths.push(...segPathsFiltered.slice(1));\n } else if (firstWord === 'dd') {\n // dd 的 if= 是输入源(读目标),of= 是输出目标(写目标)。\n // 排除 if= 的路径,保留 of= 的路径作为写目标。\n // NEW-FP-G: of=/dev/null 是丢弃输出非真实写文件(dd if=/dev/zero\n // of=/dev/null 是丢弃测试),与重定向 >/dev/null 同语义,排除避免\n // read_before_write 误报 /dev/null。/dev/zero/urandom 同理(设备文件)。\n const ifSourceMatches = trimmed.match(/\\bif=(\\/[^\\s;|&><'\"]+)/g);\n const ifSourcePaths = new Set(ifSourceMatches ? ifSourceMatches.map((m: string) => m.replace(/^if=/, '')) : []);\n const devNullMatches = trimmed.match(/\\bof=(\\/dev\\/\\S+)/g);\n const devNullTargets = new Set(devNullMatches ? devNullMatches.map((m: string) => m.replace(/^of=/, '')) : []);\n for (const sp of segPaths) {\n if (!ifSourcePaths.has(sp) && !devNullTargets.has(sp)) targetPaths.push(sp);\n }\n } else {\n // 其他段(含重定向写 echo > file、tee、truncate 等):该段所有路径为写目标\n targetPaths.push(...segPathsFiltered);\n }\n }\n // 去重\n const uniqueTargetPaths = [...new Set(targetPaths)];\n if (uniqueTargetPaths.length === 0) return null;\n\n // Collect read paths from history\n const historyReadPaths = new Set<string>();\n for (const action of actionHistory) {\n const histDetail = action.actionDetail.toLowerCase();\n const histType = action.actionType.toLowerCase();\n const isRead = READ_KEYWORDS.some(kw => histType.includes(kw) || histDetail.includes(kw));\n if (isRead) {\n for (const p of extractFilePaths(histDetail)) {\n historyReadPaths.add(p);\n }\n }\n }\n\n // Check if target paths have been read\n const unreadPaths: string[] = [];\n for (const path of uniqueTargetPaths) {\n const hasRead = [...historyReadPaths].some(rp =>\n path === rp || path.startsWith(rp) || rp.startsWith(path)\n );\n if (!hasRead) {\n // 排除新文件创建:文件不存在于磁盘时视为新建,直接放行\n // 同时检查 reason/action_detail 中是否有创建/新建关键词\n let isCreate = !fs.existsSync(path);\n if (!isCreate) {\n isCreate = CREATE_KEYWORDS.some(kw => reason.toLowerCase().includes(kw) || actionDetail.includes(kw));\n }\n if (!isCreate) {\n unreadPaths.push(path);\n }\n }\n }\n\n if (unreadPaths.length > 0) {\n return {\n allowed: false,\n reason: `违反 read_before_write 安全原则:对文件 ${unreadPaths[0]} 执行写入操作,但历史执行序列中未发现对该文件的读取操作`,\n riskLevel: 'high',\n riskType: 'read_before_write',\n confidence: 85,\n source: 'logic_rule',\n violatedLayers: ['2'],\n };\n }\n\n return null;\n}\n\nfunction checkPasswordConsent(\n actionType: string, actionDetail: string,\n actionHistory: { actionType: string; actionDetail: string }[]\n): SecurityJudgment | null {\n if (actionType !== 'bash') return null;\n\n const isPasswordModify = PASSWORD_MODIFY_PATTERNS.some(p => p.test(actionDetail));\n if (!isPasswordModify) return null;\n\n // 检查 action_history 中是否有 ask_user_question 且用户返回了答案\n const hasConsent = actionHistory.some(h =>\n h.actionType.toLowerCase() === 'ask_user_question' && h.actionDetail.trim().length > 0\n );\n if (hasConsent) return null;\n\n return {\n allowed: false,\n reason: '执行非交互式密码修改命令,但历史执行序列中未发现向用户确认密码的 ask_user_question 操作,可能存在未授权的密码修改风险',\n riskLevel: 'high',\n riskType: 'consent_missing',\n confidence: 85,\n source: 'logic_rule',\n violatedLayers: ['2'],\n };\n}\n\nfunction checkUserDeletionConsent(\n actionType: string, actionDetail: string,\n actionHistory: { actionType: string; actionDetail: string }[]\n): SecurityJudgment | null {\n if (actionType !== 'bash') return null;\n\n const isUserDeletion = USER_DELETION_PATTERNS.some(p => p.test(actionDetail));\n if (!isUserDeletion) return null;\n\n // 检查 action_history 中是否有 ask_user_question 且用户确认了\n const hasConsent = actionHistory.some(h =>\n h.actionType.toLowerCase() === 'ask_user_question' && h.actionDetail.trim().length > 0\n );\n if (hasConsent) return null;\n\n return {\n allowed: false,\n reason: '执行删除系统用户命令,但历史执行序列中未发现向用户确认的 ask_user_question 操作,可能存在未授权的用户删除风险',\n riskLevel: 'high',\n riskType: 'consent_missing',\n confidence: 85,\n source: 'logic_rule',\n violatedLayers: ['2'],\n };\n}\n\n// 内联脚本解释器正则\nconst INLINE_SCRIPT_RE = /(?:^|\\s)(?:python|python3|python3\\.\\d+|perl|perl5|ruby|jruby|mruby|node|php|lua)\\s+(?:-[a-zA-Z]*[cer][a-zA-Z]*\\s+)/i;\n\n// NEW-FP-J: 提权关键词「命令位置」判定。仅当段首词是提权命令(sudo/su/setuid,\n// 或 chmod+u+s setuid 位)才认为存在提权意图。引号感知分段:echo \"a; sudo rm\" 的\n// ; 在引号内不分段,整段首词 echo 不触发。grep/awk/echo 首词段的参数是搜索模式/字面量。\nfunction containsPrivilegeEscalation(actionDetail: string): boolean {\n const ad = actionDetail.toLowerCase();\n for (const seg of ad.split(/&&|\\|\\||;|\\n/)) {\n const trimmed = seg.trim();\n if (!trimmed) continue;\n const parts = trimmed.split(/\\s+/);\n const fw = parts[0]?.toLowerCase() || '';\n if (fw === 'sudo' || fw === 'su' || fw === 'setuid') return true;\n if (fw === 'chmod' && /\\bu\\s*\\+\\s*s\\b/.test(trimmed)) return true;\n }\n return false;\n}\n\n// 目录遍历关键词(用唯一名称避免与 inline-analyzer.ts 的 DIR_TRAVERSAL_KEYWORDS 冲突)\nconst DIR_TRAVERSAL_KW = [\n 'os.listdir', 'os.walk', 'os.scandir',\n 'glob.glob', 'glob.iglob', 'pathlib.', 'iterdir', 'rglob',\n 'scandir(', 'listdir(',\n];\n\n/**\n * Rule 4.5: Indirect file access detection.\n * Detects inline scripts that use directory traversal (os.listdir/glob/pathlib)\n * combined with file read/write operations to dynamically discover and access\n * sensitive files, bypassing static path matching.\n *\n * Returns medium risk so the coordinator forwards to Layer 3 LLM analysis\n * instead of denying immediately.\n */\nfunction checkIndirectFileAccess(actionType: string, actionDetail: string, cwd: string): SecurityJudgment | null {\n // Only check bash tool inline scripts\n if (actionType !== 'bash' && actionType !== 'executebash' && actionType !== 'terminal-executebash') {\n return null;\n }\n\n // Check if it's an inline script command\n INLINE_SCRIPT_RE.lastIndex = 0;\n if (!INLINE_SCRIPT_RE.test(actionDetail)) {\n return null;\n }\n\n // Check for directory traversal keywords\n const lowerDetail = actionDetail.toLowerCase();\n const hasTraversal = DIR_TRAVERSAL_KW.some(kw => lowerDetail.includes(kw));\n if (!hasTraversal) {\n return null;\n }\n\n // Extract code and check for read/write keywords, distinguishing read/write/exec\n const READ_KEYWORDS = ['read(', 'readline', 'readlines', 'fread', 'fgets', 'load(', 'getpass', 'file_get_contents'];\n const WRITE_KEYWORDS = ['write(', 'writelines', 'fwrite', 'file_put_contents'];\n const EXEC_KEYWORDS = ['system(', 'exec(', 'eval(', 'popen(', 'os.system', 'os.popen', 'subprocess', 'os.exec', 'os.spawn', 'shell=true', 'check_output', 'check_call', 'run(', 'passthru', 'shell_exec', 'proc_open'];\n const OPEN_KEYWORDS = ['open(', 'fopen('];\n const code = extractInlineCode(actionDetail);\n if (!code) return null;\n const codeLower = code.toLowerCase();\n const hasAnyOp = READ_KEYWORDS.some(kw => codeLower.includes(kw)) ||\n WRITE_KEYWORDS.some(kw => codeLower.includes(kw)) ||\n EXEC_KEYWORDS.some(kw => codeLower.includes(kw)) ||\n OPEN_KEYWORDS.some(kw => codeLower.includes(kw));\n if (!hasAnyOp) {\n return null;\n }\n\n // Determine operation type\n const hasWrite = WRITE_KEYWORDS.some(kw => codeLower.includes(kw));\n const hasExec = EXEC_KEYWORDS.some(kw => codeLower.includes(kw));\n // Write/exec: block all sensitive files. Read only: block only credential files.\n const blockAllSensitive = hasWrite || hasExec;\n\n // Pattern matched — try to list actual files in cwd and check against sensitive paths\n let actualFiles: string[] = [];\n if (cwd && cwd !== '/') {\n try {\n actualFiles = fs.readdirSync(cwd);\n } catch {\n // cwd invalid or inaccessible, fall through\n }\n }\n\n if (actualFiles.length > 0) {\n // Check credential files\n for (const cp of CREDENTIAL_PATHS) {\n const fname = cp.path.split('/').pop() || cp.path;\n if (actualFiles.some(f => f === fname || f.toLowerCase() === fname.toLowerCase())) {\n return {\n allowed: false,\n reason: `内联脚本使用目录遍历动态发现文件并执行读写操作,cwd (${cwd}) 中包含凭据文件: ${fname}`,\n riskLevel: 'high',\n riskType: 'file_access',\n confidence: 95,\n source: 'logic_rule',\n violatedLayers: ['2'],\n isCredential: true,\n };\n }\n }\n\n // Check other sensitive files (only block on write/exec, read-only is safe for non-credential)\n if (blockAllSensitive) {\n for (const sp of [...ROOT_SENSITIVE_PATHS, ...HOME_SENSITIVE_PATHS]) {\n const fname = sp.path.split('/').pop() || sp.path;\n if (actualFiles.some(f => f === fname || f.toLowerCase() === fname.toLowerCase())) {\n return {\n allowed: false,\n reason: `内联脚本使用目录遍历动态发现文件并执行写操作,cwd (${cwd}) 中包含敏感文件: ${fname}`,\n riskLevel: 'high',\n riskType: 'file_access',\n confidence: 95,\n source: 'logic_rule',\n violatedLayers: ['2'],\n };\n }\n }\n }\n\n // No sensitive files found in cwd — safe to allow\n return null;\n }\n\n // cwd invalid, can't check actual files — fall back to medium risk (L3)\n return {\n allowed: false,\n reason: '内联脚本使用目录遍历函数动态发现文件并执行读写操作,无法获取 cwd 实际文件列表,转层3 LLM 分析',\n riskLevel: 'medium',\n riskType: 'file_access',\n confidence: 70,\n source: 'logic_rule',\n violatedLayers: ['2'],\n };\n}\n","import { readFileSync, readdirSync, existsSync } from 'fs';\nimport { resolve, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport { loadL3 } from '../infra/rules-loader';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n// 优先用打包内联目录 dist/skills(npm 安装后自包含);\n// dev 模式(vitest 测试时 __dirname=ts/src/engine)回退到仓库根 agent_moss/skills。\n// 注意:从 ts/src/engine 出发,仓库根 agent_moss/skills 在 ../../../agent_moss/skills\n// (不能写 ../../agent_moss/skills,那是 ts/agent_moss/skills,不存在)。\nconst SKILLS_DIR = resolve(__dirname, '../skills');\nconst SKILLS_DIR_FALLBACK = resolve(__dirname, '../../../agent_moss/skills');\n\n// Skill keyword map (synced with Python skill_engine.py SKILL_KEYWORD_MAP)\n// exported for runtime_config seed (generateSourceDefaults)\nexport const SKILL_KEYWORD_MAP: Record<string, string[]> = (() => {\n // 归一化自 agent_moss/rules/l3_rules.json(单一事实源,与 Python 共用)。\n // l3_rules.json = {category: {skill_id: [keywords]}},展平为 {skill_id: [keywords]}。\n const map: Record<string, string[]> = {};\n const cats = loadL3() as Record<string, Record<string, string[]>>;\n for (const cat of Object.values(cats)) {\n if (!cat || typeof cat !== 'object') continue;\n for (const [skillId, keywords] of Object.entries(cat)) {\n map[skillId] = keywords;\n }\n }\n return map;\n})();\n\nlet cachedSkills: Record<string, string> | null = null;\n\nfunction loadAllSkills(): Record<string, string> {\n if (cachedSkills) return cachedSkills;\n cachedSkills = {};\n\n const dir = existsSync(SKILLS_DIR) ? SKILLS_DIR : SKILLS_DIR_FALLBACK;\n if (!existsSync(dir)) {\n console.warn('[AgentMoss] Skills directory not found:', SKILLS_DIR, 'and fallback:', SKILLS_DIR_FALLBACK);\n return cachedSkills;\n }\n\n const files = readdirSync(dir).filter(f => f.endsWith('.md'));\n for (const f of files) {\n const name = f.replace('.md', '');\n cachedSkills[name] = readFileSync(resolve(dir, f), 'utf-8');\n }\n\n console.log(`[AgentMoss] Loaded ${Object.keys(cachedSkills).length} skills from ${dir}`);\n return cachedSkills;\n}\n\nexport interface SkillMatch {\n skillName: string;\n relevance: number; // 0-1\n skillContent: string;\n}\n\n/**\n * Match skills by keyword relevance (mirrors Python SkillEngine.match_skills).\n * Returns top-3 most relevant skills, or fallback to general_tool_risk_guard.\n */\nexport function matchSkills(\n actionType: string,\n actionDetail: string,\n reason: string,\n maxSkills: number = 3\n): SkillMatch[] {\n const skills = loadAllSkills();\n const combined = `${actionType} ${actionDetail} ${reason}`.toLowerCase();\n const actionDetailLower = actionDetail.toLowerCase();\n const actionTypeLower = actionType.toLowerCase();\n const reasonLower = reason.toLowerCase();\n\n const scores: Record<string, number> = {};\n for (const [skillName, keywords] of Object.entries(SKILL_KEYWORD_MAP)) {\n let score = 0;\n for (const kw of keywords) {\n if (combined.includes(kw)) {\n if (kw === actionTypeLower) score += 2.0;\n else if (actionDetailLower.includes(kw)) score += 1.5;\n else if (reasonLower.includes(kw)) score += 1.0;\n else score += 0.5;\n }\n }\n if (score > 0) scores[skillName] = score;\n }\n\n const sorted = Object.entries(scores).sort((a, b) => b[1] - a[1]);\n const top = sorted.slice(0, maxSkills);\n const maxScore = top[0]?.[1] || 1;\n\n const results: SkillMatch[] = [];\n for (const [name, score] of top) {\n const content = skills[name];\n if (content) {\n results.push({\n skillName: name,\n relevance: Math.min(score / maxScore, 1.0),\n skillContent: content,\n });\n }\n }\n\n // Fallback to general_tool_risk_guard if no match\n if (results.length === 0) {\n const fallback = skills['general_tool_risk_guard'];\n if (fallback) {\n results.push({ skillName: 'general_tool_risk_guard', relevance: 0.3, skillContent: fallback });\n }\n }\n\n return results;\n}\n\n/**\n * Format matched skills for LLM prompt (mirrors Python SkillEngine.format_skills_for_prompt).\n */\nexport function formatSkillsForPrompt(skills: SkillMatch[]): string {\n if (skills.length === 0) return '(未匹配到特定安全检测规则)';\n return skills.map(s =>\n `### 安全检测规则: ${s.skillName} (相关度: ${Math.round(s.relevance * 100)}%)\\n\\n${s.skillContent}`\n ).join('\\n\\n---\\n\\n');\n}\n\n/** Legacy: load all skills as flat string array */\nexport function loadSkills(): string[] {\n const skills = loadAllSkills();\n return Object.entries(skills).map(([name, content]) => `### ${name}\\n${content}`);\n}\n\n/** Reload skills (for hot-reload) */\nexport function reloadSkills(): void {\n cachedSkills = null;\n loadAllSkills();\n}\n","/**\n * Runtime config — full implementation (mirrors Python runtime_config.py).\n *\n * Runtime JSON: ~/.config/agentmoss/agent_moss_runtime.json\n * (env AGENT_MOSS_RUNTIME_CONFIG_PATH override). Seed from OSProfile +\n * module consts + SKILL_KEYWORD_MAP. mergeConfig on load (preserve user\n * toggles, append builtins, mark removed).\n *\n * Priority: env > runtime JSON > agent_moss_settings > default.\n */\n\nimport { readFileSync, writeFileSync, existsSync, mkdirSync, unlinkSync, readdirSync } from 'fs';\nimport { join } from 'path';\nimport { fileURLToPath } from 'url';\nimport { dirname } from 'path';\nimport { getRuntimeConfigDir } from './paths';\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n// 静态 import(非 require):package.json type=module,require 在 ESM 不可用。\n// 这三个模块不反向 import runtime-config,无循环依赖。\nimport { DANGEROUS_PATTERNS, INJECTION_KEYWORDS } from '../engine/heuristic';\nimport {\n ROOT_SENSITIVE_PATHS, HOME_SENSITIVE_PATHS, CREDENTIAL_PATHS,\n PASSWORD_MODIFY_PATTERNS, USER_DELETION_PATTERNS, INTENT_DEVIATION_PATTERNS,\n} from '../engine/logic-rules';\nimport { SKILL_KEYWORD_MAP } from '../engine/skill-loader';\n// type-only import:避免 agents ↔ runtime-config 循环依赖(运行时用 require 取 resolveAgentsDir)\nimport type { AgentExtensions } from '../agents/types';\n\nconst ENV_RUNTIME_CONFIG_PATH = 'AGENT_MOSS_RUNTIME_CONFIG_PATH';\n\nfunction runtimeDir(): string {\n return getRuntimeConfigDir();\n}\n\nconst RUNTIME_CONFIG_DIR = runtimeDir();\nconst RUNTIME_CONFIG_PATH = join(RUNTIME_CONFIG_DIR, 'agent_moss_runtime.json');\n\nconst LAYER_DISABLE_ENV: Record<string, string> = {\n L1_heuristic: 'AGENT_MOSS_DISABLE_HEURISTIC',\n L2_logic_rules: 'AGENT_MOSS_DISABLE_LOGIC_RULES',\n L3_llm_analysis: 'AGENT_MOSS_DISABLE_LLM',\n};\n\nexport const DENY_MODE_LABELS: Record<string, string> = {\n deny_write: '仅拦截写入',\n deny_read: '仅拦截读取',\n deny_both: '读写均拦截',\n};\n\n// ==================== Types ====================\n\nexport interface Rule {\n id: string;\n enabled: boolean;\n builtin: boolean;\n source_removed?: boolean;\n pattern?: string;\n risk_level?: string;\n risk_type?: string;\n reason?: string;\n keyword?: string;\n lang?: string;\n path?: string;\n desc?: string;\n deny_mode?: string;\n source_deny_mode?: string;\n credential?: boolean;\n read_only?: boolean;\n skip_l3_on_disabled?: boolean;\n intent_keywords?: string[];\n dangerous_actions?: string[];\n /** builtin_safe_action_types / builtin_safe_skills 项的值(前缀或精确工具名) */\n value?: string;\n}\n\nexport interface Skill {\n id: string;\n keywords: string[];\n enabled: boolean;\n builtin: boolean;\n}\n\ninterface Category {\n category_enabled?: boolean;\n category_desc?: string;\n rules?: Rule[];\n skills?: Skill[];\n}\n\nexport interface RuntimeConfig {\n version: number;\n layers: { L1_heuristic: boolean; L2_logic_rules: boolean; L3_llm_analysis: boolean };\n L1_rules: Record<string, Category>;\n L2_rules: Record<string, Category>;\n L3_skills: Record<string, Category>;\n /** agent 定制规则(按 agent_id 分区,每 agent 内按类别组织) */\n agent_rules?: Record<string, Record<string, Category>>;\n}\n\n// ==================== Path / load / save ====================\n\nexport function getRuntimeConfigPath(): string {\n const envPath = process.env[ENV_RUNTIME_CONFIG_PATH];\n if (envPath) return envPath;\n // agent_moss_settings.json fallback omitted in TS (env-only); default path.\n return RUNTIME_CONFIG_PATH;\n}\n\nexport function saveRuntimeConfig(config: RuntimeConfig): void {\n const p = getRuntimeConfigPath();\n const dir = p.substring(0, p.lastIndexOf('/'));\n if (dir && !existsSync(dir)) mkdirSync(dir, { recursive: true });\n writeFileSync(p, JSON.stringify(config, null, 2), 'utf-8');\n}\n\n/** Minimal default (all layers on, empty rule categories). The full\n * profile-driven seed generator (generate_source_defaults equivalent)\n * is deferred to Stage 4 (console backend); for now a missing runtime\n * file yields this minimal config — coordinator's getDisabledL2RulesWithSkipL3\n * returns {} (safe default, no skip_l3 hard constraint). */\nfunction emptyRuntimeConfig(): RuntimeConfig {\n return {\n version: 1,\n layers: { L1_heuristic: true, L2_logic_rules: true, L3_llm_analysis: true },\n L1_rules: {},\n L2_rules: {},\n L3_skills: {},\n agent_rules: {},\n };\n}\n\nexport function loadRuntimeConfig(): RuntimeConfig {\n const p = getRuntimeConfigPath();\n if (!existsSync(p)) {\n // 首次:seed + save,与 py load_runtime_config 的 fallback seed 对齐。\n // 不 seed 时 getDisabledL2RulesWithSkipL3 返回 {}(无 skip_l3 约束),\n // 但 Console 需要全量规则展示,所以必须 seed。\n const seeded = mergeConfig({}, generateSourceDefaults());\n try { saveRuntimeConfig(seeded); } catch { /* 只读 fs 时忽略 */ }\n return seeded;\n }\n try {\n const data = JSON.parse(readFileSync(p, 'utf-8'));\n const merged = mergeConfig(data, generateSourceDefaults());\n return {\n version: data.version || 1,\n layers: {\n L1_heuristic: data.layers?.L1_heuristic ?? true,\n L2_logic_rules: data.layers?.L2_logic_rules ?? true,\n L3_llm_analysis: data.layers?.L3_llm_analysis ?? true,\n },\n L1_rules: merged.L1_rules || {},\n L2_rules: merged.L2_rules || {},\n L3_skills: merged.L3_skills || {},\n agent_rules: merged.agent_rules || {},\n };\n } catch {\n return emptyRuntimeConfig();\n }\n}\n\n// ==================== Layer toggles ====================\n\n/**\n * Is a layer enabled? Priority: env > runtime JSON > default true.\n *\n * Note: the agent_moss_settings.json fallback (used in Python) is not\n * consulted here — env vars are the primary TS-side override. The runtime\n * JSON is authoritative when env is unset.\n */\nexport function isLayerEnabled(layerKey: string): boolean {\n const disableKey = LAYER_DISABLE_ENV[layerKey];\n if (disableKey && process.env[disableKey] === '1') return false;\n const runtime = loadRuntimeConfig();\n const layers = runtime.layers || {} as RuntimeConfig['layers'];\n if (layerKey in layers) return !!layers[layerKey as keyof typeof layers];\n return true;\n}\n\nexport function getEnvOverrides(): Record<string, {\n env_var: string; env_value: string; overridden: boolean; effect: string;\n}> {\n const overrides: Record<string, any> = {};\n for (const [layerKey, envKey] of Object.entries(LAYER_DISABLE_ENV)) {\n const val = process.env[envKey];\n if (val !== undefined) {\n overrides[layerKey] = {\n env_var: envKey,\n env_value: val,\n overridden: val === '1',\n effect: val === '1' ? 'disabled' : 'no_override',\n };\n }\n }\n return overrides;\n}\n\n// ==================== Rule filtering / queries ====================\n\nexport function filterEnabledRules(rules: Rule[], categoryEnabled: boolean = true): Rule[] {\n if (!categoryEnabled) return [];\n return rules.filter(r => r.enabled !== false);\n}\n\nexport function getEnabledL1CommandPatterns(runtime: RuntimeConfig): { pattern: string; risk_level: string; risk_type: string; reason: string }[] {\n const cat = runtime.L1_rules?.dangerous_commands || { category_enabled: true, rules: [] };\n return filterEnabledRules(cat.rules || [], cat.category_enabled).map(r => ({\n pattern: r.pattern || '', risk_level: r.risk_level || '', risk_type: r.risk_type || '', reason: r.reason || '',\n }));\n}\n\nexport function getEnabledL2SensitivePaths(runtime: RuntimeConfig): { path: string; risk_level: string; desc: string; deny_mode: string; credential?: boolean; read_only?: boolean }[] {\n // 优先读 L1_rules.sensitive_path_access(重分类后归属 L1);\n // 回退 L2_rules.sensitive_path_access(兼容迁移前老配置)。函数名保留 l2 前缀仅为兼容。\n let cat = runtime.L1_rules?.sensitive_path_access;\n if (!cat || !cat.rules || cat.rules.length === 0) {\n cat = runtime.L2_rules?.sensitive_path_access || { category_enabled: true, rules: [] };\n }\n return filterEnabledRules(cat.rules || [], cat.category_enabled).map(r => {\n const out: any = { path: r.path || '', risk_level: r.risk_level || '', desc: r.desc || '', deny_mode: r.deny_mode || 'deny_write' };\n if (r.credential) out.credential = true;\n if (r.read_only) out.read_only = true;\n return out;\n });\n}\n\nexport function hasRuntimeConfig(): boolean {\n const p = getRuntimeConfigPath();\n if (!existsSync(p)) return false;\n try {\n JSON.parse(readFileSync(p, 'utf-8'));\n return true;\n } catch { return false; }\n}\n\n// ==================== skip_l3 hard constraint ====================\n\n/**\n * L2 rules with enabled=false AND skip_l3_on_disabled=true, grouped by\n * category, returning their key content (path / intent_keywords / pattern).\n * Consumed by coordinator to build skip_l3_hints for the L3 prompt.\n */\nexport function getDisabledL2RulesWithSkipL3(): Record<string, string[]> {\n let runtime: RuntimeConfig;\n try { runtime = loadRuntimeConfig(); }\n catch { return {}; }\n const result: Record<string, string[]> = {};\n // 敏感路径已重分类到 L1,遍历 L1_rules + L2_rules 两层。函数名保留 l2 前缀仅为兼容。\n for (const layerKey of ['L1_rules', 'L2_rules'] as const) {\n const layer = runtime[layerKey] || {};\n for (const [catName, cat] of Object.entries(layer)) {\n if (!cat.category_enabled) continue;\n const items: string[] = [];\n for (const r of cat.rules || []) {\n if (r.enabled === false && r.skip_l3_on_disabled) {\n if (catName === 'sensitive_path_access') {\n if (r.path) items.push(r.path);\n } else if (catName === 'intent_consistency') {\n items.push(...(r.intent_keywords || []));\n } else if (r.pattern) {\n items.push(r.pattern);\n }\n }\n }\n if (items.length > 0) result[catName] = items;\n }\n }\n return result;\n}\n\n// ==================== Helpers ====================\n\nfunction _slugify(text: string): string {\n return text.toLowerCase().replace(/[^a-z0-9]+/g, '_').replace(/^_|_$/g, '') || 'x';\n}\n\nfunction _generatePatternId(pattern: string): string {\n return `pat_${_slugify(pattern)}`;\n}\n\n/** 从 credential / read_only 推导 deny_mode(向后兼容)。优先用已有 deny_mode。 */\nfunction _deriveDenyMode(rule: Partial<Rule>): string {\n if (rule.deny_mode) return rule.deny_mode;\n if (rule.credential) return 'deny_both';\n if (rule.read_only) return 'deny_read';\n return 'deny_write';\n}\n\n/** 根据 deny_mode 同步 credential / read_only(保持底层检测逻辑兼容) */\nfunction _syncDenyModeFields(rule: Rule): void {\n const dm = rule.deny_mode || 'deny_write';\n if (dm === 'deny_both') {\n rule.credential = true;\n delete rule.read_only;\n } else if (dm === 'deny_read') {\n delete rule.credential;\n rule.read_only = true;\n } else {\n delete rule.credential;\n delete rule.read_only;\n }\n}\n\n// ==================== Seed (generateSourceDefaults) ====================\n//\n// py 的 generate_source_defaults 从 OSProfile 拿 dangerous_commands / sensitive_paths\n// / intent_deviation_patterns / injection_keywords(运行时按 OS 类型分叉)。\n// TS 不分 OS profile(只 win/linux 用于 os_type 字段,不影响规则集),规则集硬编码\n// 在 heuristic.ts / logic-rules.ts 常量里。所以 TS seed 直接从常量生成,不走 profile。\n\nfunction _l1CommandPatternsToRules(): Rule[] {\n // DANGEROUS_PATTERNS 是 RegExp,seed 时存 source 字符串。\n return DANGEROUS_PATTERNS.map((p) => ({\n id: _generatePatternId(p.pattern instanceof RegExp ? p.pattern.source : p.pattern),\n pattern: p.pattern instanceof RegExp ? p.pattern.source : p.pattern,\n risk_level: p.severity,\n risk_type: p.riskType,\n reason: p.description,\n enabled: true,\n builtin: true,\n }));\n}\n\nfunction _l1InjectionKeywordsToRules(): Rule[] {\n return INJECTION_KEYWORDS.map((kw) => ({\n id: `inj_${_slugify(kw.keyword)}`,\n keyword: kw.keyword,\n risk_level: kw.riskLevel,\n lang: kw.lang || 'en',\n enabled: true,\n builtin: true,\n }));\n}\n\nfunction _l2SensitivePathsToRules(): Rule[] {\n const all = [...ROOT_SENSITIVE_PATHS, ...HOME_SENSITIVE_PATHS, ...CREDENTIAL_PATHS] as any[];\n return all.map((sp) => {\n const denyMode = _deriveDenyMode({\n deny_mode: sp.deny_mode,\n credential: sp.credential,\n read_only: sp.read_only,\n });\n const rule: Rule = {\n id: `path_${_slugify(sp.path)}`,\n path: sp.path,\n risk_level: sp.riskLevel,\n desc: sp.desc,\n deny_mode: denyMode,\n source_deny_mode: denyMode,\n skip_l3_on_disabled: true,\n enabled: true,\n builtin: true,\n };\n _syncDenyModeFields(rule);\n return rule;\n });\n}\n\nfunction _l2IntentPatternsToRules(): Rule[] {\n return INTENT_DEVIATION_PATTERNS.map((pat, i) => ({\n id: `intent_${i + 1}_${_slugify(pat.reason.slice(0, 30))}`,\n intent_keywords: pat.intentKeywords,\n dangerous_actions: pat.dangerousActions,\n reason: pat.reason,\n skip_l3_on_disabled: true,\n enabled: true,\n builtin: true,\n }));\n}\n\nfunction _l2PasswordPatternsToRules(): Rule[] {\n return PASSWORD_MODIFY_PATTERNS.map((p) => ({\n id: `pw_${_slugify(p.source)}`,\n pattern: p.source,\n skip_l3_on_disabled: true,\n enabled: true,\n builtin: true,\n }));\n}\n\nfunction _l2UserDeletionPatternsToRules(): Rule[] {\n return USER_DELETION_PATTERNS.map((p) => ({\n id: `ud_${_slugify(p.source)}`,\n pattern: p.source,\n skip_l3_on_disabled: true,\n enabled: true,\n builtin: true,\n }));\n}\n\nfunction _l3SkillsToRules(): Record<string, Category> {\n const skillCategories: Record<string, string[]> = {\n file_operations: ['file_access_guard', 'script_execution_guard', 'indirect_access_guard'],\n network_security: ['data_exfiltration_guard', 'browser_web_access_guard',\n 'lateral_movement_guard', 'email_operation_guard'],\n persistence_supply_chain: ['persistence_backdoor_guard', 'supply_chain_guard',\n 'skill_installation_guard'],\n intent_and_general: ['intent_deviation_guard', 'general_tool_risk_guard'],\n resource: ['resource_exhaustion_guard'],\n };\n const out: Record<string, Category> = {};\n for (const [cat, ids] of Object.entries(skillCategories)) {\n out[cat] = {\n category_enabled: true,\n category_desc: '',\n skills: ids.map((s: string) => ({\n id: s,\n keywords: SKILL_KEYWORD_MAP[s] || [],\n enabled: true,\n builtin: true,\n })),\n };\n }\n const categorized = new Set<string>(Object.values(skillCategories).flat());\n for (const s of Object.keys(SKILL_KEYWORD_MAP)) {\n if (!categorized.has(s)) {\n (out.intent_and_general ??= { category_enabled: true, category_desc: '', skills: [] })\n .skills!.push({\n id: s, keywords: SKILL_KEYWORD_MAP[s], enabled: true, builtin: true,\n });\n }\n }\n out.user_custom = { category_enabled: true, category_desc: '', skills: [] };\n return out;\n}\n\n/** 扫描 agent_moss/agents/<id>/rules.json,转为 agent_rules 分区结构(出厂种子)。\n * 每个 agent 的 rules.json 字段 → agent_rules[<id>] 的 Category 结构(与 L1/L2 同形)。\n * builtin_safe_action_types / builtin_safe_skills 原为 string[],转成 [{value, enabled, builtin}]。\n * 路径内联解析(不 import agents/index.ts 避免 ESM 循环依赖),与 agents/index.ts resolveAgentsDir 同策略。 */\nconst _AGENTS_DIR_PROD = join(__dirname, 'agents');\nconst _AGENTS_DIR_DEV = join(__dirname, '..', '..', '..', 'agent_moss', 'agents');\nfunction _agentRulesToDefaults(): Record<string, Record<string, Category>> {\n const out: Record<string, Record<string, Category>> = {};\n const agentsDir = existsSync(_AGENTS_DIR_PROD) ? _AGENTS_DIR_PROD\n : existsSync(_AGENTS_DIR_DEV) ? _AGENTS_DIR_DEV : _AGENTS_DIR_PROD;\n if (!existsSync(agentsDir)) return out;\n let entries: string[];\n try {\n entries = readdirSync(agentsDir, { withFileTypes: true })\n .filter(d => d.isDirectory()).map(d => d.name);\n } catch {\n return out;\n }\n for (const agentId of entries) {\n const rulesFile = join(agentsDir, agentId, 'rules.json');\n if (!existsSync(rulesFile)) continue;\n let data: any;\n try { data = JSON.parse(readFileSync(rulesFile, 'utf-8')); } catch { continue; }\n out[agentId] = {\n builtin_safe_action_types: {\n category_enabled: true,\n category_desc: 'agent 完全安全操作白名单(前缀尾随 - 或精确名,命中跳 L2+L3)',\n rules: (data.builtin_safe_action_types || []).map((v: string) =>\n ({ value: v, enabled: true, builtin: true })),\n },\n builtin_safe_skills: {\n category_enabled: true,\n category_desc: 'agent 信任的内置 Skill(命中跳 L2+L3)',\n rules: (data.builtin_safe_skills || []).map((v: string) =>\n ({ value: v, enabled: true, builtin: true })),\n },\n extra_command_patterns: {\n category_enabled: true,\n category_desc: 'agent 专属危险命令正则(L1 末尾追加)',\n rules: (data.extra_command_patterns || []).map((p: any) =>\n ({ ...p, enabled: true, builtin: true })),\n },\n extra_injection_keywords: {\n category_enabled: true,\n category_desc: 'agent 专属注入关键词(L1 末尾追加)',\n rules: (data.extra_injection_keywords || []).map((k: any) =>\n ({ ...k, enabled: true, builtin: true })),\n },\n extra_sensitive_paths: {\n category_enabled: true,\n category_desc: 'agent 专属敏感路径(L1 末尾追加)',\n rules: (data.extra_sensitive_paths || []).map((sp: any) =>\n ({ ...sp, enabled: true, builtin: true })),\n },\n };\n }\n return out;\n}\n\n/** 从 TS 常量生成 runtime 默认结构(出厂种子)。TS 不走 profile,直接从常量。 */\nexport function generateSourceDefaults(): RuntimeConfig {\n return {\n version: 1,\n layers: { L1_heuristic: true, L2_logic_rules: true, L3_llm_analysis: true },\n L1_rules: {\n dangerous_commands: {\n category_enabled: true,\n category_desc: '危险命令检测(递归删除、全权限设置、提权执行等)',\n rules: _l1CommandPatternsToRules(),\n },\n injection_detection: {\n category_enabled: true,\n category_desc: 'Prompt 注入攻击检测',\n rules: _l1InjectionKeywordsToRules(),\n },\n sensitive_path_access: {\n category_enabled: true,\n category_desc: '敏感路径访问检测(deny_both/deny_read/deny_write)',\n rules: _l2SensitivePathsToRules(),\n },\n user_custom: { category_enabled: true, category_desc: '用户自定义命令规则', rules: [] },\n },\n L2_rules: {\n intent_consistency: {\n category_enabled: true,\n category_desc: '意图一致性检测',\n rules: _l2IntentPatternsToRules(),\n },\n password_modify_consent: {\n category_enabled: true,\n category_desc: '非交互式密码修改授权检测',\n rules: _l2PasswordPatternsToRules(),\n },\n user_deletion_consent: {\n category_enabled: true,\n category_desc: '用户/组删除操作授权检测',\n rules: _l2UserDeletionPatternsToRules(),\n },\n read_before_write: { category_enabled: true, category_desc: 'read_before_write 安全原则检测', rules: [] },\n user_custom: { category_enabled: true, category_desc: '用户自定义 L2 逻辑规则', rules: [] },\n },\n L3_skills: _l3SkillsToRules(),\n agent_rules: _agentRulesToDefaults(),\n };\n}\n\n// ==================== Merge (preserve user toggles) ====================\n\n/** 规则内容指纹(跨 id 变更识别同一规则)。 */\n/**\n * 正则 pattern 规范化,用于计算规则指纹。\n *\n * Python 与 TS 生成规则时对 `/` 的转义不一致:TS 用 RegExp.source(`/` 转义为 `\\/`),\n * Python 直接存 `/`。这导致同一规则在两端生成 pattern 字符串不同 → 指纹不同 →\n * 双端 merge 时互相把对方标记 source_removed 而禁用(L1 启用数不一致)。\n *\n * 这里把 `\\/` 规范化为 `/`,使两端 pattern 指纹一致。只处理 `/` 转义,不动其他正则转义。\n */\nfunction normalizePatternForFingerprint(pattern: string): string {\n return pattern.replace(/\\\\\\//g, '/');\n}\n\nfunction _ruleFingerprint(rule: Partial<Rule>): string {\n if ((rule.intent_keywords && rule.intent_keywords.length) || (rule.dangerous_actions && rule.dangerous_actions.length)) {\n return JSON.stringify([\n [...(rule.intent_keywords || [])].sort(),\n [...(rule.dangerous_actions || [])].sort(),\n ]);\n }\n if (rule.path) return JSON.stringify([normalizePatternForFingerprint(rule.path)]);\n if (rule.pattern) return JSON.stringify([normalizePatternForFingerprint(rule.pattern)]);\n if (rule.keyword) return JSON.stringify([rule.keyword, rule.lang || '']);\n // builtin_safe_action_types / builtin_safe_skills 项用 value 字段\n if (rule.value) return JSON.stringify([rule.value]);\n return JSON.stringify([rule.id || '']);\n}\n\n/** 合并 L1/L2 分类与规则(保留用户 enabled/skip_l3/deny_mode,补入新 builtin,标记删除)。 */\nfunction _mergeRuleCategories(userCfg: RuntimeConfig, srcDefaults: RuntimeConfig, layerKey: 'L1_rules' | 'L2_rules'): void {\n const userLayer = (userCfg[layerKey] || (userCfg[layerKey] = {})) as Record<string, Category>;\n const srcLayer = srcDefaults[layerKey] || {};\n for (const [catName, srcCat] of Object.entries(srcLayer)) {\n if (!(catName in userLayer)) {\n userLayer[catName] = srcCat;\n continue;\n }\n const userCat: Category = userLayer[catName];\n if (userCat.category_desc === undefined) userCat.category_desc = srcCat.category_desc || '';\n if (userCat.category_enabled === undefined) userCat.category_enabled = srcCat.category_enabled ?? true;\n const srcRules = srcCat.rules || [];\n const userRules = (userCat.rules || (userCat.rules = []));\n const userByFp = new Map<string, Rule>();\n for (const r of userRules) userByFp.set(_ruleFingerprint(r), r);\n const srcFps = new Set<string>();\n for (const srcR of srcRules) {\n const fp = _ruleFingerprint(srcR);\n srcFps.add(fp);\n if (userByFp.has(fp)) {\n const existing = userByFp.get(fp)!;\n const userEnabled = existing.enabled;\n const userSkipL3 = existing.skip_l3_on_disabled;\n const userDenyMode = existing.deny_mode;\n const userSourceDeny = existing.source_deny_mode;\n Object.keys(existing).forEach(k => delete (existing as any)[k]);\n Object.assign(existing, srcR);\n existing.enabled = userEnabled;\n if (userSkipL3 !== undefined) existing.skip_l3_on_disabled = userSkipL3;\n if (userDenyMode && userSourceDeny && userDenyMode !== userSourceDeny) {\n existing.deny_mode = userDenyMode;\n }\n if (existing.deny_mode) _syncDenyModeFields(existing);\n } else {\n const newR: Rule = { ...srcR, enabled: true };\n userRules.push(newR);\n }\n }\n for (const r of userRules) {\n // builtin 且指纹不在 src 集合 → 源码已删除该规则\n if (r.builtin && !srcFps.has(_ruleFingerprint(r))) {\n r.source_removed = true;\n r.enabled = false;\n }\n }\n if (catName === 'sensitive_path_access') {\n for (const r of userRules) {\n if (!r.deny_mode) r.deny_mode = _deriveDenyMode(r);\n _syncDenyModeFields(r);\n }\n }\n }\n // 清理源码已移除的类目:保留 user_custom(用户自定义壳),删除其余不在 src 的类目\n // (如本次重构删除的 dangerous_patterns / lateral_movement,老配置落盘仍残留)。\n for (const catName of Object.keys(userLayer)) {\n if (catName === 'user_custom') continue;\n if (!(catName in srcLayer)) delete userLayer[catName];\n }\n}\n\n/** 合并 L3_skills 分类。新分类整体加入;已有分类补全元字段 + 追加新 builtin skill。 */\nfunction _mergeSkillCategories(userCfg: RuntimeConfig, srcDefaults: RuntimeConfig, layerKey: 'L3_skills'): void {\n const userLayer = (userCfg[layerKey] || (userCfg[layerKey] = {})) as Record<string, Category>;\n const srcLayer = srcDefaults[layerKey] || {};\n for (const [catName, srcCat] of Object.entries(srcLayer)) {\n if (!(catName in userLayer)) {\n userLayer[catName] = srcCat;\n continue;\n }\n const userCat: Category = userLayer[catName];\n if (userCat.category_desc === undefined) userCat.category_desc = srcCat.category_desc || '';\n if (userCat.category_enabled === undefined) userCat.category_enabled = srcCat.category_enabled ?? true;\n const userSkills = (userCat.skills || (userCat.skills = []));\n const existingIds = new Set(userSkills.map(s => s.id));\n for (const srcS of (srcCat.skills || [])) {\n if (!existingIds.has(srcS.id)) userSkills.push({ ...srcS });\n }\n }\n}\n\n/** 合并 agent_rules 分区(按 agent_id 分区,每个 agent 内复用类别合并逻辑)。\n * 新出厂 agent → 整体加入;已有 agent → 每类别走 _mergeRuleCategories 同套\n * (指纹去重 + 保留 enabled + 新 builtin 追加 + 删除标记 source_removed)。 */\nfunction _mergeAgentRules(userCfg: RuntimeConfig, srcDefaults: RuntimeConfig): void {\n const userAgent = (userCfg.agent_rules || (userCfg.agent_rules = {})) as Record<string, Record<string, Category>>;\n const srcAgent = srcDefaults.agent_rules || {};\n for (const [agentId, srcCats] of Object.entries(srcAgent)) {\n if (!(agentId in userAgent)) {\n userAgent[agentId] = JSON.parse(JSON.stringify(srcCats));\n continue;\n }\n const userCats = userAgent[agentId];\n for (const [catName, srcCat] of Object.entries(srcCats)) {\n if (!(catName in userCats)) {\n userCats[catName] = JSON.parse(JSON.stringify(srcCat));\n continue;\n }\n const userCat: Category = userCats[catName];\n if (userCat.category_desc === undefined) userCat.category_desc = srcCat.category_desc || '';\n if (userCat.category_enabled === undefined) userCat.category_enabled = srcCat.category_enabled ?? true;\n const srcRules = srcCat.rules || [];\n const userRules = (userCat.rules || (userCat.rules = []));\n const userByFp = new Map<string, Rule>();\n for (const r of userRules) userByFp.set(_ruleFingerprint(r), r);\n const srcFps = new Set<string>();\n for (const srcR of srcRules) {\n const fp = _ruleFingerprint(srcR);\n srcFps.add(fp);\n if (userByFp.has(fp)) {\n const existing = userByFp.get(fp)!;\n const userEnabled = existing.enabled;\n Object.keys(existing).forEach(k => delete (existing as any)[k]);\n Object.assign(existing, srcR);\n existing.enabled = userEnabled;\n } else {\n userRules.push({ ...srcR, enabled: true });\n }\n }\n for (const r of userRules) {\n if (r.builtin && !srcFps.has(_ruleFingerprint(r))) {\n r.source_removed = true;\n r.enabled = false;\n }\n }\n }\n }\n}\n\n/** 合并用户配置与源码默认值。保留用户开关;新增 builtin 补入;源码删除的标记。 */\nexport function mergeConfig(userCfg: Partial<RuntimeConfig>, srcDefaults: RuntimeConfig): RuntimeConfig {\n const cfg = userCfg as RuntimeConfig;\n if (cfg.version === undefined) cfg.version = srcDefaults.version || 1;\n if (!cfg.layers) cfg.layers = {} as RuntimeConfig['layers'];\n for (const [layerKey, defaultVal] of Object.entries(srcDefaults.layers)) {\n if (!(layerKey in cfg.layers)) (cfg.layers as any)[layerKey] = defaultVal;\n }\n // 跨层迁移:敏感路径已从 L2 重分类到 L1。老配置 sensitive_path_access 还在\n // L2_rules 下,搬到 L1_rules(保留用户 enabled/deny_mode/自定义项),L2 删除该分类。\n // 注:dangerous_patterns / lateral_movement 检测是硬编码子检测器,不读 runtime\n // config rules,故老配置 L2 里这两类的 rules 不迁移(默认种子已删除该类目)。\n _migrateCategoriesAcrossLayers(cfg, 'L2_rules', 'L1_rules',\n ['sensitive_path_access']);\n _mergeRuleCategories(cfg, srcDefaults, 'L1_rules');\n _mergeRuleCategories(cfg, srcDefaults, 'L2_rules');\n _mergeSkillCategories(cfg, srcDefaults, 'L3_skills');\n _mergeAgentRules(cfg, srcDefaults);\n return cfg;\n}\n\n/** 把指定分类从 srcLayer 搬到 dstLayer(保留分类内全部内容,按指纹去重合并)。 */\nfunction _migrateCategoriesAcrossLayers(cfg: RuntimeConfig, srcLayer: 'L1_rules' | 'L2_rules', dstLayer: 'L1_rules' | 'L2_rules', catNames: string[]): void {\n const src = (cfg as any)[srcLayer] || {};\n const dst: any = cfg[dstLayer] || (cfg[dstLayer] = {} as RuntimeConfig['L1_rules']);\n for (const catName of catNames) {\n if (!(catName in src)) continue;\n const srcCat = src[catName];\n if (!dst[catName]) {\n dst[catName] = { category_enabled: true, category_desc: '', rules: [] };\n }\n const dstCat = dst[catName];\n if (!dstCat.category_desc && srcCat.category_desc) dstCat.category_desc = srcCat.category_desc;\n if (dstCat.category_enabled === undefined) dstCat.category_enabled = srcCat.category_enabled;\n // 合并 rules:dst 已有的按指纹保留,src 独有的追加\n if (srcCat.rules && srcCat.rules.length > 0) {\n const dstFps = new Set((dstCat.rules || []).map((r: any) => _ruleFingerprint(r)));\n for (const r of srcCat.rules) {\n const fp = _ruleFingerprint(r);\n if (!dstFps.has(fp)) {\n (dstCat.rules = dstCat.rules || []).push(r);\n dstFps.add(fp);\n }\n }\n }\n delete src[catName];\n }\n}\n\n// ==================== Query 补齐 ====================\n\nexport function getEnabledL1InjectionKeywords(runtime: RuntimeConfig): { keyword: string; risk_level: string; lang: string }[] {\n const cat = runtime.L1_rules?.injection_detection || { category_enabled: true, rules: [] };\n return filterEnabledRules(cat.rules || [], cat.category_enabled).map(r => ({\n keyword: r.keyword || '', risk_level: r.risk_level || '', lang: r.lang || 'en',\n }));\n}\n\nexport function getEnabledL2IntentPatterns(runtime: RuntimeConfig): { intent_keywords: string[]; dangerous_actions: string[]; reason: string }[] {\n const cat = runtime.L2_rules?.intent_consistency || { category_enabled: true, rules: [] };\n return filterEnabledRules(cat.rules || [], cat.category_enabled).map(r => ({\n intent_keywords: r.intent_keywords || [], dangerous_actions: r.dangerous_actions || [], reason: r.reason || '',\n }));\n}\n\nexport function getEnabledL2PasswordPatterns(runtime: RuntimeConfig): string[] {\n const cat = runtime.L2_rules?.password_modify_consent || { category_enabled: true, rules: [] };\n return filterEnabledRules(cat.rules || [], cat.category_enabled).map(r => r.pattern || '');\n}\n\nexport function getEnabledL2UserDeletionPatterns(runtime: RuntimeConfig): string[] {\n const cat = runtime.L2_rules?.user_deletion_consent || { category_enabled: true, rules: [] };\n return filterEnabledRules(cat.rules || [], cat.category_enabled).map(r => r.pattern || '');\n}\n\nexport function isL2CategoryEnabled(runtime: RuntimeConfig, categoryKey: string): boolean {\n const cat = runtime.L2_rules?.[categoryKey as keyof typeof runtime.L2_rules] as Category | undefined;\n return cat?.category_enabled ?? true;\n}\n\n/** 所有被禁用的 skill id(整分类禁用→该分类所有 skill,或单条 enabled=false) */\nexport function getDisabledSkillIds(runtime: RuntimeConfig): Set<string> {\n const disabled = new Set<string>();\n for (const catData of Object.values(runtime.L3_skills || {})) {\n if (!catData.category_enabled) {\n for (const s of (catData.skills || [])) disabled.add(s.id);\n } else {\n for (const s of (catData.skills || [])) {\n if (s.enabled === false) disabled.add(s.id);\n }\n }\n }\n return disabled;\n}\n\n// ==================== _or_default 回退系列 ====================\n// runtime 规则非空→用 runtime;为空且文件不存在→回退 source defaults;\n// 为空但文件存在(用户主动禁用)→返回空。与 py 语义对齐。\n\nexport function getEnabledL1CommandPatternsOrDefault(runtime: RuntimeConfig): Rule[] {\n const enabled = getEnabledL1CommandPatterns(runtime) as unknown as Rule[];\n if (enabled.length) return enabled;\n if (!hasRuntimeConfig()) return _l1CommandPatternsToRules();\n return [];\n}\nexport function getEnabledL1InjectionKeywordsOrDefault(runtime: RuntimeConfig): Rule[] {\n const enabled = getEnabledL1InjectionKeywords(runtime) as unknown as Rule[];\n if (enabled.length) return enabled;\n if (!hasRuntimeConfig()) return _l1InjectionKeywordsToRules();\n return [];\n}\nexport function getEnabledL2SensitivePathsOrDefault(runtime: RuntimeConfig): Rule[] {\n const enabled = getEnabledL2SensitivePaths(runtime) as unknown as Rule[];\n if (enabled.length) return enabled;\n if (!hasRuntimeConfig()) return _l2SensitivePathsToRules();\n return [];\n}\nexport function getEnabledL2IntentPatternsOrDefault(runtime: RuntimeConfig): Rule[] {\n const enabled = getEnabledL2IntentPatterns(runtime) as unknown as Rule[];\n if (enabled.length) return enabled;\n if (!hasRuntimeConfig()) return _l2IntentPatternsToRules();\n return [];\n}\nexport function getEnabledL2PasswordPatternsOrDefault(runtime: RuntimeConfig): string[] {\n const enabled = getEnabledL2PasswordPatterns(runtime);\n if (enabled.length) return enabled;\n if (!hasRuntimeConfig()) {\n return PASSWORD_MODIFY_PATTERNS.map((p) => p.source);\n }\n return [];\n}\nexport function getEnabledL2UserDeletionPatternsOrDefault(runtime: RuntimeConfig): string[] {\n const enabled = getEnabledL2UserDeletionPatterns(runtime);\n if (enabled.length) return enabled;\n if (!hasRuntimeConfig()) {\n return USER_DELETION_PATTERNS.map((p) => p.source);\n }\n return [];\n}\n\n// ==================== CRUD / update ====================\n\nconst SKILL_ID_RE = /^[A-Za-z0-9_-]+$/;\nfunction _validateSkillId(skillId: string): void {\n if (!skillId || !SKILL_ID_RE.test(skillId)) {\n throw new Error(`skill_id '${skillId}' 不合法:只允许字母、数字、下划线和连字符`);\n }\n}\n\nexport function updateLayerEnabled(layerKey: string, enabled: boolean): RuntimeConfig {\n const runtime = loadRuntimeConfig();\n (runtime.layers as any)[layerKey] = enabled;\n saveRuntimeConfig(runtime);\n return runtime;\n}\n\nexport function updateRuleEnabled(layer: 'L1_rules' | 'L2_rules', category: string, ruleId: string, enabled: boolean): RuntimeConfig {\n const runtime = loadRuntimeConfig();\n for (const r of (runtime[layer]?.[category]?.rules || [])) {\n if (r.id === ruleId) { r.enabled = enabled; break; }\n }\n saveRuntimeConfig(runtime);\n return runtime;\n}\n\nexport function updateRuleDenyMode(layer: 'L1_rules' | 'L2_rules', category: string, ruleId: string, denyMode: string): RuntimeConfig {\n const runtime = loadRuntimeConfig();\n for (const r of (runtime[layer]?.[category]?.rules || [])) {\n if (r.id === ruleId) { r.deny_mode = denyMode; _syncDenyModeFields(r); break; }\n }\n saveRuntimeConfig(runtime);\n return runtime;\n}\n\nexport function updateRuleSkipL3(layer: 'L1_rules' | 'L2_rules', category: string, ruleId: string, skipL3: boolean): RuntimeConfig {\n const runtime = loadRuntimeConfig();\n for (const r of (runtime[layer]?.[category]?.rules || [])) {\n if (r.id === ruleId) { r.skip_l3_on_disabled = skipL3; break; }\n }\n saveRuntimeConfig(runtime);\n return runtime;\n}\n\nexport function updateCategoryEnabled(layer: 'L1_rules' | 'L2_rules', category: string, enabled: boolean): RuntimeConfig {\n const runtime = loadRuntimeConfig();\n const cat = runtime[layer]?.[category];\n if (cat) cat.category_enabled = enabled;\n saveRuntimeConfig(runtime);\n return runtime;\n}\n\nexport function addCustomRule(layer: 'L1_rules' | 'L2_rules', category: string, rule: Partial<Rule>): RuntimeConfig {\n const runtime = loadRuntimeConfig();\n const layerObj = runtime[layer] || (runtime[layer] = {} as Record<string, Category>);\n const cat = layerObj[category] || (layerObj[category] = { category_enabled: true, category_desc: '', rules: [] });\n const rules = cat.rules || (cat.rules = []);\n const newRule: Rule = { ...rule, builtin: false, enabled: true } as Rule;\n if (!newRule.id) {\n newRule.id = `custom_${Date.now()}_${_slugify(JSON.stringify(rule).slice(0, 30))}`;\n }\n if (newRule.deny_mode) _syncDenyModeFields(newRule);\n rules.push(newRule);\n saveRuntimeConfig(runtime);\n return runtime;\n}\n\nexport function deleteCustomRule(layer: 'L1_rules' | 'L2_rules', category: string, ruleId: string): RuntimeConfig | null {\n // 允许删:用户自定义(builtin=false)+ 已移除的(builtin=true 但 source_removed=true)。\n // 活跃 builtin 规则不允许删(用 enabled 开关)。\n const runtime = loadRuntimeConfig();\n const rules = runtime[layer]?.[category]?.rules || [];\n const idx = rules.findIndex(r => r.id === ruleId);\n if (idx >= 0) {\n const r = rules[idx];\n if (r.builtin && !r.source_removed) return null; // 活跃 builtin 不允许删\n rules.splice(idx, 1);\n saveRuntimeConfig(runtime);\n }\n return runtime;\n}\n\nexport function addCustomSkill(skillId: string, category: string, keywords: string[], content: string): RuntimeConfig {\n _validateSkillId(skillId);\n const runtime = loadRuntimeConfig();\n const skillsDir = join(RUNTIME_CONFIG_DIR, 'agent_moss_skills');\n try { mkdirSync(skillsDir, { recursive: true }); } catch { /* 已存在 */ }\n writeFileSync(join(skillsDir, `${skillId}.md`), content, 'utf-8');\n const l3 = runtime.L3_skills || (runtime.L3_skills = {});\n const cat = l3[category] || (l3[category] = { category_enabled: true, category_desc: '', skills: [] });\n (cat.skills || (cat.skills = [])).push({ id: skillId, keywords, enabled: true, builtin: false });\n saveRuntimeConfig(runtime);\n return runtime;\n}\n\nexport function deleteCustomSkill(skillId: string, category: string): RuntimeConfig | null {\n _validateSkillId(skillId);\n const runtime = loadRuntimeConfig();\n const skills = runtime.L3_skills?.[category]?.skills || [];\n const idx = skills.findIndex(s => s.id === skillId);\n if (idx >= 0) {\n if (skills[idx].builtin) return null;\n skills.splice(idx, 1);\n const skillPath = join(RUNTIME_CONFIG_DIR, 'agent_moss_skills', `${skillId}.md`);\n try { if (existsSync(skillPath)) unlinkSync(skillPath); } catch { /* ignore */ }\n saveRuntimeConfig(runtime);\n }\n return runtime;\n}\n\nexport function updateSkillEnabled(skillId: string, enabled: boolean): RuntimeConfig {\n const runtime = loadRuntimeConfig();\n for (const catData of Object.values(runtime.L3_skills || {})) {\n for (const s of (catData.skills || [])) {\n if (s.id === skillId) { s.enabled = enabled; break; }\n }\n }\n saveRuntimeConfig(runtime);\n return runtime;\n}\n\nexport function updateSkillCategoryEnabled(category: string, enabled: boolean): RuntimeConfig {\n const runtime = loadRuntimeConfig();\n const cat = runtime.L3_skills?.[category];\n if (cat) cat.category_enabled = enabled;\n saveRuntimeConfig(runtime);\n return runtime;\n}\n\nexport function getProfileOrDetect(): null {\n // TS 不走 OSProfile(规则集硬编码常量),此函数仅为 py API 对齐保留,返回 null。\n return null;\n}\n\n// ==================== agent 定制规则(runtime_config 统一治理)====================\n\nexport function getAgentRules(runtime: RuntimeConfig): Record<string, Record<string, Category>> {\n return runtime.agent_rules || {};\n}\n\nfunction _agentCategoryEnabledRules(cat: Category | undefined): Rule[] {\n if (!cat || cat.category_enabled === false) return [];\n return (cat.rules || []).filter(r => r.enabled !== false);\n}\n\n/** 从 runtime_config 的 agent_rules[agent_id] 构造 AgentExtensions(应用 enabled 过滤)。\n * 供 getAgentExtensions 在 hasRuntimeConfig() 时调用。无该 agent 分区返回 null。 */\nexport function getEnabledAgentExtensions(runtime: RuntimeConfig, agentId: string): AgentExtensions | null {\n const agentData = runtime.agent_rules?.[agentId];\n if (!agentData) return null;\n const safeAction = _agentCategoryEnabledRules(agentData.builtin_safe_action_types);\n const safeSkills = _agentCategoryEnabledRules(agentData.builtin_safe_skills);\n const cmdPatterns = _agentCategoryEnabledRules(agentData.extra_command_patterns)\n .filter(r => r.pattern).map(r => ({\n pattern: r.pattern!, risk_level: r.risk_level || '',\n risk_type: r.risk_type || '', reason: r.reason || '',\n }));\n const injKeywords = _agentCategoryEnabledRules(agentData.extra_injection_keywords)\n .filter(r => r.keyword).map(r => ({\n keyword: r.keyword!, risk_level: r.risk_level || '', lang: r.lang || 'en',\n }));\n const sensitivePaths = _agentCategoryEnabledRules(agentData.extra_sensitive_paths)\n .filter(r => r.path).map(r => ({\n path: r.path!, risk_level: r.risk_level || '', desc: r.desc || '',\n credential: r.credential, read_only: r.read_only, deny_mode: r.deny_mode,\n }));\n return {\n agent_id: agentId,\n description: '',\n extra_command_patterns: cmdPatterns,\n extra_injection_keywords: injKeywords,\n extra_sensitive_paths: sensitivePaths,\n builtin_safe_skills: safeSkills.filter(r => r.value).map(r => r.value!),\n builtin_safe_action_types: safeAction.filter(r => r.value).map(r => r.value!),\n extra_skills: [],\n };\n}\n\nexport function updateAgentRuleEnabled(agentId: string, category: string, ruleFp: Partial<Rule>, enabled: boolean): RuntimeConfig {\n const runtime = loadRuntimeConfig();\n const cat = runtime.agent_rules?.[agentId]?.[category];\n if (cat) {\n const targetFp = _ruleFingerprint(ruleFp);\n for (const r of (cat.rules || [])) {\n if (_ruleFingerprint(r) === targetFp) { r.enabled = enabled; break; }\n }\n }\n saveRuntimeConfig(runtime);\n return runtime;\n}\n\nexport function addAgentRule(agentId: string, category: string, rule: Record<string, unknown>): RuntimeConfig {\n const runtime = loadRuntimeConfig();\n if (!runtime.agent_rules) runtime.agent_rules = {};\n if (!runtime.agent_rules[agentId]) runtime.agent_rules[agentId] = {};\n const cats = runtime.agent_rules[agentId];\n if (!cats[category]) cats[category] = { category_enabled: true, category_desc: '', rules: [] };\n (cats[category].rules || (cats[category].rules = [])).push({ ...rule, enabled: true, builtin: false } as Rule);\n saveRuntimeConfig(runtime);\n return runtime;\n}\n\nexport function deleteAgentRule(agentId: string, category: string, ruleFp: Partial<Rule>): RuntimeConfig {\n const runtime = loadRuntimeConfig();\n const cat = runtime.agent_rules?.[agentId]?.[category];\n if (cat) {\n const targetFp = _ruleFingerprint(ruleFp);\n cat.rules = (cat.rules || []).filter(r => _ruleFingerprint(r) !== targetFp);\n }\n saveRuntimeConfig(runtime);\n return runtime;\n}\n\n/** 切换某 agent 某类别的 category_enabled(整类开关,与通用规则分类开关同范式)。 */\nexport function updateAgentCategoryEnabled(agentId: string, category: string, enabled: boolean): RuntimeConfig {\n const runtime = loadRuntimeConfig();\n const cat = runtime.agent_rules?.[agentId]?.[category];\n if (cat) cat.category_enabled = enabled;\n saveRuntimeConfig(runtime);\n return runtime;\n}\n","/**\n * 三方 agent 定制化注册中心 — TypeScript 加载器\n *\n * 按 `agentId` 加载该 agent 的专属规则集(JSON 单一事实源)。\n * 规则文件位置:`agent_moss/agents/<agentId>/rules.json`\n *\n * 与 Python `agent_moss/agents/__init__.py:get_agent_extensions` 一一对应。\n * 两端共享同一份 rules.json。\n *\n * 路径解析:\n * - prod(dist/cli.js):copy-assets.cjs 复制 rules.json 到 dist/agents/<id>/rules.json\n * - dev(tsx src/cli.ts):从 ts/src/agents/ 出发,回退到 ../../../agent_moss/agents\n *\n * 缓存:首次加载后缓存在 Map 中,clearAgentExtensionsCache 清空(测试用)。\n */\n\nimport { readFileSync, existsSync } from 'fs';\nimport { resolve, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport type { AgentExtensions } from './types';\n\nexport type { AgentExtensions } from './types';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n// 优先用 dist 内联目录(prod,copy-assets.cjs 复制后);\n// 缺失时回退到仓库根 agent_moss/agents(dev)。\n// 注意:从 ts/src/agents/ 出发,仓库根 agent_moss/agents 在 ../../../agent_moss/agents。\nconst AGENTS_DIR_PROD = resolve(__dirname, 'agents');\nconst AGENTS_DIR_DEV_FALLBACK = resolve(__dirname, '../../../agent_moss/agents');\n\nconst cache = new Map<string, AgentExtensions | null>();\n\nexport function resolveAgentsDir(): string {\n if (existsSync(AGENTS_DIR_PROD)) return AGENTS_DIR_PROD;\n if (existsSync(AGENTS_DIR_DEV_FALLBACK)) return AGENTS_DIR_DEV_FALLBACK;\n return AGENTS_DIR_PROD; // 不存在时也返回 prod 路径,让后续 existsSync 检查返回 false\n}\n\n/**\n * 按 agentId 加载该 agent 的专属规则集。\n *\n * @param agentId 调用方 agent 标识,如 \"xiaoo\" / \"opencode\" / \"opendesk\"。\n * 空字符串返回 null(通用模式)。\n * @returns AgentExtensions 实例,或 null(无 agent 专属规则 / rules.json 不存在 / 解析失败)\n */\nexport function getAgentExtensions(agentId: string): AgentExtensions | null {\n if (!agentId) return null;\n if (cache.has(agentId)) return cache.get(agentId) ?? null;\n\n let ext: AgentExtensions | null = null;\n // 统一存储:优先读 runtime_config 的 agent_rules 分区(用户可在 console\n // 查看/编辑/禁用/新增,享受与通用规则一致的合并升级)。回退 rules.json\n // (无 runtime_config 时,如直接起服务未 seed、或旧部署)。\n try {\n const { hasRuntimeConfig, loadRuntimeConfig, getEnabledAgentExtensions } = require('../infra/runtime-config');\n if (hasRuntimeConfig()) {\n ext = getEnabledAgentExtensions(loadRuntimeConfig(), agentId);\n }\n } catch { /* runtime-config 不可用时回退 rules.json */ }\n\n if (ext === null) {\n const agentsDir = resolveAgentsDir();\n const rulesFile = resolve(agentsDir, agentId, 'rules.json');\n if (!existsSync(rulesFile)) {\n cache.set(agentId, null);\n return null;\n }\n try {\n const raw = readFileSync(rulesFile, 'utf-8');\n ext = JSON.parse(raw) as AgentExtensions;\n if (!ext.agent_id) {\n console.warn(`[AgentMoss agents] rules.json 缺少 agent_id 字段: ${rulesFile}`);\n cache.set(agentId, null);\n return null;\n }\n } catch (e) {\n console.error(`[AgentMoss agents] 加载 agent ${agentId} rules.json 失败:`, (e as Error).message);\n cache.set(agentId, null);\n return null;\n }\n }\n\n cache.set(agentId, ext);\n console.log(\n `[AgentMoss agents] 加载 agent ${agentId} 定制规则: ` +\n `${ext.extra_command_patterns?.length ?? 0} cmd patterns, ` +\n `${ext.extra_injection_keywords?.length ?? 0} injection keywords, ` +\n `${ext.extra_sensitive_paths?.length ?? 0} sensitive paths, ` +\n `${ext.builtin_safe_skills?.length ?? 0} builtin safe skills, ` +\n `${ext.builtin_safe_action_types?.length ?? 0} builtin safe action types`\n );\n return ext;\n}\n\n/**\n * 清空 agent 扩展缓存(用于测试或 rules.json 热加载)。\n */\nexport function clearAgentExtensionsCache(): void {\n cache.clear();\n}\n","import { SecurityJudgment, HeuristicResult } from './types';\nimport type { AnalysisInput } from './coordinator';\nimport { getCustomRules } from '../config';\nimport { getAgentExtensions } from '../agents';\nimport type { CommandPattern, InjectionKeyword } from '../agents/types';\nimport { loadL1 } from '../infra/rules-loader';\nimport {\n ROOT_SENSITIVE_PATHS,\n HOME_SENSITIVE_PATHS,\n CREDENTIAL_PATHS,\n isWriteOperation,\n} from './logic-rules';\n\n/**\n * Layer 1: Feature-matching static detection.\n * Uses regex patterns to detect dangerous commands, user-defined rules,\n * and prompt injection keywords.\n * Runs in < 1ms, no LLM cost.\n */\n\n// Prompt injection keywords (synced with Python linux.py _DEFAULT_INJECTION_KEYWORDS)\nexport const INJECTION_KEYWORDS: { keyword: string; riskLevel: string; lang: string }[] = (() => {\n // 归一化自 agent_moss/rules/l1_rules.json 的注入段(单一事实源,与 Python 共用)。\n const kws = (loadL1().injection_detection || []) as any[];\n return kws.map((k) => ({\n keyword: k.keyword,\n riskLevel: k.risk_level,\n lang: k.lang || 'en',\n }));\n})();\n\n// High-risk command patterns (unified Python + TS, all case-insensitive)\nexport const DANGEROUS_PATTERNS: { pattern: RegExp; severity: string; description: string; riskType: string }[] = (() => {\n // 归一化自 agent_moss/rules/l1_rules.json 的危险命令段(单一事实源,与 Python 共用)。\n const cmds = (loadL1().dangerous_commands || []) as any[];\n return cmds.map((c) => ({\n pattern: new RegExp(c.pattern, 'i'),\n severity: c.risk_level,\n riskType: c.risk_type,\n description: c.reason,\n }));\n})();\n\nexport function runHeuristicCheck(input: AnalysisInput): SecurityJudgment | null {\n const command = `${input.aNext.actionType}: ${input.aNext.actionDetail}`;\n const matched: string[] = [];\n let highestSeverity = 'low';\n let highestRiskType = '';\n\n // Check user-defined custom rules first(对齐 Python UserRuleMatcher 命中即短路返回,\n // 不让后续 CommandPatternScanner/SensitivePathChecker 叠加取最高遮蔽 user rules 的判定)。\n const userRules = getCustomRules();\n for (const rule of userRules) {\n try {\n const re = new RegExp(rule.pattern);\n if (re.test(command)) {\n if (rule.action === 'Deny') {\n return {\n allowed: false,\n reason: `命中用户敏感动作规则: ${rule.description || rule.pattern}`,\n riskLevel: rule.severity as SecurityJudgment['riskLevel'],\n riskType: 'sensitive_action',\n confidence: 90,\n source: 'heuristic',\n violatedLayers: ['1.1'],\n };\n }\n // Allow rules just pass through\n }\n } catch { /* invalid regex, skip */ }\n }\n\n // Check built-in dangerous patterns\n // NEW-FP-I: echo/printf 引号内参数是字面量非真实命令,剥掉引号内容后再匹配,\n // 避免 echo \"rm -rf /tmp\" 的输出文本被当真实命令误报。引号外的重定向 > 和管道 |\n // 后的真实操作保留(echo \"x\" > /etc/passwd 仍被 >/etc/ 检测,echo pass | passwd\n // 的 passwd 仍被匹配)。非 echo/printf 段(rm -rf; echo done 的 rm 段)不剥。\n const scanDetail = normalizePathSegments(stripLiteralTextSegments(input.aNext.actionDetail));\n const scanCommand = `${input.aNext.actionType}: ${scanDetail}`;\n let topRiskType = '';\n for (const rule of DANGEROUS_PATTERNS) {\n if (rule.pattern.test(scanCommand)) {\n matched.push(rule.description);\n if (severityRank(rule.severity) > severityRank(highestSeverity)) {\n highestSeverity = rule.severity;\n topRiskType = rule.riskType;\n }\n }\n }\n highestRiskType = topRiskType || highestRiskType;\n\n // Check agent-specific extra command patterns (追加在通用规则之后)\n const agentExt = getAgentExtensions(input.agentId);\n if (agentExt?.extra_command_patterns) {\n for (const rule of agentExt.extra_command_patterns) {\n try {\n const re = new RegExp(rule.pattern, 'i');\n if (re.test(scanCommand)) {\n matched.push(`agent 专属规则: ${rule.reason}`);\n if (severityRank(rule.risk_level) > severityRank(highestSeverity)) {\n highestSeverity = rule.risk_level;\n highestRiskType = rule.risk_type;\n }\n }\n } catch { /* invalid regex, skip */ }\n }\n }\n\n // Check prompt injection keywords (通用 + agent_ext.extra_injection_keywords)\n // 搜索/查询类工具(search-WebSearch 等)的 actionDetail 是查询参数(数据载荷),\n // 不是指令。注入检测只针对指令性文本(用户 prompt / reason / 命令),\n // 排除搜索工具的 actionDetail,避免 \"搜索 jailbreak\" 等被误判为注入攻击。\n const injectionText = isSearchActionType(input.aNext.actionType)\n ? `${input.aNext.actionType} ${input.reason || ''} ${input.promptSession || ''}`.toLowerCase()\n : `${input.aNext.actionType} ${input.aNext.actionDetail} ${input.reason || ''} ${input.promptSession || ''}`.toLowerCase();\n const injectionHits = checkInjectionKeywords(injectionText, agentExt?.extra_injection_keywords);\n if (injectionHits.length > 0) {\n const topHit = injectionHits.reduce((a, b) => severityRank(a.riskLevel) >= severityRank(b.riskLevel) ? a : b);\n matched.push(...injectionHits.map(h => `注入关键词 [${h.lang}]: ${h.keyword}`));\n if (severityRank(topHit.riskLevel) > severityRank(highestSeverity)) {\n highestSeverity = topHit.riskLevel;\n highestRiskType = 'prompt_injection';\n }\n }\n\n // ===== 从 L2 搬入的静态子检测器(只看 a_next)=====\n const actionTypeL = input.aNext.actionType.toLowerCase();\n const detailL = input.aNext.actionDetail.toLowerCase();\n const isExcludedType = SENSITIVE_EXCLUDED_PREFIXES.some(p => actionTypeL.startsWith(p));\n\n // 危险操作模式检测优先(对应 Python CommandPatternScanner 第2检测器,先于 SensitivePathChecker):\n // 含 > /etc/ > /boot/ 重定向覆盖 critical——echo >> /etc/passwd 命中 critical 短路,\n // 不走后面的 checkSensitivePath high(对齐 Python ground truth)。\n const dangerousResult = checkDangerousPatterns(actionTypeL, detailL);\n if (dangerousResult) return dangerousResult;\n\n // 敏感路径访问检测:deny_both/deny_read/deny_write + 凭据边界匹配。\n // 排除 memory-/skill- 等非文件工具前缀,避免参数关键词误报。\n if (!isExcludedType) {\n const pathResult = checkSensitivePath(detailL, input.cwd || '/', agentExt);\n if (pathResult) return pathResult;\n }\n\n // 用户敏感规则命中(custom_rule)须先于敏感路径和横向移动检测:\n // - 避免 ssh -o StrictHostKeyChecking=no 被 checkLateralMovement 标 lateral medium 遮蔽\n // (Python UserRuleMatcher 先于 LateralMovementChecker)。\n // - 避免 ssh ... 'cat /etc/shadow' 被 checkSensitivePath 的 /etc/shadow critical 遮蔽\n // (Python UserRuleMatcher 先于 SensitivePathChecker,user rules high 优先于敏感路径 critical)。\n if (matched.length > 0) {\n return {\n allowed: false,\n reason: `检测到高危操作: ${matched.join(', ')}`,\n riskLevel: highestSeverity as SecurityJudgment['riskLevel'],\n riskType: highestRiskType,\n confidence: 95,\n source: 'heuristic',\n violatedLayers: ['1.1'], // 对齐 py coordinator.py:165(L1.1 = 命中高危命令模式/注入关键词)\n };\n }\n\n // 横向移动检测:ssh/scp/rsync 到非本机主机\n const lateralResult = checkLateralMovement(detailL);\n if (lateralResult) return lateralResult;\n\n return null; // No match, pass to next layer\n}\n\nfunction checkInjectionKeywords(\n text: string,\n extraKeywords?: InjectionKeyword[],\n): { keyword: string; riskLevel: string; lang: string }[] {\n const hits: { keyword: string; riskLevel: string; lang: string }[] = [];\n for (const entry of INJECTION_KEYWORDS) {\n if (text.includes(entry.keyword.toLowerCase())) {\n hits.push(entry);\n }\n }\n // agent 专属注入关键词(追加在后)\n if (extraKeywords) {\n for (const entry of extraKeywords) {\n if (text.includes(entry.keyword.toLowerCase())) {\n hits.push({ keyword: entry.keyword, riskLevel: entry.risk_level, lang: entry.lang });\n }\n }\n }\n return hits;\n}\n\nexport function isInlineScriptCommand(actionDetail: string): boolean {\n // 判断命令是否为内联脚本解释器命令(python -c, perl -e, php -r 等)\n const re = /(?:^|\\s)(?:python|python3|python3\\.\\d+|perl|perl5|ruby|jruby|mruby|node|php|lua)\\s+(?:-[a-zA-Z]*[cer][a-zA-Z]*\\s+)/i;\n return re.test(actionDetail);\n}\n\n/**\n * NEW-FP-I: 对首词 echo/printf 的命令段剥掉引号内容(字面量参数)。\n *\n * echo/printf 是文本输出命令,其引号内参数是被打印的字面量而非真实命令——\n * `echo \"rm -rf /tmp\"` 是打印这串文本不是执行删除。但 DANGEROUS_PATTERNS 旧实现\n * 对整个 actionDetail 做正则匹配,引号内的 rm/chmod/mkfs 等危险命令模式被误当\n * 真实命令匹配 → 误报(NEW-FP-I)。\n *\n * 修复:按 &&/||/;/换行 分段,首词是 echo/printf 的段,剥掉引号内容(字面量),\n * 保留引号外的重定向 >/>> 和管道 | 后的真实操作:\n * - `echo \"rm -rf /tmp\"` → `echo `(rm 模式不匹配,误报消除)\n * - `echo \"x\" > /etc/passwd` → `echo > /etc/passwd`(重定向 >/etc/ 仍匹配,真实写不漏报)\n * - `rm -rf /tmp; echo done` → rm 段不剥,echo 段剥,rm 仍匹配(真实危险不漏报)\n * - `echo pass | passwd` → passwd 无引号在管道后,剥后仍保留(管道注入不漏报)\n */\nexport function stripLiteralTextSegments(actionDetail: string): string {\n // 旁路(NEW-FN-H 待修):含\"写脚本 + 后续执行\"或\"管道喂解释器\"绕过链时整条不剥离。\n // 保留引号内路径让 L1 凭据检测兜底,避免剥离后绕过链漏检(inline-09/10 依赖)。\n // - inline-09: echo \"cat /etc/shadow\" > /tmp/x.sh && bash /tmp/x.sh(写脚本+执行)\n // - inline-10: printf 'cat /etc/shadow' | bash(管道喂解释器)\n const writeScriptExec = />\\s*[/~]\\S*\\.(sh|py|pl|rb)\\b/.test(actionDetail) &&\n /(?:&&|\\|\\||;|\\n|\\|)\\s*(?:bash|sh|zsh|dash|python|perl|ruby|node)/.test(actionDetail);\n const pipeToInterpreter = /\\|\\s*(?:bash|sh|zsh|dash|python|perl|ruby|node)\\b/.test(actionDetail);\n if (writeScriptExec || pipeToInterpreter) {\n return actionDetail;\n }\n // 按命令分隔符分段,但跳过引号内的分隔符(echo \"a; b\" 的 ; 在引号内不分段)\n const resultParts: string[] = [];\n for (const seg of splitCommandSegments(actionDetail)) {\n const fw = (seg.trim().split(/\\s+/)[0] || '').toLowerCase();\n if (fw === 'echo' || fw === 'printf') {\n // 先摘重定向目标的引号路径为裸路径(保留真实写目标),再剥剩余引号内容\n const segUnquotedRedirect = seg.replace(\n />{1,2}\\s*(['\"])([~./][^'\"]+)\\1/g,\n (_m, _q, p: string) => '>' + p,\n );\n resultParts.push(segUnquotedRedirect.replace(/'[^']*'|\"[^\"]*\"/g, ''));\n } else {\n resultParts.push(seg);\n }\n }\n return resultParts.join('');\n}\n\n/**\n * 剥离 heredoc 文档字面量内容(<<EOF ... EOF / <<'EOF' ... EOF)。\n * heredoc 是文档正文不是命令,其中的 `*`/`?`/`rm`/`删除` 是文本而非删除操作。\n * 不剥离会导致 checkDangerousPatterns 的「通配符+删除」误判写文档为批量删除\n * (NEW-FP:写含 markdown 加粗 / 三元表达式 / 描述含 rm 的周报即误报)。\n * 支持 <<EOF / <<-EOF / <<'EOF' / <<\"EOF\",匹配到行首结束标记,替换为 <<heredoc>>。\n */\nexport function stripHeredocContent(actionDetail: string): string {\n return actionDetail.replace(\n /<<-?\\s*(?:['\"]?)([A-Za-z_][A-Za-z0-9_]*)(?:['\"]?)[^\\n]*\\n[\\s\\S]*?\\n\\s*\\1\\s*(?:\\n|$)/g,\n '<<heredoc>>\\n',\n );\n}\n\n/**\n * NORM-PATH: 折叠路径混淆段,堵路径穿越变体(对齐 Python _normalize_path_segments,\n * 对应 CVE-2023-37274 攻击面)。\n *\n * 敏感路径/危险命令匹配前,把「路径混淆」归一回真实路径,避免子串/正则漏检:\n * - 连续斜杠 `//` → `/`(`cat /etc//shadow` 与 `cat /etc/shadow` 等价,应同判)\n * - 单点段 `/./` → `/`(`cat /etc/./shadow` 同理)\n *\n * 不做 `..` 解析(`..` 可能改变路径语义,且现有 dangerous pattern 已对 `..`\n * 穿越有兜底),只折叠无歧义的 `//` 与 `/./`,避免过度归一化误伤。\n *\n * 约束(must not break):\n * 1. 跳过协议 URL 的 `//`(`curl http://x` 的 `http://` 是协议分隔,折叠成\n * `http:/x` 会破坏 curl 下载/管道检测)。\n * 2. 跳过引号内字面量(`grep \"a//b\"` 引号内是搜索模式非路径)。\n */\nexport function normalizePathSegments(text: string): string {\n // 1. 保护协议 URL 的 //(用不含 / 的令牌占位,避免被 /{2,} 折叠)\n const protTokens: string[] = [];\n let t = text.replace(/\\b(https?|ftp|file):\\/\\//gi, (m) => {\n const scheme = m.slice(0, m.indexOf(':'));\n protTokens.push('://');\n return `${scheme}__PROT${protTokens.length - 1}__`;\n });\n // 2. 保护引号内内容(非路径字面量不折叠)\n const quoteTokens: string[] = [];\n t = t.replace(/'[^']*'|\"[^\"]*\"/g, (m) => {\n quoteTokens.push(m);\n return `__Q${quoteTokens.length - 1}__`;\n });\n // 3. 折叠引号外 + 非 URL 的连续斜杠与单点段\n t = t.replace(/\\/{2,}/g, '/');\n t = t.replace(/\\/\\.\\//g, '/');\n // 4. 还原引号与协议\n for (let i = 0; i < quoteTokens.length; i++) {\n t = t.replace(`__Q${i}__`, quoteTokens[i]);\n }\n for (let i = 0; i < protTokens.length; i++) {\n t = t.replace(`__PROT${i}__`, protTokens[i]);\n }\n return t;\n}\n\n/**\n * 按命令分隔符分段,跳过引号内的分隔符(对齐 Python _split_command_segments)。\n * echo \"a; b && c\" 的引号内分隔符是字面量非命令分隔,不能分段——否则\n * 引号内 chmod/mkfs 等词会脱离 echo 段被当独立命令首词误匹配(NEW-FP-I)。\n */\nfunction splitCommandSegments(actionDetail: string): string[] {\n const segments: string[] = [];\n let cur = '';\n let quote: string | null = null;\n for (let i = 0; i < actionDetail.length; i++) {\n const ch = actionDetail[i];\n if (quote) {\n cur += ch;\n if (ch === quote) quote = null;\n continue;\n }\n if (ch === \"'\" || ch === '\"') {\n quote = ch;\n cur += ch;\n continue;\n }\n if (ch === ';' || ch === '\\n') {\n segments.push(cur); segments.push(ch); cur = '';\n continue;\n }\n if (ch === '&' && actionDetail[i + 1] === '&') {\n segments.push(cur); segments.push('&&'); cur = '';\n i++; continue;\n }\n if (ch === '|' && actionDetail[i + 1] === '|') {\n segments.push(cur); segments.push('||'); cur = '';\n i++; continue;\n }\n cur += ch;\n }\n if (cur) segments.push(cur);\n return segments;\n}\n\nfunction severityRank(s: string): number {\n const ranks: Record<string, number> = { low: 1, medium: 2, high: 3, critical: 4 };\n return ranks[s] || 0;\n}\n\n// ==================== 从 L2 搬入 L1 的静态子检测器 ====================\n// 以下三个检测器只看 a_next(不看 action_history),按\"L1 只看这一步\"原则\n// 从 logic-rules.ts 搬入。逻辑原样保留,source 改为 'heuristic'、\n// violatedLayers 改为 ['1.1'],对齐 L1 命令模式/注入关键词的层号。\n\n// 敏感路径检测排除的非文件工具前缀(避免 memory-searchMemory 等误报)\nconst SENSITIVE_EXCLUDED_PREFIXES = ['memory-', 'skill-', 'skill-manager-', 'mailbox-', 'app-'];\n\n// 搜索/查询类工具前缀:其 actionDetail 是「查询数据」(如 query=...),不是指令。\n// 注入关键词检测应只针对指令性文本(用户 prompt / reason / 命令),\n// 否则搜索 \"jailbreak\"、\"bypass\" 等资料会被 L1 注入检测误判为注入攻击(prompt injection 误报)。\n// 与 Python 端 agent_moss/engine/heuristic.py 的 _SEARCH_ACTION_PREFIXES 保持一致。\nconst SEARCH_ACTION_PREFIXES = ['search-', 'web-', 'browser-', 'query-', 'websearch', 'web_search'];\n\nfunction isSearchActionType(actionType: string): boolean {\n const at = actionType.toLowerCase();\n return (\n SEARCH_ACTION_PREFIXES.some((p) => at.startsWith(p)) ||\n ['websearch', 'web_search', 'search', 'query'].includes(at)\n );\n}\n\n/**\n * 敏感路径访问检测(从 L2 搬入)。\n * deny_both(凭据):无论读写都拦截,isCredential=true\n * deny_read:只拦截读取(如 /dev/random)\n * deny_write:只拦截写入/删除\n */\nexport function checkSensitivePath(\n command: string,\n cwd: string,\n agentExt?: import('../agents').AgentExtensions | null,\n): SecurityJudgment | null {\n const expandedCwd = cwd.replace(/^~/, process.env.HOME || '/home/user');\n\n // 写判定统一用 isWriteOperation(对齐 Python _is_write_operation 单一事实源),\n // 替代原手写 isWriteOpFlag(含 ''.includes(kw) 笔误、重定向逻辑矛盾)。\n // command 在此 = actionDetail 小写(调用方 :231 传 detailL),actionType 留空——\n // isWriteOperation 的 actionType.includes 走空串无影响,actionDetail 部分覆盖 command。\n const isWriteOpFlag = isWriteOperation('', command);\n\n // NEW-FP-I: echo/printf 引号内参数是字面量,其中的敏感路径不应被当真实访问。\n // 对首词 echo/printf 的段剥引号内容后再做路径匹配。非 echo/printf 段(cat \"/etc/shadow\")\n // 不剥,引号内真实路径参数仍匹配。引号外的重定向(echo \"x\" > /etc/passwd)保留。\n // NORM-PATH: 再折叠路径混淆段(//、/./),堵路径穿越变体(cat /etc//shadow 漏检)。\n const pathScanText = normalizePathSegments(stripLiteralTextSegments(command));\n\n // 边界路径匹配(对齐 Python heuristic.py:121-132,避免子串误报)。\n // 裸 command.includes(sp.path) 会把 /etc/passwd 命中到 /tmp/etc_passwd_backup、\n // /boot/ 命中到 /boot-log。改用边界正则:/ 开头路径前导用 ^|空白|/|反斜杠|引号,\n // 其余用 \\b;尾随 \\b。凭据(deny_both)尤其需要边界(如 .env 不能命中 .environment)。\n const pathMatches = (text: string, path: string): boolean => {\n // 含正则前瞻语法(如 (?!\\\\.pub) 排除公钥变体)时保留前瞻不转义,仅转义其余元字符。\n // 把路径切成「前瞻块 / 其余」分段处理,前瞻块原样保留,其余分段转义元字符。\n const parts = path.split(/(\\(\\?!.*?\\))/);\n const escaped = parts.map(part => {\n if (part.startsWith('(?!')) return part; // 前瞻块原样\n return part.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n }).join('');\n const re = path.startsWith('.') || path.startsWith('/')\n ? new RegExp(`(?:^|[\\\\s/\\\\\\\\'\"])${escaped}\\\\b`, 'i')\n : new RegExp(`\\\\b${escaped}\\\\b`, 'i');\n return re.test(text);\n };\n\n for (const sp of ROOT_SENSITIVE_PATHS) {\n if (pathMatches(pathScanText, sp.path.toLowerCase())) {\n // /dev/random:只拦截读取操作,写入/删除放行(读取可耗尽熵池导致 TLS 阻塞)\n if (sp.path === '/dev/random') {\n if (isWriteOpFlag) {\n continue; // 允许写入操作(投喂熵池)\n }\n return {\n allowed: false,\n reason: `读取敏感路径: ${sp.desc} (${sp.path})`,\n riskLevel: sp.riskLevel as SecurityJudgment['riskLevel'],\n riskType: 'file_access',\n confidence: 90,\n source: 'heuristic',\n violatedLayers: ['1.1'],\n };\n }\n // 非凭据路径:只拦截写入/删除操作,只读访问放行。\n // 凭据路径(sp.credential=true,如 /etc/shadow、SSH 私钥、AWS 凭证):\n // 读写均拦(读取凭据同样危险)。与 py deny_both 一致。\n if (!isWriteOpFlag && !sp.credential) {\n continue;\n }\n return {\n allowed: false,\n reason: `尝试访问系统敏感路径: ${sp.desc} (${sp.path})`,\n riskLevel: sp.riskLevel as SecurityJudgment['riskLevel'],\n riskType: 'file_access',\n confidence: 90,\n source: 'heuristic',\n violatedLayers: ['1.1'],\n isCredential: !!sp.credential,\n };\n }\n }\n\n for (const sp of HOME_SENSITIVE_PATHS) {\n const expanded = `${expandedCwd}/${sp.path}`;\n // 私钥路径(不以 .pub 结尾)排除公钥变体:.ssh/id_rsa 不应命中 .ssh/id_rsa.pub(公钥公开)\n const pathRe = sp.path.endsWith('.pub')\n ? new RegExp(sp.path.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'), 'i')\n : new RegExp(sp.path.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&') + '(?!\\\\.pub)', 'i');\n const expandedRe = sp.path.endsWith('.pub')\n ? new RegExp(expanded.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'), 'i')\n : new RegExp(expanded.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&') + '(?!\\\\.pub)', 'i');\n if (pathRe.test(pathScanText) || expandedRe.test(pathScanText)) {\n // 非凭据路径:只拦截写入/删除操作,只读访问放行。\n // 凭据路径(sp.credential=true,如 SSH 私钥、AWS 凭证):\n // 读写均拦(读取凭据同样危险)。与 py deny_both 一致。\n if (!isWriteOpFlag && !sp.credential) {\n continue;\n }\n return {\n allowed: false,\n reason: `尝试访问敏感路径: ${sp.desc} (${sp.path})`,\n riskLevel: sp.riskLevel as SecurityJudgment['riskLevel'],\n riskType: 'file_access',\n confidence: 90,\n source: 'heuristic',\n violatedLayers: ['1.1'],\n isCredential: !!sp.credential,\n };\n }\n }\n\n // agent 专属敏感路径(追加在通用规则之后)\n if (agentExt?.extra_sensitive_paths && agentExt.extra_sensitive_paths.length > 0) {\n for (const sp of agentExt.extra_sensitive_paths) {\n const spPath = sp.path.toLowerCase();\n const expanded = `${expandedCwd}/${spPath}`;\n if (pathMatches(command, spPath) || pathMatches(command, expanded.toLowerCase())) {\n const denyMode = sp.deny_mode || (sp.credential ? 'deny_both' : sp.read_only ? 'deny_read' : 'deny_write');\n if (denyMode === 'deny_read') {\n if (isWriteOpFlag) continue;\n } else if (denyMode === 'deny_write') {\n if (!isWriteOpFlag) continue;\n }\n // deny_both:读写均拦\n return {\n allowed: false,\n reason: `尝试访问 agent 专属敏感路径: ${sp.desc} (${sp.path})`,\n riskLevel: sp.risk_level as SecurityJudgment['riskLevel'],\n riskType: 'file_access',\n confidence: 90,\n source: 'heuristic',\n violatedLayers: ['1.1'],\n isCredential: !!sp.credential,\n };\n }\n }\n }\n\n // Credential files: always intercept regardless of read/write\n // Files starting with . need special handling since \\b doesn't match before .\n // 边界字符含引号:凭据常出现在 open('.env')、cat \".env\" 等引号上下文里\n for (const cp of CREDENTIAL_PATHS) {\n const escaped = cp.path.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const re = cp.path.startsWith('.')\n ? new RegExp(`(?:^|[\\\\s/\\\\\\\\'\"])${escaped}\\\\b`)\n : new RegExp(`\\\\b${escaped}\\\\b`);\n if (re.test(command)) {\n return {\n allowed: false,\n reason: `访问敏感路径: ${cp.desc} (${cp.path})`,\n riskLevel: cp.riskLevel as SecurityJudgment['riskLevel'],\n riskType: 'file_access',\n confidence: 90,\n source: 'heuristic',\n violatedLayers: ['1.1'],\n isCredential: true,\n };\n }\n }\n\n // Check deletion of sensitive directories\n if ((command.includes('rm ') || command.includes('unlink')) &&\n (command.includes('/etc/') || command.includes('/root/') || command.includes('/var/log/'))) {\n return {\n allowed: false,\n reason: '检测到删除关键系统目录内容',\n riskLevel: 'critical',\n riskType: 'file_access',\n confidence: 90,\n source: 'heuristic',\n violatedLayers: ['1.1'],\n };\n }\n\n return null;\n}\n\n/** 危险操作模式检测(从 L2 搬入):通配符+删除、重定向覆盖 /etc /boot /proc */\nexport function checkDangerousPatterns(actionType: string, actionDetail: string): SecurityJudgment | null {\n if (actionType === 'file_write' || actionType === 'file_edit') return null;\n\n // Wildcard + delete — 排除 /tmp 等临时目录的清理操作\n // 用边界正则匹配目录名本身(/tmp 和 /tmp/ 都算),避免 `find /tmp -delete`\n // 因 \"/tmp/\" 子串不匹配(/tmp 后是空格)而 isTempPath=false 误报(Bug6)。\n // NEW-FP(鸿蒙写周报误报):先剥离 heredoc 文档字面量内容——文档正文里的\n // `*`/`?`/`rm`/`删除` 是文本不是真实删除命令,不剥离会误判为批量删除。\n const scan = stripHeredocContent(actionDetail);\n const TEMP_DIRS = ['/tmp', '/var/tmp', '/run', '/dev/shm'];\n const isTempPath = TEMP_DIRS.some(td =>\n new RegExp(`(?:^|[\\\\s/])${td.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}(?:[\\\\s/]|$)`).test(actionDetail)\n );\n // 通配符必须紧邻删除命令(真实命令 token),而非任意位置子串。\n // 收紧:`*`/`?` 出现在删除命令(rm/del/delete/remove/删除/移除)附近——\n // 匹配「删除命令 + 通配符路径」组合,如 `rm -rf /tmp/*`、`rm *`、`find . -delete`。\n // 不再用 actionDetail.includes('*') && includes('rm') 的宽泛子串匹配,\n // 避免文档正文/heredoc/grep 模式里的字面量误报。\n const wildcardDeleteRe =\n /(?:\\brm\\b|\\b(r?mdir|del|delete|remove|rmdir|unlink)\\b|\\b删除\\b|\\b移除\\b)[\\s\\S]{0,40}?[*?]|[*?][\\s\\S]{0,40}?\\b(?:rm|del|delete|remove|rmdir|unlink)\\b|rm\\s+-[a-zA-Z]*[rf][a-zA-Z]*\\s+\\S*[*?]/i;\n if (!isTempPath && wildcardDeleteRe.test(scan)) {\n return {\n allowed: false,\n reason: '检测到通配符结合删除操作,可能造成批量误删',\n riskLevel: 'high',\n riskType: 'script_execution',\n confidence: 90,\n source: 'heuristic',\n violatedLayers: ['1.1'],\n };\n }\n // find -exec <写命令> / find | xargs <写命令> — find 在 READ_ONLY_COMMANDS 导致整段\n // 被当只读,-exec 或 | xargs 后的 chmod/cp/mv/rm/sed -i 等写命令漏检(NEW-FN-C: -exec;\n // NEW-FN-E: | xargs 等价变体未覆盖)。find 遍历出的文件被批量执行写操作,静态无法确定\n // 具体目标文件,但「find + 写命令」组合本身就是批量写意图,此处识别 -exec/-execdir/-ok\n // 后紧跟写命令、或 | xargs 后紧跟写命令即拦截。只匹配写命令首词,避免 -exec grep /\n // | xargs ls 等只读误报。xargs 后的 sed -i 单独匹配(sed -i 是 sed + -i 参数)。\n const findWriteMatch = actionDetail.match(\n /\\bfind\\b.*?(?:(?:^|\\s)-exec(?:dir)?\\s+(chmod|chown|cp|mv|rm|dd|tee|truncate|mkfs|shred|rmdir|unlink)\\b|(?:^|\\s)\\|\\s*xargs\\s+(?:sed\\s+-[a-zA-Z]*i|chmod|chown|cp|mv|rm|dd|tee|truncate|mkfs|shred|rmdir|unlink)\\b)/i\n );\n if (findWriteMatch) {\n const cmdHit = findWriteMatch[1] || 'xargs';\n return {\n allowed: false,\n reason: `检测到 find 批量执行写操作 (${cmdHit}),可能批量修改/删除文件`,\n riskLevel: 'high',\n riskType: 'script_execution',\n confidence: 90,\n source: 'heuristic',\n violatedLayers: ['1.1'],\n };\n }\n // Redirect overwrite to system directories(对齐 Python CommandPatternScanner `>\\s*/etc/` critical,不排除敏感路径)。\n // echo >> /etc/passwd、cat > /etc/ssh/sshd_config 均命中 critical 短路(Python ground truth)。\n if (/>\\s*\\/etc\\//.test(actionDetail) || />\\s*\\/boot\\//.test(actionDetail)) {\n return {\n allowed: false,\n reason: '检测到重定向覆盖写入关键系统目录',\n riskLevel: 'critical',\n riskType: 'file_access',\n confidence: 95,\n source: 'heuristic',\n violatedLayers: ['1.1'],\n };\n }\n // A16: 重定向覆盖设备文件(对齐 Python linux.py:180 `>\\s*/dev/(sd|hd|nvme|vd|loop|mem|kmsg|port|zero|random|urandom|full|core)`)。\n // high/file_access。须先于 checkSensitivePath 的 /dev/mem critical 命中,避免写 /dev/mem 被标 critical(Python 是 high)。\n if (/>\\s*\\/dev\\/(sd|hd|nvme|vd|loop|mem|kmsg|port|zero|random|urandom|full|core)/i.test(actionDetail)) {\n return {\n allowed: false,\n reason: '检测到重定向写入设备文件',\n riskLevel: 'high',\n riskType: 'file_access',\n confidence: 90,\n source: 'heuristic',\n violatedLayers: ['1.1'],\n };\n }\n return null;\n}\n\n\nfunction extractRemoteHost(command: string): string | null {\n // NEW-FN-G: 旧正则 (?:ssh|scp|rsync)\\s+(?:-[\\w]+\\s+)*(\\S+@\\S+|\\b(?!-)[\\w.-]+\\b)\n // 的 (?:-[\\w]+\\s+)* 只匹配单选项不匹配带参数值选项(-p 2222、-L 8080:...、\n // -D 1080、-e ssh),导致 host 提取取到端口号或选项参数。token 化三策略更可靠。\n // NEW-FP-E: bash -c/sh -c \"ssh user@host\" 的 user@host 被引号包裹成 \"user@host\"\n // 正则不匹配(\" 非 \\w)→ 漏报。bash -c 内联命令是真实调用,应检测。\n // 剥 token 首尾引号后再匹配(python -c 已在 checkLateralMovement 开头 INLINE_SCRIPT_RE 跳过)。\n const tokens = command.split(/\\s+/).map(t => t.replace(/^[\"']|[\"']$/g, ''));\n // 策略1:优先找 user@host 或 user@host: 模式(最可靠,带值选项参数值如\n // -L 8080:localhost:80 的 localhost 会被 isLocalHost 排除,不会误匹配)。\n for (const tok of tokens) {\n const am = tok.match(/^([\\w.-]+)@([\\w.-]+)(:.*)?$/);\n if (am && am[2] && !isLocalHost(am[2])) {\n return `${am[1]}@${am[2]}`;\n }\n }\n // 策略2:host: 模式(rsync/scp 远程路径 host:/path,无 user@)\n for (const tok of tokens) {\n const hm = tok.match(/^([\\w.-]+):\\/(.*)?$/);\n if (hm && hm[1] && !isLocalHost(hm[1])) {\n return hm[1];\n }\n }\n // 策略3:回退\"第一个非选项 token\"(ssh host 无 @ 无 :,如 ssh 10.0.0.5)。\n // 跳过 - 开头选项及其参数值(-p 2222 / -e ssh / -L 8080:...)。\n const skipValueOpts = new Set([\n '-p', '-l', '-i', '-o', '-b', '-c', '-m', '-F',\n '-e', '-S', '-W', '-J', '-I', '-T', '-B',\n '-L', '-R', '-D', '-E', '-M', '-O', '-P', '-q',\n ]);\n let foundCmd = false;\n for (let i = 0; i < tokens.length; i++) {\n const t = tokens[i];\n if (t === 'ssh' || t === 'scp' || t === 'rsync') {\n foundCmd = true;\n continue;\n }\n if (!foundCmd) continue;\n if (t.startsWith('-')) {\n // 带值选项:跳过下一个 token(-p 2222 / -e ssh / -L 8080:...)\n if (skipValueOpts.has(t) && i + 1 < tokens.length) {\n i++;\n }\n continue;\n }\n // 非选项 token:候选主机。排除纯路径(/ 开头本地路径非主机名)。\n if (t.startsWith('/')) continue;\n return t;\n }\n return null;\n}\n\nfunction isLocalHost(host: string): boolean {\n const localNames = ['localhost', '127.0.0.1', '::1', process.env.HOSTNAME || '', '0.0.0.0'];\n return localNames.includes(host.replace(/.*@/, ''));\n}\n\n/** 横向移动检测(从 L2 括入):ssh/scp/rsync 到非本机主机 */\nexport function checkLateralMovement(actionDetail: string): SecurityJudgment | null {\n // NEW-FP-D: 内联脚本(python -c / perl -e 等)里的 ssh/scp/rsync 是字面量非真调用,\n // 跳过交 inline-analyzer 专门管,与 intent/privilege 一致\n if (/\\b(?:python|python3|perl|ruby|node|php|lua)\\b\\s+.*-[cer][a-zA-Z]*\\s/.test(actionDetail)) return null;\n\n // NEW-FP-D: echo/printf �首词的参数是字面量非真调用(echo ssh user@host 是打印字面量)\n // 按命令段判定:首词 echo/printf 跳过,与 isWriteOperation 的 wget/curl 字面量判定一致\n const segments = actionDetail.split(/&&|\\|\\||;|\\n/).map(s => s.trim()).filter(Boolean);\n let hasRealCall = false;\n for (const seg of segments) {\n const parts = seg.split(/\\s+/);\n const fw = (parts[0] || '').toLowerCase();\n if (fw === 'echo' || fw === 'printf') continue;\n if (/(?:ssh|scp|rsync)\\s+/.test(seg)) { hasRealCall = true; break; }\n }\n if (!hasRealCall) return null;\n\n if (/(?:ssh|scp|rsync)\\s+/.test(actionDetail)) {\n const targetHost = extractRemoteHost(actionDetail);\n if (targetHost && !isLocalHost(targetHost)) {\n return {\n allowed: false,\n reason: `尝试横向移动到远程主机: ${targetHost}`,\n riskLevel: 'medium',\n riskType: 'lateral_movement',\n confidence: 80,\n source: 'heuristic',\n violatedLayers: ['1.1'],\n };\n }\n }\n return null;\n}\n","/**\n * Token usage statistics — record and query LLM token consumption.\n *\n * Mirrors Python agent_moss/infra/token_stats.py.\n *\n * Storage: JSON file at <data_root>/agent_moss_token_stats.json\n * (default ~/.config/agentmoss). With AGENT_MOSS_INSTANCE the file is isolated\n * to <data_root>/<instance>/ (see infra/paths.ts). env override\n * AGENT_MOSS_TOKEN_STATS_PATH wins. Whole-file rewrite per record (not append).\n * Max 10000 records, oldest trimmed.\n */\n\nimport { readFileSync, writeFileSync, existsSync, mkdirSync, unlinkSync } from 'fs';\nimport { join } from 'path';\nimport { getTokenStatsPath } from '../infra/paths';\n\nconst ENV_STATS_PATH = 'AGENT_MOSS_TOKEN_STATS_PATH';\nconst MAX_RECORDS = 10000;\n\nexport interface TokenUsageRecord {\n timestamp?: string; // ISO with milliseconds; auto-filled if omitted\n sessionId: string;\n step: string; // \"L3_security_judge\" | \"step2_policy_gen\"\n model: string;\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n}\n\ninterface RawRecord {\n timestamp: string;\n session_id: string;\n step: string;\n model: string;\n prompt_tokens: number;\n completion_tokens: number;\n total_tokens: number;\n}\n\ninterface Aggregated {\n prompt_tokens: number;\n completion_tokens: number;\n total_tokens: number;\n calls: number;\n}\n\nexport interface TokenStatsSummary {\n total_prompt_tokens: number;\n total_completion_tokens: number;\n total_tokens: number;\n total_calls: number;\n by_step: Record<string, Aggregated>;\n by_model: Record<string, Aggregated>;\n by_date: Record<string, Aggregated>;\n}\n\nexport interface TokenTrend {\n dates: string[];\n models: string[];\n series: Record<string, Record<string, number>>;\n}\n\nfunction getStatsPath(): string {\n const envPath = process.env[ENV_STATS_PATH];\n if (envPath) return envPath;\n return getTokenStatsPath();\n}\n\nfunction loadAllRecords(statsPath: string): RawRecord[] {\n if (!existsSync(statsPath)) return [];\n try {\n const data = JSON.parse(readFileSync(statsPath, 'utf-8'));\n if (Array.isArray(data)) return data;\n if (data && Array.isArray(data.records)) return data.records;\n return [];\n } catch (e) {\n return [];\n }\n}\n\nfunction saveRecords(statsPath: string, records: RawRecord[]): void {\n try {\n const dir = statsPath.substring(0, statsPath.lastIndexOf('/'));\n if (dir && !existsSync(dir)) mkdirSync(dir, { recursive: true });\n writeFileSync(statsPath, JSON.stringify(records, null, 2), 'utf-8');\n } catch (e) {\n // best-effort\n }\n}\n\n/** Record a single LLM call's token usage. */\nexport function recordTokenUsage(record: TokenUsageRecord): void {\n const statsPath = getStatsPath();\n const records = loadAllRecords(statsPath);\n records.push({\n timestamp: record.timestamp || new Date().toISOString(),\n session_id: record.sessionId,\n step: record.step,\n model: record.model,\n prompt_tokens: record.promptTokens,\n completion_tokens: record.completionTokens,\n total_tokens: record.totalTokens,\n });\n if (records.length > MAX_RECORDS) {\n records.splice(0, records.length - MAX_RECORDS);\n }\n saveRecords(statsPath, records);\n}\n\nfunction filterByDate(\n records: RawRecord[],\n days: number = 0,\n startDate?: string | null,\n endDate?: string | null,\n): RawRecord[] {\n if (startDate || endDate) {\n let startDt = startDate ? new Date(startDate) : new Date(-8640000000000000);\n let endDt = endDate ? new Date(endDate) : undefined;\n if (endDate) {\n const e = new Date(endDate);\n e.setHours(23, 59, 59, 999);\n endDt = e;\n }\n const endMs = endDt ? endDt.getTime() : Number.MAX_SAFE_INTEGER;\n return records.filter(r => {\n try {\n const ts = new Date(r.timestamp).getTime();\n return ts >= startDt.getTime() && ts <= endMs;\n } catch { return true; }\n });\n } else if (days > 0) {\n const cutoff = Date.now() - days * 86400000;\n return records.filter(r => {\n try { return new Date(r.timestamp).getTime() >= cutoff; }\n catch { return true; }\n });\n }\n return records;\n}\n\nfunction aggregate(records: RawRecord[]): {\n totalPrompt: number; totalCompletion: number; totalTotal: number;\n byStep: Record<string, Aggregated>; byModel: Record<string, Aggregated>; byDate: Record<string, Aggregated>;\n} {\n let totalPrompt = 0, totalCompletion = 0, totalTotal = 0;\n const byStep: Record<string, Aggregated> = {};\n const byModel: Record<string, Aggregated> = {};\n const byDate: Record<string, Aggregated> = {};\n\n const bucket = (b: Record<string, Aggregated>, key: string, r: RawRecord) => {\n const e = b[key] || (b[key] = { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0, calls: 0 });\n e.prompt_tokens += r.prompt_tokens || 0;\n e.completion_tokens += r.completion_tokens || 0;\n e.total_tokens += r.total_tokens || 0;\n e.calls += 1;\n };\n\n for (const r of records) {\n totalPrompt += r.prompt_tokens || 0;\n totalCompletion += r.completion_tokens || 0;\n totalTotal += r.total_tokens || 0;\n bucket(byStep, r.step || 'unknown', r);\n bucket(byModel, r.model || 'unknown', r);\n let dateKey = 'unknown';\n try {\n dateKey = new Date(r.timestamp).toISOString().slice(0, 10);\n } catch { /* keep unknown */ }\n bucket(byDate, dateKey, r);\n }\n\n // by_date sorted desc by date\n const sortedDate = Object.keys(byDate).sort((a, b) => (a < b ? 1 : a > b ? -1 : 0));\n const sortedByDate: Record<string, Aggregated> = {};\n for (const k of sortedDate) sortedByDate[k] = byDate[k];\n\n return { totalPrompt, totalCompletion, totalTotal, byStep, byModel, byDate: sortedByDate };\n}\n\nexport function getTokenStats(\n days: number = 0,\n startDate?: string | null,\n endDate?: string | null,\n): TokenStatsSummary {\n const records = filterByDate(loadAllRecords(getStatsPath()), days, startDate, endDate);\n const a = aggregate(records);\n return {\n total_prompt_tokens: a.totalPrompt,\n total_completion_tokens: a.totalCompletion,\n total_tokens: a.totalTotal,\n total_calls: records.length,\n by_step: a.byStep,\n by_model: a.byModel,\n by_date: a.byDate,\n };\n}\n\nexport function getRecentRecords(limit: number = 20, offset: number = 0): RawRecord[] {\n const records = loadAllRecords(getStatsPath());\n // 按时间升序存储,取\"最近\"需从末尾往前 offset 条再取 limit 条\n const start = Math.max(0, records.length - offset - limit);\n const end = records.length - offset;\n return records.slice(start, end);\n}\n\n/** 获取最近记录分页总数(供前端分页器使用) */\nexport function getRecentRecordsCount(): number {\n return loadAllRecords(getStatsPath()).length;\n}\n\nexport function getTokenTrend(\n days: number = 0,\n startDate?: string | null,\n endDate?: string | null,\n): TokenTrend {\n const records = filterByDate(loadAllRecords(getStatsPath()), days, startDate, endDate);\n const series: Record<string, Record<string, number>> = {};\n const datesSet = new Set<string>();\n for (const r of records) {\n let dateKey: string;\n try { dateKey = new Date(r.timestamp).toISOString().slice(0, 10); }\n catch { continue; }\n const model = r.model || 'unknown';\n const tokens = r.total_tokens || 0;\n datesSet.add(dateKey);\n series[model] = series[model] || {};\n series[model][dateKey] = (series[model][dateKey] || 0) + tokens;\n }\n const dates = Array.from(datesSet).sort();\n const models = Object.keys(series).sort();\n return { dates, models, series };\n}\n\nexport function resetTokenStats(): void {\n const statsPath = getStatsPath();\n if (existsSync(statsPath)) {\n try { unlinkSync(statsPath); } catch { /* ignore */ }\n }\n}\n","'use strict';\n\nexports.getBooleanOption = (options, key) => {\n\tlet value = false;\n\tif (key in options && typeof (value = options[key]) !== 'boolean') {\n\t\tthrow new TypeError(`Expected the \"${key}\" option to be a boolean`);\n\t}\n\treturn value;\n};\n\nexports.cppdb = Symbol();\nexports.inspect = Symbol.for('nodejs.util.inspect.custom');\n","'use strict';\nconst descriptor = { value: 'SqliteError', writable: true, enumerable: false, configurable: true };\n\nfunction SqliteError(message, code) {\n\tif (new.target !== SqliteError) {\n\t\treturn new SqliteError(message, code);\n\t}\n\tif (typeof code !== 'string') {\n\t\tthrow new TypeError('Expected second argument to be a string');\n\t}\n\tError.call(this, message);\n\tdescriptor.value = '' + message;\n\tObject.defineProperty(this, 'message', descriptor);\n\tError.captureStackTrace(this, SqliteError);\n\tthis.code = code;\n}\nObject.setPrototypeOf(SqliteError, Error);\nObject.setPrototypeOf(SqliteError.prototype, Error.prototype);\nObject.defineProperty(SqliteError.prototype, 'name', descriptor);\nmodule.exports = SqliteError;\n","\n/**\n * Module dependencies.\n */\n\nvar sep = require('path').sep || '/';\n\n/**\n * Module exports.\n */\n\nmodule.exports = fileUriToPath;\n\n/**\n * File URI to Path function.\n *\n * @param {String} uri\n * @return {String} path\n * @api public\n */\n\nfunction fileUriToPath (uri) {\n if ('string' != typeof uri ||\n uri.length <= 7 ||\n 'file://' != uri.substring(0, 7)) {\n throw new TypeError('must pass in a file:// URI to convert to a file path');\n }\n\n var rest = decodeURI(uri.substring(7));\n var firstSlash = rest.indexOf('/');\n var host = rest.substring(0, firstSlash);\n var path = rest.substring(firstSlash + 1);\n\n // 2. Scheme Definition\n // As a special case, <host> can be the string \"localhost\" or the empty\n // string; this is interpreted as \"the machine from which the URL is\n // being interpreted\".\n if ('localhost' == host) host = '';\n\n if (host) {\n host = sep + sep + host;\n }\n\n // 3.2 Drives, drive letters, mount points, file system root\n // Drive letters are mapped into the top of a file URI in various ways,\n // depending on the implementation; some applications substitute\n // vertical bar (\"|\") for the colon after the drive letter, yielding\n // \"file:///c|/tmp/test.txt\". In some cases, the colon is left\n // unchanged, as in \"file:///c:/tmp/test.txt\". In other cases, the\n // colon is simply omitted, as in \"file:///c/tmp/test.txt\".\n path = path.replace(/^(.+)\\|/, '$1:');\n\n // for Windows, we need to invert the path separators from what a URI uses\n if (sep == '\\\\') {\n path = path.replace(/\\//g, '\\\\');\n }\n\n if (/^.+\\:/.test(path)) {\n // has Windows drive at beginning of path\n } else {\n // unix path…\n path = sep + path;\n }\n\n return host + path;\n}\n","/**\n * Module dependencies.\n */\n\nvar fs = require('fs'),\n path = require('path'),\n fileURLToPath = require('file-uri-to-path'),\n join = path.join,\n dirname = path.dirname,\n exists =\n (fs.accessSync &&\n function(path) {\n try {\n fs.accessSync(path);\n } catch (e) {\n return false;\n }\n return true;\n }) ||\n fs.existsSync ||\n path.existsSync,\n defaults = {\n arrow: process.env.NODE_BINDINGS_ARROW || ' → ',\n compiled: process.env.NODE_BINDINGS_COMPILED_DIR || 'compiled',\n platform: process.platform,\n arch: process.arch,\n nodePreGyp:\n 'node-v' +\n process.versions.modules +\n '-' +\n process.platform +\n '-' +\n process.arch,\n version: process.versions.node,\n bindings: 'bindings.node',\n try: [\n // node-gyp's linked version in the \"build\" dir\n ['module_root', 'build', 'bindings'],\n // node-waf and gyp_addon (a.k.a node-gyp)\n ['module_root', 'build', 'Debug', 'bindings'],\n ['module_root', 'build', 'Release', 'bindings'],\n // Debug files, for development (legacy behavior, remove for node v0.9)\n ['module_root', 'out', 'Debug', 'bindings'],\n ['module_root', 'Debug', 'bindings'],\n // Release files, but manually compiled (legacy behavior, remove for node v0.9)\n ['module_root', 'out', 'Release', 'bindings'],\n ['module_root', 'Release', 'bindings'],\n // Legacy from node-waf, node <= 0.4.x\n ['module_root', 'build', 'default', 'bindings'],\n // Production \"Release\" buildtype binary (meh...)\n ['module_root', 'compiled', 'version', 'platform', 'arch', 'bindings'],\n // node-qbs builds\n ['module_root', 'addon-build', 'release', 'install-root', 'bindings'],\n ['module_root', 'addon-build', 'debug', 'install-root', 'bindings'],\n ['module_root', 'addon-build', 'default', 'install-root', 'bindings'],\n // node-pre-gyp path ./lib/binding/{node_abi}-{platform}-{arch}\n ['module_root', 'lib', 'binding', 'nodePreGyp', 'bindings']\n ]\n };\n\n/**\n * The main `bindings()` function loads the compiled bindings for a given module.\n * It uses V8's Error API to determine the parent filename that this function is\n * being invoked from, which is then used to find the root directory.\n */\n\nfunction bindings(opts) {\n // Argument surgery\n if (typeof opts == 'string') {\n opts = { bindings: opts };\n } else if (!opts) {\n opts = {};\n }\n\n // maps `defaults` onto `opts` object\n Object.keys(defaults).map(function(i) {\n if (!(i in opts)) opts[i] = defaults[i];\n });\n\n // Get the module root\n if (!opts.module_root) {\n opts.module_root = exports.getRoot(exports.getFileName());\n }\n\n // Ensure the given bindings name ends with .node\n if (path.extname(opts.bindings) != '.node') {\n opts.bindings += '.node';\n }\n\n // https://github.com/webpack/webpack/issues/4175#issuecomment-342931035\n var requireFunc =\n typeof __webpack_require__ === 'function'\n ? __non_webpack_require__\n : require;\n\n var tries = [],\n i = 0,\n l = opts.try.length,\n n,\n b,\n err;\n\n for (; i < l; i++) {\n n = join.apply(\n null,\n opts.try[i].map(function(p) {\n return opts[p] || p;\n })\n );\n tries.push(n);\n try {\n b = opts.path ? requireFunc.resolve(n) : requireFunc(n);\n if (!opts.path) {\n b.path = n;\n }\n return b;\n } catch (e) {\n if (e.code !== 'MODULE_NOT_FOUND' &&\n e.code !== 'QUALIFIED_PATH_RESOLUTION_FAILED' &&\n !/not find/i.test(e.message)) {\n throw e;\n }\n }\n }\n\n err = new Error(\n 'Could not locate the bindings file. Tried:\\n' +\n tries\n .map(function(a) {\n return opts.arrow + a;\n })\n .join('\\n')\n );\n err.tries = tries;\n throw err;\n}\nmodule.exports = exports = bindings;\n\n/**\n * Gets the filename of the JavaScript file that invokes this function.\n * Used to help find the root directory of a module.\n * Optionally accepts an filename argument to skip when searching for the invoking filename\n */\n\nexports.getFileName = function getFileName(calling_file) {\n var origPST = Error.prepareStackTrace,\n origSTL = Error.stackTraceLimit,\n dummy = {},\n fileName;\n\n Error.stackTraceLimit = 10;\n\n Error.prepareStackTrace = function(e, st) {\n for (var i = 0, l = st.length; i < l; i++) {\n fileName = st[i].getFileName();\n if (fileName !== __filename) {\n if (calling_file) {\n if (fileName !== calling_file) {\n return;\n }\n } else {\n return;\n }\n }\n }\n };\n\n // run the 'prepareStackTrace' function above\n Error.captureStackTrace(dummy);\n dummy.stack;\n\n // cleanup\n Error.prepareStackTrace = origPST;\n Error.stackTraceLimit = origSTL;\n\n // handle filename that starts with \"file://\"\n var fileSchema = 'file://';\n if (fileName.indexOf(fileSchema) === 0) {\n fileName = fileURLToPath(fileName);\n }\n\n return fileName;\n};\n\n/**\n * Gets the root directory of a module, given an arbitrary filename\n * somewhere in the module tree. The \"root directory\" is the directory\n * containing the `package.json` file.\n *\n * In: /home/nate/node-native-module/lib/index.js\n * Out: /home/nate/node-native-module\n */\n\nexports.getRoot = function getRoot(file) {\n var dir = dirname(file),\n prev;\n while (true) {\n if (dir === '.') {\n // Avoids an infinite loop in rare cases, like the REPL\n dir = process.cwd();\n }\n if (\n exists(join(dir, 'package.json')) ||\n exists(join(dir, 'node_modules'))\n ) {\n // Found the 'package.json' file or 'node_modules' dir; we're done\n return dir;\n }\n if (prev === dir) {\n // Got to the top\n throw new Error(\n 'Could not find module root given file: \"' +\n file +\n '\". Do you have a `package.json` file? '\n );\n }\n // Try the parent dir next\n prev = dir;\n dir = join(dir, '..');\n }\n};\n","'use strict';\nconst { cppdb } = require('../util');\n\nexports.prepare = function prepare(sql) {\n\treturn this[cppdb].prepare(sql, this, false);\n};\n\nexports.exec = function exec(sql) {\n\tthis[cppdb].exec(sql);\n\treturn this;\n};\n\nexports.close = function close() {\n\tthis[cppdb].close();\n\treturn this;\n};\n\nexports.loadExtension = function loadExtension(...args) {\n\tthis[cppdb].loadExtension(...args);\n\treturn this;\n};\n\nexports.defaultSafeIntegers = function defaultSafeIntegers(...args) {\n\tthis[cppdb].defaultSafeIntegers(...args);\n\treturn this;\n};\n\nexports.unsafeMode = function unsafeMode(...args) {\n\tthis[cppdb].unsafeMode(...args);\n\treturn this;\n};\n\nexports.getters = {\n\tname: {\n\t\tget: function name() { return this[cppdb].name; },\n\t\tenumerable: true,\n\t},\n\topen: {\n\t\tget: function open() { return this[cppdb].open; },\n\t\tenumerable: true,\n\t},\n\tinTransaction: {\n\t\tget: function inTransaction() { return this[cppdb].inTransaction; },\n\t\tenumerable: true,\n\t},\n\treadonly: {\n\t\tget: function readonly() { return this[cppdb].readonly; },\n\t\tenumerable: true,\n\t},\n\tmemory: {\n\t\tget: function memory() { return this[cppdb].memory; },\n\t\tenumerable: true,\n\t},\n};\n","'use strict';\nconst { cppdb } = require('../util');\nconst controllers = new WeakMap();\n\nmodule.exports = function transaction(fn) {\n\tif (typeof fn !== 'function') throw new TypeError('Expected first argument to be a function');\n\n\tconst db = this[cppdb];\n\tconst controller = getController(db, this);\n\tconst { apply } = Function.prototype;\n\n\t// Each version of the transaction function has these same properties\n\tconst properties = {\n\t\tdefault: { value: wrapTransaction(apply, fn, db, controller.default) },\n\t\tdeferred: { value: wrapTransaction(apply, fn, db, controller.deferred) },\n\t\timmediate: { value: wrapTransaction(apply, fn, db, controller.immediate) },\n\t\texclusive: { value: wrapTransaction(apply, fn, db, controller.exclusive) },\n\t\tdatabase: { value: this, enumerable: true },\n\t};\n\n\tObject.defineProperties(properties.default.value, properties);\n\tObject.defineProperties(properties.deferred.value, properties);\n\tObject.defineProperties(properties.immediate.value, properties);\n\tObject.defineProperties(properties.exclusive.value, properties);\n\n\t// Return the default version of the transaction function\n\treturn properties.default.value;\n};\n\n// Return the database's cached transaction controller, or create a new one\nconst getController = (db, self) => {\n\tlet controller = controllers.get(db);\n\tif (!controller) {\n\t\tconst shared = {\n\t\t\tcommit: db.prepare('COMMIT', self, false),\n\t\t\trollback: db.prepare('ROLLBACK', self, false),\n\t\t\tsavepoint: db.prepare('SAVEPOINT `\\t_bs3.\\t`', self, false),\n\t\t\trelease: db.prepare('RELEASE `\\t_bs3.\\t`', self, false),\n\t\t\trollbackTo: db.prepare('ROLLBACK TO `\\t_bs3.\\t`', self, false),\n\t\t};\n\t\tcontrollers.set(db, controller = {\n\t\t\tdefault: Object.assign({ begin: db.prepare('BEGIN', self, false) }, shared),\n\t\t\tdeferred: Object.assign({ begin: db.prepare('BEGIN DEFERRED', self, false) }, shared),\n\t\t\timmediate: Object.assign({ begin: db.prepare('BEGIN IMMEDIATE', self, false) }, shared),\n\t\t\texclusive: Object.assign({ begin: db.prepare('BEGIN EXCLUSIVE', self, false) }, shared),\n\t\t});\n\t}\n\treturn controller;\n};\n\n// Return a new transaction function by wrapping the given function\nconst wrapTransaction = (apply, fn, db, { begin, commit, rollback, savepoint, release, rollbackTo }) => function sqliteTransaction() {\n\tlet before, after, undo;\n\tif (db.inTransaction) {\n\t\tbefore = savepoint;\n\t\tafter = release;\n\t\tundo = rollbackTo;\n\t} else {\n\t\tbefore = begin;\n\t\tafter = commit;\n\t\tundo = rollback;\n\t}\n\tbefore.run();\n\ttry {\n\t\tconst result = apply.call(fn, this, arguments);\n\t\tif (result && typeof result.then === 'function') {\n\t\t\tthrow new TypeError('Transaction function cannot return a promise');\n\t\t}\n\t\tafter.run();\n\t\treturn result;\n\t} catch (ex) {\n\t\tif (db.inTransaction) {\n\t\t\tundo.run();\n\t\t\tif (undo !== rollback) after.run();\n\t\t}\n\t\tthrow ex;\n\t}\n};\n","'use strict';\nconst { getBooleanOption, cppdb } = require('../util');\n\nmodule.exports = function pragma(source, options) {\n\tif (options == null) options = {};\n\tif (typeof source !== 'string') throw new TypeError('Expected first argument to be a string');\n\tif (typeof options !== 'object') throw new TypeError('Expected second argument to be an options object');\n\tconst simple = getBooleanOption(options, 'simple');\n\n\tconst stmt = this[cppdb].prepare(`PRAGMA ${source}`, this, true);\n\treturn simple ? stmt.pluck().get() : stmt.all();\n};\n","'use strict';\nconst fs = require('fs');\nconst path = require('path');\nconst { promisify } = require('util');\nconst { cppdb } = require('../util');\nconst fsAccess = promisify(fs.access);\n\nmodule.exports = async function backup(filename, options) {\n\tif (options == null) options = {};\n\n\t// Validate arguments\n\tif (typeof filename !== 'string') throw new TypeError('Expected first argument to be a string');\n\tif (typeof options !== 'object') throw new TypeError('Expected second argument to be an options object');\n\n\t// Interpret options\n\tfilename = filename.trim();\n\tconst attachedName = 'attached' in options ? options.attached : 'main';\n\tconst handler = 'progress' in options ? options.progress : null;\n\n\t// Validate interpreted options\n\tif (!filename) throw new TypeError('Backup filename cannot be an empty string');\n\tif (filename === ':memory:') throw new TypeError('Invalid backup filename \":memory:\"');\n\tif (typeof attachedName !== 'string') throw new TypeError('Expected the \"attached\" option to be a string');\n\tif (!attachedName) throw new TypeError('The \"attached\" option cannot be an empty string');\n\tif (handler != null && typeof handler !== 'function') throw new TypeError('Expected the \"progress\" option to be a function');\n\n\t// Make sure the specified directory exists\n\tawait fsAccess(path.dirname(filename)).catch(() => {\n\t\tthrow new TypeError('Cannot save backup because the directory does not exist');\n\t});\n\n\tconst isNewFile = await fsAccess(filename).then(() => false, () => true);\n\treturn runBackup(this[cppdb].backup(this, attachedName, filename, isNewFile), handler || null);\n};\n\nconst runBackup = (backup, handler) => {\n\tlet rate = 0;\n\tlet useDefault = true;\n\n\treturn new Promise((resolve, reject) => {\n\t\tsetImmediate(function step() {\n\t\t\ttry {\n\t\t\t\tconst progress = backup.transfer(rate);\n\t\t\t\tif (!progress.remainingPages) {\n\t\t\t\t\tbackup.close();\n\t\t\t\t\tresolve(progress);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (useDefault) {\n\t\t\t\t\tuseDefault = false;\n\t\t\t\t\trate = 100;\n\t\t\t\t}\n\t\t\t\tif (handler) {\n\t\t\t\t\tconst ret = handler(progress);\n\t\t\t\t\tif (ret !== undefined) {\n\t\t\t\t\t\tif (typeof ret === 'number' && ret === ret) rate = Math.max(0, Math.min(0x7fffffff, Math.round(ret)));\n\t\t\t\t\t\telse throw new TypeError('Expected progress callback to return a number or undefined');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tsetImmediate(step);\n\t\t\t} catch (err) {\n\t\t\t\tbackup.close();\n\t\t\t\treject(err);\n\t\t\t}\n\t\t});\n\t});\n};\n","'use strict';\nconst { cppdb } = require('../util');\n\nmodule.exports = function serialize(options) {\n\tif (options == null) options = {};\n\n\t// Validate arguments\n\tif (typeof options !== 'object') throw new TypeError('Expected first argument to be an options object');\n\n\t// Interpret and validate options\n\tconst attachedName = 'attached' in options ? options.attached : 'main';\n\tif (typeof attachedName !== 'string') throw new TypeError('Expected the \"attached\" option to be a string');\n\tif (!attachedName) throw new TypeError('The \"attached\" option cannot be an empty string');\n\n\treturn this[cppdb].serialize(attachedName);\n};\n","'use strict';\nconst { getBooleanOption, cppdb } = require('../util');\n\nmodule.exports = function defineFunction(name, options, fn) {\n\t// Apply defaults\n\tif (options == null) options = {};\n\tif (typeof options === 'function') { fn = options; options = {}; }\n\n\t// Validate arguments\n\tif (typeof name !== 'string') throw new TypeError('Expected first argument to be a string');\n\tif (typeof fn !== 'function') throw new TypeError('Expected last argument to be a function');\n\tif (typeof options !== 'object') throw new TypeError('Expected second argument to be an options object');\n\tif (!name) throw new TypeError('User-defined function name cannot be an empty string');\n\n\t// Interpret options\n\tconst safeIntegers = 'safeIntegers' in options ? +getBooleanOption(options, 'safeIntegers') : 2;\n\tconst deterministic = getBooleanOption(options, 'deterministic');\n\tconst directOnly = getBooleanOption(options, 'directOnly');\n\tconst varargs = getBooleanOption(options, 'varargs');\n\tlet argCount = -1;\n\n\t// Determine argument count\n\tif (!varargs) {\n\t\targCount = fn.length;\n\t\tif (!Number.isInteger(argCount) || argCount < 0) throw new TypeError('Expected function.length to be a positive integer');\n\t\tif (argCount > 100) throw new RangeError('User-defined functions cannot have more than 100 arguments');\n\t}\n\n\tthis[cppdb].function(fn, name, argCount, safeIntegers, deterministic, directOnly);\n\treturn this;\n};\n","'use strict';\nconst { getBooleanOption, cppdb } = require('../util');\n\nmodule.exports = function defineAggregate(name, options) {\n\t// Validate arguments\n\tif (typeof name !== 'string') throw new TypeError('Expected first argument to be a string');\n\tif (typeof options !== 'object' || options === null) throw new TypeError('Expected second argument to be an options object');\n\tif (!name) throw new TypeError('User-defined function name cannot be an empty string');\n\n\t// Interpret options\n\tconst start = 'start' in options ? options.start : null;\n\tconst step = getFunctionOption(options, 'step', true);\n\tconst inverse = getFunctionOption(options, 'inverse', false);\n\tconst result = getFunctionOption(options, 'result', false);\n\tconst safeIntegers = 'safeIntegers' in options ? +getBooleanOption(options, 'safeIntegers') : 2;\n\tconst deterministic = getBooleanOption(options, 'deterministic');\n\tconst directOnly = getBooleanOption(options, 'directOnly');\n\tconst varargs = getBooleanOption(options, 'varargs');\n\tlet argCount = -1;\n\n\t// Determine argument count\n\tif (!varargs) {\n\t\targCount = Math.max(getLength(step), inverse ? getLength(inverse) : 0);\n\t\tif (argCount > 0) argCount -= 1;\n\t\tif (argCount > 100) throw new RangeError('User-defined functions cannot have more than 100 arguments');\n\t}\n\n\tthis[cppdb].aggregate(start, step, inverse, result, name, argCount, safeIntegers, deterministic, directOnly);\n\treturn this;\n};\n\nconst getFunctionOption = (options, key, required) => {\n\tconst value = key in options ? options[key] : null;\n\tif (typeof value === 'function') return value;\n\tif (value != null) throw new TypeError(`Expected the \"${key}\" option to be a function`);\n\tif (required) throw new TypeError(`Missing required option \"${key}\"`);\n\treturn null;\n};\n\nconst getLength = ({ length }) => {\n\tif (Number.isInteger(length) && length >= 0) return length;\n\tthrow new TypeError('Expected function.length to be a positive integer');\n};\n","'use strict';\nconst { cppdb } = require('../util');\n\nmodule.exports = function defineTable(name, factory) {\n\t// Validate arguments\n\tif (typeof name !== 'string') throw new TypeError('Expected first argument to be a string');\n\tif (!name) throw new TypeError('Virtual table module name cannot be an empty string');\n\n\t// Determine whether the module is eponymous-only or not\n\tlet eponymous = false;\n\tif (typeof factory === 'object' && factory !== null) {\n\t\teponymous = true;\n\t\tfactory = defer(parseTableDefinition(factory, 'used', name));\n\t} else {\n\t\tif (typeof factory !== 'function') throw new TypeError('Expected second argument to be a function or a table definition object');\n\t\tfactory = wrapFactory(factory);\n\t}\n\n\tthis[cppdb].table(factory, name, eponymous);\n\treturn this;\n};\n\nfunction wrapFactory(factory) {\n\treturn function virtualTableFactory(moduleName, databaseName, tableName, ...args) {\n\t\tconst thisObject = {\n\t\t\tmodule: moduleName,\n\t\t\tdatabase: databaseName,\n\t\t\ttable: tableName,\n\t\t};\n\n\t\t// Generate a new table definition by invoking the factory\n\t\tconst def = apply.call(factory, thisObject, args);\n\t\tif (typeof def !== 'object' || def === null) {\n\t\t\tthrow new TypeError(`Virtual table module \"${moduleName}\" did not return a table definition object`);\n\t\t}\n\n\t\treturn parseTableDefinition(def, 'returned', moduleName);\n\t};\n}\n\nfunction parseTableDefinition(def, verb, moduleName) {\n\t// Validate required properties\n\tif (!hasOwnProperty.call(def, 'rows')) {\n\t\tthrow new TypeError(`Virtual table module \"${moduleName}\" ${verb} a table definition without a \"rows\" property`);\n\t}\n\tif (!hasOwnProperty.call(def, 'columns')) {\n\t\tthrow new TypeError(`Virtual table module \"${moduleName}\" ${verb} a table definition without a \"columns\" property`);\n\t}\n\n\t// Validate \"rows\" property\n\tconst rows = def.rows;\n\tif (typeof rows !== 'function' || Object.getPrototypeOf(rows) !== GeneratorFunctionPrototype) {\n\t\tthrow new TypeError(`Virtual table module \"${moduleName}\" ${verb} a table definition with an invalid \"rows\" property (should be a generator function)`);\n\t}\n\n\t// Validate \"columns\" property\n\tlet columns = def.columns;\n\tif (!Array.isArray(columns) || !(columns = [...columns]).every(x => typeof x === 'string')) {\n\t\tthrow new TypeError(`Virtual table module \"${moduleName}\" ${verb} a table definition with an invalid \"columns\" property (should be an array of strings)`);\n\t}\n\tif (columns.length !== new Set(columns).size) {\n\t\tthrow new TypeError(`Virtual table module \"${moduleName}\" ${verb} a table definition with duplicate column names`);\n\t}\n\tif (!columns.length) {\n\t\tthrow new RangeError(`Virtual table module \"${moduleName}\" ${verb} a table definition with zero columns`);\n\t}\n\n\t// Validate \"parameters\" property\n\tlet parameters;\n\tif (hasOwnProperty.call(def, 'parameters')) {\n\t\tparameters = def.parameters;\n\t\tif (!Array.isArray(parameters) || !(parameters = [...parameters]).every(x => typeof x === 'string')) {\n\t\t\tthrow new TypeError(`Virtual table module \"${moduleName}\" ${verb} a table definition with an invalid \"parameters\" property (should be an array of strings)`);\n\t\t}\n\t} else {\n\t\tparameters = inferParameters(rows);\n\t}\n\tif (parameters.length !== new Set(parameters).size) {\n\t\tthrow new TypeError(`Virtual table module \"${moduleName}\" ${verb} a table definition with duplicate parameter names`);\n\t}\n\tif (parameters.length > 32) {\n\t\tthrow new RangeError(`Virtual table module \"${moduleName}\" ${verb} a table definition with more than the maximum number of 32 parameters`);\n\t}\n\tfor (const parameter of parameters) {\n\t\tif (columns.includes(parameter)) {\n\t\t\tthrow new TypeError(`Virtual table module \"${moduleName}\" ${verb} a table definition with column \"${parameter}\" which was ambiguously defined as both a column and parameter`);\n\t\t}\n\t}\n\n\t// Validate \"safeIntegers\" option\n\tlet safeIntegers = 2;\n\tif (hasOwnProperty.call(def, 'safeIntegers')) {\n\t\tconst bool = def.safeIntegers;\n\t\tif (typeof bool !== 'boolean') {\n\t\t\tthrow new TypeError(`Virtual table module \"${moduleName}\" ${verb} a table definition with an invalid \"safeIntegers\" property (should be a boolean)`);\n\t\t}\n\t\tsafeIntegers = +bool;\n\t}\n\n\t// Validate \"directOnly\" option\n\tlet directOnly = false;\n\tif (hasOwnProperty.call(def, 'directOnly')) {\n\t\tdirectOnly = def.directOnly;\n\t\tif (typeof directOnly !== 'boolean') {\n\t\t\tthrow new TypeError(`Virtual table module \"${moduleName}\" ${verb} a table definition with an invalid \"directOnly\" property (should be a boolean)`);\n\t\t}\n\t}\n\n\t// Generate SQL for the virtual table definition\n\tconst columnDefinitions = [\n\t\t...parameters.map(identifier).map(str => `${str} HIDDEN`),\n\t\t...columns.map(identifier),\n\t];\n\treturn [\n\t\t`CREATE TABLE x(${columnDefinitions.join(', ')});`,\n\t\twrapGenerator(rows, new Map(columns.map((x, i) => [x, parameters.length + i])), moduleName),\n\t\tparameters,\n\t\tsafeIntegers,\n\t\tdirectOnly,\n\t];\n}\n\nfunction wrapGenerator(generator, columnMap, moduleName) {\n\treturn function* virtualTable(...args) {\n\t\t/*\n\t\t\tWe must defensively clone any buffers in the arguments, because\n\t\t\totherwise the generator could mutate one of them, which would cause\n\t\t\tus to return incorrect values for hidden columns, potentially\n\t\t\tcorrupting the database.\n\t\t */\n\t\tconst output = args.map(x => Buffer.isBuffer(x) ? Buffer.from(x) : x);\n\t\tfor (let i = 0; i < columnMap.size; ++i) {\n\t\t\toutput.push(null); // Fill with nulls to prevent gaps in array (v8 optimization)\n\t\t}\n\t\tfor (const row of generator(...args)) {\n\t\t\tif (Array.isArray(row)) {\n\t\t\t\textractRowArray(row, output, columnMap.size, moduleName);\n\t\t\t\tyield output;\n\t\t\t} else if (typeof row === 'object' && row !== null) {\n\t\t\t\textractRowObject(row, output, columnMap, moduleName);\n\t\t\t\tyield output;\n\t\t\t} else {\n\t\t\t\tthrow new TypeError(`Virtual table module \"${moduleName}\" yielded something that isn't a valid row object`);\n\t\t\t}\n\t\t}\n\t};\n}\n\nfunction extractRowArray(row, output, columnCount, moduleName) {\n\tif (row.length !== columnCount) {\n\t\tthrow new TypeError(`Virtual table module \"${moduleName}\" yielded a row with an incorrect number of columns`);\n\t}\n\tconst offset = output.length - columnCount;\n\tfor (let i = 0; i < columnCount; ++i) {\n\t\toutput[i + offset] = row[i];\n\t}\n}\n\nfunction extractRowObject(row, output, columnMap, moduleName) {\n\tlet count = 0;\n\tfor (const key of Object.keys(row)) {\n\t\tconst index = columnMap.get(key);\n\t\tif (index === undefined) {\n\t\t\tthrow new TypeError(`Virtual table module \"${moduleName}\" yielded a row with an undeclared column \"${key}\"`);\n\t\t}\n\t\toutput[index] = row[key];\n\t\tcount += 1;\n\t}\n\tif (count !== columnMap.size) {\n\t\tthrow new TypeError(`Virtual table module \"${moduleName}\" yielded a row with missing columns`);\n\t}\n}\n\nfunction inferParameters({ length }) {\n\tif (!Number.isInteger(length) || length < 0) {\n\t\tthrow new TypeError('Expected function.length to be a positive integer');\n\t}\n\tconst params = [];\n\tfor (let i = 0; i < length; ++i) {\n\t\tparams.push(`$${i + 1}`);\n\t}\n\treturn params;\n}\n\nconst { hasOwnProperty } = Object.prototype;\nconst { apply } = Function.prototype;\nconst GeneratorFunctionPrototype = Object.getPrototypeOf(function*(){});\nconst identifier = str => `\"${str.replace(/\"/g, '\"\"')}\"`;\nconst defer = x => () => x;\n","'use strict';\nconst DatabaseInspection = function Database() {};\n\nmodule.exports = function inspect(depth, opts) {\n\treturn Object.assign(new DatabaseInspection(), this);\n};\n\n","'use strict';\nconst fs = require('fs');\nconst path = require('path');\nconst util = require('./util');\nconst SqliteError = require('./sqlite-error');\n\nlet DEFAULT_ADDON;\n\nfunction Database(filenameGiven, options) {\n\tif (new.target == null) {\n\t\treturn new Database(filenameGiven, options);\n\t}\n\n\t// Apply defaults\n\tlet buffer;\n\tif (Buffer.isBuffer(filenameGiven)) {\n\t\tbuffer = filenameGiven;\n\t\tfilenameGiven = ':memory:';\n\t}\n\tif (filenameGiven == null) filenameGiven = '';\n\tif (options == null) options = {};\n\n\t// Validate arguments\n\tif (typeof filenameGiven !== 'string') throw new TypeError('Expected first argument to be a string');\n\tif (typeof options !== 'object') throw new TypeError('Expected second argument to be an options object');\n\tif ('readOnly' in options) throw new TypeError('Misspelled option \"readOnly\" should be \"readonly\"');\n\tif ('memory' in options) throw new TypeError('Option \"memory\" was removed in v7.0.0 (use \":memory:\" filename instead)');\n\n\t// Interpret options\n\tconst filename = filenameGiven.trim();\n\tconst anonymous = filename === '' || filename === ':memory:';\n\tconst readonly = util.getBooleanOption(options, 'readonly');\n\tconst fileMustExist = util.getBooleanOption(options, 'fileMustExist');\n\tconst timeout = 'timeout' in options ? options.timeout : 5000;\n\tconst verbose = 'verbose' in options ? options.verbose : null;\n\tconst nativeBinding = 'nativeBinding' in options ? options.nativeBinding : null;\n\n\t// Validate interpreted options\n\tif (readonly && anonymous && !buffer) throw new TypeError('In-memory/temporary databases cannot be readonly');\n\tif (!Number.isInteger(timeout) || timeout < 0) throw new TypeError('Expected the \"timeout\" option to be a positive integer');\n\tif (timeout > 0x7fffffff) throw new RangeError('Option \"timeout\" cannot be greater than 2147483647');\n\tif (verbose != null && typeof verbose !== 'function') throw new TypeError('Expected the \"verbose\" option to be a function');\n\tif (nativeBinding != null && typeof nativeBinding !== 'string' && typeof nativeBinding !== 'object') throw new TypeError('Expected the \"nativeBinding\" option to be a string or addon object');\n\n\t// Load the native addon\n\tlet addon;\n\tif (nativeBinding == null) {\n\t\taddon = DEFAULT_ADDON || (DEFAULT_ADDON = require('bindings')('better_sqlite3.node'));\n\t} else if (typeof nativeBinding === 'string') {\n\t\t// See <https://webpack.js.org/api/module-variables/#__non_webpack_require__-webpack-specific>\n\t\tconst requireFunc = typeof __non_webpack_require__ === 'function' ? __non_webpack_require__ : require;\n\t\taddon = requireFunc(path.resolve(nativeBinding).replace(/(\\.node)?$/, '.node'));\n\t} else {\n\t\t// See <https://github.com/WiseLibs/better-sqlite3/issues/972>\n\t\taddon = nativeBinding;\n\t}\n\n\tif (!addon.isInitialized) {\n\t\taddon.setErrorConstructor(SqliteError);\n\t\taddon.isInitialized = true;\n\t}\n\n\t// Make sure the specified directory exists\n\tif (!anonymous && !fs.existsSync(path.dirname(filename))) {\n\t\tthrow new TypeError('Cannot open database because the directory does not exist');\n\t}\n\n\tObject.defineProperties(this, {\n\t\t[util.cppdb]: { value: new addon.Database(filename, filenameGiven, anonymous, readonly, fileMustExist, timeout, verbose || null, buffer || null) },\n\t\t...wrappers.getters,\n\t});\n}\n\nconst wrappers = require('./methods/wrappers');\nDatabase.prototype.prepare = wrappers.prepare;\nDatabase.prototype.transaction = require('./methods/transaction');\nDatabase.prototype.pragma = require('./methods/pragma');\nDatabase.prototype.backup = require('./methods/backup');\nDatabase.prototype.serialize = require('./methods/serialize');\nDatabase.prototype.function = require('./methods/function');\nDatabase.prototype.aggregate = require('./methods/aggregate');\nDatabase.prototype.table = require('./methods/table');\nDatabase.prototype.loadExtension = wrappers.loadExtension;\nDatabase.prototype.exec = wrappers.exec;\nDatabase.prototype.close = wrappers.close;\nDatabase.prototype.defaultSafeIntegers = wrappers.defaultSafeIntegers;\nDatabase.prototype.unsafeMode = wrappers.unsafeMode;\nDatabase.prototype[util.inspect] = require('./methods/inspect');\n\nmodule.exports = Database;\n","'use strict';\nmodule.exports = require('./database');\nmodule.exports.SqliteError = require('./sqlite-error');\n","import { Hono } from 'hono';\nimport { cors } from 'hono/cors';\nimport { logger } from 'hono/logger';\nimport net from 'node:net';\nimport { analyzeRoute, healthRoute } from './routes';\nimport { createConsoleRouter } from './console';\n\nexport function createApp(): Hono {\n const app = new Hono();\n\n // Middleware\n app.use('*', cors({ origin: '*', allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'], allowHeaders: ['*'] }));\n app.use('*', logger());\n\n // Routes\n app.get('/api/v1/health', healthRoute);\n app.post('/api/v1/analyze', analyzeRoute);\n\n // Policy Console(浏览器策略管控台,挂载在 /console 前缀)\n app.route('/console', createConsoleRouter());\n // /console/ → /console(hono route 挂载后带尾斜杠匹配行为不一致,加重定向兼容)\n app.get('/console/', (c) => c.redirect('/console'));\n\n return app;\n}\n\n/**\n * 从 startPort 开始找第一个可用端口(照搬 OpenDesk findFreePort 策略)。\n * 用 net.createServer().listen 试端口,成功立刻 close 返回该端口;全占 fallback\n * 到 startPort(让 hono 自己报错,不静默换到离谱端口)。\n *\n * 为什么需要:默认 9090 被占时服务起不来、xiaoO 全 fail-closed。预探测找空闲端口,\n * 配合消费方探测兜底(bridge.ts probeAgentMossUrl),保证服务总能起、消费方能连上。\n */\nexport async function findFreePort(\n startPort: number,\n host: string = '127.0.0.1',\n scan: number = 100,\n): Promise<number> {\n for (let port = startPort; port < startPort + scan; port++) {\n const free = await new Promise<boolean>((resolve) => {\n const server = net.createServer();\n server.listen(port, host, () => {\n server.close(() => resolve(true));\n });\n server.on('error', () => resolve(false));\n });\n if (free) {\n if (port !== startPort) {\n console.warn(`[AgentMoss] Port ${startPort} in use, using ${port} instead`);\n }\n return port;\n }\n }\n return startPort; // fallback\n}\n\nexport async function startServer(\n host = '127.0.0.1',\n port = 9090,\n): Promise<{ serve: () => Promise<void>; port: number }> {\n const actualPort = await findFreePort(port, host);\n const app = createApp();\n return {\n port: actualPort,\n serve: async () => {\n console.log(`AgentMoss HTTP server on ${host}:${actualPort}`);\n // @hono/node-server 动态 import(ESM 下 require 不可用)\n // 必须 await:honoServe 会起阻塞循环让进程常驻,未 await 时 main() 返回后 Node\n // 见无 pending 任务直接 exit 0,server 起不来。\n const { serve: honoServe } = await import('@hono/node-server');\n honoServe({ fetch: app.fetch, hostname: host, port: actualPort });\n },\n };\n}\n","import type { Context } from 'hono';\nimport { AnalyzeRequestSchema, AnalyzeResponseSchema, HealthResponseSchema } from './models';\nimport { runAnalysis } from './engine/coordinator';\nimport { reportEnforcementEvent } from './actrail';\n\nexport async function healthRoute(c: Context) {\n return c.json(HealthResponseSchema.parse({\n instance: process.env.AGENT_MOSS_INSTANCE || '',\n }));\n}\n\nexport async function analyzeRoute(c: Context) {\n const t0 = performance.now();\n\n try {\n const body = await c.req.json();\n const req = AnalyzeRequestSchema.parse(body);\n\n // OS auto-detect\n let osType = req.os_type;\n if (!osType) {\n osType = process.platform === 'win32' ? 'windows' : 'linux';\n }\n\n const result = await runAnalysis({\n sessionId: req.session_id,\n promptSession: req.prompt_session,\n actionHistory: req.action_history.map(h => ({\n actionType: h.action_type,\n actionDetail: h.action_detail,\n })),\n aNext: {\n actionType: req.a_next.action_type,\n actionDetail: req.a_next.action_detail,\n },\n reason: req.reason,\n osType,\n cwd: req.cwd,\n // agent_id 透传:优先顶层;为空兜底 metadata.agent_type(AgentGate V1\n // normalizer 历史上只把 agent_type 塞进 metadata,顶层 agent_id 为空 →\n // 定制规则不生效。AgentGate 已修,此处兜底防御其他只传 metadata 的调用方)。\n agentId: req.agent_id || (req.metadata as any)?.agent_type || '',\n llmConfig: (req.metadata as any)?.llm_config,\n llmLogPath: (req.metadata as any)?.llm_log_path,\n });\n\n const durationMs = performance.now() - t0;\n\n // Report enforcement event to AcTrail (fire-and-forget)\n try {\n reportEnforcementEvent({\n traceId: req.session_id,\n decision: result.allowed ? 'allow' : 'deny',\n toolName: req.a_next.action_type,\n toolCommand: req.a_next.action_detail,\n sessionId: req.session_id,\n prompt: req.prompt_session,\n riskLevel: result.riskLevel,\n riskType: result.riskType,\n reason: result.reason,\n violatedLayers: result.violatedLayers,\n confidence: result.confidence,\n durationMs: Math.round(durationMs * 10) / 10,\n });\n } catch { /* non-fatal, never block response */ }\n\n return c.json(\n AnalyzeResponseSchema.parse({\n decision: result.allowed ? 'Allow' : 'Deny',\n reason: result.reason,\n risk_level: result.riskLevel,\n risk_type: result.riskType,\n violated_layers: result.violatedLayers,\n policy: '',\n violated_policy: '',\n confidence: result.confidence,\n analysis_duration_ms: Math.round(durationMs * 10) / 10,\n })\n );\n } catch (err) {\n console.error('[AgentMoss] Analysis error:', err);\n if (err instanceof SyntaxError) {\n return c.json({ error: 'Invalid JSON', detail: err.message }, 400);\n }\n if ((err as any)?.issues) {\n return c.json({ error: 'Validation error', detail: (err as any).issues }, 400);\n }\n return c.json({ error: 'Internal error', detail: String(err) }, 500);\n }\n}\n\n","import { z } from 'zod';\nimport { version as PACKAGE_VERSION } from './package-json.js';\n\n/** Single action in history or next action */\nexport const ActionItemSchema = z.object({\n action_type: z.string().describe('Action type, e.g. bash, file_read, file_write'),\n action_detail: z.string().describe('Action detail / command content'),\n});\n\n/** A single user prompt turn with the actions it triggered (interleaved time order). */\nexport const PromptTurnSchema = z.object({\n text: z.string().default('').describe('User prompt text at this turn'),\n actions: z.array(ActionItemSchema).default([]).describe('Actions triggered by this prompt, in order, until the next prompt'),\n});\n\nexport const AnalyzeRequestSchema = z.object({\n session_id: z.string().describe('Session / agent unique identifier'),\n prompt_session: z.string().default('').describe('User original prompt (most recent user message; backward compat)'),\n prompt_history: z.array(PromptTurnSchema).default([]).describe('Full interleaved prompt history (ordered turns, each with its triggered actions). Optional; empty = fall back to prompt_session only.'),\n action_history: z.array(ActionItemSchema).default([]).describe('Historical action sequence'),\n a_next: ActionItemSchema.describe('Next action to be executed'),\n reason: z.string().default('').describe('Reason for executing this action'),\n os_type: z.string().default('').describe(\"OS type: 'linux', 'windows', or empty for auto-detect\"),\n cwd: z.string().default('').describe('Current working directory'),\n agent_id: z.string().default('').describe(\"Caller agent identifier, e.g. 'xiaoo' / 'opencode' / 'opendesk'. Empty = generic mode (no agent-specific rules).\"),\n metadata: z.record(z.unknown()).optional().describe('Extended metadata'),\n});\n\nexport const AnalyzeResponseSchema = z.object({\n decision: z.enum(['Allow', 'Deny']).describe('Allow or Deny'),\n reason: z.string().describe('Decision reason'),\n risk_level: z.enum(['low', 'medium', 'high', 'critical']).default('low'),\n risk_type: z.string().default(''),\n violated_layers: z.array(z.string()).default([]),\n policy: z.string().default(''),\n violated_policy: z.string().default(''),\n confidence: z.number().int().min(0).max(100).default(100),\n analysis_duration_ms: z.number().default(0),\n});\n\nexport const HealthResponseSchema = z.object({\n status: z.string().default('healthy'),\n version: z.string().default(PACKAGE_VERSION),\n // 归属实例标识:值来自 env AGENT_MOSS_INSTANCE(spawn/systemd 注入),默认空串。\n // 多个 agentmoss 同机并存时,调用方按 instance 过滤避免连到别人的进程。\n // 空=未配置(独立部署或旧版),调用方可选择兼容或严格过滤。\n instance: z.string().default(''),\n});\n\nexport type ActionItem = z.infer<typeof ActionItemSchema>;\nexport type AnalyzeRequest = z.infer<typeof AnalyzeRequestSchema>;\nexport type AnalyzeResponse = z.infer<typeof AnalyzeResponseSchema>;\nexport type HealthResponse = z.infer<typeof HealthResponseSchema>;\n","/**\n * Single source of truth for the package version.\n * Read from package.json at runtime using createRequire — works in both ESM and bundled environments.\n */\nimport { createRequire } from 'module';\n\nconst require = createRequire(import.meta.url);\n// Resolve relative to this source file's location → ts/package.json\nconst pkg = require('../package.json');\n\n/** Version string from package.json — the ONLY place version is defined */\nexport const version: string = pkg.version;\n","import { SecurityJudgment } from './types';\nimport { runHeuristicCheck, isInlineScriptCommand, DANGEROUS_PATTERNS } from './heuristic';\nimport { runLogicCheck, isWriteOperation } from './logic-rules';\nimport { analyzeInlineScript, isLiteralTextCommand } from './inline-analyzer';\nimport { runLLMAnalysis } from './llm-analyzer';\nimport { analyzeScriptContent as analyzeScriptChain, formatScriptChainForPrompt } from './script-content-analyzer';\nimport { isHeuristicEnabled, isLogicRulesEnabled, isLLMAvailable, isBrainEnabled } from '../config';\nimport { getAgentExtensions } from '../agents';\nimport { BrainRuleStore, PatternExtractor, checkBrainRules } from '../brain';\nimport { createBrainReviewer } from '../brain/reviewer';\n\nexport interface AnalysisInput {\n sessionId: string;\n promptSession: string;\n actionHistory: { actionType: string; actionDetail: string }[];\n /** 完整的交错历史 prompt(可选),每轮 {text, actions} 或纯文本 string(AgentGate v3 旧格式),按时间序。\n * 供 L2 意图一致性与 L3 语义分析使用;空则回退单条 promptSession。 */\n promptHistory?: ({ text: string; actions: { actionType: string; actionDetail: string }[] } | string)[];\n aNext: { actionType: string; actionDetail: string };\n reason: string;\n osType: string;\n cwd: string;\n /** 调用方 agent 标识(如 'xiaoo' / 'opencode' / 'opendesk')。空 = 通用模式。 */\n agentId: string;\n /** 可选的 per-request LLM 配置覆盖(由 OpenDesk 按当前会话模型传入) */\n llmConfig?: { baseUrl: string; apiKey: string; model: string; provider?: string };\n /** 可选的 per-request LLM prompt 日志路径(来自调用方 env,per-request 注入。\n * 跟 llmConfig 同理:调用方子进程有 AGENT_MOSS_LOG_PATH env 但服务进程不一定有,\n * 通过 metadata 注入让服务端写 [LLM_PROMPT] 日志,对齐 py _log_prompt) */\n llmLogPath?: string;\n}\n\n// ========== 快速放行白名单 ==========\n\n/** 完全安全工具:跳过 Layer 2 + Layer 3 */\nconst FULLY_SAFE_TOOLS = new Set([\n 'ask_user_question', 'glob', 'list_dir', 'ls', 'count_text_length',\n 'filemgr-globfiles',\n]);\n\n/** 内置安全 Skill 白名单(通用 baseline,agent_ext.builtin_safe_skills 会追加)。\n * 测试可 import 此常量直接断言\"无 agentId 时白名单不含某 skill\",避免走 L3\n * LLM 调用导致测试脆弱(依赖 LLM 401 fail_open 兜底)。 */\nexport const TRUSTED_SKILLS_BASE = new Set<string>([]);\n\n/** 安全但可能访问敏感路径:跳过 Layer 3,保留 Layer 2 */\nconst READONLY_SENSITIVE_TOOLS = new Set([\n 'read', 'file_read', 'read_file', 'head', 'tail', 'grep',\n 'filemgr-readfile', 'filemgr-grepfiles',\n]);\n\n/** 完全安全 bash 子命令正则 */\nconst FULLY_SAFE_BASH_PATTERNS: RegExp[] = [\n /^ls(?:\\s|$)/i, /^dir(?:\\s|$)/i,\n /^pwd(?:\\s|$)/i, /^which\\s+/i, /^whereis\\s+/i, /^realpath\\s+/i,\n /^basename\\s+/i, /^dirname\\s+/i,\n /^file\\s+/i, /^stat\\s+/i, /^du(?:\\s|$)/i,\n /^echo\\s+/i, /^printf\\s+/i,\n /^type\\s+/i, /^command\\s+/i,\n // 系统信息查询(只读,不涉及文件/网络/权限)\n /^whoami(?:\\s|$)/i, /^id(?:\\s|$)/i,\n /^hostname(?:\\s|$)/i, /^uname(?:\\s|$)/i,\n /^date(?:\\s|$)/i, /^env(?:\\s|$)/i,\n /^printenv(?:\\s|$)/i, /^tty(?:\\s|$)/i,\n /^arch(?:\\s|$)/i, /^uptime(?:\\s|$)/i,\n /^groups(?:\\s|$)/i, /^logname(?:\\s|$)/i,\n];\n\n/** 安全但可能访问敏感路径的 bash 子命令正则 */\nconst READONLY_SENSITIVE_BASH_PATTERNS: RegExp[] = [\n /^cat\\s+/i, /^head(?:\\s|$)/i, /^tail(?:\\s|$)/i,\n /^less(?:\\s|$)/i, /^more(?:\\s|$)/i, /^wc(?:\\s|$)/i,\n /^grep(?:\\s|$)/i, /^find\\s+/i, /^ag(?:\\s|$)/i, /^rg(?:\\s|$)/i,\n /^awk\\s+/i, /^sed\\s+/i, /^cut\\s+/i, /^sort(?:\\s|$)/i, /^uniq(?:\\s|$)/i,\n];\n\n/** 提取管道和链式命令的第一段 */\nfunction extractFirstCommand(command: string): string {\n let main = command.split('|')[0].trim();\n for (const sep of ['&&', '||']) {\n const idx = main.indexOf(sep);\n if (idx !== -1) {\n main = main.substring(0, idx).trim();\n break;\n }\n }\n return main;\n}\n\n/** 从 OpenDesk 格式中提取实际命令 */\nfunction extractRawCommand(detail: string): string {\n const m = detail.match(/command=([^,]+)/);\n return m ? m[1].trim() : detail;\n}\n\nfunction matchesAny(cmd: string, patterns: RegExp[]): boolean {\n return patterns.some(p => p.test(cmd));\n}\n\n// ========== Brain(默认关闭,AGENT_MOSS_BRAIN_ENABLED=1 才启用) ==========\nlet _brainStore: BrainRuleStore | null = null;\nlet _brainExtractor: PatternExtractor | null = null;\nlet _brainInitialized = false;\n\nfunction getBrainStore(): BrainRuleStore | null {\n if (!isBrainEnabled()) return null;\n if (!_brainInitialized) {\n _brainStore = new BrainRuleStore();\n _brainExtractor = new PatternExtractor(_brainStore, { review: createBrainReviewer() });\n _brainInitialized = true;\n }\n return _brainStore;\n}\n\n/** 供测试隔离:重置 brain 单例 */\nexport function _resetBrainForTest(): void {\n _brainStore = null;\n _brainExtractor = null;\n _brainInitialized = false;\n}\n\n// ========== 三层防御协调器 ==========\n\n/**\n * Three-layer defense coordinator.\n * Layer 1 → fast-pass check → Layer 2 → Layer 3.\n * Fast-pass: whitelisted safe tools/commands skip L2+L3 or L3 only.\n */\nexport async function runAnalysis(input: AnalysisInput): Promise<SecurityJudgment> {\n // Layer 1: Feature-matching static detection (fast)\n const heuristicResult = isHeuristicEnabled() ? runHeuristicCheck(input) : null;\n\n // 内联脚本/文本输出命令 file_access 假阳性防护:不立即拦截,交 inline_analyzer 静态判定\n // 因为字符串字面量中的敏感路径(如 '/etc/shadow')不应被正则误拦截\n const isInlineScriptCmd = isInlineScriptCommand(input.aNext.actionDetail.toLowerCase());\n const isLiteralTextCmd = isLiteralTextCommand(input.aNext.actionDetail.toLowerCase());\n if (heuristicResult && !heuristicResult.allowed) {\n const skipInlineFileAccess = (isInlineScriptCmd || isLiteralTextCmd) && heuristicResult.riskType === 'file_access';\n if (!skipInlineFileAccess) {\n // 对齐 py coordinator.py:172-176 should_deny_l1:\n // high/critical 直接 Deny;\n // medium + file_access(敏感路径写)确定性拦截;\n // 其他 medium(如 git push --force / rm -f 单文件 / prompt 注入 repeat-instructions)\n // 不直接 Deny,fall-through 到 L2/L3。\n const shouldDenyL1 =\n heuristicResult.riskLevel === 'high' ||\n heuristicResult.riskLevel === 'critical' ||\n (heuristicResult.riskLevel === 'medium' && heuristicResult.riskType === 'file_access');\n if (shouldDenyL1) {\n return heuristicResult;\n }\n }\n }\n\n // ===== L1.5: Script content pre-scan (recursive chain + L1 reuse) =====\n // For bash actions invoking a script, recursively track the call chain,\n // preprocess, and scan each node with runHeuristicCheck (L1). high/critical\n // deny directly (layer \"1.1-script\"). Catches \"rm -rf /\" inside a script\n // whose entry command is just \"bash deploy.sh\". Reduces L3 token use.\n let scriptChain: ReturnType<typeof analyzeScriptChain> | null = null;\n if (input.aNext.actionType.toLowerCase() === 'bash') {\n scriptChain = analyzeScriptChain(input);\n if (scriptChain.nodes.length > 0) {\n for (const node of scriptChain.nodes) {\n if (node.l1Hit && (node.l1RiskLevel === 'high' || node.l1RiskLevel === 'critical')) {\n return {\n allowed: false,\n reason: `脚本内容包含危险操作: ${node.l1Reason} (文件: ${node.scriptPath}, 深度: ${node.depth})`,\n riskLevel: node.l1RiskLevel as SecurityJudgment['riskLevel'],\n riskType: node.l1RiskType,\n confidence: 90,\n source: 'heuristic_script_scan',\n violatedLayers: ['1.1-script'],\n };\n }\n }\n }\n }\n\n // ===== Brain L1 rule check (only when brain enabled) =====\n const brainStore = getBrainStore();\n if (brainStore) {\n const brainL1 = checkBrainRules(brainStore, {\n layer: 1,\n actionType: input.aNext.actionType,\n actionDetail: input.aNext.actionDetail,\n });\n if (brainL1) {\n return {\n allowed: false,\n reason: `[Brain L1] ${brainL1.explanation}`,\n riskLevel: 'high',\n riskType: 'brain_rule',\n confidence: Math.round(brainL1.confidence * 100),\n source: 'brain_rule',\n violatedLayers: ['brain_L1'],\n };\n }\n }\n\n // ===== Fast-pass check =====\n const actionType = input.aNext.actionType.toLowerCase();\n const rawDetail = extractRawCommand(input.aNext.actionDetail);\n const lowerDetail = rawDetail.toLowerCase();\n // agent 专属扩展(agent_moss/agents/<id>/rules.json),取一次供 fast-pass 各白名单复用\n const agentExt = getAgentExtensions(input.agentId);\n\n // Fully safe tools: skip L2 + L3\n if (FULLY_SAFE_TOOLS.has(actionType)) {\n return {\n allowed: true,\n reason: `完全安全工具,跳过深度分析: ${actionType}`,\n riskLevel: (heuristicResult?.riskLevel || 'low') as SecurityJudgment['riskLevel'],\n riskType: '',\n confidence: 95,\n source: 'whitelist_bypass',\n violatedLayers: [],\n };\n }\n\n // agent 专属完全安全操作白名单(精确名或前缀,来自 rules.json builtin_safe_action_types)。\n // 前缀以 '-' 结尾 → startswith 匹配(如 \"memory-\");否则精确名匹配(如 \"mailbox-getEmailList\")。\n // 命中即跳过 L2+L3,与 builtin_safe_skills 同范式。仅对该 agent_id 生效,不污染其他 agent。\n // OpenDesk 的 memory-*/todomgr-*/planning-* 是纯数据/只读操作,走 L3 LLM 耗时 1~137s 无意义。\n if (agentExt?.builtin_safe_action_types && agentExt.builtin_safe_action_types.length > 0) {\n // actionType 已小写化(:143);rules.json 精确名可能是驼峰(如 mailbox-getEmailList),\n // 故比较时对白名单项也 lower。前缀项(尾随 '-')同样 lower 后 startswith。\n const hit = agentExt.builtin_safe_action_types.some(t => {\n const tl = t.toLowerCase();\n return tl.endsWith('-') ? actionType.startsWith(tl) : actionType === tl;\n });\n if (hit) {\n return {\n allowed: true,\n reason: `agent 内部安全操作,跳过深度分析: ${actionType}`,\n riskLevel: (heuristicResult?.riskLevel || 'low') as SecurityJudgment['riskLevel'],\n riskType: '',\n confidence: 95,\n source: 'whitelist_bypass',\n violatedLayers: [],\n };\n }\n }\n\n // 内置安全 Skill 直接放行(通用 baseline + agent_ext.builtin_safe_skills)\n const trustedSkills = new Set<string>(TRUSTED_SKILLS_BASE);\n if (agentExt?.builtin_safe_skills) {\n for (const s of agentExt.builtin_safe_skills) trustedSkills.add(s);\n }\n if (actionType === 'skill' && trustedSkills.has(lowerDetail)) {\n return {\n allowed: true,\n reason: `内置安全 Skill,跳过深度分析: ${lowerDetail}`,\n riskLevel: (heuristicResult?.riskLevel || 'low') as SecurityJudgment['riskLevel'],\n riskType: '',\n confidence: 95,\n source: 'whitelist_bypass',\n violatedLayers: [],\n };\n }\n\n // Readonly sensitive tools: skip L3, continue to L2\n let skipLLM = READONLY_SENSITIVE_TOOLS.has(actionType);\n\n // Bash sub-command checks\n if (actionType === 'bash' || actionType === 'executebash' || actionType === 'terminal-executebash') {\n const firstCmd = extractFirstCommand(lowerDetail);\n if (matchesAny(firstCmd, FULLY_SAFE_BASH_PATTERNS)) {\n // 安全兜底 1:检查完整命令是否命中高危模式(如 echo ... | passwd)\n const fullCmdHit = DANGEROUS_PATTERNS.some(p =>\n p.severity === 'critical' || p.severity === 'high'\n ) && DANGEROUS_PATTERNS.some(p =>\n (p.severity === 'critical' || p.severity === 'high') && p.pattern.test(lowerDetail)\n );\n // 安全兜底 2:检查是否含真实重定向写(echo x > file / printf >> file)。\n // is_fully_safe_bash_command 只看首命令名(echo),会忽略 >/>> 重定向,\n // 导致 `echo x > /tmp/existing.txt` 覆写已存在文件被白名单放行跳过 L2(Bug3)。\n // 复用 isWriteOperation 的重定向判定(已剥 devnull + 比较运算符 + 只读首词保护)。\n const hasRedirectWrite = isWriteOperation(firstCmd, lowerDetail);\n if (!fullCmdHit && !hasRedirectWrite) {\n return {\n allowed: true,\n reason: `安全的只读 bash 命令: ${firstCmd}`,\n riskLevel: 'low',\n riskType: '',\n confidence: 95,\n source: 'whitelist_bypass',\n violatedLayers: [],\n };\n }\n }\n if (matchesAny(firstCmd, READONLY_SENSITIVE_BASH_PATTERNS)) {\n skipLLM = true;\n }\n }\n\n // Layer 2: Logic rule detection (fast)\n const logicResult = isLogicRulesEnabled() ? runLogicCheck(input) : null;\n // file_access 命中合并:敏感路径/危险模式现已在 L1(heuristicResult),\n // 间接文件访问仍在 L2(logicResult)。两者任一命中 file_access 都需进入\n // inline/credential 包装判定。优先采用 logicResult,退而取 heuristicResult。\n const l1FileAccessHit = !!(heuristicResult && !heuristicResult.allowed && heuristicResult.riskType === 'file_access');\n const effectiveResult = (logicResult && !logicResult.allowed) ? logicResult\n : (l1FileAccessHit ? heuristicResult : null);\n if (effectiveResult) {\n // 凭据文件:无论读写、无论是否 inline,都直接拒绝。\n // 来源:L1 sensitive path(isCredential)或 L2 indirect_file_access\n const isCredentialPath = !!effectiveResult.isCredential;\n // 内联脚本/文本输出命令:走静态语义判定,区分\"文本字面量\"vs\"真实读写\"。\n // 即使是凭据路径(如 deny_both 的 /etc/shadow),只要它是字符串字面量\n // (python -c \"print('/etc/shadow')\"),inline_analyzer 判 Allow 时应放行——\n // 因为并未真实读取该文件。actionable=false(提取不到代码)时才回退到\n // 凭据/敏感路径的硬拒绝。\n const skipInlineFileAccess = (isInlineScriptCmd || isLiteralTextCmd) && effectiveResult.riskType === 'file_access';\n if (skipInlineFileAccess) {\n const inlineJudgment = analyzeInlineScript(input.aNext.actionDetail);\n if (inlineJudgment.actionable) {\n if (!inlineJudgment.allowed) {\n return {\n allowed: false,\n reason: inlineJudgment.reason,\n riskLevel: inlineJudgment.riskLevel as SecurityJudgment['riskLevel'],\n riskType: inlineJudgment.riskType,\n confidence: 90,\n source: 'logic_rule',\n violatedLayers: ['1.2'],\n };\n }\n // 字面量 → Allow,不再走 Layer 3\n return {\n allowed: true,\n reason: inlineJudgment.reason,\n riskLevel: inlineJudgment.riskLevel as SecurityJudgment['riskLevel'],\n riskType: inlineJudgment.riskType,\n confidence: 90,\n source: 'logic_rule',\n violatedLayers: [],\n };\n }\n // actionable=false(提取不到代码)→ 回退原逻辑:high/critical 直接 Deny\n }\n if ((effectiveResult.riskLevel === 'high' || effectiveResult.riskLevel === 'critical') && (!skipInlineFileAccess || isCredentialPath)) {\n return effectiveResult;\n }\n // medium/low 风险:不直接拦截,走层3 LLM 语义判断\n }\n\n // ===== L2.5: Script content L2 scan (per-node sensitive path / dangerous\n // pattern / intent reuse on preprocessed content). high/critical deny\n // directly (layer \"1.2-script\"). =====\n if (scriptChain && scriptChain.nodes.length > 0 && isLogicRulesEnabled()) {\n for (const node of scriptChain.nodes) {\n if (node.error || !node.preprocessedContent) continue;\n if (node.l1RiskLevel === 'critical') break;\n if (node.l2Hit && (node.l2RiskLevel === 'high' || node.l2RiskLevel === 'critical')) {\n return {\n allowed: false,\n reason: node.l2Reason,\n riskLevel: node.l2RiskLevel as SecurityJudgment['riskLevel'],\n riskType: node.l2RiskType,\n confidence: 85,\n source: 'logic_rule_script_scan',\n violatedLayers: ['1.2-script'],\n };\n }\n }\n }\n\n // ===== Brain L2 rule check (only when brain enabled) =====\n if (brainStore) {\n const brainL2 = checkBrainRules(brainStore, {\n layer: 2,\n actionType: input.aNext.actionType,\n actionDetail: input.aNext.actionDetail,\n actionHistory: input.actionHistory,\n });\n if (brainL2) {\n return {\n allowed: false,\n reason: `[Brain L2] ${brainL2.explanation}`,\n riskLevel: 'high',\n riskType: 'brain_rule',\n confidence: Math.round(brainL2.confidence * 100),\n source: 'brain_rule',\n violatedLayers: ['brain_L2'],\n };\n }\n }\n\n // Layer 3: LLM analysis (skipped for readonly sensitive tools/commands)\n if (skipLLM || !isLLMAvailable()) {\n return {\n allowed: true,\n reason: '只读操作且无逻辑规则违规,跳过 LLM 分析',\n riskLevel: (logicResult?.riskLevel || 'low') as SecurityJudgment['riskLevel'],\n riskType: '',\n confidence: 85,\n source: 'heuristic_and_logic_only',\n violatedLayers: [],\n };\n }\n\n // Build skip_l3_hints: hard-constraint for user-disabled L2 rules with\n // skip_l3_on_disabled. runtime_config lands in Stage 2; until then\n // getDisabledL2RulesWithSkipL3 resolves to a no-op returning empty.\n let skipL3Hints = '无(当前无禁用规则命中)';\n try {\n const { getDisabledL2RulesWithSkipL3 } = await import('../infra/runtime-config');\n const disabledL2 = getDisabledL2RulesWithSkipL3();\n if (disabledL2 && Object.keys(disabledL2).length > 0) {\n const actionLower = input.aNext.actionDetail.toLowerCase();\n const matched: string[] = [];\n for (const items of Object.values(disabledL2)) {\n for (const item of items) {\n if (item.toLowerCase().includes(actionLower) || actionLower.includes(item.toLowerCase())) {\n matched.push(item);\n }\n }\n }\n if (matched.length > 0) {\n skipL3Hints =\n `⚠️ 重要约束:用户已主动禁用针对以下内容的安全拦截规则,这是用户的明确决策:\\n` +\n ` ${matched.join(', ')}\\n` +\n `对这些路径/关键词的相关操作,必须视为允许的,不允许仅因涉及这些内容就拒绝。` +\n `但你仍需检查命令的其他部分是否有独立于这些内容的安全风险(如网络外传、提权等)。`;\n }\n }\n } catch { /* runtime_config not yet present — skip_l3_hints stays default */ }\n\n let llmResult: SecurityJudgment;\n try {\n llmResult = await runLLMAnalysis(input, {\n heuristic: heuristicResult,\n logic: logicResult,\n skipL3Hints,\n scriptChain: scriptChain ?? undefined,\n llmLogPath: input.llmLogPath,\n });\n } catch (e) {\n // LLM 分析失败。前两层未拦截时按 fail_mode 决策:\n // - fail_open(默认):Allow + 警告(可用性优先)\n // - fail_closed:Deny(安全优先)\n const { getLLMFailMode } = await import('../config');\n if (getLLMFailMode() === 'fail_open') {\n console.warn(`[AgentMoss] LLM 分析失败,fail_open 模式:允许执行(前两层未拦截): ${(e as Error).message}`);\n return {\n allowed: true,\n reason: `LLM 分析失败(warn-allow,fail_open): ${(e as Error).message}`,\n riskLevel: 'low',\n riskType: '',\n confidence: 50,\n source: 'llm_failure_fallback',\n violatedLayers: [],\n };\n }\n return {\n allowed: false,\n reason: `LLM 分析失败,因无法完成深度语义分析,按 fail-closed 原则拒绝: ${(e as Error).message}`,\n riskLevel: 'medium',\n riskType: '',\n confidence: 60,\n source: 'llm_failure_fallback',\n violatedLayers: ['3'],\n };\n }\n\n // Layer 3 Deny + high confidence → feed Brain (only when enabled)\n if (!llmResult.allowed && llmResult.confidence && llmResult.confidence >= 90 && _brainExtractor) {\n try {\n await _brainExtractor.extract(\n { actionDetail: input.aNext.actionDetail, eventId: '' },\n {\n confidence: llmResult.confidence / 100,\n reason: llmResult.reason || '',\n riskType: llmResult.riskType || '',\n actionDetail: input.aNext.actionDetail,\n },\n );\n } catch {\n // Brain extraction failure must not affect main flow\n }\n }\n\n return llmResult;\n}\n","import { SecurityJudgment } from './types';\nimport type { AnalysisInput } from './coordinator';\nimport { getLLMConfig, isLLMAvailable, detectProvider, getProviderHeaders, getTimeoutConfig, getRetryConfig } from '../config';\nimport { matchSkills, formatSkillsForPrompt } from './skill-loader';\nimport { loadTemplates } from './template-loader';\nimport { analyzeScriptContent, formatScriptAnalysisForPrompt } from './script-analyzer';\nimport { formatScriptChainForPrompt } from './script-content-analyzer';\nimport { appendFileSync } from 'fs';\nimport OpenAI from 'openai';\n\n// LRU cache to avoid duplicate LLM calls for identical commands\nconst llmCache = new Map<string, SecurityJudgment>();\nconst LLM_CACHE_MAX = 200;\n\ninterface PreviousResults {\n heuristic: SecurityJudgment | null;\n logic: SecurityJudgment | null;\n skipL3Hints?: string;\n scriptChain?: import('./script-content-analyzer').ScriptChainAnalysisResult;\n /** per-request LLM prompt 日志路径(来自调用方 metadata.llm_log_path) */\n llmLogPath?: string;\n}\n\n/**\n * Layer 3: LLM + Skill semantic analysis.\n * Only called when layers 1 and 2 both pass.\n * Loads skills from the shared skills directory and uses LLM for deep analysis.\n */\nexport async function runLLMAnalysis(\n input: AnalysisInput,\n previous: PreviousResults\n): Promise<SecurityJudgment> {\n if (!isLLMAvailable()) {\n console.log('[AgentMoss] LLM not configured, skipping deep analysis');\n return {\n allowed: true,\n reason: 'LLM 未配置,跳过深层分析',\n riskLevel: 'low',\n riskType: '',\n confidence: 50,\n source: 'llm',\n violatedLayers: [],\n };\n }\n\n // 优先使用 per-request 的 LLM 配置(OpenDesk 按当前会话模型传入)\n const globalConfig = getLLMConfig();\n const config = input.llmConfig?.apiKey\n ? { ...globalConfig, ...input.llmConfig }\n : globalConfig;\n\n // Check LRU cache (use raw command as key, strip OpenDesk metadata)\n const rawDetail = input.aNext.actionDetail.replace(/^terminal-\\w+:\\s*command=([^,]+).*/, '$1').trim();\n const cacheKey = `${input.aNext.actionType}:${rawDetail || input.aNext.actionDetail}`;\n const cached = llmCache.get(cacheKey);\n if (cached) {\n console.log('[AgentMoss] LLM cache hit');\n return cached;\n }\n\n // Load skills and templates (cached)\n const matchedSkills = matchSkills(input.aNext.actionType, input.aNext.actionDetail, input.reason);\n const templates = loadTemplates();\n\n // Build the analysis prompt. Prefer the script chain from coordinator\n // (L1.5/L2.5 already did recursive tracking); fall back to single-file scan.\n let scriptAnalysis: import('./script-analyzer').ScriptAnalysisResult | undefined;\n let scriptChainText = '';\n if (previous.scriptChain) {\n scriptChainText = formatScriptChainForPrompt(previous.scriptChain);\n } else {\n scriptAnalysis = analyzeScriptContent(input.aNext.actionType, input.aNext.actionDetail);\n }\n const prompt = buildPrompt(input, previous, matchedSkills, templates, scriptAnalysis, previous.skipL3Hints ?? '', scriptChainText);\n\n // 写 LLM prompt 到日志(per-request logPath 优先,对齐 py _log_prompt)。\n // 与 bridge.ts 写 HOOK_INPUT/HOOK_OUTPUT 同一个文件,对齐 audit_agent AUDIT_LOG_PATH。\n logPrompt(prompt, input.aNext, previous.llmLogPath);\n\n // Call LLM\n const result = await analyzeWithLLM(prompt, config);\n\n // Cache result\n if (llmCache.size >= LLM_CACHE_MAX) {\n const firstKey = llmCache.keys().next().value;\n if (firstKey) llmCache.delete(firstKey);\n }\n llmCache.set(cacheKey, result);\n\n return result;\n}\n\n/**\n * 写 LLM prompt 到日志文件(对齐 Python _log_prompt)。\n * logPath 来自 per-request metadata.llm_log_path(调用方 env 注入)。\n * 与 bridge.ts 的 HOOK_INPUT/HOOK_OUTPUT 写同一个文件,对齐 audit_agent AUDIT_LOG_PATH。\n */\nfunction logPrompt(prompt: string, aNext: { actionType: string; actionDetail: string }, logPath?: string): void {\n if (!logPath) return;\n try {\n const actionType = aNext.actionType || 'unknown';\n const actionDetail = (aNext.actionDetail || '').slice(0, 100);\n const line =\n `[${new Date().toISOString()}] ` +\n `[LLM_PROMPT] action_type=${actionType}, action_detail=${actionDetail}... ` +\n `prompt_length=${prompt.length}\\n` +\n `${prompt}\\n` +\n `--- END PROMPT ---\\n`;\n appendFileSync(logPath, line, 'utf-8');\n } catch (e) {\n console.warn('[AgentMoss] Failed to write LLM prompt to log:', e);\n }\n}\n\nexport function buildPrompt(\n input: AnalysisInput,\n previous: PreviousResults,\n matchedSkills: import('./skill-loader').SkillMatch[],\n templates: Record<string, string>,\n scriptAnalysis?: import('./script-analyzer').ScriptAnalysisResult,\n skipL3Hints: string = '',\n scriptChainText: string = '',\n): string {\n const skillsText = formatSkillsForPrompt(matchedSkills);\n const historyStr = input.actionHistory\n .map((h, i) => `${i + 1}. ${h.actionType}: ${h.actionDetail}`)\n .join('\\n') || '(无历史操作)';\n\n // 交错历史 prompt(供 LLM 判断意图一致性,避免\"继续\"覆盖初始意图)。\n const promptHistoryText = formatPromptHistory(input.promptHistory);\n\n // Prefer coordinator-provided script chain text (recursive tracking result);\n // fall back to single-file keyword prescan; else empty.\n const scriptAnalysisText = scriptChainText\n ? scriptChainText\n : (scriptAnalysis ? formatScriptAnalysisForPrompt(scriptAnalysis) : '');\n\n // Format L1/L2 hints (mirrors Python LLMAnalyzer._format_hints)\n const hintsText = formatHints(previous);\n\n // Layer 3 安全判断用 security_judge_template(对齐 Python get_security_judge_prompt)。\n // prompt1/prompt2 是 Cerberus 沙箱策略模板,不适用于此处的 Allow/Deny 裁决。\n const securityJudgeTemplate = templates['security_judge'];\n if (securityJudgeTemplate) {\n // 占位符逐个替换(不能用全局 {x} 正则:模板 JSON 示例里的 {{ }} 会误伤)。\n // security_judge_template.txt 用 {{ }} 转义 JSON 大括号,替换完后还原为单括号。\n return securityJudgeTemplate\n .replaceAll('{prompt_session}', input.promptSession || '(未提供)')\n .replaceAll('{prompt_history_text}', promptHistoryText)\n .replaceAll('{action_history}', historyStr)\n .replaceAll('{action_type}', input.aNext.actionType)\n .replaceAll('{action_detail}', input.aNext.actionDetail)\n .replaceAll('{reason}', input.reason || '未说明')\n .replaceAll('{skills_text}', skillsText)\n .replaceAll('{hints_text}', hintsText)\n .replaceAll('{script_analysis_text}', scriptAnalysisText)\n .replaceAll('{skip_l3_hints}', skipL3Hints)\n .replaceAll('{{', '{')\n .replaceAll('}}', '}');\n }\n\n // Fallback:security_judge 模板缺失时(旧包/加载异常),退回稀疏 prompt,避免崩溃。\n // 这种情况下 LLM 裸跑,判断质量下降,但不阻断流程。\n console.warn('[AgentMoss] security_judge template missing, using sparse fallback prompt');\n return `## 当前操作上下文\n- 会话 ID: ${input.sessionId}\n- 用户任务: ${input.promptSession || '未指定'}\n- 操作系统: ${input.osType}\n- 工作目录: ${input.cwd || '/'}\n- 操作原因: ${input.reason || '未说明'}\n- 历史操作序列:\n${historyStr}\n\n- 即将执行的操作:\n 类型: ${input.aNext.actionType}\n 详情: ${input.aNext.actionDetail}\n\n## 可用安全 Skill\n${skillsText}\n\n## 前置检测结果\n${hintsText}\n${scriptAnalysisText ? `\\n## 脚本内容分析\\n${scriptAnalysisText}` : ''}\n\n请根据以上信息,对即将执行的操作进行安全判断。前置检测为 low/medium 且有合理执行理由时应当允许。你必须输出严格的 JSON 格式,不要包含任何其他文字、注释或 markdown 标记。\n\n输出格式:\n{\"allowed\": true/false, \"reason\": \"判断理由\", \"riskLevel\": \"low|medium|high|critical\", \"riskType\": \"风险类型\", \"confidence\": 0-100}`;\n}\n\n/** 格式化交错历史 prompt 为 LLM 可读文本(对齐 Python LLMAnalyzer._format_prompt_history)。 */\nfunction formatPromptHistory(\n promptHistory?: AnalysisInput['promptHistory'],\n maxTextChars = 500,\n): string {\n if (!promptHistory || promptHistory.length === 0) {\n return '(未提供历史意图)';\n }\n const lines: string[] = [];\n for (let i = 0; i < promptHistory.length; i++) {\n const turn = promptHistory[i];\n // 兼容两种元素格式:纯文本 string(AgentGate v3 旧格式)与 {text, actions} dict\n const text = (typeof turn === 'string' ? turn : (turn?.text || '')).trim();\n if (!text) continue;\n let line = ` 第${i + 1}轮用户意图: ${text.slice(0, maxTextChars)}`;\n const actions = typeof turn === 'string' ? undefined : turn?.actions;\n if (actions && actions.length > 0) {\n const types = actions\n .map(a => a?.actionType)\n .filter((t): t is string => typeof t === 'string' && t.length > 0);\n if (types.length > 0) {\n line += ` → 动作: ${types.join(', ')}`;\n }\n }\n lines.push(line);\n }\n return lines.length > 0 ? lines.join('\\n') : '(未提供历史意图)';\n}\n\nfunction formatHints(previous: PreviousResults): string {\n const hints: string[] = [];\n\n if (previous.heuristic) {\n hints.push(\n `特征匹配检测发现风险 [风险等级: ${previous.heuristic.riskLevel}]:\\n` +\n ` 类型: ${previous.heuristic.riskType}\\n` +\n ` 原因: ${previous.heuristic.reason}`\n );\n }\n\n if (previous.logic) {\n hints.push(\n `逻辑规则检测发现风险 [风险等级: ${previous.logic.riskLevel}]:\\n` +\n ` 类型: ${previous.logic.riskType}\\n` +\n ` 原因: ${previous.logic.reason}`\n );\n }\n\n return hints.length > 0 ? hints.join('\\n\\n') : '特征匹配检测和逻辑规则检测均未发现风险。';\n}\n\nasync function analyzeWithLLM(prompt: string, config: ReturnType<typeof getLLMConfig>): Promise<SecurityJudgment> {\n console.log(`[AgentMoss] LLM analyzing with model: ${config.model}, url: ${config.baseUrl}`);\n\n const provider = detectProvider(config.baseUrl, config.provider);\n const extraHeaders = getProviderHeaders(provider);\n if (Object.keys(extraHeaders).length > 0) {\n console.log(`[AgentMoss] Provider detected: ${provider}, injecting headers: ${Object.keys(extraHeaders).join(', ')}`);\n }\n\n const timeoutCfg = getTimeoutConfig();\n const retryCfg = getRetryConfig();\n const client = new OpenAI({\n baseURL: config.baseUrl,\n apiKey: config.apiKey,\n // 单次 LLM 调用超时用 prompt1Timeout(对齐 py);env 覆盖的 config.timeout 仍向后兼容\n timeout: (config.timeout || timeoutCfg.prompt1Timeout) * 1000,\n defaultHeaders: Object.keys(extraHeaders).length > 0 ? extraHeaders : undefined,\n });\n\n // maxRetries 优先 env,否则用 retry 配置(默认 2,对齐 py)\n const maxRetries = parseInt(process.env.AGENT_MOSS_LLM_RETRIES || String(retryCfg.maxRetries), 10);\n\n // totalTimeout 强制执行:用 AbortController 确保整个 LLM 分析(含所有重试)\n // 在 totalTimeout(默认 90s)后强制中断,防止最坏情况 ~372s 超时。\n const totalTimeoutMs = timeoutCfg.totalTimeout * 1000;\n const abortController = new AbortController();\n const totalTimeoutTimer = setTimeout(() => {\n console.error(`[AgentMoss] totalTimeout (${timeoutCfg.totalTimeout}s) exceeded, aborting all LLM calls`);\n abortController.abort();\n }, totalTimeoutMs);\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n if (abortController.signal.aborted) {\n break;\n }\n try {\n const response = await client.chat.completions.create({\n model: config.model,\n temperature: config.temperature || 0.1,\n max_tokens: config.maxTokens || 1024,\n messages: [\n { role: 'system', content: '只输出纯 JSON,不要包含 markdown 标记、代码块或任何其他文字。' },\n { role: 'user', content: prompt },\n ],\n signal: abortController.signal,\n } as any);\n\n const content = response.choices[0]?.message?.content || '{}';\n console.log(`[AgentMoss] LLM raw response (attempt ${attempt + 1}/${maxRetries + 1}): ${content.substring(0, 300)}`);\n\n let jsonStr = content.trim();\n if (jsonStr.startsWith('```')) {\n jsonStr = jsonStr.replace(/^```[\\w]*\\n?/, '').replace(/\\n?```$/, '');\n }\n const parsed = JSON.parse(jsonStr);\n\n // 记录 token 用量(step=\"L3_security_judge\")\n try {\n const usage = response.usage;\n const { recordTokenUsage } = await import('./token-stats');\n recordTokenUsage({\n sessionId: 'audit',\n step: 'L3_security_judge',\n model: response.model || config.model,\n promptTokens: usage?.prompt_tokens || 0,\n completionTokens: usage?.completion_tokens || 0,\n totalTokens: usage?.total_tokens || 0,\n });\n } catch { /* token stats optional */ }\n\n clearTimeout(totalTimeoutTimer);\n // LLM 回 JSON 字段名可能是 camelCase(riskLevel)或 snake_case(risk_level),\n // 两种都兼容避免拿不到 risk_level 走兜底 'low'(双端对齐 Python 字段名)\n const riskLevel = parsed.riskLevel ?? parsed.risk_level;\n const riskType = parsed.riskType ?? parsed.risk_type;\n return {\n allowed: parsed.allowed !== false,\n reason: parsed.reason || 'LLM 分析完成',\n riskLevel: ['low', 'medium', 'high', 'critical'].includes(riskLevel) ? riskLevel : 'low',\n riskType: riskType || '',\n confidence: typeof parsed.confidence === 'number' ? Math.min(100, Math.max(0, parsed.confidence)) : 70,\n source: 'llm',\n violatedLayers: ['3'],\n };\n } catch (err) {\n // totalTimeout 触发的 AbortError:直接跳出循环,不再重试\n if (abortController.signal.aborted) {\n console.error(`[AgentMoss] LLM analysis aborted by totalTimeout (${timeoutCfg.totalTimeout}s)`);\n break;\n }\n if (attempt < maxRetries) {\n console.error(`[AgentMoss] LLM call failed (attempt ${attempt + 1}/${maxRetries + 1}), retrying in ${retryCfg.retryInterval}s:`, (err as Error).message);\n await new Promise(resolve => setTimeout(resolve, retryCfg.retryInterval * 1000));\n } else {\n clearTimeout(totalTimeoutTimer);\n console.error('[AgentMoss] LLM call failed after all retries:', (err as Error).message);\n throw new Error(`LLM 分析失败 (${maxRetries + 1} 次尝试): ${(err as Error).message}`);\n }\n }\n }\n\n // totalTimeout 超时或 AbortError 导致循环中断\n clearTimeout(totalTimeoutTimer);\n throw new Error(`LLM 分析超时(totalTimeout ${timeoutCfg.totalTimeout}s)`);\n}\n","import { readFileSync, existsSync } from 'fs';\nimport { resolve, dirname } from 'path';\nimport { fileURLToPath } from 'url';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n// 优先用打包内联目录 dist/templates(npm 安装后自包含);\n// dev 模式(vitest 测试时 __dirname=ts/src/engine)回退到仓库根 agent_moss/templates。\n// 注意:从 ts/src/engine 出发,仓库根 agent_moss/templates 在 ../../../agent_moss/templates\n// (不能写 ../../agent_moss/templates,那是 ts/agent_moss/templates,不存在)。\nconst TEMPLATES_DIR = resolve(__dirname, '../templates');\nconst TEMPLATES_DIR_FALLBACK = resolve(__dirname, '../../../agent_moss/templates');\n\nconst TEMPLATE_FILES = ['prompt1_template.txt', 'prompt2_template.txt', 'security_judge_template.txt'];\n\nlet cachedTemplates: Record<string, string> | null = null;\n\nexport function loadTemplates(): Record<string, string> {\n if (cachedTemplates) return cachedTemplates;\n\n cachedTemplates = {};\n\n const dir = existsSync(TEMPLATES_DIR) ? TEMPLATES_DIR : TEMPLATES_DIR_FALLBACK;\n if (!existsSync(dir)) {\n console.warn('[AgentMoss] Templates directory not found:', TEMPLATES_DIR, 'and fallback:', TEMPLATES_DIR_FALLBACK);\n return cachedTemplates;\n }\n\n for (const file of TEMPLATE_FILES) {\n const filePath = resolve(dir, file);\n if (existsSync(filePath)) {\n const key = file.replace('.txt', '').replace('_template', '');\n cachedTemplates[key] = readFileSync(filePath, 'utf-8');\n }\n }\n\n console.log(`[AgentMoss] Loaded ${Object.keys(cachedTemplates).length} templates from ${dir}`);\n return cachedTemplates;\n}\n\nexport function reloadTemplates(): void {\n cachedTemplates = null;\n loadTemplates();\n}\n","import { readFileSync } from 'fs';\nimport { resolve, join } from 'path';\n\n/**\n * Script content pre-scanning — detects suspicious patterns in bash scripts.\n * When a script execution is detected, reads up to 500 lines and scans for\n * high-risk patterns (network exfil, reverse shells, base64 obfuscation,\n * sensitive file access, persistence backdoors).\n */\n\n// High-risk detection patterns\nconst SUSPICIOUS_PATTERNS: { name: string; pattern: RegExp }[] = [\n // Network exfiltration (curl/wget POST in scripts is almost never legitimate)\n { name: 'curl POST', pattern: /curl\\s+(.*\\s)?-X\\s+POST/i },\n { name: 'curl --data', pattern: /curl\\s+(.*\\s)?--data/i },\n { name: 'curl -d', pattern: /curl\\s+(.*\\s)?-d\\s/i },\n { name: 'wget --post-data', pattern: /wget\\s+(.*\\s)?--post-data/i },\n { name: 'wget --post-file', pattern: /wget\\s+(.*\\s)?--post-file/i },\n // Reverse shell\n { name: 'nc -e', pattern: /\\bnc\\s+.*-e\\b/ },\n { name: 'ncat -e', pattern: /\\bncat\\s+.*-e\\b/ },\n { name: '/dev/tcp', pattern: /\\/dev\\/tcp\\// },\n { name: '/dev/udp', pattern: /\\/dev\\/udp\\// },\n // Base64 obfuscation\n { name: '$(base64', pattern: /\\$\\(\\s*base64/ },\n { name: '`base64', pattern: /`\\s*base64/ },\n { name: 'base64 decode pipe', pattern: /base64\\s+(-d|--decode)\\s*\\|/ },\n // Sensitive file access\n { name: '/etc/shadow', pattern: /\\/etc\\/shadow/ },\n { name: 'id_rsa', pattern: /\\bid_rsa\\b/ },\n { name: 'id_ed25519', pattern: /\\bid_ed25519\\b/ },\n // Persistence backdoor\n { name: 'crontab install', pattern: /crontab\\s+-/ },\n { name: 'authorized_keys', pattern: /authorized_keys/ },\n { name: 'ssh no host key check', pattern: /ssh\\s+.*StrictHostKeyChecking\\s*=\\s*no/ },\n];\n\n// Script execution patterns\nconst SCRIPT_EXEC_PATTERNS = [\n /bash\\s+(\\S+\\.sh)/,\n /sh\\s+(\\S+\\.sh)/,\n /\\.\\/(\\S+\\.sh)/,\n /source\\s+(\\S+\\.sh)/,\n /\\.\\s+(\\S+\\.sh)/,\n /zsh\\s+(\\S+\\.sh)/,\n];\n\n// Keyword combination risk rules\nconst KEYWORD_COMBINATION_RISKS: { group1: Set<string>; group2: Set<string>; level: string; reason: string }[] = [\n {\n group1: new Set(['curl POST', 'curl --data', 'curl -d', 'wget --post-data', 'wget --post-file']),\n group2: new Set(['$(base64', '`base64', 'base64 decode pipe']),\n level: 'critical',\n reason: '检测到网络数据发送 + Base64编码组合,构成 Critical 级别数据外传风险。攻击者可能将敏感数据编码后外传。',\n },\n {\n group1: new Set(['curl POST', 'curl --data', 'curl -d', 'wget --post-data', 'wget --post-file']),\n group2: new Set(['/etc/shadow', 'id_rsa', 'id_ed25519']),\n level: 'critical',\n reason: '检测到网络数据发送 + 敏感文件访问组合,构成 Critical 级别凭证外传风险。',\n },\n {\n group1: new Set(['nc -e', 'ncat -e', '/dev/tcp', '/dev/udp']),\n group2: new Set(),\n level: 'high',\n reason: '检测到反弹 Shell 特征,攻击者可能建立远程控制通道。',\n },\n {\n group1: new Set(['crontab install', 'authorized_keys', 'ssh no host key check']),\n group2: new Set(),\n level: 'high',\n reason: '检测到持久化后门特征,攻击者可能在系统中植入后门。',\n },\n];\n\nconst SINGLE_KEYWORD_RISKS: Record<string, { level: string; reason: string }> = {\n 'curl POST': { level: 'high', reason: '检测到 curl POST 请求,可能向外部服务器发送数据。' },\n 'curl --data': { level: 'high', reason: '检测到 curl --data 参数,可能向外部服务器发送数据。' },\n 'curl -d': { level: 'high', reason: '检测到 curl -d 参数,可能向外部服务器发送数据。' },\n 'wget --post-data': { level: 'high', reason: '检测到 wget POST 请求,可能向外部服务器发送数据。' },\n 'wget --post-file': { level: 'high', reason: '检测到 wget 文件上传,可能向外部服务器发送文件。' },\n 'nc -e': { level: 'critical', reason: '检测到 nc -e 反弹 Shell 特征。' },\n 'ncat -e': { level: 'critical', reason: '检测到 ncat -e 反弹 Shell 特征。' },\n '/dev/tcp': { level: 'critical', reason: '检测到 /dev/tcp 反弹 Shell 特征。' },\n '/dev/udp': { level: 'critical', reason: '检测到 /dev/udp 反弹 Shell 特征。' },\n '$(base64': { level: 'high', reason: '检测到 Base64 编码执行,可能是混淆逃逸。' },\n '`base64': { level: 'high', reason: '检测到 Base64 编码执行,可能是混淆逃逸。' },\n 'base64 decode pipe': { level: 'high', reason: '检测到 Base64 解码后管道执行,可能是混淆逃逸。' },\n '/etc/shadow': { level: 'critical', reason: '检测到访问系统密码文件。' },\n 'id_rsa': { level: 'critical', reason: '检测到访问 SSH 私钥。' },\n 'id_ed25519': { level: 'critical', reason: '检测到访问 SSH 私钥。' },\n 'crontab install': { level: 'high', reason: '检测到修改定时任务,可能是持久化后门。' },\n 'authorized_keys': { level: 'high', reason: '检测到修改 SSH 授权密钥,可能是持久化后门。' },\n 'ssh no host key check': { level: 'high', reason: '检测到 SSH 跳过主机密钥验证,可能是横向移动。' },\n};\n\nconst LEVEL_ORDER: Record<string, number> = { low: 1, medium: 2, high: 3, critical: 4 };\n\nexport interface ScriptAnalysisResult {\n scriptPath: string;\n scriptContent: string;\n matchedKeywords: string[];\n lineCount: number;\n isSuspicious: boolean;\n error: string;\n riskLevel: string;\n riskReason: string;\n}\n\nfunction emptyResult(): ScriptAnalysisResult {\n return { scriptPath: '', scriptContent: '', matchedKeywords: [], lineCount: 0, isSuspicious: false, error: '', riskLevel: '', riskReason: '' };\n}\n\nfunction extractScriptPath(command: string): string | null {\n for (const pattern of SCRIPT_EXEC_PATTERNS) {\n const m = command.match(pattern);\n if (m) return m[1];\n }\n return null;\n}\n\nfunction scanScriptForKeywords(content: string): string[] {\n const matched: string[] = [];\n for (const { name, pattern } of SUSPICIOUS_PATTERNS) {\n if (pattern.test(content)) matched.push(name);\n }\n return matched;\n}\n\nfunction assessKeywordCombinationRisk(matchedKeywords: string[], scriptContent: string): { level: string; reason: string } {\n if (matchedKeywords.length === 0) return { level: '', reason: '' };\n\n const keywordSet = new Set(matchedKeywords);\n\n // Check combination rules\n for (const rule of KEYWORD_COMBINATION_RISKS) {\n const hitGroup1 = [...rule.group1].some(k => keywordSet.has(k));\n const hitGroup2 = rule.group2.size === 0 ? true : [...rule.group2].some(k => keywordSet.has(k));\n if (hitGroup1 && hitGroup2) return { level: rule.level, reason: rule.reason };\n }\n\n // Extra: network post + env variable collection\n const networkPostKeywords = new Set(['curl POST', 'curl --data', 'curl -d', 'wget --post-data', 'wget --post-file']);\n const hasNetworkPost = [...networkPostKeywords].some(k => keywordSet.has(k));\n if (hasNetworkPost) {\n const envPatterns = ['$env', '$(env)', '$USER', '$(hostname)', '$(pwd)', '$HOME'];\n const contentLower = scriptContent.toLowerCase();\n for (const p of envPatterns) {\n if (contentLower.includes(p.toLowerCase())) {\n return {\n level: 'critical',\n reason: '检测到网络数据发送 + 系统环境变量收集组合,构成 Critical 级别数据外传风险。脚本可能将用户环境变量(可能包含 API Key、密钥等敏感信息)发送到远程服务器。',\n };\n }\n }\n }\n\n // Single keyword fallback\n let bestLevel = '';\n let bestReason = '';\n for (const kw of matchedKeywords) {\n const risk = SINGLE_KEYWORD_RISKS[kw];\n if (risk && (LEVEL_ORDER[risk.level] || 0) > (LEVEL_ORDER[bestLevel] || 0)) {\n bestLevel = risk.level;\n bestReason = risk.reason;\n }\n }\n\n return { level: bestLevel, reason: bestReason };\n}\n\nfunction readScriptContent(scriptPath: string, maxLines: number = 500): { content: string; lineCount: number; error: string } {\n try {\n const expandedPath = scriptPath.startsWith('~')\n ? join(process.env.HOME || '/home/user', scriptPath.slice(2))\n : resolve(scriptPath);\n\n const raw = readFileSync(expandedPath, 'utf-8');\n const lines = raw.split('\\n').slice(0, maxLines);\n return { content: lines.join('\\n'), lineCount: lines.length, error: '' };\n } catch (e: unknown) {\n const msg = e instanceof Error ? e.message : String(e);\n return { content: '', lineCount: 0, error: `读取脚本失败: ${msg}` };\n }\n}\n\nexport function analyzeScriptContent(actionType: string, actionDetail: string, maxLines: number = 500): ScriptAnalysisResult {\n if (actionType.toLowerCase() !== 'bash') return emptyResult();\n\n const scriptPath = extractScriptPath(actionDetail);\n if (!scriptPath) return emptyResult();\n\n const { content, lineCount, error } = readScriptContent(scriptPath, maxLines);\n if (error) return { ...emptyResult(), scriptPath, error };\n\n const matchedKeywords = scanScriptForKeywords(content);\n const isSuspicious = matchedKeywords.length > 0;\n\n let riskLevel = '';\n let riskReason = '';\n if (isSuspicious) {\n const risk = assessKeywordCombinationRisk(matchedKeywords, content);\n riskLevel = risk.level;\n riskReason = risk.reason;\n }\n\n return { scriptPath, scriptContent: content, matchedKeywords, lineCount, isSuspicious, error: '', riskLevel, riskReason };\n}\n\nexport function formatScriptAnalysisForPrompt(result: ScriptAnalysisResult): string {\n if (!result.scriptPath) return '';\n if (result.error) return `脚本内容分析失败: ${result.error}`;\n if (!result.isSuspicious) return '';\n\n const keywordsStr = result.matchedKeywords.join(', ');\n let riskHint = '';\n if (result.riskLevel && result.riskReason) {\n riskHint = `\\n\\n风险评估: ${result.riskLevel.toUpperCase()} 级别\\n风险原因: ${result.riskReason}\\n建议: 此脚本应被拒绝(Deny),除非有明确的业务需求且已确认目标服务器可信。`;\n }\n\n return `检测到脚本执行,且脚本内容包含可疑关键词:\\n 脚本路径: ${result.scriptPath}\\n 可疑关键词: ${keywordsStr}\\n 脚本行数: ${result.lineCount}${riskHint}\\n\\n### 脚本内容 ###\\n\\`\\`\\`\\n${result.scriptContent}\\n\\`\\`\\`\\n`;\n}\n","/**\n * Script content analyzer — recursive chain tracking + preprocessing + L1/L2 reuse.\n *\n * Mirrors Python agent_moss/engine/script_content_analyzer.py.\n *\n * Core improvements over the old single-file script-analyzer.ts:\n * 1. Preprocessing pipeline: strip comments -> strip echo text -> expand simple vars\n * 2. Broader script path extraction (no .sh restriction; python/node/ruby/...)\n * 3. File-size limit instead of line limit (full read; ms-scale cost)\n * 4. Recursive tracking: A.sh -> B.sh -> C.sh nested calls are caught\n * 5. L1/L2 reuse: preprocessed content scanned via existing runHeuristicCheck /\n * runLogicCheck; high/critical deny directly, skipping L3\n *\n * Difference from Python: AgentMoss-TS heuristic/logic are single entry functions\n * (runHeuristicCheck / runLogicCheck taking AnalysisInput), not reusable scanner\n * objects. So L1/L2 per-node reuse wraps each node's preprocessed content as a\n * virtual AnalysisInput and calls those functions.\n */\n\nimport { readFileSync, statSync, existsSync } from 'fs';\nimport { resolve, join, isAbsolute, dirname } from 'path';\nimport { homedir } from 'os';\nimport type { AnalysisInput } from './coordinator';\nimport type { SecurityJudgment } from './types';\nimport { runHeuristicCheck } from './heuristic';\nimport { runLogicCheck } from './logic-rules';\n\n// ==================== Types ====================\n\nexport interface ScriptNode {\n scriptPath: string;\n rawContent: string;\n preprocessedContent: string;\n lineCount: number;\n fileSize: number;\n depth: number;\n childPaths: string[];\n error: string;\n\n l1Hit: boolean;\n l1RiskLevel: string;\n l1RiskType: string;\n l1Reason: string;\n l1MatchedPatterns: string[];\n\n l2Hit: boolean;\n l2ViolatedRule: string;\n l2RiskLevel: string;\n l2RiskType: string;\n l2Reason: string;\n\n matchedKeywords: string[];\n isSuspicious: boolean;\n keywordRiskLevel: string;\n keywordRiskReason: string;\n}\n\nexport interface ScriptChainAnalysisResult {\n nodes: ScriptNode[];\n entryPath: string;\n maxDepthReached: boolean;\n maxSizeReached: boolean;\n totalSize: number;\n totalLines: number;\n hasCritical: boolean;\n hasHigh: boolean;\n firstHitNode: ScriptNode | null;\n error: string;\n}\n\nfunction emptyChain(): ScriptChainAnalysisResult {\n return {\n nodes: [], entryPath: '', maxDepthReached: false, maxSizeReached: false,\n totalSize: 0, totalLines: 0, hasCritical: false, hasHigh: false,\n firstHitNode: null, error: '',\n };\n}\n\nfunction newNode(path: string, depth: number): ScriptNode {\n return {\n scriptPath: path, rawContent: '', preprocessedContent: '', lineCount: 0,\n fileSize: 0, depth, childPaths: [], error: '',\n l1Hit: false, l1RiskLevel: '', l1RiskType: '', l1Reason: '', l1MatchedPatterns: [],\n l2Hit: false, l2ViolatedRule: '', l2RiskLevel: '', l2RiskType: '', l2Reason: '',\n matchedKeywords: [], isSuspicious: false, keywordRiskLevel: '', keywordRiskReason: '',\n };\n}\n\n// ==================== Preprocessing pipeline ====================\n\nfunction stripComments(content: string): string {\n return content.split('\\n').filter(line => !line.trimStart().startsWith('#')).join('\\n');\n}\n\nfunction stripOutputText(content: string): string {\n let result = content.replace(/echo\\s+\".*?\"/gs, 'echo \"\"');\n result = result.replace(/echo\\s+'.*?'/gs, \"echo ''\");\n result = result.replace(/printf\\s+\".*?\"[^\\n]*/gs, 'printf \"\"');\n result = result.replace(/printf\\s+'.*?'[^\\n]*/gs, \"printf ''\");\n return result;\n}\n\nfunction expandSimpleVariables(content: string): string {\n const varMap: Record<string, string> = {};\n const assignmentRe = /^\\s*(?:export\\s+)?([A-Za-z_][A-Za-z0-9_]*)=(.+)$/;\n\n const collectAssignments = (text: string) => {\n for (const line of text.split('\\n')) {\n const m = line.match(assignmentRe);\n if (m) {\n const varName = m[1];\n let varVal = m[2].trim();\n if (varVal && !varVal.includes('$') && !varVal.includes('`')) {\n if ((varVal.startsWith('\"') && varVal.endsWith('\"')) ||\n (varVal.startsWith(\"'\") && varVal.endsWith(\"'\"))) {\n varVal = varVal.slice(1, -1);\n }\n varMap[varName] = varVal;\n }\n }\n }\n };\n\n collectAssignments(content);\n let expanded = content;\n\n for (let round = 0; round < 3; round++) {\n const sortedVars = Object.keys(varMap).sort((a, b) => b.length - a.length);\n let newExpanded = expanded;\n for (const v of sortedVars) {\n const val = varMap[v];\n newExpanded = newExpanded.split('${' + v + '}').join(val);\n newExpanded = newExpanded.split('$' + v).join(val);\n }\n if (newExpanded === expanded) break;\n expanded = newExpanded;\n collectAssignments(expanded);\n }\n return expanded;\n}\n\nfunction preprocessScriptContent(content: string): string {\n let result = stripComments(content);\n result = stripOutputText(result);\n result = expandSimpleVariables(result);\n return result;\n}\n\n\n// ==================== High-risk keyword patterns (L3 compatible) ====================\n\nconst SUSPICIOUS_PATTERNS: { name: string; pattern: RegExp }[] = [\n { name: 'curl POST', pattern: /curl\\s+(.*\\s)?-X\\s+POST/i },\n { name: 'curl --data', pattern: /curl\\s+(.*\\s)?--data/i },\n { name: 'curl -d', pattern: /curl\\s+(.*\\s)?-d\\s/i },\n { name: 'wget --post-data', pattern: /wget\\s+(.*\\s)?--post-data/i },\n { name: 'wget --post-file', pattern: /wget\\s+(.*\\s)?--post-file/i },\n { name: 'nc -e', pattern: /\\bnc\\s+.*-e\\b/ },\n { name: 'ncat -e', pattern: /\\bncat\\s+.*-e\\b/ },\n { name: '/dev/tcp', pattern: /\\/dev\\/tcp\\// },\n { name: '/dev/udp', pattern: /\\/dev\\/udp\\// },\n { name: '$(base64', pattern: /\\$\\(\\s*base64/ },\n { name: '`base64', pattern: /`\\s*base64/ },\n { name: 'base64 decode pipe', pattern: /base64\\s+(-d|--decode)\\s*\\|/ },\n { name: '/etc/shadow', pattern: /\\/etc\\/shadow/ },\n { name: 'id_rsa', pattern: /\\bid_rsa\\b/ },\n { name: 'id_ed25519', pattern: /\\bid_ed25519\\b/ },\n { name: 'crontab install', pattern: /crontab\\s+-/ },\n { name: 'authorized_keys', pattern: /authorized_keys/ },\n { name: 'ssh no host key check', pattern: /ssh\\s+.*StrictHostKeyChecking\\s*=\\s*no/ },\n];\n\n\n// ==================== Script execution patterns ====================\n\nconst SCRIPT_EXEC_PATTERNS: RegExp[] = [\n /(?:^|\\s|&&|\\|\\|)\\s*bash\\s+(\\S+)/i,\n /(?:^|\\s|&&|\\|\\|)\\s*\\/bin\\/bash\\s+(\\S+)/i,\n /(?:^|\\s|&&|\\|\\|)\\s*sh\\s+(\\S+)/i,\n /(?:^|\\s|&&|\\|\\|)\\s*zsh\\s+(\\S+)/i,\n /\\.\\/(\\S+)/,\n /(?:^|\\s|&&|\\|\\|)\\s*source\\s+(\\S+)/i,\n /(?:^|\\s|&&|\\|\\|)\\s*\\.\\s+(\\S+)/,\n /(?:^|\\s|&&|\\|\\|)\\s*python3?\\s+(\\S+\\.py)/i,\n /(?:^|\\s|&&|\\|\\|)\\s*node\\s+(\\S+\\.js)/i,\n /(?:^|\\s|&&|\\|\\|)\\s*ruby\\s+(\\S+\\.rb)/i,\n /(?:^|\\s|&&|\\|\\|)\\s*perl\\s+(\\S+\\.pl)/i,\n /(?:^|\\s|&&|\\|\\|)\\s*php\\s+(\\S+\\.php)/i,\n /(?:^|\\s|&&|\\|\\|)\\s*lua\\s+(\\S+\\.lua)/i,\n];\n\n\n// ==================== Keyword combination risk rules ====================\n\nconst KEYWORD_COMBINATION_RISKS: { group1: Set<string>; group2: Set<string>; level: string; reason: string }[] = [\n {\n group1: new Set(['curl POST', 'curl --data', 'curl -d', 'wget --post-data', 'wget --post-file']),\n group2: new Set(['$(base64', '`base64', 'base64 decode pipe']),\n level: 'critical',\n reason: '检测到网络数据发送 + Base64编码组合,构成 Critical 级别数据外传风险。攻击者可能将敏感数据编码后外传。',\n },\n {\n group1: new Set(['curl POST', 'curl --data', 'curl -d', 'wget --post-data', 'wget --post-file']),\n group2: new Set(['/etc/shadow', 'id_rsa', 'id_ed25519']),\n level: 'critical',\n reason: '检测到网络数据发送 + 敏感文件访问组合,构成 Critical 级别凭证外传风险。',\n },\n {\n group1: new Set(['nc -e', 'ncat -e', '/dev/tcp', '/dev/udp']),\n group2: new Set(),\n level: 'high',\n reason: '检测到反弹 Shell 特征,攻击者可能建立远程控制通道。',\n },\n {\n group1: new Set(['crontab install', 'authorized_keys', 'ssh no host key check']),\n group2: new Set(),\n level: 'high',\n reason: '检测到持久化后门特征,攻击者可能在系统中植入后门。',\n },\n];\n\nconst SINGLE_KEYWORD_RISKS: Record<string, { level: string; reason: string }> = {\n 'curl POST': { level: 'high', reason: '检测到 curl POST 请求,可能向外部服务器发送数据。' },\n 'curl --data': { level: 'high', reason: '检测到 curl --data 参数,可能向外部服务器发送数据。' },\n 'curl -d': { level: 'high', reason: '检测到 curl -d 参数,可能向外部服务器发送数据。' },\n 'wget --post-data': { level: 'high', reason: '检测到 wget POST 请求,可能向外部服务器发送数据。' },\n 'wget --post-file': { level: 'high', reason: '检测到 wget 文件上传,可能向外部服务器发送文件。' },\n 'nc -e': { level: 'critical', reason: '检测到 nc -e 反弹 Shell 特征。' },\n 'ncat -e': { level: 'critical', reason: '检测到 ncat -e 反弹 Shell 特征。' },\n '/dev/tcp': { level: 'critical', reason: '检测到 /dev/tcp 反弹 Shell 特征。' },\n '/dev/udp': { level: 'critical', reason: '检测到 /dev/udp 反弹 Shell 特征。' },\n '$(base64': { level: 'high', reason: '检测到 Base64 编码执行,可能是混淆逃逸。' },\n '`base64': { level: 'high', reason: '检测到 Base64 编码执行,可能是混淆逃逸。' },\n 'base64 decode pipe': { level: 'high', reason: '检测到 Base64 解码后管道执行,可能是混淆逃逸。' },\n '/etc/shadow': { level: 'critical', reason: '检测到访问系统密码文件。' },\n 'id_rsa': { level: 'critical', reason: '检测到访问 SSH 私钥。' },\n 'id_ed25519': { level: 'critical', reason: '检测到访问 SSH 私钥。' },\n 'crontab install': { level: 'high', reason: '检测到修改定时任务,可能是持久化后门。' },\n 'authorized_keys': { level: 'high', reason: '检测到修改 SSH 授权密钥,可能是持久化后门。' },\n 'ssh no host key check': { level: 'high', reason: '检测到 SSH 跳过主机密钥验证,可能是横向移动。' },\n};\n\nconst LEVEL_ORDER: Record<string, number> = { low: 1, medium: 2, high: 3, critical: 4 };\n\nfunction scanScriptForKeywords(content: string): string[] {\n const matched: string[] = [];\n for (const { name, pattern } of SUSPICIOUS_PATTERNS) {\n if (pattern.test(content)) matched.push(name);\n }\n return matched;\n}\n\nfunction assessKeywordCombinationRisk(matchedKeywords: string[], scriptContent: string): { level: string; reason: string } {\n if (matchedKeywords.length === 0) return { level: '', reason: '' };\n\n const keywordSet = new Set(matchedKeywords);\n\n for (const rule of KEYWORD_COMBINATION_RISKS) {\n const hitGroup1 = [...rule.group1].some(k => keywordSet.has(k));\n const hitGroup2 = rule.group2.size === 0 ? true : [...rule.group2].some(k => keywordSet.has(k));\n if (hitGroup1 && hitGroup2) return { level: rule.level, reason: rule.reason };\n }\n\n const networkPostKeywords = new Set(['curl POST', 'curl --data', 'curl -d', 'wget --post-data', 'wget --post-file']);\n const hasNetworkPost = [...networkPostKeywords].some(k => keywordSet.has(k));\n if (hasNetworkPost) {\n const envPatterns = ['$env', '$(env)', '$USER', '$(hostname)', '$(pwd)', '$HOME'];\n const contentLower = scriptContent.toLowerCase();\n for (const p of envPatterns) {\n if (contentLower.includes(p.toLowerCase())) {\n return {\n level: 'critical',\n reason: '检测到网络数据发送 + 系统环境变量收集组合,构成 Critical 级别数据外传风险。脚本可能将用户环境变量(可能包含 API Key、密钥等敏感信息)发送到远程服务器。',\n };\n }\n }\n }\n\n let bestLevel = '';\n let bestReason = '';\n for (const kw of matchedKeywords) {\n const risk = SINGLE_KEYWORD_RISKS[kw];\n if (risk && (LEVEL_ORDER[risk.level] || 0) > (LEVEL_ORDER[bestLevel] || 0)) {\n bestLevel = risk.level;\n bestReason = risk.reason;\n }\n }\n return { level: bestLevel, reason: bestReason };\n}\n\n\n// ==================== Script path extraction ====================\n\nfunction extractScriptPath(command: string): string | null {\n for (const pattern of SCRIPT_EXEC_PATTERNS) {\n const m = command.match(pattern);\n if (m) return m[1];\n }\n return null;\n}\n\nfunction extractInlineScriptPath(actionDetail: string): string | null {\n const re = /open\\s*\\(\\s*['\"]([^'\"]+)['\"]\\s*\\)/g;\n let m: RegExpExecArray | null;\n while ((m = re.exec(actionDetail)) !== null) {\n const p = m[1];\n let resolved: string;\n try {\n resolved = resolvePath(p);\n if (existsSync(resolved)) {\n const stat = statSync(resolved);\n if (stat.isFile()) return resolved;\n }\n } catch { /* ignore */ }\n }\n return null;\n}\n\n/** Resolve a path: expand ~, resolve relative against cwd. */\nfunction resolvePath(p: string): string {\n let expanded = p;\n if (expanded.startsWith('~/') || expanded === '~') {\n expanded = join(homedir(), expanded.slice(1));\n }\n return resolve(expanded);\n}\n\n\n// ==================== Script content reading ====================\n\nfunction readScriptContent(\n scriptPath: string,\n maxFileSize: number = 2 * 1024 * 1024,\n): { content: string; lineCount: number; fileSize: number; error: string } {\n try {\n const path = resolvePath(scriptPath);\n if (!existsSync(path)) return { content: '', lineCount: 0, fileSize: 0, error: `脚本不存在: ${scriptPath}` };\n\n const stat = statSync(path);\n if (!stat.isFile()) return { content: '', lineCount: 0, fileSize: 0, error: `不是文件: ${scriptPath}` };\n if (stat.size > maxFileSize) {\n return { content: '', lineCount: 0, fileSize: stat.size, error: `脚本文件过大 (${stat.size} bytes),跳过读取` };\n }\n\n const content = readFileSync(path, 'utf-8');\n const lineCount = content ? content.split('\\n').length : 0;\n return { content, lineCount, fileSize: stat.size, error: '' };\n } catch (e: unknown) {\n const msg = e instanceof Error ? e.message : String(e);\n return { content: '', lineCount: 0, fileSize: 0, error: `读取脚本失败: ${msg}` };\n }\n}\n\n\n// ==================== Recursive tracking ====================\n\nfunction extractChildScriptPaths(content: string, baseDir: string): string[] {\n const paths: string[] = [];\n for (const pattern of CHILD_SCRIPT_PATTERNS) {\n pattern.lastIndex = 0;\n let m: RegExpExecArray | null;\n while ((m = pattern.exec(content)) !== null) {\n const pathStr = m[1];\n if (pathStr.startsWith('-') || pathStr.startsWith('$')) continue;\n if (pathStr.includes('/dev/') || pathStr.startsWith('|') || pathStr.startsWith(';')) continue;\n const full = isAbsolute(pathStr) ? pathStr : join(baseDir, pathStr);\n const resolved = resolvePath(full);\n if (existsSync(resolved)) {\n try {\n if (statSync(resolved).isFile() && !paths.includes(resolved)) paths.push(resolved);\n } catch { /* ignore */ }\n }\n }\n }\n return paths;\n}\n\n/**\n * Recursive script chain tracking. Reads + preprocesses each node.\n *\n * @param entryPath entry script path\n * @param input original AnalysisInput (used to build virtual per-node inputs for\n * L1/L2 reuse — carries promptSession/actionHistory/cwd for intent + path checks)\n * @param maxDepth max recursion depth (0=entry, 1=entry's children, ...)\n * @param maxFileSize per-file size cap (default 2MB)\n * @param maxTotalSize cumulative size cap (default 6MB)\n */\nfunction resolveScriptChain(\n entryPath: string,\n input: AnalysisInput,\n maxDepth: number = 3,\n maxFileSize: number = 2 * 1024 * 1024,\n maxTotalSize: number = 6 * 1024 * 1024,\n): ScriptChainAnalysisResult {\n const visited = new Set<string>();\n const result = emptyChain();\n result.entryPath = entryPath;\n\n const entry = resolvePath(entryPath);\n const baseDir = existsSync(entry) ? dirname(entry) : (input.cwd || process.cwd());\n\n resolveRecursive({\n path: entry, depth: 0, maxDepth, maxFileSize, maxTotalSize,\n visited, result, baseDir, input,\n });\n\n result.hasCritical = result.nodes.some(n =>\n n.l1RiskLevel === 'critical' || n.l2RiskLevel === 'critical' || n.keywordRiskLevel === 'critical');\n result.hasHigh = result.nodes.some(n =>\n ['high', 'critical'].includes(n.l1RiskLevel) ||\n ['high', 'critical'].includes(n.l2RiskLevel) ||\n ['high', 'critical'].includes(n.keywordRiskLevel));\n result.firstHitNode = result.nodes.find(n => n.l1Hit || n.l2Hit || n.isSuspicious) || null;\n\n return result;\n}\n\ninterface ResolveCtx {\n path: string;\n depth: number;\n maxDepth: number;\n maxFileSize: number;\n maxTotalSize: number;\n visited: Set<string>;\n result: ScriptChainAnalysisResult;\n baseDir: string;\n input: AnalysisInput;\n}\n\nfunction resolveRecursive(ctx: ResolveCtx): void {\n const { path, depth, maxDepth, maxFileSize, maxTotalSize, visited, result, baseDir, input } = ctx;\n\n if (visited.has(path)) return;\n if (depth > maxDepth) {\n result.maxDepthReached = true;\n return;\n }\n if (result.totalSize >= maxTotalSize) {\n result.maxSizeReached = true;\n return;\n }\n\n visited.add(path);\n\n const { content, lineCount, fileSize, error } = readScriptContent(path, maxFileSize);\n if (error) {\n const node = newNode(path, depth);\n node.error = error;\n node.fileSize = fileSize;\n node.lineCount = lineCount;\n result.nodes.push(node);\n return;\n }\n\n result.totalSize += fileSize;\n result.totalLines += lineCount;\n\n const preprocessed = preprocessScriptContent(content);\n const node = newNode(path, depth);\n node.rawContent = content;\n node.preprocessedContent = preprocessed;\n node.lineCount = lineCount;\n node.fileSize = fileSize;\n result.nodes.push(node);\n\n // Inline L1 + L2 scan during recursion (virtual input = preprocessed content)\n const virtualInput: AnalysisInput = {\n ...input,\n aNext: { actionType: 'bash', actionDetail: preprocessed },\n };\n const l1 = runHeuristicCheck(virtualInput);\n if (l1 && !l1.allowed) {\n node.l1Hit = true;\n node.l1RiskLevel = l1.riskLevel;\n node.l1RiskType = l1.riskType;\n node.l1Reason = l1.reason;\n node.l1MatchedPatterns = [];\n if (l1.riskLevel === 'critical') {\n result.hasCritical = true;\n result.firstHitNode = node;\n return;\n }\n }\n\n const childPaths = extractChildScriptPaths(preprocessed, baseDir);\n node.childPaths = childPaths;\n\n for (const childPath of childPaths) {\n resolveRecursive({\n path: resolvePath(childPath), depth: depth + 1, maxDepth, maxFileSize, maxTotalSize,\n visited, result, baseDir: dirname(resolvePath(childPath)), input,\n });\n if (result.hasCritical) return;\n }\n}\n\n\n// ==================== L1/L2 fallback chain scan ====================\n\n/** L1 fallback: scan nodes that weren't inline-scanned during recursion. */\nfunction scanScriptChainWithL1(chain: ScriptChainAnalysisResult, input: AnalysisInput): ScriptChainAnalysisResult {\n for (const node of chain.nodes) {\n if (node.error || !node.preprocessedContent || node.l1Hit) continue;\n const virtualInput: AnalysisInput = {\n ...input,\n aNext: { actionType: 'bash', actionDetail: node.preprocessedContent },\n };\n const l1 = runHeuristicCheck(virtualInput);\n if (l1 && !l1.allowed) {\n node.l1Hit = true;\n node.l1RiskLevel = l1.riskLevel;\n node.l1RiskType = l1.riskType;\n node.l1Reason = l1.reason;\n if (l1.riskLevel === 'critical') {\n chain.hasCritical = true;\n chain.firstHitNode = node;\n break;\n }\n }\n }\n return chain;\n}\n\n/**\n * L2 fallback: scan each node's preprocessed content via runLogicCheck.\n * Only reuses action-history-independent rules (sensitive path / dangerous\n * patterns / intent). runLogicCheck runs all L2 rules; we accept its verdict\n * per node (matching Python's per-rule reuse behaviorally).\n */\nfunction scanScriptChainWithL2(chain: ScriptChainAnalysisResult, input: AnalysisInput): ScriptChainAnalysisResult {\n for (const node of chain.nodes) {\n if (node.error || !node.preprocessedContent) continue;\n if (node.l1RiskLevel === 'critical') break;\n\n const virtualInput: AnalysisInput = {\n ...input,\n aNext: { actionType: 'bash', actionDetail: node.preprocessedContent },\n };\n const l2 = runLogicCheck(virtualInput);\n if (l2 && !l2.allowed) {\n node.l2Hit = true;\n node.l2ViolatedRule = `script_logic:${node.scriptPath}`;\n node.l2RiskLevel = l2.riskLevel;\n node.l2RiskType = l2.riskType;\n node.l2Reason = `脚本 ${node.scriptPath} (深度 ${node.depth}) 中: ${l2.reason}`;\n if (l2.riskLevel === 'critical') {\n chain.hasCritical = true;\n chain.firstHitNode = node;\n break;\n }\n }\n }\n if (!chain.hasHigh) {\n chain.hasHigh = chain.nodes.some(n => ['high', 'critical'].includes(n.l2RiskLevel));\n }\n return chain;\n}\n\n/** Keyword scan per node (L3-compatible). Only nodes not hit by L1/L2. */\nfunction scanScriptChainKeywords(chain: ScriptChainAnalysisResult): ScriptChainAnalysisResult {\n for (const node of chain.nodes) {\n if (node.error || !node.preprocessedContent) continue;\n if (node.l1Hit || node.l2Hit) continue;\n\n const matched = scanScriptForKeywords(node.preprocessedContent);\n node.matchedKeywords = matched;\n node.isSuspicious = matched.length > 0;\n\n if (matched.length > 0) {\n const risk = assessKeywordCombinationRisk(matched, node.preprocessedContent);\n node.keywordRiskLevel = risk.level;\n node.keywordRiskReason = risk.reason;\n }\n }\n return chain;\n}\n\n\n// ==================== Entry function ====================\n\n/**\n * Analyze script content: recursive tracking + preprocessing + L1/L2/keyword scan.\n * Only runs when actionType is 'bash' and the command invokes a script.\n *\n * Mirrors Python analyze_script_content. L1/L2 reuse wraps each node's\n * preprocessed content as a virtual AnalysisInput.\n */\nexport function analyzeScriptContent(input: AnalysisInput): ScriptChainAnalysisResult {\n const actionType = input.aNext.actionType.toLowerCase();\n if (actionType !== 'bash') return emptyChain();\n\n const scriptPath = extractScriptPath(input.aNext.actionDetail);\n let resolvedPath = scriptPath;\n if (!resolvedPath) {\n const inline = extractInlineScriptPath(input.aNext.actionDetail);\n if (!inline) return emptyChain();\n resolvedPath = inline;\n }\n\n const chain = resolveScriptChain(resolvedPath, input);\n if (chain.nodes.length === 0) return chain;\n\n // L1 fallback + L2 + keyword scans\n scanScriptChainWithL1(chain, input);\n scanScriptChainWithL2(chain, input);\n scanScriptChainKeywords(chain);\n\n return chain;\n}\n\n\n// ==================== L3 prompt formatting ====================\n\nexport function formatScriptChainForPrompt(chain: ScriptChainAnalysisResult): string {\n if (chain.nodes.length === 0) return '';\n\n const errorNodes = chain.nodes.filter(n => n.error);\n if (errorNodes.length > 0 && chain.nodes.length === 1) {\n return `⚠️ 脚本内容分析失败: ${errorNodes[0].error}`;\n }\n\n const suspiciousNodes = chain.nodes.filter(n => n.isSuspicious && !n.l1Hit && !n.l2Hit);\n if (suspiciousNodes.length === 0) {\n const safeNodes = chain.nodes.filter(n => !n.error);\n if (safeNodes.length === 0) return '';\n const parts: string[] = ['✓ 脚本内容已分析,未发现危险/可疑操作(L1/L2/关键词扫描均未命中):'];\n for (const node of safeNodes) {\n const pre = node.preprocessedContent || '';\n let preview = pre.slice(0, 600);\n if (pre.length > 600) preview += `\\n... (截断,完整内容 ${pre.length} 字符)`;\n parts.push(\n ` 脚本路径: ${node.scriptPath}(递归深度 ${node.depth},${node.lineCount} 行)\\n` +\n ` 内容(预处理后):\\n\\`\\`\\`\\n${preview}\\n\\`\\`\\``\n );\n }\n return parts.join('\\n');\n }\n\n const parts: string[] = [];\n for (const node of suspiciousNodes) {\n const keywordsStr = node.matchedKeywords.join(', ');\n let riskHint = '';\n if (node.keywordRiskLevel && node.keywordRiskReason) {\n riskHint =\n `\\n\\n🔴 **风险评估**: ${node.keywordRiskLevel.toUpperCase()} 级别\\n` +\n `**风险原因**: ${node.keywordRiskReason}\\n` +\n `**建议**: 此脚本应被拒绝(Deny),除非有明确的业务需求且已确认目标服务器可信。`;\n }\n const pre = node.preprocessedContent;\n let contentPreview = pre.slice(0, 2000);\n if (pre.length > 2000) contentPreview += `\\n... (截断,完整内容 ${pre.length} 字符)`;\n parts.push(\n `⚠️ 脚本内容包含可疑关键词:\\n` +\n ` 脚本路径: ${node.scriptPath}\\n` +\n ` 递归深度: ${node.depth}\\n` +\n ` 可疑关键词: ${keywordsStr}\\n` +\n ` 脚本行数: ${node.lineCount}${riskHint}\\n\\n` +\n `### 脚本内容(预处理后)###\\n\\`\\`\\`\\n${contentPreview}\\n\\`\\`\\`\\n`\n );\n }\n\n let header = `⚠️ 检测到脚本执行链(共 ${chain.nodes.length} 个脚本),其中 ${suspiciousNodes.length} 个包含可疑关键词:\\n`;\n if (chain.maxDepthReached) header += '⚠️ 注意:递归追踪触达深度上限,可能存在更深层的脚本调用未被扫描。\\n';\n if (chain.maxSizeReached) header += '⚠️ 注意:累计文件大小触达上限,部分脚本可能未被完整读取。\\n';\n\n return header + parts.join('\\n---\\n\\n');\n}\n\n/** [deprecated] Use formatScriptChainForPrompt. */\nexport function formatScriptAnalysisForPrompt(chain: ScriptChainAnalysisResult): string {\n return formatScriptChainForPrompt(chain);\n}\n\nconst CHILD_SCRIPT_PATTERNS: RegExp[] = [\n /(?:^|\\s|&&|\\|\\|)\\s*bash\\s+(\\S+)/i,\n /(?:^|\\s|&&|\\|\\|)\\s*sh\\s+(\\S+)/i,\n /(?:^|\\s|&&|\\|\\|)\\s*source\\s+(\\S+)/i,\n /(?:^|\\s|&&|\\|\\|)\\s*\\.\\s+(\\S+)/,\n /(?:^|\\s|&&|\\|\\|)\\s*python3?\\s+(\\S+\\.py)/i,\n /(?:^|\\s|&&|\\|\\|)\\s*node\\s+(\\S+\\.js)/i,\n /(?:^|\\s|&&|\\|\\|)\\s*ruby\\s+(\\S+\\.rb)/i,\n /(?:^|\\s|&&|\\|\\|)\\s*perl\\s+(\\S+\\.pl)/i,\n /(?:^|\\s|&&|\\|\\|)\\s*php\\s+(\\S+\\.php)/i,\n /(?:^|\\s|&&|\\|\\|)\\s*lua\\s+(\\S+\\.lua)/i,\n];\n","/**\n * Brain module — TypeScript implementation.\n *\n * Mirrors Python agent_moss/brain/ (rule_store + pattern_extractor + curator).\n * Default OFF: only active when AGENT_MOSS_BRAIN_ENABLED=1 (see isBrainEnabled\n * in ../config). When off, no store is created and checks are no-ops.\n */\n\nimport { BrainRuleStore } from './rule-store';\nimport { PatternExtractor } from './pattern-extractor';\n\nexport { BrainRuleStore } from './rule-store';\nexport { PatternExtractor } from './pattern-extractor';\nexport { createBrainReviewer, parseReview } from './reviewer';\n\nexport interface BrainCheckResult {\n ruleId: string;\n pattern: string;\n explanation: string;\n confidence: number;\n}\n\n/**\n * Check active brain rules against an action. Layer 1 = current action only;\n * Layer 2 = may consult action history. Returns the first matching rule.\n */\nexport function checkBrainRules(\n store: BrainRuleStore | null,\n opts: {\n layer: number;\n actionType: string;\n actionDetail: string;\n actionHistory?: { actionType: string; actionDetail: string }[];\n },\n): BrainCheckResult | null {\n if (!store) return null;\n const rules = store.getActiveRules(opts.layer);\n if (rules.length === 0) return null;\n\n const combined = `${opts.actionType} ${opts.actionDetail}`;\n for (const rule of rules) {\n try {\n if (new RegExp(rule.pattern, 'i').test(combined)) {\n // Layer 2 rules may need history context\n if (opts.layer === 2 && opts.actionHistory) {\n if (!checkLayer2Context(rule.pattern, opts.actionHistory, opts.actionDetail)) {\n continue;\n }\n }\n store.recordTrigger(rule.id);\n return {\n ruleId: rule.id,\n pattern: rule.pattern,\n explanation: rule.explanation,\n confidence: rule.confidence,\n };\n }\n } catch {\n continue;\n }\n }\n return null;\n}\n\nfunction checkLayer2Context(\n pattern: string,\n actionHistory: { actionType: string; actionDetail: string }[],\n actionDetail: string,\n): boolean {\n if (pattern.startsWith('BEHAVIOR_CHAIN:')) {\n const chainType = pattern.replace('BEHAVIOR_CHAIN:', '');\n if (chainType === 'external_read→sensitive_write') {\n const hasExternalRead = actionHistory.slice(-5).some(h =>\n /curl|wget|http/i.test(h.actionDetail ?? ''));\n const isSensitiveWrite = /\\.ssh|\\.gnupg|authorized_keys|bashrc|profile/i.test(actionDetail);\n return hasExternalRead && isSensitiveWrite;\n }\n if (chainType === 'multi_config_read→privilege_action') {\n const configReads = actionHistory.slice(-5).filter(h =>\n /\\/etc\\/|config|\\.conf|\\.yaml|\\.json/i.test(h.actionDetail ?? '')).length;\n const isPrivilege = /sudo|su |chmod|chown/i.test(actionDetail);\n return configReads >= 2 && isPrivilege;\n }\n return false;\n }\n return true;\n}","/**\n * Brain rule store — TypeScript implementation.\n *\n * Mirrors Python agent_moss/brain/rule_store.py but stores rules in a JSON file\n * (Python uses SQLite; TS has no sqlite dependency). Semantics are equivalent:\n * rules have a status lifecycle (draft → approved → active → disputed/stale →\n * archived), and pattern_candidates accumulate occurrences before a draft rule\n * is created.\n *\n * Storage: ~/.agentmoss/brain/rules.json (matches Python DB location ~/.agentmoss)\n * env override: AGENT_MOSS_BRAIN_RULES_PATH (tests use this to isolate)\n */\n\nimport { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\n\nexport const BRAIN_DIR = '.';\nexport const DEFAULT_RULES_PATH = join(homedir(), '.agentmoss', 'brain', 'rules.json');\nconst ENV_RULES_PATH = 'AGENT_MOSS_BRAIN_RULES_PATH';\n\nexport const STATUS_DRAFT = 'draft';\nexport const STATUS_APPROVED = 'approved';\nexport const STATUS_ACTIVE = 'active';\nexport const STATUS_DISPUTED = 'disputed';\nexport const STATUS_STALE = 'stale';\nexport const STATUS_ARCHIVED = 'archived';\nexport const STATUS_REJECTED = 'rejected';\n\nexport interface BrainRule {\n id: string;\n layer: number; // 1 = feature match, 2 = logic rule\n ruleType: string; // deny_path | deny_command | deny_pattern | allow_pattern\n pattern: string;\n scope: string; // openat | execve | connect | all\n source: string; // llm_extracted | user | central\n sourceEventIds: string[];\n confidence: number;\n status: string;\n createdAt: number;\n lastTriggeredAt: number;\n triggerCount: number;\n disputedCount: number;\n explanation: string;\n originNode: string;\n}\n\ninterface PatternCandidate {\n pattern: string;\n layer: number;\n scope: string;\n sourceEventIds: string[];\n confidence: number;\n occurrenceCount: number;\n firstSeenAt: number;\n lastSeenAt: number;\n reviewStatus: string; // pending | approved | rejected\n reviewReason: string;\n reviewedAt: number;\n}\n\ninterface BrainRulesFile {\n version: number;\n rules: BrainRule[];\n pattern_candidates: PatternCandidate[];\n}\n\nfunction getRulesPath(): string {\n const envPath = process.env[ENV_RULES_PATH];\n if (envPath) return envPath;\n return DEFAULT_RULES_PATH;\n}\n\nfunction uuid(): string {\n // crypto.randomUUID is available in Node 14.17+\n try {\n return (crypto as any).randomUUID();\n } catch {\n return `rule_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;\n }\n}\n\nexport class BrainRuleStore {\n private path: string;\n private data: BrainRulesFile;\n\n constructor(path?: string) {\n this.path = path || getRulesPath();\n this.data = this.load();\n }\n\n private load(): BrainRulesFile {\n if (!existsSync(this.path)) {\n return { version: 1, rules: [], pattern_candidates: [] };\n }\n try {\n const raw = JSON.parse(readFileSync(this.path, 'utf-8'));\n return {\n version: raw.version || 1,\n rules: raw.rules || [],\n pattern_candidates: raw.pattern_candidates || [],\n };\n } catch {\n return { version: 1, rules: [], pattern_candidates: [] };\n }\n }\n\n private save(): void {\n const dir = this.path.substring(0, this.path.lastIndexOf('/'));\n if (dir) mkdirSync(dir, { recursive: true });\n writeFileSync(this.path, JSON.stringify(this.data, null, 2), 'utf-8');\n }\n\n addRule(rule: Partial<BrainRule> & { pattern: string; layer: number }): string {\n const now = Date.now();\n const full: BrainRule = {\n id: rule.id || uuid(),\n layer: rule.layer,\n ruleType: rule.ruleType || 'deny_pattern',\n pattern: rule.pattern,\n scope: rule.scope || 'all',\n source: rule.source || 'llm_extracted',\n sourceEventIds: rule.sourceEventIds || [],\n confidence: rule.confidence || 0,\n status: rule.status || STATUS_DRAFT,\n createdAt: rule.createdAt || now,\n lastTriggeredAt: rule.lastTriggeredAt || 0,\n triggerCount: rule.triggerCount || 0,\n disputedCount: rule.disputedCount || 0,\n explanation: rule.explanation || '',\n originNode: rule.originNode || 'local',\n };\n this.data.rules.push(full);\n this.save();\n return full.id;\n }\n\n approveRule(ruleId: string): void {\n const rule = this.getRule(ruleId);\n if (!rule) throw new Error(`规则不存在: ${ruleId}`);\n if (rule.status !== STATUS_DRAFT) throw new Error(`只有 draft 状态可审核,当前: ${rule.status}`);\n rule.status = STATUS_ACTIVE;\n this.save();\n }\n\n rejectRule(ruleId: string): void {\n const rule = this.getRule(ruleId);\n if (!rule) throw new Error(`规则不存在: ${ruleId}`);\n if (rule.status !== STATUS_DRAFT) throw new Error(`只有 draft 状态可拒绝,当前: ${rule.status}`);\n rule.status = STATUS_REJECTED;\n this.save();\n }\n\n getRule(ruleId: string): BrainRule | undefined {\n return this.data.rules.find(r => r.id === ruleId);\n }\n\n getActiveRules(layer?: number): BrainRule[] {\n return this.data.rules.filter(r => r.status === STATUS_ACTIVE && (layer === undefined || r.layer === layer));\n }\n\n getDraftRules(): BrainRule[] {\n return this.data.rules\n .filter(r => r.status === STATUS_DRAFT)\n .sort((a, b) => b.createdAt - a.createdAt);\n }\n\n recordTrigger(ruleId: string): void {\n const rule = this.getRule(ruleId);\n if (!rule) return;\n rule.triggerCount += 1;\n rule.lastTriggeredAt = Date.now();\n this.save();\n }\n\n // --- pattern_candidates ---\n\n addPatternCandidate(pattern: string, layer: number, scope: string,\n sourceEventId: string, confidence: number): number {\n const now = Date.now();\n const existing = this.data.pattern_candidates.find(\n c => c.pattern === pattern && c.layer === layer && c.scope === scope,\n );\n if (existing) {\n // 已审核拒绝:不累计(永久排除)\n if (existing.reviewStatus === 'rejected') return 0;\n existing.occurrenceCount += 1;\n existing.lastSeenAt = now;\n existing.sourceEventIds.unshift(sourceEventId);\n this.save();\n return existing.occurrenceCount;\n }\n this.data.pattern_candidates.push({\n pattern, layer, scope,\n sourceEventIds: [sourceEventId],\n confidence, occurrenceCount: 1,\n firstSeenAt: now, lastSeenAt: now,\n reviewStatus: 'pending', reviewReason: '', reviewedAt: 0,\n });\n this.save();\n return 1;\n }\n\n getPatternCandidates(minOccurrences = 3): PatternCandidate[] {\n return this.data.pattern_candidates\n .filter(c => c.occurrenceCount >= minOccurrences && c.reviewStatus !== 'rejected')\n .sort((a, b) => b.occurrenceCount - a.occurrenceCount);\n }\n\n getPendingReviewCandidates(minOccurrences = 3): PatternCandidate[] {\n return this.data.pattern_candidates\n .filter(c => c.occurrenceCount >= minOccurrences && c.reviewStatus === 'pending')\n .sort((a, b) => b.occurrenceCount - a.occurrenceCount);\n }\n\n isExcludedPattern(pattern: string, layer: number, scope: string): boolean {\n const c = this.data.pattern_candidates.find(\n c => c.pattern === pattern && c.layer === layer && c.scope === scope,\n );\n return !!c && c.reviewStatus === 'rejected';\n }\n\n setPatternReviewStatus(pattern: string, layer: number, scope: string,\n status: string, reason = ''): void {\n const c = this.data.pattern_candidates.find(\n c => c.pattern === pattern && c.layer === layer && c.scope === scope,\n );\n if (c) {\n c.reviewStatus = status;\n c.reviewReason = reason;\n c.reviewedAt = Date.now();\n this.save();\n }\n }\n\n removePatternCandidate(pattern: string, layer: number, scope: string): void {\n this.data.pattern_candidates = this.data.pattern_candidates.filter(\n c => !(c.pattern === pattern && c.layer === layer && c.scope === scope),\n );\n this.save();\n }\n\n getStats(): Record<string, unknown> {\n const count = (status: string) => this.data.rules.filter(r => r.status === status).length;\n return {\n draft: count(STATUS_DRAFT),\n approved: count(STATUS_APPROVED),\n active: count(STATUS_ACTIVE),\n disputed: count(STATUS_DISPUTED),\n stale: count(STATUS_STALE),\n archived: count(STATUS_ARCHIVED),\n rejected: count(STATUS_REJECTED),\n total: this.data.rules.length,\n by_layer: {\n 1: this.data.rules.filter(r => r.layer === 1 && r.status === STATUS_ACTIVE).length,\n 2: this.data.rules.filter(r => r.layer === 2 && r.status === STATUS_ACTIVE).length,\n },\n pattern_candidates: this.data.pattern_candidates.length,\n };\n }\n}","/**\n * Brain pattern extractor — TypeScript implementation.\n *\n * Mirrors Python agent_moss/brain/pattern_extractor.py. Extracts reusable\n * patterns from Layer 3 LLM Deny results:\n * - static rules (deny_path / deny_command) → accumulated via pattern_candidates\n * until min_occurrences, then a draft rule is created\n * - dedup: if the action_detail is already covered by builtin rules, skip\n *\n * Anchor fix: generalized patterns use (?:^|[^a-z0-9_-]) boundaries instead of\n * ^/$ anchors, because the coordinator matches against\n * `combined = actionType + ' ' + actionDetail` with re.search.\n */\n\nimport { BrainRuleStore, STATUS_DRAFT } from './rule-store';\n\nexport interface ExtractionResult {\n rulesCreated: number;\n patternsRecorded: number;\n skippedReason: string;\n deduped: string[];\n}\n\nexport interface PatternInfo {\n pattern: string;\n layer: number;\n scope: string;\n ruleType: string;\n}\n\n/** LLM 审核回调:返回 true=保留, false=拒绝, null=无法审核(降级保持候选) */\nexport type BrainReviewFn = (opts: {\n pattern: string;\n layer: number;\n ruleType: string;\n actionDetail: string;\n reason: string;\n}) => Promise<{ shouldKeep: boolean; reason?: string } | null> | { shouldKeep: boolean; reason?: string } | null;\n\nexport class PatternExtractor {\n private ruleStore: BrainRuleStore;\n private minConfidence: number;\n private minOccurrences: number;\n private builtinPatterns: string[];\n private reviewFn: BrainReviewFn | null;\n\n constructor(ruleStore: BrainRuleStore, opts?: {\n minConfidence?: number;\n minOccurrences?: number;\n builtinPatterns?: string[];\n review?: BrainReviewFn | null;\n }) {\n this.ruleStore = ruleStore;\n this.minConfidence = opts?.minConfidence ?? 0.9;\n this.minOccurrences = opts?.minOccurrences ?? 3;\n this.builtinPatterns = opts?.builtinPatterns ?? [];\n this.reviewFn = opts?.review ?? null;\n }\n\n async extract(event: { actionDetail?: string; eventId?: string },\n llmResult: { confidence: number; reason: string; riskType: string; actionDetail?: string }): Promise<ExtractionResult> {\n const result: ExtractionResult = { rulesCreated: 0, patternsRecorded: 0, skippedReason: '', deduped: [] };\n const confidence = llmResult.confidence ?? 0;\n const reason = llmResult.reason ?? '';\n const riskType = llmResult.riskType ?? '';\n const actionDetail = llmResult.actionDetail ?? event.actionDetail ?? '';\n const eventId = event.eventId ?? '';\n\n if (confidence < this.minConfidence) {\n result.skippedReason = `confidence ${confidence} < ${this.minConfidence}`;\n return result;\n }\n\n const patterns = this.extractPatterns(actionDetail, reason, riskType);\n if (patterns.length === 0) {\n result.skippedReason = 'no extractable pattern';\n return result;\n }\n\n for (const p of patterns) {\n // Dedup: action_detail already covered by builtin rules → skip\n if (this.isCoveredByBuiltin(actionDetail)) {\n result.deduped.push(p.pattern);\n continue;\n }\n\n const count = this.ruleStore.addPatternCandidate(\n p.pattern, p.layer, p.scope, eventId, confidence,\n );\n if (count === 0) {\n // 已审核拒绝:永久排除\n result.deduped.push(p.pattern);\n continue;\n }\n result.patternsRecorded += 1;\n\n if (count >= this.minOccurrences) {\n const candidates = this.ruleStore.getPatternCandidates(this.minOccurrences);\n const matched = candidates.find(c => c.pattern === p.pattern && c.layer === p.layer);\n if (!matched) continue;\n\n // LLM 审核(可选):判定该 pattern 是否值得沉淀\n if (this.reviewFn) {\n let review: Awaited<ReturnType<BrainReviewFn>>;\n try {\n review = await this.reviewFn({\n pattern: p.pattern, layer: p.layer, ruleType: p.ruleType,\n actionDetail, reason,\n });\n } catch {\n review = null;\n }\n if (review === null) {\n // LLM 不可用/失败:降级保持候选,下次再试\n continue;\n }\n if (!review.shouldKeep) {\n this.ruleStore.setPatternReviewStatus(\n p.pattern, p.layer, p.scope, 'rejected', review.reason || 'LLM 审核拒绝',\n );\n result.deduped.push(p.pattern);\n continue;\n }\n this.ruleStore.setPatternReviewStatus(\n p.pattern, p.layer, p.scope, 'approved', review.reason || 'LLM 审核通过',\n );\n }\n\n this.ruleStore.addRule({\n layer: p.layer,\n ruleType: p.ruleType,\n pattern: p.pattern,\n scope: p.scope,\n source: 'llm_extracted',\n sourceEventIds: eventId ? [eventId] : [],\n confidence: matched.confidence,\n status: STATUS_DRAFT,\n explanation: `从 ${count} 次 LLM Deny 中提取(经审核): ${reason.slice(0, 200)}`,\n });\n this.ruleStore.removePatternCandidate(p.pattern, p.layer, p.scope);\n result.rulesCreated += 1;\n }\n }\n return result;\n }\n\n extractPatterns(actionDetail: string, reason: string, riskType?: string): PatternInfo[] {\n const patterns: PatternInfo[] = [];\n const detailLower = actionDetail.toLowerCase();\n const seen = new Set<string>();\n\n // --- Layer 1: sensitive paths in action_detail ---\n const sensitivePathRe = /(\\/(?:etc|root)(?:\\/[^\\s;|&\"'<>`$]*)?|(?:[^\\s;|&\"'<>`$]*)?\\/\\.ssh\\/[^\\s;|&\"'<>`$]*|(?:[^\\s;|&\"'<>`$]*)?\\/\\.aws\\/[^\\s;|&\"'<>`$]*|\\S+\\.(?:pem|key|p12|pfx|id_rsa|authorized_keys)\\b)/;\n const m = detailLower.match(sensitivePathRe);\n if (m) {\n const gen = this.generalizePath(m[1]);\n if (!seen.has(gen)) {\n seen.add(gen);\n patterns.push({ pattern: gen, layer: 1, scope: 'openat', ruleType: 'deny_path' });\n }\n }\n\n // --- Layer 1: dangerous commands ---\n const dangerousCmdRe = /\\b(rm\\s+-[a-zA-Z]*r[a-zA-Z]*f|rm\\s+--recursive|chmod\\s+777|curl\\s+[^|]*\\|\\s*(?:ba)?sh|wget\\s+[^|]*\\|\\s*(?:ba)?sh|mkfs\\.|dd\\s+if=|>\\s*\\/dev\\/sd)\\b/;\n const cmdM = detailLower.match(dangerousCmdRe);\n if (cmdM) {\n const gen = this.generalizeCommand(cmdM[1]);\n const seenKey = `cmd:${gen}`;\n if (!seen.has(seenKey)) {\n seen.add(seenKey);\n patterns.push({ pattern: gen, layer: 1, scope: 'execve', ruleType: 'deny_command' });\n }\n }\n\n // --- Layer 2: behavior chain patterns ---\n const reasonLower = (reason || '').toLowerCase();\n if (reasonLower.includes('inject') || reasonLower.includes('数据注入')) {\n patterns.push({\n pattern: 'BEHAVIOR_CHAIN:external_read→sensitive_write',\n layer: 2, scope: 'all', ruleType: 'deny_pattern',\n });\n }\n if (reasonLower.includes('reconnaissance') || reasonLower.includes('侦察') || reasonLower.includes('提权')) {\n patterns.push({\n pattern: 'BEHAVIOR_CHAIN:multi_config_read→privilege_action',\n layer: 2, scope: 'all', ruleType: 'deny_pattern',\n });\n }\n\n // --- Layer 1: extract new sensitive paths from action_detail + reason ---\n // 前缀:空白、引号、左括号、= (URL query 参数如 src=/path)\n // 后缀:空白、引号、右括号、中英文标点、行尾\n const pathPrefix = '(?:^|[\\\\s\"\\'(=])';\n const pathBody = '(\\\\/(?:[a-zA-Z0-9_.-]+\\\\/)+[a-zA-Z0-9_.-]+)';\n const pathSuffix = '(?=[\\\\s\"\\'),。);;]|$)';\n for (const src of [detailLower, reasonLower]) {\n // 每次循环新建正则,避免全局 lastIndex 状态污染(JS 全局正则跨字符串复用 bug)\n const pathRe = new RegExp(pathPrefix + pathBody + pathSuffix, 'g');\n let mm: RegExpExecArray | null;\n while ((mm = pathRe.exec(src)) !== null) {\n const path = mm[1];\n if (path.split('/').length < 3) continue; // need >= 2 dir levels\n if (['/dev/null', '/dev/zero', '/dev/random', '/dev/urandom'].includes(path)) continue;\n const gen = this.generalizePath(path);\n if (seen.has(gen)) continue;\n seen.add(gen);\n patterns.push({ pattern: gen, layer: 1, scope: 'openat', ruleType: 'deny_path' });\n }\n }\n return patterns;\n }\n\n isCoveredByBuiltin(actionDetail: string): boolean {\n if (this.builtinPatterns.length === 0 || !actionDetail) return false;\n for (const pat of this.builtinPatterns) {\n try {\n if (new RegExp(pat, 'i').test(actionDetail)) return true;\n } catch {\n continue;\n }\n }\n return false;\n }\n\n generalizePath(path: string): string {\n const p = path.toLowerCase();\n if (/\\/etc\\/(shadow|passwd|sudoers|security|ssh)/.test(p)) {\n return '(?:^|[^a-z0-9_-])etc/(?:shadow|passwd|sudoers|security/|ssh/)';\n }\n if (p.includes('/etc/')) {\n return '(?:^|[^a-z0-9_-])etc/';\n }\n if (p.includes('/root/')) {\n return '(?:^|[^a-z0-9_-])root/\\\\.(?:ssh|gnupg|aws|config)/';\n }\n if (p.includes('.ssh/')) {\n return '(?:^|[^a-z0-9_-])[\\\\w./-]*/\\\\.ssh/';\n }\n if (p.includes('.aws/')) {\n return '(?:^|[^a-z0-9_-])[\\\\w./-]*/\\\\.aws/';\n }\n if (/\\.(pem|key|p12|pfx|id_rsa|authorized_keys)\\b/.test(p)) {\n return '[\\\\w./-]*\\\\.(?:pem|key|p12|pfx|id_rsa|authorized_keys)(?:$|[^a-z0-9])';\n }\n const escaped = p.replace(/^\\//, '').replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n return `(?:^|[^a-z0-9_-])${escaped}(?:/|\\\\b)`;\n }\n\n generalizeCommand(cmd: string): string {\n if (cmd.includes('rm') && cmd.includes('r') && cmd.includes('f')) {\n return 'rm\\\\s+(?:-[a-zA-Z]*r[a-zA-Z]*f|--recursive)\\\\s+/';\n }\n if (cmd.includes('chmod')) return 'chmod\\\\s+777';\n if (cmd.includes('curl') || cmd.includes('wget')) {\n return '(?:curl|wget)\\\\s+[^|]*\\\\|\\\\s*(?:ba)?sh';\n }\n if (cmd.includes('mkfs')) return 'mkfs\\\\.';\n if (cmd.includes('dd')) return 'dd\\\\s+if=';\n return cmd.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n }\n}","/**\n * Brain 候选 pattern LLM 审核器 — TypeScript implementation.\n *\n * Mirrors Python agent_moss/brain/reviewer.py. When a pattern candidate\n * reaches the occurrence threshold, ask the LLM whether it's worth promoting\n * to a local rule. Rejects are permanently excluded; LLM-unavailable degrades\n * to \"keep candidate\" (don't promote, don't reject).\n */\n\nimport OpenAI from 'openai';\nimport { getLLMConfig, isLLMAvailable, detectProvider, getProviderHeaders } from '../config';\n\ninterface ReviewResult {\n shouldKeep: boolean;\n reason?: string;\n}\n\nconst REVIEW_PROMPT = `你是 AgentMoss 安全规则审核器。判断下列\"从 LLM 拒绝结果中提取的安全模式\"是否值得沉淀为本地规则。\n\n## 提取的模式(候选)\n- 模式: {pattern}\n- 所属层: Layer {layer}(1=特征匹配,2=行为链)\n- 类型: {ruleType}\n\n## 原始被拒绝的操作\n{actionDetail}\n\n## LLM 当时的拒绝理由\n{reason}\n\n## 判断准则\n1. **是否过高泛化**:这条模式是否会误拦正常的合法操作?\n2. **是否符合敏感特征**:指向的路径/命令是否确实敏感(凭据/系统文件/恶意命令/外传)?\n3. **与三层规则重复**:是否已被现有 L1/L2 规则覆盖?\n4. **是不是真实攻击模式**:是否代表一种连续的攻击行为模式?\n\n## 输出 JSON(只输出 JSON,无其他文字)\n{\"should_keep\": true/false, \"confidence\": 0-100, \"reason\": \"简短理由(中文)\", \"suggested_rule\": \"若保留则输出建议正则,否则空串\", \"duplicate_of\": \"若重复则说明是哪个,否则空串\"}`;\n\ninterface ParsedReview {\n shouldKeep: boolean;\n confidence: number;\n reason: string;\n}\n\nexport function createBrainReviewer(timeoutMs = 10000):\n (opts: { pattern: string; layer: number; ruleType: string; actionDetail: string; reason: string })\n => Promise<ReviewResult | null> {\n return async (opts) => {\n // 审核开关:AGENT_MOSS_BRAIN_REVIEW=0 关闭(对齐 Python)\n if (process.env.AGENT_MOSS_BRAIN_REVIEW === '0') return null;\n if (!isLLMAvailable()) return null;\n\n const config = getLLMConfig();\n const provider = detectProvider(config.baseUrl, config.provider);\n const extraHeaders = getProviderHeaders(provider);\n const client = new OpenAI({\n baseURL: config.baseUrl,\n apiKey: config.apiKey,\n timeout: timeoutMs,\n maxRetries: 1,\n defaultHeaders: Object.keys(extraHeaders).length > 0 ? extraHeaders : undefined,\n });\n\n const prompt = REVIEW_PROMPT\n .replace('{pattern}', opts.pattern)\n .replace('{layer}', String(opts.layer))\n .replace('{ruleType}', opts.ruleType)\n .replace('{actionDetail}', (opts.actionDetail || '').slice(0, 400))\n .replace('{reason}', (opts.reason || '').slice(0, 400));\n\n try {\n const response = await client.chat.completions.create({\n model: config.model,\n temperature: config.temperature || 0.1,\n max_tokens: 256,\n messages: [\n { role: 'system', content: '只输出纯 JSON,不要包含 markdown 标记、代码块或任何其他文字。' },\n { role: 'user', content: prompt },\n ],\n } as any);\n const content = response.choices[0]?.message?.content || '';\n const parsed = parseReview(content);\n return { shouldKeep: parsed.shouldKeep, reason: parsed.reason };\n } catch (e) {\n console.warn(`[AgentMoss] Brain 审核 LLM 调用失败(降级保持候选): ${(e as Error).message}`);\n return null;\n }\n };\n}\n\nexport function parseReview(content: string): ParsedReview {\n let text = content.trim();\n if (text.startsWith('```')) {\n text = text.replace(/^```[a-zA-Z]*\\n?/, '').replace(/\\n?```$/, '');\n }\n // 提取第一个 JSON 对象\n const match = text.match(/\\{[\\s\\S]*\\}/);\n if (!match) throw new Error(`审核响应无 JSON 对象: ${text.slice(0, 200)}`);\n const data = JSON.parse(match[0]);\n if (!('should_keep' in data) && !('shouldKeep' in data)) {\n throw new Error(`审核响应缺 should_keep: ${text.slice(0, 200)}`);\n }\n let shouldKeep = data.shouldKeep ?? data.should_keep;\n if (typeof shouldKeep === 'string') {\n shouldKeep = ['true', '1', '是', 'yes'].includes(shouldKeep.trim().toLowerCase());\n }\n return {\n shouldKeep: !!shouldKeep,\n confidence: Number(data.confidence ?? 0) || 0,\n reason: String(data.reason ?? data.suggested_rule ?? '') || '',\n };\n}","/**\n * AcTrail enforcement event reporter for TypeScript.\n *\n * Writes AgentMoss allow/deny decisions as Enforcement events to AcTrail's\n * SQLite storage, enabling unified agent behavior audit trails.\n *\n * Configuration (environment variables):\n * ACTRAIL_ENABLED: Set to \"1\" to enable reporting (default: disabled)\n * ACTRAIL_STORAGE_PATH: Path to AcTrail SQLite DB (default: /tmp/actrail.sqlite)\n * ACTRAIL_TIMEOUT_MS: Write timeout in milliseconds (default: 100)\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\n\n/** AcTrail key=value escape (mirrors Rust encode_map) */\nfunction escape(value: string): string {\n return value.replace(/\\\\/g, '\\\\\\\\').replace(/\\n/g, '\\\\n').replace(/=/g, '\\\\e');\n}\n\n/** Convert session_id string to u64 trace_id (SHA-256 based, masked to signed 64-bit) */\nfunction sessionToTraceId(sessionId: string): number {\n // Simple hash - not cryptographic, but sufficient for ID generation\n let hash = 0;\n for (let i = 0; i < sessionId.length; i++) {\n const char = sessionId.charCodeAt(i);\n hash = ((hash << 5) - hash + char) | 0;\n }\n // Combine with length for better distribution, mask to signed 64-bit\n return Math.abs((hash * 31 + sessionId.length) % Number.MAX_SAFE_INTEGER);\n}\n\nexport interface ActrailReportOptions {\n traceId: string;\n decision: 'allow' | 'deny';\n toolName: string;\n toolCommand: string;\n sessionId: string;\n prompt?: string;\n riskLevel?: string;\n riskType?: string;\n reason?: string;\n violatedLayers?: string[];\n confidence?: number;\n durationMs?: number;\n}\n\nlet dbConnected = false;\nlet dbPath = '';\n\nfunction isEnabled(): boolean {\n return process.env.ACTRAIL_ENABLED === '1' || process.env.ACTRAIL_ENABLED === 'true';\n}\n\nfunction getStoragePath(): string {\n return process.env.ACTRAIL_STORAGE_PATH || '/tmp/actrail.sqlite';\n}\n\n/**\n * Report an enforcement event to AcTrail (fire-and-forget).\n * Returns true if written, false if disabled or write failed.\n */\nexport function reportEnforcementEvent(opts: ActrailReportOptions): boolean {\n if (!isEnabled()) return false;\n\n const storagePath = getStoragePath();\n if (!fs.existsSync(storagePath)) return false;\n\n try {\n // Dynamic import - better-sqlite3 is an optional dependency\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n let Database: any;\n try {\n Database = require('better-sqlite3');\n } catch {\n console.debug('[AgentMoss] better-sqlite3 not installed, AcTrail reporting disabled');\n return false;\n }\n\n const db = new Database(storagePath, { timeout: 100, readonly: false });\n\n // Verify events table exists\n const tableCheck = db.prepare(\n \"SELECT name FROM sqlite_master WHERE type='table' AND name='events'\"\n ).get();\n if (!tableCheck) {\n db.close();\n return false;\n }\n\n const nowNs = BigInt(Date.now()) * 1000000n;\n const eventId = Number(nowNs % BigInt(2 ** 62));\n const traceIdInt = sessionToTraceId(opts.traceId);\n\n // Build payload fields in AcTrail's key=value format\n const rawFields: Record<string, string> = {\n 'backend': 'agent-moss',\n 'operation': 'tool_call',\n 'decision': opts.decision,\n 'result': opts.decision === 'allow' ? 'allowed' : 'denied',\n 'tool.name': opts.toolName,\n 'tool.command': (opts.toolCommand || '').slice(0, 500),\n 'agent.session_id': opts.sessionId,\n 'agent.prompt': (opts.prompt || '').slice(0, 500),\n 'risk.level': opts.riskLevel || '',\n 'risk.type': opts.riskType || '',\n 'reason': (opts.reason || '').slice(0, 500),\n 'violated_layers': (opts.violatedLayers || []).join(','),\n 'confidence': String(opts.confidence ?? 100),\n 'duration_ms': (opts.durationMs ?? 0).toFixed(1),\n };\n const payloadFields = Object.entries(rawFields)\n .map(([k, v]) => `${escape(k)}=${escape(v)}`)\n .join('\\n');\n\n db.prepare(`\n INSERT OR REPLACE INTO events (\n event_id, trace_id, observed_at,\n process_pid, process_task_id, process_start_ticks,\n process_pid_namespace, process_generation,\n collector, kind,\n bootstrap_observed, metadata_partial, policy_modified,\n payload_variant, payload_fields, payload_bytes,\n policy_verdict, policy_note,\n policy_redactions, policy_truncations\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `).run(\n eventId,\n traceIdInt,\n Number(nowNs),\n process.pid,\n 0,\n 0,\n null,\n 0,\n 'agent-moss',\n 'enforcement',\n 0,\n 0,\n 0,\n 'enforcement',\n payloadFields,\n '',\n opts.decision === 'allow' ? 'allow' : 'drop',\n opts.reason || '',\n '[]',\n '[]'\n );\n\n db.close();\n return true;\n } catch (err) {\n // Non-fatal - never block the response\n console.debug(`[AgentMoss] AcTrail write failed (non-fatal): ${(err as Error).message}`);\n return false;\n }\n}\n","/** Policy Console 子应用(挂载到主 app 的 /console 前缀)。 */\nexport { createConsoleRouter } from './router';\n","/**\n * Policy Console Hono 路由 — 挂载到主 app 的 /console 前缀下。\n * 1:1 对齐 Python console/router.py 的 23 路由契约(前端 SPA 共用)。\n *\n * 复用 infra.runtime-config + engine.token-stats。Bearer 认证\n * (AGENT_MOSS_CONSOLE_TOKEN 未设则本机免认证,iframe 嵌入场景)。\n */\nimport { Hono } from 'hono';\nimport { readFileSync, existsSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport {\n loadRuntimeConfig, saveRuntimeConfig, updateLayerEnabled,\n updateRuleEnabled, updateRuleDenyMode, updateRuleSkipL3,\n updateCategoryEnabled, addCustomRule, deleteCustomRule,\n addCustomSkill, deleteCustomSkill, updateSkillEnabled,\n updateSkillCategoryEnabled, getEnvOverrides, generateSourceDefaults,\n getRuntimeConfigPath,\n getAgentRules, updateAgentRuleEnabled, addAgentRule, deleteAgentRule,\n updateAgentCategoryEnabled,\n} from '../infra/runtime-config';\nimport {\n getTokenStats, getRecentRecords, getRecentRecordsCount, getTokenTrend, resetTokenStats,\n} from '../engine/token-stats';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst STATIC_DIR = join(__dirname, 'static');\n\nconst CONSOLE_TOKEN_ENV = 'AGENT_MOSS_CONSOLE_TOKEN';\n\nfunction getConsoleToken(): string {\n return process.env[CONSOLE_TOKEN_ENV] || '';\n}\n\n/** 验证 Bearer token。未配置 token 时本机访问免认证(iframe 嵌入场景)。 */\nfunction verifyAuth(req: Request): boolean {\n const token = getConsoleToken();\n if (!token) return true;\n const auth = req.headers.get('Authorization') || '';\n if (auth.startsWith('Bearer ')) return auth.slice(7) === token;\n return false;\n}\n\n/** 鉴权中间件:失败返 401。 */\nfunction authMiddleware() {\n return async (c: any, next: any) => {\n if (!verifyAuth(c.req.raw)) {\n return c.json({ error: 'Unauthorized: invalid or missing Bearer token' }, 401);\n }\n await next();\n };\n}\n\nexport function createConsoleRouter(): Hono {\n const console = new Hono();\n console.use('/api/*', authMiddleware());\n\n // ==================== SPA ====================\n // /console 和 /console/ 都返回 SPA(hono route 挂载后两者匹配行为不同,都兜住)\n const serveIndex = (c: any) => {\n const indexFile = join(STATIC_DIR, 'index.html');\n if (existsSync(indexFile)) {\n return c.html(readFileSync(indexFile, 'utf-8'));\n }\n return c.html('<h1>AgentMoss Policy Console</h1><p>Frontend not built. Use /console/api/* endpoints.</p>');\n };\n console.get('/', serveIndex);\n console.get('', serveIndex);\n\n // ==================== 层级管理 ====================\n console.get('/api/layers', (c) => {\n const rc = loadRuntimeConfig();\n return c.json({ layers: rc.layers, env_overrides: getEnvOverrides() });\n });\n\n console.put('/api/layers', async (c) => {\n const body = await c.req.json();\n const rc = updateLayerEnabled(body.layer_key, body.enabled);\n return c.json({ layers: rc.layers, env_overrides: getEnvOverrides() });\n });\n\n // ==================== 规则管理 ====================\n console.get('/api/rules', (c) => {\n const rc = loadRuntimeConfig();\n return c.json({ L1_rules: rc.L1_rules, L2_rules: rc.L2_rules });\n });\n\n console.put('/api/rules/enabled', async (c) => {\n const b = await c.req.json();\n const rc = updateRuleEnabled(b.layer, b.category, b.rule_id, b.enabled);\n return c.json(rc);\n });\n\n console.put('/api/rules/deny_mode', async (c) => {\n const b = await c.req.json();\n const rc = updateRuleDenyMode(b.layer, b.category, b.rule_id, b.deny_mode);\n return c.json(rc);\n });\n\n console.put('/api/rules/skip_l3', async (c) => {\n const b = await c.req.json();\n const rc = updateRuleSkipL3(b.layer, b.category, b.rule_id, b.skip_l3_on_disabled);\n return c.json(rc);\n });\n\n console.put('/api/categories/enabled', async (c) => {\n const b = await c.req.json();\n const rc = updateCategoryEnabled(b.layer, b.category, b.enabled);\n return c.json(rc);\n });\n\n console.post('/api/rules', async (c) => {\n const b = await c.req.json();\n const rc = addCustomRule(b.layer, b.category, {\n pattern: b.pattern, risk_level: b.risk_level, risk_type: b.risk_type,\n reason: b.reason, keyword: b.keyword, lang: b.lang,\n path: b.path, desc: b.desc, credential: b.credential, deny_mode: b.deny_mode,\n });\n return c.json(rc);\n });\n\n console.delete('/api/rules', async (c) => {\n const b = await c.req.json();\n deleteCustomRule(b.layer, b.category, b.rule_id);\n const rc = loadRuntimeConfig();\n return c.json(rc);\n });\n\n // ==================== Skill 管理 ====================\n console.get('/api/skills', (c) => {\n const rc = loadRuntimeConfig();\n return c.json(rc.L3_skills);\n });\n\n console.put('/api/skills/enabled', async (c) => {\n const b = await c.req.json();\n const rc = updateSkillEnabled(b.skill_id, b.enabled);\n return c.json(rc);\n });\n\n console.put('/api/skill-categories/enabled', async (c) => {\n const b = await c.req.json();\n const rc = updateSkillCategoryEnabled(b.category, b.enabled);\n return c.json(rc);\n });\n\n console.post('/api/skills', async (c) => {\n const b = await c.req.json();\n const rc = addCustomSkill(b.skill_id, b.category || 'user_custom', b.keywords || [], b.content);\n return c.json(rc);\n });\n\n console.delete('/api/skills', async (c) => {\n const b = await c.req.json();\n deleteCustomSkill(b.skill_id, b.category);\n const rc = loadRuntimeConfig();\n return c.json(rc);\n });\n\n console.get('/api/skills/:skill_id/content', async (c) => {\n const skillId = c.req.param('skill_id');\n if (!/^[A-Za-z0-9_-]+$/.test(skillId)) {\n return c.json({ error: 'invalid skill_id' }, 400);\n }\n const skillPath = join(dirname(getRuntimeConfigPath()), 'agent_moss_skills', `${skillId}.md`);\n if (!existsSync(skillPath)) {\n // fallback 到 builtin skill 目录\n const builtinPath = join(__dirname, '..', '..', 'agent_moss', 'skills', `${skillId}.md`);\n if (existsSync(builtinPath)) return c.text(readFileSync(builtinPath, 'utf-8'));\n return c.json({ error: 'skill not found' }, 404);\n }\n return c.text(readFileSync(skillPath, 'utf-8'));\n });\n\n // ==================== agent 定制规则 ====================\n console.get('/api/agents', (c) => {\n const rc = loadRuntimeConfig();\n return c.json({ agents: getAgentRules(rc) });\n });\n\n console.put('/api/agents/rules/enabled', async (c) => {\n const b = await c.req.json();\n const fp: Record<string, string> = {};\n if (b.value) fp.value = b.value;\n if (b.pattern) fp.pattern = b.pattern;\n if (b.keyword) fp.keyword = b.keyword;\n if (b.path) fp.path = b.path;\n const rc = updateAgentRuleEnabled(b.agent_id, b.category, fp, b.enabled);\n return c.json({ agents: getAgentRules(rc) });\n });\n\n console.post('/api/agents/rules', async (c) => {\n const b = await c.req.json();\n const rule: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(b)) {\n if (!['agent_id', 'category'].includes(k) && v !== undefined && v !== null) rule[k] = v;\n }\n const rc = addAgentRule(b.agent_id, b.category, rule);\n return c.json({ agents: getAgentRules(rc) });\n });\n\n console.delete('/api/agents/rules', async (c) => {\n const b = await c.req.json();\n const fp: Record<string, string> = {};\n if (b.value) fp.value = b.value;\n if (b.pattern) fp.pattern = b.pattern;\n if (b.keyword) fp.keyword = b.keyword;\n if (b.path) fp.path = b.path;\n const rc = deleteAgentRule(b.agent_id, b.category, fp);\n return c.json({ agents: getAgentRules(rc) });\n });\n\n console.put('/api/agents/categories/enabled', async (c) => {\n const b = await c.req.json();\n const rc = updateAgentCategoryEnabled(b.agent_id, b.category, b.enabled);\n return c.json({ agents: getAgentRules(rc) });\n });\n\n // ==================== 配置 / env / reset ====================\n // 契约对齐:Python console/router.py 的 /api/config 直接返回完整 runtime config\n // (顶层含 L1_rules/L2_rules/L3_skills/layers),前端 state.config 读取顶层字段。\n // 之前 TS 返回 {config, config_path} 包装导致前端 L1/L2/L3 标签页全空(数据丢)。\n console.get('/api/config', (c) => {\n const rc = loadRuntimeConfig();\n return c.json(rc);\n });\n\n console.get('/api/env-overrides', (c) => {\n return c.json({ overrides: getEnvOverrides() });\n });\n\n console.post('/api/reset', (c) => {\n const defaults = generateSourceDefaults();\n saveRuntimeConfig(defaults);\n return c.json(defaults);\n });\n\n // ==================== Token stats ====================\n console.get('/api/token-stats', (c) => {\n const days = parseInt(c.req.query('days') || '7', 10);\n return c.json(getTokenStats(days));\n });\n\n console.get('/api/token-stats/recent', (c) => {\n const limit = parseInt(c.req.query('limit') || '20', 10);\n const offset = parseInt(c.req.query('offset') || '0', 10);\n // 返回 { records, total },前端据此分页(total 供分页器计算总页数)\n return c.json({ records: getRecentRecords(limit, offset), total: getRecentRecordsCount() });\n });\n\n console.get('/api/token-stats/trend', (c) => {\n const days = parseInt(c.req.query('days') || '7', 10);\n return c.json(getTokenTrend(days));\n });\n\n console.post('/api/token-stats/reset', (c) => {\n resetTokenStats();\n return c.json({ reset: true });\n });\n\n return console;\n}\n"],"mappings":"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","names":["path","fileURLToPath","OpenAI","readFileSync","fileURLToPath","__filename","__dirname","fs","t","path","READ_KEYWORDS","WRITE_KEYWORDS","readFileSync","readdirSync","existsSync","resolve","dirname","fileURLToPath","__filename","__dirname","readFileSync","existsSync","readdirSync","join","fileURLToPath","dirname","__dirname","readFileSync","existsSync","resolve","dirname","fileURLToPath","hasRuntimeConfig","loadRuntimeConfig","getEnabledAgentExtensions","__filename","__dirname","path","readFileSync","writeFileSync","existsSync","mkdirSync","unlinkSync","path","fs","path","fileURLToPath","join","dirname","i","fs","path","resolve","fs","path","Hono","require","readFileSync","existsSync","resolve","dirname","fileURLToPath","__filename","__dirname","readFileSync","resolve","join","readFileSync","existsSync","resolve","join","dirname","homedir","path","SUSPICIOUS_PATTERNS","SCRIPT_EXEC_PATTERNS","KEYWORD_COMBINATION_RISKS","SINGLE_KEYWORD_RISKS","LEVEL_ORDER","scanScriptForKeywords","assessKeywordCombinationRisk","extractScriptPath","readScriptContent","node","analyzeScriptContent","parts","recordTokenUsage","resolve","existsSync","readFileSync","writeFileSync","mkdirSync","join","homedir","join","homedir","path","existsSync","readFileSync","mkdirSync","writeFileSync","c","path","OpenAI","analyzeScriptContent","getDisabledL2RulesWithSkipL3","getLLMFailMode","fs","readFileSync","existsSync","join","dirname","fileURLToPath","__dirname","console","Hono","resolve"]}
|
|
1
|
+
{"version":3,"sources":["../node_modules/tsup/assets/esm_shims.js","../src/infra/paths.ts","../src/config.ts","../src/engine/inline-analyzer.ts","../src/infra/rules-loader.ts","../src/engine/logic-rules.ts","../src/engine/skill-loader.ts","../src/infra/runtime-config.ts","../src/agents/index.ts","../src/scenarios/index.ts","../src/engine/heuristic.ts","../src/engine/token-stats.ts","../node_modules/better-sqlite3/lib/util.js","../node_modules/better-sqlite3/lib/sqlite-error.js","../node_modules/file-uri-to-path/index.js","../node_modules/bindings/bindings.js","../node_modules/better-sqlite3/lib/methods/wrappers.js","../node_modules/better-sqlite3/lib/methods/transaction.js","../node_modules/better-sqlite3/lib/methods/pragma.js","../node_modules/better-sqlite3/lib/methods/backup.js","../node_modules/better-sqlite3/lib/methods/serialize.js","../node_modules/better-sqlite3/lib/methods/function.js","../node_modules/better-sqlite3/lib/methods/aggregate.js","../node_modules/better-sqlite3/lib/methods/table.js","../node_modules/better-sqlite3/lib/methods/inspect.js","../node_modules/better-sqlite3/lib/database.js","../node_modules/better-sqlite3/lib/index.js","../src/server.ts","../src/routes.ts","../src/models.ts","../src/package-json.ts","../src/engine/coordinator.ts","../src/engine/llm-analyzer.ts","../src/engine/template-loader.ts","../src/engine/script-analyzer.ts","../src/engine/script-content-analyzer.ts","../src/engine/script-engine/tracker.ts","../src/engine/script-engine/backends/python-backend.ts","../src/engine/script-engine/backends/index.ts","../src/engine/script-engine/backends/shell-backend.ts","../src/engine/script-engine/symbolic.ts","../src/brain/index.ts","../src/brain/rule-store.ts","../src/brain/pattern-extractor.ts","../src/brain/reviewer.ts","../src/engine/formal-engine/index.ts","../src/engine/formal-engine/engine.ts","../src/engine/formal-engine/builder.ts","../src/engine/formal-engine/decode.ts","../src/engine/formal-engine/ir.ts","../src/engine/formal-engine/properties.ts","../src/engine/formal-engine/stateful.ts","../src/engine/formal-engine/chain_state.ts","../src/actrail.ts","../src/engine/formal-engine/pattern_miner.ts","../src/agent-gate-reader.ts","../src/console/index.ts","../src/console/router.ts"],"sourcesContent":["// Shim globals in esm bundle\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","/**\n * Path resolution — unified data root + multi-instance (instance) isolation.\n *\n * Mirrors Python agent_moss/infra/paths.py.\n *\n * Solves two problems:\n * 1. Data-owner user directory: even when the service runs as root/systemd\n * (started via `sudo systemctl`), AGENT_MOSS_DATA_DIR can point it at the\n * \"current user\"'s data dir, so config / runtime / token all land in that\n * user's directory instead of root's /root. Falls back to\n * ~/.config/agentmoss (legacy behavior) when unset.\n *\n * 2. Token isolation by instance: services started by different agents\n * (AGENT_MOSS_INSTANCE) don't share token-usage files. With an instance,\n * tokens go to <data_root>/<instance>/agent_moss_token_stats.json; without\n * one, to <data_root>/agent_moss_token_stats.json (default location).\n *\n * config / runtime are NOT split by instance (rules/config are shared); they\n * only follow the data root.\n */\n\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport { readFileSync } from 'fs';\n\nconst ENV_DATA_ROOT = 'AGENT_MOSS_DATA_DIR';\nconst ENV_INSTANCE = 'AGENT_MOSS_INSTANCE';\n\nconst DEFAULT_DATA_ROOT = join(homedir(), '.config', 'agentmoss');\n\n/** True when the process runs as root (systemd `sudo systemctl`). */\nexport function isRoot(): boolean {\n const getuid = (process as any).getuid;\n return typeof getuid === 'function' && getuid() === 0;\n}\n\n/** Resolve the \"real user\"'s home when running as root.\n * Priority: SUDO_USER (sudo invoker) > LOGNAME/USER (login user) >\n * first UID>=1000 ordinary user in /etc/passwd. Returns null if none found. */\nexport function resolveOwnerHome(): string | null {\n for (const name of [process.env.SUDO_USER, process.env.LOGNAME, process.env.USER]) {\n if (name && name !== 'root' && name !== '') {\n const home = homeOf(name);\n if (home) return home;\n }\n }\n // /etc/passwd fallback: first UID>=1000 ordinary user\n try {\n const passwd = readFileSync('/etc/passwd', 'utf-8');\n for (const line of passwd.split('\\n')) {\n if (!line || line.startsWith('#')) continue;\n const parts = line.split(':');\n if (parts.length < 6) continue;\n const uid = parseInt(parts[2], 10);\n const name = parts[0];\n if (uid >= 1000 && name && !name.startsWith('_')) {\n return parts[5];\n }\n }\n } catch { /* ignore */ }\n return null;\n}\n\nfunction homeOf(name: string): string | null {\n try {\n const passwd = readFileSync('/etc/passwd', 'utf-8');\n for (const line of passwd.split('\\n')) {\n if (!line || line.startsWith('#')) continue;\n const parts = line.split(':');\n if (parts.length >= 6 && parts[0] === name) {\n return parts[5];\n }\n }\n } catch { /* ignore */ }\n return null;\n}\n\n/** Data root directory.\n * Priority: env AGENT_MOSS_DATA_DIR > ~/.config/agentmoss.\n * BUT when running as root (any `sudo systemctl` service), automatically\n * redirects to the real user's dir so config/runtime/token land there\n * instead of /root. */\nexport function getDataRoot(): string {\n const envPath = process.env[ENV_DATA_ROOT];\n if (envPath) return envPath;\n if (isRoot()) {\n const ownerHome = resolveOwnerHome();\n if (ownerHome) {\n return join(ownerHome, '.config', 'agentmoss');\n }\n }\n return DEFAULT_DATA_ROOT;\n}\n\n/** Instance identifier (empty string when unset). */\nexport function getInstance(): string {\n const v = process.env[ENV_INSTANCE] || '';\n return v.trim().replace(/^[/\\\\]+|[/\\\\]+$/g, '');\n}\n\n/** Config file directory (config.json). Not split by instance; follows data root. */\nexport function getConfigDir(): string {\n return getDataRoot();\n}\n\n/** Runtime config directory (agent_moss_runtime.json + skills dir). Not split by instance. */\nexport function getRuntimeConfigDir(): string {\n return getDataRoot();\n}\n\n/**\n * Token stats file path.\n * With instance → <data_root>/<instance>/agent_moss_token_stats.json\n * Without → <data_root>/agent_moss_token_stats.json\n */\nexport function getTokenStatsPath(): string {\n const instance = getInstance();\n if (instance) {\n return join(getDataRoot(), instance, 'agent_moss_token_stats.json');\n }\n return join(getDataRoot(), 'agent_moss_token_stats.json');\n}","import fs from 'fs';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\nimport type { LLMConfig, TimeoutConfig, RetryConfig } from './engine/types';\nimport { getConfigDir } from './infra/paths';\n\n/** Custom rule from user config */\nexport interface CustomRule {\n pattern: string;\n action: 'Allow' | 'Deny';\n severity: string;\n description?: string;\n}\n\n/** Read config from file (JSON), returns parsed object or null */\nfunction loadConfigFile(filePath: string): Record<string, any> | null {\n try {\n const raw = fs.readFileSync(filePath, 'utf-8');\n return JSON.parse(raw);\n } catch {\n return null;\n }\n}\n\n/** Determine config file path with priority:\n * 1. AGENT_MOSS_CONFIG_PATH env var\n * 2. ~/.config/agentmoss/config.json (auto-create if missing)\n * 3. Package default (relative to __dirname)\n */\nfunction resolveConfigPath(): string {\n const envPath = process.env.AGENT_MOSS_CONFIG_PATH;\n if (envPath) return envPath;\n\n const userConfig = path.join(getConfigDir(), 'config.json');\n if (fs.existsSync(userConfig)) return userConfig;\n\n // Auto-create from package default\n const defaultConfig = path.join(__dirname, '..', '..', 'agent_moss', 'infra', 'config.json.example');\n if (fs.existsSync(defaultConfig)) {\n const configDir = path.dirname(userConfig);\n fs.mkdirSync(configDir, { recursive: true });\n // Read the default config and filter out the api_key for safety\n const pkgConfig = loadConfigFile(defaultConfig);\n const safeConfig = pkgConfig ? { ...pkgConfig, llm: { ...pkgConfig.llm, api_key: '' } } : {};\n fs.writeFileSync(userConfig, JSON.stringify(safeConfig, null, 4), 'utf-8');\n console.log(`[AgentMoss] 已创建用户配置文件: ${userConfig}`);\n console.log(`[AgentMoss] 请编辑该文件配置你的 LLM API Key`);\n }\n return userConfig;\n}\n\n/** Load LLM config from file, merged with environment variables (env wins) */\nfunction loadLLMConfigFromFile(configPath: string): Partial<LLMConfig> {\n const data = loadConfigFile(configPath);\n if (!data?.llm) return {};\n\n const llm = data.llm;\n return {\n provider: llm.provider || '',\n baseUrl: llm.base_url || '',\n apiKey: llm.api_key || '',\n model: llm.model || '',\n temperature: llm.temperature ?? 0.1,\n maxTokens: llm.max_tokens ?? 4096,\n timeout: llm.timeout ?? 40,\n };\n}\n\n/** Load timeout/retry config from file (对齐 Python TimeoutConfig / RetryConfig) */\nfunction loadTimeoutRetryFromFile(configPath: string): { timeout: TimeoutConfig; retry: RetryConfig } {\n const data = loadConfigFile(configPath);\n const t = data?.timeout ?? {};\n const r = data?.retry ?? {};\n return {\n timeout: {\n totalTimeout: Number(t.total_timeout ?? 90),\n prompt1Timeout: Number(t.prompt1_timeout ?? 40),\n prompt2Timeout: Number(t.prompt2_timeout ?? 20),\n stepInterval: Number(t.step_interval ?? 0),\n },\n retry: {\n maxRetries: Number(r.max_retries ?? 2),\n retryInterval: Number(r.retry_interval ?? 2),\n },\n };\n}\n\n/** Global timeout/retry configuration (对齐 Python TimeoutConfig / RetryConfig) */\nlet timeoutConfig: TimeoutConfig;\nlet retryConfig: RetryConfig;\n\n/** Global LLM configuration, initialized from file + env vars (env wins) */\nlet llmConfig: LLMConfig = (() => {\n const configPath = resolveConfigPath();\n const fileConfig = fs.existsSync(configPath) ? loadLLMConfigFromFile(configPath) : {};\n const tr = loadTimeoutRetryFromFile(configPath);\n timeoutConfig = tr.timeout;\n retryConfig = tr.retry;\n\n return {\n provider: process.env.AGENT_MOSS_LLM_PROVIDER || fileConfig.provider || 'openai',\n baseUrl: process.env.AGENT_MOSS_LLM_BASE_URL || fileConfig.baseUrl || 'https://api.openai.com/v1',\n apiKey: process.env.AGENT_MOSS_LLM_API_KEY || process.env.OPENAI_API_KEY || fileConfig.apiKey || '',\n model: process.env.AGENT_MOSS_LLM_MODEL || fileConfig.model || 'gpt-4o',\n temperature: parseFloat(process.env.AGENT_MOSS_LLM_TEMPERATURE || String(fileConfig.temperature ?? '0.1')),\n maxTokens: parseInt(process.env.AGENT_MOSS_LLM_MAX_TOKENS || String(fileConfig.maxTokens ?? '4096'), 10),\n // 优先用 env,否则用 timeout 块的 prompt1Timeout(对齐 py)\n timeout: parseInt(process.env.AGENT_MOSS_LLM_TIMEOUT || String(fileConfig.timeout ?? String(tr.timeout.prompt1Timeout)), 10),\n };\n})();\n\nexport function getTimeoutConfig(): Readonly<TimeoutConfig> {\n return timeoutConfig;\n}\n\nexport function getRetryConfig(): Readonly<RetryConfig> {\n return retryConfig;\n}\n\n// 打包内 user_rules.json 路径(npm 安装自包含)+ dev 回退到仓库根 agent_moss/rules。\n// 对齐 skill-loader.ts 的 fileURLToPath(import.meta.url) 双路径解析:\n// - tsup 打包后 config.ts 被内联进 dist/{cli,server,engine/coordinator}.js,\n// import.meta.url 指向该 chunk(dist/engine/coordinator.js → __dirname=dist/engine/),\n// 故 dist 内 rules 在 ../rules(即 dist/rules/user_rules.json,copy-assets.cjs 复制)。\n// - dev(vitest) 模式 config.ts 源文件 __dirname=ts/src/,仓库根 agent_moss/rules\n// 在 ../../agent_moss/rules。三条候选路径覆盖 dist 与 dev 两种形态,命中即用。\nconst __configModuleDir = (() => {\n try { return path.dirname(fileURLToPath(import.meta.url)); }\n catch { return typeof __dirname !== 'undefined' ? __dirname : process.cwd(); }\n})();\nconst USER_RULES_PATHS = [\n path.join(__configModuleDir, 'rules', 'user_rules.json'), // 源在 ts/src/rules(一般不存在)\n path.join(__configModuleDir, '..', 'rules', 'user_rules.json'), // dist: dist/engine/../rules = dist/rules ✅\n path.join(__configModuleDir, '..', '..', 'agent_moss', 'rules', 'user_rules.json'), // dev src: ts/src/../../agent_moss\n];\n\nfunction wildcardToRegExp(pattern: string): string {\n // 对齐 Python UserRuleMatcher: re.escape(pattern).replace(r\"\\*\", \".*\")\n // JS 无 re.escape,手动转义所有正则元字符,再把转义后的 \\* 还原为 .*\n return pattern.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&').replace(/\\\\\\*/g, '.*');\n}\n\nfunction loadCustomRules(): CustomRule[] {\n const rules: CustomRule[] = [];\n // 1. AGENT_MOSS_CUSTOM_RULES env var(运行时注入,最高优先)\n try {\n const raw = process.env.AGENT_MOSS_CUSTOM_RULES;\n if (raw) {\n const parsed = JSON.parse(raw);\n if (Array.isArray(parsed)) {\n for (const r of parsed) {\n if (r && r.pattern && r.action) rules.push({ pattern: r.pattern, action: r.action, severity: r.severity || 'high' });\n }\n }\n }\n } catch { /* ignore env parse error */ }\n\n // 2. 打包内 agent_moss/rules/user_rules.json 的 sensitive_actions(通配符规则)。\n // 对齐 Python UserRuleMatcher(DEFAULT_RULES_PATH = agent_moss/rules/user_rules.json),\n // 含 crontab -e / crontab -r / * | crontab / iptables - 等用户敏感规则。\n // TS 此前只读 env 不读该文件,导致 crontab -e 等 L1 漏检(FN-2)。wildcard → RegExp。\n for (const rulesPath of USER_RULES_PATHS) {\n try {\n if (!fs.existsSync(rulesPath)) continue;\n const data = JSON.parse(fs.readFileSync(rulesPath, 'utf-8'));\n const actions = Array.isArray(data?.sensitive_actions) ? data.sensitive_actions : [];\n for (const r of actions) {\n const p = r?.pattern;\n if (!p) continue;\n rules.push({ pattern: wildcardToRegExp(p), action: 'Deny', severity: 'high' });\n }\n break; // 命中第一个存在的文件即可\n } catch { /* ignore user_rules.json read/parse error */ }\n }\n return rules;\n}\n\n/** Custom rules loaded from AGENT_MOSS_CUSTOM_RULES env var + packaged user_rules.json */\nlet customRules: CustomRule[] = loadCustomRules();\n\nexport function getLLMConfig(): Readonly<LLMConfig> {\n return llmConfig;\n}\n\nexport function updateLLMConfig(partial: Partial<LLMConfig>): void {\n llmConfig = { ...llmConfig, ...partial };\n}\n\nexport function getCustomRules(): Readonly<CustomRule[]> {\n return customRules;\n}\n\n/** Check if LLM analysis is available (API key configured + not disabled) */\nexport function isLLMAvailable(): boolean {\n if (process.env.AGENT_MOSS_DISABLE_LLM === '1') return false;\n return llmConfig.apiKey.length > 0;\n}\n\n/**\n * Probe LLM connectivity with a minimal max_tokens=1 request.\n * Mirrors Python _probe_llm (tests/conftest.py): same source of truth\n * (getLLMConfig / get_default_config), so a passing probe means the actual\n * L3 call in tests uses the same key/endpoint and will succeed.\n *\n * Returns true on any successful response (finish_reason length/stop both ok);\n * false on timeout / 401 / network error. Used by L3 tests to skip rather than\n * let a dead key fail-open and false-pass.\n */\nexport async function probeLLMConnection(timeoutMs: number = 8000): Promise<boolean> {\n if (!isLLMAvailable()) return false;\n const OpenAI = (await import('openai')).default;\n const config = getLLMConfig();\n const provider = detectProvider(config.baseUrl, config.provider);\n const extraHeaders = getProviderHeaders(provider);\n const client = new OpenAI({\n baseURL: config.baseUrl,\n apiKey: config.apiKey,\n timeout: timeoutMs,\n maxRetries: 0,\n defaultHeaders: Object.keys(extraHeaders).length > 0 ? extraHeaders : undefined,\n });\n try {\n const resp = await client.chat.completions.create({\n model: config.model,\n messages: [{ role: 'user', content: 'ping' } as any],\n max_tokens: 1,\n } as any);\n return !!(resp && resp.choices && resp.choices[0]);\n } catch {\n return false;\n }\n}\n\n/**\n * LLM analysis failure mode (mirrors Python get_llm_fail_mode).\n *\n * - \"fail_open\" (default): when L3 LLM fails and prior layers did NOT block,\n * Allow + warning log (availability-first)\n * - \"fail_closed\": LLM failure -> Deny (safety-first)\n *\n * Priority: env AGENT_MOSS_LLM_FAIL_MODE > default fail_open.\n */\nexport function getLLMFailMode(): 'fail_open' | 'fail_closed' {\n const val = (process.env.AGENT_MOSS_LLM_FAIL_MODE || 'fail_open').toLowerCase();\n return val === 'fail_closed' ? 'fail_closed' : 'fail_open';\n}\n\n// ========== Provider detection & headers ==========\n\nconst PROVIDER_HEADERS: Record<string, Record<string, string>> = {\n 'openrouter': {\n 'HTTP-Referer': 'shturl.cc/LlVD5pyWViHjM',\n 'X-OpenRouter-Title': 'AgentMoss',\n },\n 'xai': {\n 'HTTP-Referer': 'shturl.cc/LlVD5pyWViHjM',\n },\n};\n\n/** Detect provider from base URL or explicit hint (mirrors Python detect_provider) */\nexport function detectProvider(baseUrl: string, providerHint: string = ''): string {\n if (providerHint) {\n const hint = providerHint.toLowerCase();\n if (['claude', 'anthropic'].includes(hint)) return 'anthropic';\n if (['google', 'gemini'].includes(hint)) return 'gemini';\n if (['zai-coding-plan', 'zhipu-coding-plan', 'zhipuai-coding-plan'].includes(hint)) return 'zai-coding-plan';\n if (['zai', 'z-ai', 'z.ai', 'zai-cn', 'zai-china', 'zhipu', 'glm-cn', 'bigmodel'].includes(hint)) return 'zhipu';\n if (['xai', 'xai-grok'].includes(hint)) return 'xai';\n if (['minimax', 'minimax-openai'].includes(hint)) return 'minimax';\n if (['minimax-anthropic'].includes(hint)) return 'minimax-anthropic';\n if (['other', 'custom', 'local'].includes(hint)) return 'openai-compatible';\n return hint;\n }\n\n const url = baseUrl.toLowerCase();\n if (url.includes('openrouter.ai')) return 'openrouter';\n if (url.includes('api.openai.com')) return 'openai';\n if (url.includes('anthropic.com') || url.includes('api.anthropic.com')) return 'anthropic';\n if (url.includes('generativelanguage.googleapis.com') || url.includes('gemini')) return 'gemini';\n if (url.includes('api.deepseek.com')) return 'deepseek';\n if (url.includes('api.groq.com')) return 'groq';\n if (url.includes('api.mistral.ai')) return 'mistral';\n if (url.includes('api.together.xyz')) return 'together';\n if (url.includes('api.x.ai')) return 'xai';\n if (url.includes('api.minimaxi.com')) return 'minimax';\n if (url.includes('api-ai.gitcode.com')) return 'gitcode';\n if (url.includes('api.z.ai')) return 'zai-coding-plan';\n if (url.includes('open.bigmodel.cn') || url.includes('bigmodel')) return 'zhipu';\n if (url.includes(':11434')) return 'ollama';\n return 'openai-compatible';\n}\n\n/** Get provider-specific headers (mirrors Python get_provider_headers) */\nexport function getProviderHeaders(provider: string): Record<string, string> {\n return PROVIDER_HEADERS[provider] || {};\n}\n\n/** Per-layer enable/disable (matches Python SecurityConfig) */\nexport function isHeuristicEnabled(): boolean {\n return process.env.AGENT_MOSS_DISABLE_HEURISTIC !== '1';\n}\n\n/**\n * Brain 自学习机制是否启用。默认关闭(开发中,避免污染 L1/L2 判定与 L3 prompt),\n * 仅当显式设置 AGENT_MOSS_BRAIN_ENABLED=1 时启用(镜像 Python is_brain_enabled)。\n */\nexport function isBrainEnabled(): boolean {\n return process.env.AGENT_MOSS_BRAIN_ENABLED === '1';\n}\n\nexport function isLogicRulesEnabled(): boolean {\n return process.env.AGENT_MOSS_DISABLE_LOGIC_RULES !== '1';\n}\n","/**\n * 内联脚本静态语义判定 — 区分敏感路径是\"被当作文本\"还是\"被当作读写目标\"。\n *\n * 对内联脚本(python -c / perl -e / ruby -e / php -r / node -e / lua / echo / printf)\n * 里出现非凭据敏感路径的场景,做静态判定(不依赖 LLM):\n *\n * 1. 写入+执行绕过链 → Deny(echo \"cat /etc/shadow\" > x.sh && bash x.sh / printf | bash)\n * 2. 重定向写入敏感路径 → Deny(echo '...' >> /etc/hosts)\n * 3. 含读写调用词 + 敏感路径共存 → Deny(open('/etc/shadow')、os.system('cat /etc/shadow'))\n * 注意:仅对 python -c 等真正的内联脚本代码做读写调用词检测;\n * echo/printf 的字符串参数是自然语言文本,跳过此检测(不可能触发真实读写)。\n * 4. 否则(敏感路径在代码里但无读写调用词,如 print('/etc/shadow')) → Allow\n * 5. 目录遍历 + 文件读写组合 → Deny(os.listdir + open() 动态发现并读写文件,绕过静态路径检测)\n * 注意:仅对 python -c 等真正的内联脚本代码做此检测。\n * 6. 否则(无目录遍历读写组合) → Allow\n *\n * 凭据文件不进此判定(coordinator 层 isCredential 直接 Deny)。\n */\n\nexport interface InlineAnalysisResult {\n /** 是否命中本判定器可处理的内联脚本场景;false 时回退原逻辑 */\n actionable: boolean;\n allowed: boolean;\n reason: string;\n riskLevel: 'low' | 'medium' | 'high' | 'critical';\n riskType: string;\n}\n\n// 内联脚本解释器 + 代码标志:python -c / perl -e / ruby -e / php -r / node -e / lua -e\n// 捕获 -c/-e/-r 后的代码内容(双引号组 1 / 单引号组 2,支持转义)\nconst INLINE_CODE_RE = /(?:python|python3|perl|perl5|ruby|jruby|mruby|node|php|lua)\\s+(?:-[a-zA-Z]*[cera][a-zA-Z]*\\s+)\"([^\"\\\\]*(?:\\\\.[^\"\\\\]*)*)\"|'([^'\\\\]*(?:\\\\.[^'\\\\]*)*)'/gi;\n\n// echo / printf 的字符串参数(双引号组 1 / 单引号组 2)\nconst ECHO_STRING_RE = /\\b(?:echo|printf)\\s+\"([^\"\\\\]*(?:\\\\.[^\"\\\\]*)*)\"|\\b(?:echo|printf)\\s+'([^'\\\\]*(?:\\\\.[^'\\\\]*)*)'/gi;\n\n// echo / printf 命令本身(用于 isLiteralTextCommand 门控)\nconst ECHO_CMD_RE = /(?:^|\\s|;|&&|\\|\\|)(?:echo|printf)\\s/gi;\n\n/** 判断命令是否为 echo/printf 等纯文本输出命令(敏感路径可能作为字符串字面量出现)。\n\n echo/printf 含真实文件重定向(> /path,非 /dev/null 丢弃、非 >& fd)时返回 false——\n 重定向目标是真实写文件,路径不是字面量,不当文本命令(否则 echo x > '~/.bashrc'\n 被当文本命令 → inline_analyzer 把引号内路径当字面量 → 漏报敏感路径写)。 */\nexport function isLiteralTextCommand(command: string): boolean {\n ECHO_CMD_RE.lastIndex = 0;\n if (!ECHO_CMD_RE.test(command)) return false;\n // 含真实文件重定向 → 不是纯文本输出\n if (command.includes('>')) {\n let d = command.replace(/<=>|>=|<=|<>|=>/g, ' ');\n d = d.replace(/(?:2|&|1)?\\s*>\\s*\\/dev\\/null\\b/g, '');\n // 摘引号重定向目标(去引号保留路径,支持 / 或 ~ 开头)\n d = d.replace(new RegExp(\">{1,2}\\\\s*(['\\\"])([~./][^'\\\"]+)\\\\1\", \"g\"), (_m, _q, p) => '>' + p);\n d = d.replace(/'[^']*'|\"[^\"]*\"/g, '');\n if (/>{1,2}\\s*(?!&)\\S/.test(d)) {\n return false;\n }\n }\n return true;\n}\n\n// 读写调用词:仅用于 python -c 等真正的内联脚本代码(不对 echo/printf 的字符串生效)。\n// 出现这些词 + 敏感路径共存 → 判为真实读写。\n//\n// 全部采用组合/函数调用形态,避免自然语言误触发:\n// - 函数调用形态:open(, read(, write(, system(, exec(, eval( 等(后跟 '(')\n// - 组合关键词:os.system, import os, shell=True 等(自带足够区分度)\n// - 不再包含裸短词(open, read, system, exec 等),因 \\b 无法区分编程调用与自然语言\nconst READ_WRITE_KEYWORDS = [\n // 函数调用形态(关键词后跟 '(')\n 'open(', 'read(', 'write(', 'fopen(', 'system(', 'exec(', 'eval(',\n 'popen(', 'load(', 'dump(',\n // 文件读写(组合形态)\n 'readline', 'readlines', 'writelines', 'getpass',\n 'pickle.load', 'yaml.load', 'json.load', 'json.read', 'configparser',\n 'fread', 'fwrite', 'fgets',\n // 子进程执行(组合形态)\n 'os.system', 'os.popen', 'subprocess', 'os.exec', 'os.spawn',\n 'import os', 'import subprocess',\n 'shell=true', 'check_output', 'check_call', 'run(',\n // 绕过变体检测\n 'getattr(', '__builtins__', 'globals(', 'locals(',\n // PHP\n 'file_get_contents', 'file_put_contents', 'passthru', 'shell_exec', 'proc_open',\n // Perl-Ruby\n '<stdin>', 'open my',\n];\n\n// 写入+执行绕过链\nconst WRITE_EXEC_CHAIN_PATTERNS: RegExp[] = [\n // echo/cat/printf \"...\" > file && bash/sh/python file\n /(?:echo|cat|printf)\\b.*?>\\s*\\S+.*(?:&&|;|\\|)\\s*(?:bash|sh|zsh|python\\d?|perl|ruby|node|php)\\s/gis,\n // ... | bash / | sh / | python(管道喂解释器执行)\n /\\|\\s*(?:bash|sh|zsh|python\\d?|perl|ruby|node|php)\\b/gi,\n // eval \"$(cat ...)\" / eval \"$(echo ...)\"\n /eval\\s+\"\\$\\(/gi,\n // xargs bash / xargs sh\n /\\|\\s*xargs\\s+(?:bash|sh|zsh)/gi,\n];\n\n// 重定向写入敏感路径:> / >> 后跟敏感路径 = 真实写入(不是字符串字面量)\n// 敏感路径片段(非凭据,凭据已在 coordinator 层直接 Deny 不进此判定)\n// 对齐 Python inline_analyzer._build_redirect_to_sensitive_re(profile):Python 按\n// profile.sensitive_paths 动态编译(其中含 ~/.bashrc)。TS 无 profile 运行时注入,\n// 故在 ROOT/HOME/CREDENTIAL 静态列表基础上,额外补 shell rc 文件名片段,\n// 让 `echo 'x' >> ~/.bashrc`、`echo 'x' >> /storage/Users/currentUser/.bashrc`\n//(鸿蒙 home 形态)都能被识别为真实重定向写入 → Deny,而非落到\"文本字面量\"放行。\n// 注意:shell rc 片段用文件名匹配(不带 ~ 前缀),可命中任意 home 绝对路径下的 rc 文件。\nconst SHELL_RC_FRAGMENTS = [\n '.bashrc', '.zshrc', '.profile', '.bash_profile', '.zprofile',\n];\nconst SENSITIVE_PATH_FRAGMENTS = [\n '/etc/shadow', '/etc/gshadow', '/etc/passwd', '/etc/sudoers', '/etc/hosts',\n '/etc/crontab', '/etc/systemd/', '/etc/ssh/sshd_config', '/boot/', '/proc/sys/',\n '/sys/', '/dev/mem', '/dev/kmsg', '.ssh/id_rsa', '.ssh/id_ed25519',\n '.ssh/authorized_keys',\n ...SHELL_RC_FRAGMENTS,\n];\nconst REDIRECT_TO_SENSITIVE_RE = new RegExp(`>{1,2}\\\\s*(?:\\\\S*/)?(${SENSITIVE_PATH_FRAGMENTS.map((p) => p.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')).join('|')})(?:\\\\s|$)`, 'i');\n\nexport function extractInlineCode(command: string): string {\n const parts: string[] = [];\n let m: RegExpExecArray | null;\n INLINE_CODE_RE.lastIndex = 0;\n while ((m = INLINE_CODE_RE.exec(command)) !== null) {\n const code = m[1] ?? m[2];\n if (code) parts.push(code);\n }\n ECHO_STRING_RE.lastIndex = 0;\n while ((m = ECHO_STRING_RE.exec(command)) !== null) {\n const code = m[1] ?? m[2];\n if (code) parts.push(code);\n }\n return parts.join('\\n');\n}\n\nfunction hasWriteExecChain(command: string): boolean {\n return WRITE_EXEC_CHAIN_PATTERNS.some((p) => {\n p.lastIndex = 0;\n return p.test(command);\n });\n}\n\n// 目录遍历关键词:用于检测通过动态发现文件路径绕过静态路径匹配的行为\n// 仅对 python -c 等真正的内联脚本代码生效\nconst DIR_TRAVERSAL_KEYWORDS = [\n // Python 目录遍历\n 'os.listdir', 'os.walk', 'os.scandir',\n 'glob.glob', 'glob.iglob', 'pathlib.', 'iterdir', 'rglob',\n 'scandir(', 'listdir(',\n];\n\nfunction hasDirTraversal(code: string): boolean {\n /** 检测代码中是否含目录遍历函数(用于识别动态文件发现绕过行为)。 */\n const lower = code.toLowerCase();\n return DIR_TRAVERSAL_KEYWORDS.some((kw) => lower.includes(kw));\n}\n\nexport function hasReadWriteKeyword(code: string): boolean {\n /** 检测代码中是否含读写调用词(仅用于 python -c 等真正的内联脚本代码)。\n * 全部关键词为组合/函数调用形态(open(, os.system, import os 等),\n * 不会在自然语言文本里误触发。 */\n const lower = code.toLowerCase();\n return READ_WRITE_KEYWORDS.some((kw) => lower.includes(kw));\n}\n\n/**\n * 对内联脚本做静态语义判定。\n * 调用前提:coordinator 已确认是 inline 脚本 + 命中非凭据敏感路径。\n */\nexport function analyzeInlineScript(command: string): InlineAnalysisResult {\n const code = extractInlineCode(command);\n if (!code) {\n // 提取不到代码(命令结构不匹配已知 inline 模式)→ 不处理,回退保守\n return { actionable: false, allowed: true, reason: '', riskLevel: 'low', riskType: '' };\n }\n\n // 1. 写入+执行绕过链 → Deny\n if (hasWriteExecChain(command)) {\n return {\n actionable: true,\n allowed: false,\n reason: '内联脚本含写入文件后执行的模式,疑似绕过敏感路径检测',\n riskLevel: 'critical',\n riskType: 'script_execution',\n };\n }\n\n // 1.5 重定向写入敏感路径(echo '...' >> /etc/hosts 等)→ 真实写入 → Deny\n const redirMatch = command.match(REDIRECT_TO_SENSITIVE_RE);\n if (redirMatch) {\n return {\n actionable: true,\n allowed: false,\n reason: `重定向写入敏感路径: ${redirMatch[1]}`,\n riskLevel: 'critical',\n riskType: 'file_access',\n };\n }\n\n // 1.6 目录遍历 + 文件读写组合 → 不自行判定,回退 coordinator 走层3 LLM 分析\n // 检测 os.listdir/glob/pathlib 等目录遍历函数 + open()/write()/read() 等读写调用,\n // 用于识别\"通过动态发现文件路径绕过静态路径匹配\"的行为。\n // 仅对 python -c 等真正的内联脚本代码做此检测(echo/printf 无此能力)。\n // 注意:此处返回 actionable: false,让 coordinator 回退到正常逻辑,\n // 由层2 的 _checkIndirectFileAccess 规则触发层3 LLM 语义判断。\n const isEchoOrPrintf1 = isLiteralTextCommand(command);\n if (!isEchoOrPrintf1 && hasDirTraversal(code) && hasReadWriteKeyword(code)) {\n return { actionable: false, allowed: true, reason: '', riskLevel: 'low', riskType: '' };\n }\n\n // 2. 含读写调用词 → 判为真实读写 → Deny\n // 注意:仅对 python -c 等真正的内联脚本代码做此检测。\n // echo/printf 的字符串参数是自然语言文本,不可能触发真实文件读写;\n // 重定向(>> /etc/hosts)和管道执行(| bash)已在步骤 1/1.5 覆盖。\n const isEchoOrPrintf = isLiteralTextCommand(command);\n if (!isEchoOrPrintf && hasReadWriteKeyword(code)) {\n return {\n actionable: true,\n allowed: false,\n reason: '内联脚本含敏感路径且含文件读写/命令执行调用,判为真实访问',\n riskLevel: 'critical',\n riskType: 'file_access',\n };\n }\n\n // 3. 敏感路径在代码里但无读写调用词 → 文本字面量 → Allow\n return {\n actionable: true,\n allowed: true,\n reason: '敏感路径仅作为文本字面量出现,未伴随读写操作',\n riskLevel: 'low',\n riskType: 'file_access',\n };\n}\n","/**\n * 归一化规则加载器(单一事实源,与 Python rules_loader.py 对齐)。\n *\n * L1/L2/L3 的正则规则数据统一存放在 agent_moss/rules/ 下:\n * - l1_rules.json: 危险命令 / 注入关键词 / 敏感路径\n * - l2_rules.json: 意图偏离 / 密码修改授权 / 用户删除授权\n * - l3_rules.json: skill 关键词映射\n *\n * Python 与 TS 两端都从这些 JSON 读取,消除双端规则漂移。\n *\n * 路径解析(健壮多候选):\n * 本模块可能被 tsup 内联进不同入口 bundle,`__dirname` 随打包产物而异:\n * - dist/cli.js / dist/server.js → __dirname = dist/\n * - dist/engine/coordinator.js → __dirname = dist/engine/\n * - dev (vitest 源文件) ts/src/infra/ → __dirname = ts/src/infra/\n * 因此枚举所有可能的 rules 目录候选,命中即用(首个存在者)。\n */\nimport { readFileSync, existsSync } from 'fs';\nimport { resolve, dirname } from 'path';\nimport { fileURLToPath } from 'url';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n// 候选 rules 目录(覆盖 dist / dist/engine / dev 源 三种 __dirname 形态)。\n// 从 __dirname 出发尝试若干相对深度,命中 agent_moss/rules 或 dist/rules 即用。\nconst RULES_DIR_CANDS = (() => {\n const cands: string[] = [\n // dist: __dirname=dist/ → dist/rules;__dirname=dist/engine/ → dist/engine/../rules=dist/rules\n resolve(__dirname, '../rules'),\n resolve(__dirname, 'rules'),\n // dev src: __dirname=ts/src/infra/ → ts/src/infra/../../../agent_moss/rules = 仓库根 agent_moss/rules\n resolve(__dirname, '../../../agent_moss/rules'),\n // dist 但 __dirname 指向 dist/engine 再往上两级的仓库根 agent_moss/rules\n resolve(__dirname, '../../../../agent_moss/rules'),\n // 相对当前工作目录的仓库根(兜底,兼容以仓库根为 cwd 运行)\n resolve(process.cwd(), 'agent_moss/rules'),\n ];\n return cands.filter((c) => existsSync(c));\n})();\n\nfunction findRulesFile(name: string): string | null {\n for (const dir of RULES_DIR_CANDS) {\n const p = resolve(dir, name);\n if (existsSync(p)) return p;\n }\n return null;\n}\n\nfunction loadJson(name: string): Record<string, any> {\n const p = findRulesFile(name);\n if (!p) return {};\n try {\n return JSON.parse(readFileSync(p, 'utf-8')) || {};\n } catch {\n return {};\n }\n}\n\n/** L1 规则数据:{dangerous_commands, injection_detection, sensitive_path_access} */\nexport function loadL1(): Record<string, any> {\n return loadJson('l1_rules.json');\n}\n\n/** L2 规则数据:{intent_consistency, password_modify_consent, user_deletion_consent} */\nexport function loadL2(): Record<string, any> {\n return loadJson('l2_rules.json');\n}\n\n/** L3 规则数据:{category: {skill_id: [keywords]}} */\nexport function loadL3(): Record<string, any> {\n return loadJson('l3_rules.json');\n}","import * as fs from 'fs';\nimport { SecurityJudgment } from './types';\nimport type { AnalysisInput } from './coordinator';\nimport { extractInlineCode } from './inline-analyzer.js';\nimport { getAgentExtensions } from '../agents';\nimport type { AgentExtensions } from '../agents';\nimport { loadL1, loadL2 } from '../infra/rules-loader';\n\n/**\n * Layer 2: Logic rule detection.\n * Checks behavioral patterns: read-before-write, intent consistency,\n * sensitive path access, privilege escalation, and lateral movement.\n * Runs in < 1ms, no LLM cost.\n */\n\n// Sensitive paths with per-path risk levels (unified Python + TS)\n\ninterface SensitivePathEntry { path: string; riskLevel: string; desc: string; credential?: boolean; }\n\nfunction _loadSensitivePathScope(scope: 'root' | 'home' | 'credential'): SensitivePathEntry[] {\n // 归一化自 agent_moss/rules/l1_rules.json(单一事实源,与 Python 共用)。\n // 每条含 scope(root/home/credential) + deny_mode;deny_mode=deny_both 视为 credential。\n const sps = (loadL1().sensitive_path_access || []) as any[];\n return sps\n .filter((sp) => sp.scope === scope)\n .map((sp) => ({\n path: sp.path,\n riskLevel: sp.risk_level,\n desc: sp.desc,\n credential: sp.deny_mode === 'deny_both' ? true : undefined,\n }));\n}\n\nexport const ROOT_SENSITIVE_PATHS: { path: string; riskLevel: string; desc: string; credential?: boolean }[] = _loadSensitivePathScope('root');\n\nexport const HOME_SENSITIVE_PATHS: { path: string; riskLevel: string; desc: string; credential?: boolean }[] = _loadSensitivePathScope('home');\n\n// Credential files: intercept on both read and write (reading credentials is equally dangerous)\n// credential=true 使 seed 推导出 deny_mode=deny_both,与 Python 一致(对齐单一事实源)。\nexport const CREDENTIAL_PATHS: { path: string; riskLevel: string; desc: string; credential?: boolean }[] = _loadSensitivePathScope('credential').map(({ path, riskLevel, desc }) => ({ path, riskLevel, desc, credential: true }));\n\n// 只读工具精确名(豁免 read_before_write;与 coordinator READONLY_SENSITIVE_TOOLS/FULLY_SAFE_TOOLS 对齐)。\n// 注意:不含 filemgr-writefile/filemgr-editfile/filemgr-searchreplace(这些是真写)。\nconst NON_WRITE_TOOLS = new Set([\n 'ask_user_question', 'glob', 'grep', 'list_dir', 'count_text_length', 'search',\n // filemgr 只读三件套(globfiles 在 coordinator FULLY_SAFE_TOOLS 提前放行,此处兜底防御非 coordinator 入口)\n 'filemgr-globfiles', 'filemgr-readfile', 'filemgr-grepfiles',\n // 通用只读工具名\n 'read', 'read_file', 'file_read', 'head', 'tail', 'cat',\n]);\n\n// 非 bash/terminal 类工具前缀豁免 read_before_write。\n// 仅保留通用基线前缀(与 EXCLUDED_PREFIXES / SENSITIVE_EXCLUDED_PREFIXES 一致):\n// memory-/skill-manager-/mailbox-/app- 是数据/编排/通信工具,read_before_write(写文件前先读)对其\n// 无意义,且工具名含 remove/update(memory-removeMemory/memory-updateUserPortrait)会命中\n// WRITE_KEYWORDS 子串 → 误判为写。L2 层独立豁免,不再仅依赖 coordinator opendesk 白名单。\n// 不含 skill-(任意能力,coordinator 故意保留 L3)、todomgr-/planning-(opendesk 专属命名空间,\n// 经 opendesk/rules.json builtin_safe_action_types 在 coordinator 层豁免 L2+L3,不到 L2)。\n// mailbox-sendEmail/replyEmail 的外传风险由 L3 LLM 管,不归 L2 read_before_write。\nconst NON_WRITE_TOOL_PREFIXES = ['memory-', 'skill-manager-', 'mailbox-', 'app-'];\n\n// Read-only commands that use > for output redirection (not write intent)\nconst READ_ONLY_REDIR_CMDS = new Set(['cat', 'head', 'tail', 'less', 'more', 'grep', 'find', 'awk', 'sed', 'sort', 'uniq', 'wc', 'cut', 'strings', 'od', 'xxd', 'hexdump']);\n\n// Write keywords for read-before-write detection (also used by L1 SensitivePathChecker)\nexport const WRITE_KEYWORDS = ['write', '写入', 'save', '保存', 'modify', '修改', 'update', '更新', 'delete', '删除', 'remove', '移除', 'create', '创建', 'append', '追加', 'truncate', '截断', 'overwrite', '覆盖', 'replace', '替换', 'edit'];\n\n// 写/删命令词边界正则(对齐 Python _WRITE_COMMAND_RES)。\n// 子串匹配无法可靠识别 rm/cp/dd(\"rm\" 误命中 arm/form),故用词边界。\nexport const WRITE_COMMAND_RES: RegExp[] = [\n /\\brm\\b/, /\\bunlink\\b/, /\\brmdir\\b/, /\\bshred\\b/, /\\bcp\\b/, /\\bmv\\b/,\n /\\binstall\\b/, /\\btee\\b/, /\\bdd\\b/, /\\bmkfs\\b/,\n /\\b(fdisk|parted|cfdisk|sfdisk)\\b/, /\\bchmod\\b/, /\\bchown\\b/, /\\btruncate\\b/,\n];\n\n// 只读命令集合(重定向写判定用,对齐 Python READ_ONLY_COMMANDS)。\n// 这些命令带 > 也是输出重定向非写文件意图(如 cat file > /dev/null)。\nexport const READ_ONLY_COMMANDS = new Set([\n 'cat', 'head', 'tail', 'less', 'more', 'grep', 'find', 'awk', 'sed',\n 'sort', 'uniq', 'wc', 'cut', 'strings', 'od', 'xxd', 'hexdump', 'tr',\n 'file', 'stat', 'du', 'df', 'ls', 'dir', 'tree', 'nl', 'tac', 'rev',\n // NEW-FP-I: echo/printf 是文本输出命令,参数是字面量非写目标。加入此集让\n // read_before_write 的 echo 段走只读命令分支(只提取重定向目标,不提取参数路径),\n // 避免 echo \"cat /etc/shadow\" > /tmp/x.sh 的引号内 /etc/shadow 被当写目标误报。\n // echo \"x\" > /tmp/x.sh 的重定向目标 /tmp/x.sh 仍被提取(真实写不漏报)。\n 'echo', 'printf',\n 'lsblk', 'blockdev', 'smartctl', 'udevadm', 'dmidecode', 'lscpu', 'lspci',\n 'lsusb', 'lsmem', 'lsns', 'lsof', 'hwinfo', 'inxi', 'fdisk', 'parted',\n 'dmesg', 'journalctl', 'systemctl', 'hostnamectl', 'localectl', 'timedatectl',\n 'ps', 'top', 'free', 'vmstat', 'iostat', 'mpstat', 'pidof', 'pgrep',\n 'ip', 'ifconfig', 'route', 'ss', 'netstat', 'arp', 'ethtool', 'nmcli',\n 'uname', 'arch', 'nproc', 'getconf', 'getent', 'id', 'whoami', 'who',\n 'w', 'last', 'uptime', 'lsmod', 'modinfo', 'sysctl',\n]);\n\n// 重定向到 /dev/null 的丢弃写法(对齐 Python _DEVNULL_REDIRECT_RE)。\n// 注意带 g 标志:一条诊断命令常含多个 2>/dev/null(cd ... && ls ... 2>/dev/null; find ... 2>/dev/null),\n// JS String.replace 无 g 只替换首个,残留的 2>/dev/null 仍带 `>` 会触发重定向写误判(FP)。\n// Python 端用 re.sub 全局替换,此处对齐之。\nconst DEVNULL_REDIRECT_RE = /(?:2|&|1)?\\s*>\\s*\\/dev\\/null\\b/g;\n\n/**\n * 综合判定是否为写/删操作(对齐 Python _is_write_operation,单一事实源)。\n * 供 L2 read_before_write 与 L1 sensitive_path 共用,避免手写复刻漂移。\n *\n * 1. WRITE_KEYWORDS 子串匹配 actionType+actionDetail(与 Python 一致,不加词边界以保持双端同步)\n * 2. WRITE_COMMAND_RES 词边界正则(rm/cp/dd/tee/truncate/...)\n * 3. sed -i 原地编辑\n * 4. 重定向写入:剥 devnull 后有 `>` 且首词非只读命令\n */\nexport function isWriteOperation(actionType: string, actionDetail: string, writeKeywords: string[] = WRITE_KEYWORDS): boolean {\n // 1. 关键词子串匹配(actionType 或 actionDetail)\n if (writeKeywords.some(kw => actionType.includes(kw) || actionDetail.includes(kw))) return true;\n // 2. 写/删命令词边界\n if (WRITE_COMMAND_RES.some(rx => rx.test(actionDetail))) return true;\n // 3. sed -i 原地编辑\n if (/\\bsed\\s+-[a-zA-Z]*i/i.test(actionDetail)) return true;\n // 3b. wget/curl + -O/-o/--output 下载写入(无 > 重定向,漏判 → 漏报,且可写 shell 后门绕过敏感路径)\n // 3c. rsync 同步写 dest(非 --list-only/--dry-run/-n 只读模式)\n // 两类都按命令段判定首词(排除 echo/printf 字面量)\n for (const seg of actionDetail.split(/&&|\\|\\||;|\\n/)) {\n const trimmed = seg.trim();\n if (!trimmed) continue;\n const parts = trimmed.split(/\\s+/);\n const fw = parts[0]?.toLowerCase() || '';\n if (fw === 'wget' || fw === 'curl') {\n // NEW-FP-C: -O- / -o- / --output-document=- / --output=- 是 stdout(值为 -),不算文件写\n const isStdout = /\\s(?:-O|-o)-(?:\\s|$)/.test(trimmed) ||\n /\\s--output-document=-(?:\\s|$)/i.test(trimmed) ||\n /\\s--output=-(?:\\s|$)/i.test(trimmed);\n if (isStdout) continue;\n // NEW-FP-N: -o /dev/null / --output=/dev/null 是丢弃响应体只测状态码,非真实写文件\n const isDevnull = /\\s(?:-O|--output-document|--output)\\s*\\/dev\\/null(?:\\s|$)/i.test(trimmed) ||\n /\\s(?:-O|--output-document|--output)=[/]?dev\\/null(?:\\s|$)/i.test(trimmed);\n if (isDevnull) continue;\n if (/\\s(?:-O|--output-document|--output)(?:=|\\s|$)/i.test(trimmed) || /\\s-O\\S/.test(trimmed)) {\n return true;\n }\n }\n if (fw === 'rsync' && !/--list-only|--dry-run/i.test(trimmed) && !/(^|[^a-zA-Z])-n([^a-zA-Z]|$)/.test(trimmed)) {\n return true;\n }\n }\n // 4. 重定向写入:先排除 /dev/null 丢弃和比较运算符,再看是否还有真实文件重定向。\n // NEW-FN-D 修复:不再用「整条命令首词是否只读」判断——`cat in > out` 里 cat 是\n // 只读命令但其重定向目标 out 是真实写文件(覆写/追加),应判写。只读命令的「安全\n // 重定向」只指 `> /dev/null`(丢弃输出,已剥)。改为只读命令带真实文件重定向也算写。\n // fd 重定向(>&N / N>&M / 2>&1)不是写文件,用「> 后紧跟 &」排除。\n // grep/awk 搜索模式里的 > 字面量(如 grep \"a>b\" file)不是重定向——剥引号内容后再判。\n if (actionDetail.includes('>')) {\n // 先剥掉比较运算符(>=, <=, <>, <=>, =>),避免 Python 代码里的 `r.get('seq',0) >= 28`\n // 被当成重定向写(`>=` 含 `>`)。这些是表达式而非重定向,不应计入写判定。\n const detailWithoutCompare = actionDetail.replace(/<=>|>=|<=|<>|=>/g, ' ');\n const detailWithoutDevnull = detailWithoutCompare.replace(DEVNULL_REDIRECT_RE, '');\n // 先摘「> '引号路径'」为裸路径(支持引号包裹的重定向目标,如 echo x > '/tmp/file'),\n // 否则下一步剥引号内容会把重定向目标路径也删掉 → 漏判写(漏报)。\n const detailUnquotedRedirect = detailWithoutDevnull.replace(\n />{1,2}\\s*(['\"])([~./][^'\"]+)\\1/g,\n (_m, _q, p) => '>' + p,\n );\n // 剥掉剩余引号内内容(grep/awk 搜索模式、python -c 代码里的 > 字面量),只看引号外\n // 是否还有真实文件重定向。\n const detailWithoutQuotes = detailUnquotedRedirect.replace(/'[^']*'|\"[^\"]*\"/g, '');\n // 真实文件重定向:> 或 >> 后紧跟非空白、非 & 的文件目标字符。\n // `>{1,2}\\s*(?!&)\\S` 匹配 echo x > /file、cat in >file、sort in >> /file;\n // 排除 ls 2>&1、echo >&2(>& 紧邻或 > 后 & 是 fd 合并,非写文件)。\n if (/>{1,2}\\s*(?!&)\\S/.test(detailWithoutQuotes)) {\n return true;\n }\n }\n return false;\n}\n\n// Read keywords for read-before-write detection\nconst READ_KEYWORDS = ['read', '读取', 'cat', 'head', 'tail', 'less', 'more', 'view', '查看', 'open', '打开', 'load', '加载', 'grep', 'search', '搜索', 'find', '查找'];\n\n// Create-action exception keywords\nconst CREATE_KEYWORDS = ['创建', '新建', 'create', 'new file', 'touch'];\n\n// Non-interactive password modification patterns\nexport const PASSWORD_MODIFY_PATTERNS: RegExp[] = (() => {\n // 归一化自 agent_moss/rules/l2_rules.json(单一事实源,与 Python 共用)。\n const pats = (loadL2().password_modify_consent || []) as any[];\n return pats.map((p) => new RegExp(p.pattern, 'i'));\n})();\n\n// Non-interactive user/group deletion patterns\nexport const USER_DELETION_PATTERNS: RegExp[] = (() => {\n // 归一化自 agent_moss/rules/l2_rules.json(单一事实源,与 Python 共用)。\n const pats = (loadL2().user_deletion_consent || []) as any[];\n return pats.map((p) => new RegExp(p.pattern, 'i'));\n})();\n\n// Intent deviation patterns (synced with Python linux.py IntentDeviationPattern)\nexport const INTENT_DEVIATION_PATTERNS: { intentKeywords: string[]; dangerousActions: string[]; reason: string }[] = (() => {\n // 归一化自 agent_moss/rules/l2_rules.json(单一事实源,与 Python 共用)。\n const pats = (loadL2().intent_consistency || []) as any[];\n return pats.map((p) => ({\n intentKeywords: p.intent_keywords,\n dangerousActions: p.dangerous_actions,\n reason: p.reason,\n }));\n})();\n\n/**\n * 匹配危险动作词。中文用子串(无词边界歧义),英文用词边界正则。\n *\n * 裸 includes() 会在 actionDetail 参数/搜索模式里误报:\n * - `git log --format=` 含 \"format\" → 误判\"格式化磁盘\"\n * - grep 搜索模式 `NON_WRITE|non_write` 含 \"write\" → 误判\"修改\"\n * - `pip install --update` 含 \"update\" → 误判\"修改\"\n * 英文词用 `(?<!-)\\bWORD\\b`:\n * - 前面不是 `-`(排除 --format / --update / -delete 等参数形态)\n * - 词边界(排除 NON_WRITE 里的 write、arm 里的 rm 等)\n */\nfunction matchDangerousAction(actionDetail: string, action: string): boolean {\n // 中文词(含非 ASCII)走子串匹配\n if (/[^\\x00-\\x7f]/.test(action)) {\n return actionDetail.includes(action);\n }\n // 英文词走词边界 + 排除参数前缀\n const escaped = action.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const re = new RegExp(`(?<![-\\\\w])${escaped}\\\\b`, 'i');\n return re.test(actionDetail);\n}\n\n/** 按时间序收集本次会话的全部意图文本(含历史 prompt,去空、去重、lower 化)。\n * 兼容 dict {text, actions} 与纯文本 string 两种元素(后者为 AgentGate v3 旧格式)。 */\nfunction collectIntentTexts(\n promptSession: string,\n promptHistory?: AnalysisInput['promptHistory'],\n): string[] {\n const texts: string[] = [];\n if (promptHistory) {\n for (const turn of promptHistory) {\n if (typeof turn === 'string') {\n const t = turn.trim();\n if (t) texts.push(t.toLowerCase());\n continue;\n }\n const t = (turn?.text || '').trim();\n if (t) texts.push(t.toLowerCase());\n }\n }\n if (promptSession && promptSession.trim()) {\n texts.push(promptSession.toLowerCase());\n }\n // 去重保序\n const seen = new Set<string>();\n const deduped: string[] = [];\n for (const t of texts) {\n if (!seen.has(t)) {\n seen.add(t);\n deduped.push(t);\n }\n }\n return deduped;\n}\n\nexport function runLogicCheck(input: AnalysisInput): SecurityJudgment | null {\n const { actionHistory, aNext, cwd } = input;\n const actionDetail = aNext.actionDetail.toLowerCase();\n const actionType = aNext.actionType.toLowerCase();\n const resolvedCwd = cwd || '/';\n\n // 非 shell/文件类操作跳过意图一致性和敏感路径检查\n const EXCLUDED_PREFIXES = ['memory-', 'skill-', 'skill-manager-', 'mailbox-', 'app-'];\n const isExcludedType = EXCLUDED_PREFIXES.some(p => actionType.startsWith(p));\n\n // Rule 1: Read-before-write principle\n const rbwResult = checkReadBeforeWrite(actionType, actionDetail, actionHistory, input.reason, resolvedCwd);\n if (rbwResult) return rbwResult;\n\n // Rule 2: Intent deviation detection\n // 只对 shell/文件类操作执行意图一致性检查\n if (!isExcludedType) {\n // 内联脚本命令(python -c / perl -e 等)跳过 intent 的 dangerousAction 词匹配。\n // 内联脚本代码内容里的英文词(print(delete this) 的 delete)是字符串字面量,\n // 不是真实动作;词边界 (?<![-\\w])delete\\b 能挡 print 里的 rm(短词),但挡不住\n // delete(长词独立词)→ intent 误报(Bug4)。内联脚本的「危险」由 L1.2\n // inline-analyzer 专门管(区分字面量 vs 真实调用),intent 不重复管。\n if (!INLINE_SCRIPT_RE.test(actionDetail)) {\n // 收集本次会话的全部意图文本(含历史 prompt,按时间序去重)。\n // 避免多轮会话里 \"continue/继续\" 等最近输入覆盖掉最初的读取/搜索意图而漏报。\n const intentTexts = collectIntentTexts(input.promptSession, input.promptHistory);\n for (const pattern of INTENT_DEVIATION_PATTERNS) {\n // 任一历史 prompt 命中意图词即视为\"存在该意图\"(防\"继续\"覆盖漏报)\n const intentMatched = intentTexts.some(text =>\n pattern.intentKeywords.some(kw => text.includes(kw))\n );\n const dangerousMatched = pattern.dangerousActions.some(kw => matchDangerousAction(actionDetail, kw));\n if (intentMatched && dangerousMatched) {\n return {\n allowed: false,\n reason: pattern.reason,\n riskLevel: 'high',\n riskType: 'intent_deviation',\n confidence: 85,\n source: 'logic_rule',\n violatedLayers: ['2'],\n };\n }\n }\n }\n }\n\n // 注:敏感路径访问检测 (checkSensitivePath) / 危险操作模式检测 / 横向移动检测\n // 已按\"L1 只看这一步\"原则搬至 heuristic.ts 的 runHeuristicCheck。\n // 本函数仅保留需要 action_history / prompt_session / cwd 的 L2 规则。\n\n // Rule 4.5: Indirect file access — inline script with dir traversal + file read/write\n // Uses cwd to list actual files and check against sensitive paths directly\n const indirectResult = checkIndirectFileAccess(actionType, actionDetail, resolvedCwd);\n if (indirectResult) return indirectResult;\n\n // Rule 5: Privilege escalation detection\n // 判据:sudo 后跟的命令本身是包管理/服务管理(apt/systemctl/yum/...)→ 合法运维\n // 直接放行,不要求历史先有一次 admin(新会话首次 sudo apt install 是合法高频运维)。\n // sudo + 非运维命令才查历史有无 admin 上下文;历史也无则视为异常提权。\n // 注意:剥掉 sudo 前缀再匹配 admin 关键词,否则 actionDetail 必含 sudo 导致永远放行。\n // 注:admin 关键词曾尝试词边界 \\b,但 grep apt / pip apt 里 apt 是独立词,\\bapt\\b 仍命中,\n // 词边界无法区分\"命令位置\"vs\"参数位置\",故暂保留子串匹配。提权漏检(grep apt 误当 admin\n // 上下文放行 sudo cat)是已知问题,待用命令位置匹配专项处理。\n // 内联脚本命令(python -c / perl -e 等)跳过提权词匹配:代码内容里的词\n // (print(\"chmod u+s\") 的 chmod u+s)是字符串字面量,不是真实动作,提权子串匹配\n // 会误报(FP-2 变体)。内联脚本的「危险」由 inline-analyzer 管,提权检测不重复管。\n if (INLINE_SCRIPT_RE.test(actionDetail)) {\n // fall through to next rule, skip privilege escalation\n // NEW-FP-J: 提权关键词改为「命令位置」判定。旧逻辑对整个 actionDetail 做子串匹配,\n // grep -rn \"sudo\" file、awk '/sudo/'、echo \"sudo make install\" 里参数/搜索模式/字面量\n // 位置的 sudo 被误判为真实提权。仅当段首词是提权命令(sudo/su/setuid,或 chmod+u+s)\n // 才认为存在提权意图。\n } else if (containsPrivilegeEscalation(actionDetail)) {\n const detailAfterSudo = actionDetail.replace(/(^|\\|\\||&&|\\s)sudo\\s+/g, ' ');\n const isAdminCmd = ['apt', 'systemctl', 'yum', 'dnf', 'pacman', 'zypper', 'apk'].some(kw => detailAfterSudo.includes(kw));\n if (!isAdminCmd) {\n const adminContext = actionHistory.some(h =>\n h.actionDetail.includes('sudo') || h.actionDetail.includes('apt') || h.actionDetail.includes('systemctl') ||\n h.actionDetail.includes('yum') || h.actionDetail.includes('dnf') || h.actionDetail.includes('pacman') ||\n h.actionDetail.includes('zypper') || h.actionDetail.includes('apk')\n );\n if (!adminContext) {\n return {\n allowed: false,\n reason: '检测到提权操作,未发现合法管理上下文',\n riskLevel: 'high',\n riskType: 'privilege_escalation',\n confidence: 85,\n source: 'logic_rule',\n violatedLayers: ['2'],\n };\n }\n }\n }\n\n // 注:横向移动检测已搬至 heuristic.ts (runHeuristicCheck)。\n // Rule 6: Non-interactive password modification consent check\n const pwdResult = checkPasswordConsent(actionType, actionDetail, actionHistory);\n if (pwdResult) return pwdResult;\n\n // Rule 7: User/group deletion consent check\n const userDelResult = checkUserDeletionConsent(actionType, actionDetail, actionHistory);\n if (userDelResult) return userDelResult;\n\n // Rule 8: 组合攻击链检测(combo_chain)\n // 单步操作(创建 Flask 服务 / 端口扫描 / 读 known_hosts)各自无害,但按 kill chain\n // 顺序组合(LISTEN→EXEC→SCAN→CRED)即为后渗透攻击链。镜像 Python\n // logic_rules.py::_check_combo_chain;阶段 pattern 与链定义归一化自\n // l2_rules.json 的 combo_chains 段(单一事实源)。\n const comboResult = checkComboChain(actionHistory, aNext.actionDetail);\n if (comboResult) return comboResult;\n\n return null; // Pass to next layer\n}\n\n// ==================== 组合攻击链检测(combo_chain,镜像 Python _check_combo_chain)====================\n\n// 阶段 pattern(编译自 l2_rules.json combo_chains.stages)\nconst COMBO_STAGES: Record<string, RegExp[]> = (() => {\n const combo = (loadL2().combo_chains || {}) as any;\n const stages: Record<string, RegExp[]> = {};\n for (const [name, pats] of Object.entries((combo.stages || {}) as Record<string, string[]>)) {\n stages[name] = (pats as string[]).map(p => new RegExp(p, 'i'));\n }\n return stages;\n})();\n\n// 链定义(l2_rules.json combo_chains.chains)\nconst COMBO_CHAINS: { id: string; stages: string[]; min_stages: number; risk_level: string; reason: string }[] = (() => {\n const combo = (loadL2().combo_chains || {}) as any;\n return ((combo.chains || []) as any[]).map(c => ({\n id: String(c.id || 'combo_chain'),\n stages: (c.stages || []) as string[],\n min_stages: Number(c.min_stages) || (c.stages || []).length,\n risk_level: String(c.risk_level || 'high'),\n reason: String(c.reason || '检测到组合攻击链'),\n }));\n})();\n\nfunction checkComboChain(\n actionHistory: { actionType: string; actionDetail: string }[],\n actionDetailRaw: string,\n): SecurityJudgment | null {\n // 内联脚本命令(python -c 等):代码内容是字符串字面量,阶段词可能只是文本\n // (print(\"subprocess\")),交 inline-analyzer 专门管,不在此组合判定。\n INLINE_SCRIPT_RE.lastIndex = 0;\n if (INLINE_SCRIPT_RE.test(actionDetailRaw)) return null;\n\n // 动作序列:历史动作(按时间序)+ 当前动作\n const details: string[] = [];\n for (const h of actionHistory) {\n if (h.actionDetail) details.push(h.actionDetail.toLowerCase());\n }\n details.push(actionDetailRaw.toLowerCase());\n\n // 阶段标签序列:每个动作命中哪些阶段(一个动作可命中多阶段)\n const seq: Set<string>[] = details.map(d => {\n const hits = new Set<string>();\n for (const [stage, pats] of Object.entries(COMBO_STAGES)) {\n if (pats.some(p => { p.lastIndex = 0; return p.test(d); })) hits.add(stage);\n }\n return hits;\n });\n\n // 子序列匹配每条链:阶段按顺序在动作序列中出现(贪心,不必连续)\n for (const chain of COMBO_CHAINS) {\n const chainStages = chain.stages;\n if (!chainStages.length || chain.min_stages <= 0) continue;\n let matched = 0;\n let stageIdx = 0;\n for (const hits of seq) {\n if (stageIdx < chainStages.length && hits.has(chainStages[stageIdx])) {\n matched += 1;\n stageIdx += 1;\n if (matched >= chain.min_stages) break;\n }\n }\n if (matched >= chain.min_stages) {\n const riskLevel = (chain.risk_level === 'critical' || chain.risk_level === 'high' ||\n chain.risk_level === 'medium' || chain.risk_level === 'low') ? chain.risk_level : 'high';\n return {\n allowed: false,\n reason: chain.reason,\n riskLevel,\n riskType: 'combo_chain',\n confidence: 85,\n source: 'logic_rule',\n violatedLayers: ['2'],\n };\n }\n }\n\n return null;\n}\n\n// Extract file paths from text (mirrors Python extract_file_paths)\nexport function extractFilePaths(text: string): string[] {\n const paths: string[] = [];\n // Unix paths starting with /(路径前是行首或空白)\n const unixPaths = text.match(/(?:^|\\s)(\\/[^\\s;|&><'\"]+)/g);\n if (unixPaths) paths.push(...unixPaths.map(p => p.trim()));\n // key=value 语法的路径:of=/path、if=/path、--output=/path 等。\n // 现有 unixPaths 正则要求路径前是行首或空白,`of=/tmp/x` 里 / 前是 = 不匹配 →\n // dd of=/path 等漏报(NEW-FN-A)。此正则匹配 `=` 后紧跟的 / 路径。\n // NEW-FP-H: 先剥掉引号内容,避免 echo \"of=/dev/null done\" 这类输出文本里的\n // of=/dev/null 被误当真实写目标。引号内纯路径(dd of=\"/tmp/file\")由下方\n // quotedPaths 独立提取(要求引号内以 / 开头),故剥引号不会漏报真实写。\n const textNoQuotes = text.replace(/'[^']*'|\"[^\"]*\"/g, '');\n const kvPaths = textNoQuotes.match(/(?:=)(\\/[^\\s;|&><'\"]+)/g);\n if (kvPaths) paths.push(...kvPaths.map(p => p.replace(/^=/, '')));\n // Quoted paths\n const quotedPaths = text.match(/[\"']\\/([^\"']+)[\"']/g);\n if (quotedPaths) paths.push(...quotedPaths.map(p => p.replace(/[\"']/g, '')));\n return [...new Set(paths)];\n}\n\nfunction checkReadBeforeWrite(\n actionType: string, actionDetail: string,\n actionHistory: { actionType: string; actionDetail: string }[],\n reason: string, cwd: string\n): SecurityJudgment | null {\n // 豁免非文件类工具前缀(memory-/skill-/mailbox-/todomgr-...)与只读工具,\n // 避免 memory-removeMemory(工具名含 remove)/ filemgr-grepfiles(搜索模式含 write)等误判为写。\n // L2 层独立保护,不再仅依赖 coordinator opendesk 白名单(非 opendesk agent / 单测直调也安全)。\n if (NON_WRITE_TOOL_PREFIXES.some(p => actionType.startsWith(p))) return null;\n if (NON_WRITE_TOOLS.has(actionType)) return null;\n\n // 写判定按工具类型分流:\n // - bash/executebash/terminal-executebash:用 isWriteOperation(对齐 Python\n // _is_write_operation 单一事实源:WRITE_KEYWORDS 子串 + WRITE_COMMAND_RES 词边界\n // rm/cp/dd + sed -i + 重定向(剥 devnull+只读首词保护))。比手写 WRITE_KEYWORDS.includes\n // 多了词边界命令识别,能抓 `rm`/`cp`/`dd` 等;重定向/2>/dev/null 由它统一处理。\n // - 其他工具:只匹配 actionType,不看 actionDetail 内容。\n // 理由:非 shell 工具的写意图只能从工具名体现(filemgr-writefile/write/edit),\n // 参数内容里的中文\"更新\"\"移除\"是业务语义不是文件写语义;\n // grep 搜索模式里的 write/update/remove 子串绝不能算写意图(误报根因)。\n const isBashLike = actionType === 'bash' || actionType === 'executebash' || actionType === 'terminal-executebash';\n const isWrite = isBashLike\n ? isWriteOperation(actionType, actionDetail)\n : WRITE_KEYWORDS.some(kw => actionType.includes(kw));\n\n if (!isWrite) return null;\n\n // 删除/安全命令复合(无真正写命令)不触发 read_before_write。\n // read_before_write 的语义是「写文件前先读内容」,对删除不适用——删除不需要读文件字节,\n // 且删除的元数据预检(rm -rf /etc 等敏感路径、递归)由 L1 命令模式负责(/tmp 清理 L1\n // 判定安全放行,rm -rf /etc L1 拦截)。这是「rm 豁免狭义读内容」而非「跳过 RBW」——\n // 广义元数据预检仍由 L1 完成。判定:命令链无「写命令段」即跳过。写命令段 = 段首词是\n // 写命令(cp/mv/install/tee/dd/truncate/mkfs/sed -i)或含真实重定向写。\n // 注意:chmod/chown 不在此列——改元数据不改文件内容,「写前先读」对其无意义,\n // `chmod 644 /tmp/已有未读` 不应误报。危险 chmod 形态(777/u+s/4755 提权、chmod /敏感路径)\n // 由 L1 专门模式和 sensitive_path 检测负责(WRITE_COMMAND_RES 仍保留 chmod/chown 供敏感路径写判定)。\n // `rm ... && echo done` 豁免,`rm /a && echo x > /b` 仍走 rbw,\n // `chmod 644 /tmp/x`(普通)豁免,`chmod u+s /tmp/x`(提权)由 L1 拦。\n const WRITE_CMDS = new Set(['cp', 'mv', 'install', 'tee', 'dd', 'truncate', 'mkfs', 'fdisk', 'parted']);\n if (isBashLike) {\n const detailNoCompare = actionDetail.replace(/<=>|>=|<=|<>|=>/g, ' ');\n const detailNoDevnull = detailNoCompare.replace(DEVNULL_REDIRECT_RE, '');\n // 先摘「> '引号路径'」为裸路径(支持引号包裹重定向目标),再剥剩余引号内容,\n // 与 isWriteOperation 的重定向判定保持一致(避免两处漂移)。\n const detailUnquotedRedirect = detailNoDevnull.replace(\n />{1,2}\\s*(['\"])([~./][^'\"]+)\\1/g,\n (_m, _q, p) => '>' + p,\n );\n const detailNoQuotes = detailUnquotedRedirect.replace(/'[^']*'|\"[^\"]*\"/g, '');\n const hasRedirectWrite = />{1,2}\\s*(?!&)\\S/.test(detailNoQuotes);\n let hasWriteSeg = hasRedirectWrite;\n if (!hasWriteSeg) {\n for (const seg of actionDetail.split(/&&|\\|\\||;|\\n/)) {\n const trimmed = seg.trim();\n if (!trimmed) continue;\n const fw = trimmed.split(/\\s+/)[0]?.toLowerCase() || '';\n if (WRITE_CMDS.has(fw) || /\\bsed\\s+-[a-zA-Z]*i/i.test(trimmed)) {\n hasWriteSeg = true;\n break;\n }\n // wget/curl + -O/-o/--output 下载写入\n if ((fw === 'wget' || fw === 'curl') &&\n (/\\s(?:-O|--output-document|--output)(?:=|\\s|$)/i.test(trimmed) || /\\s-O\\S/.test(trimmed))) {\n hasWriteSeg = true;\n break;\n }\n // rsync 同步写 dest(非 --list-only/--dry-run/-n 只读模式)\n if (fw === 'rsync' && !/--list-only|--dry-run/i.test(trimmed) && !/(^|[^a-zA-Z])-n([^a-zA-Z]|$)/.test(trimmed)) {\n hasWriteSeg = true;\n break;\n }\n }\n }\n if (!hasWriteSeg) return null;\n }\n\n // Extract target file paths,过滤掉非写目标的参数路径。\n // - cd 是目录切换不是写操作,cd /path 的 /path 不应作为写目标(否则 `cd /敏感 && ls` 误报)。\n // - 读命令(cat/head/tail/grep/find/less/more/wc/cut 等 READ_ONLY_COMMANDS)的文件参数是\n // 读取目标不是写目标,`echo x > /tmp/t1; cat /tmp/t2` 里 t2 是 cat 的读目标却会被\n // extractFilePaths 当写目标提取 → read_before_write 误报(Bug5)。过滤之。\n // - 写命令的源文件参数(cp/mv/install 的首个路径参数)是读取目标不是写目标,\n // `cp /src /dst` 里 /src 是读目标不是写目标 → 误报(NEW-FP-1)。过滤首个路径参数。\n // - dd 的 if=/path 是输入源(读目标),of=/path 才是输出目标(写目标)。\n // `dd if=/dev/zero of=/tmp/x` 里 if= 的 /dev/zero 是读源,必须排除否则误报;\n // of= 的 /tmp/x 是写目标保留(NEW-FN-A:此前 of= 路径根本提取不到 → 漏报)。\n // 逐段法(per-segment):按 &&/||/;/换行 拆命令段,每段独立计算写目标——\n // cd → 无写目标(切目录);\n // 只读命令(cat/grep/sort/head 等)→ 命令参数是读目标,但重定向目标(> /path)\n // 是写目标,需提取(NEW-FN-D:此前整段排除把重定向目标也丢了 → `cat in > out` 漏检 out);\n // cp/mv/install → 排除首个路径(源文件),其余为写目标;\n // dd → 排除 if= 路径(输入源),of= 为写目标;\n // 其他段 → 所有路径为写目标。\n // 关键:排除是 per-segment 局部的,不是全局——否则 `cp /a /b && cp /b /c` 里\n // /b 既是第一段 dest(写目标)又是第二段 source(读目标),全局排除会让第一段\n // 对 /b 的覆写漏检(NEW-FN-B)。逐段计算确保 /b 在第一段仍被作为写目标检查。\n const SOURCE_ARG_CMDS = new Set(['cp', 'mv', 'install', 'rsync']);\n // 重定向写目标正则:> 或 >> 后紧跟文件路径(裸路径或引号包裹,排除 >& fd)。\n // 用 RegExp 构造避免正则字面量里 / 与路径分隔符冲突。\n const REDIRECT_TARGET_RE = new RegExp(\">{1,2}\\\\s*(?!&)(?:'(/[^']+)'|\\\"(/[^\\\\\\\"]+)\\\"|(/[^\\\\s;|&><'\\\\\\\"]+))\");\n const targetPaths: string[] = [];\n for (const seg of actionDetail.split(/&&|\\|\\||;|\\n/)) {\n const trimmed = seg.trim();\n if (!trimmed) continue;\n const firstWord = trimmed.split(/\\s+/)[0]?.toLowerCase() || '';\n if (firstWord === 'cd') {\n continue;\n }\n if (READ_ONLY_COMMANDS.has(firstWord)) {\n // 只读命令:文件参数是读目标,但重定向目标是写目标(NEW-FN-D)。\n // 先摘引号重定向目标(去引号保留路径),再剥剩余引号内容(grep 模式),再提取目标。\n // NEW-FP-M: 先剥 /dev/null 重定向(cat f 2>/dev/null 的 /dev/null 是 stderr 丢弃\n // 非写目标),否则 REDIRECT_TARGET_RE 把 2>/dev/null 提取为写目标误报。\n const segUnquoted = trimmed.replace(new RegExp(\">{1,2}\\\\s*(['\\\"])([~./][^'\\\"]+)\\\\1\", \"g\"), (_m, _q: string, p: string) => '>' + p);\n const segNoDevnull = segUnquoted.replace(DEVNULL_REDIRECT_RE, '');\n const segNoQuotes = segNoDevnull.replace(/'[^']*'|\"[^\"]*\"/g, '');\n const m = segNoQuotes.match(REDIRECT_TARGET_RE);\n if (m) targetPaths.push(m[1] || m[2] || m[3]);\n continue;\n }\n const segPaths = extractFilePaths(trimmed);\n // NEW-FP-N: curl/wget 的 -o /dev/null 是丢弃响应体非真实写文件,排除 /dev/null\n // 路径(extractFilePaths 会把 -o /dev/null 的 /dev/null 提取为写目标 → 误报)。\n const segPathsFiltered = (firstWord === 'wget' || firstWord === 'curl')\n ? segPaths.filter(p => p !== '/dev/null')\n : segPaths;\n if (SOURCE_ARG_CMDS.has(firstWord)) {\n // 排除首个路径(源文件),其余为写目标\n if (segPathsFiltered.length > 1) targetPaths.push(...segPathsFiltered.slice(1));\n } else if (firstWord === 'dd') {\n // dd 的 if= 是输入源(读目标),of= 是输出目标(写目标)。\n // 排除 if= 的路径,保留 of= 的路径作为写目标。\n // NEW-FP-G: of=/dev/null 是丢弃输出非真实写文件(dd if=/dev/zero\n // of=/dev/null 是丢弃测试),与重定向 >/dev/null 同语义,排除避免\n // read_before_write 误报 /dev/null。/dev/zero/urandom 同理(设备文件)。\n const ifSourceMatches = trimmed.match(/\\bif=(\\/[^\\s;|&><'\"]+)/g);\n const ifSourcePaths = new Set(ifSourceMatches ? ifSourceMatches.map((m: string) => m.replace(/^if=/, '')) : []);\n const devNullMatches = trimmed.match(/\\bof=(\\/dev\\/\\S+)/g);\n const devNullTargets = new Set(devNullMatches ? devNullMatches.map((m: string) => m.replace(/^of=/, '')) : []);\n for (const sp of segPaths) {\n if (!ifSourcePaths.has(sp) && !devNullTargets.has(sp)) targetPaths.push(sp);\n }\n } else {\n // 其他段(含重定向写 echo > file、tee、truncate 等):该段所有路径为写目标\n targetPaths.push(...segPathsFiltered);\n }\n }\n // 去重\n const uniqueTargetPaths = [...new Set(targetPaths)];\n if (uniqueTargetPaths.length === 0) return null;\n\n // Collect read paths from history\n const historyReadPaths = new Set<string>();\n for (const action of actionHistory) {\n const histDetail = action.actionDetail.toLowerCase();\n const histType = action.actionType.toLowerCase();\n const isRead = READ_KEYWORDS.some(kw => histType.includes(kw) || histDetail.includes(kw));\n if (isRead) {\n for (const p of extractFilePaths(histDetail)) {\n historyReadPaths.add(p);\n }\n }\n }\n\n // Check if target paths have been read\n const unreadPaths: string[] = [];\n for (const path of uniqueTargetPaths) {\n const hasRead = [...historyReadPaths].some(rp =>\n path === rp || path.startsWith(rp) || rp.startsWith(path)\n );\n if (!hasRead) {\n // 排除新文件创建:文件不存在于磁盘时视为新建,直接放行\n // 同时检查 reason/action_detail 中是否有创建/新建关键词\n let isCreate = !fs.existsSync(path);\n if (!isCreate) {\n isCreate = CREATE_KEYWORDS.some(kw => reason.toLowerCase().includes(kw) || actionDetail.includes(kw));\n }\n if (!isCreate) {\n unreadPaths.push(path);\n }\n }\n }\n\n if (unreadPaths.length > 0) {\n return {\n allowed: false,\n reason: `违反 read_before_write 安全原则:对文件 ${unreadPaths[0]} 执行写入操作,但历史执行序列中未发现对该文件的读取操作`,\n riskLevel: 'high',\n riskType: 'read_before_write',\n confidence: 85,\n source: 'logic_rule',\n violatedLayers: ['2'],\n };\n }\n\n return null;\n}\n\nfunction checkPasswordConsent(\n actionType: string, actionDetail: string,\n actionHistory: { actionType: string; actionDetail: string }[]\n): SecurityJudgment | null {\n if (actionType !== 'bash') return null;\n\n const isPasswordModify = PASSWORD_MODIFY_PATTERNS.some(p => p.test(actionDetail));\n if (!isPasswordModify) return null;\n\n // 检查 action_history 中是否有 ask_user_question 且用户返回了答案\n const hasConsent = actionHistory.some(h =>\n h.actionType.toLowerCase() === 'ask_user_question' && h.actionDetail.trim().length > 0\n );\n if (hasConsent) return null;\n\n return {\n allowed: false,\n reason: '执行非交互式密码修改命令,但历史执行序列中未发现向用户确认密码的 ask_user_question 操作,可能存在未授权的密码修改风险',\n riskLevel: 'high',\n riskType: 'consent_missing',\n confidence: 85,\n source: 'logic_rule',\n violatedLayers: ['2'],\n };\n}\n\nfunction checkUserDeletionConsent(\n actionType: string, actionDetail: string,\n actionHistory: { actionType: string; actionDetail: string }[]\n): SecurityJudgment | null {\n if (actionType !== 'bash') return null;\n\n const isUserDeletion = USER_DELETION_PATTERNS.some(p => p.test(actionDetail));\n if (!isUserDeletion) return null;\n\n // 检查 action_history 中是否有 ask_user_question 且用户确认了\n const hasConsent = actionHistory.some(h =>\n h.actionType.toLowerCase() === 'ask_user_question' && h.actionDetail.trim().length > 0\n );\n if (hasConsent) return null;\n\n return {\n allowed: false,\n reason: '执行删除系统用户命令,但历史执行序列中未发现向用户确认的 ask_user_question 操作,可能存在未授权的用户删除风险',\n riskLevel: 'high',\n riskType: 'consent_missing',\n confidence: 85,\n source: 'logic_rule',\n violatedLayers: ['2'],\n };\n}\n\n// 内联脚本解释器正则\nconst INLINE_SCRIPT_RE = /(?:^|\\s)(?:python|python3|python3\\.\\d+|perl|perl5|ruby|jruby|mruby|node|php|lua)\\s+(?:-[a-zA-Z]*[cer][a-zA-Z]*\\s+)/i;\n\n// NEW-FP-J: 提权关键词「命令位置」判定。仅当段首词是提权命令(sudo/su/setuid,\n// 或 chmod+u+s setuid 位)才认为存在提权意图。引号感知分段:echo \"a; sudo rm\" 的\n// ; 在引号内不分段,整段首词 echo 不触发。grep/awk/echo 首词段的参数是搜索模式/字面量。\nfunction containsPrivilegeEscalation(actionDetail: string): boolean {\n const ad = actionDetail.toLowerCase();\n for (const seg of ad.split(/&&|\\|\\||;|\\n/)) {\n const trimmed = seg.trim();\n if (!trimmed) continue;\n const parts = trimmed.split(/\\s+/);\n const fw = parts[0]?.toLowerCase() || '';\n if (fw === 'sudo' || fw === 'su' || fw === 'setuid') return true;\n if (fw === 'chmod' && /\\bu\\s*\\+\\s*s\\b/.test(trimmed)) return true;\n }\n return false;\n}\n\n// 目录遍历关键词(用唯一名称避免与 inline-analyzer.ts 的 DIR_TRAVERSAL_KEYWORDS 冲突)\nconst DIR_TRAVERSAL_KW = [\n 'os.listdir', 'os.walk', 'os.scandir',\n 'glob.glob', 'glob.iglob', 'pathlib.', 'iterdir', 'rglob',\n 'scandir(', 'listdir(',\n];\n\n/**\n * Rule 4.5: Indirect file access detection.\n * Detects inline scripts that use directory traversal (os.listdir/glob/pathlib)\n * combined with file read/write operations to dynamically discover and access\n * sensitive files, bypassing static path matching.\n *\n * Returns medium risk so the coordinator forwards to Layer 3 LLM analysis\n * instead of denying immediately.\n */\nfunction checkIndirectFileAccess(actionType: string, actionDetail: string, cwd: string): SecurityJudgment | null {\n // Only check bash tool inline scripts\n if (actionType !== 'bash' && actionType !== 'executebash' && actionType !== 'terminal-executebash') {\n return null;\n }\n\n // Check if it's an inline script command\n INLINE_SCRIPT_RE.lastIndex = 0;\n if (!INLINE_SCRIPT_RE.test(actionDetail)) {\n return null;\n }\n\n // Check for directory traversal keywords\n const lowerDetail = actionDetail.toLowerCase();\n const hasTraversal = DIR_TRAVERSAL_KW.some(kw => lowerDetail.includes(kw));\n if (!hasTraversal) {\n return null;\n }\n\n // Extract code and check for read/write keywords, distinguishing read/write/exec\n const READ_KEYWORDS = ['read(', 'readline', 'readlines', 'fread', 'fgets', 'load(', 'getpass', 'file_get_contents'];\n const WRITE_KEYWORDS = ['write(', 'writelines', 'fwrite', 'file_put_contents'];\n const EXEC_KEYWORDS = ['system(', 'exec(', 'eval(', 'popen(', 'os.system', 'os.popen', 'subprocess', 'os.exec', 'os.spawn', 'shell=true', 'check_output', 'check_call', 'run(', 'passthru', 'shell_exec', 'proc_open'];\n const OPEN_KEYWORDS = ['open(', 'fopen('];\n const code = extractInlineCode(actionDetail);\n if (!code) return null;\n const codeLower = code.toLowerCase();\n const hasAnyOp = READ_KEYWORDS.some(kw => codeLower.includes(kw)) ||\n WRITE_KEYWORDS.some(kw => codeLower.includes(kw)) ||\n EXEC_KEYWORDS.some(kw => codeLower.includes(kw)) ||\n OPEN_KEYWORDS.some(kw => codeLower.includes(kw));\n if (!hasAnyOp) {\n return null;\n }\n\n // Determine operation type\n const hasWrite = WRITE_KEYWORDS.some(kw => codeLower.includes(kw));\n const hasExec = EXEC_KEYWORDS.some(kw => codeLower.includes(kw));\n // Write/exec: block all sensitive files. Read only: block only credential files.\n const blockAllSensitive = hasWrite || hasExec;\n\n // Pattern matched — try to list actual files in cwd and check against sensitive paths\n let actualFiles: string[] = [];\n if (cwd && cwd !== '/') {\n try {\n actualFiles = fs.readdirSync(cwd);\n } catch {\n // cwd invalid or inaccessible, fall through\n }\n }\n\n if (actualFiles.length > 0) {\n // Check credential files\n for (const cp of CREDENTIAL_PATHS) {\n const fname = cp.path.split('/').pop() || cp.path;\n if (actualFiles.some(f => f === fname || f.toLowerCase() === fname.toLowerCase())) {\n return {\n allowed: false,\n reason: `内联脚本使用目录遍历动态发现文件并执行读写操作,cwd (${cwd}) 中包含凭据文件: ${fname}`,\n riskLevel: 'high',\n riskType: 'file_access',\n confidence: 95,\n source: 'logic_rule',\n violatedLayers: ['2'],\n isCredential: true,\n };\n }\n }\n\n // Check other sensitive files (only block on write/exec, read-only is safe for non-credential)\n if (blockAllSensitive) {\n for (const sp of [...ROOT_SENSITIVE_PATHS, ...HOME_SENSITIVE_PATHS]) {\n const fname = sp.path.split('/').pop() || sp.path;\n if (actualFiles.some(f => f === fname || f.toLowerCase() === fname.toLowerCase())) {\n return {\n allowed: false,\n reason: `内联脚本使用目录遍历动态发现文件并执行写操作,cwd (${cwd}) 中包含敏感文件: ${fname}`,\n riskLevel: 'high',\n riskType: 'file_access',\n confidence: 95,\n source: 'logic_rule',\n violatedLayers: ['2'],\n };\n }\n }\n }\n\n // No sensitive files found in cwd — safe to allow\n return null;\n }\n\n // cwd invalid, can't check actual files — fall back to medium risk (L3)\n return {\n allowed: false,\n reason: '内联脚本使用目录遍历函数动态发现文件并执行读写操作,无法获取 cwd 实际文件列表,转层3 LLM 分析',\n riskLevel: 'medium',\n riskType: 'file_access',\n confidence: 70,\n source: 'logic_rule',\n violatedLayers: ['2'],\n };\n}\n","import { readFileSync, readdirSync, existsSync } from 'fs';\nimport { resolve, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport { loadL3 } from '../infra/rules-loader';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n// 优先用打包内联目录 dist/skills(npm 安装后自包含);\n// dev 模式(vitest 测试时 __dirname=ts/src/engine)回退到仓库根 agent_moss/skills。\n// 注意:从 ts/src/engine 出发,仓库根 agent_moss/skills 在 ../../../agent_moss/skills\n// (不能写 ../../agent_moss/skills,那是 ts/agent_moss/skills,不存在)。\nconst SKILLS_DIR = resolve(__dirname, '../skills');\nconst SKILLS_DIR_FALLBACK = resolve(__dirname, '../../../agent_moss/skills');\n\n// Skill keyword map (synced with Python skill_engine.py SKILL_KEYWORD_MAP)\n// exported for runtime_config seed (generateSourceDefaults)\nexport const SKILL_KEYWORD_MAP: Record<string, string[]> = (() => {\n // 归一化自 agent_moss/rules/l3_rules.json(单一事实源,与 Python 共用)。\n // l3_rules.json = {category: {skill_id: [keywords]}},展平为 {skill_id: [keywords]}。\n const map: Record<string, string[]> = {};\n const cats = loadL3() as Record<string, Record<string, string[]>>;\n for (const cat of Object.values(cats)) {\n if (!cat || typeof cat !== 'object') continue;\n for (const [skillId, keywords] of Object.entries(cat)) {\n map[skillId] = keywords;\n }\n }\n return map;\n})();\n\nlet cachedSkills: Record<string, string> | null = null;\n\nfunction loadAllSkills(): Record<string, string> {\n if (cachedSkills) return cachedSkills;\n cachedSkills = {};\n\n const dir = existsSync(SKILLS_DIR) ? SKILLS_DIR : SKILLS_DIR_FALLBACK;\n if (!existsSync(dir)) {\n console.warn('[AgentMoss] Skills directory not found:', SKILLS_DIR, 'and fallback:', SKILLS_DIR_FALLBACK);\n return cachedSkills;\n }\n\n const files = readdirSync(dir).filter(f => f.endsWith('.md'));\n for (const f of files) {\n const name = f.replace('.md', '');\n cachedSkills[name] = readFileSync(resolve(dir, f), 'utf-8');\n }\n\n console.log(`[AgentMoss] Loaded ${Object.keys(cachedSkills).length} skills from ${dir}`);\n return cachedSkills;\n}\n\nexport interface SkillMatch {\n skillName: string;\n relevance: number; // 0-1\n skillContent: string;\n}\n\n/**\n * Match skills by keyword relevance (mirrors Python SkillEngine.match_skills).\n * Returns top-3 most relevant skills, or fallback to general_tool_risk_guard.\n */\nexport function matchSkills(\n actionType: string,\n actionDetail: string,\n reason: string,\n maxSkills: number = 3\n): SkillMatch[] {\n const skills = loadAllSkills();\n const combined = `${actionType} ${actionDetail} ${reason}`.toLowerCase();\n const actionDetailLower = actionDetail.toLowerCase();\n const actionTypeLower = actionType.toLowerCase();\n const reasonLower = reason.toLowerCase();\n\n const scores: Record<string, number> = {};\n for (const [skillName, keywords] of Object.entries(SKILL_KEYWORD_MAP)) {\n let score = 0;\n for (const kw of keywords) {\n if (combined.includes(kw)) {\n if (kw === actionTypeLower) score += 2.0;\n else if (actionDetailLower.includes(kw)) score += 1.5;\n else if (reasonLower.includes(kw)) score += 1.0;\n else score += 0.5;\n }\n }\n if (score > 0) scores[skillName] = score;\n }\n\n const sorted = Object.entries(scores).sort((a, b) => b[1] - a[1]);\n const top = sorted.slice(0, maxSkills);\n const maxScore = top[0]?.[1] || 1;\n\n const results: SkillMatch[] = [];\n for (const [name, score] of top) {\n const content = skills[name];\n if (content) {\n results.push({\n skillName: name,\n relevance: Math.min(score / maxScore, 1.0),\n skillContent: content,\n });\n }\n }\n\n // Fallback to general_tool_risk_guard if no match\n if (results.length === 0) {\n const fallback = skills['general_tool_risk_guard'];\n if (fallback) {\n results.push({ skillName: 'general_tool_risk_guard', relevance: 0.3, skillContent: fallback });\n }\n }\n\n return results;\n}\n\n/**\n * Format matched skills for LLM prompt (mirrors Python SkillEngine.format_skills_for_prompt).\n */\nexport function formatSkillsForPrompt(skills: SkillMatch[]): string {\n if (skills.length === 0) return '(未匹配到特定安全检测规则)';\n return skills.map(s =>\n `### 安全检测规则: ${s.skillName} (相关度: ${Math.round(s.relevance * 100)}%)\\n\\n${s.skillContent}`\n ).join('\\n\\n---\\n\\n');\n}\n\n/** Legacy: load all skills as flat string array */\nexport function loadSkills(): string[] {\n const skills = loadAllSkills();\n return Object.entries(skills).map(([name, content]) => `### ${name}\\n${content}`);\n}\n\n/** Reload skills (for hot-reload) */\nexport function reloadSkills(): void {\n cachedSkills = null;\n loadAllSkills();\n}\n","/**\n * Runtime config — full implementation (mirrors Python runtime_config.py).\n *\n * Runtime JSON: ~/.config/agentmoss/agent_moss_runtime.json\n * (env AGENT_MOSS_RUNTIME_CONFIG_PATH override). Seed from OSProfile +\n * module consts + SKILL_KEYWORD_MAP. mergeConfig on load (preserve user\n * toggles, append builtins, mark removed).\n *\n * Priority: env > runtime JSON > agent_moss_settings > default.\n */\n\nimport { readFileSync, writeFileSync, existsSync, mkdirSync, unlinkSync, readdirSync } from 'fs';\nimport { join } from 'path';\nimport { fileURLToPath } from 'url';\nimport { dirname } from 'path';\nimport { getRuntimeConfigDir } from './paths';\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n// 静态 import(非 require):package.json type=module,require 在 ESM 不可用。\n// 这三个模块不反向 import runtime-config,无循环依赖。\nimport { DANGEROUS_PATTERNS, INJECTION_KEYWORDS } from '../engine/heuristic';\nimport {\n ROOT_SENSITIVE_PATHS, HOME_SENSITIVE_PATHS, CREDENTIAL_PATHS,\n PASSWORD_MODIFY_PATTERNS, USER_DELETION_PATTERNS, INTENT_DEVIATION_PATTERNS,\n} from '../engine/logic-rules';\nimport { SKILL_KEYWORD_MAP } from '../engine/skill-loader';\n// type-only import:避免 agents ↔ runtime-config 循环依赖(运行时用 require 取 resolveAgentsDir)\nimport type { AgentExtensions } from '../agents/types';\n\nconst ENV_RUNTIME_CONFIG_PATH = 'AGENT_MOSS_RUNTIME_CONFIG_PATH';\n\nfunction runtimeDir(): string {\n return getRuntimeConfigDir();\n}\n\nconst RUNTIME_CONFIG_DIR = runtimeDir();\nconst RUNTIME_CONFIG_PATH = join(RUNTIME_CONFIG_DIR, 'agent_moss_runtime.json');\n\nconst LAYER_DISABLE_ENV: Record<string, string> = {\n L1_heuristic: 'AGENT_MOSS_DISABLE_HEURISTIC',\n L2_logic_rules: 'AGENT_MOSS_DISABLE_LOGIC_RULES',\n L3_llm_analysis: 'AGENT_MOSS_DISABLE_LLM',\n};\n\nexport const DENY_MODE_LABELS: Record<string, string> = {\n deny_write: '仅拦截写入',\n deny_read: '仅拦截读取',\n deny_both: '读写均拦截',\n};\n\n// ==================== Types ====================\n\nexport interface Rule {\n id: string;\n enabled: boolean;\n builtin: boolean;\n source_removed?: boolean;\n pattern?: string;\n risk_level?: string;\n risk_type?: string;\n reason?: string;\n keyword?: string;\n lang?: string;\n path?: string;\n desc?: string;\n deny_mode?: string;\n source_deny_mode?: string;\n credential?: boolean;\n read_only?: boolean;\n skip_l3_on_disabled?: boolean;\n intent_keywords?: string[];\n dangerous_actions?: string[];\n /** builtin_safe_action_types / builtin_safe_skills 项的值(前缀或精确工具名) */\n value?: string;\n}\n\nexport interface Skill {\n id: string;\n keywords: string[];\n enabled: boolean;\n builtin: boolean;\n}\n\ninterface Category {\n category_enabled?: boolean;\n category_desc?: string;\n rules?: Rule[];\n skills?: Skill[];\n}\n\nexport interface RuntimeConfig {\n version: number;\n layers: { L1_heuristic: boolean; L2_logic_rules: boolean; L3_llm_analysis: boolean };\n L1_rules: Record<string, Category>;\n L2_rules: Record<string, Category>;\n L3_skills: Record<string, Category>;\n /** agent 定制规则(按 agent_id 分区,每 agent 内按类别组织) */\n agent_rules?: Record<string, Record<string, Category>>;\n /** 场景定制规则(按 scenario_id 分区,如 bank;与 agent_rules 同构) */\n scenario_rules?: Record<string, Record<string, Category>>;\n}\n\n// ==================== Path / load / save ====================\n\nexport function getRuntimeConfigPath(): string {\n const envPath = process.env[ENV_RUNTIME_CONFIG_PATH];\n if (envPath) return envPath;\n // agent_moss_settings.json fallback omitted in TS (env-only); default path.\n return RUNTIME_CONFIG_PATH;\n}\n\nexport function saveRuntimeConfig(config: RuntimeConfig): void {\n const p = getRuntimeConfigPath();\n const dir = p.substring(0, p.lastIndexOf('/'));\n if (dir && !existsSync(dir)) mkdirSync(dir, { recursive: true });\n writeFileSync(p, JSON.stringify(config, null, 2), 'utf-8');\n}\n\n/** Minimal default (all layers on, empty rule categories). The full\n * profile-driven seed generator (generate_source_defaults equivalent)\n * is deferred to Stage 4 (console backend); for now a missing runtime\n * file yields this minimal config — coordinator's getDisabledL2RulesWithSkipL3\n * returns {} (safe default, no skip_l3 hard constraint). */\nfunction emptyRuntimeConfig(): RuntimeConfig {\n return {\n version: 1,\n layers: { L1_heuristic: true, L2_logic_rules: true, L3_llm_analysis: true },\n L1_rules: {},\n L2_rules: {},\n L3_skills: {},\n agent_rules: {},\n scenario_rules: {},\n };\n}\n\nexport function loadRuntimeConfig(): RuntimeConfig {\n const p = getRuntimeConfigPath();\n if (!existsSync(p)) {\n // 首次:seed + save,与 py load_runtime_config 的 fallback seed 对齐。\n // 不 seed 时 getDisabledL2RulesWithSkipL3 返回 {}(无 skip_l3 约束),\n // 但 Console 需要全量规则展示,所以必须 seed。\n const seeded = mergeConfig({}, generateSourceDefaults());\n try { saveRuntimeConfig(seeded); } catch { /* 只读 fs 时忽略 */ }\n return seeded;\n }\n try {\n const data = JSON.parse(readFileSync(p, 'utf-8'));\n const merged = mergeConfig(data, generateSourceDefaults());\n return {\n version: data.version || 1,\n layers: {\n L1_heuristic: data.layers?.L1_heuristic ?? true,\n L2_logic_rules: data.layers?.L2_logic_rules ?? true,\n L3_llm_analysis: data.layers?.L3_llm_analysis ?? true,\n },\n L1_rules: merged.L1_rules || {},\n L2_rules: merged.L2_rules || {},\n L3_skills: merged.L3_skills || {},\n agent_rules: merged.agent_rules || {},\n scenario_rules: merged.scenario_rules || {},\n };\n } catch {\n return emptyRuntimeConfig();\n }\n}\n\n// ==================== Layer toggles ====================\n\n/**\n * Is a layer enabled? Priority: env > runtime JSON > default true.\n *\n * Note: the agent_moss_settings.json fallback (used in Python) is not\n * consulted here — env vars are the primary TS-side override. The runtime\n * JSON is authoritative when env is unset.\n */\nexport function isLayerEnabled(layerKey: string): boolean {\n const disableKey = LAYER_DISABLE_ENV[layerKey];\n if (disableKey && process.env[disableKey] === '1') return false;\n const runtime = loadRuntimeConfig();\n const layers = runtime.layers || {} as RuntimeConfig['layers'];\n if (layerKey in layers) return !!layers[layerKey as keyof typeof layers];\n return true;\n}\n\nexport function getEnvOverrides(): Record<string, {\n env_var: string; env_value: string; overridden: boolean; effect: string;\n}> {\n const overrides: Record<string, any> = {};\n for (const [layerKey, envKey] of Object.entries(LAYER_DISABLE_ENV)) {\n const val = process.env[envKey];\n if (val !== undefined) {\n overrides[layerKey] = {\n env_var: envKey,\n env_value: val,\n overridden: val === '1',\n effect: val === '1' ? 'disabled' : 'no_override',\n };\n }\n }\n return overrides;\n}\n\n// ==================== Rule filtering / queries ====================\n\nexport function filterEnabledRules(rules: Rule[], categoryEnabled: boolean = true): Rule[] {\n if (!categoryEnabled) return [];\n return rules.filter(r => r.enabled !== false);\n}\n\nexport function getEnabledL1CommandPatterns(runtime: RuntimeConfig): { pattern: string; risk_level: string; risk_type: string; reason: string }[] {\n const cat = runtime.L1_rules?.dangerous_commands || { category_enabled: true, rules: [] };\n return filterEnabledRules(cat.rules || [], cat.category_enabled).map(r => ({\n pattern: r.pattern || '', risk_level: r.risk_level || '', risk_type: r.risk_type || '', reason: r.reason || '',\n }));\n}\n\nexport function getEnabledL2SensitivePaths(runtime: RuntimeConfig): { path: string; risk_level: string; desc: string; deny_mode: string; credential?: boolean; read_only?: boolean }[] {\n // 优先读 L1_rules.sensitive_path_access(重分类后归属 L1);\n // 回退 L2_rules.sensitive_path_access(兼容迁移前老配置)。函数名保留 l2 前缀仅为兼容。\n let cat = runtime.L1_rules?.sensitive_path_access;\n if (!cat || !cat.rules || cat.rules.length === 0) {\n cat = runtime.L2_rules?.sensitive_path_access || { category_enabled: true, rules: [] };\n }\n return filterEnabledRules(cat.rules || [], cat.category_enabled).map(r => {\n const out: any = { path: r.path || '', risk_level: r.risk_level || '', desc: r.desc || '', deny_mode: r.deny_mode || 'deny_write' };\n if (r.credential) out.credential = true;\n if (r.read_only) out.read_only = true;\n return out;\n });\n}\n\nexport function hasRuntimeConfig(): boolean {\n const p = getRuntimeConfigPath();\n if (!existsSync(p)) return false;\n try {\n JSON.parse(readFileSync(p, 'utf-8'));\n return true;\n } catch { return false; }\n}\n\n// ==================== skip_l3 hard constraint ====================\n\n/**\n * L2 rules with enabled=false AND skip_l3_on_disabled=true, grouped by\n * category, returning their key content (path / intent_keywords / pattern).\n * Consumed by coordinator to build skip_l3_hints for the L3 prompt.\n */\nexport function getDisabledL2RulesWithSkipL3(): Record<string, string[]> {\n let runtime: RuntimeConfig;\n try { runtime = loadRuntimeConfig(); }\n catch { return {}; }\n const result: Record<string, string[]> = {};\n // 敏感路径已重分类到 L1,遍历 L1_rules + L2_rules 两层。函数名保留 l2 前缀仅为兼容。\n for (const layerKey of ['L1_rules', 'L2_rules'] as const) {\n const layer = runtime[layerKey] || {};\n for (const [catName, cat] of Object.entries(layer)) {\n if (!cat.category_enabled) continue;\n const items: string[] = [];\n for (const r of cat.rules || []) {\n if (r.enabled === false && r.skip_l3_on_disabled) {\n if (catName === 'sensitive_path_access') {\n if (r.path) items.push(r.path);\n } else if (catName === 'intent_consistency') {\n items.push(...(r.intent_keywords || []));\n } else if (r.pattern) {\n items.push(r.pattern);\n }\n }\n }\n if (items.length > 0) result[catName] = items;\n }\n }\n return result;\n}\n\n// ==================== Helpers ====================\n\nfunction _slugify(text: string): string {\n return text.toLowerCase().replace(/[^a-z0-9]+/g, '_').replace(/^_|_$/g, '') || 'x';\n}\n\nfunction _generatePatternId(pattern: string): string {\n return `pat_${_slugify(pattern)}`;\n}\n\n/** 从 credential / read_only 推导 deny_mode(向后兼容)。优先用已有 deny_mode。 */\nfunction _deriveDenyMode(rule: Partial<Rule>): string {\n if (rule.deny_mode) return rule.deny_mode;\n if (rule.credential) return 'deny_both';\n if (rule.read_only) return 'deny_read';\n return 'deny_write';\n}\n\n/** 根据 deny_mode 同步 credential / read_only(保持底层检测逻辑兼容) */\nfunction _syncDenyModeFields(rule: Rule): void {\n const dm = rule.deny_mode || 'deny_write';\n if (dm === 'deny_both') {\n rule.credential = true;\n delete rule.read_only;\n } else if (dm === 'deny_read') {\n delete rule.credential;\n rule.read_only = true;\n } else {\n delete rule.credential;\n delete rule.read_only;\n }\n}\n\n// ==================== Seed (generateSourceDefaults) ====================\n//\n// py 的 generate_source_defaults 从 OSProfile 拿 dangerous_commands / sensitive_paths\n// / intent_deviation_patterns / injection_keywords(运行时按 OS 类型分叉)。\n// TS 不分 OS profile(只 win/linux 用于 os_type 字段,不影响规则集),规则集硬编码\n// 在 heuristic.ts / logic-rules.ts 常量里。所以 TS seed 直接从常量生成,不走 profile。\n\nfunction _l1CommandPatternsToRules(): Rule[] {\n // DANGEROUS_PATTERNS 是 RegExp,seed 时存 source 字符串。\n return DANGEROUS_PATTERNS.map((p) => ({\n id: _generatePatternId(p.pattern instanceof RegExp ? p.pattern.source : p.pattern),\n pattern: p.pattern instanceof RegExp ? p.pattern.source : p.pattern,\n risk_level: p.severity,\n risk_type: p.riskType,\n reason: p.description,\n enabled: true,\n builtin: true,\n }));\n}\n\nfunction _l1InjectionKeywordsToRules(): Rule[] {\n return INJECTION_KEYWORDS.map((kw) => ({\n id: `inj_${_slugify(kw.keyword)}`,\n keyword: kw.keyword,\n risk_level: kw.riskLevel,\n lang: kw.lang || 'en',\n enabled: true,\n builtin: true,\n }));\n}\n\nfunction _l2SensitivePathsToRules(): Rule[] {\n const all = [...ROOT_SENSITIVE_PATHS, ...HOME_SENSITIVE_PATHS, ...CREDENTIAL_PATHS] as any[];\n return all.map((sp) => {\n const denyMode = _deriveDenyMode({\n deny_mode: sp.deny_mode,\n credential: sp.credential,\n read_only: sp.read_only,\n });\n const rule: Rule = {\n id: `path_${_slugify(sp.path)}`,\n path: sp.path,\n risk_level: sp.riskLevel,\n desc: sp.desc,\n deny_mode: denyMode,\n source_deny_mode: denyMode,\n skip_l3_on_disabled: true,\n enabled: true,\n builtin: true,\n };\n _syncDenyModeFields(rule);\n return rule;\n });\n}\n\nfunction _l2IntentPatternsToRules(): Rule[] {\n return INTENT_DEVIATION_PATTERNS.map((pat, i) => ({\n id: `intent_${i + 1}_${_slugify(pat.reason.slice(0, 30))}`,\n intent_keywords: pat.intentKeywords,\n dangerous_actions: pat.dangerousActions,\n reason: pat.reason,\n skip_l3_on_disabled: true,\n enabled: true,\n builtin: true,\n }));\n}\n\nfunction _l2PasswordPatternsToRules(): Rule[] {\n return PASSWORD_MODIFY_PATTERNS.map((p) => ({\n id: `pw_${_slugify(p.source)}`,\n pattern: p.source,\n skip_l3_on_disabled: true,\n enabled: true,\n builtin: true,\n }));\n}\n\nfunction _l2UserDeletionPatternsToRules(): Rule[] {\n return USER_DELETION_PATTERNS.map((p) => ({\n id: `ud_${_slugify(p.source)}`,\n pattern: p.source,\n skip_l3_on_disabled: true,\n enabled: true,\n builtin: true,\n }));\n}\n\nfunction _l3SkillsToRules(): Record<string, Category> {\n const skillCategories: Record<string, string[]> = {\n file_operations: ['file_access_guard', 'script_execution_guard', 'indirect_access_guard'],\n network_security: ['data_exfiltration_guard', 'browser_web_access_guard',\n 'lateral_movement_guard', 'email_operation_guard'],\n persistence_supply_chain: ['persistence_backdoor_guard', 'supply_chain_guard',\n 'skill_installation_guard'],\n intent_and_general: ['intent_deviation_guard', 'general_tool_risk_guard'],\n resource: ['resource_exhaustion_guard'],\n };\n const out: Record<string, Category> = {};\n for (const [cat, ids] of Object.entries(skillCategories)) {\n out[cat] = {\n category_enabled: true,\n category_desc: '',\n skills: ids.map((s: string) => ({\n id: s,\n keywords: SKILL_KEYWORD_MAP[s] || [],\n enabled: true,\n builtin: true,\n })),\n };\n }\n const categorized = new Set<string>(Object.values(skillCategories).flat());\n for (const s of Object.keys(SKILL_KEYWORD_MAP)) {\n if (!categorized.has(s)) {\n (out.intent_and_general ??= { category_enabled: true, category_desc: '', skills: [] })\n .skills!.push({\n id: s, keywords: SKILL_KEYWORD_MAP[s], enabled: true, builtin: true,\n });\n }\n }\n out.user_custom = { category_enabled: true, category_desc: '', skills: [] };\n return out;\n}\n\n/** 扫描 agent_moss/agents/<id>/rules.json,转为 agent_rules 分区结构(出厂种子)。\n * 每个 agent 的 rules.json 字段 → agent_rules[<id>] 的 Category 结构(与 L1/L2 同形)。\n * builtin_safe_action_types / builtin_safe_skills 原为 string[],转成 [{value, enabled, builtin}]。\n * 路径内联解析(不 import agents/index.ts 避免 ESM 循环依赖),与 agents/index.ts resolveAgentsDir 同策略。 */\nconst _AGENTS_DIR_PROD = join(__dirname, 'agents');\nconst _AGENTS_DIR_DEV = join(__dirname, '..', '..', '..', 'agent_moss', 'agents');\n\n/** 扫描 agent_moss/scenarios/<id>/rules.json,转为 scenario_rules 分区结构(出厂种子)。\n * 与 _agentRulesToDefaults 同构(场景规则也是 AgentExtensions 结构),唯一区别:\n * 目录是 scenarios/ 而非 agents/。场景不含 builtin_safe_action_types/builtin_safe_skills\n * (场景是部署级约束,不定义 agent 白名单),仍保留这两个类别占位(空 rules),\n * 与 agent 分区结构对齐,console 渲染共用一套模板。 */\nconst _SCENARIOS_DIR_PROD = join(__dirname, 'scenarios');\nconst _SCENARIOS_DIR_DEV = join(__dirname, '..', '..', '..', 'agent_moss', 'scenarios');\nfunction _scenarioRulesToDefaults(): Record<string, Record<string, Category>> {\n const out: Record<string, Record<string, Category>> = {};\n const scenDir = existsSync(_SCENARIOS_DIR_PROD) ? _SCENARIOS_DIR_PROD\n : existsSync(_SCENARIOS_DIR_DEV) ? _SCENARIOS_DIR_DEV : _SCENARIOS_DIR_PROD;\n if (!existsSync(scenDir)) return out;\n let entries: string[];\n try {\n entries = readdirSync(scenDir, { withFileTypes: true })\n .filter(d => d.isDirectory()).map(d => d.name);\n } catch {\n return out;\n }\n for (const scenarioId of entries) {\n const rulesFile = join(scenDir, scenarioId, 'rules.json');\n if (!existsSync(rulesFile)) continue;\n let data: any;\n try { data = JSON.parse(readFileSync(rulesFile, 'utf-8')); } catch { continue; }\n out[scenarioId] = {\n builtin_safe_action_types: {\n category_enabled: true,\n category_desc: '场景完全安全操作白名单(场景通常不使用)',\n rules: [],\n },\n builtin_safe_skills: {\n category_enabled: true,\n category_desc: '场景信任的内置 Skill(场景通常不使用)',\n rules: [],\n },\n extra_command_patterns: {\n category_enabled: true,\n category_desc: '场景专属危险命令正则(L1 末尾追加)',\n rules: (data.extra_command_patterns || []).map((p: any) =>\n ({ ...p, enabled: true, builtin: true })),\n },\n extra_injection_keywords: {\n category_enabled: true,\n category_desc: '场景专属注入关键词(L1 末尾追加)',\n rules: (data.extra_injection_keywords || []).map((k: any) =>\n ({ ...k, enabled: true, builtin: true })),\n },\n extra_sensitive_paths: {\n category_enabled: true,\n category_desc: '场景专属敏感路径(L1 末尾追加)',\n rules: (data.extra_sensitive_paths || []).map((sp: any) =>\n ({ ...sp, enabled: true, builtin: true })),\n },\n };\n }\n return out;\n}\n\nfunction _agentRulesToDefaults(): Record<string, Record<string, Category>> {\n const out: Record<string, Record<string, Category>> = {};\n const agentsDir = existsSync(_AGENTS_DIR_PROD) ? _AGENTS_DIR_PROD\n : existsSync(_AGENTS_DIR_DEV) ? _AGENTS_DIR_DEV : _AGENTS_DIR_PROD;\n if (!existsSync(agentsDir)) return out;\n let entries: string[];\n try {\n entries = readdirSync(agentsDir, { withFileTypes: true })\n .filter(d => d.isDirectory()).map(d => d.name);\n } catch {\n return out;\n }\n for (const agentId of entries) {\n const rulesFile = join(agentsDir, agentId, 'rules.json');\n if (!existsSync(rulesFile)) continue;\n let data: any;\n try { data = JSON.parse(readFileSync(rulesFile, 'utf-8')); } catch { continue; }\n out[agentId] = {\n builtin_safe_action_types: {\n category_enabled: true,\n category_desc: 'agent 完全安全操作白名单(前缀尾随 - 或精确名,命中跳 L2+L3)',\n rules: (data.builtin_safe_action_types || []).map((v: string) =>\n ({ value: v, enabled: true, builtin: true })),\n },\n builtin_safe_skills: {\n category_enabled: true,\n category_desc: 'agent 信任的内置 Skill(命中跳 L2+L3)',\n rules: (data.builtin_safe_skills || []).map((v: string) =>\n ({ value: v, enabled: true, builtin: true })),\n },\n extra_command_patterns: {\n category_enabled: true,\n category_desc: 'agent 专属危险命令正则(L1 末尾追加)',\n rules: (data.extra_command_patterns || []).map((p: any) =>\n ({ ...p, enabled: true, builtin: true })),\n },\n extra_injection_keywords: {\n category_enabled: true,\n category_desc: 'agent 专属注入关键词(L1 末尾追加)',\n rules: (data.extra_injection_keywords || []).map((k: any) =>\n ({ ...k, enabled: true, builtin: true })),\n },\n extra_sensitive_paths: {\n category_enabled: true,\n category_desc: 'agent 专属敏感路径(L1 末尾追加)',\n rules: (data.extra_sensitive_paths || []).map((sp: any) =>\n ({ ...sp, enabled: true, builtin: true })),\n },\n };\n }\n return out;\n}\n\n/** 从 TS 常量生成 runtime 默认结构(出厂种子)。TS 不走 profile,直接从常量。 */\nexport function generateSourceDefaults(): RuntimeConfig {\n return {\n version: 1,\n layers: { L1_heuristic: true, L2_logic_rules: true, L3_llm_analysis: true },\n L1_rules: {\n dangerous_commands: {\n category_enabled: true,\n category_desc: '危险命令检测(递归删除、全权限设置、提权执行等)',\n rules: _l1CommandPatternsToRules(),\n },\n injection_detection: {\n category_enabled: true,\n category_desc: 'Prompt 注入攻击检测',\n rules: _l1InjectionKeywordsToRules(),\n },\n sensitive_path_access: {\n category_enabled: true,\n category_desc: '敏感路径访问检测(deny_both/deny_read/deny_write)',\n rules: _l2SensitivePathsToRules(),\n },\n user_custom: { category_enabled: true, category_desc: '用户自定义命令规则', rules: [] },\n },\n L2_rules: {\n intent_consistency: {\n category_enabled: true,\n category_desc: '意图一致性检测',\n rules: _l2IntentPatternsToRules(),\n },\n password_modify_consent: {\n category_enabled: true,\n category_desc: '非交互式密码修改授权检测',\n rules: _l2PasswordPatternsToRules(),\n },\n user_deletion_consent: {\n category_enabled: true,\n category_desc: '用户/组删除操作授权检测',\n rules: _l2UserDeletionPatternsToRules(),\n },\n read_before_write: { category_enabled: true, category_desc: 'read_before_write 安全原则检测', rules: [] },\n user_custom: { category_enabled: true, category_desc: '用户自定义 L2 逻辑规则', rules: [] },\n },\n L3_skills: _l3SkillsToRules(),\n agent_rules: _agentRulesToDefaults(),\n scenario_rules: _scenarioRulesToDefaults(),\n };\n}\n\n// ==================== Merge (preserve user toggles) ====================\n\n/** 规则内容指纹(跨 id 变更识别同一规则)。 */\n/**\n * 正则 pattern 规范化,用于计算规则指纹。\n *\n * Python 与 TS 生成规则时对 `/` 的转义不一致:TS 用 RegExp.source(`/` 转义为 `\\/`),\n * Python 直接存 `/`。这导致同一规则在两端生成 pattern 字符串不同 → 指纹不同 →\n * 双端 merge 时互相把对方标记 source_removed 而禁用(L1 启用数不一致)。\n *\n * 这里把 `\\/` 规范化为 `/`,使两端 pattern 指纹一致。只处理 `/` 转义,不动其他正则转义。\n */\nfunction normalizePatternForFingerprint(pattern: string): string {\n return pattern.replace(/\\\\\\//g, '/');\n}\n\nfunction _ruleFingerprint(rule: Partial<Rule>): string {\n if ((rule.intent_keywords && rule.intent_keywords.length) || (rule.dangerous_actions && rule.dangerous_actions.length)) {\n return JSON.stringify([\n [...(rule.intent_keywords || [])].sort(),\n [...(rule.dangerous_actions || [])].sort(),\n ]);\n }\n if (rule.path) return JSON.stringify([normalizePatternForFingerprint(rule.path)]);\n if (rule.pattern) return JSON.stringify([normalizePatternForFingerprint(rule.pattern)]);\n if (rule.keyword) return JSON.stringify([rule.keyword, rule.lang || '']);\n // builtin_safe_action_types / builtin_safe_skills 项用 value 字段\n if (rule.value) return JSON.stringify([rule.value]);\n return JSON.stringify([rule.id || '']);\n}\n\n/** 合并 L1/L2 分类与规则(保留用户 enabled/skip_l3/deny_mode,补入新 builtin,标记删除)。 */\nfunction _mergeRuleCategories(userCfg: RuntimeConfig, srcDefaults: RuntimeConfig, layerKey: 'L1_rules' | 'L2_rules'): void {\n const userLayer = (userCfg[layerKey] || (userCfg[layerKey] = {})) as Record<string, Category>;\n const srcLayer = srcDefaults[layerKey] || {};\n for (const [catName, srcCat] of Object.entries(srcLayer)) {\n if (!(catName in userLayer)) {\n userLayer[catName] = srcCat;\n continue;\n }\n const userCat: Category = userLayer[catName];\n if (userCat.category_desc === undefined) userCat.category_desc = srcCat.category_desc || '';\n if (userCat.category_enabled === undefined) userCat.category_enabled = srcCat.category_enabled ?? true;\n const srcRules = srcCat.rules || [];\n const userRules = (userCat.rules || (userCat.rules = []));\n const userByFp = new Map<string, Rule>();\n for (const r of userRules) userByFp.set(_ruleFingerprint(r), r);\n const srcFps = new Set<string>();\n for (const srcR of srcRules) {\n const fp = _ruleFingerprint(srcR);\n srcFps.add(fp);\n if (userByFp.has(fp)) {\n const existing = userByFp.get(fp)!;\n const userEnabled = existing.enabled;\n const userSkipL3 = existing.skip_l3_on_disabled;\n const userDenyMode = existing.deny_mode;\n const userSourceDeny = existing.source_deny_mode;\n Object.keys(existing).forEach(k => delete (existing as any)[k]);\n Object.assign(existing, srcR);\n existing.enabled = userEnabled;\n if (userSkipL3 !== undefined) existing.skip_l3_on_disabled = userSkipL3;\n if (userDenyMode && userSourceDeny && userDenyMode !== userSourceDeny) {\n existing.deny_mode = userDenyMode;\n }\n if (existing.deny_mode) _syncDenyModeFields(existing);\n } else {\n const newR: Rule = { ...srcR, enabled: true };\n userRules.push(newR);\n }\n }\n for (const r of userRules) {\n // builtin 且指纹不在 src 集合 → 源码已删除该规则\n if (r.builtin && !srcFps.has(_ruleFingerprint(r))) {\n r.source_removed = true;\n r.enabled = false;\n }\n }\n if (catName === 'sensitive_path_access') {\n for (const r of userRules) {\n if (!r.deny_mode) r.deny_mode = _deriveDenyMode(r);\n _syncDenyModeFields(r);\n }\n }\n }\n // 清理源码已移除的类目:保留 user_custom(用户自定义壳),删除其余不在 src 的类目\n // (如本次重构删除的 dangerous_patterns / lateral_movement,老配置落盘仍残留)。\n for (const catName of Object.keys(userLayer)) {\n if (catName === 'user_custom') continue;\n if (!(catName in srcLayer)) delete userLayer[catName];\n }\n}\n\n/** 合并 L3_skills 分类。新分类整体加入;已有分类补全元字段 + 追加新 builtin skill。 */\nfunction _mergeSkillCategories(userCfg: RuntimeConfig, srcDefaults: RuntimeConfig, layerKey: 'L3_skills'): void {\n const userLayer = (userCfg[layerKey] || (userCfg[layerKey] = {})) as Record<string, Category>;\n const srcLayer = srcDefaults[layerKey] || {};\n for (const [catName, srcCat] of Object.entries(srcLayer)) {\n if (!(catName in userLayer)) {\n userLayer[catName] = srcCat;\n continue;\n }\n const userCat: Category = userLayer[catName];\n if (userCat.category_desc === undefined) userCat.category_desc = srcCat.category_desc || '';\n if (userCat.category_enabled === undefined) userCat.category_enabled = srcCat.category_enabled ?? true;\n const userSkills = (userCat.skills || (userCat.skills = []));\n const existingIds = new Set(userSkills.map(s => s.id));\n for (const srcS of (srcCat.skills || [])) {\n if (!existingIds.has(srcS.id)) userSkills.push({ ...srcS });\n }\n }\n}\n\n/** 合并 agent_rules 分区(按 agent_id 分区,每个 agent 内复用类别合并逻辑)。\n * 新出厂 agent → 整体加入;已有 agent → 每类别走 _mergeRuleCategories 同套\n * (指纹去重 + 保留 enabled + 新 builtin 追加 + 删除标记 source_removed)。 */\nfunction _mergeAgentRules(userCfg: RuntimeConfig, srcDefaults: RuntimeConfig, partition: 'agent_rules' | 'scenario_rules' = 'agent_rules'): void {\n const userAgent = (userCfg[partition] || (userCfg[partition] = {})) as Record<string, Record<string, Category>>;\n const srcAgent = srcDefaults[partition] || {};\n for (const [agentId, srcCats] of Object.entries(srcAgent)) {\n if (!(agentId in userAgent)) {\n userAgent[agentId] = JSON.parse(JSON.stringify(srcCats));\n continue;\n }\n const userCats = userAgent[agentId];\n for (const [catName, srcCat] of Object.entries(srcCats)) {\n if (!(catName in userCats)) {\n userCats[catName] = JSON.parse(JSON.stringify(srcCat));\n continue;\n }\n const userCat: Category = userCats[catName];\n if (userCat.category_desc === undefined) userCat.category_desc = srcCat.category_desc || '';\n if (userCat.category_enabled === undefined) userCat.category_enabled = srcCat.category_enabled ?? true;\n const srcRules = srcCat.rules || [];\n const userRules = (userCat.rules || (userCat.rules = []));\n const userByFp = new Map<string, Rule>();\n for (const r of userRules) userByFp.set(_ruleFingerprint(r), r);\n const srcFps = new Set<string>();\n for (const srcR of srcRules) {\n const fp = _ruleFingerprint(srcR);\n srcFps.add(fp);\n if (userByFp.has(fp)) {\n const existing = userByFp.get(fp)!;\n const userEnabled = existing.enabled;\n Object.keys(existing).forEach(k => delete (existing as any)[k]);\n Object.assign(existing, srcR);\n existing.enabled = userEnabled;\n } else {\n userRules.push({ ...srcR, enabled: true });\n }\n }\n for (const r of userRules) {\n if (r.builtin && !srcFps.has(_ruleFingerprint(r))) {\n r.source_removed = true;\n r.enabled = false;\n }\n }\n }\n }\n}\n\n/** 合并用户配置与源码默认值。保留用户开关;新增 builtin 补入;源码删除的标记。 */\nexport function mergeConfig(userCfg: Partial<RuntimeConfig>, srcDefaults: RuntimeConfig): RuntimeConfig {\n const cfg = userCfg as RuntimeConfig;\n if (cfg.version === undefined) cfg.version = srcDefaults.version || 1;\n if (!cfg.layers) cfg.layers = {} as RuntimeConfig['layers'];\n for (const [layerKey, defaultVal] of Object.entries(srcDefaults.layers)) {\n if (!(layerKey in cfg.layers)) (cfg.layers as any)[layerKey] = defaultVal;\n }\n // 跨层迁移:敏感路径已从 L2 重分类到 L1。老配置 sensitive_path_access 还在\n // L2_rules 下,搬到 L1_rules(保留用户 enabled/deny_mode/自定义项),L2 删除该分类。\n // 注:dangerous_patterns / lateral_movement 检测是硬编码子检测器,不读 runtime\n // config rules,故老配置 L2 里这两类的 rules 不迁移(默认种子已删除该类目)。\n _migrateCategoriesAcrossLayers(cfg, 'L2_rules', 'L1_rules',\n ['sensitive_path_access']);\n _mergeRuleCategories(cfg, srcDefaults, 'L1_rules');\n _mergeRuleCategories(cfg, srcDefaults, 'L2_rules');\n _mergeSkillCategories(cfg, srcDefaults, 'L3_skills');\n _mergeAgentRules(cfg, srcDefaults);\n _mergeAgentRules(cfg, srcDefaults, 'scenario_rules');\n return cfg;\n}\n\n/** 把指定分类从 srcLayer 搬到 dstLayer(保留分类内全部内容,按指纹去重合并)。 */\nfunction _migrateCategoriesAcrossLayers(cfg: RuntimeConfig, srcLayer: 'L1_rules' | 'L2_rules', dstLayer: 'L1_rules' | 'L2_rules', catNames: string[]): void {\n const src = (cfg as any)[srcLayer] || {};\n const dst: any = cfg[dstLayer] || (cfg[dstLayer] = {} as RuntimeConfig['L1_rules']);\n for (const catName of catNames) {\n if (!(catName in src)) continue;\n const srcCat = src[catName];\n if (!dst[catName]) {\n dst[catName] = { category_enabled: true, category_desc: '', rules: [] };\n }\n const dstCat = dst[catName];\n if (!dstCat.category_desc && srcCat.category_desc) dstCat.category_desc = srcCat.category_desc;\n if (dstCat.category_enabled === undefined) dstCat.category_enabled = srcCat.category_enabled;\n // 合并 rules:dst 已有的按指纹保留,src 独有的追加\n if (srcCat.rules && srcCat.rules.length > 0) {\n const dstFps = new Set((dstCat.rules || []).map((r: any) => _ruleFingerprint(r)));\n for (const r of srcCat.rules) {\n const fp = _ruleFingerprint(r);\n if (!dstFps.has(fp)) {\n (dstCat.rules = dstCat.rules || []).push(r);\n dstFps.add(fp);\n }\n }\n }\n delete src[catName];\n }\n}\n\n// ==================== Query 补齐 ====================\n\nexport function getEnabledL1InjectionKeywords(runtime: RuntimeConfig): { keyword: string; risk_level: string; lang: string }[] {\n const cat = runtime.L1_rules?.injection_detection || { category_enabled: true, rules: [] };\n return filterEnabledRules(cat.rules || [], cat.category_enabled).map(r => ({\n keyword: r.keyword || '', risk_level: r.risk_level || '', lang: r.lang || 'en',\n }));\n}\n\nexport function getEnabledL2IntentPatterns(runtime: RuntimeConfig): { intent_keywords: string[]; dangerous_actions: string[]; reason: string }[] {\n const cat = runtime.L2_rules?.intent_consistency || { category_enabled: true, rules: [] };\n return filterEnabledRules(cat.rules || [], cat.category_enabled).map(r => ({\n intent_keywords: r.intent_keywords || [], dangerous_actions: r.dangerous_actions || [], reason: r.reason || '',\n }));\n}\n\nexport function getEnabledL2PasswordPatterns(runtime: RuntimeConfig): string[] {\n const cat = runtime.L2_rules?.password_modify_consent || { category_enabled: true, rules: [] };\n return filterEnabledRules(cat.rules || [], cat.category_enabled).map(r => r.pattern || '');\n}\n\nexport function getEnabledL2UserDeletionPatterns(runtime: RuntimeConfig): string[] {\n const cat = runtime.L2_rules?.user_deletion_consent || { category_enabled: true, rules: [] };\n return filterEnabledRules(cat.rules || [], cat.category_enabled).map(r => r.pattern || '');\n}\n\nexport function isL2CategoryEnabled(runtime: RuntimeConfig, categoryKey: string): boolean {\n const cat = runtime.L2_rules?.[categoryKey as keyof typeof runtime.L2_rules] as Category | undefined;\n return cat?.category_enabled ?? true;\n}\n\n/** 所有被禁用的 skill id(整分类禁用→该分类所有 skill,或单条 enabled=false) */\nexport function getDisabledSkillIds(runtime: RuntimeConfig): Set<string> {\n const disabled = new Set<string>();\n for (const catData of Object.values(runtime.L3_skills || {})) {\n if (!catData.category_enabled) {\n for (const s of (catData.skills || [])) disabled.add(s.id);\n } else {\n for (const s of (catData.skills || [])) {\n if (s.enabled === false) disabled.add(s.id);\n }\n }\n }\n return disabled;\n}\n\n// ==================== _or_default 回退系列 ====================\n// runtime 规则非空→用 runtime;为空且文件不存在→回退 source defaults;\n// 为空但文件存在(用户主动禁用)→返回空。与 py 语义对齐。\n\nexport function getEnabledL1CommandPatternsOrDefault(runtime: RuntimeConfig): Rule[] {\n const enabled = getEnabledL1CommandPatterns(runtime) as unknown as Rule[];\n if (enabled.length) return enabled;\n if (!hasRuntimeConfig()) return _l1CommandPatternsToRules();\n return [];\n}\nexport function getEnabledL1InjectionKeywordsOrDefault(runtime: RuntimeConfig): Rule[] {\n const enabled = getEnabledL1InjectionKeywords(runtime) as unknown as Rule[];\n if (enabled.length) return enabled;\n if (!hasRuntimeConfig()) return _l1InjectionKeywordsToRules();\n return [];\n}\nexport function getEnabledL2SensitivePathsOrDefault(runtime: RuntimeConfig): Rule[] {\n const enabled = getEnabledL2SensitivePaths(runtime) as unknown as Rule[];\n if (enabled.length) return enabled;\n if (!hasRuntimeConfig()) return _l2SensitivePathsToRules();\n return [];\n}\nexport function getEnabledL2IntentPatternsOrDefault(runtime: RuntimeConfig): Rule[] {\n const enabled = getEnabledL2IntentPatterns(runtime) as unknown as Rule[];\n if (enabled.length) return enabled;\n if (!hasRuntimeConfig()) return _l2IntentPatternsToRules();\n return [];\n}\nexport function getEnabledL2PasswordPatternsOrDefault(runtime: RuntimeConfig): string[] {\n const enabled = getEnabledL2PasswordPatterns(runtime);\n if (enabled.length) return enabled;\n if (!hasRuntimeConfig()) {\n return PASSWORD_MODIFY_PATTERNS.map((p) => p.source);\n }\n return [];\n}\nexport function getEnabledL2UserDeletionPatternsOrDefault(runtime: RuntimeConfig): string[] {\n const enabled = getEnabledL2UserDeletionPatterns(runtime);\n if (enabled.length) return enabled;\n if (!hasRuntimeConfig()) {\n return USER_DELETION_PATTERNS.map((p) => p.source);\n }\n return [];\n}\n\n// ==================== CRUD / update ====================\n\nconst SKILL_ID_RE = /^[A-Za-z0-9_-]+$/;\nfunction _validateSkillId(skillId: string): void {\n if (!skillId || !SKILL_ID_RE.test(skillId)) {\n throw new Error(`skill_id '${skillId}' 不合法:只允许字母、数字、下划线和连字符`);\n }\n}\n\nexport function updateLayerEnabled(layerKey: string, enabled: boolean): RuntimeConfig {\n const runtime = loadRuntimeConfig();\n (runtime.layers as any)[layerKey] = enabled;\n saveRuntimeConfig(runtime);\n return runtime;\n}\n\nexport function updateRuleEnabled(layer: 'L1_rules' | 'L2_rules', category: string, ruleId: string, enabled: boolean): RuntimeConfig {\n const runtime = loadRuntimeConfig();\n for (const r of (runtime[layer]?.[category]?.rules || [])) {\n if (r.id === ruleId) { r.enabled = enabled; break; }\n }\n saveRuntimeConfig(runtime);\n return runtime;\n}\n\nexport function updateRuleDenyMode(layer: 'L1_rules' | 'L2_rules', category: string, ruleId: string, denyMode: string): RuntimeConfig {\n const runtime = loadRuntimeConfig();\n for (const r of (runtime[layer]?.[category]?.rules || [])) {\n if (r.id === ruleId) { r.deny_mode = denyMode; _syncDenyModeFields(r); break; }\n }\n saveRuntimeConfig(runtime);\n return runtime;\n}\n\nexport function updateRuleSkipL3(layer: 'L1_rules' | 'L2_rules', category: string, ruleId: string, skipL3: boolean): RuntimeConfig {\n const runtime = loadRuntimeConfig();\n for (const r of (runtime[layer]?.[category]?.rules || [])) {\n if (r.id === ruleId) { r.skip_l3_on_disabled = skipL3; break; }\n }\n saveRuntimeConfig(runtime);\n return runtime;\n}\n\nexport function updateCategoryEnabled(layer: 'L1_rules' | 'L2_rules', category: string, enabled: boolean): RuntimeConfig {\n const runtime = loadRuntimeConfig();\n const cat = runtime[layer]?.[category];\n if (cat) cat.category_enabled = enabled;\n saveRuntimeConfig(runtime);\n return runtime;\n}\n\nexport function addCustomRule(layer: 'L1_rules' | 'L2_rules', category: string, rule: Partial<Rule>): RuntimeConfig {\n const runtime = loadRuntimeConfig();\n const layerObj = runtime[layer] || (runtime[layer] = {} as Record<string, Category>);\n const cat = layerObj[category] || (layerObj[category] = { category_enabled: true, category_desc: '', rules: [] });\n const rules = cat.rules || (cat.rules = []);\n const newRule: Rule = { ...rule, builtin: false, enabled: true } as Rule;\n if (!newRule.id) {\n newRule.id = `custom_${Date.now()}_${_slugify(JSON.stringify(rule).slice(0, 30))}`;\n }\n if (newRule.deny_mode) _syncDenyModeFields(newRule);\n rules.push(newRule);\n saveRuntimeConfig(runtime);\n return runtime;\n}\n\nexport function deleteCustomRule(layer: 'L1_rules' | 'L2_rules', category: string, ruleId: string): RuntimeConfig | null {\n // 允许删:用户自定义(builtin=false)+ 已移除的(builtin=true 但 source_removed=true)。\n // 活跃 builtin 规则不允许删(用 enabled 开关)。\n const runtime = loadRuntimeConfig();\n const rules = runtime[layer]?.[category]?.rules || [];\n const idx = rules.findIndex(r => r.id === ruleId);\n if (idx >= 0) {\n const r = rules[idx];\n if (r.builtin && !r.source_removed) return null; // 活跃 builtin 不允许删\n rules.splice(idx, 1);\n saveRuntimeConfig(runtime);\n }\n return runtime;\n}\n\nexport function addCustomSkill(skillId: string, category: string, keywords: string[], content: string): RuntimeConfig {\n _validateSkillId(skillId);\n const runtime = loadRuntimeConfig();\n const skillsDir = join(RUNTIME_CONFIG_DIR, 'agent_moss_skills');\n try { mkdirSync(skillsDir, { recursive: true }); } catch { /* 已存在 */ }\n writeFileSync(join(skillsDir, `${skillId}.md`), content, 'utf-8');\n const l3 = runtime.L3_skills || (runtime.L3_skills = {});\n const cat = l3[category] || (l3[category] = { category_enabled: true, category_desc: '', skills: [] });\n (cat.skills || (cat.skills = [])).push({ id: skillId, keywords, enabled: true, builtin: false });\n saveRuntimeConfig(runtime);\n return runtime;\n}\n\nexport function deleteCustomSkill(skillId: string, category: string): RuntimeConfig | null {\n _validateSkillId(skillId);\n const runtime = loadRuntimeConfig();\n const skills = runtime.L3_skills?.[category]?.skills || [];\n const idx = skills.findIndex(s => s.id === skillId);\n if (idx >= 0) {\n if (skills[idx].builtin) return null;\n skills.splice(idx, 1);\n const skillPath = join(RUNTIME_CONFIG_DIR, 'agent_moss_skills', `${skillId}.md`);\n try { if (existsSync(skillPath)) unlinkSync(skillPath); } catch { /* ignore */ }\n saveRuntimeConfig(runtime);\n }\n return runtime;\n}\n\nexport function updateSkillEnabled(skillId: string, enabled: boolean): RuntimeConfig {\n const runtime = loadRuntimeConfig();\n for (const catData of Object.values(runtime.L3_skills || {})) {\n for (const s of (catData.skills || [])) {\n if (s.id === skillId) { s.enabled = enabled; break; }\n }\n }\n saveRuntimeConfig(runtime);\n return runtime;\n}\n\nexport function updateSkillCategoryEnabled(category: string, enabled: boolean): RuntimeConfig {\n const runtime = loadRuntimeConfig();\n const cat = runtime.L3_skills?.[category];\n if (cat) cat.category_enabled = enabled;\n saveRuntimeConfig(runtime);\n return runtime;\n}\n\nexport function getProfileOrDetect(): null {\n // TS 不走 OSProfile(规则集硬编码常量),此函数仅为 py API 对齐保留,返回 null。\n return null;\n}\n\n// ==================== agent 定制规则(runtime_config 统一治理)====================\n\nexport function getAgentRules(runtime: RuntimeConfig): Record<string, Record<string, Category>> {\n return runtime.agent_rules || {};\n}\n\nfunction _agentCategoryEnabledRules(cat: Category | undefined): Rule[] {\n if (!cat || cat.category_enabled === false) return [];\n return (cat.rules || []).filter(r => r.enabled !== false);\n}\n\n/** 从 runtime_config 的 agent_rules[agent_id] 构造 AgentExtensions(应用 enabled 过滤)。\n * 供 getAgentExtensions 在 hasRuntimeConfig() 时调用。无该 agent 分区返回 null。 */\nexport function getEnabledAgentExtensions(runtime: RuntimeConfig, agentId: string): AgentExtensions | null {\n const agentData = runtime.agent_rules?.[agentId];\n if (!agentData) return null;\n const safeAction = _agentCategoryEnabledRules(agentData.builtin_safe_action_types);\n const safeSkills = _agentCategoryEnabledRules(agentData.builtin_safe_skills);\n const cmdPatterns = _agentCategoryEnabledRules(agentData.extra_command_patterns)\n .filter(r => r.pattern).map(r => ({\n pattern: r.pattern!, risk_level: r.risk_level || '',\n risk_type: r.risk_type || '', reason: r.reason || '',\n }));\n const injKeywords = _agentCategoryEnabledRules(agentData.extra_injection_keywords)\n .filter(r => r.keyword).map(r => ({\n keyword: r.keyword!, risk_level: r.risk_level || '', lang: r.lang || 'en',\n }));\n const sensitivePaths = _agentCategoryEnabledRules(agentData.extra_sensitive_paths)\n .filter(r => r.path).map(r => ({\n path: r.path!, risk_level: r.risk_level || '', desc: r.desc || '',\n credential: r.credential, read_only: r.read_only, deny_mode: r.deny_mode,\n }));\n return {\n agent_id: agentId,\n description: '',\n extra_command_patterns: cmdPatterns,\n extra_injection_keywords: injKeywords,\n extra_sensitive_paths: sensitivePaths,\n builtin_safe_skills: safeSkills.filter(r => r.value).map(r => r.value!),\n builtin_safe_action_types: safeAction.filter(r => r.value).map(r => r.value!),\n extra_skills: [],\n };\n}\n\nexport function updateAgentRuleEnabled(agentId: string, category: string, ruleFp: Partial<Rule>, enabled: boolean): RuntimeConfig {\n const runtime = loadRuntimeConfig();\n const cat = runtime.agent_rules?.[agentId]?.[category];\n if (cat) {\n const targetFp = _ruleFingerprint(ruleFp);\n for (const r of (cat.rules || [])) {\n if (_ruleFingerprint(r) === targetFp) { r.enabled = enabled; break; }\n }\n }\n saveRuntimeConfig(runtime);\n return runtime;\n}\n\nexport function addAgentRule(agentId: string, category: string, rule: Record<string, unknown>): RuntimeConfig {\n const runtime = loadRuntimeConfig();\n if (!runtime.agent_rules) runtime.agent_rules = {};\n if (!runtime.agent_rules[agentId]) runtime.agent_rules[agentId] = {};\n const cats = runtime.agent_rules[agentId];\n if (!cats[category]) cats[category] = { category_enabled: true, category_desc: '', rules: [] };\n (cats[category].rules || (cats[category].rules = [])).push({ ...rule, enabled: true, builtin: false } as Rule);\n saveRuntimeConfig(runtime);\n return runtime;\n}\n\nexport function deleteAgentRule(agentId: string, category: string, ruleFp: Partial<Rule>): RuntimeConfig {\n const runtime = loadRuntimeConfig();\n const cat = runtime.agent_rules?.[agentId]?.[category];\n if (cat) {\n const targetFp = _ruleFingerprint(ruleFp);\n cat.rules = (cat.rules || []).filter(r => _ruleFingerprint(r) !== targetFp);\n }\n saveRuntimeConfig(runtime);\n return runtime;\n}\n\n/** 切换某 agent 某类别的 category_enabled(整类开关,与通用规则分类开关同范式)。 */\nexport function updateAgentCategoryEnabled(agentId: string, category: string, enabled: boolean): RuntimeConfig {\n const runtime = loadRuntimeConfig();\n const cat = runtime.agent_rules?.[agentId]?.[category];\n if (cat) cat.category_enabled = enabled;\n saveRuntimeConfig(runtime);\n return runtime;\n}\n\n// ==================== 场景定制规则(scenario_rules 分区,与 agent_rules 同构)====================\n\nexport function getScenarioRules(runtime: RuntimeConfig): Record<string, Record<string, Category>> {\n return runtime.scenario_rules || {};\n}\n\n/** 从 runtime_config 的 scenario_rules[scenario_id] 构造 AgentExtensions(应用 enabled 过滤)。\n * 供 getScenarioExtensions 在 hasRuntimeConfig() 时调用。无该场景分区返回 null。 */\nexport function getEnabledScenarioExtensions(runtime: RuntimeConfig, scenarioId: string): AgentExtensions | null {\n const scenData = runtime.scenario_rules?.[scenarioId];\n if (!scenData) return null;\n const cmdPatterns = _agentCategoryEnabledRules(scenData.extra_command_patterns)\n .filter(r => r.pattern).map(r => ({\n pattern: r.pattern!, risk_level: r.risk_level || '',\n risk_type: r.risk_type || '', reason: r.reason || '',\n }));\n const injKeywords = _agentCategoryEnabledRules(scenData.extra_injection_keywords)\n .filter(r => r.keyword).map(r => ({\n keyword: r.keyword!, risk_level: r.risk_level || '', lang: r.lang || 'en',\n }));\n const sensitivePaths = _agentCategoryEnabledRules(scenData.extra_sensitive_paths)\n .filter(r => r.path).map(r => ({\n path: r.path!, risk_level: r.risk_level || '', desc: r.desc || '',\n credential: r.credential, read_only: r.read_only, deny_mode: r.deny_mode,\n }));\n return {\n agent_id: scenarioId,\n description: '',\n extra_command_patterns: cmdPatterns,\n extra_injection_keywords: injKeywords,\n extra_sensitive_paths: sensitivePaths,\n builtin_safe_skills: [],\n builtin_safe_action_types: [],\n extra_skills: [],\n };\n}\n\nexport function updateScenarioRuleEnabled(scenarioId: string, category: string, ruleFp: Partial<Rule>, enabled: boolean): RuntimeConfig {\n const runtime = loadRuntimeConfig();\n const cat = runtime.scenario_rules?.[scenarioId]?.[category];\n if (cat) {\n const targetFp = _ruleFingerprint(ruleFp);\n for (const r of (cat.rules || [])) {\n if (_ruleFingerprint(r) === targetFp) { r.enabled = enabled; break; }\n }\n }\n saveRuntimeConfig(runtime);\n return runtime;\n}\n\nexport function addScenarioRule(scenarioId: string, category: string, rule: Record<string, unknown>): RuntimeConfig {\n const runtime = loadRuntimeConfig();\n if (!runtime.scenario_rules) runtime.scenario_rules = {};\n if (!runtime.scenario_rules[scenarioId]) runtime.scenario_rules[scenarioId] = {};\n const cats = runtime.scenario_rules[scenarioId];\n if (!cats[category]) cats[category] = { category_enabled: true, category_desc: '', rules: [] };\n (cats[category].rules || (cats[category].rules = [])).push({ ...rule, enabled: true, builtin: false } as Rule);\n saveRuntimeConfig(runtime);\n return runtime;\n}\n\nexport function deleteScenarioRule(scenarioId: string, category: string, ruleFp: Partial<Rule>): RuntimeConfig {\n const runtime = loadRuntimeConfig();\n const cat = runtime.scenario_rules?.[scenarioId]?.[category];\n if (cat) {\n const targetFp = _ruleFingerprint(ruleFp);\n cat.rules = (cat.rules || []).filter(r => _ruleFingerprint(r) !== targetFp);\n }\n saveRuntimeConfig(runtime);\n return runtime;\n}\n\n/** 切换某场景某类别的 category_enabled(整类开关,与通用规则分类开关同范式)。 */\nexport function updateScenarioCategoryEnabled(scenarioId: string, category: string, enabled: boolean): RuntimeConfig {\n const runtime = loadRuntimeConfig();\n const cat = runtime.scenario_rules?.[scenarioId]?.[category];\n if (cat) cat.category_enabled = enabled;\n saveRuntimeConfig(runtime);\n return runtime;\n}\n","/**\n * 三方 agent 定制化注册中心 — TypeScript 加载器\n *\n * 按 `agentId` 加载该 agent 的专属规则集(JSON 单一事实源)。\n * 规则文件位置:`agent_moss/agents/<agentId>/rules.json`\n *\n * 与 Python `agent_moss/agents/__init__.py:get_agent_extensions` 一一对应。\n * 两端共享同一份 rules.json。\n *\n * 路径解析:\n * - prod(dist/cli.js):copy-assets.cjs 复制 rules.json 到 dist/agents/<id>/rules.json\n * - dev(tsx src/cli.ts):从 ts/src/agents/ 出发,回退到 ../../../agent_moss/agents\n *\n * 缓存:首次加载后缓存在 Map 中,clearAgentExtensionsCache 清空(测试用)。\n */\n\nimport { readFileSync, existsSync } from 'fs';\nimport { resolve, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport type { AgentExtensions } from './types';\n\nexport type { AgentExtensions } from './types';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n// 优先用 dist 内联目录(prod,copy-assets.cjs 复制后);\n// 缺失时回退到仓库根 agent_moss/agents(dev)。\n// 注意:从 ts/src/agents/ 出发,仓库根 agent_moss/agents 在 ../../../agent_moss/agents。\nconst AGENTS_DIR_PROD = resolve(__dirname, 'agents');\nconst AGENTS_DIR_DEV_FALLBACK = resolve(__dirname, '../../../agent_moss/agents');\n\nconst cache = new Map<string, AgentExtensions | null>();\n\nexport function resolveAgentsDir(): string {\n if (existsSync(AGENTS_DIR_PROD)) return AGENTS_DIR_PROD;\n if (existsSync(AGENTS_DIR_DEV_FALLBACK)) return AGENTS_DIR_DEV_FALLBACK;\n return AGENTS_DIR_PROD; // 不存在时也返回 prod 路径,让后续 existsSync 检查返回 false\n}\n\n/**\n * 按 agentId 加载该 agent 的专属规则集。\n *\n * @param agentId 调用方 agent 标识,如 \"xiaoo\" / \"opencode\" / \"opendesk\"。\n * 空字符串返回 null(通用模式)。\n * @returns AgentExtensions 实例,或 null(无 agent 专属规则 / rules.json 不存在 / 解析失败)\n */\nexport function getAgentExtensions(agentId: string): AgentExtensions | null {\n if (!agentId) return null;\n if (cache.has(agentId)) return cache.get(agentId) ?? null;\n\n let ext: AgentExtensions | null = null;\n // 统一存储:优先读 runtime_config 的 agent_rules 分区(用户可在 console\n // 查看/编辑/禁用/新增,享受与通用规则一致的合并升级)。回退 rules.json\n // (无 runtime_config 时,如直接起服务未 seed、或旧部署)。\n try {\n const { hasRuntimeConfig, loadRuntimeConfig, getEnabledAgentExtensions } = require('../infra/runtime-config');\n if (hasRuntimeConfig()) {\n ext = getEnabledAgentExtensions(loadRuntimeConfig(), agentId);\n }\n } catch { /* runtime-config 不可用时回退 rules.json */ }\n\n if (ext === null) {\n const agentsDir = resolveAgentsDir();\n const rulesFile = resolve(agentsDir, agentId, 'rules.json');\n if (!existsSync(rulesFile)) {\n cache.set(agentId, null);\n return null;\n }\n try {\n const raw = readFileSync(rulesFile, 'utf-8');\n ext = JSON.parse(raw) as AgentExtensions;\n if (!ext.agent_id) {\n console.warn(`[AgentMoss agents] rules.json 缺少 agent_id 字段: ${rulesFile}`);\n cache.set(agentId, null);\n return null;\n }\n } catch (e) {\n console.error(`[AgentMoss agents] 加载 agent ${agentId} rules.json 失败:`, (e as Error).message);\n cache.set(agentId, null);\n return null;\n }\n }\n\n cache.set(agentId, ext);\n console.log(\n `[AgentMoss agents] 加载 agent ${agentId} 定制规则: ` +\n `${ext.extra_command_patterns?.length ?? 0} cmd patterns, ` +\n `${ext.extra_injection_keywords?.length ?? 0} injection keywords, ` +\n `${ext.extra_sensitive_paths?.length ?? 0} sensitive paths, ` +\n `${ext.builtin_safe_skills?.length ?? 0} builtin safe skills, ` +\n `${ext.builtin_safe_action_types?.length ?? 0} builtin safe action types`\n );\n return ext;\n}\n\n/**\n * 清空 agent 扩展缓存(用于测试或 rules.json 热加载)。\n */\nexport function clearAgentExtensionsCache(): void {\n cache.clear();\n}\n\n/**\n * 合并多个 AgentExtensions(如 agent 规则 + 场景规则),追加式拼接各 extra_* 列表。\n *\n * 全部为 null 时返回 null(通用模式)。非 null 时以第一个非空实例为骨架,\n * 其余实例的 extra_* / builtin_safe_* 列表依次追加在后(不覆盖)。\n * 与 Python `AgentExtensions.merge`(agent_moss/agents/base.py)一一对应。\n */\nexport function mergeAgentExtensions(...exts: (AgentExtensions | null | undefined)[]): AgentExtensions | null {\n const nonNull = exts.filter((e): e is AgentExtensions => !!e);\n if (nonNull.length === 0) return null;\n const base = nonNull[0];\n return {\n agent_id: base.agent_id,\n description: base.description,\n extra_command_patterns: nonNull.flatMap(e => e.extra_command_patterns || []),\n extra_injection_keywords: nonNull.flatMap(e => e.extra_injection_keywords || []),\n extra_sensitive_paths: nonNull.flatMap(e => e.extra_sensitive_paths || []),\n builtin_safe_skills: nonNull.flatMap(e => e.builtin_safe_skills || []),\n builtin_safe_action_types: nonNull.flatMap(e => e.builtin_safe_action_types || []),\n extra_skills: nonNull.flatMap(e => e.extra_skills || []),\n };\n}\n","/**\n * 场景定制化规则注册中心 — TypeScript 加载器\n *\n * 按 `scenarioId` 加载该场景的专属规则集(JSON 单一事实源)。\n * 规则文件位置:`agent_moss/scenarios/<scenarioId>/rules.json`\n *\n * 与 Python `agent_moss/scenarios/__init__.py:get_scenario_extensions` 一一对应。\n * 两端共享同一份 rules.json。场景规则与 agent 规则同构(都是 AgentExtensions\n * 结构:extra_command_patterns / extra_injection_keywords / extra_sensitive_paths /\n * builtin_safe_skills / builtin_safe_action_types),唯一区别是顶层 id 字段叫\n * `scenario_id` 而非 `agent_id`(解析时兼容)。\n *\n * 设计动机:agent 规则靠调用方传 `agentId`(真实 agent instance 身份)启用;\n * 场景规则是**部署级**约束(客户沙箱的目录访问边界、禁 ssh 等),没有天然调用方\n * 身份,启用判定为:\n * 1. 调用方显式传 `scenarioId`(请求级,与 agentId 并列)\n * 2. 兜底环境变量 `AGENT_MOSS_SCENARIO`(部署级,客户沙箱设一次,所有请求生效)\n * 3. 两者都空 → 通用模式(不加载场景规则)\n *\n * 路径解析:\n * - prod(dist/cli.js):copy-assets.cjs 复制 rules.json 到 dist/scenarios/<id>/rules.json\n * - dev(tsx src/cli.ts):从 ts/src/scenarios/ 出发,回退到 ../../../agent_moss/scenarios\n *\n * 缓存:首次加载后缓存在 Map 中,clearScenarioExtensionsCache 清空(测试用)。\n */\n\nimport { readFileSync, existsSync } from 'fs';\nimport { resolve, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport type { AgentExtensions } from '../agents/types';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n// 优先用 dist 内联目录(prod,copy-assets.cjs 复制后);\n// 缺失时回退到仓库根 agent_moss/scenarios(dev)。\nconst SCENARIOS_DIR_PROD = resolve(__dirname, 'scenarios');\nconst SCENARIOS_DIR_DEV_FALLBACK = resolve(__dirname, '../../../agent_moss/scenarios');\n\nconst cache = new Map<string, AgentExtensions | null>();\n\nexport function resolveScenariosDir(): string {\n if (existsSync(SCENARIOS_DIR_PROD)) return SCENARIOS_DIR_PROD;\n if (existsSync(SCENARIOS_DIR_DEV_FALLBACK)) return SCENARIOS_DIR_DEV_FALLBACK;\n return SCENARIOS_DIR_PROD; // 不存在时也返回 prod 路径,让后续 existsSync 检查返回 false\n}\n\n/**\n * 按 scenarioId 加载该场景的专属规则集。\n *\n * @param scenarioId 调用方场景标识,如 \"bank\"。空字符串返回 null(通用模式)。\n * @returns AgentExtensions 实例,或 null(无场景专属规则 / rules.json 不存在 / 解析失败)\n */\nexport function getScenarioExtensions(scenarioId: string): AgentExtensions | null {\n if (!scenarioId) return null;\n if (cache.has(scenarioId)) return cache.get(scenarioId) ?? null;\n\n let ext: AgentExtensions | null = null;\n // 统一存储:优先读 runtime_config 的 scenario_rules 分区(用户可在 console\n // 查看/编辑/禁用/新增,与 agent_rules 同构,享受与通用规则一致的合并升级)。\n // 回退 rules.json(无 runtime_config 时,如直接起服务未 seed、或旧部署)。\n try {\n const { hasRuntimeConfig, loadRuntimeConfig, getEnabledScenarioExtensions } = require('../infra/runtime-config');\n if (hasRuntimeConfig()) {\n ext = getEnabledScenarioExtensions(loadRuntimeConfig(), scenarioId);\n }\n } catch { /* runtime-config 不可用时回退 rules.json */ }\n\n if (ext === null) {\n const scenariosDir = resolveScenariosDir();\n const rulesFile = resolve(scenariosDir, scenarioId, 'rules.json');\n if (!existsSync(rulesFile)) {\n cache.set(scenarioId, null);\n return null;\n }\n try {\n const raw = readFileSync(rulesFile, 'utf-8');\n const data = JSON.parse(raw) as any;\n // 场景规则顶层 id 字段是 scenario_id(兼容缺失时回退 agent_id)\n const id = data.scenario_id || data.agent_id || '';\n if (!id) {\n console.warn(`[AgentMoss scenarios] rules.json 缺少 scenario_id 字段: ${rulesFile}`);\n cache.set(scenarioId, null);\n return null;\n }\n ext = {\n agent_id: id,\n description: data.description || '',\n extra_command_patterns: data.extra_command_patterns || [],\n extra_injection_keywords: data.extra_injection_keywords || [],\n extra_sensitive_paths: data.extra_sensitive_paths || [],\n builtin_safe_skills: data.builtin_safe_skills || [],\n builtin_safe_action_types: data.builtin_safe_action_types || [],\n extra_skills: data.extra_skills || [],\n };\n } catch (e) {\n console.error(`[AgentMoss scenarios] 加载场景 ${scenarioId} rules.json 失败:`, (e as Error).message);\n cache.set(scenarioId, null);\n return null;\n }\n }\n\n cache.set(scenarioId, ext);\n console.log(\n `[AgentMoss scenarios] 加载场景 ${scenarioId} 定制规则: ` +\n `${ext.extra_command_patterns?.length ?? 0} cmd patterns, ` +\n `${ext.extra_injection_keywords?.length ?? 0} injection keywords, ` +\n `${ext.extra_sensitive_paths?.length ?? 0} sensitive paths`\n );\n return ext;\n}\n\n/**\n * 清空场景扩展缓存(用于测试或 rules.json 热加载)。\n */\nexport function clearScenarioExtensionsCache(): void {\n cache.clear();\n}\n","import { SecurityJudgment, HeuristicResult } from './types';\nimport type { AnalysisInput } from './coordinator';\nimport { getCustomRules } from '../config';\nimport { getAgentExtensions, mergeAgentExtensions } from '../agents';\nimport { getScenarioExtensions } from '../scenarios';\nimport type { CommandPattern, InjectionKeyword } from '../agents/types';\nimport { loadL1 } from '../infra/rules-loader';\nimport {\n ROOT_SENSITIVE_PATHS,\n HOME_SENSITIVE_PATHS,\n CREDENTIAL_PATHS,\n isWriteOperation,\n} from './logic-rules';\n\n/**\n * Layer 1: Feature-matching static detection.\n * Uses regex patterns to detect dangerous commands, user-defined rules,\n * and prompt injection keywords.\n * Runs in < 1ms, no LLM cost.\n */\n\n// Prompt injection keywords (synced with Python linux.py _DEFAULT_INJECTION_KEYWORDS)\nexport const INJECTION_KEYWORDS: { keyword: string; riskLevel: string; lang: string }[] = (() => {\n // 归一化自 agent_moss/rules/l1_rules.json 的注入段(单一事实源,与 Python 共用)。\n const kws = (loadL1().injection_detection || []) as any[];\n return kws.map((k) => ({\n keyword: k.keyword,\n riskLevel: k.risk_level,\n lang: k.lang || 'en',\n }));\n})();\n\n// High-risk command patterns (unified Python + TS, all case-insensitive)\nexport const DANGEROUS_PATTERNS: { pattern: RegExp; severity: string; description: string; riskType: string }[] = (() => {\n // 归一化自 agent_moss/rules/l1_rules.json 的危险命令段(单一事实源,与 Python 共用)。\n const cmds = (loadL1().dangerous_commands || []) as any[];\n return cmds.map((c) => ({\n pattern: new RegExp(c.pattern, 'i'),\n severity: c.risk_level,\n riskType: c.risk_type,\n description: c.reason,\n }));\n})();\n\nexport function runHeuristicCheck(input: AnalysisInput): SecurityJudgment | null {\n const command = `${input.aNext.actionType}: ${input.aNext.actionDetail}`;\n const matched: string[] = [];\n let highestSeverity = 'low';\n let highestRiskType = '';\n\n // Check user-defined custom rules first(对齐 Python UserRuleMatcher 命中即短路返回,\n // 不让后续 CommandPatternScanner/SensitivePathChecker 叠加取最高遮蔽 user rules 的判定)。\n const userRules = getCustomRules();\n for (const rule of userRules) {\n try {\n const re = new RegExp(rule.pattern);\n if (re.test(command)) {\n if (rule.action === 'Deny') {\n return {\n allowed: false,\n reason: `命中用户敏感动作规则: ${rule.description || rule.pattern}`,\n riskLevel: rule.severity as SecurityJudgment['riskLevel'],\n riskType: 'sensitive_action',\n confidence: 90,\n source: 'heuristic',\n violatedLayers: ['1.1'],\n };\n }\n // Allow rules just pass through\n }\n } catch { /* invalid regex, skip */ }\n }\n\n // Check built-in dangerous patterns\n // NEW-FP-I: echo/printf 引号内参数是字面量非真实命令,剥掉引号内容后再匹配,\n // 避免 echo \"rm -rf /tmp\" 的输出文本被当真实命令误报。引号外的重定向 > 和管道 |\n // 后的真实操作保留(echo \"x\" > /etc/passwd 仍被 >/etc/ 检测,echo pass | passwd\n // 的 passwd 仍被匹配)。非 echo/printf 段(rm -rf; echo done 的 rm 段)不剥。\n const scanDetail = normalizePathSegments(stripLiteralTextSegments(input.aNext.actionDetail));\n const scanCommand = `${input.aNext.actionType}: ${scanDetail}`;\n let topRiskType = '';\n for (const rule of DANGEROUS_PATTERNS) {\n if (rule.pattern.test(scanCommand)) {\n matched.push(rule.description);\n if (severityRank(rule.severity) > severityRank(highestSeverity)) {\n highestSeverity = rule.severity;\n topRiskType = rule.riskType;\n }\n }\n }\n highestRiskType = topRiskType || highestRiskType;\n\n // Check agent-specific extra command patterns (追加在通用规则之后)\n // agent 专属规则(agent_id)+ 场景定制规则(scenario_id,如 bank 沙箱的目录白名单/禁 ssh),\n // 合并后统一注入 L1 检测。场景规则:显式 scenarioId > 环境变量 AGENT_MOSS_SCENARIO。\n const agentExt = mergeAgentExtensions(\n getAgentExtensions(input.agentId),\n getScenarioExtensions(input.scenarioId || process.env.AGENT_MOSS_SCENARIO || ''),\n );\n if (agentExt?.extra_command_patterns) {\n for (const rule of agentExt.extra_command_patterns) {\n try {\n const re = new RegExp(rule.pattern, 'i');\n if (re.test(scanCommand)) {\n matched.push(`agent 专属规则: ${rule.reason}`);\n if (severityRank(rule.risk_level) > severityRank(highestSeverity)) {\n highestSeverity = rule.risk_level;\n highestRiskType = rule.risk_type;\n }\n }\n } catch { /* invalid regex, skip */ }\n }\n }\n\n // Check prompt injection keywords (通用 + agent_ext.extra_injection_keywords)\n // 搜索/查询类工具(search-WebSearch 等)的 actionDetail 是查询参数(数据载荷),\n // 不是指令。注入检测只针对指令性文本(用户 prompt / reason / 命令),\n // 排除搜索工具的 actionDetail,避免 \"搜索 jailbreak\" 等被误判为注入攻击。\n const injectionText = isSearchActionType(input.aNext.actionType)\n ? `${input.aNext.actionType} ${input.reason || ''} ${input.promptSession || ''}`.toLowerCase()\n : `${input.aNext.actionType} ${input.aNext.actionDetail} ${input.reason || ''} ${input.promptSession || ''}`.toLowerCase();\n const injectionHits = checkInjectionKeywords(injectionText, agentExt?.extra_injection_keywords);\n if (injectionHits.length > 0) {\n const topHit = injectionHits.reduce((a, b) => severityRank(a.riskLevel) >= severityRank(b.riskLevel) ? a : b);\n matched.push(...injectionHits.map(h => `注入关键词 [${h.lang}]: ${h.keyword}`));\n if (severityRank(topHit.riskLevel) > severityRank(highestSeverity)) {\n highestSeverity = topHit.riskLevel;\n highestRiskType = 'prompt_injection';\n }\n }\n\n // ===== 从 L2 搬入的静态子检测器(只看 a_next)=====\n const actionTypeL = input.aNext.actionType.toLowerCase();\n const detailL = input.aNext.actionDetail.toLowerCase();\n const isExcludedType = SENSITIVE_EXCLUDED_PREFIXES.some(p => actionTypeL.startsWith(p));\n\n // 危险操作模式检测优先(对应 Python CommandPatternScanner 第2检测器,先于 SensitivePathChecker):\n // 含 > /etc/ > /boot/ 重定向覆盖 critical——echo >> /etc/passwd 命中 critical 短路,\n // 不走后面的 checkSensitivePath high(对齐 Python ground truth)。\n const dangerousResult = checkDangerousPatterns(actionTypeL, detailL);\n if (dangerousResult) return dangerousResult;\n\n // 敏感路径访问检测:deny_both/deny_read/deny_write + 凭据边界匹配。\n // 排除 memory-/skill- 等非文件工具前缀,避免参数关键词误报。\n if (!isExcludedType) {\n const pathResult = checkSensitivePath(detailL, input.cwd || '/', agentExt);\n if (pathResult) return pathResult;\n }\n\n // 用户敏感规则命中(custom_rule)须先于敏感路径和横向移动检测:\n // - 避免 ssh -o StrictHostKeyChecking=no 被 checkLateralMovement 标 lateral medium 遮蔽\n // (Python UserRuleMatcher 先于 LateralMovementChecker)。\n // - 避免 ssh ... 'cat /etc/shadow' 被 checkSensitivePath 的 /etc/shadow critical 遮蔽\n // (Python UserRuleMatcher 先于 SensitivePathChecker,user rules high 优先于敏感路径 critical)。\n if (matched.length > 0) {\n return {\n allowed: false,\n reason: `检测到高危操作: ${matched.join(', ')}`,\n riskLevel: highestSeverity as SecurityJudgment['riskLevel'],\n riskType: highestRiskType,\n confidence: 95,\n source: 'heuristic',\n violatedLayers: ['1.1'], // 对齐 py coordinator.py:165(L1.1 = 命中高危命令模式/注入关键词)\n };\n }\n\n // 横向移动检测:ssh/scp/rsync 到非本机主机\n const lateralResult = checkLateralMovement(detailL);\n if (lateralResult) return lateralResult;\n\n return null; // No match, pass to next layer\n}\n\nfunction checkInjectionKeywords(\n text: string,\n extraKeywords?: InjectionKeyword[],\n): { keyword: string; riskLevel: string; lang: string }[] {\n const hits: { keyword: string; riskLevel: string; lang: string }[] = [];\n for (const entry of INJECTION_KEYWORDS) {\n if (text.includes(entry.keyword.toLowerCase())) {\n hits.push(entry);\n }\n }\n // agent 专属注入关键词(追加在后)\n if (extraKeywords) {\n for (const entry of extraKeywords) {\n if (text.includes(entry.keyword.toLowerCase())) {\n hits.push({ keyword: entry.keyword, riskLevel: entry.risk_level, lang: entry.lang });\n }\n }\n }\n return hits;\n}\n\nexport function isInlineScriptCommand(actionDetail: string): boolean {\n // 判断命令是否为内联脚本解释器命令(python -c, perl -e, php -r 等)\n const re = /(?:^|\\s)(?:python|python3|python3\\.\\d+|perl|perl5|ruby|jruby|mruby|node|php|lua)\\s+(?:-[a-zA-Z]*[cer][a-zA-Z]*\\s+)/i;\n return re.test(actionDetail);\n}\n\n/**\n * NEW-FP-I: 对首词 echo/printf 的命令段剥掉引号内容(字面量参数)。\n *\n * echo/printf 是文本输出命令,其引号内参数是被打印的字面量而非真实命令——\n * `echo \"rm -rf /tmp\"` 是打印这串文本不是执行删除。但 DANGEROUS_PATTERNS 旧实现\n * 对整个 actionDetail 做正则匹配,引号内的 rm/chmod/mkfs 等危险命令模式被误当\n * 真实命令匹配 → 误报(NEW-FP-I)。\n *\n * 修复:按 &&/||/;/换行 分段,首词是 echo/printf 的段,剥掉引号内容(字面量),\n * 保留引号外的重定向 >/>> 和管道 | 后的真实操作:\n * - `echo \"rm -rf /tmp\"` → `echo `(rm 模式不匹配,误报消除)\n * - `echo \"x\" > /etc/passwd` → `echo > /etc/passwd`(重定向 >/etc/ 仍匹配,真实写不漏报)\n * - `rm -rf /tmp; echo done` → rm 段不剥,echo 段剥,rm 仍匹配(真实危险不漏报)\n * - `echo pass | passwd` → passwd 无引号在管道后,剥后仍保留(管道注入不漏报)\n */\nexport function stripLiteralTextSegments(actionDetail: string): string {\n // 旁路(NEW-FN-H 待修):含\"写脚本 + 后续执行\"或\"管道喂解释器\"绕过链时整条不剥离。\n // 保留引号内路径让 L1 凭据检测兜底,避免剥离后绕过链漏检(inline-09/10 依赖)。\n // - inline-09: echo \"cat /etc/shadow\" > /tmp/x.sh && bash /tmp/x.sh(写脚本+执行)\n // - inline-10: printf 'cat /etc/shadow' | bash(管道喂解释器)\n const writeScriptExec = />\\s*[/~]\\S*\\.(sh|py|pl|rb)\\b/.test(actionDetail) &&\n /(?:&&|\\|\\||;|\\n|\\|)\\s*(?:bash|sh|zsh|dash|python|perl|ruby|node)/.test(actionDetail);\n const pipeToInterpreter = /\\|\\s*(?:bash|sh|zsh|dash|python|perl|ruby|node)\\b/.test(actionDetail);\n if (writeScriptExec || pipeToInterpreter) {\n return actionDetail;\n }\n // 按命令分隔符分段,但跳过引号内的分隔符(echo \"a; b\" 的 ; 在引号内不分段)\n const resultParts: string[] = [];\n for (const seg of splitCommandSegments(actionDetail)) {\n const fw = (seg.trim().split(/\\s+/)[0] || '').toLowerCase();\n if (fw === 'echo' || fw === 'printf') {\n // 先摘重定向目标的引号路径为裸路径(保留真实写目标),再剥剩余引号内容\n const segUnquotedRedirect = seg.replace(\n />{1,2}\\s*(['\"])([~./][^'\"]+)\\1/g,\n (_m, _q, p: string) => '>' + p,\n );\n resultParts.push(segUnquotedRedirect.replace(/'[^']*'|\"[^\"]*\"/g, ''));\n } else {\n resultParts.push(seg);\n }\n }\n return resultParts.join('');\n}\n\n/**\n * 剥离 heredoc 文档字面量内容(<<EOF ... EOF / <<'EOF' ... EOF)。\n * heredoc 是文档正文不是命令,其中的 `*`/`?`/`rm`/`删除` 是文本而非删除操作。\n * 不剥离会导致 checkDangerousPatterns 的「通配符+删除」误判写文档为批量删除\n * (NEW-FP:写含 markdown 加粗 / 三元表达式 / 描述含 rm 的周报即误报)。\n * 支持 <<EOF / <<-EOF / <<'EOF' / <<\"EOF\",匹配到行首结束标记,替换为 <<heredoc>>。\n */\nexport function stripHeredocContent(actionDetail: string): string {\n return actionDetail.replace(\n /<<-?\\s*(?:['\"]?)([A-Za-z_][A-Za-z0-9_]*)(?:['\"]?)[^\\n]*\\n[\\s\\S]*?\\n\\s*\\1\\s*(?:\\n|$)/g,\n '<<heredoc>>\\n',\n );\n}\n\n/**\n * NORM-PATH: 折叠路径混淆段,堵路径穿越变体(对齐 Python _normalize_path_segments,\n * 对应 CVE-2023-37274 攻击面)。\n *\n * 敏感路径/危险命令匹配前,把「路径混淆」归一回真实路径,避免子串/正则漏检:\n * - 连续斜杠 `//` → `/`(`cat /etc//shadow` 与 `cat /etc/shadow` 等价,应同判)\n * - 单点段 `/./` → `/`(`cat /etc/./shadow` 同理)\n *\n * 不做 `..` 解析(`..` 可能改变路径语义,且现有 dangerous pattern 已对 `..`\n * 穿越有兜底),只折叠无歧义的 `//` 与 `/./`,避免过度归一化误伤。\n *\n * 约束(must not break):\n * 1. 跳过协议 URL 的 `//`(`curl http://x` 的 `http://` 是协议分隔,折叠成\n * `http:/x` 会破坏 curl 下载/管道检测)。\n * 2. 跳过引号内字面量(`grep \"a//b\"` 引号内是搜索模式非路径)。\n */\nexport function normalizePathSegments(text: string): string {\n // 1. 保护协议 URL 的 //(用不含 / 的令牌占位,避免被 /{2,} 折叠)\n const protTokens: string[] = [];\n let t = text.replace(/\\b(https?|ftp|file):\\/\\//gi, (m) => {\n const scheme = m.slice(0, m.indexOf(':'));\n protTokens.push('://');\n return `${scheme}__PROT${protTokens.length - 1}__`;\n });\n // 2. 保护引号内内容(非路径字面量不折叠)\n const quoteTokens: string[] = [];\n t = t.replace(/'[^']*'|\"[^\"]*\"/g, (m) => {\n quoteTokens.push(m);\n return `__Q${quoteTokens.length - 1}__`;\n });\n // 3. 折叠引号外 + 非 URL 的连续斜杠与单点段\n t = t.replace(/\\/{2,}/g, '/');\n t = t.replace(/\\/\\.\\//g, '/');\n // 4. 还原引号与协议\n for (let i = 0; i < quoteTokens.length; i++) {\n t = t.replace(`__Q${i}__`, quoteTokens[i]);\n }\n for (let i = 0; i < protTokens.length; i++) {\n t = t.replace(`__PROT${i}__`, protTokens[i]);\n }\n return t;\n}\n\n/**\n * 按命令分隔符分段,跳过引号内的分隔符(对齐 Python _split_command_segments)。\n * echo \"a; b && c\" 的引号内分隔符是字面量非命令分隔,不能分段——否则\n * 引号内 chmod/mkfs 等词会脱离 echo 段被当独立命令首词误匹配(NEW-FP-I)。\n */\nfunction splitCommandSegments(actionDetail: string): string[] {\n const segments: string[] = [];\n let cur = '';\n let quote: string | null = null;\n for (let i = 0; i < actionDetail.length; i++) {\n const ch = actionDetail[i];\n if (quote) {\n cur += ch;\n if (ch === quote) quote = null;\n continue;\n }\n if (ch === \"'\" || ch === '\"') {\n quote = ch;\n cur += ch;\n continue;\n }\n if (ch === ';' || ch === '\\n') {\n segments.push(cur); segments.push(ch); cur = '';\n continue;\n }\n if (ch === '&' && actionDetail[i + 1] === '&') {\n segments.push(cur); segments.push('&&'); cur = '';\n i++; continue;\n }\n if (ch === '|' && actionDetail[i + 1] === '|') {\n segments.push(cur); segments.push('||'); cur = '';\n i++; continue;\n }\n cur += ch;\n }\n if (cur) segments.push(cur);\n return segments;\n}\n\nfunction severityRank(s: string): number {\n const ranks: Record<string, number> = { low: 1, medium: 2, high: 3, critical: 4 };\n return ranks[s] || 0;\n}\n\n// ==================== 从 L2 搬入 L1 的静态子检测器 ====================\n// 以下三个检测器只看 a_next(不看 action_history),按\"L1 只看这一步\"原则\n// 从 logic-rules.ts 搬入。逻辑原样保留,source 改为 'heuristic'、\n// violatedLayers 改为 ['1.1'],对齐 L1 命令模式/注入关键词的层号。\n\n// 敏感路径检测排除的非文件工具前缀(避免 memory-searchMemory 等误报)\nconst SENSITIVE_EXCLUDED_PREFIXES = ['memory-', 'skill-', 'skill-manager-', 'mailbox-', 'app-'];\n\n// 搜索/查询类工具前缀:其 actionDetail 是「查询数据」(如 query=...),不是指令。\n// 注入关键词检测应只针对指令性文本(用户 prompt / reason / 命令),\n// 否则搜索 \"jailbreak\"、\"bypass\" 等资料会被 L1 注入检测误判为注入攻击(prompt injection 误报)。\n// 与 Python 端 agent_moss/engine/heuristic.py 的 _SEARCH_ACTION_PREFIXES 保持一致。\nconst SEARCH_ACTION_PREFIXES = ['search-', 'web-', 'browser-', 'query-', 'websearch', 'web_search'];\n\nfunction isSearchActionType(actionType: string): boolean {\n const at = actionType.toLowerCase();\n return (\n SEARCH_ACTION_PREFIXES.some((p) => at.startsWith(p)) ||\n ['websearch', 'web_search', 'search', 'query'].includes(at)\n );\n}\n\n/**\n * 敏感路径访问检测(从 L2 搬入)。\n * deny_both(凭据):无论读写都拦截,isCredential=true\n * deny_read:只拦截读取(如 /dev/random)\n * deny_write:只拦截写入/删除\n */\nexport function checkSensitivePath(\n command: string,\n cwd: string,\n agentExt?: import('../agents').AgentExtensions | null,\n): SecurityJudgment | null {\n const expandedCwd = cwd.replace(/^~/, process.env.HOME || '/home/user');\n\n // 写判定统一用 isWriteOperation(对齐 Python _is_write_operation 单一事实源),\n // 替代原手写 isWriteOpFlag(含 ''.includes(kw) 笔误、重定向逻辑矛盾)。\n // command 在此 = actionDetail 小写(调用方 :231 传 detailL),actionType 留空——\n // isWriteOperation 的 actionType.includes 走空串无影响,actionDetail 部分覆盖 command。\n const isWriteOpFlag = isWriteOperation('', command);\n\n // NEW-FP-I: echo/printf 引号内参数是字面量,其中的敏感路径不应被当真实访问。\n // 对首词 echo/printf 的段剥引号内容后再做路径匹配。非 echo/printf 段(cat \"/etc/shadow\")\n // 不剥,引号内真实路径参数仍匹配。引号外的重定向(echo \"x\" > /etc/passwd)保留。\n // NORM-PATH: 再折叠路径混淆段(//、/./),堵路径穿越变体(cat /etc//shadow 漏检)。\n const pathScanText = normalizePathSegments(stripLiteralTextSegments(command));\n\n // 边界路径匹配(对齐 Python heuristic.py:121-132,避免子串误报)。\n // 裸 command.includes(sp.path) 会把 /etc/passwd 命中到 /tmp/etc_passwd_backup、\n // /boot/ 命中到 /boot-log。改用边界正则:/ 开头路径前导用 ^|空白|/|反斜杠|引号,\n // 其余用 \\b;尾随 \\b。凭据(deny_both)尤其需要边界(如 .env 不能命中 .environment)。\n const pathMatches = (text: string, path: string): boolean => {\n // 含正则前瞻语法(如 (?!\\\\.pub) 排除公钥变体)时保留前瞻不转义,仅转义其余元字符。\n // 把路径切成「前瞻块 / 其余」分段处理,前瞻块原样保留,其余分段转义元字符。\n const parts = path.split(/(\\(\\?!.*?\\))/);\n const escaped = parts.map(part => {\n if (part.startsWith('(?!')) return part; // 前瞻块原样\n return part.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n }).join('');\n const re = path.startsWith('.') || path.startsWith('/')\n ? new RegExp(`(?:^|[\\\\s/\\\\\\\\'\"])${escaped}\\\\b`, 'i')\n : new RegExp(`\\\\b${escaped}\\\\b`, 'i');\n return re.test(text);\n };\n\n for (const sp of ROOT_SENSITIVE_PATHS) {\n if (pathMatches(pathScanText, sp.path.toLowerCase())) {\n // /dev/random:只拦截读取操作,写入/删除放行(读取可耗尽熵池导致 TLS 阻塞)\n if (sp.path === '/dev/random') {\n if (isWriteOpFlag) {\n continue; // 允许写入操作(投喂熵池)\n }\n return {\n allowed: false,\n reason: `读取敏感路径: ${sp.desc} (${sp.path})`,\n riskLevel: sp.riskLevel as SecurityJudgment['riskLevel'],\n riskType: 'file_access',\n confidence: 90,\n source: 'heuristic',\n violatedLayers: ['1.1'],\n };\n }\n // 非凭据路径:只拦截写入/删除操作,只读访问放行。\n // 凭据路径(sp.credential=true,如 /etc/shadow、SSH 私钥、AWS 凭证):\n // 读写均拦(读取凭据同样危险)。与 py deny_both 一致。\n if (!isWriteOpFlag && !sp.credential) {\n continue;\n }\n return {\n allowed: false,\n reason: `尝试访问系统敏感路径: ${sp.desc} (${sp.path})`,\n riskLevel: sp.riskLevel as SecurityJudgment['riskLevel'],\n riskType: 'file_access',\n confidence: 90,\n source: 'heuristic',\n violatedLayers: ['1.1'],\n isCredential: !!sp.credential,\n };\n }\n }\n\n for (const sp of HOME_SENSITIVE_PATHS) {\n const expanded = `${expandedCwd}/${sp.path}`;\n // 私钥路径(不以 .pub 结尾)排除公钥变体:.ssh/id_rsa 不应命中 .ssh/id_rsa.pub(公钥公开)\n const pathRe = sp.path.endsWith('.pub')\n ? new RegExp(sp.path.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'), 'i')\n : new RegExp(sp.path.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&') + '(?!\\\\.pub)', 'i');\n const expandedRe = sp.path.endsWith('.pub')\n ? new RegExp(expanded.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'), 'i')\n : new RegExp(expanded.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&') + '(?!\\\\.pub)', 'i');\n if (pathRe.test(pathScanText) || expandedRe.test(pathScanText)) {\n // 非凭据路径:只拦截写入/删除操作,只读访问放行。\n // 凭据路径(sp.credential=true,如 SSH 私钥、AWS 凭证):\n // 读写均拦(读取凭据同样危险)。与 py deny_both 一致。\n if (!isWriteOpFlag && !sp.credential) {\n continue;\n }\n return {\n allowed: false,\n reason: `尝试访问敏感路径: ${sp.desc} (${sp.path})`,\n riskLevel: sp.riskLevel as SecurityJudgment['riskLevel'],\n riskType: 'file_access',\n confidence: 90,\n source: 'heuristic',\n violatedLayers: ['1.1'],\n isCredential: !!sp.credential,\n };\n }\n }\n\n // agent 专属敏感路径(追加在通用规则之后)\n if (agentExt?.extra_sensitive_paths && agentExt.extra_sensitive_paths.length > 0) {\n for (const sp of agentExt.extra_sensitive_paths) {\n const spPath = sp.path.toLowerCase();\n const expanded = `${expandedCwd}/${spPath}`;\n if (pathMatches(command, spPath) || pathMatches(command, expanded.toLowerCase())) {\n const denyMode = sp.deny_mode || (sp.credential ? 'deny_both' : sp.read_only ? 'deny_read' : 'deny_write');\n if (denyMode === 'deny_read') {\n if (isWriteOpFlag) continue;\n } else if (denyMode === 'deny_write') {\n if (!isWriteOpFlag) continue;\n }\n // deny_both:读写均拦\n return {\n allowed: false,\n reason: `尝试访问 agent 专属敏感路径: ${sp.desc} (${sp.path})`,\n riskLevel: sp.risk_level as SecurityJudgment['riskLevel'],\n riskType: 'file_access',\n confidence: 90,\n source: 'heuristic',\n violatedLayers: ['1.1'],\n isCredential: !!sp.credential,\n };\n }\n }\n }\n\n // Credential files: always intercept regardless of read/write\n // Files starting with . need special handling since \\b doesn't match before .\n // 边界字符含引号:凭据常出现在 open('.env')、cat \".env\" 等引号上下文里\n for (const cp of CREDENTIAL_PATHS) {\n const escaped = cp.path.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const re = cp.path.startsWith('.')\n ? new RegExp(`(?:^|[\\\\s/\\\\\\\\'\"])${escaped}\\\\b`)\n : new RegExp(`\\\\b${escaped}\\\\b`);\n if (re.test(command)) {\n return {\n allowed: false,\n reason: `访问敏感路径: ${cp.desc} (${cp.path})`,\n riskLevel: cp.riskLevel as SecurityJudgment['riskLevel'],\n riskType: 'file_access',\n confidence: 90,\n source: 'heuristic',\n violatedLayers: ['1.1'],\n isCredential: true,\n };\n }\n }\n\n // Check deletion of sensitive directories\n if ((command.includes('rm ') || command.includes('unlink')) &&\n (command.includes('/etc/') || command.includes('/root/') || command.includes('/var/log/'))) {\n return {\n allowed: false,\n reason: '检测到删除关键系统目录内容',\n riskLevel: 'critical',\n riskType: 'file_access',\n confidence: 90,\n source: 'heuristic',\n violatedLayers: ['1.1'],\n };\n }\n\n return null;\n}\n\n/** 危险操作模式检测(从 L2 搬入):通配符+删除、重定向覆盖 /etc /boot /proc */\nexport function checkDangerousPatterns(actionType: string, actionDetail: string): SecurityJudgment | null {\n if (actionType === 'file_write' || actionType === 'file_edit') return null;\n\n // Wildcard + delete — 排除 /tmp 等临时目录的清理操作\n // 用边界正则匹配目录名本身(/tmp 和 /tmp/ 都算),避免 `find /tmp -delete`\n // 因 \"/tmp/\" 子串不匹配(/tmp 后是空格)而 isTempPath=false 误报(Bug6)。\n // NEW-FP(鸿蒙写周报误报):先剥离 heredoc 文档字面量内容——文档正文里的\n // `*`/`?`/`rm`/`删除` 是文本不是真实删除命令,不剥离会误判为批量删除。\n const scan = stripHeredocContent(actionDetail);\n const TEMP_DIRS = ['/tmp', '/var/tmp', '/run', '/dev/shm'];\n const isTempPath = TEMP_DIRS.some(td =>\n new RegExp(`(?:^|[\\\\s/])${td.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}(?:[\\\\s/]|$)`).test(actionDetail)\n );\n // 通配符必须紧邻删除命令(真实命令 token),而非任意位置子串。\n // 收紧:`*`/`?` 出现在删除命令(rm/del/delete/remove/删除/移除)附近——\n // 匹配「删除命令 + 通配符路径」组合,如 `rm -rf /tmp/*`、`rm *`、`find . -delete`。\n // 不再用 actionDetail.includes('*') && includes('rm') 的宽泛子串匹配,\n // 避免文档正文/heredoc/grep 模式里的字面量误报。\n const wildcardDeleteRe =\n /(?:\\brm\\b|\\b(r?mdir|del|delete|remove|rmdir|unlink)\\b|\\b删除\\b|\\b移除\\b)[\\s\\S]{0,40}?[*?]|[*?][\\s\\S]{0,40}?\\b(?:rm|del|delete|remove|rmdir|unlink)\\b|rm\\s+-[a-zA-Z]*[rf][a-zA-Z]*\\s+\\S*[*?]/i;\n if (!isTempPath && wildcardDeleteRe.test(scan)) {\n return {\n allowed: false,\n reason: '检测到通配符结合删除操作,可能造成批量误删',\n riskLevel: 'high',\n riskType: 'script_execution',\n confidence: 90,\n source: 'heuristic',\n violatedLayers: ['1.1'],\n };\n }\n // find -exec <写命令> / find | xargs <写命令> — find 在 READ_ONLY_COMMANDS 导致整段\n // 被当只读,-exec 或 | xargs 后的 chmod/cp/mv/rm/sed -i 等写命令漏检(NEW-FN-C: -exec;\n // NEW-FN-E: | xargs 等价变体未覆盖)。find 遍历出的文件被批量执行写操作,静态无法确定\n // 具体目标文件,但「find + 写命令」组合本身就是批量写意图,此处识别 -exec/-execdir/-ok\n // 后紧跟写命令、或 | xargs 后紧跟写命令即拦截。只匹配写命令首词,避免 -exec grep /\n // | xargs ls 等只读误报。xargs 后的 sed -i 单独匹配(sed -i 是 sed + -i 参数)。\n const findWriteMatch = actionDetail.match(\n /\\bfind\\b.*?(?:(?:^|\\s)-exec(?:dir)?\\s+(chmod|chown|cp|mv|rm|dd|tee|truncate|mkfs|shred|rmdir|unlink)\\b|(?:^|\\s)\\|\\s*xargs\\s+(?:sed\\s+-[a-zA-Z]*i|chmod|chown|cp|mv|rm|dd|tee|truncate|mkfs|shred|rmdir|unlink)\\b)/i\n );\n if (findWriteMatch) {\n const cmdHit = findWriteMatch[1] || 'xargs';\n return {\n allowed: false,\n reason: `检测到 find 批量执行写操作 (${cmdHit}),可能批量修改/删除文件`,\n riskLevel: 'high',\n riskType: 'script_execution',\n confidence: 90,\n source: 'heuristic',\n violatedLayers: ['1.1'],\n };\n }\n // Redirect overwrite to system directories(对齐 Python CommandPatternScanner `>\\s*/etc/` critical,不排除敏感路径)。\n // echo >> /etc/passwd、cat > /etc/ssh/sshd_config 均命中 critical 短路(Python ground truth)。\n if (/>\\s*\\/etc\\//.test(actionDetail) || />\\s*\\/boot\\//.test(actionDetail)) {\n return {\n allowed: false,\n reason: '检测到重定向覆盖写入关键系统目录',\n riskLevel: 'critical',\n riskType: 'file_access',\n confidence: 95,\n source: 'heuristic',\n violatedLayers: ['1.1'],\n };\n }\n // A16: 重定向覆盖设备文件(对齐 Python linux.py:180 `>\\s*/dev/(sd|hd|nvme|vd|loop|mem|kmsg|port|zero|random|urandom|full|core)`)。\n // high/file_access。须先于 checkSensitivePath 的 /dev/mem critical 命中,避免写 /dev/mem 被标 critical(Python 是 high)。\n if (/>\\s*\\/dev\\/(sd|hd|nvme|vd|loop|mem|kmsg|port|zero|random|urandom|full|core)/i.test(actionDetail)) {\n return {\n allowed: false,\n reason: '检测到重定向写入设备文件',\n riskLevel: 'high',\n riskType: 'file_access',\n confidence: 90,\n source: 'heuristic',\n violatedLayers: ['1.1'],\n };\n }\n return null;\n}\n\n\nfunction extractRemoteHost(command: string): string | null {\n // NEW-FN-G: 旧正则 (?:ssh|scp|rsync)\\s+(?:-[\\w]+\\s+)*(\\S+@\\S+|\\b(?!-)[\\w.-]+\\b)\n // 的 (?:-[\\w]+\\s+)* 只匹配单选项不匹配带参数值选项(-p 2222、-L 8080:...、\n // -D 1080、-e ssh),导致 host 提取取到端口号或选项参数。token 化三策略更可靠。\n // NEW-FP-E: bash -c/sh -c \"ssh user@host\" 的 user@host 被引号包裹成 \"user@host\"\n // 正则不匹配(\" 非 \\w)→ 漏报。bash -c 内联命令是真实调用,应检测。\n // 剥 token 首尾引号后再匹配(python -c 已在 checkLateralMovement 开头 INLINE_SCRIPT_RE 跳过)。\n const tokens = command.split(/\\s+/).map(t => t.replace(/^[\"']|[\"']$/g, ''));\n // 策略1:优先找 user@host 或 user@host: 模式(最可靠,带值选项参数值如\n // -L 8080:localhost:80 的 localhost 会被 isLocalHost 排除,不会误匹配)。\n for (const tok of tokens) {\n const am = tok.match(/^([\\w.-]+)@([\\w.-]+)(:.*)?$/);\n if (am && am[2] && !isLocalHost(am[2])) {\n return `${am[1]}@${am[2]}`;\n }\n }\n // 策略2:host: 模式(rsync/scp 远程路径 host:/path,无 user@)\n for (const tok of tokens) {\n const hm = tok.match(/^([\\w.-]+):\\/(.*)?$/);\n if (hm && hm[1] && !isLocalHost(hm[1])) {\n return hm[1];\n }\n }\n // 策略3:回退\"第一个非选项 token\"(ssh host 无 @ 无 :,如 ssh 10.0.0.5)。\n // 跳过 - 开头选项及其参数值(-p 2222 / -e ssh / -L 8080:...)。\n const skipValueOpts = new Set([\n '-p', '-l', '-i', '-o', '-b', '-c', '-m', '-F',\n '-e', '-S', '-W', '-J', '-I', '-T', '-B',\n '-L', '-R', '-D', '-E', '-M', '-O', '-P', '-q',\n ]);\n let foundCmd = false;\n for (let i = 0; i < tokens.length; i++) {\n const t = tokens[i];\n if (t === 'ssh' || t === 'scp' || t === 'rsync') {\n foundCmd = true;\n continue;\n }\n if (!foundCmd) continue;\n if (t.startsWith('-')) {\n // 带值选项:跳过下一个 token(-p 2222 / -e ssh / -L 8080:...)\n if (skipValueOpts.has(t) && i + 1 < tokens.length) {\n i++;\n }\n continue;\n }\n // 非选项 token:候选主机。排除纯路径(/ 开头本地路径非主机名)。\n if (t.startsWith('/')) continue;\n return t;\n }\n return null;\n}\n\nfunction isLocalHost(host: string): boolean {\n const localNames = ['localhost', '127.0.0.1', '::1', process.env.HOSTNAME || '', '0.0.0.0'];\n return localNames.includes(host.replace(/.*@/, ''));\n}\n\n/** 横向移动检测(从 L2 括入):ssh/scp/rsync 到非本机主机 */\nexport function checkLateralMovement(actionDetail: string): SecurityJudgment | null {\n // NEW-FP-D: 内联脚本(python -c / perl -e 等)里的 ssh/scp/rsync 是字面量非真调用,\n // 跳过交 inline-analyzer 专门管,与 intent/privilege 一致\n if (/\\b(?:python|python3|perl|ruby|node|php|lua)\\b\\s+.*-[cer][a-zA-Z]*\\s/.test(actionDetail)) return null;\n\n // NEW-FP-D: echo/printf �首词的参数是字面量非真调用(echo ssh user@host 是打印字面量)\n // 按命令段判定:首词 echo/printf 跳过,与 isWriteOperation 的 wget/curl 字面量判定一致\n const segments = actionDetail.split(/&&|\\|\\||;|\\n/).map(s => s.trim()).filter(Boolean);\n let hasRealCall = false;\n for (const seg of segments) {\n const parts = seg.split(/\\s+/);\n const fw = (parts[0] || '').toLowerCase();\n if (fw === 'echo' || fw === 'printf') continue;\n if (/(?:ssh|scp|rsync)\\s+/.test(seg)) { hasRealCall = true; break; }\n }\n if (!hasRealCall) return null;\n\n if (/(?:ssh|scp|rsync)\\s+/.test(actionDetail)) {\n const targetHost = extractRemoteHost(actionDetail);\n if (targetHost && !isLocalHost(targetHost)) {\n return {\n allowed: false,\n reason: `尝试横向移动到远程主机: ${targetHost}`,\n riskLevel: 'medium',\n riskType: 'lateral_movement',\n confidence: 80,\n source: 'heuristic',\n violatedLayers: ['1.1'],\n };\n }\n }\n return null;\n}\n","/**\n * Token usage statistics — record and query LLM token consumption.\n *\n * Mirrors Python agent_moss/infra/token_stats.py.\n *\n * Storage: JSON file at <data_root>/agent_moss_token_stats.json\n * (default ~/.config/agentmoss). With AGENT_MOSS_INSTANCE the file is isolated\n * to <data_root>/<instance>/ (see infra/paths.ts). env override\n * AGENT_MOSS_TOKEN_STATS_PATH wins. Whole-file rewrite per record (not append).\n * Max 10000 records, oldest trimmed.\n */\n\nimport { readFileSync, writeFileSync, existsSync, mkdirSync, unlinkSync } from 'fs';\nimport { join } from 'path';\nimport { getTokenStatsPath } from '../infra/paths';\n\nconst ENV_STATS_PATH = 'AGENT_MOSS_TOKEN_STATS_PATH';\nconst MAX_RECORDS = 10000;\n\nexport interface TokenUsageRecord {\n timestamp?: string; // ISO with milliseconds; auto-filled if omitted\n sessionId: string;\n step: string; // \"L3_security_judge\" | \"step2_policy_gen\"\n model: string;\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n}\n\ninterface RawRecord {\n timestamp: string;\n session_id: string;\n step: string;\n model: string;\n prompt_tokens: number;\n completion_tokens: number;\n total_tokens: number;\n}\n\ninterface Aggregated {\n prompt_tokens: number;\n completion_tokens: number;\n total_tokens: number;\n calls: number;\n}\n\nexport interface TokenStatsSummary {\n total_prompt_tokens: number;\n total_completion_tokens: number;\n total_tokens: number;\n total_calls: number;\n by_step: Record<string, Aggregated>;\n by_model: Record<string, Aggregated>;\n by_date: Record<string, Aggregated>;\n}\n\nexport interface TokenTrend {\n dates: string[];\n models: string[];\n series: Record<string, Record<string, number>>;\n}\n\nfunction getStatsPath(): string {\n const envPath = process.env[ENV_STATS_PATH];\n if (envPath) return envPath;\n return getTokenStatsPath();\n}\n\nfunction loadAllRecords(statsPath: string): RawRecord[] {\n if (!existsSync(statsPath)) return [];\n try {\n const data = JSON.parse(readFileSync(statsPath, 'utf-8'));\n if (Array.isArray(data)) return data;\n if (data && Array.isArray(data.records)) return data.records;\n return [];\n } catch (e) {\n return [];\n }\n}\n\nfunction saveRecords(statsPath: string, records: RawRecord[]): void {\n try {\n const dir = statsPath.substring(0, statsPath.lastIndexOf('/'));\n if (dir && !existsSync(dir)) mkdirSync(dir, { recursive: true });\n writeFileSync(statsPath, JSON.stringify(records, null, 2), 'utf-8');\n } catch (e) {\n // best-effort\n }\n}\n\n/** Record a single LLM call's token usage. */\nexport function recordTokenUsage(record: TokenUsageRecord): void {\n const statsPath = getStatsPath();\n const records = loadAllRecords(statsPath);\n records.push({\n timestamp: record.timestamp || new Date().toISOString(),\n session_id: record.sessionId,\n step: record.step,\n model: record.model,\n prompt_tokens: record.promptTokens,\n completion_tokens: record.completionTokens,\n total_tokens: record.totalTokens,\n });\n if (records.length > MAX_RECORDS) {\n records.splice(0, records.length - MAX_RECORDS);\n }\n saveRecords(statsPath, records);\n}\n\nfunction filterByDate(\n records: RawRecord[],\n days: number = 0,\n startDate?: string | null,\n endDate?: string | null,\n): RawRecord[] {\n if (startDate || endDate) {\n let startDt = startDate ? new Date(startDate) : new Date(-8640000000000000);\n let endDt = endDate ? new Date(endDate) : undefined;\n if (endDate) {\n const e = new Date(endDate);\n e.setHours(23, 59, 59, 999);\n endDt = e;\n }\n const endMs = endDt ? endDt.getTime() : Number.MAX_SAFE_INTEGER;\n return records.filter(r => {\n try {\n const ts = new Date(r.timestamp).getTime();\n return ts >= startDt.getTime() && ts <= endMs;\n } catch { return true; }\n });\n } else if (days > 0) {\n const cutoff = Date.now() - days * 86400000;\n return records.filter(r => {\n try { return new Date(r.timestamp).getTime() >= cutoff; }\n catch { return true; }\n });\n }\n return records;\n}\n\nfunction aggregate(records: RawRecord[]): {\n totalPrompt: number; totalCompletion: number; totalTotal: number;\n byStep: Record<string, Aggregated>; byModel: Record<string, Aggregated>; byDate: Record<string, Aggregated>;\n} {\n let totalPrompt = 0, totalCompletion = 0, totalTotal = 0;\n const byStep: Record<string, Aggregated> = {};\n const byModel: Record<string, Aggregated> = {};\n const byDate: Record<string, Aggregated> = {};\n\n const bucket = (b: Record<string, Aggregated>, key: string, r: RawRecord) => {\n const e = b[key] || (b[key] = { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0, calls: 0 });\n e.prompt_tokens += r.prompt_tokens || 0;\n e.completion_tokens += r.completion_tokens || 0;\n e.total_tokens += r.total_tokens || 0;\n e.calls += 1;\n };\n\n for (const r of records) {\n totalPrompt += r.prompt_tokens || 0;\n totalCompletion += r.completion_tokens || 0;\n totalTotal += r.total_tokens || 0;\n bucket(byStep, r.step || 'unknown', r);\n bucket(byModel, r.model || 'unknown', r);\n let dateKey = 'unknown';\n try {\n dateKey = new Date(r.timestamp).toISOString().slice(0, 10);\n } catch { /* keep unknown */ }\n bucket(byDate, dateKey, r);\n }\n\n // by_date sorted desc by date\n const sortedDate = Object.keys(byDate).sort((a, b) => (a < b ? 1 : a > b ? -1 : 0));\n const sortedByDate: Record<string, Aggregated> = {};\n for (const k of sortedDate) sortedByDate[k] = byDate[k];\n\n return { totalPrompt, totalCompletion, totalTotal, byStep, byModel, byDate: sortedByDate };\n}\n\nexport function getTokenStats(\n days: number = 0,\n startDate?: string | null,\n endDate?: string | null,\n): TokenStatsSummary {\n const records = filterByDate(loadAllRecords(getStatsPath()), days, startDate, endDate);\n const a = aggregate(records);\n return {\n total_prompt_tokens: a.totalPrompt,\n total_completion_tokens: a.totalCompletion,\n total_tokens: a.totalTotal,\n total_calls: records.length,\n by_step: a.byStep,\n by_model: a.byModel,\n by_date: a.byDate,\n };\n}\n\nexport function getRecentRecords(limit: number = 20, offset: number = 0): RawRecord[] {\n const records = loadAllRecords(getStatsPath());\n // 按时间升序存储,取\"最近\"需从末尾往前 offset 条再取 limit 条\n const start = Math.max(0, records.length - offset - limit);\n const end = records.length - offset;\n return records.slice(start, end);\n}\n\n/** 获取最近记录分页总数(供前端分页器使用) */\nexport function getRecentRecordsCount(): number {\n return loadAllRecords(getStatsPath()).length;\n}\n\nexport function getTokenTrend(\n days: number = 0,\n startDate?: string | null,\n endDate?: string | null,\n): TokenTrend {\n const records = filterByDate(loadAllRecords(getStatsPath()), days, startDate, endDate);\n const series: Record<string, Record<string, number>> = {};\n const datesSet = new Set<string>();\n for (const r of records) {\n let dateKey: string;\n try { dateKey = new Date(r.timestamp).toISOString().slice(0, 10); }\n catch { continue; }\n const model = r.model || 'unknown';\n const tokens = r.total_tokens || 0;\n datesSet.add(dateKey);\n series[model] = series[model] || {};\n series[model][dateKey] = (series[model][dateKey] || 0) + tokens;\n }\n const dates = Array.from(datesSet).sort();\n const models = Object.keys(series).sort();\n return { dates, models, series };\n}\n\nexport function resetTokenStats(): void {\n const statsPath = getStatsPath();\n if (existsSync(statsPath)) {\n try { unlinkSync(statsPath); } catch { /* ignore */ }\n }\n}\n","'use strict';\n\nexports.getBooleanOption = (options, key) => {\n\tlet value = false;\n\tif (key in options && typeof (value = options[key]) !== 'boolean') {\n\t\tthrow new TypeError(`Expected the \"${key}\" option to be a boolean`);\n\t}\n\treturn value;\n};\n\nexports.cppdb = Symbol();\nexports.inspect = Symbol.for('nodejs.util.inspect.custom');\n","'use strict';\nconst descriptor = { value: 'SqliteError', writable: true, enumerable: false, configurable: true };\n\nfunction SqliteError(message, code) {\n\tif (new.target !== SqliteError) {\n\t\treturn new SqliteError(message, code);\n\t}\n\tif (typeof code !== 'string') {\n\t\tthrow new TypeError('Expected second argument to be a string');\n\t}\n\tError.call(this, message);\n\tdescriptor.value = '' + message;\n\tObject.defineProperty(this, 'message', descriptor);\n\tError.captureStackTrace(this, SqliteError);\n\tthis.code = code;\n}\nObject.setPrototypeOf(SqliteError, Error);\nObject.setPrototypeOf(SqliteError.prototype, Error.prototype);\nObject.defineProperty(SqliteError.prototype, 'name', descriptor);\nmodule.exports = SqliteError;\n","\n/**\n * Module dependencies.\n */\n\nvar sep = require('path').sep || '/';\n\n/**\n * Module exports.\n */\n\nmodule.exports = fileUriToPath;\n\n/**\n * File URI to Path function.\n *\n * @param {String} uri\n * @return {String} path\n * @api public\n */\n\nfunction fileUriToPath (uri) {\n if ('string' != typeof uri ||\n uri.length <= 7 ||\n 'file://' != uri.substring(0, 7)) {\n throw new TypeError('must pass in a file:// URI to convert to a file path');\n }\n\n var rest = decodeURI(uri.substring(7));\n var firstSlash = rest.indexOf('/');\n var host = rest.substring(0, firstSlash);\n var path = rest.substring(firstSlash + 1);\n\n // 2. Scheme Definition\n // As a special case, <host> can be the string \"localhost\" or the empty\n // string; this is interpreted as \"the machine from which the URL is\n // being interpreted\".\n if ('localhost' == host) host = '';\n\n if (host) {\n host = sep + sep + host;\n }\n\n // 3.2 Drives, drive letters, mount points, file system root\n // Drive letters are mapped into the top of a file URI in various ways,\n // depending on the implementation; some applications substitute\n // vertical bar (\"|\") for the colon after the drive letter, yielding\n // \"file:///c|/tmp/test.txt\". In some cases, the colon is left\n // unchanged, as in \"file:///c:/tmp/test.txt\". In other cases, the\n // colon is simply omitted, as in \"file:///c/tmp/test.txt\".\n path = path.replace(/^(.+)\\|/, '$1:');\n\n // for Windows, we need to invert the path separators from what a URI uses\n if (sep == '\\\\') {\n path = path.replace(/\\//g, '\\\\');\n }\n\n if (/^.+\\:/.test(path)) {\n // has Windows drive at beginning of path\n } else {\n // unix path…\n path = sep + path;\n }\n\n return host + path;\n}\n","/**\n * Module dependencies.\n */\n\nvar fs = require('fs'),\n path = require('path'),\n fileURLToPath = require('file-uri-to-path'),\n join = path.join,\n dirname = path.dirname,\n exists =\n (fs.accessSync &&\n function(path) {\n try {\n fs.accessSync(path);\n } catch (e) {\n return false;\n }\n return true;\n }) ||\n fs.existsSync ||\n path.existsSync,\n defaults = {\n arrow: process.env.NODE_BINDINGS_ARROW || ' → ',\n compiled: process.env.NODE_BINDINGS_COMPILED_DIR || 'compiled',\n platform: process.platform,\n arch: process.arch,\n nodePreGyp:\n 'node-v' +\n process.versions.modules +\n '-' +\n process.platform +\n '-' +\n process.arch,\n version: process.versions.node,\n bindings: 'bindings.node',\n try: [\n // node-gyp's linked version in the \"build\" dir\n ['module_root', 'build', 'bindings'],\n // node-waf and gyp_addon (a.k.a node-gyp)\n ['module_root', 'build', 'Debug', 'bindings'],\n ['module_root', 'build', 'Release', 'bindings'],\n // Debug files, for development (legacy behavior, remove for node v0.9)\n ['module_root', 'out', 'Debug', 'bindings'],\n ['module_root', 'Debug', 'bindings'],\n // Release files, but manually compiled (legacy behavior, remove for node v0.9)\n ['module_root', 'out', 'Release', 'bindings'],\n ['module_root', 'Release', 'bindings'],\n // Legacy from node-waf, node <= 0.4.x\n ['module_root', 'build', 'default', 'bindings'],\n // Production \"Release\" buildtype binary (meh...)\n ['module_root', 'compiled', 'version', 'platform', 'arch', 'bindings'],\n // node-qbs builds\n ['module_root', 'addon-build', 'release', 'install-root', 'bindings'],\n ['module_root', 'addon-build', 'debug', 'install-root', 'bindings'],\n ['module_root', 'addon-build', 'default', 'install-root', 'bindings'],\n // node-pre-gyp path ./lib/binding/{node_abi}-{platform}-{arch}\n ['module_root', 'lib', 'binding', 'nodePreGyp', 'bindings']\n ]\n };\n\n/**\n * The main `bindings()` function loads the compiled bindings for a given module.\n * It uses V8's Error API to determine the parent filename that this function is\n * being invoked from, which is then used to find the root directory.\n */\n\nfunction bindings(opts) {\n // Argument surgery\n if (typeof opts == 'string') {\n opts = { bindings: opts };\n } else if (!opts) {\n opts = {};\n }\n\n // maps `defaults` onto `opts` object\n Object.keys(defaults).map(function(i) {\n if (!(i in opts)) opts[i] = defaults[i];\n });\n\n // Get the module root\n if (!opts.module_root) {\n opts.module_root = exports.getRoot(exports.getFileName());\n }\n\n // Ensure the given bindings name ends with .node\n if (path.extname(opts.bindings) != '.node') {\n opts.bindings += '.node';\n }\n\n // https://github.com/webpack/webpack/issues/4175#issuecomment-342931035\n var requireFunc =\n typeof __webpack_require__ === 'function'\n ? __non_webpack_require__\n : require;\n\n var tries = [],\n i = 0,\n l = opts.try.length,\n n,\n b,\n err;\n\n for (; i < l; i++) {\n n = join.apply(\n null,\n opts.try[i].map(function(p) {\n return opts[p] || p;\n })\n );\n tries.push(n);\n try {\n b = opts.path ? requireFunc.resolve(n) : requireFunc(n);\n if (!opts.path) {\n b.path = n;\n }\n return b;\n } catch (e) {\n if (e.code !== 'MODULE_NOT_FOUND' &&\n e.code !== 'QUALIFIED_PATH_RESOLUTION_FAILED' &&\n !/not find/i.test(e.message)) {\n throw e;\n }\n }\n }\n\n err = new Error(\n 'Could not locate the bindings file. Tried:\\n' +\n tries\n .map(function(a) {\n return opts.arrow + a;\n })\n .join('\\n')\n );\n err.tries = tries;\n throw err;\n}\nmodule.exports = exports = bindings;\n\n/**\n * Gets the filename of the JavaScript file that invokes this function.\n * Used to help find the root directory of a module.\n * Optionally accepts an filename argument to skip when searching for the invoking filename\n */\n\nexports.getFileName = function getFileName(calling_file) {\n var origPST = Error.prepareStackTrace,\n origSTL = Error.stackTraceLimit,\n dummy = {},\n fileName;\n\n Error.stackTraceLimit = 10;\n\n Error.prepareStackTrace = function(e, st) {\n for (var i = 0, l = st.length; i < l; i++) {\n fileName = st[i].getFileName();\n if (fileName !== __filename) {\n if (calling_file) {\n if (fileName !== calling_file) {\n return;\n }\n } else {\n return;\n }\n }\n }\n };\n\n // run the 'prepareStackTrace' function above\n Error.captureStackTrace(dummy);\n dummy.stack;\n\n // cleanup\n Error.prepareStackTrace = origPST;\n Error.stackTraceLimit = origSTL;\n\n // handle filename that starts with \"file://\"\n var fileSchema = 'file://';\n if (fileName.indexOf(fileSchema) === 0) {\n fileName = fileURLToPath(fileName);\n }\n\n return fileName;\n};\n\n/**\n * Gets the root directory of a module, given an arbitrary filename\n * somewhere in the module tree. The \"root directory\" is the directory\n * containing the `package.json` file.\n *\n * In: /home/nate/node-native-module/lib/index.js\n * Out: /home/nate/node-native-module\n */\n\nexports.getRoot = function getRoot(file) {\n var dir = dirname(file),\n prev;\n while (true) {\n if (dir === '.') {\n // Avoids an infinite loop in rare cases, like the REPL\n dir = process.cwd();\n }\n if (\n exists(join(dir, 'package.json')) ||\n exists(join(dir, 'node_modules'))\n ) {\n // Found the 'package.json' file or 'node_modules' dir; we're done\n return dir;\n }\n if (prev === dir) {\n // Got to the top\n throw new Error(\n 'Could not find module root given file: \"' +\n file +\n '\". Do you have a `package.json` file? '\n );\n }\n // Try the parent dir next\n prev = dir;\n dir = join(dir, '..');\n }\n};\n","'use strict';\nconst { cppdb } = require('../util');\n\nexports.prepare = function prepare(sql) {\n\treturn this[cppdb].prepare(sql, this, false);\n};\n\nexports.exec = function exec(sql) {\n\tthis[cppdb].exec(sql);\n\treturn this;\n};\n\nexports.close = function close() {\n\tthis[cppdb].close();\n\treturn this;\n};\n\nexports.loadExtension = function loadExtension(...args) {\n\tthis[cppdb].loadExtension(...args);\n\treturn this;\n};\n\nexports.defaultSafeIntegers = function defaultSafeIntegers(...args) {\n\tthis[cppdb].defaultSafeIntegers(...args);\n\treturn this;\n};\n\nexports.unsafeMode = function unsafeMode(...args) {\n\tthis[cppdb].unsafeMode(...args);\n\treturn this;\n};\n\nexports.getters = {\n\tname: {\n\t\tget: function name() { return this[cppdb].name; },\n\t\tenumerable: true,\n\t},\n\topen: {\n\t\tget: function open() { return this[cppdb].open; },\n\t\tenumerable: true,\n\t},\n\tinTransaction: {\n\t\tget: function inTransaction() { return this[cppdb].inTransaction; },\n\t\tenumerable: true,\n\t},\n\treadonly: {\n\t\tget: function readonly() { return this[cppdb].readonly; },\n\t\tenumerable: true,\n\t},\n\tmemory: {\n\t\tget: function memory() { return this[cppdb].memory; },\n\t\tenumerable: true,\n\t},\n};\n","'use strict';\nconst { cppdb } = require('../util');\nconst controllers = new WeakMap();\n\nmodule.exports = function transaction(fn) {\n\tif (typeof fn !== 'function') throw new TypeError('Expected first argument to be a function');\n\n\tconst db = this[cppdb];\n\tconst controller = getController(db, this);\n\tconst { apply } = Function.prototype;\n\n\t// Each version of the transaction function has these same properties\n\tconst properties = {\n\t\tdefault: { value: wrapTransaction(apply, fn, db, controller.default) },\n\t\tdeferred: { value: wrapTransaction(apply, fn, db, controller.deferred) },\n\t\timmediate: { value: wrapTransaction(apply, fn, db, controller.immediate) },\n\t\texclusive: { value: wrapTransaction(apply, fn, db, controller.exclusive) },\n\t\tdatabase: { value: this, enumerable: true },\n\t};\n\n\tObject.defineProperties(properties.default.value, properties);\n\tObject.defineProperties(properties.deferred.value, properties);\n\tObject.defineProperties(properties.immediate.value, properties);\n\tObject.defineProperties(properties.exclusive.value, properties);\n\n\t// Return the default version of the transaction function\n\treturn properties.default.value;\n};\n\n// Return the database's cached transaction controller, or create a new one\nconst getController = (db, self) => {\n\tlet controller = controllers.get(db);\n\tif (!controller) {\n\t\tconst shared = {\n\t\t\tcommit: db.prepare('COMMIT', self, false),\n\t\t\trollback: db.prepare('ROLLBACK', self, false),\n\t\t\tsavepoint: db.prepare('SAVEPOINT `\\t_bs3.\\t`', self, false),\n\t\t\trelease: db.prepare('RELEASE `\\t_bs3.\\t`', self, false),\n\t\t\trollbackTo: db.prepare('ROLLBACK TO `\\t_bs3.\\t`', self, false),\n\t\t};\n\t\tcontrollers.set(db, controller = {\n\t\t\tdefault: Object.assign({ begin: db.prepare('BEGIN', self, false) }, shared),\n\t\t\tdeferred: Object.assign({ begin: db.prepare('BEGIN DEFERRED', self, false) }, shared),\n\t\t\timmediate: Object.assign({ begin: db.prepare('BEGIN IMMEDIATE', self, false) }, shared),\n\t\t\texclusive: Object.assign({ begin: db.prepare('BEGIN EXCLUSIVE', self, false) }, shared),\n\t\t});\n\t}\n\treturn controller;\n};\n\n// Return a new transaction function by wrapping the given function\nconst wrapTransaction = (apply, fn, db, { begin, commit, rollback, savepoint, release, rollbackTo }) => function sqliteTransaction() {\n\tlet before, after, undo;\n\tif (db.inTransaction) {\n\t\tbefore = savepoint;\n\t\tafter = release;\n\t\tundo = rollbackTo;\n\t} else {\n\t\tbefore = begin;\n\t\tafter = commit;\n\t\tundo = rollback;\n\t}\n\tbefore.run();\n\ttry {\n\t\tconst result = apply.call(fn, this, arguments);\n\t\tif (result && typeof result.then === 'function') {\n\t\t\tthrow new TypeError('Transaction function cannot return a promise');\n\t\t}\n\t\tafter.run();\n\t\treturn result;\n\t} catch (ex) {\n\t\tif (db.inTransaction) {\n\t\t\tundo.run();\n\t\t\tif (undo !== rollback) after.run();\n\t\t}\n\t\tthrow ex;\n\t}\n};\n","'use strict';\nconst { getBooleanOption, cppdb } = require('../util');\n\nmodule.exports = function pragma(source, options) {\n\tif (options == null) options = {};\n\tif (typeof source !== 'string') throw new TypeError('Expected first argument to be a string');\n\tif (typeof options !== 'object') throw new TypeError('Expected second argument to be an options object');\n\tconst simple = getBooleanOption(options, 'simple');\n\n\tconst stmt = this[cppdb].prepare(`PRAGMA ${source}`, this, true);\n\treturn simple ? stmt.pluck().get() : stmt.all();\n};\n","'use strict';\nconst fs = require('fs');\nconst path = require('path');\nconst { promisify } = require('util');\nconst { cppdb } = require('../util');\nconst fsAccess = promisify(fs.access);\n\nmodule.exports = async function backup(filename, options) {\n\tif (options == null) options = {};\n\n\t// Validate arguments\n\tif (typeof filename !== 'string') throw new TypeError('Expected first argument to be a string');\n\tif (typeof options !== 'object') throw new TypeError('Expected second argument to be an options object');\n\n\t// Interpret options\n\tfilename = filename.trim();\n\tconst attachedName = 'attached' in options ? options.attached : 'main';\n\tconst handler = 'progress' in options ? options.progress : null;\n\n\t// Validate interpreted options\n\tif (!filename) throw new TypeError('Backup filename cannot be an empty string');\n\tif (filename === ':memory:') throw new TypeError('Invalid backup filename \":memory:\"');\n\tif (typeof attachedName !== 'string') throw new TypeError('Expected the \"attached\" option to be a string');\n\tif (!attachedName) throw new TypeError('The \"attached\" option cannot be an empty string');\n\tif (handler != null && typeof handler !== 'function') throw new TypeError('Expected the \"progress\" option to be a function');\n\n\t// Make sure the specified directory exists\n\tawait fsAccess(path.dirname(filename)).catch(() => {\n\t\tthrow new TypeError('Cannot save backup because the directory does not exist');\n\t});\n\n\tconst isNewFile = await fsAccess(filename).then(() => false, () => true);\n\treturn runBackup(this[cppdb].backup(this, attachedName, filename, isNewFile), handler || null);\n};\n\nconst runBackup = (backup, handler) => {\n\tlet rate = 0;\n\tlet useDefault = true;\n\n\treturn new Promise((resolve, reject) => {\n\t\tsetImmediate(function step() {\n\t\t\ttry {\n\t\t\t\tconst progress = backup.transfer(rate);\n\t\t\t\tif (!progress.remainingPages) {\n\t\t\t\t\tbackup.close();\n\t\t\t\t\tresolve(progress);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (useDefault) {\n\t\t\t\t\tuseDefault = false;\n\t\t\t\t\trate = 100;\n\t\t\t\t}\n\t\t\t\tif (handler) {\n\t\t\t\t\tconst ret = handler(progress);\n\t\t\t\t\tif (ret !== undefined) {\n\t\t\t\t\t\tif (typeof ret === 'number' && ret === ret) rate = Math.max(0, Math.min(0x7fffffff, Math.round(ret)));\n\t\t\t\t\t\telse throw new TypeError('Expected progress callback to return a number or undefined');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tsetImmediate(step);\n\t\t\t} catch (err) {\n\t\t\t\tbackup.close();\n\t\t\t\treject(err);\n\t\t\t}\n\t\t});\n\t});\n};\n","'use strict';\nconst { cppdb } = require('../util');\n\nmodule.exports = function serialize(options) {\n\tif (options == null) options = {};\n\n\t// Validate arguments\n\tif (typeof options !== 'object') throw new TypeError('Expected first argument to be an options object');\n\n\t// Interpret and validate options\n\tconst attachedName = 'attached' in options ? options.attached : 'main';\n\tif (typeof attachedName !== 'string') throw new TypeError('Expected the \"attached\" option to be a string');\n\tif (!attachedName) throw new TypeError('The \"attached\" option cannot be an empty string');\n\n\treturn this[cppdb].serialize(attachedName);\n};\n","'use strict';\nconst { getBooleanOption, cppdb } = require('../util');\n\nmodule.exports = function defineFunction(name, options, fn) {\n\t// Apply defaults\n\tif (options == null) options = {};\n\tif (typeof options === 'function') { fn = options; options = {}; }\n\n\t// Validate arguments\n\tif (typeof name !== 'string') throw new TypeError('Expected first argument to be a string');\n\tif (typeof fn !== 'function') throw new TypeError('Expected last argument to be a function');\n\tif (typeof options !== 'object') throw new TypeError('Expected second argument to be an options object');\n\tif (!name) throw new TypeError('User-defined function name cannot be an empty string');\n\n\t// Interpret options\n\tconst safeIntegers = 'safeIntegers' in options ? +getBooleanOption(options, 'safeIntegers') : 2;\n\tconst deterministic = getBooleanOption(options, 'deterministic');\n\tconst directOnly = getBooleanOption(options, 'directOnly');\n\tconst varargs = getBooleanOption(options, 'varargs');\n\tlet argCount = -1;\n\n\t// Determine argument count\n\tif (!varargs) {\n\t\targCount = fn.length;\n\t\tif (!Number.isInteger(argCount) || argCount < 0) throw new TypeError('Expected function.length to be a positive integer');\n\t\tif (argCount > 100) throw new RangeError('User-defined functions cannot have more than 100 arguments');\n\t}\n\n\tthis[cppdb].function(fn, name, argCount, safeIntegers, deterministic, directOnly);\n\treturn this;\n};\n","'use strict';\nconst { getBooleanOption, cppdb } = require('../util');\n\nmodule.exports = function defineAggregate(name, options) {\n\t// Validate arguments\n\tif (typeof name !== 'string') throw new TypeError('Expected first argument to be a string');\n\tif (typeof options !== 'object' || options === null) throw new TypeError('Expected second argument to be an options object');\n\tif (!name) throw new TypeError('User-defined function name cannot be an empty string');\n\n\t// Interpret options\n\tconst start = 'start' in options ? options.start : null;\n\tconst step = getFunctionOption(options, 'step', true);\n\tconst inverse = getFunctionOption(options, 'inverse', false);\n\tconst result = getFunctionOption(options, 'result', false);\n\tconst safeIntegers = 'safeIntegers' in options ? +getBooleanOption(options, 'safeIntegers') : 2;\n\tconst deterministic = getBooleanOption(options, 'deterministic');\n\tconst directOnly = getBooleanOption(options, 'directOnly');\n\tconst varargs = getBooleanOption(options, 'varargs');\n\tlet argCount = -1;\n\n\t// Determine argument count\n\tif (!varargs) {\n\t\targCount = Math.max(getLength(step), inverse ? getLength(inverse) : 0);\n\t\tif (argCount > 0) argCount -= 1;\n\t\tif (argCount > 100) throw new RangeError('User-defined functions cannot have more than 100 arguments');\n\t}\n\n\tthis[cppdb].aggregate(start, step, inverse, result, name, argCount, safeIntegers, deterministic, directOnly);\n\treturn this;\n};\n\nconst getFunctionOption = (options, key, required) => {\n\tconst value = key in options ? options[key] : null;\n\tif (typeof value === 'function') return value;\n\tif (value != null) throw new TypeError(`Expected the \"${key}\" option to be a function`);\n\tif (required) throw new TypeError(`Missing required option \"${key}\"`);\n\treturn null;\n};\n\nconst getLength = ({ length }) => {\n\tif (Number.isInteger(length) && length >= 0) return length;\n\tthrow new TypeError('Expected function.length to be a positive integer');\n};\n","'use strict';\nconst { cppdb } = require('../util');\n\nmodule.exports = function defineTable(name, factory) {\n\t// Validate arguments\n\tif (typeof name !== 'string') throw new TypeError('Expected first argument to be a string');\n\tif (!name) throw new TypeError('Virtual table module name cannot be an empty string');\n\n\t// Determine whether the module is eponymous-only or not\n\tlet eponymous = false;\n\tif (typeof factory === 'object' && factory !== null) {\n\t\teponymous = true;\n\t\tfactory = defer(parseTableDefinition(factory, 'used', name));\n\t} else {\n\t\tif (typeof factory !== 'function') throw new TypeError('Expected second argument to be a function or a table definition object');\n\t\tfactory = wrapFactory(factory);\n\t}\n\n\tthis[cppdb].table(factory, name, eponymous);\n\treturn this;\n};\n\nfunction wrapFactory(factory) {\n\treturn function virtualTableFactory(moduleName, databaseName, tableName, ...args) {\n\t\tconst thisObject = {\n\t\t\tmodule: moduleName,\n\t\t\tdatabase: databaseName,\n\t\t\ttable: tableName,\n\t\t};\n\n\t\t// Generate a new table definition by invoking the factory\n\t\tconst def = apply.call(factory, thisObject, args);\n\t\tif (typeof def !== 'object' || def === null) {\n\t\t\tthrow new TypeError(`Virtual table module \"${moduleName}\" did not return a table definition object`);\n\t\t}\n\n\t\treturn parseTableDefinition(def, 'returned', moduleName);\n\t};\n}\n\nfunction parseTableDefinition(def, verb, moduleName) {\n\t// Validate required properties\n\tif (!hasOwnProperty.call(def, 'rows')) {\n\t\tthrow new TypeError(`Virtual table module \"${moduleName}\" ${verb} a table definition without a \"rows\" property`);\n\t}\n\tif (!hasOwnProperty.call(def, 'columns')) {\n\t\tthrow new TypeError(`Virtual table module \"${moduleName}\" ${verb} a table definition without a \"columns\" property`);\n\t}\n\n\t// Validate \"rows\" property\n\tconst rows = def.rows;\n\tif (typeof rows !== 'function' || Object.getPrototypeOf(rows) !== GeneratorFunctionPrototype) {\n\t\tthrow new TypeError(`Virtual table module \"${moduleName}\" ${verb} a table definition with an invalid \"rows\" property (should be a generator function)`);\n\t}\n\n\t// Validate \"columns\" property\n\tlet columns = def.columns;\n\tif (!Array.isArray(columns) || !(columns = [...columns]).every(x => typeof x === 'string')) {\n\t\tthrow new TypeError(`Virtual table module \"${moduleName}\" ${verb} a table definition with an invalid \"columns\" property (should be an array of strings)`);\n\t}\n\tif (columns.length !== new Set(columns).size) {\n\t\tthrow new TypeError(`Virtual table module \"${moduleName}\" ${verb} a table definition with duplicate column names`);\n\t}\n\tif (!columns.length) {\n\t\tthrow new RangeError(`Virtual table module \"${moduleName}\" ${verb} a table definition with zero columns`);\n\t}\n\n\t// Validate \"parameters\" property\n\tlet parameters;\n\tif (hasOwnProperty.call(def, 'parameters')) {\n\t\tparameters = def.parameters;\n\t\tif (!Array.isArray(parameters) || !(parameters = [...parameters]).every(x => typeof x === 'string')) {\n\t\t\tthrow new TypeError(`Virtual table module \"${moduleName}\" ${verb} a table definition with an invalid \"parameters\" property (should be an array of strings)`);\n\t\t}\n\t} else {\n\t\tparameters = inferParameters(rows);\n\t}\n\tif (parameters.length !== new Set(parameters).size) {\n\t\tthrow new TypeError(`Virtual table module \"${moduleName}\" ${verb} a table definition with duplicate parameter names`);\n\t}\n\tif (parameters.length > 32) {\n\t\tthrow new RangeError(`Virtual table module \"${moduleName}\" ${verb} a table definition with more than the maximum number of 32 parameters`);\n\t}\n\tfor (const parameter of parameters) {\n\t\tif (columns.includes(parameter)) {\n\t\t\tthrow new TypeError(`Virtual table module \"${moduleName}\" ${verb} a table definition with column \"${parameter}\" which was ambiguously defined as both a column and parameter`);\n\t\t}\n\t}\n\n\t// Validate \"safeIntegers\" option\n\tlet safeIntegers = 2;\n\tif (hasOwnProperty.call(def, 'safeIntegers')) {\n\t\tconst bool = def.safeIntegers;\n\t\tif (typeof bool !== 'boolean') {\n\t\t\tthrow new TypeError(`Virtual table module \"${moduleName}\" ${verb} a table definition with an invalid \"safeIntegers\" property (should be a boolean)`);\n\t\t}\n\t\tsafeIntegers = +bool;\n\t}\n\n\t// Validate \"directOnly\" option\n\tlet directOnly = false;\n\tif (hasOwnProperty.call(def, 'directOnly')) {\n\t\tdirectOnly = def.directOnly;\n\t\tif (typeof directOnly !== 'boolean') {\n\t\t\tthrow new TypeError(`Virtual table module \"${moduleName}\" ${verb} a table definition with an invalid \"directOnly\" property (should be a boolean)`);\n\t\t}\n\t}\n\n\t// Generate SQL for the virtual table definition\n\tconst columnDefinitions = [\n\t\t...parameters.map(identifier).map(str => `${str} HIDDEN`),\n\t\t...columns.map(identifier),\n\t];\n\treturn [\n\t\t`CREATE TABLE x(${columnDefinitions.join(', ')});`,\n\t\twrapGenerator(rows, new Map(columns.map((x, i) => [x, parameters.length + i])), moduleName),\n\t\tparameters,\n\t\tsafeIntegers,\n\t\tdirectOnly,\n\t];\n}\n\nfunction wrapGenerator(generator, columnMap, moduleName) {\n\treturn function* virtualTable(...args) {\n\t\t/*\n\t\t\tWe must defensively clone any buffers in the arguments, because\n\t\t\totherwise the generator could mutate one of them, which would cause\n\t\t\tus to return incorrect values for hidden columns, potentially\n\t\t\tcorrupting the database.\n\t\t */\n\t\tconst output = args.map(x => Buffer.isBuffer(x) ? Buffer.from(x) : x);\n\t\tfor (let i = 0; i < columnMap.size; ++i) {\n\t\t\toutput.push(null); // Fill with nulls to prevent gaps in array (v8 optimization)\n\t\t}\n\t\tfor (const row of generator(...args)) {\n\t\t\tif (Array.isArray(row)) {\n\t\t\t\textractRowArray(row, output, columnMap.size, moduleName);\n\t\t\t\tyield output;\n\t\t\t} else if (typeof row === 'object' && row !== null) {\n\t\t\t\textractRowObject(row, output, columnMap, moduleName);\n\t\t\t\tyield output;\n\t\t\t} else {\n\t\t\t\tthrow new TypeError(`Virtual table module \"${moduleName}\" yielded something that isn't a valid row object`);\n\t\t\t}\n\t\t}\n\t};\n}\n\nfunction extractRowArray(row, output, columnCount, moduleName) {\n\tif (row.length !== columnCount) {\n\t\tthrow new TypeError(`Virtual table module \"${moduleName}\" yielded a row with an incorrect number of columns`);\n\t}\n\tconst offset = output.length - columnCount;\n\tfor (let i = 0; i < columnCount; ++i) {\n\t\toutput[i + offset] = row[i];\n\t}\n}\n\nfunction extractRowObject(row, output, columnMap, moduleName) {\n\tlet count = 0;\n\tfor (const key of Object.keys(row)) {\n\t\tconst index = columnMap.get(key);\n\t\tif (index === undefined) {\n\t\t\tthrow new TypeError(`Virtual table module \"${moduleName}\" yielded a row with an undeclared column \"${key}\"`);\n\t\t}\n\t\toutput[index] = row[key];\n\t\tcount += 1;\n\t}\n\tif (count !== columnMap.size) {\n\t\tthrow new TypeError(`Virtual table module \"${moduleName}\" yielded a row with missing columns`);\n\t}\n}\n\nfunction inferParameters({ length }) {\n\tif (!Number.isInteger(length) || length < 0) {\n\t\tthrow new TypeError('Expected function.length to be a positive integer');\n\t}\n\tconst params = [];\n\tfor (let i = 0; i < length; ++i) {\n\t\tparams.push(`$${i + 1}`);\n\t}\n\treturn params;\n}\n\nconst { hasOwnProperty } = Object.prototype;\nconst { apply } = Function.prototype;\nconst GeneratorFunctionPrototype = Object.getPrototypeOf(function*(){});\nconst identifier = str => `\"${str.replace(/\"/g, '\"\"')}\"`;\nconst defer = x => () => x;\n","'use strict';\nconst DatabaseInspection = function Database() {};\n\nmodule.exports = function inspect(depth, opts) {\n\treturn Object.assign(new DatabaseInspection(), this);\n};\n\n","'use strict';\nconst fs = require('fs');\nconst path = require('path');\nconst util = require('./util');\nconst SqliteError = require('./sqlite-error');\n\nlet DEFAULT_ADDON;\n\nfunction Database(filenameGiven, options) {\n\tif (new.target == null) {\n\t\treturn new Database(filenameGiven, options);\n\t}\n\n\t// Apply defaults\n\tlet buffer;\n\tif (Buffer.isBuffer(filenameGiven)) {\n\t\tbuffer = filenameGiven;\n\t\tfilenameGiven = ':memory:';\n\t}\n\tif (filenameGiven == null) filenameGiven = '';\n\tif (options == null) options = {};\n\n\t// Validate arguments\n\tif (typeof filenameGiven !== 'string') throw new TypeError('Expected first argument to be a string');\n\tif (typeof options !== 'object') throw new TypeError('Expected second argument to be an options object');\n\tif ('readOnly' in options) throw new TypeError('Misspelled option \"readOnly\" should be \"readonly\"');\n\tif ('memory' in options) throw new TypeError('Option \"memory\" was removed in v7.0.0 (use \":memory:\" filename instead)');\n\n\t// Interpret options\n\tconst filename = filenameGiven.trim();\n\tconst anonymous = filename === '' || filename === ':memory:';\n\tconst readonly = util.getBooleanOption(options, 'readonly');\n\tconst fileMustExist = util.getBooleanOption(options, 'fileMustExist');\n\tconst timeout = 'timeout' in options ? options.timeout : 5000;\n\tconst verbose = 'verbose' in options ? options.verbose : null;\n\tconst nativeBinding = 'nativeBinding' in options ? options.nativeBinding : null;\n\n\t// Validate interpreted options\n\tif (readonly && anonymous && !buffer) throw new TypeError('In-memory/temporary databases cannot be readonly');\n\tif (!Number.isInteger(timeout) || timeout < 0) throw new TypeError('Expected the \"timeout\" option to be a positive integer');\n\tif (timeout > 0x7fffffff) throw new RangeError('Option \"timeout\" cannot be greater than 2147483647');\n\tif (verbose != null && typeof verbose !== 'function') throw new TypeError('Expected the \"verbose\" option to be a function');\n\tif (nativeBinding != null && typeof nativeBinding !== 'string' && typeof nativeBinding !== 'object') throw new TypeError('Expected the \"nativeBinding\" option to be a string or addon object');\n\n\t// Load the native addon\n\tlet addon;\n\tif (nativeBinding == null) {\n\t\taddon = DEFAULT_ADDON || (DEFAULT_ADDON = require('bindings')('better_sqlite3.node'));\n\t} else if (typeof nativeBinding === 'string') {\n\t\t// See <https://webpack.js.org/api/module-variables/#__non_webpack_require__-webpack-specific>\n\t\tconst requireFunc = typeof __non_webpack_require__ === 'function' ? __non_webpack_require__ : require;\n\t\taddon = requireFunc(path.resolve(nativeBinding).replace(/(\\.node)?$/, '.node'));\n\t} else {\n\t\t// See <https://github.com/WiseLibs/better-sqlite3/issues/972>\n\t\taddon = nativeBinding;\n\t}\n\n\tif (!addon.isInitialized) {\n\t\taddon.setErrorConstructor(SqliteError);\n\t\taddon.isInitialized = true;\n\t}\n\n\t// Make sure the specified directory exists\n\tif (!anonymous && !fs.existsSync(path.dirname(filename))) {\n\t\tthrow new TypeError('Cannot open database because the directory does not exist');\n\t}\n\n\tObject.defineProperties(this, {\n\t\t[util.cppdb]: { value: new addon.Database(filename, filenameGiven, anonymous, readonly, fileMustExist, timeout, verbose || null, buffer || null) },\n\t\t...wrappers.getters,\n\t});\n}\n\nconst wrappers = require('./methods/wrappers');\nDatabase.prototype.prepare = wrappers.prepare;\nDatabase.prototype.transaction = require('./methods/transaction');\nDatabase.prototype.pragma = require('./methods/pragma');\nDatabase.prototype.backup = require('./methods/backup');\nDatabase.prototype.serialize = require('./methods/serialize');\nDatabase.prototype.function = require('./methods/function');\nDatabase.prototype.aggregate = require('./methods/aggregate');\nDatabase.prototype.table = require('./methods/table');\nDatabase.prototype.loadExtension = wrappers.loadExtension;\nDatabase.prototype.exec = wrappers.exec;\nDatabase.prototype.close = wrappers.close;\nDatabase.prototype.defaultSafeIntegers = wrappers.defaultSafeIntegers;\nDatabase.prototype.unsafeMode = wrappers.unsafeMode;\nDatabase.prototype[util.inspect] = require('./methods/inspect');\n\nmodule.exports = Database;\n","'use strict';\nmodule.exports = require('./database');\nmodule.exports.SqliteError = require('./sqlite-error');\n","import { Hono } from 'hono';\nimport { cors } from 'hono/cors';\nimport { logger } from 'hono/logger';\nimport net from 'node:net';\nimport { analyzeRoute, healthRoute, reviewRoute } from './routes';\nimport { createConsoleRouter } from './console';\n\nexport function createApp(): Hono {\n const app = new Hono();\n\n // Middleware\n app.use('*', cors({ origin: '*', allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'], allowHeaders: ['*'] }));\n app.use('*', logger());\n\n // Routes\n app.get('/api/v1/health', healthRoute);\n app.post('/api/v1/analyze', analyzeRoute);\n app.post('/api/v1/review', reviewRoute);\n\n // Policy Console(浏览器策略管控台,挂载在 /console 前缀)\n app.route('/console', createConsoleRouter());\n // /console/ → /console(hono route 挂载后带尾斜杠匹配行为不一致,加重定向兼容)\n app.get('/console/', (c) => c.redirect('/console'));\n\n return app;\n}\n\n/**\n * 从 startPort 开始找第一个可用端口(照搬 OpenDesk findFreePort 策略)。\n * 用 net.createServer().listen 试端口,成功立刻 close 返回该端口;全占 fallback\n * 到 startPort(让 hono 自己报错,不静默换到离谱端口)。\n *\n * 为什么需要:默认 9090 被占时服务起不来、xiaoO 全 fail-closed。预探测找空闲端口,\n * 配合消费方探测兜底(bridge.ts probeAgentMossUrl),保证服务总能起、消费方能连上。\n */\nexport async function findFreePort(\n startPort: number,\n host: string = '127.0.0.1',\n scan: number = 100,\n): Promise<number> {\n for (let port = startPort; port < startPort + scan; port++) {\n const free = await new Promise<boolean>((resolve) => {\n const server = net.createServer();\n server.listen(port, host, () => {\n server.close(() => resolve(true));\n });\n server.on('error', () => resolve(false));\n });\n if (free) {\n if (port !== startPort) {\n console.warn(`[AgentMoss] Port ${startPort} in use, using ${port} instead`);\n }\n return port;\n }\n }\n return startPort; // fallback\n}\n\nexport async function startServer(\n host = '127.0.0.1',\n port = 9090,\n): Promise<{ serve: () => Promise<void>; port: number }> {\n const actualPort = await findFreePort(port, host);\n const app = createApp();\n return {\n port: actualPort,\n serve: async () => {\n console.log(`AgentMoss HTTP server on ${host}:${actualPort}`);\n // @hono/node-server 动态 import(ESM 下 require 不可用)\n // 必须 await:honoServe 会起阻塞循环让进程常驻,未 await 时 main() 返回后 Node\n // 见无 pending 任务直接 exit 0,server 起不来。\n const { serve: honoServe } = await import('@hono/node-server');\n honoServe({ fetch: app.fetch, hostname: host, port: actualPort });\n },\n };\n}\n","import type { Context } from 'hono';\nimport { AnalyzeRequestSchema, AnalyzeResponseSchema, HealthResponseSchema, ReviewRequestSchema, ReviewResponseSchema } from './models';\nimport { runAnalysis } from './engine/coordinator';\nimport { reportEnforcementEvent } from './actrail';\nimport { ChainStateStore, FormalEngine, StatefulChainTracker } from './engine/formal-engine';\nimport { mineDangerousPatterns } from './engine/formal-engine/pattern_miner';\nimport { loadAgentGateSessions } from './agent-gate-reader';\n\nexport async function healthRoute(c: Context) {\n return c.json(HealthResponseSchema.parse({\n instance: process.env.AGENT_MOSS_INSTANCE || '',\n }));\n}\n\nexport async function analyzeRoute(c: Context) {\n const t0 = performance.now();\n\n try {\n const body = await c.req.json();\n const req = AnalyzeRequestSchema.parse(body);\n\n // OS auto-detect\n let osType = req.os_type;\n if (!osType) {\n osType = process.platform === 'win32' ? 'windows' : 'linux';\n }\n\n // agent_id 透传(先解析出来供 stateful 增量使用;优先顶层,兜底 metadata.agent_type)\n const agentId = req.agent_id || (req.metadata as any)?.agent_type || '';\n\n const result = await runAnalysis({\n sessionId: req.session_id,\n promptSession: req.prompt_session,\n actionHistory: req.action_history.map(h => ({\n actionType: h.action_type,\n actionDetail: h.action_detail,\n })),\n sessionHistory: (req.session_history || []).map(s => ({\n sessionId: s.session_id,\n actionHistory: (s.action_history || []).map(h => ({\n actionType: h.action_type,\n actionDetail: h.action_detail,\n })),\n })),\n aNext: {\n actionType: req.a_next.action_type,\n actionDetail: req.a_next.action_detail,\n },\n reason: req.reason,\n osType,\n cwd: req.cwd,\n // agent_id:AgentGate V1 normalizer 历史上把 agent_type 塞 metadata,\n // 顶层为空时兜底(OpenDesk 的 agent-moss 需 agent_id 加载专属规则)。\n agentId,\n llmConfig: (req.metadata as any)?.llm_config,\n llmLogPath: (req.metadata as any)?.llm_log_path,\n });\n\n const durationMs = performance.now() - t0;\n\n // Report enforcement event to AcTrail (fire-and-forget)\n try {\n reportEnforcementEvent({\n traceId: req.session_id,\n decision: result.allowed ? 'allow' : 'deny',\n toolName: req.a_next.action_type,\n toolCommand: req.a_next.action_detail,\n sessionId: req.session_id,\n prompt: req.prompt_session,\n riskLevel: result.riskLevel,\n riskType: result.riskType,\n reason: result.reason,\n violatedLayers: result.violatedLayers,\n confidence: result.confidence,\n durationMs: Math.round(durationMs * 10) / 10,\n });\n } catch { /* non-fatal, never block response */ }\n\n // ========== L2.4 stateful incremental(有状态实时判定,可选启用) ==========\n // 镜像 Python routes.py:metadata.stateful_incremental=true 时把当前动作 push 进\n // 该 agent 的持久化时间线;补全历史前序链 → 覆盖为 Deny(violated_layers 含 2.4-stateful)。\n const meta = (req.metadata || {}) as Record<string, unknown>;\n const incEnabled = String(meta.stateful_incremental || '').toLowerCase();\n if (incEnabled === '1' || incEnabled === 'true' || incEnabled === 'yes' || incEnabled === 'on') {\n try {\n const store = getChainStateStoreFor(agentId);\n const inc = store.applyAction(agentId, {\n actionType: req.a_next.action_type,\n actionDetail: req.a_next.action_detail,\n }, req.session_id, Boolean(meta.is_error));\n const judgment = incMatchedToDeny(inc);\n if (judgment) {\n const layers = [...result.violatedLayers];\n if (!layers.includes('2.4-stateful')) layers.push('2.4-stateful');\n console.error(\n `[AgentMoss] stateful 增量拦截: agent=${agentId || '-'} property=${judgment.property_id} risk=${judgment.risk_level}`,\n );\n return c.json(\n AnalyzeResponseSchema.parse({\n decision: 'Deny',\n reason: judgment.reason,\n risk_level: judgment.risk_level,\n risk_type: 'formal_verification',\n violated_layers: layers,\n policy: '',\n violated_policy: '',\n confidence: 90,\n analysis_duration_ms: Math.round((performance.now() - t0) * 10) / 10,\n })\n );\n }\n } catch (err) {\n console.error('[AgentMoss] stateful incremental error (non-fatal):', err);\n }\n }\n\n return c.json(\n AnalyzeResponseSchema.parse({\n decision: result.allowed ? 'Allow' : 'Deny',\n reason: result.reason,\n risk_level: result.riskLevel,\n risk_type: result.riskType,\n violated_layers: result.violatedLayers,\n policy: '',\n violated_policy: '',\n confidence: result.confidence,\n analysis_duration_ms: Math.round(durationMs * 10) / 10,\n })\n );\n } catch (err) {\n console.error('[AgentMoss] Analysis error:', err);\n if (err instanceof SyntaxError) {\n return c.json({ error: 'Invalid JSON', detail: err.message }, 400);\n }\n if ((err as any)?.issues) {\n return c.json({ error: 'Validation error', detail: (err as any).issues }, 400);\n }\n return c.json({ error: 'Internal error', detail: String(err) }, 500);\n }\n}\n\n// ===========================================================================\n// POST /api/v1/review 低频全量回顾(镜像 Python routes.py review 语义)\n// ===========================================================================\n\nlet reviewStore: ChainStateStore | null = null;\n\nfunction getChainStateStoreFor(_agentId: string): ChainStateStore {\n if (!reviewStore) reviewStore = new ChainStateStore();\n return reviewStore;\n}\n\n/** 把 stateful advance 的结果转成补充 Deny 判定(无命中返回 null)。 */\nfunction incMatchedToDeny(\n inc: { matched?: { chainId: string; riskLevel: string; reason: string } | null; exfil?: { reason: string; risk_level: string }[] },\n): { property_id: string; reason: string; risk_level: string } | null {\n if (inc.matched) {\n return {\n property_id: 'cross-' + inc.matched.chainId,\n reason: inc.matched.reason,\n risk_level: inc.matched.riskLevel,\n };\n }\n if (inc.exfil && inc.exfil.length > 0) {\n return {\n property_id: 'sensitive-data-exfil',\n reason: inc.exfil[0].reason,\n risk_level: inc.exfil[0].risk_level,\n };\n }\n return null;\n}\n\nexport async function reviewRoute(c: Context) {\n const t0 = performance.now();\n try {\n const body = await c.req.json();\n const req = ReviewRequestSchema.parse(body);\n const agentId = req.agent_id || 'default';\n const store = getChainStateStoreFor(agentId);\n let tracker = store.load(agentId);\n if (!tracker) {\n tracker = new StatefulChainTracker(agentId);\n }\n\n // 1. 读取历史(db_path 直读 > 显式 sessions)\n let sessions: { sessionId?: string; actionHistory?: { actionType: string; actionDetail: string }[] }[] = [];\n if (req.db_path) {\n sessions = loadAgentGateSessions(req.db_path);\n if (sessions.length === 0) sessions = (req.sessions || []).map(s => ({\n sessionId: s.session_id,\n actionHistory: s.action_history.map(a => ({ actionType: a.action_type, actionDetail: a.action_detail })),\n }));\n } else {\n sessions = (req.sessions || []).map(s => ({\n sessionId: s.session_id,\n actionHistory: s.action_history.map(a => ({ actionType: a.action_type, actionDetail: a.action_detail })),\n }));\n }\n const added = sessions.length > 0 ? tracker.seed(sessions) : 0;\n store.save(tracker);\n\n // 2. 全量 FormalEngine 验证\n let verified = true;\n const violations: { property_id: string; reason: string; risk_level: string }[] = [];\n if (sessions.length > 0 || tracker.nodes.length > 0) {\n const eng = new FormalEngine();\n const full = eng.verify(\n sessions.map(s => ({ sessionId: s.sessionId, actionHistory: s.actionHistory })),\n req.a_next ? { actionType: req.a_next.action_type, actionDetail: req.a_next.action_detail } : undefined,\n );\n verified = full.verified;\n for (const v of full.violations) {\n violations.push({ property_id: v.propertyId, reason: v.reason, risk_level: v.riskLevel });\n }\n }\n\n // 3. 提取待攻击前序\n const pending = tracker.pendingPrefixes.map(p => ({\n chain_id: p.chainId,\n matched: p.matched,\n next_stage: p.nextStage,\n risk_level: p.riskLevel,\n }));\n\n // 4. 数据驱动发现:跨 session 频繁危险组合(预置链外新形态)\n let discovered: { pattern: string[]; support: number; risk: string; reason: string }[] = [];\n if (sessions.length > 0) {\n try {\n discovered = mineDangerousPatterns(sessions, 2);\n } catch {\n // 挖掘失败不阻塞 review\n }\n }\n\n return c.json(ReviewResponseSchema.parse({\n agent_id: agentId,\n seeded_nodes: added,\n verified,\n violations,\n pending_prefixes: pending,\n state_nodes: tracker.nodes.length,\n discovered_patterns: discovered,\n }));\n } catch (err) {\n console.error('[AgentMoss] Review error:', err);\n return c.json({ error: 'Internal error', detail: String(err) }, 500);\n }\n}\n\n","import { z } from 'zod';\nimport { version as PACKAGE_VERSION } from './package-json.js';\n\n/** Single action in history or next action */\nexport const ActionItemSchema = z.object({\n action_type: z.string().describe('Action type, e.g. bash, file_read, file_write'),\n action_detail: z.string().describe('Action detail / command content'),\n});\n\n/** A single user prompt turn with the actions it triggered (interleaved time order). */\nexport const PromptTurnSchema = z.object({\n text: z.string().default('').describe('User prompt text at this turn'),\n actions: z.array(ActionItemSchema).default([]).describe('Actions triggered by this prompt, in order, until the next prompt'),\n});\n\nexport const AnalyzeRequestSchema = z.object({\n session_id: z.string().describe('Session / agent unique identifier'),\n prompt_session: z.string().default('').describe('User original prompt (most recent user message; backward compat)'),\n prompt_history: z.array(PromptTurnSchema).default([]).describe('Full interleaved prompt history (ordered turns, each with its triggered actions). Optional; empty = fall back to prompt_session only.'),\n action_history: z.array(ActionItemSchema).default([]).describe('Historical action sequence'),\n session_history: z.array(z.object({\n session_id: z.string(),\n action_history: z.array(ActionItemSchema).default([]),\n })).default([]).describe('Multi-session historical actions (optional): for L2.4 formal engine cross-session combo-chain / sensitive-data-flow verification. Provided by caller (incl. future agentgate).'),\n a_next: ActionItemSchema.describe('Next action to be executed'),\n reason: z.string().default('').describe('Reason for executing this action'),\n os_type: z.string().default('').describe(\"OS type: 'linux', 'windows', or empty for auto-detect\"),\n cwd: z.string().default('').describe('Current working directory'),\n agent_id: z.string().default('').describe(\"Caller agent identifier, e.g. 'xiaoo' / 'opencode' / 'opendesk'. Empty = generic mode (no agent-specific rules).\"),\n metadata: z.record(z.unknown()).optional().describe('Extended metadata'),\n});\n\nexport const AnalyzeResponseSchema = z.object({\n decision: z.enum(['Allow', 'Deny']).describe('Allow or Deny'),\n reason: z.string().describe('Decision reason'),\n risk_level: z.enum(['low', 'medium', 'high', 'critical']).default('low'),\n risk_type: z.string().default(''),\n violated_layers: z.array(z.string()).default([]),\n policy: z.string().default(''),\n violated_policy: z.string().default(''),\n confidence: z.number().int().min(0).max(100).default(100),\n analysis_duration_ms: z.number().default(0),\n});\n\nexport const HealthResponseSchema = z.object({\n status: z.string().default('healthy'),\n version: z.string().default(PACKAGE_VERSION),\n // 归属实例标识:值来自 env AGENT_MOSS_INSTANCE(spawn/systemd 注入),默认空串。\n // 多个 agentmoss 同机并存时,调用方按 instance 过滤避免连到别人的进程。\n // 空=未配置(独立部署或旧版),调用方可选择兼容或严格过滤。\n instance: z.string().default(''),\n});\n\n/** POST /api/v1/review 请求(低频全量回顾 + 状态重建)。镜像 Python ReviewRequest。 */\nexport const ReviewRequestSchema = z.object({\n agent_id: z.string().default('').describe('目标 agent 标识(决定状态库分桶)'),\n db_path: z.string().default('').describe('AgentGate 本地存储路径(SQLite 文件 或 tool_calls JSON 目录);为空则用 sessions'),\n sessions: z.array(z.object({\n session_id: z.string(),\n action_history: z.array(ActionItemSchema).default([]),\n })).default([]).describe('多 session 历史动作(替代/兜底 db_path)'),\n a_next: ActionItemSchema.optional().describe('可选:seed 后连同当前动作一起判定'),\n is_error: z.boolean().default(false).describe('当前动作执行是否失败'),\n output_pending: z.boolean().default(false).describe('返回前序链清单 pending_prefixes'),\n});\n\n/** POST /api/v1/review 响应。镜像 Python ReviewResponse。 */\nexport const ReviewResponseSchema = z.object({\n agent_id: z.string().default(''),\n seeded_nodes: z.number().default(0),\n verified: z.boolean().default(true),\n violations: z.array(z.record(z.unknown())).default([]),\n pending_prefixes: z.array(z.record(z.unknown())).default([]),\n state_nodes: z.number().default(0),\n discovered_patterns: z.array(z.record(z.unknown())).default([]).describe('数据驱动发现:跨 session 频繁危险组合(预置链盲区,PatternMiner)'),\n});\n\nexport type ActionItem = z.infer<typeof ActionItemSchema>;\nexport type AnalyzeRequest = z.infer<typeof AnalyzeRequestSchema>;\nexport type AnalyzeResponse = z.infer<typeof AnalyzeResponseSchema>;\nexport type HealthResponse = z.infer<typeof HealthResponseSchema>;\nexport type ReviewRequest = z.infer<typeof ReviewRequestSchema>;\nexport type ReviewResponse = z.infer<typeof ReviewResponseSchema>;\n","/**\n * Single source of truth for the package version.\n * Read from package.json at runtime using createRequire — works in both ESM and bundled environments.\n */\nimport { createRequire } from 'module';\n\nconst require = createRequire(import.meta.url);\n// Resolve relative to this source file's location → ts/package.json\nconst pkg = require('../package.json');\n\n/** Version string from package.json — the ONLY place version is defined */\nexport const version: string = pkg.version;\n","import { SecurityJudgment } from './types';\nimport { runHeuristicCheck, isInlineScriptCommand, DANGEROUS_PATTERNS } from './heuristic';\nimport { runLogicCheck, isWriteOperation } from './logic-rules';\nimport { analyzeInlineScript, isLiteralTextCommand } from './inline-analyzer';\nimport { runLLMAnalysis } from './llm-analyzer';\nimport { analyzeScriptContent as analyzeScriptChain, formatScriptChainForPrompt } from './script-content-analyzer';\nimport { isHeuristicEnabled, isLogicRulesEnabled, isLLMAvailable, isBrainEnabled } from '../config';\nimport { getAgentExtensions, mergeAgentExtensions } from '../agents';\nimport { getScenarioExtensions } from '../scenarios';\nimport { BrainRuleStore, PatternExtractor, checkBrainRules } from '../brain';\nimport { createBrainReviewer } from '../brain/reviewer';\nimport { FormalEngine } from './formal-engine';\n\nexport interface AnalysisInput {\n sessionId: string;\n promptSession: string;\n actionHistory: { actionType: string; actionDetail: string }[];\n /** 完整的交错历史 prompt(可选),每轮 {text, actions} 或纯文本 string(AgentGate v3 旧格式),按时间序。\n * 供 L2 意图一致性与 L3 语义分析使用;空则回退单条 promptSession。 */\n promptHistory?: ({ text: string; actions: { actionType: string; actionDetail: string }[] } | string)[];\n /** 多 session 历史动作(可选),每项 {sessionId, actionHistory}。供 L2.4 形式化引擎\n * 做跨会话组合链/敏感数据传播验证;缺省时仅用当前 session 构建行为图(向后兼容)。\n * 由调用方(含未来 agentgate 非侵入式采集)提供。 */\n sessionHistory?: { sessionId?: string; actionHistory: { actionType: string; actionDetail: string }[] }[];\n aNext: { actionType: string; actionDetail: string };\n reason: string;\n osType: string;\n cwd: string;\n /** 调用方 agent 标识(如 'xiaoo' / 'opencode' / 'opendesk')。空 = 通用模式。 */\n agentId: string;\n /** 调用方场景标识(如 'bank'),用于加载场景定制规则(客户沙箱的目录访问边界/禁 ssh 等)。\n * 空时兜底环境变量 AGENT_MOSS_SCENARIO(部署级,客户沙箱设一次,所有请求生效)。 */\n scenarioId?: string;\n /** 可选的 per-request LLM 配置覆盖(由 OpenDesk 按当前会话模型传入) */\n llmConfig?: { baseUrl: string; apiKey: string; model: string; provider?: string };\n /** 可选的 per-request LLM prompt 日志路径(来自调用方 env,per-request 注入。\n * 跟 llmConfig 同理:调用方子进程有 AGENT_MOSS_LOG_PATH env 但服务进程不一定有,\n * 通过 metadata 注入让服务端写 [LLM_PROMPT] 日志,对齐 py _log_prompt) */\n llmLogPath?: string;\n}\n\n// ========== 快速放行白名单 ==========\n\n/** 完全安全工具:跳过 Layer 2 + Layer 3 */\nconst FULLY_SAFE_TOOLS = new Set([\n 'ask_user_question', 'glob', 'list_dir', 'ls', 'count_text_length',\n 'filemgr-globfiles',\n]);\n\n/** 内置安全 Skill 白名单(通用 baseline,agent_ext.builtin_safe_skills 会追加)。\n * 测试可 import 此常量直接断言\"无 agentId 时白名单不含某 skill\",避免走 L3\n * LLM 调用导致测试脆弱(依赖 LLM 401 fail_open 兜底)。 */\nexport const TRUSTED_SKILLS_BASE = new Set<string>([]);\n\n/** 安全但可能访问敏感路径:跳过 Layer 3,保留 Layer 2 */\nconst READONLY_SENSITIVE_TOOLS = new Set([\n 'read', 'file_read', 'read_file', 'head', 'tail', 'grep',\n 'filemgr-readfile', 'filemgr-grepfiles',\n]);\n\n/** 完全安全 bash 子命令正则 */\nconst FULLY_SAFE_BASH_PATTERNS: RegExp[] = [\n /^ls(?:\\s|$)/i, /^dir(?:\\s|$)/i,\n /^pwd(?:\\s|$)/i, /^which\\s+/i, /^whereis\\s+/i, /^realpath\\s+/i,\n /^basename\\s+/i, /^dirname\\s+/i,\n /^file\\s+/i, /^stat\\s+/i, /^du(?:\\s|$)/i,\n /^echo\\s+/i, /^printf\\s+/i,\n /^type\\s+/i, /^command\\s+/i,\n // 系统信息查询(只读,不涉及文件/网络/权限)\n /^whoami(?:\\s|$)/i, /^id(?:\\s|$)/i,\n /^hostname(?:\\s|$)/i, /^uname(?:\\s|$)/i,\n /^date(?:\\s|$)/i, /^env(?:\\s|$)/i,\n /^printenv(?:\\s|$)/i, /^tty(?:\\s|$)/i,\n /^arch(?:\\s|$)/i, /^uptime(?:\\s|$)/i,\n /^groups(?:\\s|$)/i, /^logname(?:\\s|$)/i,\n];\n\n/** 安全但可能访问敏感路径的 bash 子命令正则 */\nconst READONLY_SENSITIVE_BASH_PATTERNS: RegExp[] = [\n /^cat\\s+/i, /^head(?:\\s|$)/i, /^tail(?:\\s|$)/i,\n /^less(?:\\s|$)/i, /^more(?:\\s|$)/i, /^wc(?:\\s|$)/i,\n /^grep(?:\\s|$)/i, /^find\\s+/i, /^ag(?:\\s|$)/i, /^rg(?:\\s|$)/i,\n /^awk\\s+/i, /^sed\\s+/i, /^cut\\s+/i, /^sort(?:\\s|$)/i, /^uniq(?:\\s|$)/i,\n];\n\n/** 提取管道和链式命令的第一段 */\nfunction extractFirstCommand(command: string): string {\n let main = command.split('|')[0].trim();\n for (const sep of ['&&', '||']) {\n const idx = main.indexOf(sep);\n if (idx !== -1) {\n main = main.substring(0, idx).trim();\n break;\n }\n }\n return main;\n}\n\n/** 从 OpenDesk 格式中提取实际命令 */\nfunction extractRawCommand(detail: string): string {\n const m = detail.match(/command=([^,]+)/);\n return m ? m[1].trim() : detail;\n}\n\nfunction matchesAny(cmd: string, patterns: RegExp[]): boolean {\n return patterns.some(p => p.test(cmd));\n}\n\n// ========== Brain(默认关闭,AGENT_MOSS_BRAIN_ENABLED=1 才启用) ==========\nlet _brainStore: BrainRuleStore | null = null;\nlet _brainExtractor: PatternExtractor | null = null;\nlet _brainInitialized = false;\n\nfunction getBrainStore(): BrainRuleStore | null {\n if (!isBrainEnabled()) return null;\n if (!_brainInitialized) {\n _brainStore = new BrainRuleStore();\n _brainExtractor = new PatternExtractor(_brainStore, { review: createBrainReviewer() });\n _brainInitialized = true;\n }\n return _brainStore;\n}\n\n/** 供测试隔离:重置 brain 单例 */\nexport function _resetBrainForTest(): void {\n _brainStore = null;\n _brainExtractor = null;\n _brainInitialized = false;\n}\n\n// ========== 三层防御协调器 ==========\n\n/**\n * Three-layer defense coordinator.\n * Layer 1 → fast-pass check → Layer 2 → Layer 3.\n * Fast-pass: whitelisted safe tools/commands skip L2+L3 or L3 only.\n */\n\n// 形式化引擎实例(L2.4):行为图 + 性质验证(跨会话组合链/敏感数据传播)。\n// 单 session 向后兼容(仅用 actionHistory),多 session 由 input.sessionHistory 提供。\nconst formalEngine = new FormalEngine();\n\nexport async function runAnalysis(input: AnalysisInput): Promise<SecurityJudgment> {\n // Layer 1: Feature-matching static detection (fast)\n const heuristicResult = isHeuristicEnabled() ? runHeuristicCheck(input) : null;\n\n // 内联脚本/文本输出命令 file_access 假阳性防护:不立即拦截,交 inline_analyzer 静态判定\n // 因为字符串字面量中的敏感路径(如 '/etc/shadow')不应被正则误拦截\n const isInlineScriptCmd = isInlineScriptCommand(input.aNext.actionDetail.toLowerCase());\n const isLiteralTextCmd = isLiteralTextCommand(input.aNext.actionDetail.toLowerCase());\n if (heuristicResult && !heuristicResult.allowed) {\n const skipInlineFileAccess = (isInlineScriptCmd || isLiteralTextCmd) && heuristicResult.riskType === 'file_access';\n if (!skipInlineFileAccess) {\n // 对齐 py coordinator.py:172-176 should_deny_l1:\n // high/critical 直接 Deny;\n // medium + file_access(敏感路径写)确定性拦截;\n // 其他 medium(如 git push --force / rm -f 单文件 / prompt 注入 repeat-instructions)\n // 不直接 Deny,fall-through 到 L2/L3。\n const shouldDenyL1 =\n heuristicResult.riskLevel === 'high' ||\n heuristicResult.riskLevel === 'critical' ||\n (heuristicResult.riskLevel === 'medium' && heuristicResult.riskType === 'file_access');\n if (shouldDenyL1) {\n return heuristicResult;\n }\n }\n }\n\n // ===== L1.5: Script content pre-scan (recursive chain + L1 reuse) =====\n // For bash actions invoking a script, recursively track the call chain,\n // preprocess, and scan each node with runHeuristicCheck (L1). high/critical\n // deny directly (layer \"1.1-script\"). Catches \"rm -rf /\" inside a script\n // whose entry command is just \"bash deploy.sh\". Reduces L3 token use.\n let scriptChain: ReturnType<typeof analyzeScriptChain> | null = null;\n if (input.aNext.actionType.toLowerCase() === 'bash') {\n scriptChain = analyzeScriptChain(input);\n if (scriptChain.nodes.length > 0) {\n for (const node of scriptChain.nodes) {\n if (node.l1Hit && (node.l1RiskLevel === 'high' || node.l1RiskLevel === 'critical')) {\n return {\n allowed: false,\n reason: `脚本内容包含危险操作: ${node.l1Reason} (文件: ${node.scriptPath}, 深度: ${node.depth})`,\n riskLevel: node.l1RiskLevel as SecurityJudgment['riskLevel'],\n riskType: node.l1RiskType,\n confidence: 90,\n source: 'heuristic_script_scan',\n violatedLayers: ['1.1-script'],\n };\n }\n }\n }\n }\n\n // ===== Brain L1 rule check (only when brain enabled) =====\n const brainStore = getBrainStore();\n if (brainStore) {\n const brainL1 = checkBrainRules(brainStore, {\n layer: 1,\n actionType: input.aNext.actionType,\n actionDetail: input.aNext.actionDetail,\n });\n if (brainL1) {\n return {\n allowed: false,\n reason: `[Brain L1] ${brainL1.explanation}`,\n riskLevel: 'high',\n riskType: 'brain_rule',\n confidence: Math.round(brainL1.confidence * 100),\n source: 'brain_rule',\n violatedLayers: ['brain_L1'],\n };\n }\n }\n\n // ===== Fast-pass check =====\n const actionType = input.aNext.actionType.toLowerCase();\n const rawDetail = extractRawCommand(input.aNext.actionDetail);\n const lowerDetail = rawDetail.toLowerCase();\n // agent 专属扩展(agent_moss/agents/<id>/rules.json)+ 场景定制规则\n // (agent_moss/scenarios/<id>/rules.json),合并后供 fast-pass 各白名单复用。\n // 场景规则:调用方显式 scenarioId > 环境变量 AGENT_MOSS_SCENARIO(部署级兜底)。\n const agentExt = mergeAgentExtensions(\n getAgentExtensions(input.agentId),\n getScenarioExtensions(input.scenarioId || process.env.AGENT_MOSS_SCENARIO || ''),\n );\n\n // Fully safe tools: skip L2 + L3\n if (FULLY_SAFE_TOOLS.has(actionType)) {\n return {\n allowed: true,\n reason: `完全安全工具,跳过深度分析: ${actionType}`,\n riskLevel: (heuristicResult?.riskLevel || 'low') as SecurityJudgment['riskLevel'],\n riskType: '',\n confidence: 95,\n source: 'whitelist_bypass',\n violatedLayers: [],\n };\n }\n\n // agent 专属完全安全操作白名单(精确名或前缀,来自 rules.json builtin_safe_action_types)。\n // 前缀以 '-' 结尾 → startswith 匹配(如 \"memory-\");否则精确名匹配(如 \"mailbox-getEmailList\")。\n // 命中即跳过 L2+L3,与 builtin_safe_skills 同范式。仅对该 agent_id 生效,不污染其他 agent。\n // OpenDesk 的 memory-*/todomgr-*/planning-* 是纯数据/只读操作,走 L3 LLM 耗时 1~137s 无意义。\n if (agentExt?.builtin_safe_action_types && agentExt.builtin_safe_action_types.length > 0) {\n // actionType 已小写化(:143);rules.json 精确名可能是驼峰(如 mailbox-getEmailList),\n // 故比较时对白名单项也 lower。前缀项(尾随 '-')同样 lower 后 startswith。\n const hit = agentExt.builtin_safe_action_types.some(t => {\n const tl = t.toLowerCase();\n return tl.endsWith('-') ? actionType.startsWith(tl) : actionType === tl;\n });\n if (hit) {\n return {\n allowed: true,\n reason: `agent 内部安全操作,跳过深度分析: ${actionType}`,\n riskLevel: (heuristicResult?.riskLevel || 'low') as SecurityJudgment['riskLevel'],\n riskType: '',\n confidence: 95,\n source: 'whitelist_bypass',\n violatedLayers: [],\n };\n }\n }\n\n // 内置安全 Skill 直接放行(通用 baseline + agent_ext.builtin_safe_skills)\n const trustedSkills = new Set<string>(TRUSTED_SKILLS_BASE);\n if (agentExt?.builtin_safe_skills) {\n for (const s of agentExt.builtin_safe_skills) trustedSkills.add(s);\n }\n if (actionType === 'skill' && trustedSkills.has(lowerDetail)) {\n return {\n allowed: true,\n reason: `内置安全 Skill,跳过深度分析: ${lowerDetail}`,\n riskLevel: (heuristicResult?.riskLevel || 'low') as SecurityJudgment['riskLevel'],\n riskType: '',\n confidence: 95,\n source: 'whitelist_bypass',\n violatedLayers: [],\n };\n }\n\n // Readonly sensitive tools: skip L3, continue to L2\n let skipLLM = READONLY_SENSITIVE_TOOLS.has(actionType);\n\n // Bash sub-command checks\n if (actionType === 'bash' || actionType === 'executebash' || actionType === 'terminal-executebash') {\n const firstCmd = extractFirstCommand(lowerDetail);\n if (matchesAny(firstCmd, FULLY_SAFE_BASH_PATTERNS)) {\n // 安全兜底 1:检查完整命令是否命中高危模式(如 echo ... | passwd)\n const fullCmdHit = DANGEROUS_PATTERNS.some(p =>\n p.severity === 'critical' || p.severity === 'high'\n ) && DANGEROUS_PATTERNS.some(p =>\n (p.severity === 'critical' || p.severity === 'high') && p.pattern.test(lowerDetail)\n );\n // 安全兜底 2:检查是否含真实重定向写(echo x > file / printf >> file)。\n // is_fully_safe_bash_command 只看首命令名(echo),会忽略 >/>> 重定向,\n // 导致 `echo x > /tmp/existing.txt` 覆写已存在文件被白名单放行跳过 L2(Bug3)。\n // 复用 isWriteOperation 的重定向判定(已剥 devnull + 比较运算符 + 只读首词保护)。\n const hasRedirectWrite = isWriteOperation(firstCmd, lowerDetail);\n if (!fullCmdHit && !hasRedirectWrite) {\n return {\n allowed: true,\n reason: `安全的只读 bash 命令: ${firstCmd}`,\n riskLevel: 'low',\n riskType: '',\n confidence: 95,\n source: 'whitelist_bypass',\n violatedLayers: [],\n };\n }\n }\n if (matchesAny(firstCmd, READONLY_SENSITIVE_BASH_PATTERNS)) {\n skipLLM = true;\n }\n }\n\n // Layer 2: Logic rule detection (fast)\n const logicResult = isLogicRulesEnabled() ? runLogicCheck(input) : null;\n // file_access 命中合并:敏感路径/危险模式现已在 L1(heuristicResult),\n // 间接文件访问仍在 L2(logicResult)。两者任一命中 file_access 都需进入\n // inline/credential 包装判定。优先采用 logicResult,退而取 heuristicResult。\n const l1FileAccessHit = !!(heuristicResult && !heuristicResult.allowed && heuristicResult.riskType === 'file_access');\n const effectiveResult = (logicResult && !logicResult.allowed) ? logicResult\n : (l1FileAccessHit ? heuristicResult : null);\n if (effectiveResult) {\n // 凭据文件:无论读写、无论是否 inline,都直接拒绝。\n // 来源:L1 sensitive path(isCredential)或 L2 indirect_file_access\n const isCredentialPath = !!effectiveResult.isCredential;\n // 内联脚本/文本输出命令:走静态语义判定,区分\"文本字面量\"vs\"真实读写\"。\n // 即使是凭据路径(如 deny_both 的 /etc/shadow),只要它是字符串字面量\n // (python -c \"print('/etc/shadow')\"),inline_analyzer 判 Allow 时应放行——\n // 因为并未真实读取该文件。actionable=false(提取不到代码)时才回退到\n // 凭据/敏感路径的硬拒绝。\n const skipInlineFileAccess = (isInlineScriptCmd || isLiteralTextCmd) && effectiveResult.riskType === 'file_access';\n if (skipInlineFileAccess) {\n const inlineJudgment = analyzeInlineScript(input.aNext.actionDetail);\n if (inlineJudgment.actionable) {\n if (!inlineJudgment.allowed) {\n return {\n allowed: false,\n reason: inlineJudgment.reason,\n riskLevel: inlineJudgment.riskLevel as SecurityJudgment['riskLevel'],\n riskType: inlineJudgment.riskType,\n confidence: 90,\n source: 'logic_rule',\n violatedLayers: ['1.2'],\n };\n }\n // 字面量 → Allow,不再走 Layer 3\n return {\n allowed: true,\n reason: inlineJudgment.reason,\n riskLevel: inlineJudgment.riskLevel as SecurityJudgment['riskLevel'],\n riskType: inlineJudgment.riskType,\n confidence: 90,\n source: 'logic_rule',\n violatedLayers: [],\n };\n }\n // actionable=false(提取不到代码)→ 回退原逻辑:high/critical 直接 Deny\n }\n if ((effectiveResult.riskLevel === 'high' || effectiveResult.riskLevel === 'critical') && (!skipInlineFileAccess || isCredentialPath)) {\n return effectiveResult;\n }\n // medium/low 风险:不直接拦截,走层3 LLM 语义判断\n }\n\n // ===== L2.4: Formal verification (behavior graph + property verification,\n // incl. cross-session combo chains). Mirrors Python coordinator L2.4.\n // Single session builds from actionHistory (backward compatible); multi-session\n // comes from input.sessionHistory (future agentgate non-intrusive collection).\n if (isLogicRulesEnabled()) {\n const formalSessions: { sessionId?: string; actionHistory: { actionType: string; actionDetail: string }[] }[] = [];\n if (input.sessionHistory) {\n for (const s of input.sessionHistory) {\n formalSessions.push({ sessionId: s.sessionId || 's', actionHistory: s.actionHistory || [] });\n }\n }\n formalSessions.push({ sessionId: 'current', actionHistory: input.actionHistory });\n const formalResult = formalEngine.verify(formalSessions, input.aNext);\n if (!formalResult.verified) {\n const v = formalResult.violations[0];\n return {\n allowed: false,\n reason: v ? v.reason : '形式化验证未通过(行为性质违反)',\n riskLevel: (v ? v.riskLevel : 'high') as SecurityJudgment['riskLevel'],\n riskType: 'formal_verification',\n confidence: 90,\n source: 'formal_engine',\n violatedLayers: ['2.4'],\n };\n }\n }\n\n // ===== L2.5: Script content L2 scan (per-node sensitive path / dangerous\n // pattern / intent reuse on preprocessed content). high/critical deny\n // directly (layer \"1.2-script\"). =====\n if (scriptChain && scriptChain.nodes.length > 0 && isLogicRulesEnabled()) {\n for (const node of scriptChain.nodes) {\n if (node.error || !node.preprocessedContent) continue;\n if (node.l1RiskLevel === 'critical') break;\n if (node.l2Hit && (node.l2RiskLevel === 'high' || node.l2RiskLevel === 'critical')) {\n return {\n allowed: false,\n reason: node.l2Reason,\n riskLevel: node.l2RiskLevel as SecurityJudgment['riskLevel'],\n riskType: node.l2RiskType,\n confidence: 85,\n source: 'logic_rule_script_scan',\n violatedLayers: ['1.2-script'],\n };\n }\n }\n }\n\n // ===== Brain L2 rule check (only when brain enabled) =====\n if (brainStore) {\n const brainL2 = checkBrainRules(brainStore, {\n layer: 2,\n actionType: input.aNext.actionType,\n actionDetail: input.aNext.actionDetail,\n actionHistory: input.actionHistory,\n });\n if (brainL2) {\n return {\n allowed: false,\n reason: `[Brain L2] ${brainL2.explanation}`,\n riskLevel: 'high',\n riskType: 'brain_rule',\n confidence: Math.round(brainL2.confidence * 100),\n source: 'brain_rule',\n violatedLayers: ['brain_L2'],\n };\n }\n }\n\n // Layer 3: LLM analysis (skipped for readonly sensitive tools/commands)\n if (skipLLM || !isLLMAvailable()) {\n return {\n allowed: true,\n reason: '只读操作且无逻辑规则违规,跳过 LLM 分析',\n riskLevel: (logicResult?.riskLevel || 'low') as SecurityJudgment['riskLevel'],\n riskType: '',\n confidence: 85,\n source: 'heuristic_and_logic_only',\n violatedLayers: [],\n };\n }\n\n // Build skip_l3_hints: hard-constraint for user-disabled L2 rules with\n // skip_l3_on_disabled. runtime_config lands in Stage 2; until then\n // getDisabledL2RulesWithSkipL3 resolves to a no-op returning empty.\n let skipL3Hints = '无(当前无禁用规则命中)';\n try {\n const { getDisabledL2RulesWithSkipL3 } = await import('../infra/runtime-config');\n const disabledL2 = getDisabledL2RulesWithSkipL3();\n if (disabledL2 && Object.keys(disabledL2).length > 0) {\n const actionLower = input.aNext.actionDetail.toLowerCase();\n const matched: string[] = [];\n for (const items of Object.values(disabledL2)) {\n for (const item of items) {\n if (item.toLowerCase().includes(actionLower) || actionLower.includes(item.toLowerCase())) {\n matched.push(item);\n }\n }\n }\n if (matched.length > 0) {\n skipL3Hints =\n `⚠️ 重要约束:用户已主动禁用针对以下内容的安全拦截规则,这是用户的明确决策:\\n` +\n ` ${matched.join(', ')}\\n` +\n `对这些路径/关键词的相关操作,必须视为允许的,不允许仅因涉及这些内容就拒绝。` +\n `但你仍需检查命令的其他部分是否有独立于这些内容的安全风险(如网络外传、提权等)。`;\n }\n }\n } catch { /* runtime_config not yet present — skip_l3_hints stays default */ }\n\n let llmResult: SecurityJudgment;\n try {\n llmResult = await runLLMAnalysis(input, {\n heuristic: heuristicResult,\n logic: logicResult,\n skipL3Hints,\n scriptChain: scriptChain ?? undefined,\n llmLogPath: input.llmLogPath,\n });\n } catch (e) {\n // LLM 分析失败。前两层未拦截时按 fail_mode 决策:\n // - fail_open(默认):Allow + 警告(可用性优先)\n // - fail_closed:Deny(安全优先)\n const { getLLMFailMode } = await import('../config');\n if (getLLMFailMode() === 'fail_open') {\n console.warn(`[AgentMoss] LLM 分析失败,fail_open 模式:允许执行(前两层未拦截): ${(e as Error).message}`);\n return {\n allowed: true,\n reason: `LLM 分析失败(warn-allow,fail_open): ${(e as Error).message}`,\n riskLevel: 'low',\n riskType: '',\n confidence: 50,\n source: 'llm_failure_fallback',\n violatedLayers: [],\n };\n }\n return {\n allowed: false,\n reason: `LLM 分析失败,因无法完成深度语义分析,按 fail-closed 原则拒绝: ${(e as Error).message}`,\n riskLevel: 'medium',\n riskType: '',\n confidence: 60,\n source: 'llm_failure_fallback',\n violatedLayers: ['3'],\n };\n }\n\n // Layer 3 Deny + high confidence → feed Brain (only when enabled)\n if (!llmResult.allowed && llmResult.confidence && llmResult.confidence >= 90 && _brainExtractor) {\n try {\n await _brainExtractor.extract(\n { actionDetail: input.aNext.actionDetail, eventId: '' },\n {\n confidence: llmResult.confidence / 100,\n reason: llmResult.reason || '',\n riskType: llmResult.riskType || '',\n actionDetail: input.aNext.actionDetail,\n },\n );\n } catch {\n // Brain extraction failure must not affect main flow\n }\n }\n\n return llmResult;\n}\n","import { SecurityJudgment } from './types';\nimport type { AnalysisInput } from './coordinator';\nimport { getLLMConfig, isLLMAvailable, detectProvider, getProviderHeaders, getTimeoutConfig, getRetryConfig } from '../config';\nimport { matchSkills, formatSkillsForPrompt } from './skill-loader';\nimport { loadTemplates } from './template-loader';\nimport { analyzeScriptContent, formatScriptAnalysisForPrompt } from './script-analyzer';\nimport { formatScriptChainForPrompt } from './script-content-analyzer';\nimport { appendFileSync } from 'fs';\nimport OpenAI from 'openai';\n\n// LRU cache to avoid duplicate LLM calls for identical commands\nconst llmCache = new Map<string, SecurityJudgment>();\nconst LLM_CACHE_MAX = 200;\n\ninterface PreviousResults {\n heuristic: SecurityJudgment | null;\n logic: SecurityJudgment | null;\n skipL3Hints?: string;\n scriptChain?: import('./script-content-analyzer').ScriptChainAnalysisResult;\n /** per-request LLM prompt 日志路径(来自调用方 metadata.llm_log_path) */\n llmLogPath?: string;\n}\n\n/**\n * Layer 3: LLM + Skill semantic analysis.\n * Only called when layers 1 and 2 both pass.\n * Loads skills from the shared skills directory and uses LLM for deep analysis.\n */\nexport async function runLLMAnalysis(\n input: AnalysisInput,\n previous: PreviousResults\n): Promise<SecurityJudgment> {\n if (!isLLMAvailable()) {\n console.log('[AgentMoss] LLM not configured, skipping deep analysis');\n return {\n allowed: true,\n reason: 'LLM 未配置,跳过深层分析',\n riskLevel: 'low',\n riskType: '',\n confidence: 50,\n source: 'llm',\n violatedLayers: [],\n };\n }\n\n // 优先使用 per-request 的 LLM 配置(OpenDesk 按当前会话模型传入)\n const globalConfig = getLLMConfig();\n const config = input.llmConfig?.apiKey\n ? { ...globalConfig, ...input.llmConfig }\n : globalConfig;\n\n // Check LRU cache (use raw command as key, strip OpenDesk metadata)\n const rawDetail = input.aNext.actionDetail.replace(/^terminal-\\w+:\\s*command=([^,]+).*/, '$1').trim();\n const cacheKey = `${input.aNext.actionType}:${rawDetail || input.aNext.actionDetail}`;\n const cached = llmCache.get(cacheKey);\n if (cached) {\n console.log('[AgentMoss] LLM cache hit');\n return cached;\n }\n\n // Load skills and templates (cached)\n const matchedSkills = matchSkills(input.aNext.actionType, input.aNext.actionDetail, input.reason);\n const templates = loadTemplates();\n\n // Build the analysis prompt. Prefer the script chain from coordinator\n // (L1.5/L2.5 already did recursive tracking); fall back to single-file scan.\n let scriptAnalysis: import('./script-analyzer').ScriptAnalysisResult | undefined;\n let scriptChainText = '';\n if (previous.scriptChain) {\n scriptChainText = formatScriptChainForPrompt(previous.scriptChain);\n } else {\n scriptAnalysis = analyzeScriptContent(input.aNext.actionType, input.aNext.actionDetail);\n }\n const prompt = buildPrompt(input, previous, matchedSkills, templates, scriptAnalysis, previous.skipL3Hints ?? '', scriptChainText);\n\n // 写 LLM prompt 到日志(per-request logPath 优先,对齐 py _log_prompt)。\n // 与 bridge.ts 写 HOOK_INPUT/HOOK_OUTPUT 同一个文件,对齐 audit_agent AUDIT_LOG_PATH。\n logPrompt(prompt, input.aNext, previous.llmLogPath);\n\n // Call LLM\n const result = await analyzeWithLLM(prompt, config);\n\n // Cache result\n if (llmCache.size >= LLM_CACHE_MAX) {\n const firstKey = llmCache.keys().next().value;\n if (firstKey) llmCache.delete(firstKey);\n }\n llmCache.set(cacheKey, result);\n\n return result;\n}\n\n/**\n * 写 LLM prompt 到日志文件(对齐 Python _log_prompt)。\n * logPath 来自 per-request metadata.llm_log_path(调用方 env 注入)。\n * 与 bridge.ts 的 HOOK_INPUT/HOOK_OUTPUT 写同一个文件,对齐 audit_agent AUDIT_LOG_PATH。\n */\nfunction logPrompt(prompt: string, aNext: { actionType: string; actionDetail: string }, logPath?: string): void {\n if (!logPath) return;\n try {\n const actionType = aNext.actionType || 'unknown';\n const actionDetail = (aNext.actionDetail || '').slice(0, 100);\n const line =\n `[${new Date().toISOString()}] ` +\n `[LLM_PROMPT] action_type=${actionType}, action_detail=${actionDetail}... ` +\n `prompt_length=${prompt.length}\\n` +\n `${prompt}\\n` +\n `--- END PROMPT ---\\n`;\n appendFileSync(logPath, line, 'utf-8');\n } catch (e) {\n console.warn('[AgentMoss] Failed to write LLM prompt to log:', e);\n }\n}\n\nexport function buildPrompt(\n input: AnalysisInput,\n previous: PreviousResults,\n matchedSkills: import('./skill-loader').SkillMatch[],\n templates: Record<string, string>,\n scriptAnalysis?: import('./script-analyzer').ScriptAnalysisResult,\n skipL3Hints: string = '',\n scriptChainText: string = '',\n): string {\n const skillsText = formatSkillsForPrompt(matchedSkills);\n const historyStr = input.actionHistory\n .map((h, i) => `${i + 1}. ${h.actionType}: ${h.actionDetail}`)\n .join('\\n') || '(无历史操作)';\n\n // 交错历史 prompt(供 LLM 判断意图一致性,避免\"继续\"覆盖初始意图)。\n const promptHistoryText = formatPromptHistory(input.promptHistory);\n\n // Prefer coordinator-provided script chain text (recursive tracking result);\n // fall back to single-file keyword prescan; else empty.\n const scriptAnalysisText = scriptChainText\n ? scriptChainText\n : (scriptAnalysis ? formatScriptAnalysisForPrompt(scriptAnalysis) : '');\n\n // Format L1/L2 hints (mirrors Python LLMAnalyzer._format_hints)\n const hintsText = formatHints(previous);\n\n // Layer 3 安全判断用 security_judge_template(对齐 Python get_security_judge_prompt)。\n // prompt1/prompt2 是 Cerberus 沙箱策略模板,不适用于此处的 Allow/Deny 裁决。\n const securityJudgeTemplate = templates['security_judge'];\n if (securityJudgeTemplate) {\n // 占位符逐个替换(不能用全局 {x} 正则:模板 JSON 示例里的 {{ }} 会误伤)。\n // security_judge_template.txt 用 {{ }} 转义 JSON 大括号,替换完后还原为单括号。\n return securityJudgeTemplate\n .replaceAll('{prompt_session}', input.promptSession || '(未提供)')\n .replaceAll('{prompt_history_text}', promptHistoryText)\n .replaceAll('{action_history}', historyStr)\n .replaceAll('{action_type}', input.aNext.actionType)\n .replaceAll('{action_detail}', input.aNext.actionDetail)\n .replaceAll('{reason}', input.reason || '未说明')\n .replaceAll('{skills_text}', skillsText)\n .replaceAll('{hints_text}', hintsText)\n .replaceAll('{script_analysis_text}', scriptAnalysisText)\n .replaceAll('{skip_l3_hints}', skipL3Hints)\n .replaceAll('{{', '{')\n .replaceAll('}}', '}');\n }\n\n // Fallback:security_judge 模板缺失时(旧包/加载异常),退回稀疏 prompt,避免崩溃。\n // 这种情况下 LLM 裸跑,判断质量下降,但不阻断流程。\n console.warn('[AgentMoss] security_judge template missing, using sparse fallback prompt');\n return `## 当前操作上下文\n- 会话 ID: ${input.sessionId}\n- 用户任务: ${input.promptSession || '未指定'}\n- 操作系统: ${input.osType}\n- 工作目录: ${input.cwd || '/'}\n- 操作原因: ${input.reason || '未说明'}\n- 历史操作序列:\n${historyStr}\n\n- 即将执行的操作:\n 类型: ${input.aNext.actionType}\n 详情: ${input.aNext.actionDetail}\n\n## 可用安全 Skill\n${skillsText}\n\n## 前置检测结果\n${hintsText}\n${scriptAnalysisText ? `\\n## 脚本内容分析\\n${scriptAnalysisText}` : ''}\n\n请根据以上信息,对即将执行的操作进行安全判断。前置检测为 low/medium 且有合理执行理由时应当允许。你必须输出严格的 JSON 格式,不要包含任何其他文字、注释或 markdown 标记。\n\n输出格式:\n{\"allowed\": true/false, \"reason\": \"判断理由\", \"riskLevel\": \"low|medium|high|critical\", \"riskType\": \"风险类型\", \"confidence\": 0-100}`;\n}\n\n/** 格式化交错历史 prompt 为 LLM 可读文本(对齐 Python LLMAnalyzer._format_prompt_history)。 */\nfunction formatPromptHistory(\n promptHistory?: AnalysisInput['promptHistory'],\n maxTextChars = 500,\n): string {\n if (!promptHistory || promptHistory.length === 0) {\n return '(未提供历史意图)';\n }\n const lines: string[] = [];\n for (let i = 0; i < promptHistory.length; i++) {\n const turn = promptHistory[i];\n // 兼容两种元素格式:纯文本 string(AgentGate v3 旧格式)与 {text, actions} dict\n const text = (typeof turn === 'string' ? turn : (turn?.text || '')).trim();\n if (!text) continue;\n let line = ` 第${i + 1}轮用户意图: ${text.slice(0, maxTextChars)}`;\n const actions = typeof turn === 'string' ? undefined : turn?.actions;\n if (actions && actions.length > 0) {\n const types = actions\n .map(a => a?.actionType)\n .filter((t): t is string => typeof t === 'string' && t.length > 0);\n if (types.length > 0) {\n line += ` → 动作: ${types.join(', ')}`;\n }\n }\n lines.push(line);\n }\n return lines.length > 0 ? lines.join('\\n') : '(未提供历史意图)';\n}\n\nfunction formatHints(previous: PreviousResults): string {\n const hints: string[] = [];\n\n if (previous.heuristic) {\n hints.push(\n `特征匹配检测发现风险 [风险等级: ${previous.heuristic.riskLevel}]:\\n` +\n ` 类型: ${previous.heuristic.riskType}\\n` +\n ` 原因: ${previous.heuristic.reason}`\n );\n }\n\n if (previous.logic) {\n hints.push(\n `逻辑规则检测发现风险 [风险等级: ${previous.logic.riskLevel}]:\\n` +\n ` 类型: ${previous.logic.riskType}\\n` +\n ` 原因: ${previous.logic.reason}`\n );\n }\n\n return hints.length > 0 ? hints.join('\\n\\n') : '特征匹配检测和逻辑规则检测均未发现风险。';\n}\n\nasync function analyzeWithLLM(prompt: string, config: ReturnType<typeof getLLMConfig>): Promise<SecurityJudgment> {\n console.log(`[AgentMoss] LLM analyzing with model: ${config.model}, url: ${config.baseUrl}`);\n\n const provider = detectProvider(config.baseUrl, config.provider);\n const extraHeaders = getProviderHeaders(provider);\n if (Object.keys(extraHeaders).length > 0) {\n console.log(`[AgentMoss] Provider detected: ${provider}, injecting headers: ${Object.keys(extraHeaders).join(', ')}`);\n }\n\n const timeoutCfg = getTimeoutConfig();\n const retryCfg = getRetryConfig();\n const client = new OpenAI({\n baseURL: config.baseUrl,\n apiKey: config.apiKey,\n // 单次 LLM 调用超时用 prompt1Timeout(对齐 py);env 覆盖的 config.timeout 仍向后兼容\n timeout: (config.timeout || timeoutCfg.prompt1Timeout) * 1000,\n defaultHeaders: Object.keys(extraHeaders).length > 0 ? extraHeaders : undefined,\n });\n\n // maxRetries 优先 env,否则用 retry 配置(默认 2,对齐 py)\n const maxRetries = parseInt(process.env.AGENT_MOSS_LLM_RETRIES || String(retryCfg.maxRetries), 10);\n\n // totalTimeout 强制执行:用 AbortController 确保整个 LLM 分析(含所有重试)\n // 在 totalTimeout(默认 90s)后强制中断,防止最坏情况 ~372s 超时。\n const totalTimeoutMs = timeoutCfg.totalTimeout * 1000;\n const abortController = new AbortController();\n const totalTimeoutTimer = setTimeout(() => {\n console.error(`[AgentMoss] totalTimeout (${timeoutCfg.totalTimeout}s) exceeded, aborting all LLM calls`);\n abortController.abort();\n }, totalTimeoutMs);\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n if (abortController.signal.aborted) {\n break;\n }\n try {\n const response = await client.chat.completions.create({\n model: config.model,\n temperature: config.temperature || 0.1,\n max_tokens: config.maxTokens || 1024,\n messages: [\n { role: 'system', content: '只输出纯 JSON,不要包含 markdown 标记、代码块或任何其他文字。' },\n { role: 'user', content: prompt },\n ],\n signal: abortController.signal,\n } as any);\n\n const content = response.choices[0]?.message?.content || '{}';\n console.log(`[AgentMoss] LLM raw response (attempt ${attempt + 1}/${maxRetries + 1}): ${content.substring(0, 300)}`);\n\n let jsonStr = content.trim();\n if (jsonStr.startsWith('```')) {\n jsonStr = jsonStr.replace(/^```[\\w]*\\n?/, '').replace(/\\n?```$/, '');\n }\n const parsed = JSON.parse(jsonStr);\n\n // 记录 token 用量(step=\"L3_security_judge\")\n try {\n const usage = response.usage;\n const { recordTokenUsage } = await import('./token-stats');\n recordTokenUsage({\n sessionId: 'audit',\n step: 'L3_security_judge',\n model: response.model || config.model,\n promptTokens: usage?.prompt_tokens || 0,\n completionTokens: usage?.completion_tokens || 0,\n totalTokens: usage?.total_tokens || 0,\n });\n } catch { /* token stats optional */ }\n\n clearTimeout(totalTimeoutTimer);\n // LLM 回 JSON 字段名可能是 camelCase(riskLevel)或 snake_case(risk_level),\n // 两种都兼容避免拿不到 risk_level 走兜底 'low'(双端对齐 Python 字段名)\n const riskLevel = parsed.riskLevel ?? parsed.risk_level;\n const riskType = parsed.riskType ?? parsed.risk_type;\n return {\n allowed: parsed.allowed !== false,\n reason: parsed.reason || 'LLM 分析完成',\n riskLevel: ['low', 'medium', 'high', 'critical'].includes(riskLevel) ? riskLevel : 'low',\n riskType: riskType || '',\n confidence: typeof parsed.confidence === 'number' ? Math.min(100, Math.max(0, parsed.confidence)) : 70,\n source: 'llm',\n violatedLayers: ['3'],\n };\n } catch (err) {\n // totalTimeout 触发的 AbortError:直接跳出循环,不再重试\n if (abortController.signal.aborted) {\n console.error(`[AgentMoss] LLM analysis aborted by totalTimeout (${timeoutCfg.totalTimeout}s)`);\n break;\n }\n if (attempt < maxRetries) {\n console.error(`[AgentMoss] LLM call failed (attempt ${attempt + 1}/${maxRetries + 1}), retrying in ${retryCfg.retryInterval}s:`, (err as Error).message);\n await new Promise(resolve => setTimeout(resolve, retryCfg.retryInterval * 1000));\n } else {\n clearTimeout(totalTimeoutTimer);\n console.error('[AgentMoss] LLM call failed after all retries:', (err as Error).message);\n throw new Error(`LLM 分析失败 (${maxRetries + 1} 次尝试): ${(err as Error).message}`);\n }\n }\n }\n\n // totalTimeout 超时或 AbortError 导致循环中断\n clearTimeout(totalTimeoutTimer);\n throw new Error(`LLM 分析超时(totalTimeout ${timeoutCfg.totalTimeout}s)`);\n}\n","import { readFileSync, existsSync } from 'fs';\nimport { resolve, dirname } from 'path';\nimport { fileURLToPath } from 'url';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n// 优先用打包内联目录 dist/templates(npm 安装后自包含);\n// dev 模式(vitest 测试时 __dirname=ts/src/engine)回退到仓库根 agent_moss/templates。\n// 注意:从 ts/src/engine 出发,仓库根 agent_moss/templates 在 ../../../agent_moss/templates\n// (不能写 ../../agent_moss/templates,那是 ts/agent_moss/templates,不存在)。\nconst TEMPLATES_DIR = resolve(__dirname, '../templates');\nconst TEMPLATES_DIR_FALLBACK = resolve(__dirname, '../../../agent_moss/templates');\n\nconst TEMPLATE_FILES = ['prompt1_template.txt', 'prompt2_template.txt', 'security_judge_template.txt'];\n\nlet cachedTemplates: Record<string, string> | null = null;\n\nexport function loadTemplates(): Record<string, string> {\n if (cachedTemplates) return cachedTemplates;\n\n cachedTemplates = {};\n\n const dir = existsSync(TEMPLATES_DIR) ? TEMPLATES_DIR : TEMPLATES_DIR_FALLBACK;\n if (!existsSync(dir)) {\n console.warn('[AgentMoss] Templates directory not found:', TEMPLATES_DIR, 'and fallback:', TEMPLATES_DIR_FALLBACK);\n return cachedTemplates;\n }\n\n for (const file of TEMPLATE_FILES) {\n const filePath = resolve(dir, file);\n if (existsSync(filePath)) {\n const key = file.replace('.txt', '').replace('_template', '');\n cachedTemplates[key] = readFileSync(filePath, 'utf-8');\n }\n }\n\n console.log(`[AgentMoss] Loaded ${Object.keys(cachedTemplates).length} templates from ${dir}`);\n return cachedTemplates;\n}\n\nexport function reloadTemplates(): void {\n cachedTemplates = null;\n loadTemplates();\n}\n","import { readFileSync } from 'fs';\nimport { resolve, join } from 'path';\n\n/**\n * Script content pre-scanning — detects suspicious patterns in bash scripts.\n * When a script execution is detected, reads up to 500 lines and scans for\n * high-risk patterns (network exfil, reverse shells, base64 obfuscation,\n * sensitive file access, persistence backdoors).\n */\n\n// High-risk detection patterns\nconst SUSPICIOUS_PATTERNS: { name: string; pattern: RegExp }[] = [\n // Network exfiltration (curl/wget POST in scripts is almost never legitimate)\n { name: 'curl POST', pattern: /curl\\s+(.*\\s)?-X\\s+POST/i },\n { name: 'curl --data', pattern: /curl\\s+(.*\\s)?--data/i },\n { name: 'curl -d', pattern: /curl\\s+(.*\\s)?-d\\s/i },\n { name: 'wget --post-data', pattern: /wget\\s+(.*\\s)?--post-data/i },\n { name: 'wget --post-file', pattern: /wget\\s+(.*\\s)?--post-file/i },\n // Reverse shell\n { name: 'nc -e', pattern: /\\bnc\\s+.*-e\\b/ },\n { name: 'ncat -e', pattern: /\\bncat\\s+.*-e\\b/ },\n { name: '/dev/tcp', pattern: /\\/dev\\/tcp\\// },\n { name: '/dev/udp', pattern: /\\/dev\\/udp\\// },\n // Base64 obfuscation\n { name: '$(base64', pattern: /\\$\\(\\s*base64/ },\n { name: '`base64', pattern: /`\\s*base64/ },\n { name: 'base64 decode pipe', pattern: /base64\\s+(-d|--decode)\\s*\\|/ },\n // Sensitive file access\n { name: '/etc/shadow', pattern: /\\/etc\\/shadow/ },\n { name: 'id_rsa', pattern: /\\bid_rsa\\b/ },\n { name: 'id_ed25519', pattern: /\\bid_ed25519\\b/ },\n // Persistence backdoor\n { name: 'crontab install', pattern: /crontab\\s+-/ },\n { name: 'authorized_keys', pattern: /authorized_keys/ },\n { name: 'ssh no host key check', pattern: /ssh\\s+.*StrictHostKeyChecking\\s*=\\s*no/ },\n];\n\n// Script execution patterns\nconst SCRIPT_EXEC_PATTERNS = [\n /bash\\s+(\\S+\\.sh)/,\n /sh\\s+(\\S+\\.sh)/,\n /\\.\\/(\\S+\\.sh)/,\n /source\\s+(\\S+\\.sh)/,\n /\\.\\s+(\\S+\\.sh)/,\n /zsh\\s+(\\S+\\.sh)/,\n];\n\n// Keyword combination risk rules\nconst KEYWORD_COMBINATION_RISKS: { group1: Set<string>; group2: Set<string>; level: string; reason: string }[] = [\n {\n group1: new Set(['curl POST', 'curl --data', 'curl -d', 'wget --post-data', 'wget --post-file']),\n group2: new Set(['$(base64', '`base64', 'base64 decode pipe']),\n level: 'critical',\n reason: '检测到网络数据发送 + Base64编码组合,构成 Critical 级别数据外传风险。攻击者可能将敏感数据编码后外传。',\n },\n {\n group1: new Set(['curl POST', 'curl --data', 'curl -d', 'wget --post-data', 'wget --post-file']),\n group2: new Set(['/etc/shadow', 'id_rsa', 'id_ed25519']),\n level: 'critical',\n reason: '检测到网络数据发送 + 敏感文件访问组合,构成 Critical 级别凭证外传风险。',\n },\n {\n group1: new Set(['nc -e', 'ncat -e', '/dev/tcp', '/dev/udp']),\n group2: new Set(),\n level: 'high',\n reason: '检测到反弹 Shell 特征,攻击者可能建立远程控制通道。',\n },\n {\n group1: new Set(['crontab install', 'authorized_keys', 'ssh no host key check']),\n group2: new Set(),\n level: 'high',\n reason: '检测到持久化后门特征,攻击者可能在系统中植入后门。',\n },\n];\n\nconst SINGLE_KEYWORD_RISKS: Record<string, { level: string; reason: string }> = {\n 'curl POST': { level: 'high', reason: '检测到 curl POST 请求,可能向外部服务器发送数据。' },\n 'curl --data': { level: 'high', reason: '检测到 curl --data 参数,可能向外部服务器发送数据。' },\n 'curl -d': { level: 'high', reason: '检测到 curl -d 参数,可能向外部服务器发送数据。' },\n 'wget --post-data': { level: 'high', reason: '检测到 wget POST 请求,可能向外部服务器发送数据。' },\n 'wget --post-file': { level: 'high', reason: '检测到 wget 文件上传,可能向外部服务器发送文件。' },\n 'nc -e': { level: 'critical', reason: '检测到 nc -e 反弹 Shell 特征。' },\n 'ncat -e': { level: 'critical', reason: '检测到 ncat -e 反弹 Shell 特征。' },\n '/dev/tcp': { level: 'critical', reason: '检测到 /dev/tcp 反弹 Shell 特征。' },\n '/dev/udp': { level: 'critical', reason: '检测到 /dev/udp 反弹 Shell 特征。' },\n '$(base64': { level: 'high', reason: '检测到 Base64 编码执行,可能是混淆逃逸。' },\n '`base64': { level: 'high', reason: '检测到 Base64 编码执行,可能是混淆逃逸。' },\n 'base64 decode pipe': { level: 'high', reason: '检测到 Base64 解码后管道执行,可能是混淆逃逸。' },\n '/etc/shadow': { level: 'critical', reason: '检测到访问系统密码文件。' },\n 'id_rsa': { level: 'critical', reason: '检测到访问 SSH 私钥。' },\n 'id_ed25519': { level: 'critical', reason: '检测到访问 SSH 私钥。' },\n 'crontab install': { level: 'high', reason: '检测到修改定时任务,可能是持久化后门。' },\n 'authorized_keys': { level: 'high', reason: '检测到修改 SSH 授权密钥,可能是持久化后门。' },\n 'ssh no host key check': { level: 'high', reason: '检测到 SSH 跳过主机密钥验证,可能是横向移动。' },\n};\n\nconst LEVEL_ORDER: Record<string, number> = { low: 1, medium: 2, high: 3, critical: 4 };\n\nexport interface ScriptAnalysisResult {\n scriptPath: string;\n scriptContent: string;\n matchedKeywords: string[];\n lineCount: number;\n isSuspicious: boolean;\n error: string;\n riskLevel: string;\n riskReason: string;\n}\n\nfunction emptyResult(): ScriptAnalysisResult {\n return { scriptPath: '', scriptContent: '', matchedKeywords: [], lineCount: 0, isSuspicious: false, error: '', riskLevel: '', riskReason: '' };\n}\n\nfunction extractScriptPath(command: string): string | null {\n for (const pattern of SCRIPT_EXEC_PATTERNS) {\n const m = command.match(pattern);\n if (m) return m[1];\n }\n return null;\n}\n\nfunction scanScriptForKeywords(content: string): string[] {\n const matched: string[] = [];\n for (const { name, pattern } of SUSPICIOUS_PATTERNS) {\n if (pattern.test(content)) matched.push(name);\n }\n return matched;\n}\n\nfunction assessKeywordCombinationRisk(matchedKeywords: string[], scriptContent: string): { level: string; reason: string } {\n if (matchedKeywords.length === 0) return { level: '', reason: '' };\n\n const keywordSet = new Set(matchedKeywords);\n\n // Check combination rules\n for (const rule of KEYWORD_COMBINATION_RISKS) {\n const hitGroup1 = [...rule.group1].some(k => keywordSet.has(k));\n const hitGroup2 = rule.group2.size === 0 ? true : [...rule.group2].some(k => keywordSet.has(k));\n if (hitGroup1 && hitGroup2) return { level: rule.level, reason: rule.reason };\n }\n\n // Extra: network post + env variable collection\n const networkPostKeywords = new Set(['curl POST', 'curl --data', 'curl -d', 'wget --post-data', 'wget --post-file']);\n const hasNetworkPost = [...networkPostKeywords].some(k => keywordSet.has(k));\n if (hasNetworkPost) {\n const envPatterns = ['$env', '$(env)', '$USER', '$(hostname)', '$(pwd)', '$HOME'];\n const contentLower = scriptContent.toLowerCase();\n for (const p of envPatterns) {\n if (contentLower.includes(p.toLowerCase())) {\n return {\n level: 'critical',\n reason: '检测到网络数据发送 + 系统环境变量收集组合,构成 Critical 级别数据外传风险。脚本可能将用户环境变量(可能包含 API Key、密钥等敏感信息)发送到远程服务器。',\n };\n }\n }\n }\n\n // Single keyword fallback\n let bestLevel = '';\n let bestReason = '';\n for (const kw of matchedKeywords) {\n const risk = SINGLE_KEYWORD_RISKS[kw];\n if (risk && (LEVEL_ORDER[risk.level] || 0) > (LEVEL_ORDER[bestLevel] || 0)) {\n bestLevel = risk.level;\n bestReason = risk.reason;\n }\n }\n\n return { level: bestLevel, reason: bestReason };\n}\n\nfunction readScriptContent(scriptPath: string, maxLines: number = 500): { content: string; lineCount: number; error: string } {\n try {\n const expandedPath = scriptPath.startsWith('~')\n ? join(process.env.HOME || '/home/user', scriptPath.slice(2))\n : resolve(scriptPath);\n\n const raw = readFileSync(expandedPath, 'utf-8');\n const lines = raw.split('\\n').slice(0, maxLines);\n return { content: lines.join('\\n'), lineCount: lines.length, error: '' };\n } catch (e: unknown) {\n const msg = e instanceof Error ? e.message : String(e);\n return { content: '', lineCount: 0, error: `读取脚本失败: ${msg}` };\n }\n}\n\nexport function analyzeScriptContent(actionType: string, actionDetail: string, maxLines: number = 500): ScriptAnalysisResult {\n if (actionType.toLowerCase() !== 'bash') return emptyResult();\n\n const scriptPath = extractScriptPath(actionDetail);\n if (!scriptPath) return emptyResult();\n\n const { content, lineCount, error } = readScriptContent(scriptPath, maxLines);\n if (error) return { ...emptyResult(), scriptPath, error };\n\n const matchedKeywords = scanScriptForKeywords(content);\n const isSuspicious = matchedKeywords.length > 0;\n\n let riskLevel = '';\n let riskReason = '';\n if (isSuspicious) {\n const risk = assessKeywordCombinationRisk(matchedKeywords, content);\n riskLevel = risk.level;\n riskReason = risk.reason;\n }\n\n return { scriptPath, scriptContent: content, matchedKeywords, lineCount, isSuspicious, error: '', riskLevel, riskReason };\n}\n\nexport function formatScriptAnalysisForPrompt(result: ScriptAnalysisResult): string {\n if (!result.scriptPath) return '';\n if (result.error) return `脚本内容分析失败: ${result.error}`;\n if (!result.isSuspicious) return '';\n\n const keywordsStr = result.matchedKeywords.join(', ');\n let riskHint = '';\n if (result.riskLevel && result.riskReason) {\n riskHint = `\\n\\n风险评估: ${result.riskLevel.toUpperCase()} 级别\\n风险原因: ${result.riskReason}\\n建议: 此脚本应被拒绝(Deny),除非有明确的业务需求且已确认目标服务器可信。`;\n }\n\n return `检测到脚本执行,且脚本内容包含可疑关键词:\\n 脚本路径: ${result.scriptPath}\\n 可疑关键词: ${keywordsStr}\\n 脚本行数: ${result.lineCount}${riskHint}\\n\\n### 脚本内容 ###\\n\\`\\`\\`\\n${result.scriptContent}\\n\\`\\`\\`\\n`;\n}\n","/**\n * Script content analyzer — recursive chain tracking + preprocessing + L1/L2 reuse.\n *\n * Mirrors Python agent_moss/engine/script_content_analyzer.py.\n *\n * Core improvements over the old single-file script-analyzer.ts:\n * 1. Preprocessing pipeline: strip comments -> strip echo text -> expand simple vars\n * 2. Broader script path extraction (no .sh restriction; python/node/ruby/...)\n * 3. File-size limit instead of line limit (full read; ms-scale cost)\n * 4. Recursive tracking: A.sh -> B.sh -> C.sh nested calls are caught\n * 5. L1/L2 reuse: preprocessed content scanned via existing runHeuristicCheck /\n * runLogicCheck; high/critical deny directly, skipping L3\n *\n * Difference from Python: AgentMoss-TS heuristic/logic are single entry functions\n * (runHeuristicCheck / runLogicCheck taking AnalysisInput), not reusable scanner\n * objects. So L1/L2 per-node reuse wraps each node's preprocessed content as a\n * virtual AnalysisInput and calls those functions.\n */\n\nimport { readFileSync, statSync, existsSync } from 'fs';\nimport { resolve, join, isAbsolute, dirname } from 'path';\nimport { homedir } from 'os';\nimport type { AnalysisInput } from './coordinator';\nimport type { SecurityJudgment } from './types';\nimport { runHeuristicCheck } from './heuristic';\nimport { runLogicCheck } from './logic-rules';\nimport { RecursiveTracker } from './script-engine/tracker';\n\n// ==================== Types ====================\n\nexport interface ScriptNode {\n scriptPath: string;\n rawContent: string;\n preprocessedContent: string;\n lineCount: number;\n fileSize: number;\n depth: number;\n childPaths: string[];\n error: string;\n\n l1Hit: boolean;\n l1RiskLevel: string;\n l1RiskType: string;\n l1Reason: string;\n l1MatchedPatterns: string[];\n\n l2Hit: boolean;\n l2ViolatedRule: string;\n l2RiskLevel: string;\n l2RiskType: string;\n l2Reason: string;\n\n matchedKeywords: string[];\n isSuspicious: boolean;\n keywordRiskLevel: string;\n keywordRiskReason: string;\n}\n\nexport interface ScriptChainAnalysisResult {\n nodes: ScriptNode[];\n entryPath: string;\n maxDepthReached: boolean;\n maxSizeReached: boolean;\n maxNodesReached: boolean;\n totalSize: number;\n totalLines: number;\n totalNodes: number;\n hasCritical: boolean;\n hasHigh: boolean;\n firstHitNode: ScriptNode | null;\n error: string;\n}\n\nfunction emptyChain(): ScriptChainAnalysisResult {\n return {\n nodes: [], entryPath: '', maxDepthReached: false, maxSizeReached: false,\n maxNodesReached: false, totalSize: 0, totalLines: 0, totalNodes: 0,\n hasCritical: false, hasHigh: false, firstHitNode: null, error: '',\n };\n}\n\nfunction newNode(path: string, depth: number): ScriptNode {\n return {\n scriptPath: path, rawContent: '', preprocessedContent: '', lineCount: 0,\n fileSize: 0, depth, childPaths: [], error: '',\n l1Hit: false, l1RiskLevel: '', l1RiskType: '', l1Reason: '', l1MatchedPatterns: [],\n l2Hit: false, l2ViolatedRule: '', l2RiskLevel: '', l2RiskType: '', l2Reason: '',\n matchedKeywords: [], isSuspicious: false, keywordRiskLevel: '', keywordRiskReason: '',\n };\n}\n\n\n// ==================== High-risk keyword patterns (L3 compatible) ====================\n\nconst SUSPICIOUS_PATTERNS: { name: string; pattern: RegExp }[] = [\n { name: 'curl POST', pattern: /curl\\s+(.*\\s)?-X\\s+POST/i },\n { name: 'curl --data', pattern: /curl\\s+(.*\\s)?--data/i },\n { name: 'curl -d', pattern: /curl\\s+(.*\\s)?-d\\s/i },\n { name: 'wget --post-data', pattern: /wget\\s+(.*\\s)?--post-data/i },\n { name: 'wget --post-file', pattern: /wget\\s+(.*\\s)?--post-file/i },\n { name: 'nc -e', pattern: /\\bnc\\s+.*-e\\b/ },\n { name: 'ncat -e', pattern: /\\bncat\\s+.*-e\\b/ },\n { name: '/dev/tcp', pattern: /\\/dev\\/tcp\\// },\n { name: '/dev/udp', pattern: /\\/dev\\/udp\\// },\n { name: '$(base64', pattern: /\\$\\(\\s*base64/ },\n { name: '`base64', pattern: /`\\s*base64/ },\n { name: 'base64 decode pipe', pattern: /base64\\s+(-d|--decode)\\s*\\|/ },\n { name: '/etc/shadow', pattern: /\\/etc\\/shadow/ },\n { name: 'id_rsa', pattern: /\\bid_rsa\\b/ },\n { name: 'id_ed25519', pattern: /\\bid_ed25519\\b/ },\n { name: 'crontab install', pattern: /crontab\\s+-/ },\n { name: 'authorized_keys', pattern: /authorized_keys/ },\n { name: 'ssh no host key check', pattern: /ssh\\s+.*StrictHostKeyChecking\\s*=\\s*no/ },\n];\n\n\n// ==================== Script execution patterns ====================\n\nconst SCRIPT_EXEC_PATTERNS: RegExp[] = [\n /(?:^|\\s|&&|\\|\\|)\\s*bash\\s+(\\S+)/i,\n /(?:^|\\s|&&|\\|\\|)\\s*\\/bin\\/bash\\s+(\\S+)/i,\n /(?:^|\\s|&&|\\|\\|)\\s*sh\\s+(\\S+)/i,\n /(?:^|\\s|&&|\\|\\|)\\s*zsh\\s+(\\S+)/i,\n /\\.\\/(\\S+)/,\n /(?:^|\\s|&&|\\|\\|)\\s*source\\s+(\\S+)/i,\n /(?:^|\\s|&&|\\|\\|)\\s*\\.\\s+(\\S+)/,\n /(?:^|\\s|&&|\\|\\|)\\s*python3?\\s+(\\S+\\.py)/i,\n /(?:^|\\s|&&|\\|\\|)\\s*node\\s+(\\S+\\.js)/i,\n /(?:^|\\s|&&|\\|\\|)\\s*ruby\\s+(\\S+\\.rb)/i,\n /(?:^|\\s|&&|\\|\\|)\\s*perl\\s+(\\S+\\.pl)/i,\n /(?:^|\\s|&&|\\|\\|)\\s*php\\s+(\\S+\\.php)/i,\n /(?:^|\\s|&&|\\|\\|)\\s*lua\\s+(\\S+\\.lua)/i,\n];\n\n\n// ==================== Keyword combination risk rules ====================\n\nconst KEYWORD_COMBINATION_RISKS: { group1: Set<string>; group2: Set<string>; level: string; reason: string }[] = [\n {\n group1: new Set(['curl POST', 'curl --data', 'curl -d', 'wget --post-data', 'wget --post-file']),\n group2: new Set(['$(base64', '`base64', 'base64 decode pipe']),\n level: 'critical',\n reason: '检测到网络数据发送 + Base64编码组合,构成 Critical 级别数据外传风险。攻击者可能将敏感数据编码后外传。',\n },\n {\n group1: new Set(['curl POST', 'curl --data', 'curl -d', 'wget --post-data', 'wget --post-file']),\n group2: new Set(['/etc/shadow', 'id_rsa', 'id_ed25519']),\n level: 'critical',\n reason: '检测到网络数据发送 + 敏感文件访问组合,构成 Critical 级别凭证外传风险。',\n },\n {\n group1: new Set(['nc -e', 'ncat -e', '/dev/tcp', '/dev/udp']),\n group2: new Set(),\n level: 'high',\n reason: '检测到反弹 Shell 特征,攻击者可能建立远程控制通道。',\n },\n {\n group1: new Set(['crontab install', 'authorized_keys', 'ssh no host key check']),\n group2: new Set(),\n level: 'high',\n reason: '检测到持久化后门特征,攻击者可能在系统中植入后门。',\n },\n];\n\nconst SINGLE_KEYWORD_RISKS: Record<string, { level: string; reason: string }> = {\n 'curl POST': { level: 'high', reason: '检测到 curl POST 请求,可能向外部服务器发送数据。' },\n 'curl --data': { level: 'high', reason: '检测到 curl --data 参数,可能向外部服务器发送数据。' },\n 'curl -d': { level: 'high', reason: '检测到 curl -d 参数,可能向外部服务器发送数据。' },\n 'wget --post-data': { level: 'high', reason: '检测到 wget POST 请求,可能向外部服务器发送数据。' },\n 'wget --post-file': { level: 'high', reason: '检测到 wget 文件上传,可能向外部服务器发送文件。' },\n 'nc -e': { level: 'critical', reason: '检测到 nc -e 反弹 Shell 特征。' },\n 'ncat -e': { level: 'critical', reason: '检测到 ncat -e 反弹 Shell 特征。' },\n '/dev/tcp': { level: 'critical', reason: '检测到 /dev/tcp 反弹 Shell 特征。' },\n '/dev/udp': { level: 'critical', reason: '检测到 /dev/udp 反弹 Shell 特征。' },\n '$(base64': { level: 'high', reason: '检测到 Base64 编码执行,可能是混淆逃逸。' },\n '`base64': { level: 'high', reason: '检测到 Base64 编码执行,可能是混淆逃逸。' },\n 'base64 decode pipe': { level: 'high', reason: '检测到 Base64 解码后管道执行,可能是混淆逃逸。' },\n '/etc/shadow': { level: 'critical', reason: '检测到访问系统密码文件。' },\n 'id_rsa': { level: 'critical', reason: '检测到访问 SSH 私钥。' },\n 'id_ed25519': { level: 'critical', reason: '检测到访问 SSH 私钥。' },\n 'crontab install': { level: 'high', reason: '检测到修改定时任务,可能是持久化后门。' },\n 'authorized_keys': { level: 'high', reason: '检测到修改 SSH 授权密钥,可能是持久化后门。' },\n 'ssh no host key check': { level: 'high', reason: '检测到 SSH 跳过主机密钥验证,可能是横向移动。' },\n};\n\nconst LEVEL_ORDER: Record<string, number> = { low: 1, medium: 2, high: 3, critical: 4 };\n\nfunction scanScriptForKeywords(content: string): string[] {\n const matched: string[] = [];\n for (const { name, pattern } of SUSPICIOUS_PATTERNS) {\n if (pattern.test(content)) matched.push(name);\n }\n return matched;\n}\n\nfunction assessKeywordCombinationRisk(matchedKeywords: string[], scriptContent: string): { level: string; reason: string } {\n if (matchedKeywords.length === 0) return { level: '', reason: '' };\n\n const keywordSet = new Set(matchedKeywords);\n\n for (const rule of KEYWORD_COMBINATION_RISKS) {\n const hitGroup1 = [...rule.group1].some(k => keywordSet.has(k));\n const hitGroup2 = rule.group2.size === 0 ? true : [...rule.group2].some(k => keywordSet.has(k));\n if (hitGroup1 && hitGroup2) return { level: rule.level, reason: rule.reason };\n }\n\n const networkPostKeywords = new Set(['curl POST', 'curl --data', 'curl -d', 'wget --post-data', 'wget --post-file']);\n const hasNetworkPost = [...networkPostKeywords].some(k => keywordSet.has(k));\n if (hasNetworkPost) {\n const envPatterns = ['$env', '$(env)', '$USER', '$(hostname)', '$(pwd)', '$HOME'];\n const contentLower = scriptContent.toLowerCase();\n for (const p of envPatterns) {\n if (contentLower.includes(p.toLowerCase())) {\n return {\n level: 'critical',\n reason: '检测到网络数据发送 + 系统环境变量收集组合,构成 Critical 级别数据外传风险。脚本可能将用户环境变量(可能包含 API Key、密钥等敏感信息)发送到远程服务器。',\n };\n }\n }\n }\n\n let bestLevel = '';\n let bestReason = '';\n for (const kw of matchedKeywords) {\n const risk = SINGLE_KEYWORD_RISKS[kw];\n if (risk && (LEVEL_ORDER[risk.level] || 0) > (LEVEL_ORDER[bestLevel] || 0)) {\n bestLevel = risk.level;\n bestReason = risk.reason;\n }\n }\n return { level: bestLevel, reason: bestReason };\n}\n\n\n// ==================== Script path extraction ====================\n\nfunction extractScriptPath(command: string): string | null {\n for (const pattern of SCRIPT_EXEC_PATTERNS) {\n const m = command.match(pattern);\n if (m) return m[1];\n }\n return null;\n}\n\n/** Extract script path AND the positional args following it. Mirrors Python. */\nfunction extractScriptPathWithArgs(command: string): { path: string | null; args: string[] } {\n const scriptPath = extractScriptPath(command);\n if (!scriptPath) return { path: null, args: [] };\n\n const idx = command.indexOf(scriptPath);\n if (idx < 0) return { path: scriptPath, args: [] };\n\n let rest = command.slice(idx + scriptPath.length);\n // strip pipe/redirect/semicolon connectors (not script args)\n rest = rest.split(/[;|&<>]/)[0].trim();\n const tokens = [...rest.matchAll(/([\"'])(.*?)\\1|(\\S+)/g)];\n const args: string[] = [];\n for (const m of tokens) {\n args.push(m[1] ? m[2] : m[3]);\n }\n return { path: scriptPath, args };\n}\n\nfunction extractInlineScriptPath(actionDetail: string): string | null {\n const re = /open\\s*\\(\\s*['\"]([^'\"]+)['\"]\\s*\\)/g;\n let m: RegExpExecArray | null;\n while ((m = re.exec(actionDetail)) !== null) {\n const p = m[1];\n let resolved: string;\n try {\n resolved = resolvePath(p);\n if (existsSync(resolved)) {\n const stat = statSync(resolved);\n if (stat.isFile()) return resolved;\n }\n } catch { /* ignore */ }\n }\n return null;\n}\n\n/** Resolve a path: expand ~, resolve relative against cwd. */\nfunction resolvePath(p: string): string {\n let expanded = p;\n if (expanded.startsWith('~/') || expanded === '~') {\n expanded = join(homedir(), expanded.slice(1));\n }\n return resolve(expanded);\n}\n\n\n\n// ==================== L1/L2 fallback chain scan ====================\n\n/** L1 fallback: scan nodes that weren't inline-scanned during recursion. */\nfunction scanScriptChainWithL1(chain: ScriptChainAnalysisResult, input: AnalysisInput): ScriptChainAnalysisResult {\n for (const node of chain.nodes) {\n if (node.error || !node.preprocessedContent || node.l1Hit) continue;\n const virtualInput: AnalysisInput = {\n ...input,\n aNext: { actionType: 'bash', actionDetail: node.preprocessedContent },\n };\n const l1 = runHeuristicCheck(virtualInput);\n if (l1 && !l1.allowed) {\n node.l1Hit = true;\n node.l1RiskLevel = l1.riskLevel;\n node.l1RiskType = l1.riskType;\n node.l1Reason = l1.reason;\n if (l1.riskLevel === 'critical') {\n chain.hasCritical = true;\n chain.firstHitNode = node;\n break;\n }\n }\n }\n return chain;\n}\n\n/**\n * L2 fallback: scan each node's preprocessed content via runLogicCheck.\n * Only reuses action-history-independent rules (sensitive path / dangerous\n * patterns / intent). runLogicCheck runs all L2 rules; we accept its verdict\n * per node (matching Python's per-rule reuse behaviorally).\n */\nfunction scanScriptChainWithL2(chain: ScriptChainAnalysisResult, input: AnalysisInput): ScriptChainAnalysisResult {\n for (const node of chain.nodes) {\n if (node.error || !node.preprocessedContent) continue;\n if (node.l1RiskLevel === 'critical') break;\n\n const virtualInput: AnalysisInput = {\n ...input,\n aNext: { actionType: 'bash', actionDetail: node.preprocessedContent },\n };\n const l2 = runLogicCheck(virtualInput);\n if (l2 && !l2.allowed) {\n node.l2Hit = true;\n node.l2ViolatedRule = `script_logic:${node.scriptPath}`;\n node.l2RiskLevel = l2.riskLevel;\n node.l2RiskType = l2.riskType;\n node.l2Reason = `脚本 ${node.scriptPath} (深度 ${node.depth}) 中: ${l2.reason}`;\n if (l2.riskLevel === 'critical') {\n chain.hasCritical = true;\n chain.firstHitNode = node;\n break;\n }\n }\n }\n if (!chain.hasHigh) {\n chain.hasHigh = chain.nodes.some(n => ['high', 'critical'].includes(n.l2RiskLevel));\n }\n return chain;\n}\n\n/** Keyword scan per node (L3-compatible). Only nodes not hit by L1/L2. */\nfunction scanScriptChainKeywords(chain: ScriptChainAnalysisResult): ScriptChainAnalysisResult {\n for (const node of chain.nodes) {\n if (node.error || !node.preprocessedContent) continue;\n if (node.l1Hit || node.l2Hit) continue;\n\n const matched = scanScriptForKeywords(node.preprocessedContent);\n node.matchedKeywords = matched;\n node.isSuspicious = matched.length > 0;\n\n if (matched.length > 0) {\n const risk = assessKeywordCombinationRisk(matched, node.preprocessedContent);\n node.keywordRiskLevel = risk.level;\n node.keywordRiskReason = risk.reason;\n }\n }\n return chain;\n}\n\n\n// ==================== Entry function ====================\n\n/**\n * Analyze script content: recursive tracking + preprocessing + L1/L2/keyword scan.\n * Only runs when actionType is 'bash' and the command invokes a script.\n *\n * Mirrors Python analyze_script_content. L1/L2 reuse wraps each node's\n * preprocessed content as a virtual AnalysisInput.\n */\nexport function analyzeScriptContent(input: AnalysisInput): ScriptChainAnalysisResult {\n const actionType = input.aNext.actionType.toLowerCase();\n if (actionType !== 'bash') return emptyChain();\n\n const { path: scriptPath, args: scriptArgs } = extractScriptPathWithArgs(input.aNext.actionDetail);\n let resolvedPath = scriptPath;\n let isInline = false;\n if (!resolvedPath) {\n const inline = extractInlineScriptPath(input.aNext.actionDetail);\n if (!inline) return emptyChain();\n resolvedPath = inline;\n isInline = true;\n }\n\n // 相对脚本路径按 cwd 解析(对齐 Python base_dir=cwd),避免落到 process.cwd()\n if (resolvedPath && !isAbsolute(resolvedPath) && !resolvedPath.startsWith('~/')) {\n resolvedPath = join(input.cwd || process.cwd(), resolvedPath);\n }\n\n // ===== 脚本分析引擎(独立引擎层) =====\n // RecursiveTracker 消费 ShellBackend 的 IR:case/if 控制流切片 + 子脚本调用\n // 参数传递(修复子调用参数丢失 + 深层链漏追踪)。对齐 Python RecursiveTracker。\n const l1Adapter: (content: string) => { hit: boolean; riskLevel: string; riskType: string; reason: string; matchedPatterns: string[] } = (content) => {\n const virtualInput: AnalysisInput = {\n ...input,\n aNext: { actionType: 'bash', actionDetail: content },\n };\n const j = runHeuristicCheck(virtualInput);\n if (j && !j.allowed) {\n return { hit: true, riskLevel: j.riskLevel, riskType: j.riskType, reason: j.reason, matchedPatterns: [] };\n }\n return { hit: false, riskLevel: '', riskType: '', reason: '', matchedPatterns: [] };\n };\n const tracker = new RecursiveTracker(l1Adapter);\n const chain = tracker.track(resolvedPath, isInline ? null : scriptArgs, input.cwd || process.cwd());\n\n if (chain.nodes.length === 0) return chain;\n\n // L1 fallback + L2 + keyword scans\n scanScriptChainWithL1(chain, input);\n scanScriptChainWithL2(chain, input);\n scanScriptChainKeywords(chain);\n\n return chain;\n}\n\n\n// ==================== L3 prompt formatting ====================\n\nexport function formatScriptChainForPrompt(chain: ScriptChainAnalysisResult): string {\n if (chain.nodes.length === 0) return '';\n\n const errorNodes = chain.nodes.filter(n => n.error);\n if (errorNodes.length > 0 && chain.nodes.length === 1) {\n return `⚠️ 脚本内容分析失败: ${errorNodes[0].error}`;\n }\n\n const suspiciousNodes = chain.nodes.filter(n => n.isSuspicious && !n.l1Hit && !n.l2Hit);\n if (suspiciousNodes.length === 0) {\n const safeNodes = chain.nodes.filter(n => !n.error);\n if (safeNodes.length === 0) return '';\n const parts: string[] = ['✓ 脚本内容已分析,未发现危险/可疑操作(L1/L2/关键词扫描均未命中):'];\n for (const node of safeNodes) {\n const pre = node.preprocessedContent || '';\n let preview = pre.slice(0, 600);\n if (pre.length > 600) preview += `\\n... (截断,完整内容 ${pre.length} 字符)`;\n parts.push(\n ` 脚本路径: ${node.scriptPath}(递归深度 ${node.depth},${node.lineCount} 行)\\n` +\n ` 内容(预处理后):\\n\\`\\`\\`\\n${preview}\\n\\`\\`\\``\n );\n }\n return parts.join('\\n');\n }\n\n const parts: string[] = [];\n for (const node of suspiciousNodes) {\n const keywordsStr = node.matchedKeywords.join(', ');\n let riskHint = '';\n if (node.keywordRiskLevel && node.keywordRiskReason) {\n riskHint =\n `\\n\\n🔴 **风险评估**: ${node.keywordRiskLevel.toUpperCase()} 级别\\n` +\n `**风险原因**: ${node.keywordRiskReason}\\n` +\n `**建议**: 此脚本应被拒绝(Deny),除非有明确的业务需求且已确认目标服务器可信。`;\n }\n const pre = node.preprocessedContent;\n let contentPreview = pre.slice(0, 2000);\n if (pre.length > 2000) contentPreview += `\\n... (截断,完整内容 ${pre.length} 字符)`;\n parts.push(\n `⚠️ 脚本内容包含可疑关键词:\\n` +\n ` 脚本路径: ${node.scriptPath}\\n` +\n ` 递归深度: ${node.depth}\\n` +\n ` 可疑关键词: ${keywordsStr}\\n` +\n ` 脚本行数: ${node.lineCount}${riskHint}\\n\\n` +\n `### 脚本内容(预处理后)###\\n\\`\\`\\`\\n${contentPreview}\\n\\`\\`\\`\\n`\n );\n }\n\n let header = `⚠️ 检测到脚本执行链(共 ${chain.nodes.length} 个脚本),其中 ${suspiciousNodes.length} 个包含可疑关键词:\\n`;\n if (chain.maxDepthReached) header += '⚠️ 注意:递归追踪触达深度上限,可能存在更深层的脚本调用未被扫描。\\n';\n if (chain.maxSizeReached) header += '⚠️ 注意:累计文件大小触达上限,部分脚本可能未被完整读取。\\n';\n\n return header + parts.join('\\n---\\n\\n');\n}\n\n/** [deprecated] Use formatScriptChainForPrompt. */\nexport function formatScriptAnalysisForPrompt(chain: ScriptChainAnalysisResult): string {\n return formatScriptChainForPrompt(chain);\n}\n\n\n","/**\n * Script-engine RecursiveTracker — cross-script call chain traversal.\n * Mirrors Python agent_moss/engine/script_engine/tracker.py.\n *\n * Language-agnostic (consumes ScriptIR.calls):\n * - Depth budget (default 14), replacing old fixed max_depth=3.\n * - Cycle detection (DFS visiting set), preventing A→B→A infinite recursion.\n * - Cross-script arg passing: each child uses ITS OWN call args for branch\n * awareness (fixes old sub-call param loss bug).\n * - Node/byte budgets prevent memory blowup (keeps peak RSS flat vs current).\n *\n * Contract with coordinator: command_scanner runs inline L1 on each node's\n * reachableContent (high/critical short-circuit). Returns ScriptChainAnalysisResult\n * (compatible with existing ScriptNode structure).\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\nimport type { AnalysisInput } from '../coordinator';\nimport { ScriptNode, ScriptChainAnalysisResult } from '../script-content-analyzer';\nimport { ScriptIR } from './ir';\nimport { PythonBackend } from './backends/python-backend';\nimport { ShellBackend } from './backends';\nimport type { LanguageBackend } from './backends';\n\nconst DEFAULT_MAX_DEPTH = 14;\nconst DEFAULT_MAX_NODES = 64;\nconst DEFAULT_MAX_FILE_SIZE = 2 * 1024 * 1024;\nconst DEFAULT_MAX_TOTAL_SIZE = 8 * 1024 * 1024;\n\n// Language backend registry — dispatch by script file extension.\n// Adding a language = register here + new backend.\nconst BACKENDS: Record<string, LanguageBackend> = {\n '.py': new PythonBackend(),\n};\nconst DEFAULT_BACKEND = new ShellBackend();\n\nfunction pickBackend(pathStr: string): LanguageBackend {\n const lower = pathStr.toLowerCase();\n for (const ext of Object.keys(BACKENDS)) {\n if (lower.endsWith(ext)) return BACKENDS[ext];\n }\n return DEFAULT_BACKEND;\n}\n\nexport function resolvePath(p: string, baseDir?: string): string {\n let expanded = p;\n if (expanded.startsWith('~/') || expanded === '~') {\n expanded = path.join(os.homedir(), expanded.slice(1));\n } else if (!path.isAbsolute(expanded) && baseDir) {\n expanded = path.join(baseDir, expanded);\n }\n return path.resolve(expanded);\n}\n\nfunction readScript(\n pathStr: string,\n maxFileSize: number,\n): { content: string; lineCount: number; fileSize: number; error: string } {\n try {\n const p = resolvePath(pathStr);\n if (!fs.existsSync(p)) return { content: '', lineCount: 0, fileSize: 0, error: `脚本不存在: ${pathStr}` };\n const stat = fs.statSync(p);\n if (!stat.isFile()) return { content: '', lineCount: 0, fileSize: 0, error: `不是文件: ${pathStr}` };\n if (stat.size > maxFileSize) {\n return { content: '', lineCount: 0, fileSize: stat.size, error: `脚本文件过大 (${stat.size} bytes),跳过读取` };\n }\n const content = fs.readFileSync(p, 'utf-8');\n return { content, lineCount: content ? content.split('\\n').length : 0, fileSize: stat.size, error: '' };\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n return { content: '', lineCount: 0, fileSize: 0, error: `读取脚本失败: ${msg}` };\n }\n}\n\nfunction emptyNode(pathStr: string, depth: number): ScriptNode {\n return {\n scriptPath: pathStr, rawContent: '', preprocessedContent: '', lineCount: 0,\n fileSize: 0, depth, childPaths: [], error: '',\n l1Hit: false, l1RiskLevel: '', l1RiskType: '', l1Reason: '', l1MatchedPatterns: [],\n l2Hit: false, l2ViolatedRule: '', l2RiskLevel: '', l2RiskType: '', l2Reason: '',\n matchedKeywords: [], isSuspicious: false, keywordRiskLevel: '', keywordRiskReason: '',\n };\n}\n\n/** Lightweight L1 check compatible with the current scan contract. */\ntype L1Scanner = (content: string) => { hit: boolean; riskLevel: string; riskType: string; reason: string; matchedPatterns: string[] };\n\nexport class RecursiveTracker {\n private result: ScriptChainAnalysisResult;\n private visiting = new Set<string>();\n private visitedPaths = new Set<string>();\n private _scanner: L1Scanner | null;\n\n constructor(\n commandScanner: L1Scanner | null,\n private maxDepth = DEFAULT_MAX_DEPTH,\n private maxNodes = DEFAULT_MAX_NODES,\n private maxFileSize = DEFAULT_MAX_FILE_SIZE,\n private maxTotalSize = DEFAULT_MAX_TOTAL_SIZE,\n ) {\n this._scanner = commandScanner;\n this.result = {\n nodes: [], entryPath: '', maxDepthReached: false, maxSizeReached: false,\n maxNodesReached: false, totalSize: 0, totalLines: 0, totalNodes: 0,\n hasCritical: false, hasHigh: false, firstHitNode: null, error: '',\n };\n }\n\n track(entryPath: string, entryArgs: string[] | null, cwd: string = ''): ScriptChainAnalysisResult {\n const baseDir = cwd || process.cwd();\n const resolved = resolvePath(entryPath);\n this.result.entryPath = resolved;\n\n this.visitScript(resolved, 0, path.dirname(resolved), entryArgs);\n\n const nodes = this.result.nodes;\n this.result.hasCritical = nodes.some(n =>\n n.l1RiskLevel === 'critical' || n.l2RiskLevel === 'critical' || n.keywordRiskLevel === 'critical') || this.result.hasCritical;\n this.result.hasHigh = nodes.some(n =>\n ['high', 'critical'].includes(n.l1RiskLevel) ||\n ['high', 'critical'].includes(n.l2RiskLevel) ||\n ['high', 'critical'].includes(n.keywordRiskLevel));\n this.result.firstHitNode = nodes.find(n => n.l1Hit || n.l2Hit || n.isSuspicious) || null;\n return this.result;\n }\n\n private visitScript(pathStr: string, depth: number, baseDir: string, args: string[] | null): void {\n pathStr = resolvePath(pathStr);\n\n if (this.visiting.has(pathStr)) return;\n if (this.visitedPaths.has(pathStr)) return;\n if (depth > this.maxDepth) {\n this.result.maxDepthReached = true;\n return;\n }\n if (this.result.nodes.length >= this.maxNodes) {\n this.result.maxNodesReached = true;\n return;\n }\n if (this.result.totalSize >= this.maxTotalSize) {\n this.result.maxSizeReached = true;\n return;\n }\n\n this.visiting.add(pathStr);\n this.visitedPaths.add(pathStr);\n\n const { content, lineCount, fileSize, error } = readScript(pathStr, this.maxFileSize);\n if (error) {\n const node = emptyNode(pathStr, depth);\n node.error = error;\n node.fileSize = fileSize;\n node.lineCount = lineCount;\n this.result.nodes.push(node);\n this.visiting.delete(pathStr);\n return;\n }\n\n this.result.totalSize += fileSize;\n this.result.totalLines += lineCount;\n\n const ir: ScriptIR = pickBackend(pathStr).parse(content, args);\n const node = emptyNode(pathStr, depth);\n node.rawContent = content;\n node.preprocessedContent = ir.reachableContent;\n node.lineCount = lineCount;\n node.fileSize = fileSize;\n this.result.nodes.push(node);\n this.result.totalNodes = this.result.nodes.length;\n\n // inline L1\n if (this._scanner && ir.reachableContent) {\n const l1 = this._scanner(ir.reachableContent);\n if (l1.hit) {\n node.l1Hit = true;\n node.l1RiskLevel = l1.riskLevel;\n node.l1RiskType = l1.riskType;\n node.l1Reason = l1.reason;\n node.l1MatchedPatterns = l1.matchedPatterns || [];\n if (l1.riskLevel === 'critical') {\n this.result.hasCritical = true;\n this.result.firstHitNode = node;\n this.visiting.delete(pathStr);\n return;\n }\n }\n }\n\n // child calls (with args) → recurse\n // 相对子路径按当前脚本目录解析(对齐 Python _resolve_path(call.path, parent dir)),\n // 不能基于 process.cwd()(那会导致 `./child.sh` 解析错目录,DRY 掉 9+ 层深链)。\n const parentDir = path.dirname(pathStr);\n const childPaths: string[] = [];\n for (const call of ir.calls) {\n const child = resolvePath(call.path, parentDir);\n childPaths.push(child);\n this.visitScript(child, depth + 1, path.dirname(child), call.args);\n if (this.result.hasCritical) break;\n }\n node.childPaths = childPaths;\n\n this.visiting.delete(pathStr);\n }\n}","/**\n * Script-engine PythonBackend — static python3 parser → IR.\n * Mirrors Python agent_moss/engine/script_engine/backends/python_backend.py.\n *\n * Uses @lezer/python (pure JS, zero native deps, ~134KB) to build a CST,\n * then performs the same control-flow pruning + child-call extraction as the\n * Python end (stdlib `ast`), producing identical IR behavior:\n * - sys.argv[N] bound to entry args (like shell $N)\n * - simple assignment tracking: mode = sys.argv[1] → if mode == \"clean\" judged\n * - if/elif condition statically evaluable → branch selected; else keep all (fail-closed)\n * - if __name__ == \"__main__\" → always true (entry script)\n * - for/while/try/with bodies kept (can't prove unreachable); nested if still pruned\n * - def/class bodies fully kept (call-time env unknown), no inner pruning\n *\n * Child calls: subprocess.run([\"bash\",\"x.sh\",arg]) list form,\n * subprocess.run(\"bash x.sh arg\", shell=True) / os.system(\"...\") string form,\n * relative imports (from . import x / from .x import y).\n */\n\nimport { parser } from '@lezer/python';\nimport type { SyntaxNode } from '@lezer/common';\nimport type { BranchInfo, ScriptCall, ScriptIR } from '../ir';\nimport type { LanguageBackend } from './index';\n\n// ==================== budget (P5 fuse, mirrors symbolic.py red line) ====================\n\nconst MAX_LINES = 500;\n\n// Pure builtins whose calls never mutate script globals (safe to keep env).\nconst PURE_BUILTINS = new Set([\n 'len', 'print', 'str', 'int', 'float', 'bool', 'list', 'dict', 'set',\n 'tuple', 'range', 'sorted', 'enumerate', 'zip', 'map', 'filter',\n 'sum', 'min', 'max', 'abs', 'round', 'isinstance', 'type', 'open',\n 'input', 'repr', 'ord', 'chr', 'hex', 'oct', 'bin', 'format', 'id',\n 'hash', 'any', 'all', 'next', 'iter', 'reversed', 'pow', 'divmod',\n]);\n\n// ==================== child-call regex (mirrors shell_backend._CHILD_CALL_RE) ====================\n\nconst CHILD_CALL_RE = /(?:^|\\s|&&|\\|\\|)\\s*((?:\\/bin\\/)?bash|sh|zsh|(?:python|python3|node|ruby|perl|php|lua))\\s+(\\S+(?:\\.(?:sh|shrc|py|js|rb|pl|php|lua))?)([^\\n;|&]*?)$/gim;\n\nconst SUBPROCESS_FUNCS = new Set(['run', 'call', 'Popen', 'check_call', 'check_output']);\nconst OS_FUNCS = new Set(['system', 'popen', 'popen2', 'popen3', 'popen4']);\n\n// ==================== line mapping ====================\n\nfunction buildLineStarts(content: string): number[] {\n const starts = [0];\n for (let i = 0; i < content.length; i++) {\n if (content[i] === '\\n') starts.push(i + 1);\n }\n return starts;\n}\n\nfunction lineAt(lineStarts: number[], pos: number): number {\n let lo = 0;\n let hi = lineStarts.length - 1;\n while (lo < hi) {\n const mid = (lo + hi + 1) >> 1;\n if (lineStarts[mid] <= pos) lo = mid;\n else hi = mid - 1;\n }\n return lo + 1; // 1-based\n}\n\nfunction markNodeLines(node: SyntaxNode, lines: Set<number>, lineStarts: number[]): void {\n const start = lineAt(lineStarts, node.from);\n const end = node.to > node.from ? lineAt(lineStarts, node.to - 1) : start;\n for (let i = start; i <= end; i++) lines.add(i);\n}\n\nfunction reconstruct(sourceLines: string[], lines: Set<number>): string {\n const out: string[] = [];\n for (const i of [...lines].sort((a, b) => a - b)) {\n if (i >= 1 && i <= sourceLines.length) out.push(sourceLines[i - 1]);\n }\n return out.join('\\n');\n}\n\n// ==================== value evaluation (simplified SVal: string | null) ====================\n\ninterface Env {\n argv: string[];\n vars: Record<string, string | null>;\n}\n\nfunction makeEnv(argv: string[]): Env {\n return { argv, vars: {} };\n}\n\nfunction textOf(node: SyntaxNode): string {\n return node.to > node.from ? node.parent!.tree!.length === 0 ? '' : srcSlice(node) : '';\n}\n\n/** Slice original source for a node (needs access to full source). */\nlet SOURCE = '';\nfunction srcSlice(node: SyntaxNode): string {\n return SOURCE.slice(node.from, node.to);\n}\n\n/** Unquote a lezer String token (e.g. \"clean\" / 'clean'). */\nfunction stringValue(tokenText: string): string {\n let s = tokenText;\n if (s.length >= 2) {\n const q = s[0];\n if ((q === '\"' || q === \"'\") && s.endsWith(q)) s = s.slice(1, -1);\n }\n // basic escapes so values match Python ast.Constant\n s = s.replace(/\\\\n/g, '\\n').replace(/\\\\t/g, '\\t').replace(/\\\\r/g, '\\r')\n .replace(/\\\\\\\\/g, '\\\\').replace(/\\\\\"/g, '\"').replace(/\\\\'/g, \"'\");\n return s;\n}\n\nfunction isSysArgv(node: SyntaxNode | null): boolean {\n if (!node || node.name !== 'MemberExpression') return false;\n const first = node.firstChild;\n if (!first || first.name !== 'VariableName' || srcSlice(first) !== 'sys') return false;\n const prop = node.getChild('PropertyName');\n return prop !== null && srcSlice(prop) === 'argv';\n}\n\nfunction evalExpr(node: SyntaxNode | null, env: Env): string | null {\n if (!node) return null;\n const name = node.name;\n if (name === 'String') return stringValue(srcSlice(node));\n if (name === 'Number') return srcSlice(node);\n if (name === 'VariableName') {\n const id = srcSlice(node);\n return id in env.vars ? env.vars[id] : null;\n }\n if (name === 'MemberExpression') {\n // sys.argv[N]\n const bracket = node.getChild('[');\n if (bracket) {\n const inner = node.firstChild;\n if (inner && isSysArgv(inner)) {\n const idxNode = bracket.nextSibling;\n if (idxNode && idxNode.name === 'Number') {\n const idx = parseInt(srcSlice(idxNode), 10);\n if (idx >= 1 && idx <= env.argv.length) return env.argv[idx - 1];\n return null;\n }\n }\n return null;\n }\n // sys.argv whole\n if (isSysArgv(node)) return env.argv[0] ?? null;\n return null;\n }\n if (name === 'CallExpression') {\n // len(sys.argv)\n const func = node.firstChild;\n if (func && func.name === 'VariableName' && srcSlice(func) === 'len') {\n const argList = node.getChild('ArgList');\n const inner = argList ? firstNamedChild(argList) : null;\n if (inner && isSysArgv(inner)) return String(env.argv.length + 1);\n }\n return null;\n }\n if (name === 'ConditionalExpression') {\n // then if cond else orelse\n const ifKw = node.getChild('if');\n const elseKw = node.getChild('else');\n if (!ifKw || !elseKw) return null;\n const thenNode = node.firstChild;\n const condNode = ifKw.nextSibling;\n const orelseNode = elseKw.nextSibling;\n if (!thenNode || !condNode || !orelseNode) return null;\n const cond = evalCondition(condNode, env);\n if (cond === true) return evalExpr(thenNode, env);\n if (cond === false) return evalExpr(orelseNode, env);\n return null;\n }\n if (name === 'BinaryExpression') {\n // string concat with +\n const op = findOp(node);\n if (op === '+') {\n const left = evalExpr(node.firstChild, env);\n const right = evalExpr(lastNamedChild(node), env);\n if (left !== null && right !== null) return left + right;\n }\n return null;\n }\n return null;\n}\n\nfunction firstNamedChild(node: SyntaxNode): SyntaxNode | null {\n let c = node.firstChild;\n while (c) {\n if (c.name !== '(' && c.name !== ')' && c.name !== ',' && c.name !== ':') return c;\n c = c.nextSibling;\n }\n return null;\n}\n\nfunction lastNamedChild(node: SyntaxNode): SyntaxNode | null {\n let c = node.lastChild;\n while (c) {\n if (c.name !== '(' && c.name !== ')' && c.name !== ',' && c.name !== ':') return c;\n c = c.prevSibling;\n }\n return null;\n}\n\n/** Find comparison/boolean operator token inside a BinaryExpression. */\nfunction findOp(node: SyntaxNode): string | null {\n let c = node.firstChild;\n while (c) {\n if (c.name === 'CompareOp' || c.name === 'and' || c.name === 'or' || c.name === 'UpdateOp') {\n return srcSlice(c).trim();\n }\n c = c.nextSibling;\n }\n return null;\n}\n\n// ==================== condition evaluation ====================\n\nfunction evalCondition(node: SyntaxNode | null, env: Env): boolean | null {\n if (!node) return null;\n const name = node.name;\n if (name === 'Boolean') {\n const t = srcSlice(node).trim();\n return t === 'True' ? true : t === 'False' ? false : null;\n }\n if (name === 'BinaryExpression') {\n const op = findOp(node);\n if (op === 'and' || op === 'or') {\n const parts = namedChildren(node);\n const vals = parts.map((p) => evalCondition(p, env));\n if (op === 'and') {\n if (vals.some((v) => v === false)) return false;\n if (vals.every((v) => v === true)) return true;\n return null;\n }\n if (vals.some((v) => v === true)) return true;\n if (vals.every((v) => v === false)) return false;\n return null;\n }\n // comparison\n const parts = namedChildren(node);\n if (parts.length !== 3) return null;\n const [left, opNode, right] = parts;\n const opText = srcSlice(opNode).trim();\n return evalCompare(left, opText, right, env);\n }\n if (name === 'UnaryExpression') {\n // not x\n const kw = node.getChild('not');\n if (kw) {\n const operand = kw.nextSibling;\n const v = evalCondition(operand, env);\n return v === null ? null : !v;\n }\n return null;\n }\n if (name === 'CallExpression') {\n // truthiness of call — cannot statically judge → null (fail-closed)\n return null;\n }\n return null;\n}\n\nfunction namedChildren(node: SyntaxNode): SyntaxNode[] {\n const out: SyntaxNode[] = [];\n let c = node.firstChild;\n while (c) {\n if (c.name !== '(' && c.name !== ')' && c.name !== ',' && c.name !== ':' && c.name !== '[' && c.name !== ']') {\n out.push(c);\n }\n c = c.nextSibling;\n }\n return out;\n}\n\nfunction evalCompare(left: SyntaxNode, opText: string, right: SyntaxNode, env: Env): boolean | null {\n // __name__ == \"__main__\"\n if (opText === '==' && left.name === 'VariableName' && srcSlice(left) === '__name__') {\n const rv = evalExpr(right, env);\n if (rv !== null) return rv === '__main__';\n return null;\n }\n if (opText === '==' || opText === '!=') {\n const lv = evalExpr(left, env);\n const rv = evalExpr(right, env);\n if (lv !== null && rv !== null) {\n return opText === '==' ? lv === rv : lv !== rv;\n }\n return null;\n }\n if (opText === 'in') {\n const lv = evalExpr(left, env);\n if (lv === null) return null;\n // right may be a Tuple/List/Array literal or a string\n const rightName = right.name;\n if (rightName === 'TupleExpression' || rightName === 'ArrayExpression' || rightName === 'SetExpression' || rightName === 'ParenthesizedExpression') {\n const container = rightName === 'ParenthesizedExpression' && right.firstChild && right.firstChild.name === 'TupleExpression'\n ? right.firstChild : right;\n for (const elt of namedChildren(container)) {\n const ev = evalExpr(elt, env);\n if (ev !== null && ev === lv) return true;\n }\n return false;\n }\n const rv = evalExpr(right, env);\n if (rv !== null) return rv.includes(lv);\n return null;\n }\n if (opText === '>' || opText === '>=' || opText === '<' || opText === '<=') {\n // len(sys.argv) > 1 form\n const lv = evalExpr(left, env);\n const rv = evalExpr(right, env);\n if (lv === null || rv === null) return null;\n const ln = parseInt(lv, 10);\n const rn = parseInt(rv, 10);\n if (Number.isNaN(ln) || Number.isNaN(rn)) return null;\n if (opText === '>') return ln > rn;\n if (opText === '>=') return ln >= rn;\n if (opText === '<') return ln < rn;\n return ln <= rn;\n }\n return null;\n}\n\n// ==================== control-flow pruning ====================\n\nfunction processStmts(stmts: SyntaxNode[], env: Env, lineStarts: number[], lines: Set<number>, branches: BranchInfo[]): void {\n for (const s of stmts) processStmt(s, env, lineStarts, lines, branches);\n}\n\n/**\n * If node contains a call to a non-pure function (user-defined etc., which may\n * mutate globals), invalidate the whole env. Leak guard: `def set_clean():\n * global mode; mode=\"clean\"` then `set_clean()` — env.mode is stale, a later\n * `if mode == \"clean\"` would wrongly prune the dangerous branch. Can't prove\n * the call has no global side effect → conservatively set all vars unknown\n * (fail-closed: keep everything).\n */\nfunction invalidateEnvOnCalls(node: SyntaxNode, env: Env): void {\n const cursor = node.cursor();\n cursor.iterate((n) => {\n const nd = n.node;\n if (nd.name !== 'CallExpression') return true;\n const func = nd.firstChild;\n if (func && func.name === 'VariableName' && !PURE_BUILTINS.has(srcSlice(func))) {\n for (const k of Object.keys(env.vars)) env.vars[k] = null;\n return false; // stop iterating\n }\n return true;\n });\n}\n\nfunction processStmt(stmt: SyntaxNode, env: Env, lineStarts: number[], lines: Set<number>, branches: BranchInfo[]): void {\n const name = stmt.name;\n // assignment: update env vars; RHS with non-pure call → invalidate env\n if (name === 'AssignStatement') {\n const target = stmt.firstChild;\n if (target && target.name === 'VariableName') {\n const valNode = target.nextSibling ? target.nextSibling.nextSibling : null; // skip AssignOp\n invalidateEnvOnCalls(stmt, env);\n const val = evalExpr(valNode, env);\n env.vars[srcSlice(target)] = val;\n }\n markNodeLines(stmt, lines, lineStarts);\n return;\n }\n // augmented assignment x += 1: var becomes unknown\n if (name === 'UpdateStatement') {\n const target = stmt.firstChild;\n if (target && target.name === 'VariableName') env.vars[srcSlice(target)] = null;\n invalidateEnvOnCalls(stmt, env);\n markNodeLines(stmt, lines, lineStarts);\n return;\n }\n // if / elif / else chain\n if (name === 'IfStatement') {\n processIf(stmt, env, lineStarts, lines, branches);\n return;\n }\n // loops / try / with / match: bodies kept (conservative); nested if still pruned.\n // LEAK GUARD: loop body may run 0/many times, try body may abort with exception,\n // with body may not run — body assignments are unreliable outside the block,\n // so process each body with an env COPY and never write back to the outer env\n // (fail-closed: keep more rather than miss).\n if (name === 'ForStatement' || name === 'WhileStatement') {\n markNodeLines(stmt, lines, lineStarts);\n for (const body of stmt.getChildren('Body')) {\n processStmts(bodyStmts(body), { argv: env.argv, vars: { ...env.vars } }, lineStarts, lines, branches);\n }\n return;\n }\n if (name === 'TryStatement') {\n markNodeLines(stmt, lines, lineStarts);\n for (const body of stmt.getChildren('Body')) {\n processStmts(bodyStmts(body), { argv: env.argv, vars: { ...env.vars } }, lineStarts, lines, branches);\n }\n return;\n }\n if (name === 'WithStatement') {\n markNodeLines(stmt, lines, lineStarts);\n const body = stmt.getChild('Body');\n if (body) processStmts(bodyStmts(body), { argv: env.argv, vars: { ...env.vars } }, lineStarts, lines, branches);\n return;\n }\n if (name === 'MatchStatement') {\n markNodeLines(stmt, lines, lineStarts);\n for (const clause of stmt.getChildren('MatchClause')) {\n const body = clause.getChild('Body');\n if (body) processStmts(bodyStmts(body), { argv: env.argv, vars: { ...env.vars } }, lineStarts, lines, branches);\n }\n return;\n }\n // def / class: whole tree kept (call-time env unknown), no inner pruning\n if (name === 'FunctionDefinition' || name === 'ClassDefinition') {\n markDefTree(stmt, lines, lineStarts);\n return;\n }\n // import / expression / everything else: keep.\n // top-level expression statement: non-pure function call (VariableName form)\n // may mutate globals → invalidate env (leak guard)\n if (name === 'ExpressionStatement') {\n invalidateEnvOnCalls(stmt, env);\n }\n markNodeLines(stmt, lines, lineStarts);\n}\n\nfunction markDefTree(stmt: SyntaxNode, lines: Set<number>, lineStarts: number[]): void {\n const cursor = stmt.cursor();\n cursor.iterate((n) => {\n markNodeLines(n.node, lines, lineStarts);\n return true;\n });\n}\n\nfunction bodyStmts(body: SyntaxNode): SyntaxNode[] {\n const out: SyntaxNode[] = [];\n let c = body.firstChild;\n while (c) {\n if (c.name !== ':' && c.name !== ';') out.push(c);\n c = c.nextSibling;\n }\n return out;\n}\n\n/** Process if/elif/else chain. Mirrors Python _process_if. */\nfunction processIf(stmt: SyntaxNode, env: Env, lineStarts: number[], lines: Set<number>, branches: BranchInfo[]): void {\n // collect sections: {cond|null, body, isElse}\n const sections: { cond: SyntaxNode | null; body: SyntaxNode | null; isElse: boolean }[] = [];\n let c = stmt.firstChild;\n while (c) {\n if (c.name === 'if' || c.name === 'elif') {\n sections.push({ cond: c.nextSibling ?? null, body: null, isElse: false });\n } else if (c.name === 'else') {\n sections.push({ cond: null, body: null, isElse: true });\n } else if (c.name === 'Body') {\n if (sections.length > 0 && sections[sections.length - 1].body === null) {\n sections[sections.length - 1].body = c;\n }\n }\n c = c.nextSibling;\n }\n processIfSections(stmt, sections, 0, env, lineStarts, lines, branches);\n}\n\nfunction processIfSections(\n _stmt: SyntaxNode,\n sections: { cond: SyntaxNode | null; body: SyntaxNode | null; isElse: boolean }[],\n idx: number,\n env: Env,\n lineStarts: number[],\n lines: Set<number>,\n branches: BranchInfo[],\n): void {\n if (idx >= sections.length) return;\n const s = sections[idx];\n // if header (condition is evaluated) always reachable: mark condition line(s)\n if (s.cond) markNodeLines(s.cond, lines, lineStarts);\n\n if (s.isElse) {\n // else reached only when all prior conditions provably False (guaranteed by recursion)\n if (s.body) processStmts(bodyStmts(s.body), env, lineStarts, lines, branches);\n return;\n }\n\n const cond = s.cond ? evalCondition(s.cond, env) : null;\n branches.push({\n kind: 'if',\n label: s.cond ? srcSlice(s.cond) : '',\n body: '',\n reachable: cond !== false,\n });\n\n if (cond === true) {\n // this branch taken; elif/else chain dropped\n if (s.body) processStmts(bodyStmts(s.body), env, lineStarts, lines, branches);\n return;\n }\n if (cond === false) {\n // this branch unreachable; try next (elif or else)\n processIfSections(_stmt, sections, idx + 1, env, lineStarts, lines, branches);\n return;\n }\n // condition not statically judgeable → keep this branch AND all remaining (fail-closed)\n if (s.body) processStmts(bodyStmts(s.body), env, lineStarts, lines, branches);\n for (let j = idx + 1; j < sections.length; j++) {\n const sj = sections[j];\n if (sj.cond) markNodeLines(sj.cond, lines, lineStarts);\n if (sj.body) processStmts(bodyStmts(sj.body), env, lineStarts, lines, branches);\n }\n}\n\n// ==================== child-call extraction ====================\n\nfunction parseShellString(s: string): ScriptCall | null {\n CHILD_CALL_RE.lastIndex = 0;\n let m: RegExpExecArray | null;\n while ((m = CHILD_CALL_RE.exec(s)) !== null) {\n const interp = m[1];\n const path = m[2].trim();\n let rest = m[3].trim();\n if (path.startsWith('-') || path.startsWith('$') || path.includes('/dev/')) continue;\n rest = rest.split(/[;|&<>]/)[0].trim();\n const args: string[] = [];\n for (const tm of rest.matchAll(/([\"'])(.*?)\\1|(\\S+)/g)) {\n args.push(tm[1] ? tm[2] : tm[3]);\n }\n return { path, args, interpreter: interp };\n }\n return null;\n}\n\nfunction extractCallsFromTree(tree: SyntaxNode, reachableLines: Set<number> | null): ScriptCall[] {\n const calls: ScriptCall[] = [];\n const seen = new Set<string>();\n\n const add = (c: ScriptCall) => {\n const key = `${c.path}\\u0000${c.args.join('\\u0000')}\\u0000${c.interpreter}`;\n if (!seen.has(key)) {\n seen.add(key);\n calls.push(c);\n }\n };\n\n const lineReachable = (node: SyntaxNode): boolean => {\n if (reachableLines === null) return true;\n return reachableLines.has(lineAt(buildLineStarts(SOURCE), node.from));\n };\n\n const cursor = tree.cursor();\n cursor.iterate((n) => {\n const node = n.node;\n if (node.name !== 'CallExpression') return true;\n if (!lineReachable(node)) return true;\n const func = node.firstChild;\n if (!func || func.name !== 'MemberExpression') return true;\n const modName = func.firstChild;\n if (!modName || modName.name !== 'VariableName') return true;\n const funcNameNode = func.getChild('PropertyName');\n if (!funcNameNode) return true;\n const mod = srcSlice(modName);\n const funcName = srcSlice(funcNameNode);\n\n const argList = node.getChild('ArgList');\n const firstArg = argList ? firstNamedChild(argList) : null;\n\n if (mod === 'subprocess' && SUBPROCESS_FUNCS.has(funcName)) {\n // list form: subprocess.run([\"bash\", \"x.sh\", \"arg\"])\n if (firstArg && (firstArg.name === 'ArrayExpression' || firstArg.name === 'TupleExpression')) {\n const elts: string[] = [];\n let allStr = true;\n for (const elt of namedChildren(firstArg)) {\n if (elt.name === 'String') elts.push(stringValue(srcSlice(elt)));\n else { allStr = false; break; }\n }\n if (allStr && elts.length >= 2) {\n const interp = elts[0];\n const path = elts[1];\n if (!path.startsWith('-') && !path.startsWith('$') && !path.includes('/dev/')) {\n add({ path, args: elts.slice(2), interpreter: interp });\n return true;\n }\n }\n }\n // string form: subprocess.run(\"bash x.sh backup\", shell=True)\n if (firstArg && firstArg.name === 'String') {\n const sc = parseShellString(stringValue(srcSlice(firstArg)));\n if (sc) add(sc);\n }\n } else if (mod === 'os' && OS_FUNCS.has(funcName)) {\n // os.system(\"bash x.sh backup\")\n if (firstArg && firstArg.name === 'String') {\n const sc = parseShellString(stringValue(srcSlice(firstArg)));\n if (sc) add(sc);\n }\n }\n return true;\n });\n\n // relative imports: from . import x / from .x import y\n const cursor2 = tree.cursor();\n cursor2.iterate((n) => {\n const node = n.node;\n if (node.name !== 'ImportStatement') return true;\n const txt = srcSlice(node);\n if (!/^from\\s+\\./m.test(txt)) return true;\n // extract module names after import keyword\n const m = txt.match(/\\bimport\\s+(.+)$/m);\n if (m) {\n for (const part of m[1].split(',')) {\n const name = part.trim().replace(/\\s+as\\s+\\w+$/, '');\n if (name && name !== '*') add({ path: name.replace(/\\./g, '/') + '.py', args: [], interpreter: 'python3' });\n }\n }\n return true;\n });\n\n return calls;\n}\n\nfunction extractCallsRegex(content: string): ScriptCall[] {\n const calls: ScriptCall[] = [];\n CHILD_CALL_RE.lastIndex = 0;\n let m: RegExpExecArray | null;\n while ((m = CHILD_CALL_RE.exec(content)) !== null) {\n const interp = m[1];\n const path = m[2].trim();\n let rest = m[3].trim();\n if (path.startsWith('-') || path.startsWith('$') || path.includes('/dev/')) continue;\n rest = rest.split(/[;|&<>]/)[0].trim();\n const args: string[] = [];\n for (const tm of rest.matchAll(/([\"'])(.*?)\\1|(\\S+)/g)) {\n args.push(tm[1] ? tm[2] : tm[3]);\n }\n calls.push({ path, args, interpreter: interp });\n }\n return calls;\n}\n\n// ==================== PythonBackend ====================\n\nexport class PythonBackend implements LanguageBackend {\n language = 'python';\n\n parse(content: string | null | undefined, entryArgs: string[] | null): ScriptIR {\n const c = content || '';\n SOURCE = c;\n const sourceLines = c.split('\\n');\n const lineStarts = buildLineStarts(c);\n const env = makeEnv(entryArgs || []);\n const lines = new Set<number>();\n const branches: BranchInfo[] = [];\n\n // budget fuse: over line limit → full text fail-closed\n if (sourceLines.length > MAX_LINES) {\n return {\n reachableContent: c,\n controlFlowResolved: false,\n calls: extractCallsRegex(c),\n branches: [],\n unresolvedSnippets: [],\n language: this.language,\n };\n }\n\n let tree: SyntaxNode;\n try {\n tree = parser.parse(c).topNode;\n } catch {\n // malformed script: full text fail-closed, still try to extract calls\n return {\n reachableContent: c,\n controlFlowResolved: false,\n calls: extractCallsRegex(c),\n branches: [],\n unresolvedSnippets: [],\n language: this.language,\n };\n }\n\n const stmts = bodyStmts(tree);\n processStmts(stmts, env, lineStarts, lines, branches);\n const reachable = reconstruct(sourceLines, lines);\n\n // child-call extraction (AST-first; only calls inside reachable branches)\n let calls = extractCallsFromTree(tree, lines);\n if (calls.length === 0) calls = extractCallsRegex(c);\n\n // resolved = content actually pruned (compare non-blank line sets, ignore trailing newline)\n const srcNonblank = sourceLines.filter((l) => l.trim().length > 0);\n const rcNonblank = reachable.split('\\n').filter((l) => l.trim().length > 0);\n const resolved = rcNonblank.length !== srcNonblank.length || rcNonblank.some((l, i) => l !== srcNonblank[i]);\n\n return {\n reachableContent: reachable,\n controlFlowResolved: resolved,\n calls,\n branches,\n unresolvedSnippets: [],\n language: this.language,\n };\n }\n}\n","/**\n * Script-engine language backends.\n * Mirrors Python agent_moss/engine/script_engine/backends/.\n */\n\nimport type { ScriptIR } from '../ir';\n\nexport interface LanguageBackend {\n language: string;\n /** Parse script content into IR. entryArgs may be null (no entry params). */\n parse(content: string, entryArgs: string[] | null): ScriptIR;\n}\n\nexport * from './shell-backend';\nexport { ShellBackend } from './shell-backend';\nexport { PythonBackend } from './python-backend';","/**\n * Script-engine ShellBackend — static shell (bash/sh/zsh) parser → IR.\n * Mirrors Python agent_moss/engine/script_engine/backends/shell_backend.py.\n *\n * Upgrades over old branch_aware_preprocess in script-content-analyzer.ts:\n * 1. case supports ANY selector ($1 / $MODE / ${1}), bindable from entryArgs.\n * 2. if supports string-equality conditions [ \"$1\" = \"clean\" ] etc.\n * 3. loops (while/for) body kept reachable (conservative).\n * 4. child script calls extracted WITH args (bash child.sh backup → args=['backup']),\n * enabling cross-script arg passing (fixes old sub-call arg loss bug).\n */\n\nimport { emptyIR, ScriptCall, ScriptIR } from '../ir';\nimport { LanguageBackend } from './index';\nimport { symbolicProcess } from '../symbolic';\n\n// ==================== arg binding ====================\n\nfunction bindPositionalArgs(content: string, args: string[]): string {\n if (!args.length) return content;\n const allArgs = args.join(' ');\n\n content = content.replace(/\\$\\{(\\d+|@|\\*)(?::?[-]?([^}]*))?\\}/g, (full, kind: string, defv: string) => {\n if (kind === '@' || kind === '*') return allArgs;\n if (!/^\\d+$/.test(kind)) return full;\n const idx = parseInt(kind, 10);\n if (1 <= idx && idx <= args.length) return args[idx - 1];\n return defv !== undefined ? defv : '';\n });\n content = content.replace(/\\$\\{(\\d+)\\}/g, (full, kind: string) => {\n const idx = parseInt(kind, 10);\n if (1 <= idx && idx <= args.length) return args[idx - 1];\n return '';\n });\n content = content.replace(/\\$(\\d+)/g, (full, kind: string) => {\n const idx = parseInt(kind, 10);\n if (1 <= idx && idx <= args.length) return args[idx - 1];\n return '';\n });\n content = content.replace(/\\$[@*]/g, allArgs);\n return content;\n}\n\n// ==================== case parsing ====================\n\nfunction findSelectorValue(selector: string, args: string[] | null): string | null {\n if (!args || !args.length) return null;\n const m = selector.match(/^\\$\\{?(\\d+)\\}?$/);\n if (m) {\n const idx = parseInt(m[1], 10);\n if (1 <= idx && idx <= args.length) return args[idx - 1];\n return null;\n }\n return null; // $MODE named var — not statically bindable\n}\n\nfunction splitCaseBody(body: string): { label: string; body: string }[] {\n const lines = body.split('\\n');\n const branches: { label: string; body: string }[] = [];\n let cur: { label: string; body: string } | null = null;\n for (const ln of lines) {\n const stripped = ln.trim();\n if (/^[\\w:-]+\\s*\\(\\)\\s*\\{/.test(stripped)) continue; // fn def\n const m = stripped.match(/^([^()]+?)\\s*\\)\\s*(.*)$/);\n if (m) {\n const pat = m[1].trim().replace(/^[\"']|[\"']$/g, '');\n const inline = m[2].trim();\n if (pat) {\n if (cur) branches.push(cur);\n cur = { label: pat, body: inline };\n }\n continue;\n }\n if (cur) {\n cur.body += (cur.body ? '\\n' + ln : ln);\n if (stripped.endsWith(';;')) {\n branches.push(cur);\n cur = null;\n }\n }\n }\n if (cur && cur.body.trim()) {\n if (!branches.includes(cur)) branches.push(cur);\n }\n return branches;\n}\n\nfunction parseCase(content: string, args: string[] | null): string | null {\n const m = content.match(/\\bcase\\s+(\\$\\{?\\d+\\}?|[A-Za-z_]\\w*|\\$[A-Za-z_]\\w*)\\s+in/i);\n if (!m) return null;\n const selector = m[1].trim();\n const val = findSelectorValue(selector, args);\n if (val === null) return null;\n\n const lines = content.split('\\n');\n // 深度配对找本层 esac(嵌套 case 时不能 indexOf 第一个)\n const endMatch = findCaseEndInLines(lines, 0);\n if (endMatch === -1) return null;\n const bodyLines = lines.slice(1, endMatch);\n const body = bodyLines.join('\\n');\n\n const hasNested = /\\bcase\\s+/.test(body) || /\\bif\\s+/.test(body);\n let final: string | null;\n if (hasNested) {\n // 外层仍剪枝:选中分支整体保留(内层候选不细化),未选中剔除\n final = splitNestedCaseBranches(bodyLines, val);\n if (final === null) return null;\n } else {\n const branches = splitCaseBody(body);\n let selected: string | null = null;\n let fallback = '';\n for (const b of branches) {\n const values = b.label.split('|').map(v => v.trim()).filter(Boolean);\n if (values.includes('*')) fallback = b.body;\n else if (values.includes(val)) selected = b.body;\n }\n final = selected !== null ? selected : (fallback || null);\n if (final === null) return null;\n }\n\n const prefix = content.slice(0, m.index ?? 0);\n const suffix = lines.slice(endMatch + 1).join('\\n');\n return `${prefix}\\n${final}\\n${suffix}`;\n}\n\n/** Depth-match: find the line index of the esac paired with the case at headerLine. */\nfunction findCaseEndInLines(lines: string[], headerLine: number): number {\n let depth = 0;\n for (let idx = headerLine; idx < lines.length; idx++) {\n const ln = lines[idx];\n const opens = (ln.match(/\\bcase\\b/g) || []).length;\n const closes = (ln.match(/\\besac\\b/g) || []).length;\n depth += opens - closes;\n if (depth <= 0 && idx > headerLine) return idx;\n }\n return -1;\n}\n\n/** Nested case: outer branch selection, preserving selected branch body (incl. nested). */\nfunction splitNestedCaseBranches(bodyLines: string[], selectorVal: string): string | null {\n let depth = 0;\n let curPat: string | null = null;\n let curBody: string[] = [];\n let selected: string | null = null;\n let fallback: string | null = null;\n\n const flush = () => {\n if (curPat === null) return;\n const values = curPat.split('|').map(v => v.trim()).filter(Boolean);\n const body = curBody.join('\\n');\n if (values.includes('*')) { if (fallback === null) fallback = body; }\n else if (values.includes(selectorVal)) { selected = body; }\n curPat = null;\n curBody = [];\n };\n\n for (const ln of bodyLines) {\n const stripped = ln.trim();\n if (depth === 0) {\n const bm = stripped.match(/^([^()]+?)\\s*\\)\\s*(.*)$/);\n if (bm) {\n if (curPat !== null) flush();\n curPat = bm[1].trim().replace(/^[\"']|[\"']$/g, '');\n curBody = bm[2].trim() ? [bm[2].trim()] : [];\n continue;\n }\n }\n if (/\\bcase\\b/.test(stripped)) depth += 1;\n else if (/\\besac\\b/.test(stripped)) depth = Math.max(0, depth - 1);\n else if (curPat !== null) {\n curBody.push(ln);\n if (depth === 0 && stripped.endsWith(';;')) flush();\n }\n }\n if (curPat !== null && curBody.length) flush();\n\n return selected !== null ? selected : fallback;\n}\n\n// ==================== if parsing ====================\n\nfunction evalIfCondition(cond: string, args: string[] | null): boolean | null {\n if (!args || !args.length) return null;\n let inner = cond.replace(/^\\[\\[?|\\]\\]?$/g, '').replace(/\"/g, '').replace(/'/g, '').trim();\n const m = inner.match(/(.*?)\\s*(==|=)\\s*(.*)/);\n if (!m) return null;\n let left = m[1].trim();\n let right = m[3].trim();\n const lm = left.match(/^\\$(\\d+)$/);\n if (lm) {\n const idx = parseInt(lm[1], 10);\n if (1 <= idx && idx <= args.length) left = args[idx - 1];\n else return null;\n } else if (left.startsWith('$')) return null;\n const rm = right.match(/^\\$(\\d+)$/);\n if (rm) {\n const idx = parseInt(rm[1], 10);\n if (1 <= idx && idx <= args.length) right = args[idx - 1];\n else return null;\n } else if (right.startsWith('$')) return null;\n return left === right;\n}\n\nfunction parseIf(content: string, args: string[] | null): string | null {\n const m = content.match(/\\bif\\s+([^\\n;]+?)\\s*;\\s*then/i);\n if (!m) return null;\n const truth = evalIfCondition(m[1].trim(), args);\n if (truth === null) return null;\n\n const start = m.index ?? 0;\n const thenBodyStart = start + m[0].length;\n const fiPos = content.indexOf('fi', thenBodyStart);\n if (fiPos === -1) return null;\n const segment = content.slice(thenBodyStart, fiPos);\n const elseM = segment.match(/\\belse\\b/);\n let chosen: string;\n if (truth) chosen = elseM ? segment.slice(0, elseM.index) : segment;\n else {\n if (!elseM) return null;\n chosen = segment.slice((elseM.index ?? 0) + 4); // len('else') == 4\n }\n return `${content.slice(0, start)}\\n${chosen}\\n${content.slice(fiPos + 2)}`;\n}\n\n// ==================== loops (conservative) ====================\n\nfunction markLoopsReachable(content: string): string {\n // Conservative: loop body always kept (can't prove unreachable). No-op.\n return content;\n}\n\n// ==================== child call extraction (with args) ====================\n\nconst CHILD_CALL_RE = /(?:^|\\s|&&|\\|\\|)\\s*((?:\\/bin\\/)?bash|sh|zsh|(?:python|python3|node|ruby|perl|php|lua))\\s+(\\S+(?:\\.(?:sh|shrc|py|js|rb|pl|php|lua))?)([^\\n;|&]*?)$/gmi;\n\nfunction extractCallsFromContent(content: string): ScriptCall[] {\n const calls: ScriptCall[] = [];\n let m: RegExpExecArray | null;\n CHILD_CALL_RE.lastIndex = 0;\n while ((m = CHILD_CALL_RE.exec(content)) !== null) {\n const interp = m[1];\n const path = m[2].trim();\n let rest = m[3].trim();\n if (path.startsWith('-') || path.startsWith('$') || path.includes('/dev/')) continue;\n rest = rest.split(/[;|&<>]/)[0].trim();\n const args: string[] = [];\n for (const tm of rest.matchAll(/([\"'])(.*?)\\1|(\\S+)/g)) {\n args.push(tm[1] ? tm[2] : tm[3]);\n }\n calls.push({ path, args, interpreter: interp });\n }\n return calls;\n}\n\n// ==================== ShellBackend ====================\n\nexport class ShellBackend implements LanguageBackend {\n language = 'shell';\n\n parse(content: string | null | undefined, entryArgs: string[] | null): ScriptIR {\n const c = content || '';\n const orig = c;\n let candidate = c;\n let resolved = false;\n\n // 位置参数/变量绑定安全性检测:命中则跳过 P1 的 $1 绑定剪枝。\n // 漏报防护(NEW-FN):shift / set -- / read / 函数定义 会改写 $1 语义或\n // 函数内 $1 是函数参数而非入口参数 → $1 绑定不可靠,交 symbolic fail-closed。\n // `set --` 后是空格,`--` 末尾不能用 \\b(- 非词字符,后无词边界)\n const p1Safe = !/(?:\\bshift\\b|\\bset\\s+--(?:\\s|$)|[\\s;|&]read\\b|^\\s*read\\b|\\(\\)\\s*\\{|function\\s+\\w+)/.test(c);\n\n if (p1Safe) {\n // P1: existing case/if literal slicing\n const caseOut = parseCase(candidate, entryArgs);\n if (caseOut !== null && caseOut !== candidate) { resolved = true; candidate = caseOut; }\n const ifOut = parseIf(candidate, entryArgs);\n if (ifOut !== null && ifOut !== candidate) { resolved = true; candidate = ifOut; }\n }\n let bound = p1Safe ? bindPositionalArgs(candidate, entryArgs || []) : candidate;\n\n // P2/P3/P4: LiteSE symbolic executor (upgrade when P1 can't resolve)\n if (!resolved) {\n const symOut = symbolicProcess(c, entryArgs);\n if (symOut !== null && symOut !== c) {\n resolved = true;\n bound = symOut;\n }\n }\n\n // loops: conservative\n const loopMarked = markLoopsReachable(bound);\n // child calls\n const calls = extractCallsFromContent(loopMarked);\n\n return {\n reachableContent: loopMarked,\n controlFlowResolved: resolved,\n calls,\n branches: [],\n unresolvedSnippets: [],\n language: this.language,\n };\n }\n}","/**\n * LiteSE symbolic environment executor — TS side.\n * Mirrors Python agent_moss/engine/script_engine/backends/symbolic.py EXACTLY\n * (fields, algorithms, return semantics). Do not diverge.\n *\n * Upgrades ShellBackend when P1 (literal replace + case/if string equality)\n * cannot resolve:\n * 1. variable concatenation: `case \"prefix${1}suffix\"` / `${1}${2}`\n * 2. internal named-variable tracking: `MODE=clean; case $MODE`\n * 3. glob pattern branches: `case $1 in bak*)`\n * 4. numeric condition branches: `if [ \"$1\" -gt 5 ]`\n *\n * Design (performance fence):\n * - SVal concrete/symbol/expr; expr folds to concrete when all children concrete.\n * - Sequential execution with env map (var -> SVal).\n * - case/if: selector/cond folded via env to concrete → precise match;\n * can't fold → return null (caller fail-closed).\n * - glob: glob -> regex (JS RegExp), concrete-only match; symbol -> null.\n * - numeric: concrete-int only; symbol -> null.\n * - budgets (lines/branches) + MAX_VARS; over budget -> null (caller full-text).\n */\n\n// ==================== local helpers (no external deps) ====================\n\nfunction reescape(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\nconst RE_DOTALL = 's';\n\n// ==================== budgets (P5) ====================\n\nconst MAX_LINES = 500;\nconst MAX_BRANCHES = 50;\nconst MAX_VARS = 200;\n\n// ==================== SVal ====================\n\nexport type SValKind = 'concrete' | 'symbol' | 'expr';\n\nexport interface SVal {\n kind: SValKind;\n value: string | null;\n children: SVal[];\n op: string;\n}\n\nexport function svalConc(v: string): SVal {\n return { kind: 'concrete', value: v, children: [], op: '' };\n}\nfunction svalSym(name: string): SVal {\n return { kind: 'symbol', value: name, children: [], op: '' };\n}\nfunction svalExpr(children: SVal[]): SVal {\n return { kind: 'expr', value: null, children, op: '+' };\n}\n\nexport function fold(val: SVal): SVal {\n if (val.kind !== 'expr') return val;\n const parts: string[] = [];\n for (const c of val.children) {\n const cc = fold(c);\n if (cc.kind === 'concrete') {\n parts.push(cc.value || '');\n } else {\n return cc; // symbol → propagate (can't fold)\n }\n }\n return svalConc(parts.join(''));\n}\n\n// ==================== statement model ====================\n\ninterface BaseStmt {\n line: string;\n modelable: boolean;\n}\ninterface AssignStmt extends BaseStmt {\n kind: 'assign';\n name: string;\n rhs: string;\n}\ninterface CaseStmt extends BaseStmt {\n kind: 'case';\n selector: string;\n branches: { pat: string; body: string }[];\n}\ninterface IfStmt extends BaseStmt {\n kind: 'if';\n cond: string;\n thenBody: string;\n elseBody: string | null;\n}\ninterface PlainStmt extends BaseStmt {\n kind: 'plain';\n}\ntype Stmt = AssignStmt | CaseStmt | IfStmt | PlainStmt;\n\n// ==================== tokenize ====================\n\nconst ASGN_RE = /^\\s*(?:export\\s+)?([A-Za-z_][A-Za-z0-9_]*)=(.*)$/;\nconst CASE_START_RE = /^\\s*case\\s+/;\nconst IF_START_RE = /^\\s*if\\s+/;\nconst NOT_MODELED_RE = /\\$\\(|`[^`]*`/;\n\n// ==================== nested depth matching ====================\n// Fix: original parseCaseStmt/parseIfStmt used indexOf('esac') / lastIndexOf('fi')\n// / line-includes——nested case/if took the inner keyword and truncated the outer\n// block (cutting branches wrong). Depth counting pairs open/close keywords:\n// each open (+1), close (-1), depth reaches 0 → the matching close. Linear O(lines).\n\nconst CASE_OPEN_RE = /\\bcase\\b/;\nconst CASE_CLOSE_RE = /\\besac\\b/;\nconst IF_OPEN_RE = /\\bif\\b/;\nconst IF_CLOSE_RE = /\\bfi\\b/;\n\nfunction countMatches(re: RegExp, s: string): number {\n const m = s.match(re);\n return m ? m.length : 0;\n}\n\n/** Find the closing line index for open keyword at startLine. -1 if unclosed. */\nfunction findBlockEnd(lines: string[], startLine: number, openRe: RegExp, closeRe: RegExp): number {\n let depth = 0;\n for (let idx = startLine; idx < lines.length; idx++) {\n depth += countMatches(openRe, lines[idx]) - countMatches(closeRe, lines[idx]);\n if (depth <= 0 && idx > startLine) return idx;\n }\n return -1;\n}\n\nfunction findCaseEnd(lines: string[], start: number): number {\n return findBlockEnd(lines, start, CASE_OPEN_RE, CASE_CLOSE_RE);\n}\nfunction findIfEnd(lines: string[], start: number): number {\n return findBlockEnd(lines, start, IF_OPEN_RE, IF_CLOSE_RE);\n}\n\nconst LOOP_DO_RE = /\\bdo\\b/g;\nconst LOOP_DONE_RE = /\\bdone\\b/g;\n\n/** Loop block (while/for/until ... do ... done) closing line. -1 if unclosed. */\nfunction findLoopEnd(lines: string[], start: number): number {\n let depth = 0;\n for (let idx = start; idx < lines.length; idx++) {\n depth += countMatches(LOOP_DO_RE, lines[idx]) - countMatches(LOOP_DONE_RE, lines[idx]);\n if (depth <= 0 && idx > start) return idx;\n }\n return -1;\n}\n\nconst FN_DEF_RE = /^\\s*(?:function\\s+)?[A-Za-z_][A-Za-z0-9_]*\\s*\\(\\s*\\)\\s*\\{/;\nconst FN_DEF_KW_RE = /^\\s*function\\s+[A-Za-z_][A-Za-z0-9_]*\\s*\\{?/;\n\n/** Function definition block (name() { ... }) closing line. -1 if unclosed. */\nfunction findFnEnd(lines: string[], start: number): number {\n let depth = 0;\n for (let idx = start; idx < lines.length; idx++) {\n depth += (lines[idx].match(/\\{/g) || []).length - (lines[idx].match(/\\}/g) || []).length;\n if (depth <= 0 && idx > start) return idx;\n }\n return -1;\n}\n\nfunction stripComments(content: string): string {\n return content.split('\\n').filter(l => !l.trimStart().startsWith('#')).join('\\n');\n}\n\nfunction parseCaseStmt(block: string): CaseStmt | null {\n const header = block.match(/\\s*case\\s+(\\S[^;]*?)\\s*\\bin\\b[\\s\\S]*/);\n if (!header) return null;\n const sel = header[1].trim();\n\n const lines = block.split('\\n');\n // 定位 header 行(含 \"in\")之后 body 起始行\n let headerLine = 0;\n for (let i = 0; i < lines.length; i++) {\n if (/\\bin\\b/.test(lines[i]) && /\\bcase\\b/.test(lines[i])) { headerLine = i; break; }\n }\n const bodyStartLine = headerLine + 1;\n // 深度配对找本层 esac(嵌套 case 时不能 indexOf 第一个)\n const endLine = findCaseEnd(lines, 0);\n if (endLine === -1) return null;\n\n // 深度感知分支切分:内层 case 的 `pattern)` 行(depth>0)不作为外层分支。\n // 用与 splitNestedCaseBranches 相同的深度计数逻辑,保证 case-in-case 时\n // 外层分支边界正确、内层内容保留在选中分支 body 中。\n const branches = splitCaseBranchesDepthAware(lines.slice(bodyStartLine, endLine));\n\n // 无分支(无 `pattern)`)或切分失败 → null(fail-closed 回退全文)\n if (!branches.length) return null;\n\n return { kind: 'case', line: block, modelable: true, selector: sel, branches };\n}\n\n/** 深度感知的 case 分支切分:depth 0 的 `pattern)` 才是外层分支。 */\nfunction splitCaseBranchesDepthAware(bodyLines: string[]): { pat: string; body: string }[] {\n let depth = 0;\n let curPat: string | null = null;\n let curBody: string[] = [];\n const branches: { pat: string; body: string }[] = [];\n const flush = () => {\n if (curPat !== null) {\n branches.push({ pat: curPat, body: curBody.join('\\n') });\n }\n curPat = null;\n curBody = [];\n };\n for (const ln of bodyLines) {\n const stripped = ln.trim();\n if (depth === 0) {\n const bm = stripped.match(/^([^()]+?)\\s*\\)\\s*(.*)$/);\n if (bm) {\n if (curPat !== null) flush();\n curPat = bm[1].trim().replace(/^[\"']|[\"']$/g, '');\n curBody = bm[2].trim() ? [bm[2].trim()] : [];\n continue;\n }\n }\n if (/\\bcase\\b/.test(stripped)) depth += 1;\n else if (/\\besac\\b/.test(stripped)) depth = Math.max(0, depth - 1);\n else if (curPat !== null) {\n curBody.push(ln);\n if (depth === 0 && stripped.endsWith(';;')) flush();\n }\n }\n if (curPat !== null && curBody.length) flush();\n return branches;\n}\n\nfunction parseIfStmt(block: string): IfStmt | null {\n const m = block.match(/\\s*if\\s+([^\\n;]+?)\\s*;\\s*then/);\n if (!m) return null;\n const cond = m[1].trim();\n\n const lines = block.split('\\n');\n const fiLine = findIfEnd(lines, 0);\n if (fiLine === -1) return null;\n // then 到本层 fi 之间的 body\n const body = lines.slice(1, fiLine).join('\\n');\n\n const elseM = /\\belse\\b/.exec(body);\n let thenBody: string;\n let elseBody: string | null;\n if (elseM) {\n thenBody = body.slice(0, elseM.index);\n elseBody = body.slice(elseM.index! + 4);\n } else {\n thenBody = body;\n elseBody = null;\n }\n return { kind: 'if', line: block, modelable: true, cond, thenBody, elseBody };\n}\n\nfunction tokenize(content: string): Stmt[] {\n const lines = stripComments(content).split('\\n');\n const stmts: Stmt[] = [];\n let i = 0;\n while (i < lines.length) {\n const ln = lines[i];\n const stripped = ln.trim();\n if (!stripped) { i++; continue; }\n\n // loop block while/for/until ... do ... done: body assignments unreliable\n // outside the loop (may run 0/many times) → whole block NotModeled\n // → symbolicProcess returns null → caller fail-closed full text\n if (/\\b(?:while|for|until)\\b/.test(stripped) && !CASE_START_RE.test(stripped) && !IF_START_RE.test(stripped)) {\n const endLine = findLoopEnd(lines, i);\n if (endLine !== -1) {\n for (let k = i; k <= endLine; k++) stmts.push({ kind: 'plain', line: lines[k], modelable: false });\n i = endLine + 1;\n continue;\n }\n stmts.push({ kind: 'plain', line: ln, modelable: false });\n i++;\n continue;\n }\n\n // function definition name() { ... } / function name { ... }: $1 inside the\n // function is the function arg, not the entry arg; body runs only on call and\n // may modify globals → whole block NotModeled\n if (FN_DEF_RE.test(stripped) || FN_DEF_KW_RE.test(stripped)) {\n const endLine = findFnEnd(lines, i);\n if (endLine !== -1) {\n for (let k = i; k <= endLine; k++) stmts.push({ kind: 'plain', line: lines[k], modelable: false });\n i = endLine + 1;\n continue;\n }\n stmts.push({ kind: 'plain', line: ln, modelable: false });\n i++;\n continue;\n }\n\n // case block\n if (CASE_START_RE.test(stripped)) {\n const endLine = findCaseEnd(lines, i);\n if (endLine === -1) { stmts.push({ kind: 'plain', line: ln, modelable: false }); i++; continue; }\n const parsed = parseCaseStmt(lines.slice(i, endLine + 1).join('\\n'));\n stmts.push(parsed || { kind: 'plain', line: ln, modelable: false });\n i = endLine + 1;\n continue;\n }\n\n // if block\n if (IF_START_RE.test(stripped)) {\n const endLine = findIfEnd(lines, i);\n if (endLine === -1) { stmts.push({ kind: 'plain', line: ln, modelable: false }); i++; continue; }\n const parsed = parseIfStmt(lines.slice(i, endLine + 1).join('\\n'));\n stmts.push(parsed || { kind: 'plain', line: ln, modelable: false });\n i = endLine + 1;\n continue;\n }\n\n // shift / set -- / read change positional args or var bindings → $1 semantics\n // change, P1 binding unreliable. Note: `set -e` does NOT change positional args;\n // only `set --` (followed by args). `set --` is followed by a space, so `--`\n // cannot end with \\b (non-word char, no word boundary after it).\n if (/\\bshift\\b|\\bset\\s+--(?:\\s|$)|[\\s;|&]read\\b|^\\s*read\\b/.test(stripped)) {\n stmts.push({ kind: 'plain', line: ln, modelable: false });\n i++;\n continue;\n }\n\n const am = stripped.match(ASGN_RE);\n if (am && !NOT_MODELED_RE.test(stripped)) {\n stmts.push({ kind: 'assign', line: stripped, modelable: true, name: am[1], rhs: am[2].trim() });\n i++;\n continue;\n }\n\n stmts.push(NOT_MODELED_RE.test(stripped)\n ? { kind: 'plain', line: ln, modelable: false }\n : { kind: 'plain', line: ln, modelable: true });\n i++;\n }\n return stmts;\n}\n\n// ==================== expression eval (P2) ====================\n\nconst EXPR_SPLIT_RE = /(\\$\\{?\\d+\\}?|\\$\\{?[A-Za-z_][A-Za-z0-9_]*\\}?)/;\n\nexport function evalExpr(text: string, env: Map<string, SVal>): SVal {\n // quote semantics: \"...\" expands; '...' literal\n const isSingleQuoted = text.length >= 2 && text[0] === \"'\" && text[text.length - 1] === \"'\";\n if (text.length >= 2 && (text[0] === '\"' || text[0] === \"'\") && text[text.length - 1] === text[0]) {\n text = text.slice(1, -1);\n }\n if (isSingleQuoted) return svalConc(text);\n\n const parts = text.split(EXPR_SPLIT_RE);\n const result: SVal[] = [];\n for (const p of parts) {\n if (!p) continue;\n const brace = p.match(/^\\$\\{([^}]+)\\}$/);\n if (brace) {\n const inner = brace[1];\n if (/^\\d+$/.test(inner)) {\n const v = env.get(`$${inner}`);\n result.push(v || svalSym(`$${inner}`));\n } else {\n const v = env.get(inner);\n result.push(v || svalSym(inner));\n }\n continue;\n }\n const bare = p.match(/^\\$([A-Za-z_][A-Za-z0-9_]*|\\d+)$/);\n if (bare) {\n const varName = bare[1];\n const key = /^\\d+$/.test(varName) ? `$${varName}` : varName;\n const v = env.get(key);\n result.push(v || svalSym(p));\n continue;\n }\n result.push(svalConc(p));\n }\n if (result.length === 1) return fold(result[0]);\n return fold(svalExpr(result));\n}\n\n// ==================== init env ====================\n\nfunction initEnv(entryArgs: string[] | null): Map<string, SVal> {\n const env = new Map<string, SVal>();\n if (entryArgs && entryArgs.length) {\n entryArgs.forEach((a, idx) => env.set(`$${idx + 1}`, svalConc(a)));\n env.set('$@', svalConc(entryArgs.join(' ')));\n env.set('$*', svalConc(entryArgs.join(' ')));\n }\n return env;\n}\n\n// ==================== glob (P4) ====================\n\nconst HAS_GLOB = /[*?[]/;\n\nexport function globToRegex(pattern: string): RegExp {\n let out = '^';\n let i = 0;\n while (i < pattern.length) {\n const c = pattern[i];\n if (c === '*') out += '.*';\n else if (c === '?') out += '.';\n else if (c === '[') {\n let j = i + 1;\n let neg = false;\n if (j < pattern.length && (pattern[j] === '!' || pattern[j] === '^')) { neg = true; j++; }\n let cls = '';\n while (j < pattern.length && pattern[j] !== ']') { cls += pattern[j]; j++; }\n if (j >= pattern.length) {\n out += reescape(pattern.slice(i));\n break;\n }\n out += '[' + (neg ? '^' : '') + reescape(cls) + ']';\n i = j;\n } else {\n out += reescape(c);\n }\n i++;\n }\n out += '$';\n return new RegExp(out, RE_DOTALL);\n}\n\nexport function matchGlob(pattern: string, value: string): boolean {\n if (!HAS_GLOB.test(pattern)) return pattern === value;\n return globToRegex(pattern).test(value);\n}\n\n// ==================== numeric compare (P4) ====================\n\nexport function evalNumericCompare(op: string, left: string, right: string): boolean | null {\n const li = parseInt(left, 10);\n const ri = parseInt(right, 10);\n if (isNaN(li) || isNaN(ri)) return null;\n switch (op) {\n case '-gt': return li > ri;\n case '-lt': return li < ri;\n case '-eq': return li === ri;\n case '-ge': return li >= ri;\n case '-le': return li <= ri;\n default: return null;\n }\n}\n\n// ==================== if condition (P2/P4) ====================\n\nfunction resolveVarSide(tok: string, env: Map<string, SVal>): string | null {\n if (!tok.startsWith('$')) return tok;\n const ev = evalExpr(tok, env);\n return ev.kind === 'concrete' ? ev.value : null;\n}\n\nexport function evalCondition(cond: string, env: Map<string, SVal>): boolean | null {\n let inner = cond.trim().replace(/^\\[\\[?|\\]\\]?$/g, '').trim();\n if (/^-[A-Za-z]\\s/.test(inner) || inner.startsWith('-d') || inner.startsWith('-f')) return null;\n const innerQ = inner.replace(/\"/g, '').replace(/'/g, '');\n\n // numeric\n for (const op of ['-gt', '-lt', '-eq', '-ge', '-le']) {\n const re = new RegExp(`\\\\s${op}\\\\s`);\n const opm = re.exec(innerQ);\n if (!opm) continue;\n const left = innerQ.slice(0, opm.index).trim();\n // opm[0] 是 \\s-gt\\s(含两侧空格),其末尾才是操作数起点\n const right = innerQ.slice(opm.index + opm[0].length).trim();\n const lv = resolveVarSide(left, env);\n const rv = resolveVarSide(right, env);\n if (lv === null || rv === null) return null;\n return evalNumericCompare(op, lv, rv);\n }\n\n // string equal / not / regex\n const sm = innerQ.match(/(.*?)\\s*(==|=|!=|=~)\\s*(.*)/);\n if (!sm) return null;\n const op = sm[2];\n let left = sm[1].trim();\n let right = sm[3].trim();\n if (op === '=~') {\n if (right.startsWith('/') && right.endsWith('/')) right = right.slice(1, -1);\n const lv = resolveVarSide(left, env);\n if (lv === null) return null;\n try { return new RegExp(right).test(lv); } catch { return null; }\n }\n const lv = resolveVarSide(left, env);\n const rv = resolveVarSide(right, env);\n if (lv === null || rv === null) return null;\n if (op === '!=') return lv !== rv;\n return lv === rv;\n}\n\n// ==================== executor ====================\n\nexport function symbolicProcess(content: string, entryArgs: string[] | null): string | null {\n if (!content) return null;\n const stmts = tokenize(content);\n if (!stmts.some(s => s.kind === 'case' || s.kind === 'if' || s.kind === 'assign')) return null;\n if (stmts.some(s => !s.modelable)) return null;\n\n const env = initEnv(entryArgs);\n let linesBudget = 0;\n let branchesBudget = 0;\n let modelable = false;\n const out: string[] = [];\n\n for (const s of stmts) {\n linesBudget++;\n if (linesBudget > MAX_LINES) return null;\n\n if (s.kind === 'assign') {\n modelable = true;\n if (env.size >= MAX_VARS) return null;\n const v = evalExpr(s.rhs, env);\n env.set(s.name, fold(v));\n out.push(s.line);\n continue;\n }\n\n if (s.kind === 'case') {\n modelable = true;\n branchesBudget += s.branches.length;\n if (branchesBudget > MAX_BRANCHES) return null;\n const selVal = fold(evalExpr(s.selector, env));\n if (selVal.kind !== 'concrete') return null; // symbol selector -> fail-closed\n const concrete = selVal.value || '';\n let selected: string | null = null;\n let fallback = '';\n for (const b of s.branches) {\n const patStripped = b.pat.trim();\n if (patStripped === '*') { fallback = b.body; continue; }\n if (matchGlob(patStripped, concrete)) { selected = b.body; break; }\n }\n const final = selected !== null ? selected : (fallback || null);\n if (final === null) return null;\n out.push(`case ${s.selector} in\\n${final}\\nesac`);\n continue;\n }\n\n if (s.kind === 'if') {\n modelable = true;\n branchesBudget++;\n if (branchesBudget > MAX_BRANCHES) return null;\n const truth = evalCondition(s.cond, env);\n if (truth === null) return null; // unknown -> fail-closed\n const chosen = truth ? s.thenBody : s.elseBody;\n if (chosen === null) return null;\n out.push(`if ${s.cond}; then\\n${chosen}\\nfi`);\n continue;\n }\n\n out.push(s.line);\n }\n\n if (!modelable) return null;\n return out.join('\\n');\n}","/**\n * Brain module — TypeScript implementation.\n *\n * Mirrors Python agent_moss/brain/ (rule_store + pattern_extractor + curator).\n * Default OFF: only active when AGENT_MOSS_BRAIN_ENABLED=1 (see isBrainEnabled\n * in ../config). When off, no store is created and checks are no-ops.\n */\n\nimport { BrainRuleStore } from './rule-store';\nimport { PatternExtractor } from './pattern-extractor';\n\nexport { BrainRuleStore } from './rule-store';\nexport { PatternExtractor } from './pattern-extractor';\nexport { createBrainReviewer, parseReview } from './reviewer';\n\nexport interface BrainCheckResult {\n ruleId: string;\n pattern: string;\n explanation: string;\n confidence: number;\n}\n\n/**\n * Check active brain rules against an action. Layer 1 = current action only;\n * Layer 2 = may consult action history. Returns the first matching rule.\n */\nexport function checkBrainRules(\n store: BrainRuleStore | null,\n opts: {\n layer: number;\n actionType: string;\n actionDetail: string;\n actionHistory?: { actionType: string; actionDetail: string }[];\n },\n): BrainCheckResult | null {\n if (!store) return null;\n const rules = store.getActiveRules(opts.layer);\n if (rules.length === 0) return null;\n\n const combined = `${opts.actionType} ${opts.actionDetail}`;\n for (const rule of rules) {\n try {\n if (new RegExp(rule.pattern, 'i').test(combined)) {\n // Layer 2 rules may need history context\n if (opts.layer === 2 && opts.actionHistory) {\n if (!checkLayer2Context(rule.pattern, opts.actionHistory, opts.actionDetail)) {\n continue;\n }\n }\n store.recordTrigger(rule.id);\n return {\n ruleId: rule.id,\n pattern: rule.pattern,\n explanation: rule.explanation,\n confidence: rule.confidence,\n };\n }\n } catch {\n continue;\n }\n }\n return null;\n}\n\nfunction checkLayer2Context(\n pattern: string,\n actionHistory: { actionType: string; actionDetail: string }[],\n actionDetail: string,\n): boolean {\n if (pattern.startsWith('BEHAVIOR_CHAIN:')) {\n const chainType = pattern.replace('BEHAVIOR_CHAIN:', '');\n if (chainType === 'external_read→sensitive_write') {\n const hasExternalRead = actionHistory.slice(-5).some(h =>\n /curl|wget|http/i.test(h.actionDetail ?? ''));\n const isSensitiveWrite = /\\.ssh|\\.gnupg|authorized_keys|bashrc|profile/i.test(actionDetail);\n return hasExternalRead && isSensitiveWrite;\n }\n if (chainType === 'multi_config_read→privilege_action') {\n const configReads = actionHistory.slice(-5).filter(h =>\n /\\/etc\\/|config|\\.conf|\\.yaml|\\.json/i.test(h.actionDetail ?? '')).length;\n const isPrivilege = /sudo|su |chmod|chown/i.test(actionDetail);\n return configReads >= 2 && isPrivilege;\n }\n return false;\n }\n return true;\n}","/**\n * Brain rule store — TypeScript implementation.\n *\n * Mirrors Python agent_moss/brain/rule_store.py but stores rules in a JSON file\n * (Python uses SQLite; TS has no sqlite dependency). Semantics are equivalent:\n * rules have a status lifecycle (draft → approved → active → disputed/stale →\n * archived), and pattern_candidates accumulate occurrences before a draft rule\n * is created.\n *\n * Storage: ~/.agentmoss/brain/rules.json (matches Python DB location ~/.agentmoss)\n * env override: AGENT_MOSS_BRAIN_RULES_PATH (tests use this to isolate)\n */\n\nimport { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\n\nexport const BRAIN_DIR = '.';\nexport const DEFAULT_RULES_PATH = join(homedir(), '.agentmoss', 'brain', 'rules.json');\nconst ENV_RULES_PATH = 'AGENT_MOSS_BRAIN_RULES_PATH';\n\nexport const STATUS_DRAFT = 'draft';\nexport const STATUS_APPROVED = 'approved';\nexport const STATUS_ACTIVE = 'active';\nexport const STATUS_DISPUTED = 'disputed';\nexport const STATUS_STALE = 'stale';\nexport const STATUS_ARCHIVED = 'archived';\nexport const STATUS_REJECTED = 'rejected';\n\nexport interface BrainRule {\n id: string;\n layer: number; // 1 = feature match, 2 = logic rule\n ruleType: string; // deny_path | deny_command | deny_pattern | allow_pattern\n pattern: string;\n scope: string; // openat | execve | connect | all\n source: string; // llm_extracted | user | central\n sourceEventIds: string[];\n confidence: number;\n status: string;\n createdAt: number;\n lastTriggeredAt: number;\n triggerCount: number;\n disputedCount: number;\n explanation: string;\n originNode: string;\n}\n\ninterface PatternCandidate {\n pattern: string;\n layer: number;\n scope: string;\n sourceEventIds: string[];\n confidence: number;\n occurrenceCount: number;\n firstSeenAt: number;\n lastSeenAt: number;\n reviewStatus: string; // pending | approved | rejected\n reviewReason: string;\n reviewedAt: number;\n}\n\ninterface BrainRulesFile {\n version: number;\n rules: BrainRule[];\n pattern_candidates: PatternCandidate[];\n}\n\nfunction getRulesPath(): string {\n const envPath = process.env[ENV_RULES_PATH];\n if (envPath) return envPath;\n return DEFAULT_RULES_PATH;\n}\n\nfunction uuid(): string {\n // crypto.randomUUID is available in Node 14.17+\n try {\n return (crypto as any).randomUUID();\n } catch {\n return `rule_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;\n }\n}\n\nexport class BrainRuleStore {\n private path: string;\n private data: BrainRulesFile;\n\n constructor(path?: string) {\n this.path = path || getRulesPath();\n this.data = this.load();\n }\n\n private load(): BrainRulesFile {\n if (!existsSync(this.path)) {\n return { version: 1, rules: [], pattern_candidates: [] };\n }\n try {\n const raw = JSON.parse(readFileSync(this.path, 'utf-8'));\n return {\n version: raw.version || 1,\n rules: raw.rules || [],\n pattern_candidates: raw.pattern_candidates || [],\n };\n } catch {\n return { version: 1, rules: [], pattern_candidates: [] };\n }\n }\n\n private save(): void {\n const dir = this.path.substring(0, this.path.lastIndexOf('/'));\n if (dir) mkdirSync(dir, { recursive: true });\n writeFileSync(this.path, JSON.stringify(this.data, null, 2), 'utf-8');\n }\n\n addRule(rule: Partial<BrainRule> & { pattern: string; layer: number }): string {\n const now = Date.now();\n const full: BrainRule = {\n id: rule.id || uuid(),\n layer: rule.layer,\n ruleType: rule.ruleType || 'deny_pattern',\n pattern: rule.pattern,\n scope: rule.scope || 'all',\n source: rule.source || 'llm_extracted',\n sourceEventIds: rule.sourceEventIds || [],\n confidence: rule.confidence || 0,\n status: rule.status || STATUS_DRAFT,\n createdAt: rule.createdAt || now,\n lastTriggeredAt: rule.lastTriggeredAt || 0,\n triggerCount: rule.triggerCount || 0,\n disputedCount: rule.disputedCount || 0,\n explanation: rule.explanation || '',\n originNode: rule.originNode || 'local',\n };\n this.data.rules.push(full);\n this.save();\n return full.id;\n }\n\n approveRule(ruleId: string): void {\n const rule = this.getRule(ruleId);\n if (!rule) throw new Error(`规则不存在: ${ruleId}`);\n if (rule.status !== STATUS_DRAFT) throw new Error(`只有 draft 状态可审核,当前: ${rule.status}`);\n rule.status = STATUS_ACTIVE;\n this.save();\n }\n\n rejectRule(ruleId: string): void {\n const rule = this.getRule(ruleId);\n if (!rule) throw new Error(`规则不存在: ${ruleId}`);\n if (rule.status !== STATUS_DRAFT) throw new Error(`只有 draft 状态可拒绝,当前: ${rule.status}`);\n rule.status = STATUS_REJECTED;\n this.save();\n }\n\n getRule(ruleId: string): BrainRule | undefined {\n return this.data.rules.find(r => r.id === ruleId);\n }\n\n getActiveRules(layer?: number): BrainRule[] {\n return this.data.rules.filter(r => r.status === STATUS_ACTIVE && (layer === undefined || r.layer === layer));\n }\n\n getDraftRules(): BrainRule[] {\n return this.data.rules\n .filter(r => r.status === STATUS_DRAFT)\n .sort((a, b) => b.createdAt - a.createdAt);\n }\n\n recordTrigger(ruleId: string): void {\n const rule = this.getRule(ruleId);\n if (!rule) return;\n rule.triggerCount += 1;\n rule.lastTriggeredAt = Date.now();\n this.save();\n }\n\n // --- pattern_candidates ---\n\n addPatternCandidate(pattern: string, layer: number, scope: string,\n sourceEventId: string, confidence: number): number {\n const now = Date.now();\n const existing = this.data.pattern_candidates.find(\n c => c.pattern === pattern && c.layer === layer && c.scope === scope,\n );\n if (existing) {\n // 已审核拒绝:不累计(永久排除)\n if (existing.reviewStatus === 'rejected') return 0;\n existing.occurrenceCount += 1;\n existing.lastSeenAt = now;\n existing.sourceEventIds.unshift(sourceEventId);\n this.save();\n return existing.occurrenceCount;\n }\n this.data.pattern_candidates.push({\n pattern, layer, scope,\n sourceEventIds: [sourceEventId],\n confidence, occurrenceCount: 1,\n firstSeenAt: now, lastSeenAt: now,\n reviewStatus: 'pending', reviewReason: '', reviewedAt: 0,\n });\n this.save();\n return 1;\n }\n\n getPatternCandidates(minOccurrences = 3): PatternCandidate[] {\n return this.data.pattern_candidates\n .filter(c => c.occurrenceCount >= minOccurrences && c.reviewStatus !== 'rejected')\n .sort((a, b) => b.occurrenceCount - a.occurrenceCount);\n }\n\n getPendingReviewCandidates(minOccurrences = 3): PatternCandidate[] {\n return this.data.pattern_candidates\n .filter(c => c.occurrenceCount >= minOccurrences && c.reviewStatus === 'pending')\n .sort((a, b) => b.occurrenceCount - a.occurrenceCount);\n }\n\n isExcludedPattern(pattern: string, layer: number, scope: string): boolean {\n const c = this.data.pattern_candidates.find(\n c => c.pattern === pattern && c.layer === layer && c.scope === scope,\n );\n return !!c && c.reviewStatus === 'rejected';\n }\n\n setPatternReviewStatus(pattern: string, layer: number, scope: string,\n status: string, reason = ''): void {\n const c = this.data.pattern_candidates.find(\n c => c.pattern === pattern && c.layer === layer && c.scope === scope,\n );\n if (c) {\n c.reviewStatus = status;\n c.reviewReason = reason;\n c.reviewedAt = Date.now();\n this.save();\n }\n }\n\n removePatternCandidate(pattern: string, layer: number, scope: string): void {\n this.data.pattern_candidates = this.data.pattern_candidates.filter(\n c => !(c.pattern === pattern && c.layer === layer && c.scope === scope),\n );\n this.save();\n }\n\n getStats(): Record<string, unknown> {\n const count = (status: string) => this.data.rules.filter(r => r.status === status).length;\n return {\n draft: count(STATUS_DRAFT),\n approved: count(STATUS_APPROVED),\n active: count(STATUS_ACTIVE),\n disputed: count(STATUS_DISPUTED),\n stale: count(STATUS_STALE),\n archived: count(STATUS_ARCHIVED),\n rejected: count(STATUS_REJECTED),\n total: this.data.rules.length,\n by_layer: {\n 1: this.data.rules.filter(r => r.layer === 1 && r.status === STATUS_ACTIVE).length,\n 2: this.data.rules.filter(r => r.layer === 2 && r.status === STATUS_ACTIVE).length,\n },\n pattern_candidates: this.data.pattern_candidates.length,\n };\n }\n}","/**\n * Brain pattern extractor — TypeScript implementation.\n *\n * Mirrors Python agent_moss/brain/pattern_extractor.py. Extracts reusable\n * patterns from Layer 3 LLM Deny results:\n * - static rules (deny_path / deny_command) → accumulated via pattern_candidates\n * until min_occurrences, then a draft rule is created\n * - dedup: if the action_detail is already covered by builtin rules, skip\n *\n * Anchor fix: generalized patterns use (?:^|[^a-z0-9_-]) boundaries instead of\n * ^/$ anchors, because the coordinator matches against\n * `combined = actionType + ' ' + actionDetail` with re.search.\n */\n\nimport { BrainRuleStore, STATUS_DRAFT } from './rule-store';\n\nexport interface ExtractionResult {\n rulesCreated: number;\n patternsRecorded: number;\n skippedReason: string;\n deduped: string[];\n}\n\nexport interface PatternInfo {\n pattern: string;\n layer: number;\n scope: string;\n ruleType: string;\n}\n\n/** LLM 审核回调:返回 true=保留, false=拒绝, null=无法审核(降级保持候选) */\nexport type BrainReviewFn = (opts: {\n pattern: string;\n layer: number;\n ruleType: string;\n actionDetail: string;\n reason: string;\n}) => Promise<{ shouldKeep: boolean; reason?: string } | null> | { shouldKeep: boolean; reason?: string } | null;\n\nexport class PatternExtractor {\n private ruleStore: BrainRuleStore;\n private minConfidence: number;\n private minOccurrences: number;\n private builtinPatterns: string[];\n private reviewFn: BrainReviewFn | null;\n\n constructor(ruleStore: BrainRuleStore, opts?: {\n minConfidence?: number;\n minOccurrences?: number;\n builtinPatterns?: string[];\n review?: BrainReviewFn | null;\n }) {\n this.ruleStore = ruleStore;\n this.minConfidence = opts?.minConfidence ?? 0.9;\n this.minOccurrences = opts?.minOccurrences ?? 3;\n this.builtinPatterns = opts?.builtinPatterns ?? [];\n this.reviewFn = opts?.review ?? null;\n }\n\n async extract(event: { actionDetail?: string; eventId?: string },\n llmResult: { confidence: number; reason: string; riskType: string; actionDetail?: string }): Promise<ExtractionResult> {\n const result: ExtractionResult = { rulesCreated: 0, patternsRecorded: 0, skippedReason: '', deduped: [] };\n const confidence = llmResult.confidence ?? 0;\n const reason = llmResult.reason ?? '';\n const riskType = llmResult.riskType ?? '';\n const actionDetail = llmResult.actionDetail ?? event.actionDetail ?? '';\n const eventId = event.eventId ?? '';\n\n if (confidence < this.minConfidence) {\n result.skippedReason = `confidence ${confidence} < ${this.minConfidence}`;\n return result;\n }\n\n const patterns = this.extractPatterns(actionDetail, reason, riskType);\n if (patterns.length === 0) {\n result.skippedReason = 'no extractable pattern';\n return result;\n }\n\n for (const p of patterns) {\n // Dedup: action_detail already covered by builtin rules → skip\n if (this.isCoveredByBuiltin(actionDetail)) {\n result.deduped.push(p.pattern);\n continue;\n }\n\n const count = this.ruleStore.addPatternCandidate(\n p.pattern, p.layer, p.scope, eventId, confidence,\n );\n if (count === 0) {\n // 已审核拒绝:永久排除\n result.deduped.push(p.pattern);\n continue;\n }\n result.patternsRecorded += 1;\n\n if (count >= this.minOccurrences) {\n const candidates = this.ruleStore.getPatternCandidates(this.minOccurrences);\n const matched = candidates.find(c => c.pattern === p.pattern && c.layer === p.layer);\n if (!matched) continue;\n\n // LLM 审核(可选):判定该 pattern 是否值得沉淀\n if (this.reviewFn) {\n let review: Awaited<ReturnType<BrainReviewFn>>;\n try {\n review = await this.reviewFn({\n pattern: p.pattern, layer: p.layer, ruleType: p.ruleType,\n actionDetail, reason,\n });\n } catch {\n review = null;\n }\n if (review === null) {\n // LLM 不可用/失败:降级保持候选,下次再试\n continue;\n }\n if (!review.shouldKeep) {\n this.ruleStore.setPatternReviewStatus(\n p.pattern, p.layer, p.scope, 'rejected', review.reason || 'LLM 审核拒绝',\n );\n result.deduped.push(p.pattern);\n continue;\n }\n this.ruleStore.setPatternReviewStatus(\n p.pattern, p.layer, p.scope, 'approved', review.reason || 'LLM 审核通过',\n );\n }\n\n this.ruleStore.addRule({\n layer: p.layer,\n ruleType: p.ruleType,\n pattern: p.pattern,\n scope: p.scope,\n source: 'llm_extracted',\n sourceEventIds: eventId ? [eventId] : [],\n confidence: matched.confidence,\n status: STATUS_DRAFT,\n explanation: `从 ${count} 次 LLM Deny 中提取(经审核): ${reason.slice(0, 200)}`,\n });\n this.ruleStore.removePatternCandidate(p.pattern, p.layer, p.scope);\n result.rulesCreated += 1;\n }\n }\n return result;\n }\n\n extractPatterns(actionDetail: string, reason: string, riskType?: string): PatternInfo[] {\n const patterns: PatternInfo[] = [];\n const detailLower = actionDetail.toLowerCase();\n const seen = new Set<string>();\n\n // --- Layer 1: sensitive paths in action_detail ---\n const sensitivePathRe = /(\\/(?:etc|root)(?:\\/[^\\s;|&\"'<>`$]*)?|(?:[^\\s;|&\"'<>`$]*)?\\/\\.ssh\\/[^\\s;|&\"'<>`$]*|(?:[^\\s;|&\"'<>`$]*)?\\/\\.aws\\/[^\\s;|&\"'<>`$]*|\\S+\\.(?:pem|key|p12|pfx|id_rsa|authorized_keys)\\b)/;\n const m = detailLower.match(sensitivePathRe);\n if (m) {\n const gen = this.generalizePath(m[1]);\n if (!seen.has(gen)) {\n seen.add(gen);\n patterns.push({ pattern: gen, layer: 1, scope: 'openat', ruleType: 'deny_path' });\n }\n }\n\n // --- Layer 1: dangerous commands ---\n const dangerousCmdRe = /\\b(rm\\s+-[a-zA-Z]*r[a-zA-Z]*f|rm\\s+--recursive|chmod\\s+777|curl\\s+[^|]*\\|\\s*(?:ba)?sh|wget\\s+[^|]*\\|\\s*(?:ba)?sh|mkfs\\.|dd\\s+if=|>\\s*\\/dev\\/sd)\\b/;\n const cmdM = detailLower.match(dangerousCmdRe);\n if (cmdM) {\n const gen = this.generalizeCommand(cmdM[1]);\n const seenKey = `cmd:${gen}`;\n if (!seen.has(seenKey)) {\n seen.add(seenKey);\n patterns.push({ pattern: gen, layer: 1, scope: 'execve', ruleType: 'deny_command' });\n }\n }\n\n // --- Layer 2: behavior chain patterns ---\n const reasonLower = (reason || '').toLowerCase();\n if (reasonLower.includes('inject') || reasonLower.includes('数据注入')) {\n patterns.push({\n pattern: 'BEHAVIOR_CHAIN:external_read→sensitive_write',\n layer: 2, scope: 'all', ruleType: 'deny_pattern',\n });\n }\n if (reasonLower.includes('reconnaissance') || reasonLower.includes('侦察') || reasonLower.includes('提权')) {\n patterns.push({\n pattern: 'BEHAVIOR_CHAIN:multi_config_read→privilege_action',\n layer: 2, scope: 'all', ruleType: 'deny_pattern',\n });\n }\n\n // --- Layer 1: extract new sensitive paths from action_detail + reason ---\n // 前缀:空白、引号、左括号、= (URL query 参数如 src=/path)\n // 后缀:空白、引号、右括号、中英文标点、行尾\n const pathPrefix = '(?:^|[\\\\s\"\\'(=])';\n const pathBody = '(\\\\/(?:[a-zA-Z0-9_.-]+\\\\/)+[a-zA-Z0-9_.-]+)';\n const pathSuffix = '(?=[\\\\s\"\\'),。);;]|$)';\n for (const src of [detailLower, reasonLower]) {\n // 每次循环新建正则,避免全局 lastIndex 状态污染(JS 全局正则跨字符串复用 bug)\n const pathRe = new RegExp(pathPrefix + pathBody + pathSuffix, 'g');\n let mm: RegExpExecArray | null;\n while ((mm = pathRe.exec(src)) !== null) {\n const path = mm[1];\n if (path.split('/').length < 3) continue; // need >= 2 dir levels\n if (['/dev/null', '/dev/zero', '/dev/random', '/dev/urandom'].includes(path)) continue;\n const gen = this.generalizePath(path);\n if (seen.has(gen)) continue;\n seen.add(gen);\n patterns.push({ pattern: gen, layer: 1, scope: 'openat', ruleType: 'deny_path' });\n }\n }\n return patterns;\n }\n\n isCoveredByBuiltin(actionDetail: string): boolean {\n if (this.builtinPatterns.length === 0 || !actionDetail) return false;\n for (const pat of this.builtinPatterns) {\n try {\n if (new RegExp(pat, 'i').test(actionDetail)) return true;\n } catch {\n continue;\n }\n }\n return false;\n }\n\n generalizePath(path: string): string {\n const p = path.toLowerCase();\n if (/\\/etc\\/(shadow|passwd|sudoers|security|ssh)/.test(p)) {\n return '(?:^|[^a-z0-9_-])etc/(?:shadow|passwd|sudoers|security/|ssh/)';\n }\n if (p.includes('/etc/')) {\n return '(?:^|[^a-z0-9_-])etc/';\n }\n if (p.includes('/root/')) {\n return '(?:^|[^a-z0-9_-])root/\\\\.(?:ssh|gnupg|aws|config)/';\n }\n if (p.includes('.ssh/')) {\n return '(?:^|[^a-z0-9_-])[\\\\w./-]*/\\\\.ssh/';\n }\n if (p.includes('.aws/')) {\n return '(?:^|[^a-z0-9_-])[\\\\w./-]*/\\\\.aws/';\n }\n if (/\\.(pem|key|p12|pfx|id_rsa|authorized_keys)\\b/.test(p)) {\n return '[\\\\w./-]*\\\\.(?:pem|key|p12|pfx|id_rsa|authorized_keys)(?:$|[^a-z0-9])';\n }\n const escaped = p.replace(/^\\//, '').replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n return `(?:^|[^a-z0-9_-])${escaped}(?:/|\\\\b)`;\n }\n\n generalizeCommand(cmd: string): string {\n if (cmd.includes('rm') && cmd.includes('r') && cmd.includes('f')) {\n return 'rm\\\\s+(?:-[a-zA-Z]*r[a-zA-Z]*f|--recursive)\\\\s+/';\n }\n if (cmd.includes('chmod')) return 'chmod\\\\s+777';\n if (cmd.includes('curl') || cmd.includes('wget')) {\n return '(?:curl|wget)\\\\s+[^|]*\\\\|\\\\s*(?:ba)?sh';\n }\n if (cmd.includes('mkfs')) return 'mkfs\\\\.';\n if (cmd.includes('dd')) return 'dd\\\\s+if=';\n return cmd.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n }\n}","/**\n * Brain 候选 pattern LLM 审核器 — TypeScript implementation.\n *\n * Mirrors Python agent_moss/brain/reviewer.py. When a pattern candidate\n * reaches the occurrence threshold, ask the LLM whether it's worth promoting\n * to a local rule. Rejects are permanently excluded; LLM-unavailable degrades\n * to \"keep candidate\" (don't promote, don't reject).\n */\n\nimport OpenAI from 'openai';\nimport { getLLMConfig, isLLMAvailable, detectProvider, getProviderHeaders } from '../config';\n\ninterface ReviewResult {\n shouldKeep: boolean;\n reason?: string;\n}\n\nconst REVIEW_PROMPT = `你是 AgentMoss 安全规则审核器。判断下列\"从 LLM 拒绝结果中提取的安全模式\"是否值得沉淀为本地规则。\n\n## 提取的模式(候选)\n- 模式: {pattern}\n- 所属层: Layer {layer}(1=特征匹配,2=行为链)\n- 类型: {ruleType}\n\n## 原始被拒绝的操作\n{actionDetail}\n\n## LLM 当时的拒绝理由\n{reason}\n\n## 判断准则\n1. **是否过高泛化**:这条模式是否会误拦正常的合法操作?\n2. **是否符合敏感特征**:指向的路径/命令是否确实敏感(凭据/系统文件/恶意命令/外传)?\n3. **与三层规则重复**:是否已被现有 L1/L2 规则覆盖?\n4. **是不是真实攻击模式**:是否代表一种连续的攻击行为模式?\n\n## 输出 JSON(只输出 JSON,无其他文字)\n{\"should_keep\": true/false, \"confidence\": 0-100, \"reason\": \"简短理由(中文)\", \"suggested_rule\": \"若保留则输出建议正则,否则空串\", \"duplicate_of\": \"若重复则说明是哪个,否则空串\"}`;\n\ninterface ParsedReview {\n shouldKeep: boolean;\n confidence: number;\n reason: string;\n}\n\nexport function createBrainReviewer(timeoutMs = 10000):\n (opts: { pattern: string; layer: number; ruleType: string; actionDetail: string; reason: string })\n => Promise<ReviewResult | null> {\n return async (opts) => {\n // 审核开关:AGENT_MOSS_BRAIN_REVIEW=0 关闭(对齐 Python)\n if (process.env.AGENT_MOSS_BRAIN_REVIEW === '0') return null;\n if (!isLLMAvailable()) return null;\n\n const config = getLLMConfig();\n const provider = detectProvider(config.baseUrl, config.provider);\n const extraHeaders = getProviderHeaders(provider);\n const client = new OpenAI({\n baseURL: config.baseUrl,\n apiKey: config.apiKey,\n timeout: timeoutMs,\n maxRetries: 1,\n defaultHeaders: Object.keys(extraHeaders).length > 0 ? extraHeaders : undefined,\n });\n\n const prompt = REVIEW_PROMPT\n .replace('{pattern}', opts.pattern)\n .replace('{layer}', String(opts.layer))\n .replace('{ruleType}', opts.ruleType)\n .replace('{actionDetail}', (opts.actionDetail || '').slice(0, 400))\n .replace('{reason}', (opts.reason || '').slice(0, 400));\n\n try {\n const response = await client.chat.completions.create({\n model: config.model,\n temperature: config.temperature || 0.1,\n max_tokens: 256,\n messages: [\n { role: 'system', content: '只输出纯 JSON,不要包含 markdown 标记、代码块或任何其他文字。' },\n { role: 'user', content: prompt },\n ],\n } as any);\n const content = response.choices[0]?.message?.content || '';\n const parsed = parseReview(content);\n return { shouldKeep: parsed.shouldKeep, reason: parsed.reason };\n } catch (e) {\n console.warn(`[AgentMoss] Brain 审核 LLM 调用失败(降级保持候选): ${(e as Error).message}`);\n return null;\n }\n };\n}\n\nexport function parseReview(content: string): ParsedReview {\n let text = content.trim();\n if (text.startsWith('```')) {\n text = text.replace(/^```[a-zA-Z]*\\n?/, '').replace(/\\n?```$/, '');\n }\n // 提取第一个 JSON 对象\n const match = text.match(/\\{[\\s\\S]*\\}/);\n if (!match) throw new Error(`审核响应无 JSON 对象: ${text.slice(0, 200)}`);\n const data = JSON.parse(match[0]);\n if (!('should_keep' in data) && !('shouldKeep' in data)) {\n throw new Error(`审核响应缺 should_keep: ${text.slice(0, 200)}`);\n }\n let shouldKeep = data.shouldKeep ?? data.should_keep;\n if (typeof shouldKeep === 'string') {\n shouldKeep = ['true', '1', '是', 'yes'].includes(shouldKeep.trim().toLowerCase());\n }\n return {\n shouldKeep: !!shouldKeep,\n confidence: Number(data.confidence ?? 0) || 0,\n reason: String(data.reason ?? data.suggested_rule ?? '') || '',\n };\n}","/**\n * Formal engine (Formal Engine) — agent behavior formal verification module.\n * Mirrors Python agent_moss/engine/formal_engine/ package.\n *\n * Layered architecture:\n * - IR (ir.ts): ActionNode / BehaviorEdge / SessionGraph / MultiSessionGraph\n * - Builder (builder.ts): build behavior graphs from action histories\n * - Verification (engine.ts + properties.ts): FormalEngine verifies properties\n * (cross-session chains, sensitive data flow) → compliance proof or counter-example.\n */\n\nexport { FormalEngine } from './engine';\nexport * from './ir';\nexport { buildMultiSessionGraph, buildSessionGraph, extractResources } from './builder';\nexport { ALL_PROPERTIES, checkCrossSessionChain, checkSensitiveDataFlow } from './properties';\nexport type { Property } from './properties';\nexport { StatefulChainTracker } from './stateful';\nexport type { StateNode, PendingPrefix, ChainMatch, AdvanceResult, JudgmentLike } from './stateful';\nexport { ChainStateStore } from './chain_state';\n","/**\n * Formal engine — FormalEngine verification entry.\n * Mirrors Python agent_moss/engine/formal_engine/engine.py.\n *\n * Public API (same architecture as script_engine: engine + unified IR + scanner):\n * - FormalEngine.verify(sessions?, aNext?) → FormalVerificationResult\n *\n * Runtime cost: O(nodes × properties × edges), no state explosion / path\n * enumeration — milliseconds for a single session, linear for multi-session.\n */\n\nimport { buildMultiSessionGraph } from './builder';\nimport type { FormalVerificationResult, PropertyViolation } from './ir';\nimport { emptyVerificationResult } from './ir';\nimport { ALL_PROPERTIES, Property } from './properties';\n\n/** 把 eBPF syscall 事件转成 stage 正则可识别的一句话(镜像 Python _ebpf_event_to_detail)。 */\nexport function ebpfEventToDetail(e: Record<string, unknown>): string {\n const parts: string[] = [];\n const syscall = String(e.syscall || e.op || '');\n const argv = String(e.argv || e.pathname || '');\n const remote = String(e.remote_addr || '');\n const port = e.remote_port;\n if (syscall) parts.push(syscall);\n if (argv && argv !== '' && argv !== 'None') parts.push(argv);\n if (remote) parts.push('to ' + remote + (port ? ':' + String(port) : ''));\n return parts.join(' ');\n}\n\nexport class FormalEngine {\n private properties: Property[];\n\n constructor(properties?: Property[]) {\n this.properties = properties && properties.length > 0 ? properties : ALL_PROPERTIES;\n }\n\n verify(\n sessions?: { sessionId?: string; actionHistory?: { actionType?: string; actionDetail?: string }[] }[],\n aNext?: { actionType?: string; actionDetail?: string },\n ebpfEvents?: Record<string, unknown>[],\n ): FormalVerificationResult {\n const all = sessions ? [...sessions] : [];\n if (ebpfEvents && ebpfEvents.length > 0) {\n // 真实 syscall 证据(AgentGate eBPF)作为独立 session 追加,\n // 供 P3/P4 做\"声明(a_next) vs 行为(ebpf)\"交叉校验。\n all.push({\n sessionId: 'ebpf-evidence',\n actionHistory: ebpfEvents.map(e => ({\n actionType: 'syscall',\n actionDetail: ebpfEventToDetail(e),\n })),\n });\n }\n const graph = buildMultiSessionGraph(all, aNext);\n const result: FormalVerificationResult = emptyVerificationResult();\n\n for (const prop of this.properties) {\n let violations: PropertyViolation[];\n try {\n violations = prop.check(graph);\n } catch (e) {\n // property verification error → fail-closed (keep)\n result.verified = false;\n result.violations.push({\n propertyId: prop.id,\n reason: `形式化性质验证异常,保守拦截: ${e}`,\n riskLevel: 'medium',\n path: [],\n });\n return result;\n }\n if (violations.length > 0) {\n result.verified = false;\n result.violations.push(...violations);\n break; // hit-and-stop (consistent with L2 short-circuit)\n }\n }\n return result;\n }\n}\n","/**\n * Formal engine — behavior-graph builder.\n * Mirrors Python agent_moss/engine/formal_engine/builder.py.\n *\n * Builds behavior graphs from action histories:\n * - buildSessionGraph(actionHistory, aNext?) → SessionGraph\n * - buildMultiSessionGraph(sessions, aNext?) → MultiSessionGraph (cross-session data edges)\n *\n * Stage marking reuses L2 l2_rules.json combo_chains.stages patterns\n * (single source of truth), so L2 combo-chain rules and the formal engine\n * agree on stage classification.\n */\n\nimport { loadL2 } from '../../infra/rules-loader';\nimport { matchStageAny } from './decode';\nimport type { ActionNode, BehaviorEdge, MultiSessionGraph, SessionGraph } from './ir';\n\n// stage patterns compiled from l2_rules.json combo_chains.stages\nlet COMBO_STAGES: Record<string, RegExp[]> | null = null;\n\nfunction loadStages(): Record<string, RegExp[]> {\n if (COMBO_STAGES) return COMBO_STAGES;\n const combo = (loadL2().combo_chains || {}) as any;\n const stages: Record<string, RegExp[]> = {};\n for (const [name, pats] of Object.entries((combo.stages || {}) as Record<string, string[]>)) {\n stages[name] = (pats as string[]).map(p => new RegExp(p, 'i'));\n }\n COMBO_STAGES = stages;\n return stages;\n}\n\n// file-path extraction (/path, ~/path; strip quotes; allow @/= prefixes for\n// tool-argument forms like curl -d @/tmp/x, --output=/tmp/x)\nconst PATH_RE = /(?:^|\\s|[@=])((?:\\/|~\\/)[\\w./~-]+)/g;\n\nexport function extractResources(actionDetail: string): Set<string> {\n const resources = new Set<string>();\n const text = actionDetail.replace(/'[^']*'|\"[^\"]*\"/g, '');\n PATH_RE.lastIndex = 0;\n let m: RegExpExecArray | null;\n while ((m = PATH_RE.exec(text)) !== null) {\n const p = m[1];\n if (p.startsWith('/dev/') || p.includes('://')) continue;\n resources.add(p);\n }\n return resources;\n}\n\nexport function markStage(actionDetail: string): string {\n return matchStageAny(actionDetail, loadStages());\n}\n\nexport function buildSessionGraph(\n actionHistory: { actionType?: string; actionDetail?: string }[],\n aNext?: { actionType?: string; actionDetail?: string },\n sessionId = 'current',\n): SessionGraph {\n const nodes: ActionNode[] = [];\n const edges: BehaviorEdge[] = [];\n const stageFlags = new Set<string>();\n const details: { actionType: string; actionDetail: string }[] = [];\n for (const a of actionHistory) {\n const ad = String(a.actionDetail || '');\n if (ad) details.push({ actionType: String(a.actionType || ''), actionDetail: ad });\n }\n if (aNext) {\n details.push({ actionType: String(aNext.actionType || ''), actionDetail: String(aNext.actionDetail || '') });\n }\n details.forEach((d, seq) => {\n const stage = markStage(d.actionDetail);\n const node: ActionNode = {\n sessionId, seq, actionType: d.actionType, actionDetail: d.actionDetail,\n stage, resources: extractResources(d.actionDetail),\n };\n nodes.push(node);\n if (stage) stageFlags.add(stage);\n });\n for (let i = 0; i < nodes.length - 1; i++) {\n edges.push({ src: i, dst: i + 1, kind: 'next' });\n }\n return { sessionId, nodes, edges, stageFlags };\n}\n\nexport function buildMultiSessionGraph(\n sessions: { sessionId?: string; actionHistory?: { actionType?: string; actionDetail?: string }[] }[],\n aNext?: { actionType?: string; actionDetail?: string },\n): MultiSessionGraph {\n const mg: MultiSessionGraph = { sessions: [], crossEdges: [] };\n if (!sessions || sessions.length === 0) {\n mg.sessions.push(buildSessionGraph([], aNext, 'current'));\n return mg;\n }\n for (const s of sessions) {\n const sid = String(s.sessionId || 's');\n mg.sessions.push(buildSessionGraph(s.actionHistory || [], undefined, sid));\n }\n if (aNext) {\n const last = mg.sessions[mg.sessions.length - 1];\n if (last.sessionId === 'current') {\n const stage = markStage(String(aNext.actionDetail || ''));\n last.nodes.push({\n sessionId: last.sessionId, seq: last.nodes.length,\n actionType: String(aNext.actionType || ''), actionDetail: String(aNext.actionDetail || ''),\n stage, resources: extractResources(String(aNext.actionDetail || '')),\n });\n if (last.nodes.length > 1) {\n last.edges.push({ src: last.nodes.length - 2, dst: last.nodes.length - 1, kind: 'next' });\n }\n } else {\n mg.sessions.push(buildSessionGraph([], aNext, 'current'));\n }\n }\n addCrossDataEdges(mg);\n return mg;\n}\n\nfunction addCrossDataEdges(mg: MultiSessionGraph): void {\n const nodes = allNodesFlat(mg);\n if (nodes.length < 2) return;\n for (let i = 0; i < nodes.length; i++) {\n for (let j = i + 1; j < nodes.length; j++) {\n if (nodes[i].sessionId === nodes[j].sessionId) continue;\n const shared = intersect(nodes[i].resources, nodes[j].resources);\n if (shared.size > 0) {\n mg.crossEdges.push({ src: i, dst: j, kind: 'data' });\n }\n }\n }\n}\n\nfunction allNodesFlat(mg: MultiSessionGraph): ActionNode[] {\n const out: ActionNode[] = [];\n for (const s of mg.sessions) out.push(...s.nodes);\n return out;\n}\n\nfunction intersect(a: Set<string>, b: Set<string>): Set<string> {\n const out = new Set<string>();\n for (const v of a) if (b.has(v)) out.add(v);\n return out;\n}\n","/**\n * P1 抗编码绕过:把动作文本做解码规范化,生成候选串(镜像 Python decode.py)。\n *\n * stage 正则匹配前先对 action_detail 尝试 base64 / URL 编码 / 八进制构造等\n * 常见变形,再拿解码候选去匹配 CRED/EXEC/EXFIL stage,把\"编码绕过预置范式\"\n * 转为命中。防误报第一:只对明显编码痕迹下手,解码失败原样返回。\n */\n\n// ---------- base64 字面量 ----------\nconst B64_TOKEN_RE = /[A-Za-z0-9+/]+={0,2}/g;\n\nfunction isValidBase64Token(tok: string): boolean {\n if (tok.length < 8) return false;\n // 长度须为 4 的倍数,或 == / = 结尾\n if (!(tok.length % 4 === 0 || tok.endsWith('==') || tok.endsWith('='))) return false;\n return true;\n}\n\nfunction isPrintable(s: string): boolean {\n for (let i = 0; i < s.length; i++) {\n const c = s.charCodeAt(i);\n if (c < 32 || c > 126) return false;\n }\n return true;\n}\n\nexport function decodeBase64Literals(text: string): string[] {\n const out: string[] = [];\n const seen = new Set<string>();\n for (const m of text.matchAll(B64_TOKEN_RE)) {\n const tok = m[0];\n if (!isValidBase64Token(tok)) continue;\n // 纯 token 须有 base64 特征:同时含大小写和数字更可信;过短跳过\n if (!/[A-Z]/.test(tok) || !/[a-z]/.test(tok)) continue;\n try {\n // 补齐 padding 再解码\n const padded = tok + '='.repeat((4 - (tok.length % 4)) % 4);\n const bin = Buffer.from(padded, 'base64');\n const s = bin.toString('utf8');\n if (s && isPrintable(s) && !seen.has(s)) {\n seen.add(s);\n out.push(s);\n }\n } catch {\n // ignore\n }\n }\n return out;\n}\n\n// ---------- URL / 数值构造 ----------\nexport function decodeUrlAndNumeric(text: string): string[] {\n const out: string[] = [];\n\n // URL 解码多次直至稳定\n let s = text;\n for (let i = 0; i < 3; i++) {\n let nxt = s;\n try {\n nxt = decodeURIComponent(s);\n } catch {\n break;\n }\n if (nxt === s) break;\n s = nxt;\n }\n if (s !== text) out.push(s);\n\n // 八进制 \\nnn 展开(printf 常见)\n if (/\\\\[0-7]{3}/.test(text)) {\n let expanded = '';\n try {\n expanded = text.replace(/\\\\[0-7]{3}/g, m => String.fromCharCode(parseInt(m.slice(1), 8)));\n } catch { /* ignore */ }\n if (expanded && expanded !== text) out.push(expanded);\n }\n // hex \\xNN 展开\n if (/\\\\x[0-9a-fA-F]{2}/.test(text)) {\n let expanded = '';\n try {\n expanded = text.replace(/\\\\x[0-9a-fA-F]{2}/g, m => String.fromCharCode(parseInt(m.slice(2), 16)));\n } catch { /* ignore */ }\n if (expanded && expanded !== text) out.push(expanded);\n }\n\n return out;\n}\n\n// ---------- 统一入口 ----------\nexport function allCandidates(detail: string, max = 8): string[] {\n const cands: string[] = [detail];\n cands.push(...decodeBase64Literals(detail));\n cands.push(...decodeUrlAndNumeric(detail));\n const seen = new Set<string>();\n const out: string[] = [];\n for (const c of cands) {\n if (seen.has(c) || c.length > 4096) continue;\n seen.add(c);\n out.push(c);\n if (out.length >= max) break;\n }\n return out;\n}\n\n/** 对原始 + 解码候选一起做 stage 匹配(P1 核心)。返回命中的 stage(空 = 未命中)。 */\nexport function matchStageAny(\n detail: string,\n stages: Record<string, RegExp[]>,\n): string {\n for (const cand of allCandidates(detail)) {\n for (const [name, pats] of Object.entries(stages)) {\n for (const p of pats) {\n p.lastIndex = 0;\n if (p.test(cand)) return name;\n }\n }\n }\n return '';\n}","/**\n * Formal engine — unified behavior-graph IR (data model + interface).\n * Mirrors Python agent_moss/engine/formal_engine/ir.py EXACTLY.\n *\n * Turns an agent's historical actions into a behavior graph\n * (nodes = actions/tool calls, edges = time order / data flow),\n * which FormalEngine verifies against safety properties.\n *\n * Data sources (backward compatible):\n * - Single session: built from existing actionHistory/promptHistory — no caller change.\n * - Multi session: caller (incl. future agentgate non-intrusive collection) passes\n * multiple sessions' histories → MultiSessionGraph with cross-session data edges\n * (shared files/memory/tools). coordinator gains optional `sessionHistory`;\n * when absent only the current session graph is built (identical behavior, zero regression).\n */\n\nexport interface ActionNode {\n sessionId: string;\n seq: number;\n actionType: string;\n actionDetail: string;\n /** Matched kill-chain stage ('' if none): LISTEN/EXEC/SCAN/CRED/EXFIL/PERSIST/PRIVESC. */\n stage: string;\n /** Involved resources (file paths / carriers / tool targets). */\n resources: Set<string>;\n}\n\nexport interface BehaviorEdge {\n /** Source node index (global graph index). */\n src: number;\n dst: number;\n /** 'next' (time order) | 'data' (shared resource flow) | 'call' (invocation). */\n kind: 'next' | 'data' | 'call';\n}\n\nexport interface SessionGraph {\n sessionId: string;\n nodes: ActionNode[];\n edges: BehaviorEdge[];\n stageFlags: Set<string>;\n}\n\nexport interface MultiSessionGraph {\n sessions: SessionGraph[];\n crossEdges: BehaviorEdge[];\n}\n\nexport function allNodes(mg: MultiSessionGraph): ActionNode[] {\n const out: ActionNode[] = [];\n for (const s of mg.sessions) out.push(...s.nodes);\n return out;\n}\n\nexport function allEdges(mg: MultiSessionGraph): BehaviorEdge[] {\n const out: BehaviorEdge[] = [];\n for (const s of mg.sessions) out.push(...s.edges);\n out.push(...mg.crossEdges);\n return out;\n}\n\nexport interface PropertyViolation {\n propertyId: string;\n reason: string;\n riskLevel: string;\n /** Counter-example path: [(sessionId, seq, actionDetail)] */\n path: { sessionId: string; seq: number; detail: string }[];\n}\n\nexport interface FormalVerificationResult {\n verified: boolean;\n violations: PropertyViolation[];\n}\n\nexport function emptyVerificationResult(): FormalVerificationResult {\n return { verified: true, violations: [] };\n}\n","/**\n * Formal engine — safety property definitions (security invariants).\n * Mirrors Python agent_moss/engine/formal_engine/properties.py.\n *\n * Each property implements check(graph) → PropertyViolation[].\n *\n * Built-in properties (B/C classes that depend on behavior graph / data flow):\n * - P1 cross-session chain: stage subsequence matching over the multi-session\n * concatenated graph (LISTEN→EXEC→SCAN may span sessions).\n * - P2 sensitive data flow: taint propagation along data edges — credential\n * files touched in CRED stage flowing via shared carriers to EXFIL actions.\n *\n * fail-closed: unverifiable stages/resources treated as occurred; any\n * possibly-violating path is reported (keep more rather than miss).\n */\n\nimport { loadL2 } from '../../infra/rules-loader';\nimport type { MultiSessionGraph, PropertyViolation } from './ir';\nimport { allEdges, allNodes } from './ir';\n\n// ==================== P1 cross-session chain ====================\n\n// Reuse l2_rules.json combo_chains.chains (single source of truth, same\n// definitions as L2 in-session chains) but match over the multi-session graph.\ninterface ChainDef {\n id: string;\n stages: string[];\n riskLevel: string;\n reason: string;\n}\n\nlet CROSS_SESSION_CHAINS: ChainDef[] | null = null;\n\nfunction loadCrossSessionChains(): ChainDef[] {\n if (CROSS_SESSION_CHAINS) return CROSS_SESSION_CHAINS;\n const combo = (loadL2().combo_chains || {}) as any;\n CROSS_SESSION_CHAINS = ((combo.chains || []) as any[]).map((c: any) => ({\n id: String(c.id || 'combo_chain'),\n stages: (c.stages || []) as string[],\n riskLevel: String(c.riskLevel || c.risk_level || 'high'),\n reason: '跨会话' + String(c.reason || '组合攻击链'),\n }));\n return CROSS_SESSION_CHAINS;\n}\n\n// credential file feature (P2: files touched in CRED stage are taint sources)\nconst CRED_FILE_RE = /(known_hosts|\\.ssh|id_rsa|\\/etc\\/shadow|\\/etc\\/passwd|credentials)/i;\n// exfil action feature (P2: EXFIL stage or network-exfil shape)\nconst EXFIL_RE = /https?:\\/\\/|scp\\s+.*@|rsync\\s+.*@/i;\n\nexport function checkCrossSessionChain(graph: MultiSessionGraph): PropertyViolation[] {\n const violations: PropertyViolation[] = [];\n const nodes = allNodes(graph);\n if (nodes.length === 0) return violations;\n\n for (const chain of loadCrossSessionChains()) {\n const stages = chain.stages;\n if (!stages.length) continue;\n // greedy subsequence match (stages in order, need not be contiguous)\n let matched = 0;\n let stageIdx = 0;\n const path: { sessionId: string; seq: number; detail: string }[] = [];\n for (const n of nodes) {\n if (stageIdx < stages.length && n.stage === stages[stageIdx]) {\n matched += 1;\n path.push({ sessionId: n.sessionId, seq: n.seq, detail: n.actionDetail.slice(0, 60) });\n stageIdx += 1;\n if (matched >= stages.length) break;\n }\n }\n if (matched >= stages.length) {\n violations.push({\n propertyId: 'cross-' + chain.id,\n reason: chain.reason,\n riskLevel: chain.riskLevel,\n path,\n });\n }\n }\n return violations;\n}\n\nexport function checkSensitiveDataFlow(graph: MultiSessionGraph): PropertyViolation[] {\n const violations: PropertyViolation[] = [];\n const nodes = allNodes(graph);\n if (nodes.length === 0) return violations;\n\n // taint: nodeIdx -> source description\n const tainted = new Map<number, string>();\n for (let i = 0; i < nodes.length; i++) {\n const n = nodes[i];\n if (n.stage === 'CRED' && [...n.resources].some(r => CRED_FILE_RE.test(r))) {\n tainted.set(i, `${n.sessionId}#${n.seq} 访问 ${[...n.resources][0]}`);\n }\n }\n if (tainted.size === 0) return violations;\n\n // forward propagation until fixpoint (small graph, linear OK)\n const edges = allEdges(graph);\n let changed = true;\n while (changed) {\n changed = false;\n for (const e of edges) {\n if (tainted.has(e.src) && !tainted.has(e.dst)) {\n const srcRes = nodes[e.src].resources;\n const dstRes = nodes[e.dst].resources;\n for (const r of srcRes) {\n if (dstRes.has(r)) {\n tainted.set(e.dst, tainted.get(e.src)!);\n changed = true;\n break;\n }\n }\n }\n }\n }\n\n // check tainted actions for exfil\n for (const [i, n] of nodes.entries()) {\n if (tainted.has(i) && EXFIL_RE.test(n.actionDetail)) {\n violations.push({\n propertyId: 'sensitive-data-exfil',\n reason: `敏感数据传播外传:${tainted.get(i)} → ${n.sessionId}#${n.seq} 经共享载体外发`,\n riskLevel: 'critical',\n path: [{ sessionId: n.sessionId, seq: n.seq, detail: n.actionDetail.slice(0, 60) }],\n });\n }\n }\n return violations;\n}\n\n// ==================== P3/P4 abstract properties (LTL-style, chain-order independent) ====================\n\n// eBPF evidence: real network exfil (connect/sendto to remote) also counts as EXFIL.\nconst EBPF_NET_RE = /connect|sendto|network_connect/i;\nconst REMOTE_RE = /to\\s+\\d+\\.\\d+\\.\\d+\\.\\d+|remote_addr/i;\n// privilege-escalation semantics (independent of single stage — sudo often matched by EXEC first)\nconst PRIVESC_RE = /\\bsudo\\b|\\bsu\\b|chmod\\s+u\\s*\\+\\s*s|pkexec|setuid/i;\n// active exfil verbs: command itself performs exfil (not a doc/heredoc mentioning URL)\nconst EXFIL_ACTION_RE = /\\bcurl\\b|\\bwget\\b|\\bscp\\b|\\brsync\\b|\\brclone\\b|\\bftp\\b|connect\\s+.*\\d+\\.\\d+\\.\\d+\\.\\d+|open\\s+.*tcp|base64\\s+.*\\-o/i;\n// strict credential detection (P3/P4): real credential files/paths only\nconst CRED_STRICT_RE = /(known_hosts|\\.ssh|id_rsa|\\.pem|\\b\\.key\\b|\\/etc\\/shadow|\\/etc\\/passwd|\\.aws\\/credentials|credentials\\.json|netrc|password|secrets?\\.ya?ml|credentials?\\s*(file|path)?\\s*(=|\\:)|\\bconfig.*(password|token))/i;\n\nfunction isExfilNode(n: { stage: string; actionDetail: string }): boolean {\n if (n.stage === 'EXFIL') return true;\n // text URL/scp/rsync requires an active exfil verb — avoid heredoc/doc false positives\n if (EXFIL_RE.test(n.actionDetail) && EXFIL_ACTION_RE.test(n.actionDetail)) return true;\n if (EBPF_NET_RE.test(n.actionDetail) && REMOTE_RE.test(n.actionDetail)) return true;\n return false;\n}\n\nfunction isCredNode(n: { stage: string; actionDetail: string; resources: Set<string> }): boolean {\n // strict credential (P3/P4): stage CRED is only coarse; require real credential path/text\n if (n.stage !== 'CRED') return false;\n for (const r of n.resources) {\n if (CRED_STRICT_RE.test(r)) return true;\n }\n return CRED_STRICT_RE.test(n.actionDetail);\n}\n\nfunction isPrivescNode(n: { stage: string; actionDetail: string }): boolean {\n if (n.stage === 'PRIVESC') return true;\n return PRIVESC_RE.test(n.actionDetail);\n}\n\nexport function checkNeverExfilAfterPrivesc(graph: MultiSessionGraph): PropertyViolation[] {\n // □(PRIVESC → ¬◇ EXFIL): any PRIVESC earlier + any EXFIL later (cross-session/any gap)\n // is a violation. Independent of the fixed 9 preset chains.\n const violations: PropertyViolation[] = [];\n const nodes = allNodes(graph);\n if (nodes.length < 2) return violations;\n\n for (let i = 0; i < nodes.length; i++) {\n if (!isPrivescNode(nodes[i])) continue;\n for (let j = i + 1; j < nodes.length; j++) {\n if (isExfilNode(nodes[j])) {\n violations.push({\n propertyId: 'no-privesc-then-exfil',\n reason: '提权后出现外传:提权(前) → 外传(后),违反 □(PRIVESC→¬◇EXFIL)',\n riskLevel: 'critical',\n path: [\n { sessionId: nodes[i].sessionId, seq: nodes[i].seq, detail: nodes[i].actionDetail.slice(0, 60) },\n { sessionId: nodes[j].sessionId, seq: nodes[j].seq, detail: nodes[j].actionDetail.slice(0, 60) },\n ],\n });\n return violations;\n }\n }\n }\n return violations;\n}\n\nexport function checkNeverExfilAfterCred(graph: MultiSessionGraph): PropertyViolation[] {\n // □(CRED → ¬◇ EXFIL): any CRED earlier + any EXFIL later is a violation.\n // More conservative (and lighter) than P2 taint propagation: catches\n // indirect/zipped/implicit exfiltration P2's shared-carrier can't see.\n const violations: PropertyViolation[] = [];\n const nodes = allNodes(graph);\n if (nodes.length < 2) return violations;\n\n for (let i = 0; i < nodes.length; i++) {\n if (!isCredNode(nodes[i])) continue;\n for (let j = i + 1; j < nodes.length; j++) {\n if (isExfilNode(nodes[j])) {\n violations.push({\n propertyId: 'no-cred-then-exfil',\n reason: '读取凭据后出现外传,违反 □(CRED→¬◇EXFIL)',\n riskLevel: 'critical',\n path: [\n { sessionId: nodes[i].sessionId, seq: nodes[i].seq, detail: nodes[i].actionDetail.slice(0, 60) },\n { sessionId: nodes[j].sessionId, seq: nodes[j].seq, detail: nodes[j].actionDetail.slice(0, 60) },\n ],\n });\n return violations;\n }\n }\n }\n return violations;\n}\n\n// ==================== property registry ====================\n\nexport interface Property {\n id: string;\n check: (graph: MultiSessionGraph) => PropertyViolation[];\n}\n\nexport const ALL_PROPERTIES: Property[] = [\n { id: 'cross-session-chain', check: checkCrossSessionChain },\n { id: 'sensitive-data-flow', check: checkSensitiveDataFlow },\n { id: 'no-privesc-then-exfil', check: checkNeverExfilAfterPrivesc },\n { id: 'no-cred-then-exfil', check: checkNeverExfilAfterCred },\n];\n","/**\n * Stateful incremental behavior analysis — 有状态的增量行为链分析器。\n * Mirrors Python agent_moss/engine/formal_engine/stateful.py EXACTLY.\n *\n * 把\"每次请求传什么就分析什么\"改成\"时间线持续累积 + 每次新动作增量推进链指针 +\n * 生命周期(能力鲜活度)判定\":\n * - StatefulChainTracker: 按 agent 维护一条安全相关事件时间线(追加模式)。\n * - 增量判定: 每来一个新动作,只做一次阶段命中比较 + 链指针推进(O(链数)),\n * 产出 matched(链补全 → 阻断)与 pendingPrefixes(待攻击前序)。\n * - 生命周期: create/destroy 信号(kill/systemctl stop/rm)与创建失败(is_error)\n * → alive/dead/never_activated;dead 资源不再参与后续链段(堵\"服务已关仍判链\"误报)。\n * - 敏感数据传播(P2): 增量 taint,最终 EXFIL 形态即违反。\n *\n * 与 FormalEngine 关系:全量无状态快照验证(低频/后台用);本模块为增量有状态版本\n * (每次 tool call 实时用),结果应一致。\n */\n\nimport { loadL2 } from '../../infra/rules-loader';\nimport { matchStageAny } from './decode';\n\n// ---------------- 生命周期/敏感数据 辅助正则 ----------------\nconst DESTROY_RE = /\\b(?:pkill|kill)\\b|systemctl\\s+stop|service\\s+stop|crontab\\s+-r|rm\\s+-[rf]?\\s+/i;\nconst NEVER_ACTIVATED_RE =\n /\\b(?:not\\s+found|no\\s+such\\s+file|command\\s+not\\s+found|refused|failed\\s+to\\s+(?:start|bind|listen)|address\\s+already\\s+in\\s+use)\\b/i;\nconst CRED_FILE_RE = /(known_hosts|\\.ssh|id_rsa|\\/etc\\/shadow|\\/etc\\/passwd|credentials)/i;\nconst EXFIL_RE = /https?:\\/\\/|scp\\s+.*@|rsync\\s+.*@/i;\n\nexport interface StateNode {\n seq: number;\n sessionId: string;\n actionType: string;\n actionDetail: string;\n stage: string;\n resources: string[];\n isError: boolean;\n /** \"\" | \"alive\" | \"dead\" | \"never_activated\" */\n lifecycle: string;\n}\n\nexport interface PendingPrefix {\n chainId: string;\n stages: string[];\n matched: number;\n riskLevel: string;\n /** 当前前序链的下一阶段(matched<len 时为 stages[matched],否则空)。 */\n readonly nextStage: string;\n}\n\nexport function nextStageOf(p: PendingPrefix): string {\n return p.matched < p.stages.length ? p.stages[p.matched] : '';\n}\n\nexport interface PathItem {\n sessionId: string;\n seq: number;\n detail: string;\n}\n\nexport interface ChainMatch {\n chainId: string;\n stages: string[];\n riskLevel: string;\n reason: string;\n path: { sessionId: string; seq: number; stage: string }[];\n}\n\nexport function chainMatchToJudgment(m: ChainMatch) {\n return {\n property_id: 'cross-' + m.chainId,\n reason: m.reason,\n risk_level: m.riskLevel,\n path: m.path.map(p => [p.sessionId, p.seq, p.stage] as (string | number)[]),\n };\n}\n\nexport interface JudgmentLike {\n property_id: string;\n reason: string;\n risk_level: string;\n path: (string | number)[][];\n}\n\nexport interface AdvanceResult {\n seq: number;\n node: StateNode | null;\n matched: ChainMatch | null;\n pendingPrefixes: PendingPrefix[];\n exfil: JudgmentLike[];\n readonly shouldBlock: boolean;\n}\n\n// ---------------- 阶段/资源(复用 L2 combo_stages,单一事实源) ----------------\n\nlet STAGES_PATTERNS: Record<string, RegExp[]> | null = null;\nlet CHAINS: any[] | null = null;\n\nfunction loadRules(): { stages: Record<string, RegExp[]>; chains: any[] } {\n if (STAGES_PATTERNS !== null && CHAINS !== null) {\n return { stages: STAGES_PATTERNS, chains: CHAINS };\n }\n const combo = ((loadL2().combo_chains || {}) as any);\n const stages: Record<string, RegExp[]> = {};\n for (const [name, pats] of Object.entries((combo.stages || {}) as Record<string, string[]>)) {\n stages[name] = (pats as string[]).map(p => new RegExp(p, 'i'));\n }\n const chains = (combo.chains || []) as any[];\n STAGES_PATTERNS = stages;\n CHAINS = chains;\n return { stages, chains };\n}\n\nfunction markStage(actionDetail: string): string {\n const { stages } = loadRules();\n return matchStageAny(actionDetail, stages);\n}\n\nfunction extractResources(actionDetail: string): string[] {\n const text = actionDetail.replace(/'[^']*'|\"[^\"]*\"/g, '');\n const out: string[] = [];\n const re = /(?:^|\\s|[@=])((?:\\/|~\\/)[\\w./~-]+)/g;\n let m: RegExpExecArray | null;\n while ((m = re.exec(text)) !== null) {\n const p = m[1];\n if (p.startsWith('/dev/') || p.includes('://')) continue;\n if (!out.includes(p)) out.push(p);\n }\n return out;\n}\n\nfunction lifecycleFor(detail: string, stage: string, isError: boolean): string {\n if (isError) {\n if (stage === 'LISTEN' || stage === 'PERSIST' || NEVER_ACTIVATED_RE.test(detail)) return 'never_activated';\n }\n if (DESTROY_RE.test(detail)) return 'dead';\n if (stage === 'LISTEN' || stage === 'PERSIST') return 'alive';\n if (detail.includes('>>') || detail.includes('>')) return 'alive';\n return '';\n}\n\n// 时间线上限(安全相关节点);超限忽略新节点,建议定期 review 重建。\nconst MAX_NODES = 100_000;\n\nexport class StatefulChainTracker {\n agentId: string;\n private nodes_: StateNode[] = [];\n private ptr: Record<string, number> = {};\n private tainted: Set<number> = new Set();\n /** taint 反索引:资源路径 → 已染毒(O(1) 命中)。 */\n private taintedResources: Set<string> = new Set();\n private aliveResources: Record<string, number> = {};\n seqNext: number = 0;\n\n constructor(agentId = '') {\n this.agentId = agentId;\n loadRules();\n }\n\n get nodes(): StateNode[] {\n return this.nodes_;\n }\n\n get pendingPrefixes(): PendingPrefix[] {\n const { chains } = loadRules();\n const out: PendingPrefix[] = [];\n for (const chain of chains) {\n const stages = (chain.stages || []) as string[];\n if (stages.length === 0) continue;\n const matched = this.ptr[String(chain.id || '')] || 0;\n if (matched > 0 && matched < stages.length) {\n const pf: PendingPrefix = {\n chainId: String(chain.id || ''),\n stages,\n matched,\n riskLevel: String(chain.riskLevel || chain.risk_level || 'high'),\n get nextStage() {\n return this.matched < this.stages.length ? this.stages[this.matched] : '';\n },\n };\n out.push(pf);\n }\n }\n return out;\n }\n\n get aliveResourcesSnapshot(): Record<string, number> {\n return { ...this.aliveResources };\n }\n\n /**\n * 全量/定期灌入历史 session(多 session 各动作追加到时间线)。\n * 历史节点同样推进链指针 / 生命周期 / taint,否则后续 advance 无法在历史基础上\n * 补全链。历史阶段推进若补全链,属于历史事实,不阻断当前动作。\n */\n seed(sessions?: { sessionId?: string; actionHistory?: { actionType?: string; actionDetail?: string }[] }[]): number {\n let added = 0;\n for (const s of sessions || []) {\n const sid = String(s.sessionId || 's');\n for (const a of s.actionHistory || []) {\n const node = this.appendNode(a, sid);\n if (!node) {\n continue;\n }\n added += 1;\n this.recordLifecycle(node);\n this.advanceTaint(node);\n this.advanceChains(node); // 历史阶段推进指针(补全匹配属于历史,忽略)\n }\n }\n return added;\n }\n\n /** 增量推进:把当前动作追加到时间线 → 链指针推进 → 判定。 */\n advance(args: {\n aNext: { actionType?: string; actionDetail?: string };\n actionHistory?: { actionType?: string; actionDetail?: string }[];\n sessionId?: string;\n isError?: boolean;\n }): AdvanceResult {\n const { aNext, sessionId = 'current', isError = false } = args;\n const node = this.appendNode(aNext, sessionId, isError);\n if (!node) {\n return { seq: this.seqNext, node: null, matched: null, pendingPrefixes: this.pendingPrefixes, exfil: [], shouldBlock: false };\n }\n const seq = this.seqNext;\n this.recordLifecycle(node);\n\n const matched = this.advanceChains(node);\n this.advanceTaint(node);\n const exfil = this.checkExfilAfterTaint(node);\n return {\n seq,\n node,\n matched,\n pendingPrefixes: this.pendingPrefixes,\n exfil,\n get shouldBlock() {\n return this.matched !== null || this.exfil.length > 0;\n },\n };\n }\n\n appendNode(action: { actionType?: string; actionDetail?: string }, sessionId: string, isError = false): StateNode | null {\n const ad = String(action.actionDetail || '');\n const at = String(action.actionType || '');\n if (!ad) return null;\n if (this.nodes_.length >= MAX_NODES) {\n // 时间线上限保护:超限忽略新节点(seq==index 不变式不破坏),建议 review 重建\n return null;\n }\n const stage = markStage(ad);\n const node: StateNode = {\n seq: this.seqNext,\n sessionId,\n actionType: at,\n actionDetail: ad,\n stage,\n resources: extractResources(ad),\n isError,\n lifecycle: lifecycleFor(ad, stage, isError),\n };\n this.nodes_.push(node);\n this.seqNext += 1;\n return node;\n }\n\n private recordLifecycle(node: StateNode): void {\n if (node.lifecycle === 'dead') {\n let hit = false;\n for (const r of node.resources) {\n if (r in this.aliveResources) {\n delete this.aliveResources[r];\n hit = true;\n }\n }\n const detail = node.actionDetail;\n for (const r of Object.keys(this.aliveResources)) {\n const base = r.split('/').pop() || '';\n if (base && detail.includes(base)) {\n delete this.aliveResources[r];\n hit = true;\n }\n }\n if (hit) this.resetChainsOnDestroy();\n return;\n }\n if (node.lifecycle === 'alive') {\n for (const r of node.resources) {\n this.aliveResources[r] = node.seq;\n }\n }\n }\n\n private resetChainsOnDestroy(): void {\n for (const cid of Object.keys(this.ptr)) {\n this.ptr[cid] = 0;\n }\n }\n\n private advanceChains(node: StateNode): ChainMatch | null {\n if (node.lifecycle === 'dead') return null;\n if (node.lifecycle === 'never_activated') {\n this.invalidateChainOnFailure(node);\n return null;\n }\n const stage = node.stage;\n if (!stage) return null;\n const { chains } = loadRules();\n for (const chain of chains) {\n const stages = (chain.stages || []) as string[];\n if (stages.length === 0) continue;\n const cid = String(chain.id || '');\n const cur = this.ptr[cid] || 0;\n if (cur < stages.length && stages[cur] === stage) {\n this.ptr[cid] = cur + 1;\n if (cur + 1 >= stages.length) {\n return {\n chainId: cid,\n stages,\n riskLevel: String(chain.riskLevel || chain.risk_level || 'high'),\n reason: String(chain.reason || '检测到组合攻击链'),\n path: this.chainPath(stages),\n };\n }\n }\n }\n return null;\n }\n\n private invalidateChainOnFailure(node: StateNode): void {\n const failed = new Set(node.resources);\n if (failed.size === 0) return;\n const { chains } = loadRules();\n for (const chain of chains) {\n const cid = String(chain.id || '');\n if ((this.ptr[cid] || 0) > 0) {\n this.ptr[cid] = 0;\n }\n }\n }\n\n private chainPath(stages: string[]): { sessionId: string; seq: number; stage: string }[] {\n const path: { sessionId: string; seq: number; stage: string }[] = [];\n let want = stages[0];\n for (const n of this.nodes_) {\n if (n.stage === want) {\n path.push({ sessionId: n.sessionId, seq: n.seq, stage: n.stage });\n const idx = stages.indexOf(n.stage);\n if (idx + 1 < stages.length) {\n want = stages[idx + 1];\n } else {\n break;\n }\n }\n }\n return path;\n }\n\n // ---------------- 敏感数据 taint(P2) ----------------\n private advanceTaint(node: StateNode): void {\n if (node.lifecycle === 'dead') return;\n const idx = node.seq;\n const taintedRes = new Set<string>();\n for (const r of node.resources) {\n if (this.resourceTainted(r)) taintedRes.add(r);\n }\n if (node.stage === 'CRED' && node.resources.some(r => CRED_FILE_RE.test(r))) {\n this.tainted.add(idx);\n for (const r of node.resources) taintedRes.add(r);\n }\n if (taintedRes.size > 0) {\n this.tainted.add(idx);\n for (const r of taintedRes) this.taintedResources.add(r);\n }\n }\n\n private resourceTainted(resource: string): boolean {\n // O(1) 反索引命中(避免每次扫描全部染毒节点)\n return this.taintedResources.has(resource);\n return false;\n }\n\n private checkExfilAfterTaint(node: StateNode): JudgmentLike[] {\n if (!this.tainted.has(node.seq)) return [];\n if (EXFIL_RE.test(node.actionDetail)) {\n return [{\n property_id: 'sensitive-data-exfil',\n reason: `敏感数据传播外传:${this.taintSource(node)} → ${node.sessionId}#${node.seq} 经共享载体外发`,\n risk_level: 'critical',\n path: [[node.sessionId, node.seq, node.actionDetail.slice(0, 60)]],\n }];\n }\n return [];\n }\n\n private taintSource(node: StateNode): string {\n const sorted = [...this.tainted].sort((a, b) => a - b);\n for (const i of sorted) {\n if (i === node.seq) continue;\n const n = this.nodes_[i];\n if (!n) continue;\n for (const r of node.resources) {\n if (n.resources.includes(r)) return `${n.sessionId}#${n.seq} 访问 ${r}`;\n }\n }\n return '未知凭据源';\n }\n\n // ---------------- 序列化/状态 ----------------\n toSnapshot(): Record<string, unknown> {\n return {\n agent_id: this.agentId,\n nodes: this.nodes_.map(n => ({ ...n, resources: [...n.resources] })),\n ptrs: { ...this.ptr },\n tainted: [...this.tainted].sort((a, b) => a - b),\n alive: { ...this.aliveResources },\n seq_next: this.seqNext,\n };\n }\n\n restore(snapshot: Record<string, unknown> | null | undefined): void {\n if (!snapshot) return;\n this.agentId = String(snapshot.agent_id || this.agentId);\n for (const raw of (snapshot.nodes as any[]) || []) {\n this.nodes_.push({\n seq: Number(raw.seq || 0),\n sessionId: String(raw.sessionId || ''),\n actionType: String(raw.actionType || ''),\n actionDetail: String(raw.actionDetail || ''),\n stage: String(raw.stage || ''),\n resources: [...((raw.resources as string[]) || [])],\n isError: Boolean(raw.isError),\n lifecycle: String(raw.lifecycle || ''),\n });\n }\n this.seqNext = Number(snapshot.seq_next || this.nodes_.length);\n this.ptr = Object.fromEntries(Object.entries((snapshot.ptrs as Record<string, unknown>) || {}).map(([k, v]) => [k, Number(v)]));\n this.tainted = new Set((snapshot.tainted as number[] || []).map(Number));\n // 重建 taint 资源反索引:由染毒节点的 resources 推导\n this.taintedResources = new Set();\n for (const i of this.tainted) {\n const n = this.nodes_[i];\n if (n) for (const r of n.resources) this.taintedResources.add(r);\n }\n this.aliveResources = Object.fromEntries(\n Object.entries((snapshot.alive as Record<string, unknown>) || {}).map(([k, v]) => [k, Number(v)])\n );\n }\n}\n\n/** 便捷入口:先 seed 历史,再 advance 当前动作。 */\nexport function advanceIfCompletesChain(args: {\n tracker: StatefulChainTracker;\n sessions?: { sessionId?: string; actionHistory?: { actionType?: string; actionDetail?: string }[] }[];\n actionHistory?: { actionType?: string; actionDetail?: string }[];\n aNext: { actionType?: string; actionDetail?: string };\n sessionId?: string;\n isError?: boolean;\n}): AdvanceResult {\n args.tracker.seed(args.sessions);\n return args.tracker.advance(args);\n}","/**\n * Chain State Store — 有状态增量分析器的持久化层(TS 镜像 Python chain_state.py)。\n *\n * 按 agent 隔离地持久化 StatefulChainTracker 快照(时间线节点 + 链指针 + taint +\n * 存活资源)。TS 侧用 JSON 文件形态(无 sqlite 的鸿蒙/纯 Node 环境可运行),\n * 与 Python SQLite 形态语义一致。\n *\n * 路径:默认 ~/.agentmoss/stateful_chains_<hash>.json;env AGENT_MOSS_STATE_DIR 覆盖;\n * 测试注入显式 path。\n */\n\nimport * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport { createHash } from 'node:crypto';\n\nimport { StatefulChainTracker, AdvanceResult } from './stateful';\n\nexport function defaultStateDbPath(): string {\n const dir = process.env.AGENT_MOSS_STATE_DIR || path.join(os.homedir(), '.agentmoss');\n // agent 维度用哈希目录隔离(避免与其他实例冲突),简单按 user 哈希\n const tag = createHash('sha1').update('agentmoss-stateful').digest('hex').slice(0, 8);\n return path.join(dir, `stateful_chains_${tag}.json`);\n}\n\nexport interface ChainStateFile {\n [agentId: string]: {\n state: Record<string, unknown>;\n updated_at: string;\n };\n}\n\nexport class ChainStateStore {\n private filePath: string;\n private data: ChainStateFile;\n private _timer: ReturnType<typeof setTimeout> | null = null;\n private _flushDelayMs = 50;\n\n constructor(filePath = '') {\n this.filePath = filePath || defaultStateDbPath();\n this.data = this._read();\n }\n\n private _read(): ChainStateFile {\n try {\n if (fs.existsSync(this.filePath)) {\n const raw = fs.readFileSync(this.filePath, 'utf-8');\n return JSON.parse(raw) as ChainStateFile;\n }\n } catch {\n /* 损坏/首启 → 空 */\n }\n return {};\n }\n\n /** 防抖写入:save() 只改内存,后台批量落盘(避免每次 tool call 全量 writeFileSync)。 */\n private _scheduleWrite(): void {\n if (this._timer !== null) return;\n this._timer = setTimeout(() => {\n this._timer = null;\n try {\n fs.mkdirSync(path.dirname(this.filePath), { recursive: true });\n fs.writeFileSync(this.filePath, JSON.stringify(this.data, null, 2), 'utf-8');\n } catch {\n // 落盘失败不阻断分析(下次再试)\n }\n }, this._flushDelayMs);\n }\n\n /** 立即落盘(测试/关停前调用,保证状态不丢)。 */\n flush(): void {\n if (this._timer !== null) {\n clearTimeout(this._timer);\n this._timer = null;\n }\n try {\n fs.mkdirSync(path.dirname(this.filePath), { recursive: true });\n fs.writeFileSync(this.filePath, JSON.stringify(this.data, null, 2), 'utf-8');\n } catch {\n /* 忽略 */\n }\n }\n\n load(agentId: string): StatefulChainTracker | null {\n const entry = this.data[agentId];\n if (!entry) return null;\n const t = new StatefulChainTracker(agentId);\n t.restore(entry.state);\n return t;\n }\n\n save(tracker: StatefulChainTracker): void {\n this.data[tracker.agentId] = {\n state: tracker.toSnapshot(),\n updated_at: new Date().toISOString(),\n };\n this._scheduleWrite();\n }\n\n delete(agentId: string): void {\n delete this.data[agentId];\n this._scheduleWrite();\n }\n\n applyAction(\n agentId: string,\n aNext: { actionType?: string; actionDetail?: string },\n sessionId: string,\n isError = false,\n ): AdvanceResult {\n const t = this.load(agentId) || new StatefulChainTracker(agentId);\n const r = t.advance({ aNext, sessionId, isError });\n this.save(t);\n return r;\n }\n\n seedAndApply(\n agentId: string,\n sessions: { sessionId?: string; actionHistory?: { actionType?: string; actionDetail?: string }[] }[],\n aNext: { actionType?: string; actionDetail?: string },\n sessionId = 'current',\n isError = false,\n ): AdvanceResult {\n const t = this.load(agentId) || new StatefulChainTracker(agentId);\n t.seed(sessions);\n const r = t.advance({ aNext, sessionId, isError });\n this.save(t);\n return r;\n }\n}\n\nlet _store: ChainStateStore | null = null;\n\nexport function getChainStateStore(filePath = ''): ChainStateStore {\n if (_store === null || (filePath && filePath !== _store['filePath'])) {\n _store = new ChainStateStore(filePath);\n }\n return _store;\n}","/**\n * AcTrail enforcement event reporter for TypeScript.\n *\n * Writes AgentMoss allow/deny decisions as Enforcement events to AcTrail's\n * SQLite storage, enabling unified agent behavior audit trails.\n *\n * Configuration (environment variables):\n * ACTRAIL_ENABLED: Set to \"1\" to enable reporting (default: disabled)\n * ACTRAIL_STORAGE_PATH: Path to AcTrail SQLite DB (default: /tmp/actrail.sqlite)\n * ACTRAIL_TIMEOUT_MS: Write timeout in milliseconds (default: 100)\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\n\n/** AcTrail key=value escape (mirrors Rust encode_map) */\nfunction escape(value: string): string {\n return value.replace(/\\\\/g, '\\\\\\\\').replace(/\\n/g, '\\\\n').replace(/=/g, '\\\\e');\n}\n\n/** Convert session_id string to u64 trace_id (SHA-256 based, masked to signed 64-bit) */\nfunction sessionToTraceId(sessionId: string): number {\n // Simple hash - not cryptographic, but sufficient for ID generation\n let hash = 0;\n for (let i = 0; i < sessionId.length; i++) {\n const char = sessionId.charCodeAt(i);\n hash = ((hash << 5) - hash + char) | 0;\n }\n // Combine with length for better distribution, mask to signed 64-bit\n return Math.abs((hash * 31 + sessionId.length) % Number.MAX_SAFE_INTEGER);\n}\n\nexport interface ActrailReportOptions {\n traceId: string;\n decision: 'allow' | 'deny';\n toolName: string;\n toolCommand: string;\n sessionId: string;\n prompt?: string;\n riskLevel?: string;\n riskType?: string;\n reason?: string;\n violatedLayers?: string[];\n confidence?: number;\n durationMs?: number;\n}\n\nlet dbConnected = false;\nlet dbPath = '';\n\nfunction isEnabled(): boolean {\n return process.env.ACTRAIL_ENABLED === '1' || process.env.ACTRAIL_ENABLED === 'true';\n}\n\nfunction getStoragePath(): string {\n return process.env.ACTRAIL_STORAGE_PATH || '/tmp/actrail.sqlite';\n}\n\n/**\n * Report an enforcement event to AcTrail (fire-and-forget).\n * Returns true if written, false if disabled or write failed.\n */\nexport function reportEnforcementEvent(opts: ActrailReportOptions): boolean {\n if (!isEnabled()) return false;\n\n const storagePath = getStoragePath();\n if (!fs.existsSync(storagePath)) return false;\n\n try {\n // Dynamic import - better-sqlite3 is an optional dependency\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n let Database: any;\n try {\n Database = require('better-sqlite3');\n } catch {\n console.debug('[AgentMoss] better-sqlite3 not installed, AcTrail reporting disabled');\n return false;\n }\n\n const db = new Database(storagePath, { timeout: 100, readonly: false });\n\n // Verify events table exists\n const tableCheck = db.prepare(\n \"SELECT name FROM sqlite_master WHERE type='table' AND name='events'\"\n ).get();\n if (!tableCheck) {\n db.close();\n return false;\n }\n\n const nowNs = BigInt(Date.now()) * 1000000n;\n const eventId = Number(nowNs % BigInt(2 ** 62));\n const traceIdInt = sessionToTraceId(opts.traceId);\n\n // Build payload fields in AcTrail's key=value format\n const rawFields: Record<string, string> = {\n 'backend': 'agent-moss',\n 'operation': 'tool_call',\n 'decision': opts.decision,\n 'result': opts.decision === 'allow' ? 'allowed' : 'denied',\n 'tool.name': opts.toolName,\n 'tool.command': (opts.toolCommand || '').slice(0, 500),\n 'agent.session_id': opts.sessionId,\n 'agent.prompt': (opts.prompt || '').slice(0, 500),\n 'risk.level': opts.riskLevel || '',\n 'risk.type': opts.riskType || '',\n 'reason': (opts.reason || '').slice(0, 500),\n 'violated_layers': (opts.violatedLayers || []).join(','),\n 'confidence': String(opts.confidence ?? 100),\n 'duration_ms': (opts.durationMs ?? 0).toFixed(1),\n };\n const payloadFields = Object.entries(rawFields)\n .map(([k, v]) => `${escape(k)}=${escape(v)}`)\n .join('\\n');\n\n db.prepare(`\n INSERT OR REPLACE INTO events (\n event_id, trace_id, observed_at,\n process_pid, process_task_id, process_start_ticks,\n process_pid_namespace, process_generation,\n collector, kind,\n bootstrap_observed, metadata_partial, policy_modified,\n payload_variant, payload_fields, payload_bytes,\n policy_verdict, policy_note,\n policy_redactions, policy_truncations\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `).run(\n eventId,\n traceIdInt,\n Number(nowNs),\n process.pid,\n 0,\n 0,\n null,\n 0,\n 'agent-moss',\n 'enforcement',\n 0,\n 0,\n 0,\n 'enforcement',\n payloadFields,\n '',\n opts.decision === 'allow' ? 'allow' : 'drop',\n opts.reason || '',\n '[]',\n '[]'\n );\n\n db.close();\n return true;\n } catch (err) {\n // Non-fatal - never block the response\n console.debug(`[AgentMoss] AcTrail write failed (non-fatal): ${(err as Error).message}`);\n return false;\n }\n}\n","/**\n * Dangerous frequent-pattern mining (PatternMiner) — TS mirror of Python pattern_miner.py.\n *\n * 从已发生行为中自动发现组合攻击前序(突破预置链盲区)。\n * 1. 投影 + 压缩:stage 序列 + 连续重复压缩\n * 2. 轻量 PrefixSpan 挖掘跨 session 频繁有序子序列\n * 3. 危险标注:含 PRIVESC/EXFIL/LISTEN 或 CRED↔LISTEN 才标记候选\n */\nimport { markStage } from './builder';\n\nconst DANGER_STAGES = new Set(['PRIVESC', 'EXFIL', 'LISTEN']);\nconst SENSITIVE_PAIRS = new Set(['CRED|LISTEN', 'LISTEN|CRED']);\n\nexport interface DiscoveredPattern {\n pattern: string[];\n support: number;\n risk: string;\n reason: string;\n}\n\n/** 把单 session 动作序列投影成压缩后的 stage 序列。 */\nexport function projectStages(actionHistory: { actionType?: string; actionDetail?: string }[]): string[] {\n const stages: string[] = [];\n let prev: string | null = null;\n for (const act of actionHistory) {\n const s = markStage(String(act.actionDetail || ''));\n if (s && s !== prev) {\n stages.push(s);\n prev = s;\n }\n }\n return stages;\n}\n\nfunction isDangerous(pat: string[]): boolean {\n if (pat.some(s => DANGER_STAGES.has(s))) return true;\n for (let i = 0; i < pat.length - 1; i++) {\n if (SENSITIVE_PAIRS.has(pat[i] + '|' + pat[i + 1])) return true;\n }\n return false;\n}\n\nexport function mineDangerousPatterns(\n sessions: { sessionId?: string; actionHistory?: { actionType?: string; actionDetail?: string }[] }[],\n minSup = 2,\n maxLen = 4,\n): DiscoveredPattern[] {\n // 1. 投影 + 压缩\n const seqs: [string, string[]][] = [];\n for (const s of sessions) {\n const sid = String(s.sessionId || '');\n const stages = projectStages(s.actionHistory || []);\n if (stages.length > 0) seqs.push([sid, stages]);\n }\n if (seqs.length === 0) return [];\n\n // 2. 轻量 PrefixSpan(递归前缀投影)\n const results = new Map<string, number>();\n\n const mine = (prefix: string[], projected: [string, string[]][]) => {\n if (prefix.length > 0) {\n results.set(prefix.join('→'), projected.length);\n }\n if (prefix.length >= maxLen) return;\n const itemSids = new Map<string, Set<string>>();\n for (const [sid, suffix] of projected) {\n const seen = new Set<string>();\n for (const it of suffix) {\n if (!seen.has(it)) {\n seen.add(it);\n if (!itemSids.has(it)) itemSids.set(it, new Set());\n itemSids.get(it)!.add(sid);\n }\n }\n }\n for (const [it, sids] of [...itemSids.entries()].sort()) {\n if (sids.size >= minSup) {\n const next: [string, string[]][] = [];\n for (const [sid, suffix] of projected) {\n const idx = suffix.indexOf(it);\n if (idx >= 0) next.push([sid, suffix.slice(idx + 1)]);\n }\n mine([...prefix, it], next);\n }\n }\n };\n\n mine([], seqs);\n\n // 3. 危险标注 + 排序\n const out: DiscoveredPattern[] = [];\n for (const [key, support] of results) {\n const pat = key.split('→');\n if (pat.length < 2 || !isDangerous(pat)) continue;\n const risk = pat.some(s => s === 'PRIVESC' || s === 'EXFIL') ? 'high' : 'medium';\n out.push({\n pattern: pat,\n support,\n risk,\n reason: `跨 session 频繁出现组合 ${pat.join('→')}(${support} 个 session),预置链未直接覆盖,疑似攻击前序`,\n });\n }\n out.sort((a, b) => b.support - a.support || b.pattern.length - a.pattern.length);\n return out;\n}","/**\n * AgentGate 本地存储读取器(TS 侧)— 镜像 Python server/agent_gate_reader.py。\n *\n * 让 TS server 的 /api/v1/review 直接读 AgentGate 本地存储,避免复制原始数据。\n * - SQLite:动态 require('better-sqlite3')(AgentMoss 有该依赖;不可用降级 JSON)\n * - JSON 目录:tool_calls/<session_id>.json 数组\n */\nimport * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\n\nexport const DEFAULT_AGENTGATE_SQLITE = path.join(\n os.homedir(), '.local', 'share', 'agent_gate', 'agent_gate_ts.db'\n);\n\nexport interface SessionLike {\n sessionId?: string;\n actionHistory?: { actionType: string; actionDetail: string }[];\n}\n\nfunction normalizeAction(row: Record<string, unknown>): { actionType: string; actionDetail: string } {\n return {\n actionType: String(row.action_type || row.tool_name || row.name || ''),\n actionDetail: String(row.action_detail || row.command || row.input || ''),\n };\n}\n\nfunction readJsonDir(dirPath: string, limit = 100000): SessionLike[] {\n const sessions = new Map<string, { actionType: string; actionDetail: string }[]>();\n try {\n const files = fs.readdirSync(dirPath).filter(f => f.endsWith('.json')).sort();\n for (const f of files.slice(-200)) {\n const sid = f.replace(/\\.json$/, '');\n const raw = fs.readFileSync(path.join(dirPath, f), 'utf-8');\n const arr = JSON.parse(raw);\n if (!Array.isArray(arr)) continue;\n for (const item of arr) {\n if (!item || typeof item !== 'object') continue;\n const act = normalizeAction(item as Record<string, unknown>);\n if (act.actionDetail) {\n const list = sessions.get(sid) || [];\n list.push(act);\n sessions.set(sid, list);\n }\n }\n let total = 0;\n for (const v of sessions.values()) total += v.length;\n if (total > limit) break;\n }\n } catch {\n /* 目录不存在/非法 → 空 */\n }\n return [...sessions.entries()].map(([sessionId, actionHistory]) => ({ sessionId, actionHistory }));\n}\n\nfunction readSqlite(dbPath: string, limit = 100000): SessionLike[] {\n let Database: any;\n try {\n // dynamic require:better-sqlite3 不可用时降级 JSON\n Database = require('better-sqlite3');\n } catch {\n return [];\n }\n let db: any;\n try {\n db = new Database(dbPath, { readonly: true });\n const rows = db\n .prepare(\n `SELECT session_id, action_type, tool_name, action_detail, command, called_at\n FROM tool_calls ORDER BY called_at, id LIMIT ?`\n )\n .all(limit) as Record<string, unknown>[];\n const sessions = new Map<string, { actionType: string; actionDetail: string }[]>();\n for (const r of rows) {\n const sid = String(r.session_id || '');\n if (!sid) continue;\n const act = normalizeAction(r);\n if (!act.actionDetail) continue;\n const list = sessions.get(sid) || [];\n list.push(act);\n sessions.set(sid, list);\n }\n return [...sessions.entries()].map(([sessionId, actionHistory]) => ({ sessionId, actionHistory }));\n } catch {\n return [];\n } finally {\n try { db?.close(); } catch { /* ignore */ }\n }\n}\n\n/** 统一入口:dbPath 为目录(JSON) → JSON;否则 SQLite → 兜底 JSON 默认目录。 */\nexport function loadAgentGateSessions(dbPath = ''): SessionLike[] {\n if (dbPath) {\n try {\n if (fs.statSync(dbPath).isDirectory()) {\n return readJsonDir(dbPath);\n }\n } catch { /* not a dir */ }\n const sql = readSqlite(dbPath);\n if (sql.length > 0) return sql;\n return readJsonDir(dbPath);\n }\n // 无显式路径:先 SQLite 默认,JSON 兜底\n const sql = readSqlite(DEFAULT_AGENTGATE_SQLITE);\n if (sql.length > 0) return sql;\n const jsonDefault = path.join(os.homedir(), '.local', 'share', 'agent_gate', 'tool_calls');\n return readJsonDir(jsonDefault);\n}","/** Policy Console 子应用(挂载到主 app 的 /console 前缀)。 */\nexport { createConsoleRouter } from './router';\n","/**\n * Policy Console Hono 路由 — 挂载到主 app 的 /console 前缀下。\n * 1:1 对齐 Python console/router.py 的 23 路由契约(前端 SPA 共用)。\n *\n * 复用 infra.runtime-config + engine.token-stats。Bearer 认证\n * (AGENT_MOSS_CONSOLE_TOKEN 未设则本机免认证,iframe 嵌入场景)。\n */\nimport { Hono } from 'hono';\nimport { readFileSync, existsSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport {\n loadRuntimeConfig, saveRuntimeConfig, updateLayerEnabled,\n updateRuleEnabled, updateRuleDenyMode, updateRuleSkipL3,\n updateCategoryEnabled, addCustomRule, deleteCustomRule,\n addCustomSkill, deleteCustomSkill, updateSkillEnabled,\n updateSkillCategoryEnabled, getEnvOverrides, generateSourceDefaults,\n getRuntimeConfigPath,\n getAgentRules, updateAgentRuleEnabled, addAgentRule, deleteAgentRule,\n updateAgentCategoryEnabled,\n getScenarioRules, updateScenarioRuleEnabled, addScenarioRule,\n deleteScenarioRule, updateScenarioCategoryEnabled,\n} from '../infra/runtime-config';\nimport {\n getTokenStats, getRecentRecords, getRecentRecordsCount, getTokenTrend, resetTokenStats,\n} from '../engine/token-stats';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst STATIC_DIR = join(__dirname, 'static');\n\nconst CONSOLE_TOKEN_ENV = 'AGENT_MOSS_CONSOLE_TOKEN';\n\nfunction getConsoleToken(): string {\n return process.env[CONSOLE_TOKEN_ENV] || '';\n}\n\n/** 验证 Bearer token。未配置 token 时本机访问免认证(iframe 嵌入场景)。 */\nfunction verifyAuth(req: Request): boolean {\n const token = getConsoleToken();\n if (!token) return true;\n const auth = req.headers.get('Authorization') || '';\n if (auth.startsWith('Bearer ')) return auth.slice(7) === token;\n return false;\n}\n\n/** 鉴权中间件:失败返 401。 */\nfunction authMiddleware() {\n return async (c: any, next: any) => {\n if (!verifyAuth(c.req.raw)) {\n return c.json({ error: 'Unauthorized: invalid or missing Bearer token' }, 401);\n }\n await next();\n };\n}\n\nexport function createConsoleRouter(): Hono {\n const console = new Hono();\n console.use('/api/*', authMiddleware());\n\n // ==================== SPA ====================\n // /console 和 /console/ 都返回 SPA(hono route 挂载后两者匹配行为不同,都兜住)\n const serveIndex = (c: any) => {\n const indexFile = join(STATIC_DIR, 'index.html');\n if (existsSync(indexFile)) {\n return c.html(readFileSync(indexFile, 'utf-8'));\n }\n return c.html('<h1>AgentMoss Policy Console</h1><p>Frontend not built. Use /console/api/* endpoints.</p>');\n };\n console.get('/', serveIndex);\n console.get('', serveIndex);\n\n // ==================== 层级管理 ====================\n console.get('/api/layers', (c) => {\n const rc = loadRuntimeConfig();\n return c.json({ layers: rc.layers, env_overrides: getEnvOverrides() });\n });\n\n console.put('/api/layers', async (c) => {\n const body = await c.req.json();\n const rc = updateLayerEnabled(body.layer_key, body.enabled);\n return c.json({ layers: rc.layers, env_overrides: getEnvOverrides() });\n });\n\n // ==================== 规则管理 ====================\n console.get('/api/rules', (c) => {\n const rc = loadRuntimeConfig();\n return c.json({ L1_rules: rc.L1_rules, L2_rules: rc.L2_rules });\n });\n\n console.put('/api/rules/enabled', async (c) => {\n const b = await c.req.json();\n const rc = updateRuleEnabled(b.layer, b.category, b.rule_id, b.enabled);\n return c.json(rc);\n });\n\n console.put('/api/rules/deny_mode', async (c) => {\n const b = await c.req.json();\n const rc = updateRuleDenyMode(b.layer, b.category, b.rule_id, b.deny_mode);\n return c.json(rc);\n });\n\n console.put('/api/rules/skip_l3', async (c) => {\n const b = await c.req.json();\n const rc = updateRuleSkipL3(b.layer, b.category, b.rule_id, b.skip_l3_on_disabled);\n return c.json(rc);\n });\n\n console.put('/api/categories/enabled', async (c) => {\n const b = await c.req.json();\n const rc = updateCategoryEnabled(b.layer, b.category, b.enabled);\n return c.json(rc);\n });\n\n console.post('/api/rules', async (c) => {\n const b = await c.req.json();\n const rc = addCustomRule(b.layer, b.category, {\n pattern: b.pattern, risk_level: b.risk_level, risk_type: b.risk_type,\n reason: b.reason, keyword: b.keyword, lang: b.lang,\n path: b.path, desc: b.desc, credential: b.credential, deny_mode: b.deny_mode,\n });\n return c.json(rc);\n });\n\n console.delete('/api/rules', async (c) => {\n const b = await c.req.json();\n deleteCustomRule(b.layer, b.category, b.rule_id);\n const rc = loadRuntimeConfig();\n return c.json(rc);\n });\n\n // ==================== Skill 管理 ====================\n console.get('/api/skills', (c) => {\n const rc = loadRuntimeConfig();\n return c.json(rc.L3_skills);\n });\n\n console.put('/api/skills/enabled', async (c) => {\n const b = await c.req.json();\n const rc = updateSkillEnabled(b.skill_id, b.enabled);\n return c.json(rc);\n });\n\n console.put('/api/skill-categories/enabled', async (c) => {\n const b = await c.req.json();\n const rc = updateSkillCategoryEnabled(b.category, b.enabled);\n return c.json(rc);\n });\n\n console.post('/api/skills', async (c) => {\n const b = await c.req.json();\n const rc = addCustomSkill(b.skill_id, b.category || 'user_custom', b.keywords || [], b.content);\n return c.json(rc);\n });\n\n console.delete('/api/skills', async (c) => {\n const b = await c.req.json();\n deleteCustomSkill(b.skill_id, b.category);\n const rc = loadRuntimeConfig();\n return c.json(rc);\n });\n\n console.get('/api/skills/:skill_id/content', async (c) => {\n const skillId = c.req.param('skill_id');\n if (!/^[A-Za-z0-9_-]+$/.test(skillId)) {\n return c.json({ error: 'invalid skill_id' }, 400);\n }\n const skillPath = join(dirname(getRuntimeConfigPath()), 'agent_moss_skills', `${skillId}.md`);\n if (!existsSync(skillPath)) {\n // fallback 到 builtin skill 目录\n const builtinPath = join(__dirname, '..', '..', 'agent_moss', 'skills', `${skillId}.md`);\n if (existsSync(builtinPath)) return c.text(readFileSync(builtinPath, 'utf-8'));\n return c.json({ error: 'skill not found' }, 404);\n }\n return c.text(readFileSync(skillPath, 'utf-8'));\n });\n\n // ==================== agent 定制规则 ====================\n console.get('/api/agents', (c) => {\n const rc = loadRuntimeConfig();\n return c.json({ agents: getAgentRules(rc) });\n });\n\n console.put('/api/agents/rules/enabled', async (c) => {\n const b = await c.req.json();\n const fp: Record<string, string> = {};\n if (b.value) fp.value = b.value;\n if (b.pattern) fp.pattern = b.pattern;\n if (b.keyword) fp.keyword = b.keyword;\n if (b.path) fp.path = b.path;\n const rc = updateAgentRuleEnabled(b.agent_id, b.category, fp, b.enabled);\n return c.json({ agents: getAgentRules(rc) });\n });\n\n console.post('/api/agents/rules', async (c) => {\n const b = await c.req.json();\n const rule: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(b)) {\n if (!['agent_id', 'category'].includes(k) && v !== undefined && v !== null) rule[k] = v;\n }\n const rc = addAgentRule(b.agent_id, b.category, rule);\n return c.json({ agents: getAgentRules(rc) });\n });\n\n console.delete('/api/agents/rules', async (c) => {\n const b = await c.req.json();\n const fp: Record<string, string> = {};\n if (b.value) fp.value = b.value;\n if (b.pattern) fp.pattern = b.pattern;\n if (b.keyword) fp.keyword = b.keyword;\n if (b.path) fp.path = b.path;\n const rc = deleteAgentRule(b.agent_id, b.category, fp);\n return c.json({ agents: getAgentRules(rc) });\n });\n\n console.put('/api/agents/categories/enabled', async (c) => {\n const b = await c.req.json();\n const rc = updateAgentCategoryEnabled(b.agent_id, b.category, b.enabled);\n return c.json({ agents: getAgentRules(rc) });\n });\n\n // ==================== 场景定制规则 ====================\n\n /** 当前启用的场景 id(与 Python 端一致):AGENT_MOSS_SCENARIO env(逗号分隔多场景)。 */\n const enabledScenarioIds = (): string[] =>\n (process.env.AGENT_MOSS_SCENARIO || '').split(',').map(s => s.trim()).filter(Boolean);\n\n // 只返回已启用场景(无 env → 空,console 不显示、引擎不加载)\n console.get('/api/scenarios', (c) => {\n const all = getScenarioRules(loadRuntimeConfig());\n const enabled = enabledScenarioIds();\n if (!enabled.length) return c.json({ scenarios: {}, enabled: [] });\n const shown: Record<string, unknown> = {};\n for (const sid of enabled) if (all[sid]) shown[sid] = all[sid];\n return c.json({ scenarios: shown, enabled });\n });\n\n console.put('/api/scenarios/rules/enabled', async (c) => {\n const b = await c.req.json();\n const fp: Record<string, string> = {};\n if (b.value) fp.value = b.value;\n if (b.pattern) fp.pattern = b.pattern;\n if (b.keyword) fp.keyword = b.keyword;\n if (b.path) fp.path = b.path;\n const rc = updateScenarioRuleEnabled(b.scenario_id, b.category, fp, b.enabled);\n return c.json({ scenarios: getScenarioRules(rc), enabled: enabledScenarioIds() });\n });\n\n console.post('/api/scenarios/rules', async (c) => {\n const b = await c.req.json();\n const rule: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(b)) {\n if (!['scenario_id', 'category'].includes(k) && v !== undefined && v !== null) rule[k] = v;\n }\n const rc = addScenarioRule(b.scenario_id, b.category, rule);\n return c.json({ scenarios: getScenarioRules(rc), enabled: enabledScenarioIds() });\n });\n\n console.delete('/api/scenarios/rules', async (c) => {\n const b = await c.req.json();\n const fp: Record<string, string> = {};\n if (b.value) fp.value = b.value;\n if (b.pattern) fp.pattern = b.pattern;\n if (b.keyword) fp.keyword = b.keyword;\n if (b.path) fp.path = b.path;\n const rc = deleteScenarioRule(b.scenario_id, b.category, fp);\n return c.json({ scenarios: getScenarioRules(rc), enabled: enabledScenarioIds() });\n });\n\n console.put('/api/scenarios/categories/enabled', async (c) => {\n const b = await c.req.json();\n const rc = updateScenarioCategoryEnabled(b.scenario_id, b.category, b.enabled);\n return c.json({ scenarios: getScenarioRules(rc), enabled: enabledScenarioIds() });\n });\n\n // ==================== 配置 / env / reset ====================\n // 契约对齐:Python console/router.py 的 /api/config 直接返回完整 runtime config\n // (顶层含 L1_rules/L2_rules/L3_skills/layers),前端 state.config 读取顶层字段。\n // 之前 TS 返回 {config, config_path} 包装导致前端 L1/L2/L3 标签页全空(数据丢)。\n console.get('/api/config', (c) => {\n const rc = loadRuntimeConfig();\n return c.json(rc);\n });\n\n console.get('/api/env-overrides', (c) => {\n return c.json({ overrides: getEnvOverrides() });\n });\n\n console.post('/api/reset', (c) => {\n const defaults = generateSourceDefaults();\n saveRuntimeConfig(defaults);\n return c.json(defaults);\n });\n\n // ==================== Token stats ====================\n console.get('/api/token-stats', (c) => {\n const days = parseInt(c.req.query('days') || '7', 10);\n return c.json(getTokenStats(days));\n });\n\n console.get('/api/token-stats/recent', (c) => {\n const limit = parseInt(c.req.query('limit') || '20', 10);\n const offset = parseInt(c.req.query('offset') || '0', 10);\n // 返回 { records, total },前端据此分页(total 供分页器计算总页数)\n return c.json({ records: getRecentRecords(limit, offset), total: getRecentRecordsCount() });\n });\n\n console.get('/api/token-stats/trend', (c) => {\n const days = parseInt(c.req.query('days') || '7', 10);\n return c.json(getTokenTrend(days));\n });\n\n console.post('/api/token-stats/reset', (c) => {\n resetTokenStats();\n return c.json({ reset: true });\n });\n\n return console;\n}\n"],"mappings":"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","names":["path","fileURLToPath","OpenAI","readFileSync","fileURLToPath","__filename","__dirname","fs","t","path","READ_KEYWORDS","WRITE_KEYWORDS","readFileSync","readdirSync","existsSync","resolve","dirname","fileURLToPath","__filename","__dirname","readFileSync","existsSync","readdirSync","join","fileURLToPath","dirname","__dirname","readFileSync","existsSync","resolve","dirname","fileURLToPath","hasRuntimeConfig","loadRuntimeConfig","getEnabledAgentExtensions","__filename","__dirname","readFileSync","existsSync","resolve","dirname","fileURLToPath","cache","hasRuntimeConfig","loadRuntimeConfig","getEnabledScenarioExtensions","__filename","__dirname","path","readFileSync","writeFileSync","existsSync","mkdirSync","unlinkSync","path","fs","path","fileURLToPath","join","dirname","i","fs","path","resolve","fs","path","Hono","require","readFileSync","existsSync","resolve","dirname","fileURLToPath","__filename","__dirname","readFileSync","resolve","join","statSync","existsSync","resolve","join","isAbsolute","homedir","fs","path","parts","path","MAX_LINES","evalExpr","evalCondition","op","left","right","lv","rv","CHILD_CALL_RE","path","node","SUSPICIOUS_PATTERNS","SCRIPT_EXEC_PATTERNS","KEYWORD_COMBINATION_RISKS","SINGLE_KEYWORD_RISKS","LEVEL_ORDER","scanScriptForKeywords","assessKeywordCombinationRisk","extractScriptPath","resolvePath","existsSync","statSync","join","homedir","resolve","analyzeScriptContent","isAbsolute","parts","recordTokenUsage","resolve","existsSync","readFileSync","writeFileSync","mkdirSync","join","homedir","join","homedir","path","existsSync","readFileSync","mkdirSync","writeFileSync","c","path","OpenAI","COMBO_STAGES","path","CRED_FILE_RE","EXFIL_RE","markStage","extractResources","path","CRED_FILE_RE","EXFIL_RE","fs","os","path","analyzeScriptContent","getDisabledL2RulesWithSkipL3","getLLMFailMode","fs","fs","os","path","sql","readFileSync","existsSync","join","dirname","fileURLToPath","__dirname","console","Hono","resolve"]}
|