@visorcraft/idlehands 0.9.1
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/LICENSE +21 -0
- package/README.md +30 -0
- package/dist/agent.js +2604 -0
- package/dist/agent.js.map +1 -0
- package/dist/anton/controller.js +341 -0
- package/dist/anton/controller.js.map +1 -0
- package/dist/anton/lock.js +110 -0
- package/dist/anton/lock.js.map +1 -0
- package/dist/anton/parser.js +303 -0
- package/dist/anton/parser.js.map +1 -0
- package/dist/anton/prompt.js +203 -0
- package/dist/anton/prompt.js.map +1 -0
- package/dist/anton/reporter.js +119 -0
- package/dist/anton/reporter.js.map +1 -0
- package/dist/anton/session.js +51 -0
- package/dist/anton/session.js.map +1 -0
- package/dist/anton/types.js +7 -0
- package/dist/anton/types.js.map +1 -0
- package/dist/anton/verifier.js +263 -0
- package/dist/anton/verifier.js.map +1 -0
- package/dist/bench/compare.js +239 -0
- package/dist/bench/compare.js.map +1 -0
- package/dist/bench/debug_hooks.js +17 -0
- package/dist/bench/debug_hooks.js.map +1 -0
- package/dist/bench/json_extract.js +22 -0
- package/dist/bench/json_extract.js.map +1 -0
- package/dist/bench/openclaw.js +86 -0
- package/dist/bench/openclaw.js.map +1 -0
- package/dist/bench/report.js +116 -0
- package/dist/bench/report.js.map +1 -0
- package/dist/bench/runner.js +312 -0
- package/dist/bench/runner.js.map +1 -0
- package/dist/bench/types.js +2 -0
- package/dist/bench/types.js.map +1 -0
- package/dist/bot/commands.js +444 -0
- package/dist/bot/commands.js.map +1 -0
- package/dist/bot/confirm-discord.js +133 -0
- package/dist/bot/confirm-discord.js.map +1 -0
- package/dist/bot/confirm-telegram.js +290 -0
- package/dist/bot/confirm-telegram.js.map +1 -0
- package/dist/bot/discord.js +826 -0
- package/dist/bot/discord.js.map +1 -0
- package/dist/bot/format.js +210 -0
- package/dist/bot/format.js.map +1 -0
- package/dist/bot/session-manager.js +270 -0
- package/dist/bot/session-manager.js.map +1 -0
- package/dist/bot/telegram.js +678 -0
- package/dist/bot/telegram.js.map +1 -0
- package/dist/cli/agent-turn.js +45 -0
- package/dist/cli/agent-turn.js.map +1 -0
- package/dist/cli/args.js +236 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/bot.js +252 -0
- package/dist/cli/bot.js.map +1 -0
- package/dist/cli/build-repl-context.js +365 -0
- package/dist/cli/build-repl-context.js.map +1 -0
- package/dist/cli/command-registry.js +20 -0
- package/dist/cli/command-registry.js.map +1 -0
- package/dist/cli/commands/anton.js +271 -0
- package/dist/cli/commands/anton.js.map +1 -0
- package/dist/cli/commands/editing.js +328 -0
- package/dist/cli/commands/editing.js.map +1 -0
- package/dist/cli/commands/model.js +274 -0
- package/dist/cli/commands/model.js.map +1 -0
- package/dist/cli/commands/project.js +255 -0
- package/dist/cli/commands/project.js.map +1 -0
- package/dist/cli/commands/runtime.js +63 -0
- package/dist/cli/commands/runtime.js.map +1 -0
- package/dist/cli/commands/session.js +281 -0
- package/dist/cli/commands/session.js.map +1 -0
- package/dist/cli/commands/tools.js +126 -0
- package/dist/cli/commands/tools.js.map +1 -0
- package/dist/cli/commands/trifecta.js +221 -0
- package/dist/cli/commands/trifecta.js.map +1 -0
- package/dist/cli/commands/tui.js +17 -0
- package/dist/cli/commands/tui.js.map +1 -0
- package/dist/cli/init.js +222 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/input.js +360 -0
- package/dist/cli/input.js.map +1 -0
- package/dist/cli/oneshot.js +254 -0
- package/dist/cli/oneshot.js.map +1 -0
- package/dist/cli/repl-context.js +2 -0
- package/dist/cli/repl-context.js.map +1 -0
- package/dist/cli/runtime-cmds.js +811 -0
- package/dist/cli/runtime-cmds.js.map +1 -0
- package/dist/cli/service.js +145 -0
- package/dist/cli/service.js.map +1 -0
- package/dist/cli/session-state.js +130 -0
- package/dist/cli/session-state.js.map +1 -0
- package/dist/cli/setup.js +815 -0
- package/dist/cli/setup.js.map +1 -0
- package/dist/cli/shell.js +79 -0
- package/dist/cli/shell.js.map +1 -0
- package/dist/cli/status.js +392 -0
- package/dist/cli/status.js.map +1 -0
- package/dist/cli/watch.js +33 -0
- package/dist/cli/watch.js.map +1 -0
- package/dist/client.js +676 -0
- package/dist/client.js.map +1 -0
- package/dist/commands.js +194 -0
- package/dist/commands.js.map +1 -0
- package/dist/config.js +507 -0
- package/dist/config.js.map +1 -0
- package/dist/confirm/auto.js +13 -0
- package/dist/confirm/auto.js.map +1 -0
- package/dist/confirm/headless.js +41 -0
- package/dist/confirm/headless.js.map +1 -0
- package/dist/confirm/terminal.js +90 -0
- package/dist/confirm/terminal.js.map +1 -0
- package/dist/context.js +49 -0
- package/dist/context.js.map +1 -0
- package/dist/git.js +136 -0
- package/dist/git.js.map +1 -0
- package/dist/harnesses.js +171 -0
- package/dist/harnesses.js.map +1 -0
- package/dist/history.js +139 -0
- package/dist/history.js.map +1 -0
- package/dist/index.js +700 -0
- package/dist/index.js.map +1 -0
- package/dist/indexer.js +374 -0
- package/dist/indexer.js.map +1 -0
- package/dist/jsonrpc.js +76 -0
- package/dist/jsonrpc.js.map +1 -0
- package/dist/lens.js +525 -0
- package/dist/lens.js.map +1 -0
- package/dist/lsp.js +605 -0
- package/dist/lsp.js.map +1 -0
- package/dist/markdown.js +275 -0
- package/dist/markdown.js.map +1 -0
- package/dist/mcp.js +554 -0
- package/dist/mcp.js.map +1 -0
- package/dist/recovery.js +178 -0
- package/dist/recovery.js.map +1 -0
- package/dist/replay.js +132 -0
- package/dist/replay.js.map +1 -0
- package/dist/replay_cli.js +24 -0
- package/dist/replay_cli.js.map +1 -0
- package/dist/runtime/executor.js +418 -0
- package/dist/runtime/executor.js.map +1 -0
- package/dist/runtime/planner.js +197 -0
- package/dist/runtime/planner.js.map +1 -0
- package/dist/runtime/store.js +289 -0
- package/dist/runtime/store.js.map +1 -0
- package/dist/runtime/types.js +2 -0
- package/dist/runtime/types.js.map +1 -0
- package/dist/safety.js +446 -0
- package/dist/safety.js.map +1 -0
- package/dist/spinner.js +224 -0
- package/dist/spinner.js.map +1 -0
- package/dist/sys/context.js +124 -0
- package/dist/sys/context.js.map +1 -0
- package/dist/sys/snapshot.sh +97 -0
- package/dist/term.js +61 -0
- package/dist/term.js.map +1 -0
- package/dist/themes.js +135 -0
- package/dist/themes.js.map +1 -0
- package/dist/tools.js +1114 -0
- package/dist/tools.js.map +1 -0
- package/dist/tui/branch-picker.js +65 -0
- package/dist/tui/branch-picker.js.map +1 -0
- package/dist/tui/command-handler.js +108 -0
- package/dist/tui/command-handler.js.map +1 -0
- package/dist/tui/confirm.js +90 -0
- package/dist/tui/confirm.js.map +1 -0
- package/dist/tui/controller.js +463 -0
- package/dist/tui/controller.js.map +1 -0
- package/dist/tui/event-bridge.js +44 -0
- package/dist/tui/event-bridge.js.map +1 -0
- package/dist/tui/events.js +2 -0
- package/dist/tui/events.js.map +1 -0
- package/dist/tui/keymap.js +144 -0
- package/dist/tui/keymap.js.map +1 -0
- package/dist/tui/layout.js +11 -0
- package/dist/tui/layout.js.map +1 -0
- package/dist/tui/render.js +186 -0
- package/dist/tui/render.js.map +1 -0
- package/dist/tui/screen.js +48 -0
- package/dist/tui/screen.js.map +1 -0
- package/dist/tui/state.js +167 -0
- package/dist/tui/state.js.map +1 -0
- package/dist/tui/theme.js +70 -0
- package/dist/tui/theme.js.map +1 -0
- package/dist/tui/types.js +2 -0
- package/dist/tui/types.js.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/upgrade.js +412 -0
- package/dist/upgrade.js.map +1 -0
- package/dist/utils.js +87 -0
- package/dist/utils.js.map +1 -0
- package/dist/vault.js +520 -0
- package/dist/vault.js.map +1 -0
- package/dist/vim.js +160 -0
- package/dist/vim.js.map +1 -0
- package/package.json +67 -0
- package/src/sys/snapshot.sh +97 -0
package/dist/safety.js
ADDED
|
@@ -0,0 +1,446 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Safety module — graduated permission system for exec and file operations.
|
|
3
|
+
*
|
|
4
|
+
* Three tiers:
|
|
5
|
+
* - FORBIDDEN: Always blocked, even in yolo mode. Hard stop, no override.
|
|
6
|
+
* - CAUTIOUS: Require explicit confirmation in default/auto-edit modes.
|
|
7
|
+
* Skipped only in yolo mode.
|
|
8
|
+
* - FREE: No restrictions.
|
|
9
|
+
*
|
|
10
|
+
* Also enforces:
|
|
11
|
+
* - Protected path restrictions (write/edit never touch system-critical files)
|
|
12
|
+
* - Path traversal detection (symlink escape, ../ escape outside cwd)
|
|
13
|
+
* - Working directory containment (optional)
|
|
14
|
+
* - Lockdown mode (--lockdown): promotes ALL cautious → forbidden
|
|
15
|
+
* - User-configurable overrides via ~/.config/idlehands/safety.json
|
|
16
|
+
* - Safety logging to stderr
|
|
17
|
+
*/
|
|
18
|
+
import path from 'node:path';
|
|
19
|
+
import fs from 'node:fs/promises';
|
|
20
|
+
import { configDir } from './utils.js';
|
|
21
|
+
// ──────────────────────────────────────────────────────
|
|
22
|
+
// Forbidden patterns — ALWAYS blocked, even in yolo mode
|
|
23
|
+
// ──────────────────────────────────────────────────────
|
|
24
|
+
export const FORBIDDEN_PATTERNS = [
|
|
25
|
+
// Wipe root / home / system directories
|
|
26
|
+
{ re: /\brm\s+(-\w*[rf]\w*\s+)*\s*\/\s*$/, reason: 'rm targeting /' },
|
|
27
|
+
{ re: /\brm\s+(-\w*[rf]\w*\s+)+\/$/, reason: 'rm -rf /' },
|
|
28
|
+
{ re: /\brm\s+(-\w*[rf]\w*\s+)+\/(boot|etc|usr|lib|sbin|bin|var|sys|proc|dev)\b/,
|
|
29
|
+
reason: 'rm targeting system directory' },
|
|
30
|
+
{ re: /\brm\s+(-\w*[rf]\w*\s+)+~\/?$/, reason: 'rm targeting home directory' },
|
|
31
|
+
{ re: /\brm\s+(-\w*[rf]\w*\s+)+\$HOME\b/, reason: 'rm targeting $HOME' },
|
|
32
|
+
// Block device / partition destruction
|
|
33
|
+
{ re: /\bdd\b.*\bof\s*=\s*\/dev\//, reason: 'dd writing to block device' },
|
|
34
|
+
{ re: /\bmkfs\b/, reason: 'mkfs (filesystem creation)' },
|
|
35
|
+
{ re: /\bfdisk\b/, reason: 'fdisk (partition table modification)' },
|
|
36
|
+
{ re: /\bparted\b/, reason: 'parted (partition modification)' },
|
|
37
|
+
// Boot/kernel destruction
|
|
38
|
+
{ re: /\bupdate-grub\b/, reason: 'GRUB modification' },
|
|
39
|
+
{ re: /\bgrub-install\b/, reason: 'GRUB installation' },
|
|
40
|
+
// Recursive permission nuke
|
|
41
|
+
{ re: /\bchmod\s+(-\w*R\w*\s+)*(0?777|a\+rwx)\s+\/\s*$/,
|
|
42
|
+
reason: 'chmod 777 / (recursive permission nuke)' },
|
|
43
|
+
{ re: /\bchown\s+(-\w*R\w*\s+).*\s+\/\s*$/, reason: 'chown targeting /' },
|
|
44
|
+
// Fork bomb
|
|
45
|
+
{ re: /:\s*\(\s*\)\s*\{\s*:\s*\|\s*:\s*&\s*\}\s*;\s*:/,
|
|
46
|
+
reason: 'fork bomb' },
|
|
47
|
+
// Direct passwd/shadow manipulation
|
|
48
|
+
{ re: />\s*\/etc\/passwd\b/, reason: 'overwriting /etc/passwd' },
|
|
49
|
+
{ re: />\s*\/etc\/shadow\b/, reason: 'overwriting /etc/shadow' },
|
|
50
|
+
// Disable firewall entirely
|
|
51
|
+
{ re: /\bufw\s+disable\b/, reason: 'disabling firewall' },
|
|
52
|
+
{ re: /\biptables\s+-F\b/, reason: 'flushing all iptables rules' },
|
|
53
|
+
// System shutdown/reboot (model shouldn't decide this)
|
|
54
|
+
{ re: /\b(shutdown|reboot|poweroff|init\s+[06])\b/, reason: 'system shutdown/reboot' },
|
|
55
|
+
// Wipe entire git history
|
|
56
|
+
{ re: /\bgit\s+push\s+--mirror\b/, reason: 'git mirror push (overwrites remote)' },
|
|
57
|
+
];
|
|
58
|
+
// ──────────────────────────────────────────────────────
|
|
59
|
+
// Cautious patterns — require confirmation in default/auto-edit
|
|
60
|
+
// ──────────────────────────────────────────────────────
|
|
61
|
+
export const CAUTIOUS_PATTERNS = [
|
|
62
|
+
// Recursive delete (non-system paths)
|
|
63
|
+
{ re: /\brm\s+(-\w*[rf]\w*\s+)/, reason: 'rm with -r or -f flags' },
|
|
64
|
+
// Sudo escalation
|
|
65
|
+
{ re: /\bsudo\b/, reason: 'sudo (privilege escalation)' },
|
|
66
|
+
// Remote code execution
|
|
67
|
+
{ re: /\bcurl\b.*\|\s*(ba)?sh\b/, reason: 'piping curl to shell' },
|
|
68
|
+
{ re: /\bwget\b.*\|\s*(ba)?sh\b/, reason: 'piping wget to shell' },
|
|
69
|
+
// Git force operations
|
|
70
|
+
{ re: /\bgit\s+push\s+.*--force\b/, reason: 'git force push' },
|
|
71
|
+
{ re: /\bgit\s+push\s+-f\b/, reason: 'git force push' },
|
|
72
|
+
{ re: /\bgit\s+reset\s+--hard\b/, reason: 'git reset --hard' },
|
|
73
|
+
{ re: /\bgit\s+clean\s+-[dfx]/, reason: 'git clean (removes untracked files)' },
|
|
74
|
+
// Package management
|
|
75
|
+
{ re: /\b(apt|apt-get|dnf|yum|pacman|pip|npm)\s+(install|remove|purge|uninstall)\b/,
|
|
76
|
+
reason: 'package install/remove' },
|
|
77
|
+
// Service management
|
|
78
|
+
{ re: /\bsystemctl\s+(start|stop|restart|enable|disable|mask)\b/,
|
|
79
|
+
reason: 'service state change' },
|
|
80
|
+
// Network/firewall changes
|
|
81
|
+
{ re: /\bufw\s+(allow|deny|reject)\b/, reason: 'firewall rule change' },
|
|
82
|
+
{ re: /\biptables\s+(-A|-I|-D)\b/, reason: 'iptables rule change' },
|
|
83
|
+
// Docker management
|
|
84
|
+
{ re: /\bdocker\s+(rm|rmi|system\s+prune)\b/, reason: 'docker resource removal' },
|
|
85
|
+
// Dangerous file operations outside of the tool system
|
|
86
|
+
{ re: /\bmv\s+.*\/\.\./, reason: 'mv with path traversal' },
|
|
87
|
+
{ re: /\bcp\s+.*--no-preserve\b/, reason: 'cp without preserving attributes' },
|
|
88
|
+
// SSH/SCP to remote (model should confirm remote operations)
|
|
89
|
+
{ re: /\bssh\b/, reason: 'ssh (remote operation)' },
|
|
90
|
+
{ re: /\bscp\b/, reason: 'scp (remote copy)' },
|
|
91
|
+
{ re: /\brsync\b/, reason: 'rsync (remote sync)' },
|
|
92
|
+
];
|
|
93
|
+
// ──────────────────────────────────────────────────────
|
|
94
|
+
// Protected paths — file tools can NEVER write to these
|
|
95
|
+
// ──────────────────────────────────────────────────────
|
|
96
|
+
const PROTECTED_PATHS = [
|
|
97
|
+
'/boot',
|
|
98
|
+
'/etc/grub.d',
|
|
99
|
+
'/etc/default/grub',
|
|
100
|
+
'/etc/passwd',
|
|
101
|
+
'/etc/shadow',
|
|
102
|
+
'/etc/sudoers',
|
|
103
|
+
'/etc/fstab',
|
|
104
|
+
'/proc',
|
|
105
|
+
'/sys',
|
|
106
|
+
'/dev',
|
|
107
|
+
];
|
|
108
|
+
/**
|
|
109
|
+
* Paths that should never be the target of rm -rf or similar bulk deletion.
|
|
110
|
+
* These are broader than PROTECTED_PATHS — they protect user data, not just system files.
|
|
111
|
+
*/
|
|
112
|
+
const PROTECTED_DELETE_ROOTS = [
|
|
113
|
+
'/',
|
|
114
|
+
'/home',
|
|
115
|
+
'/root',
|
|
116
|
+
'/var',
|
|
117
|
+
'/usr',
|
|
118
|
+
'/lib',
|
|
119
|
+
'/bin',
|
|
120
|
+
'/sbin',
|
|
121
|
+
'/etc',
|
|
122
|
+
'/boot',
|
|
123
|
+
'/opt',
|
|
124
|
+
];
|
|
125
|
+
// ──────────────────────────────────────────────────────
|
|
126
|
+
// Safety options (set once at startup, consulted per-check)
|
|
127
|
+
// ──────────────────────────────────────────────────────
|
|
128
|
+
let _lockdown = false;
|
|
129
|
+
let _logEnabled = false;
|
|
130
|
+
let _userForbidden = [];
|
|
131
|
+
let _userCautious = [];
|
|
132
|
+
let _userAllow = [];
|
|
133
|
+
let _userProtectedPaths = [];
|
|
134
|
+
let _userProtectedDeleteRoots = [];
|
|
135
|
+
/** Enable lockdown mode: all cautious commands become forbidden. */
|
|
136
|
+
export function setLockdown(enabled) { _lockdown = enabled; }
|
|
137
|
+
function isLockdown() { return _lockdown; }
|
|
138
|
+
/** Enable safety logging to stderr. */
|
|
139
|
+
export function setSafetyLogging(enabled) { _logEnabled = enabled; }
|
|
140
|
+
function safetyLog(tier, detail) {
|
|
141
|
+
if (!_logEnabled)
|
|
142
|
+
return;
|
|
143
|
+
const tag = tier === 'forbidden' ? '\x1b[31m[safety] BLOCKED\x1b[0m'
|
|
144
|
+
: tier === 'cautious' ? '\x1b[33m[safety] cautious\x1b[0m'
|
|
145
|
+
: '\x1b[2m[safety] free\x1b[0m';
|
|
146
|
+
process.stderr.write(`${tag}: ${detail}\n`);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Load user safety config from ~/.config/idlehands/safety.json
|
|
150
|
+
* Invalid patterns are silently skipped with a warning on stderr.
|
|
151
|
+
*/
|
|
152
|
+
export async function loadSafetyConfig(configPath) {
|
|
153
|
+
const p = configPath ?? path.join(configDir(), 'safety.json');
|
|
154
|
+
let raw;
|
|
155
|
+
try {
|
|
156
|
+
raw = await fs.readFile(p, 'utf8');
|
|
157
|
+
}
|
|
158
|
+
catch (e) {
|
|
159
|
+
if (e?.code === 'ENOENT')
|
|
160
|
+
return {};
|
|
161
|
+
if (!process.env.IDLEHANDS_QUIET_WARNINGS) {
|
|
162
|
+
process.stderr.write(`[safety] warning: failed to read ${p}: ${e?.message}\n`);
|
|
163
|
+
}
|
|
164
|
+
return {};
|
|
165
|
+
}
|
|
166
|
+
try {
|
|
167
|
+
const parsed = JSON.parse(raw);
|
|
168
|
+
_userForbidden = compilePatterns(parsed.forbidden_patterns, 'forbidden');
|
|
169
|
+
_userCautious = compilePatterns(parsed.cautious_patterns, 'cautious');
|
|
170
|
+
_userAllow = compileAllowPatterns(parsed.allow_patterns);
|
|
171
|
+
_userProtectedPaths = Array.isArray(parsed.protected_paths) ? parsed.protected_paths.filter((s) => typeof s === 'string') : [];
|
|
172
|
+
_userProtectedDeleteRoots = Array.isArray(parsed.protected_delete_roots) ? parsed.protected_delete_roots.filter((s) => typeof s === 'string') : [];
|
|
173
|
+
return parsed;
|
|
174
|
+
}
|
|
175
|
+
catch (e) {
|
|
176
|
+
if (!process.env.IDLEHANDS_QUIET_WARNINGS) {
|
|
177
|
+
process.stderr.write(`[safety] warning: invalid JSON in ${p}: ${e?.message}\n`);
|
|
178
|
+
}
|
|
179
|
+
return {};
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
function compilePatterns(patterns, label) {
|
|
183
|
+
if (!Array.isArray(patterns))
|
|
184
|
+
return [];
|
|
185
|
+
const result = [];
|
|
186
|
+
for (const p of patterns) {
|
|
187
|
+
if (typeof p !== 'string')
|
|
188
|
+
continue;
|
|
189
|
+
try {
|
|
190
|
+
result.push({ re: new RegExp(p), reason: `user ${label}: ${p}` });
|
|
191
|
+
}
|
|
192
|
+
catch (e) {
|
|
193
|
+
if (!process.env.IDLEHANDS_QUIET_WARNINGS) {
|
|
194
|
+
process.stderr.write(`[safety] warning: invalid regex in ${label}: ${p} — ${e?.message}\n`);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return result;
|
|
199
|
+
}
|
|
200
|
+
function compileAllowPatterns(patterns) {
|
|
201
|
+
if (!Array.isArray(patterns))
|
|
202
|
+
return [];
|
|
203
|
+
const result = [];
|
|
204
|
+
for (const p of patterns) {
|
|
205
|
+
if (typeof p !== 'string')
|
|
206
|
+
continue;
|
|
207
|
+
try {
|
|
208
|
+
result.push(new RegExp(p));
|
|
209
|
+
}
|
|
210
|
+
catch (e) {
|
|
211
|
+
if (!process.env.IDLEHANDS_QUIET_WARNINGS) {
|
|
212
|
+
process.stderr.write(`[safety] warning: invalid allow regex: ${p} — ${e?.message}\n`);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return result;
|
|
217
|
+
}
|
|
218
|
+
/** Reset all runtime safety state (for testing). */
|
|
219
|
+
export function resetSafetyState() {
|
|
220
|
+
_lockdown = false;
|
|
221
|
+
_logEnabled = false;
|
|
222
|
+
_userForbidden = [];
|
|
223
|
+
_userCautious = [];
|
|
224
|
+
_userAllow = [];
|
|
225
|
+
_userProtectedPaths = [];
|
|
226
|
+
_userProtectedDeleteRoots = [];
|
|
227
|
+
}
|
|
228
|
+
// ──────────────────────────────────────────────────────
|
|
229
|
+
// Exec safety check
|
|
230
|
+
// ──────────────────────────────────────────────────────
|
|
231
|
+
/**
|
|
232
|
+
* Screen an exec command against safety patterns.
|
|
233
|
+
* Returns a verdict indicating whether the command should be blocked, confirmed, or free.
|
|
234
|
+
*/
|
|
235
|
+
export function checkExecSafety(command) {
|
|
236
|
+
// Normalize: collapse whitespace, trim
|
|
237
|
+
const cmd = command.replace(/\s+/g, ' ').trim();
|
|
238
|
+
// Check forbidden patterns first (highest priority)
|
|
239
|
+
// Built-in forbidden
|
|
240
|
+
for (const { re, reason } of FORBIDDEN_PATTERNS) {
|
|
241
|
+
if (re.test(cmd)) {
|
|
242
|
+
safetyLog('forbidden', `${reason} — ${cmd}`);
|
|
243
|
+
return { allowed: false, tier: 'forbidden', reason: `BLOCKED: ${reason}` };
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
// User-defined forbidden
|
|
247
|
+
for (const { re, reason } of _userForbidden) {
|
|
248
|
+
if (re.test(cmd)) {
|
|
249
|
+
safetyLog('forbidden', `${reason} — ${cmd}`);
|
|
250
|
+
return { allowed: false, tier: 'forbidden', reason: `BLOCKED: ${reason}` };
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
// Check cautious patterns
|
|
254
|
+
// Built-in cautious
|
|
255
|
+
for (const { re, reason } of CAUTIOUS_PATTERNS) {
|
|
256
|
+
if (re.test(cmd)) {
|
|
257
|
+
// Check user allow-list first (explicit bypass for known-safe commands)
|
|
258
|
+
if (_userAllow.some(a => a.test(cmd))) {
|
|
259
|
+
safetyLog('free', `allowed by user allow_patterns — ${cmd}`);
|
|
260
|
+
return { allowed: true, tier: 'free' };
|
|
261
|
+
}
|
|
262
|
+
// Lockdown: cautious → forbidden
|
|
263
|
+
if (_lockdown) {
|
|
264
|
+
safetyLog('forbidden', `lockdown promoted: ${reason} — ${cmd}`);
|
|
265
|
+
return { allowed: false, tier: 'forbidden', reason: `BLOCKED (lockdown): ${reason}` };
|
|
266
|
+
}
|
|
267
|
+
safetyLog('cautious', `${reason} — ${cmd}`);
|
|
268
|
+
return {
|
|
269
|
+
allowed: true, // allowed but needs confirmation
|
|
270
|
+
tier: 'cautious',
|
|
271
|
+
reason,
|
|
272
|
+
prompt: `⚠️ Cautious command detected: ${reason}\n\n ${command}\n\nProceed?`,
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
// User-defined cautious
|
|
277
|
+
for (const { re, reason } of _userCautious) {
|
|
278
|
+
if (re.test(cmd)) {
|
|
279
|
+
if (_userAllow.some(a => a.test(cmd))) {
|
|
280
|
+
safetyLog('free', `allowed by user allow_patterns — ${cmd}`);
|
|
281
|
+
return { allowed: true, tier: 'free' };
|
|
282
|
+
}
|
|
283
|
+
if (_lockdown) {
|
|
284
|
+
safetyLog('forbidden', `lockdown promoted: ${reason} — ${cmd}`);
|
|
285
|
+
return { allowed: false, tier: 'forbidden', reason: `BLOCKED (lockdown): ${reason}` };
|
|
286
|
+
}
|
|
287
|
+
safetyLog('cautious', `${reason} — ${cmd}`);
|
|
288
|
+
return {
|
|
289
|
+
allowed: true,
|
|
290
|
+
tier: 'cautious',
|
|
291
|
+
reason,
|
|
292
|
+
prompt: `⚠️ Cautious command detected: ${reason}\n\n ${command}\n\nProceed?`,
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
safetyLog('free', cmd);
|
|
297
|
+
return { allowed: true, tier: 'free' };
|
|
298
|
+
}
|
|
299
|
+
// ──────────────────────────────────────────────────────
|
|
300
|
+
// Path safety check (for write_file / edit_file / insert_file)
|
|
301
|
+
// ──────────────────────────────────────────────────────
|
|
302
|
+
/**
|
|
303
|
+
* Check if a resolved absolute path is safe to write to.
|
|
304
|
+
* This runs BEFORE any file operation.
|
|
305
|
+
*/
|
|
306
|
+
export function checkPathSafety(absPath) {
|
|
307
|
+
const norm = path.normalize(absPath);
|
|
308
|
+
// Check against built-in protected paths
|
|
309
|
+
for (const pp of PROTECTED_PATHS) {
|
|
310
|
+
if (norm === pp || norm.startsWith(pp + '/')) {
|
|
311
|
+
safetyLog('forbidden', `write to protected path ${pp}: ${norm}`);
|
|
312
|
+
return {
|
|
313
|
+
allowed: false,
|
|
314
|
+
tier: 'forbidden',
|
|
315
|
+
reason: `BLOCKED: write to protected path ${pp}`,
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
// Check against user-defined protected paths
|
|
320
|
+
for (const pp of _userProtectedPaths) {
|
|
321
|
+
const normPP = path.normalize(pp);
|
|
322
|
+
if (norm === normPP || norm.startsWith(normPP + '/')) {
|
|
323
|
+
safetyLog('forbidden', `write to user-protected path ${pp}: ${norm}`);
|
|
324
|
+
return {
|
|
325
|
+
allowed: false,
|
|
326
|
+
tier: 'forbidden',
|
|
327
|
+
reason: `BLOCKED: write to user-protected path ${pp}`,
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
// Warn on writes outside home directory (likely unintentional)
|
|
332
|
+
const home = process.env.HOME || '/home/' + process.env.USER;
|
|
333
|
+
if (!norm.startsWith(home + '/') && norm !== home) {
|
|
334
|
+
// /tmp is fine for scratch work
|
|
335
|
+
if (!norm.startsWith('/tmp/') && !norm.startsWith('/var/tmp/')) {
|
|
336
|
+
if (_lockdown) {
|
|
337
|
+
safetyLog('forbidden', `lockdown: write outside home: ${norm}`);
|
|
338
|
+
return {
|
|
339
|
+
allowed: false,
|
|
340
|
+
tier: 'forbidden',
|
|
341
|
+
reason: `BLOCKED (lockdown): write outside home directory: ${norm}`,
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
safetyLog('cautious', `write outside home: ${norm}`);
|
|
345
|
+
return {
|
|
346
|
+
allowed: true,
|
|
347
|
+
tier: 'cautious',
|
|
348
|
+
reason: `writing outside home directory: ${norm}`,
|
|
349
|
+
prompt: `⚠️ Writing outside home directory:\n ${norm}\n\nProceed?`,
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
safetyLog('free', `path ok: ${norm}`);
|
|
354
|
+
return { allowed: true, tier: 'free' };
|
|
355
|
+
}
|
|
356
|
+
// ──────────────────────────────────────────────────────
|
|
357
|
+
// Path traversal detection
|
|
358
|
+
// ──────────────────────────────────────────────────────
|
|
359
|
+
/**
|
|
360
|
+
* Detect if a resolved path escapes the given working directory.
|
|
361
|
+
* Also checks for symlink escapes (resolves real path).
|
|
362
|
+
*
|
|
363
|
+
* Returns null if safe, or an error message if escaping.
|
|
364
|
+
*/
|
|
365
|
+
export async function checkPathTraversal(absPath, cwd, allowedDirs) {
|
|
366
|
+
const norm = path.normalize(absPath);
|
|
367
|
+
// Check if within cwd
|
|
368
|
+
if (norm.startsWith(cwd + '/') || norm === cwd)
|
|
369
|
+
return null;
|
|
370
|
+
// Check if within any allowed directory
|
|
371
|
+
if (allowedDirs) {
|
|
372
|
+
for (const dir of allowedDirs) {
|
|
373
|
+
const resolved = path.resolve(dir);
|
|
374
|
+
if (norm.startsWith(resolved + '/') || norm === resolved)
|
|
375
|
+
return null;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
// Check home directory — always allow access to files under home
|
|
379
|
+
const home = process.env.HOME || '/home/' + process.env.USER;
|
|
380
|
+
if (norm.startsWith(home + '/') || norm === home)
|
|
381
|
+
return null;
|
|
382
|
+
// If path exists, check for symlink escape
|
|
383
|
+
try {
|
|
384
|
+
const realPath = await fs.realpath(absPath);
|
|
385
|
+
if (realPath !== norm) {
|
|
386
|
+
// Symlink resolved to different location — re-check
|
|
387
|
+
if (!realPath.startsWith(cwd + '/') && realPath !== cwd) {
|
|
388
|
+
if (allowedDirs) {
|
|
389
|
+
const inAllowed = allowedDirs.some(d => {
|
|
390
|
+
const rd = path.resolve(d);
|
|
391
|
+
return realPath.startsWith(rd + '/') || realPath === rd;
|
|
392
|
+
});
|
|
393
|
+
if (inAllowed)
|
|
394
|
+
return null;
|
|
395
|
+
}
|
|
396
|
+
return `path traversal: ${absPath} resolves to ${realPath} (outside working directory ${cwd})`;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
catch {
|
|
401
|
+
// File doesn't exist yet — that's fine for write operations
|
|
402
|
+
}
|
|
403
|
+
return `path outside working directory: ${norm} is not within ${cwd}`;
|
|
404
|
+
}
|
|
405
|
+
// ──────────────────────────────────────────────────────
|
|
406
|
+
// Helpers
|
|
407
|
+
// ──────────────────────────────────────────────────────
|
|
408
|
+
/**
|
|
409
|
+
* Check if a command targets a protected delete root.
|
|
410
|
+
* Used for extra protection on rm commands beyond pattern matching.
|
|
411
|
+
*/
|
|
412
|
+
export function isProtectedDeleteTarget(command) {
|
|
413
|
+
// Extract paths from rm commands
|
|
414
|
+
const rmMatch = /\brm\s+(-\w+\s+)*(.+)/.exec(command);
|
|
415
|
+
if (!rmMatch)
|
|
416
|
+
return false;
|
|
417
|
+
const allRoots = [...PROTECTED_DELETE_ROOTS, ..._userProtectedDeleteRoots];
|
|
418
|
+
const targets = rmMatch[2].split(/\s+/).filter(t => t.startsWith('/'));
|
|
419
|
+
for (const target of targets) {
|
|
420
|
+
const norm = path.normalize(target).replace(/\/+$/, '') || '/';
|
|
421
|
+
if (allRoots.includes(norm))
|
|
422
|
+
return true;
|
|
423
|
+
// Also catch /home/username (protect entire user homes)
|
|
424
|
+
if (/^\/home\/[^/]+\/?$/.test(norm))
|
|
425
|
+
return true;
|
|
426
|
+
}
|
|
427
|
+
return false;
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* Summary of all safety classifications for a command (for testing/debugging).
|
|
431
|
+
*/
|
|
432
|
+
export function classifyCommand(command) {
|
|
433
|
+
const cmd = command.replace(/\s+/g, ' ').trim();
|
|
434
|
+
const forbidden = [];
|
|
435
|
+
const cautious = [];
|
|
436
|
+
for (const { re, reason } of FORBIDDEN_PATTERNS) {
|
|
437
|
+
if (re.test(cmd))
|
|
438
|
+
forbidden.push({ pattern: re.source, reason });
|
|
439
|
+
}
|
|
440
|
+
for (const { re, reason } of CAUTIOUS_PATTERNS) {
|
|
441
|
+
if (re.test(cmd))
|
|
442
|
+
cautious.push({ pattern: re.source, reason });
|
|
443
|
+
}
|
|
444
|
+
return { forbidden, cautious };
|
|
445
|
+
}
|
|
446
|
+
//# sourceMappingURL=safety.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"safety.js","sourceRoot":"","sources":["../src/safety.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,yDAAyD;AACzD,yDAAyD;AACzD,yDAAyD;AAEzD,MAAM,CAAC,MAAM,kBAAkB,GAA0C;IACvE,wCAAwC;IACxC,EAAE,EAAE,EAAE,mCAAmC,EAAI,MAAM,EAAE,gBAAgB,EAAE;IACvE,EAAE,EAAE,EAAE,6BAA6B,EAAW,MAAM,EAAE,UAAU,EAAE;IAClE,EAAE,EAAE,EAAE,0EAA0E;QAChC,MAAM,EAAE,+BAA+B,EAAE;IACzF,EAAE,EAAE,EAAE,+BAA+B,EAAS,MAAM,EAAE,6BAA6B,EAAE;IACrF,EAAE,EAAE,EAAE,kCAAkC,EAAM,MAAM,EAAE,oBAAoB,EAAE;IAE5E,uCAAuC;IACvC,EAAE,EAAE,EAAE,4BAA4B,EAAa,MAAM,EAAE,4BAA4B,EAAE;IACrF,EAAE,EAAE,EAAE,UAAU,EAAgC,MAAM,EAAE,4BAA4B,EAAE;IACtF,EAAE,EAAE,EAAE,WAAW,EAA+B,MAAM,EAAE,sCAAsC,EAAE;IAChG,EAAE,EAAE,EAAE,YAAY,EAA8B,MAAM,EAAE,iCAAiC,EAAE;IAE3F,0BAA0B;IAC1B,EAAE,EAAE,EAAE,iBAAiB,EAAyB,MAAM,EAAE,mBAAmB,EAAE;IAC7E,EAAE,EAAE,EAAE,kBAAkB,EAAwB,MAAM,EAAE,mBAAmB,EAAE;IAE7E,4BAA4B;IAC5B,EAAE,EAAE,EAAE,iDAAiD;QACP,MAAM,EAAE,yCAAyC,EAAE;IACnG,EAAE,EAAE,EAAE,oCAAoC,EAAI,MAAM,EAAE,mBAAmB,EAAE;IAE3E,YAAY;IACZ,EAAE,EAAE,EAAE,gDAAgD;QACN,MAAM,EAAE,WAAW,EAAE;IAErE,oCAAoC;IACpC,EAAE,EAAE,EAAE,qBAAqB,EAAqB,MAAM,EAAE,yBAAyB,EAAE;IACnF,EAAE,EAAE,EAAE,qBAAqB,EAAqB,MAAM,EAAE,yBAAyB,EAAE;IAEnF,4BAA4B;IAC5B,EAAE,EAAE,EAAE,mBAAmB,EAAuB,MAAM,EAAE,oBAAoB,EAAE;IAC9E,EAAE,EAAE,EAAE,mBAAmB,EAAuB,MAAM,EAAE,6BAA6B,EAAE;IAEvF,uDAAuD;IACvD,EAAE,EAAE,EAAE,4CAA4C,EAAE,MAAM,EAAE,wBAAwB,EAAE;IAEtF,0BAA0B;IAC1B,EAAE,EAAE,EAAE,2BAA2B,EAAc,MAAM,EAAE,qCAAqC,EAAE;CAC/F,CAAC;AAEF,yDAAyD;AACzD,gEAAgE;AAChE,yDAAyD;AAEzD,MAAM,CAAC,MAAM,iBAAiB,GAA0C;IACtE,sCAAsC;IACtC,EAAE,EAAE,EAAE,yBAAyB,EAAgB,MAAM,EAAE,wBAAwB,EAAE;IAEjF,kBAAkB;IAClB,EAAE,EAAE,EAAE,UAAU,EAAgC,MAAM,EAAE,6BAA6B,EAAE;IAEvF,wBAAwB;IACxB,EAAE,EAAE,EAAE,0BAA0B,EAAe,MAAM,EAAE,sBAAsB,EAAE;IAC/E,EAAE,EAAE,EAAE,0BAA0B,EAAe,MAAM,EAAE,sBAAsB,EAAE;IAE/E,uBAAuB;IACvB,EAAE,EAAE,EAAE,4BAA4B,EAAa,MAAM,EAAE,gBAAgB,EAAE;IACzE,EAAE,EAAE,EAAE,qBAAqB,EAAoB,MAAM,EAAE,gBAAgB,EAAE;IACzE,EAAE,EAAE,EAAE,0BAA0B,EAAe,MAAM,EAAE,kBAAkB,EAAE;IAC3E,EAAE,EAAE,EAAE,wBAAwB,EAAiB,MAAM,EAAE,qCAAqC,EAAE;IAE9F,qBAAqB;IACrB,EAAE,EAAE,EAAE,6EAA6E;QACnC,MAAM,EAAE,wBAAwB,EAAE;IAElF,qBAAqB;IACrB,EAAE,EAAE,EAAE,0DAA0D;QAChB,MAAM,EAAE,sBAAsB,EAAE;IAEhF,2BAA2B;IAC3B,EAAE,EAAE,EAAE,+BAA+B,EAAU,MAAM,EAAE,sBAAsB,EAAE;IAC/E,EAAE,EAAE,EAAE,2BAA2B,EAAc,MAAM,EAAE,sBAAsB,EAAE;IAE/E,oBAAoB;IACpB,EAAE,EAAE,EAAE,sCAAsC,EAAG,MAAM,EAAE,yBAAyB,EAAE;IAElF,uDAAuD;IACvD,EAAE,EAAE,EAAE,iBAAiB,EAAyB,MAAM,EAAE,wBAAwB,EAAE;IAClF,EAAE,EAAE,EAAE,0BAA0B,EAAe,MAAM,EAAE,kCAAkC,EAAE;IAE3F,6DAA6D;IAC7D,EAAE,EAAE,EAAE,SAAS,EAAiC,MAAM,EAAE,wBAAwB,EAAE;IAClF,EAAE,EAAE,EAAE,SAAS,EAAiC,MAAM,EAAE,mBAAmB,EAAE;IAC7E,EAAE,EAAE,EAAE,WAAW,EAA+B,MAAM,EAAE,qBAAqB,EAAE;CAChF,CAAC;AAEF,yDAAyD;AACzD,wDAAwD;AACxD,yDAAyD;AAEzD,MAAM,eAAe,GAAa;IAChC,OAAO;IACP,aAAa;IACb,mBAAmB;IACnB,aAAa;IACb,aAAa;IACb,cAAc;IACd,YAAY;IACZ,OAAO;IACP,MAAM;IACN,MAAM;CACP,CAAC;AAEF;;;GAGG;AACH,MAAM,sBAAsB,GAAa;IACvC,GAAG;IACH,OAAO;IACP,OAAO;IACP,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;CACP,CAAC;AA8BF,yDAAyD;AACzD,4DAA4D;AAC5D,yDAAyD;AAEzD,IAAI,SAAS,GAAG,KAAK,CAAC;AACtB,IAAI,WAAW,GAAG,KAAK,CAAC;AACxB,IAAI,cAAc,GAA0C,EAAE,CAAC;AAC/D,IAAI,aAAa,GAA0C,EAAE,CAAC;AAC9D,IAAI,UAAU,GAAa,EAAE,CAAC;AAC9B,IAAI,mBAAmB,GAAa,EAAE,CAAC;AACvC,IAAI,yBAAyB,GAAa,EAAE,CAAC;AAE7C,oEAAoE;AACpE,MAAM,UAAU,WAAW,CAAC,OAAgB,IAAI,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC;AACtE,SAAS,UAAU,KAAK,OAAO,SAAS,CAAC,CAAC,CAAC;AAE3C,uCAAuC;AACvC,MAAM,UAAU,gBAAgB,CAAC,OAAgB,IAAI,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC;AAE7E,SAAS,SAAS,CAAC,IAAY,EAAE,MAAc;IAC7C,IAAI,CAAC,WAAW;QAAE,OAAO;IACzB,MAAM,GAAG,GAAG,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,iCAAiC;QAC1D,CAAC,CAAC,IAAI,KAAK,UAAU,CAAE,CAAC,CAAC,kCAAkC;YAC3D,CAAC,CAAC,6BAA6B,CAAC;IAC1C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,KAAK,MAAM,IAAI,CAAC,CAAC;AAC9C,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,UAAmB;IACxD,MAAM,CAAC,GAAG,UAAU,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,aAAa,CAAC,CAAC;IAC9D,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IACrC,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,IAAI,CAAC,EAAE,IAAI,KAAK,QAAQ;YAAE,OAAO,EAAE,CAAC;QACpC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,wBAAwB,EAAE,CAAC;YAC1C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,oCAAoC,CAAC,KAAK,CAAC,EAAE,OAAO,IAAI,CAAC,CAAC;QACjF,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/B,cAAc,GAAG,eAAe,CAAC,MAAM,CAAC,kBAAkB,EAAE,WAAW,CAAC,CAAC;QACzE,aAAa,GAAG,eAAe,CAAC,MAAM,CAAC,iBAAiB,EAAE,UAAU,CAAC,CAAC;QACtE,UAAU,GAAG,oBAAoB,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;QACzD,mBAAmB,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACpI,yBAAyB,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACxJ,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,wBAAwB,EAAE,CAAC;YAC1C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,qCAAqC,CAAC,KAAK,CAAC,EAAE,OAAO,IAAI,CAAC,CAAC;QAClF,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,QAAiB,EAAE,KAAa;IACvD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC;QAAE,OAAO,EAAE,CAAC;IACxC,MAAM,MAAM,GAA0C,EAAE,CAAC;IACzD,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,IAAI,OAAO,CAAC,KAAK,QAAQ;YAAE,SAAS;QACpC,IAAI,CAAC;YACH,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,KAAK,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;QACpE,CAAC;QAAC,OAAO,CAAM,EAAE,CAAC;YAChB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,wBAAwB,EAAE,CAAC;gBAC1C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,sCAAsC,KAAK,KAAK,CAAC,MAAM,CAAC,EAAE,OAAO,IAAI,CAAC,CAAC;YAC9F,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,oBAAoB,CAAC,QAAiB;IAC7C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC;QAAE,OAAO,EAAE,CAAC;IACxC,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,IAAI,OAAO,CAAC,KAAK,QAAQ;YAAE,SAAS;QACpC,IAAI,CAAC;YACH,MAAM,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7B,CAAC;QAAC,OAAO,CAAM,EAAE,CAAC;YAChB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,wBAAwB,EAAE,CAAC;gBAC1C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,0CAA0C,CAAC,MAAM,CAAC,EAAE,OAAO,IAAI,CAAC,CAAC;YACxF,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,oDAAoD;AACpD,MAAM,UAAU,gBAAgB;IAC9B,SAAS,GAAG,KAAK,CAAC;IAClB,WAAW,GAAG,KAAK,CAAC;IACpB,cAAc,GAAG,EAAE,CAAC;IACpB,aAAa,GAAG,EAAE,CAAC;IACnB,UAAU,GAAG,EAAE,CAAC;IAChB,mBAAmB,GAAG,EAAE,CAAC;IACzB,yBAAyB,GAAG,EAAE,CAAC;AACjC,CAAC;AAED,yDAAyD;AACzD,oBAAoB;AACpB,yDAAyD;AAEzD;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,uCAAuC;IACvC,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAEhD,oDAAoD;IACpD,qBAAqB;IACrB,KAAK,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,kBAAkB,EAAE,CAAC;QAChD,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACjB,SAAS,CAAC,WAAW,EAAE,GAAG,MAAM,MAAM,GAAG,EAAE,CAAC,CAAC;YAC7C,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,MAAM,EAAE,EAAE,CAAC;QAC7E,CAAC;IACH,CAAC;IACD,yBAAyB;IACzB,KAAK,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,cAAc,EAAE,CAAC;QAC5C,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACjB,SAAS,CAAC,WAAW,EAAE,GAAG,MAAM,MAAM,GAAG,EAAE,CAAC,CAAC;YAC7C,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,MAAM,EAAE,EAAE,CAAC;QAC7E,CAAC;IACH,CAAC;IAED,0BAA0B;IAC1B,oBAAoB;IACpB,KAAK,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,iBAAiB,EAAE,CAAC;QAC/C,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACjB,wEAAwE;YACxE,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;gBACtC,SAAS,CAAC,MAAM,EAAE,oCAAoC,GAAG,EAAE,CAAC,CAAC;gBAC7D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;YACzC,CAAC;YACD,iCAAiC;YACjC,IAAI,SAAS,EAAE,CAAC;gBACd,SAAS,CAAC,WAAW,EAAE,sBAAsB,MAAM,MAAM,GAAG,EAAE,CAAC,CAAC;gBAChE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,uBAAuB,MAAM,EAAE,EAAE,CAAC;YACxF,CAAC;YACD,SAAS,CAAC,UAAU,EAAE,GAAG,MAAM,MAAM,GAAG,EAAE,CAAC,CAAC;YAC5C,OAAO;gBACL,OAAO,EAAE,IAAI,EAAE,iCAAiC;gBAChD,IAAI,EAAE,UAAU;gBAChB,MAAM;gBACN,MAAM,EAAE,kCAAkC,MAAM,SAAS,OAAO,cAAc;aAC/E,CAAC;QACJ,CAAC;IACH,CAAC;IACD,wBAAwB;IACxB,KAAK,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,aAAa,EAAE,CAAC;QAC3C,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACjB,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;gBACtC,SAAS,CAAC,MAAM,EAAE,oCAAoC,GAAG,EAAE,CAAC,CAAC;gBAC7D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;YACzC,CAAC;YACD,IAAI,SAAS,EAAE,CAAC;gBACd,SAAS,CAAC,WAAW,EAAE,sBAAsB,MAAM,MAAM,GAAG,EAAE,CAAC,CAAC;gBAChE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,uBAAuB,MAAM,EAAE,EAAE,CAAC;YACxF,CAAC;YACD,SAAS,CAAC,UAAU,EAAE,GAAG,MAAM,MAAM,GAAG,EAAE,CAAC,CAAC;YAC5C,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,IAAI,EAAE,UAAU;gBAChB,MAAM;gBACN,MAAM,EAAE,kCAAkC,MAAM,SAAS,OAAO,cAAc;aAC/E,CAAC;QACJ,CAAC;IACH,CAAC;IAED,SAAS,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACvB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;AACzC,CAAC;AAED,yDAAyD;AACzD,+DAA+D;AAC/D,yDAAyD;AAEzD;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAErC,yCAAyC;IACzC,KAAK,MAAM,EAAE,IAAI,eAAe,EAAE,CAAC;QACjC,IAAI,IAAI,KAAK,EAAE,IAAI,IAAI,CAAC,UAAU,CAAC,EAAE,GAAG,GAAG,CAAC,EAAE,CAAC;YAC7C,SAAS,CAAC,WAAW,EAAE,2BAA2B,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;YACjE,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,IAAI,EAAE,WAAW;gBACjB,MAAM,EAAE,oCAAoC,EAAE,EAAE;aACjD,CAAC;QACJ,CAAC;IACH,CAAC;IAED,6CAA6C;IAC7C,KAAK,MAAM,EAAE,IAAI,mBAAmB,EAAE,CAAC;QACrC,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QAClC,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,GAAG,CAAC,EAAE,CAAC;YACrD,SAAS,CAAC,WAAW,EAAE,gCAAgC,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;YACtE,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,IAAI,EAAE,WAAW;gBACjB,MAAM,EAAE,yCAAyC,EAAE,EAAE;aACtD,CAAC;QACJ,CAAC;IACH,CAAC;IAED,+DAA+D;IAC/D,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;IAC7D,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,GAAG,GAAG,CAAC,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClD,gCAAgC;QAChC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAC/D,IAAI,SAAS,EAAE,CAAC;gBACd,SAAS,CAAC,WAAW,EAAE,iCAAiC,IAAI,EAAE,CAAC,CAAC;gBAChE,OAAO;oBACL,OAAO,EAAE,KAAK;oBACd,IAAI,EAAE,WAAW;oBACjB,MAAM,EAAE,qDAAqD,IAAI,EAAE;iBACpE,CAAC;YACJ,CAAC;YACD,SAAS,CAAC,UAAU,EAAE,uBAAuB,IAAI,EAAE,CAAC,CAAC;YACrD,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,IAAI,EAAE,UAAU;gBAChB,MAAM,EAAE,mCAAmC,IAAI,EAAE;gBACjD,MAAM,EAAE,0CAA0C,IAAI,cAAc;aACrE,CAAC;QACJ,CAAC;IACH,CAAC;IAED,SAAS,CAAC,MAAM,EAAE,YAAY,IAAI,EAAE,CAAC,CAAC;IACtC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;AACzC,CAAC;AAED,yDAAyD;AACzD,2BAA2B;AAC3B,yDAAyD;AAEzD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,OAAe,EACf,GAAW,EACX,WAAsB;IAEtB,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAErC,sBAAsB;IACtB,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,GAAG,GAAG,CAAC,IAAI,IAAI,KAAK,GAAG;QAAE,OAAO,IAAI,CAAC;IAE5D,wCAAwC;IACxC,IAAI,WAAW,EAAE,CAAC;QAChB,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;YAC9B,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACnC,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,GAAG,GAAG,CAAC,IAAI,IAAI,KAAK,QAAQ;gBAAE,OAAO,IAAI,CAAC;QACxE,CAAC;IACH,CAAC;IAED,iEAAiE;IACjE,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;IAC7D,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,GAAG,GAAG,CAAC,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAE9D,2CAA2C;IAC3C,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC5C,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;YACtB,oDAAoD;YACpD,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,GAAG,GAAG,GAAG,CAAC,IAAI,QAAQ,KAAK,GAAG,EAAE,CAAC;gBACxD,IAAI,WAAW,EAAE,CAAC;oBAChB,MAAM,SAAS,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;wBACrC,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;wBAC3B,OAAO,QAAQ,CAAC,UAAU,CAAC,EAAE,GAAG,GAAG,CAAC,IAAI,QAAQ,KAAK,EAAE,CAAC;oBAC1D,CAAC,CAAC,CAAC;oBACH,IAAI,SAAS;wBAAE,OAAO,IAAI,CAAC;gBAC7B,CAAC;gBACD,OAAO,mBAAmB,OAAO,gBAAgB,QAAQ,+BAA+B,GAAG,GAAG,CAAC;YACjG,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,4DAA4D;IAC9D,CAAC;IAED,OAAO,mCAAmC,IAAI,kBAAkB,GAAG,EAAE,CAAC;AACxE,CAAC;AAED,yDAAyD;AACzD,UAAU;AACV,yDAAyD;AAEzD;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CAAC,OAAe;IACrD,iCAAiC;IACjC,MAAM,OAAO,GAAG,uBAAuB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACtD,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IAE3B,MAAM,QAAQ,GAAG,CAAC,GAAG,sBAAsB,EAAE,GAAG,yBAAyB,CAAC,CAAC;IAE3E,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;IACvE,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC;QAC/D,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QACzC,wDAAwD;QACxD,IAAI,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;IACnD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,OAAe;IAI7C,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAChD,MAAM,SAAS,GAA+C,EAAE,CAAC;IACjE,MAAM,QAAQ,GAA+C,EAAE,CAAC;IAEhE,KAAK,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,kBAAkB,EAAE,CAAC;QAChD,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,SAAS,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACnE,CAAC;IACD,KAAK,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,iBAAiB,EAAE,CAAC;QAC/C,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC;AACjC,CAAC"}
|