zora-agent 0.9.4 → 0.9.6

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.
Files changed (245) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/README.md +103 -92
  3. package/dist/cli/audit-commands.d.ts.map +1 -1
  4. package/dist/cli/audit-commands.js +3 -1
  5. package/dist/cli/audit-commands.js.map +1 -1
  6. package/dist/cli/daemon.js +86 -28
  7. package/dist/cli/daemon.js.map +1 -1
  8. package/dist/cli/edit-commands.d.ts.map +1 -1
  9. package/dist/cli/edit-commands.js +3 -1
  10. package/dist/cli/edit-commands.js.map +1 -1
  11. package/dist/cli/hook-commands.d.ts +9 -0
  12. package/dist/cli/hook-commands.d.ts.map +1 -0
  13. package/dist/cli/hook-commands.js +106 -0
  14. package/dist/cli/hook-commands.js.map +1 -0
  15. package/dist/cli/index.js +87 -35
  16. package/dist/cli/index.js.map +1 -1
  17. package/dist/cli/init-command.d.ts.map +1 -1
  18. package/dist/cli/init-command.js +108 -9
  19. package/dist/cli/init-command.js.map +1 -1
  20. package/dist/cli/memory-commands.d.ts +1 -1
  21. package/dist/cli/memory-commands.d.ts.map +1 -1
  22. package/dist/cli/memory-commands.js +213 -1
  23. package/dist/cli/memory-commands.js.map +1 -1
  24. package/dist/cli/presets.d.ts.map +1 -1
  25. package/dist/cli/presets.js +2 -1
  26. package/dist/cli/presets.js.map +1 -1
  27. package/dist/cli/skill-commands.d.ts.map +1 -1
  28. package/dist/cli/skill-commands.js +4 -2
  29. package/dist/cli/skill-commands.js.map +1 -1
  30. package/dist/cli/steer-commands.d.ts.map +1 -1
  31. package/dist/cli/steer-commands.js +6 -4
  32. package/dist/cli/steer-commands.js.map +1 -1
  33. package/dist/cli/team-commands.d.ts.map +1 -1
  34. package/dist/cli/team-commands.js +3 -1
  35. package/dist/cli/team-commands.js.map +1 -1
  36. package/dist/config/defaults.d.ts.map +1 -1
  37. package/dist/config/defaults.js +12 -2
  38. package/dist/config/defaults.js.map +1 -1
  39. package/dist/config/loader.d.ts +23 -0
  40. package/dist/config/loader.d.ts.map +1 -1
  41. package/dist/config/loader.js +64 -3
  42. package/dist/config/loader.js.map +1 -1
  43. package/dist/config/policy-loader.d.ts +14 -0
  44. package/dist/config/policy-loader.d.ts.map +1 -1
  45. package/dist/config/policy-loader.js +33 -0
  46. package/dist/config/policy-loader.js.map +1 -1
  47. package/dist/dashboard/frontend/dist/assets/index-BcOGj1EF.css +1 -0
  48. package/dist/dashboard/frontend/dist/assets/index-BtiFO9YN.js +261 -0
  49. package/dist/dashboard/frontend/dist/assets/index-Cfjy5acU.css +1 -0
  50. package/dist/dashboard/frontend/dist/assets/index-D41hcjgc.js +253 -0
  51. package/dist/dashboard/frontend/dist/assets/index-D83BawFd.css +1 -0
  52. package/dist/dashboard/frontend/dist/assets/index-DAODjoxu.css +1 -0
  53. package/dist/dashboard/frontend/dist/assets/index-DB-Eu5oV.js +253 -0
  54. package/dist/dashboard/frontend/dist/assets/index-W0VVEDu6.js +253 -0
  55. package/dist/dashboard/frontend/dist/index.html +17 -0
  56. package/dist/dashboard/server.d.ts +19 -2
  57. package/dist/dashboard/server.d.ts.map +1 -1
  58. package/dist/dashboard/server.js +121 -20
  59. package/dist/dashboard/server.js.map +1 -1
  60. package/dist/hooks/hook-runner.d.ts +55 -0
  61. package/dist/hooks/hook-runner.d.ts.map +1 -0
  62. package/dist/hooks/hook-runner.js +120 -0
  63. package/dist/hooks/hook-runner.js.map +1 -0
  64. package/dist/hooks/hook-types.d.ts +82 -0
  65. package/dist/hooks/hook-types.d.ts.map +1 -0
  66. package/dist/hooks/hook-types.js +20 -0
  67. package/dist/hooks/hook-types.js.map +1 -0
  68. package/dist/hooks/index.d.ts +6 -0
  69. package/dist/hooks/index.d.ts.map +1 -0
  70. package/dist/hooks/index.js +6 -0
  71. package/dist/hooks/index.js.map +1 -0
  72. package/dist/memory/context-compressor.d.ts +108 -0
  73. package/dist/memory/context-compressor.d.ts.map +1 -0
  74. package/dist/memory/context-compressor.js +307 -0
  75. package/dist/memory/context-compressor.js.map +1 -0
  76. package/dist/memory/index.d.ts +1 -0
  77. package/dist/memory/index.d.ts.map +1 -1
  78. package/dist/memory/index.js +1 -0
  79. package/dist/memory/index.js.map +1 -1
  80. package/dist/memory/memory-manager.d.ts +88 -4
  81. package/dist/memory/memory-manager.d.ts.map +1 -1
  82. package/dist/memory/memory-manager.js +299 -7
  83. package/dist/memory/memory-manager.js.map +1 -1
  84. package/dist/memory/observation-store.d.ts +75 -0
  85. package/dist/memory/observation-store.d.ts.map +1 -0
  86. package/dist/memory/observation-store.js +162 -0
  87. package/dist/memory/observation-store.js.map +1 -0
  88. package/dist/memory/observer-worker.d.ts +34 -0
  89. package/dist/memory/observer-worker.d.ts.map +1 -0
  90. package/dist/memory/observer-worker.js +161 -0
  91. package/dist/memory/observer-worker.js.map +1 -0
  92. package/dist/memory/reflector-worker.d.ts +40 -0
  93. package/dist/memory/reflector-worker.d.ts.map +1 -0
  94. package/dist/memory/reflector-worker.js +185 -0
  95. package/dist/memory/reflector-worker.js.map +1 -0
  96. package/dist/memory/salience-scorer.d.ts +16 -6
  97. package/dist/memory/salience-scorer.d.ts.map +1 -1
  98. package/dist/memory/salience-scorer.js +42 -22
  99. package/dist/memory/salience-scorer.js.map +1 -1
  100. package/dist/memory/structured-memory.d.ts +36 -1
  101. package/dist/memory/structured-memory.d.ts.map +1 -1
  102. package/dist/memory/structured-memory.js +207 -8
  103. package/dist/memory/structured-memory.js.map +1 -1
  104. package/dist/memory/token-estimator.d.ts +31 -0
  105. package/dist/memory/token-estimator.d.ts.map +1 -0
  106. package/dist/memory/token-estimator.js +77 -0
  107. package/dist/memory/token-estimator.js.map +1 -0
  108. package/dist/memory/validation-pipeline.d.ts +37 -0
  109. package/dist/memory/validation-pipeline.d.ts.map +1 -0
  110. package/dist/memory/validation-pipeline.js +106 -0
  111. package/dist/memory/validation-pipeline.js.map +1 -0
  112. package/dist/orchestrator/auth-monitor.d.ts.map +1 -1
  113. package/dist/orchestrator/auth-monitor.js +3 -1
  114. package/dist/orchestrator/auth-monitor.js.map +1 -1
  115. package/dist/orchestrator/execution-loop.d.ts +23 -0
  116. package/dist/orchestrator/execution-loop.d.ts.map +1 -1
  117. package/dist/orchestrator/execution-loop.js +60 -19
  118. package/dist/orchestrator/execution-loop.js.map +1 -1
  119. package/dist/orchestrator/failover-controller.d.ts +26 -2
  120. package/dist/orchestrator/failover-controller.d.ts.map +1 -1
  121. package/dist/orchestrator/failover-controller.js +143 -23
  122. package/dist/orchestrator/failover-controller.js.map +1 -1
  123. package/dist/orchestrator/orchestrator.d.ts +70 -7
  124. package/dist/orchestrator/orchestrator.d.ts.map +1 -1
  125. package/dist/orchestrator/orchestrator.js +416 -92
  126. package/dist/orchestrator/orchestrator.js.map +1 -1
  127. package/dist/orchestrator/retry-queue.d.ts.map +1 -1
  128. package/dist/orchestrator/retry-queue.js +24 -9
  129. package/dist/orchestrator/retry-queue.js.map +1 -1
  130. package/dist/orchestrator/router.d.ts +16 -1
  131. package/dist/orchestrator/router.d.ts.map +1 -1
  132. package/dist/orchestrator/router.js +79 -20
  133. package/dist/orchestrator/router.js.map +1 -1
  134. package/dist/orchestrator/session-manager.d.ts +26 -1
  135. package/dist/orchestrator/session-manager.d.ts.map +1 -1
  136. package/dist/orchestrator/session-manager.js +88 -4
  137. package/dist/orchestrator/session-manager.js.map +1 -1
  138. package/dist/providers/circuit-breaker.d.ts +78 -0
  139. package/dist/providers/circuit-breaker.d.ts.map +1 -0
  140. package/dist/providers/circuit-breaker.js +129 -0
  141. package/dist/providers/circuit-breaker.js.map +1 -0
  142. package/dist/providers/claude-provider.d.ts +27 -11
  143. package/dist/providers/claude-provider.d.ts.map +1 -1
  144. package/dist/providers/claude-provider.js +161 -46
  145. package/dist/providers/claude-provider.js.map +1 -1
  146. package/dist/providers/gemini-provider.d.ts +9 -1
  147. package/dist/providers/gemini-provider.d.ts.map +1 -1
  148. package/dist/providers/gemini-provider.js +97 -48
  149. package/dist/providers/gemini-provider.js.map +1 -1
  150. package/dist/providers/index.d.ts +1 -0
  151. package/dist/providers/index.d.ts.map +1 -1
  152. package/dist/providers/index.js +1 -0
  153. package/dist/providers/index.js.map +1 -1
  154. package/dist/providers/ollama-provider.d.ts +7 -0
  155. package/dist/providers/ollama-provider.d.ts.map +1 -1
  156. package/dist/providers/ollama-provider.js +89 -18
  157. package/dist/providers/ollama-provider.js.map +1 -1
  158. package/dist/routines/heartbeat.d.ts +10 -2
  159. package/dist/routines/heartbeat.d.ts.map +1 -1
  160. package/dist/routines/heartbeat.js +42 -5
  161. package/dist/routines/heartbeat.js.map +1 -1
  162. package/dist/routines/routine-manager.d.ts.map +1 -1
  163. package/dist/routines/routine-manager.js +22 -15
  164. package/dist/routines/routine-manager.js.map +1 -1
  165. package/dist/security/audit-logger.d.ts.map +1 -1
  166. package/dist/security/audit-logger.js +5 -7
  167. package/dist/security/audit-logger.js.map +1 -1
  168. package/dist/security/policy-engine.d.ts +28 -17
  169. package/dist/security/policy-engine.d.ts.map +1 -1
  170. package/dist/security/policy-engine.js +42 -185
  171. package/dist/security/policy-engine.js.map +1 -1
  172. package/dist/security/policy-serializer.d.ts +19 -0
  173. package/dist/security/policy-serializer.d.ts.map +1 -0
  174. package/dist/security/policy-serializer.js +100 -0
  175. package/dist/security/policy-serializer.js.map +1 -0
  176. package/dist/security/shell-validator.d.ts +42 -0
  177. package/dist/security/shell-validator.d.ts.map +1 -0
  178. package/dist/security/shell-validator.js +231 -0
  179. package/dist/security/shell-validator.js.map +1 -0
  180. package/dist/skills/index.d.ts +1 -0
  181. package/dist/skills/index.d.ts.map +1 -1
  182. package/dist/skills/index.js +1 -0
  183. package/dist/skills/index.js.map +1 -1
  184. package/dist/skills/skill-loader.d.ts +38 -2
  185. package/dist/skills/skill-loader.d.ts.map +1 -1
  186. package/dist/skills/skill-loader.js +83 -2
  187. package/dist/skills/skill-loader.js.map +1 -1
  188. package/dist/skills/subagent-loader.d.ts +66 -0
  189. package/dist/skills/subagent-loader.d.ts.map +1 -0
  190. package/dist/skills/subagent-loader.js +143 -0
  191. package/dist/skills/subagent-loader.js.map +1 -0
  192. package/dist/steering/flag-manager.d.ts +20 -0
  193. package/dist/steering/flag-manager.d.ts.map +1 -1
  194. package/dist/steering/flag-manager.js +94 -11
  195. package/dist/steering/flag-manager.js.map +1 -1
  196. package/dist/steering/steering-manager.d.ts +11 -0
  197. package/dist/steering/steering-manager.d.ts.map +1 -1
  198. package/dist/steering/steering-manager.js +23 -0
  199. package/dist/steering/steering-manager.js.map +1 -1
  200. package/dist/steering/telegram-gateway.d.ts +4 -1
  201. package/dist/steering/telegram-gateway.d.ts.map +1 -1
  202. package/dist/steering/telegram-gateway.js +49 -10
  203. package/dist/steering/telegram-gateway.js.map +1 -1
  204. package/dist/teams/bridge-watchdog.d.ts.map +1 -1
  205. package/dist/teams/bridge-watchdog.js +5 -3
  206. package/dist/teams/bridge-watchdog.js.map +1 -1
  207. package/dist/teams/gemini-bridge.d.ts.map +1 -1
  208. package/dist/teams/gemini-bridge.js +9 -4
  209. package/dist/teams/gemini-bridge.js.map +1 -1
  210. package/dist/tools/index.d.ts +2 -0
  211. package/dist/tools/index.d.ts.map +1 -1
  212. package/dist/tools/index.js +2 -0
  213. package/dist/tools/index.js.map +1 -1
  214. package/dist/tools/memory-tools.d.ts +16 -0
  215. package/dist/tools/memory-tools.d.ts.map +1 -0
  216. package/dist/tools/memory-tools.js +207 -0
  217. package/dist/tools/memory-tools.js.map +1 -0
  218. package/dist/tools/notifications.d.ts.map +1 -1
  219. package/dist/tools/notifications.js +3 -1
  220. package/dist/tools/notifications.js.map +1 -1
  221. package/dist/tools/tool-factory.d.ts +36 -0
  222. package/dist/tools/tool-factory.d.ts.map +1 -0
  223. package/dist/tools/tool-factory.js +55 -0
  224. package/dist/tools/tool-factory.js.map +1 -0
  225. package/dist/types.d.ts +205 -1
  226. package/dist/types.d.ts.map +1 -1
  227. package/dist/types.js +47 -1
  228. package/dist/types.js.map +1 -1
  229. package/dist/utils/errors.d.ts +21 -0
  230. package/dist/utils/errors.d.ts.map +1 -0
  231. package/dist/utils/errors.js +29 -0
  232. package/dist/utils/errors.js.map +1 -0
  233. package/dist/utils/event-filter.d.ts +25 -0
  234. package/dist/utils/event-filter.d.ts.map +1 -0
  235. package/dist/utils/event-filter.js +61 -0
  236. package/dist/utils/event-filter.js.map +1 -0
  237. package/dist/utils/logger.d.ts +33 -36
  238. package/dist/utils/logger.d.ts.map +1 -1
  239. package/dist/utils/logger.js +60 -130
  240. package/dist/utils/logger.js.map +1 -1
  241. package/dist/utils/validate-job-id.d.ts +6 -0
  242. package/dist/utils/validate-job-id.d.ts.map +1 -0
  243. package/dist/utils/validate-job-id.js +10 -0
  244. package/dist/utils/validate-job-id.js.map +1 -0
  245. package/package.json +12 -3
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Policy serialization and summary utilities.
3
+ *
4
+ * Extracted from PolicyEngine to separate concerns:
5
+ * - Human-readable policy summaries (for system prompt injection)
6
+ * - TOML file serialization (for runtime policy persistence)
7
+ */
8
+ import fs from 'node:fs';
9
+ import { createLogger } from '../utils/logger.js';
10
+ const log = createLogger('policy-serializer');
11
+ /**
12
+ * Returns a short text summary of the current policy for system prompt injection.
13
+ * Intentionally terse to minimize context usage.
14
+ */
15
+ export function getPolicySummary(policy) {
16
+ const fsPolicy = policy.filesystem;
17
+ const sh = policy.shell;
18
+ const lines = [];
19
+ if (fsPolicy.allowed_paths.length === 0) {
20
+ lines.push('Filesystem: LOCKED (no paths allowed)');
21
+ }
22
+ else {
23
+ lines.push(`Filesystem: ${fsPolicy.allowed_paths.join(', ')}`);
24
+ }
25
+ if (fsPolicy.denied_paths.length > 0) {
26
+ lines.push(`Denied: ${fsPolicy.denied_paths.join(', ')}`);
27
+ }
28
+ if (sh.mode === 'deny_all') {
29
+ lines.push('Shell: DISABLED (no commands allowed)');
30
+ }
31
+ else if (sh.mode === 'allowlist') {
32
+ lines.push(`Shell: ${sh.allowed_commands.join(', ')}`);
33
+ }
34
+ else {
35
+ lines.push('Shell: denylist mode');
36
+ }
37
+ if (policy.budget) {
38
+ const b = policy.budget;
39
+ lines.push(`Budget: ${b.max_actions_per_session || 'unlimited'} actions/session, ${b.token_budget || 'unlimited'} tokens`);
40
+ }
41
+ if (policy.dry_run?.enabled) {
42
+ lines.push('Dry Run: ENABLED (write operations will be previewed only)');
43
+ }
44
+ return lines.join('\n');
45
+ }
46
+ /**
47
+ * Writes the policy state to a TOML file.
48
+ * Builds TOML manually for simplicity (avoids needing smol-toml at runtime).
49
+ */
50
+ export function writePolicyFile(policy, filePath) {
51
+ try {
52
+ // Build TOML manually for simplicity (avoids needing smol-toml at runtime here)
53
+ const lines = [
54
+ '# Zora Security Policy — auto-generated (runtime expansion applied)',
55
+ '',
56
+ '[filesystem]',
57
+ `allowed_paths = ${JSON.stringify(policy.filesystem.allowed_paths)}`,
58
+ `denied_paths = ${JSON.stringify(policy.filesystem.denied_paths)}`,
59
+ `resolve_symlinks = ${policy.filesystem.resolve_symlinks}`,
60
+ `follow_symlinks = ${policy.filesystem.follow_symlinks}`,
61
+ '',
62
+ '[shell]',
63
+ `mode = "${policy.shell.mode}"`,
64
+ `allowed_commands = ${JSON.stringify(policy.shell.allowed_commands)}`,
65
+ `denied_commands = ${JSON.stringify(policy.shell.denied_commands)}`,
66
+ `split_chained_commands = ${policy.shell.split_chained_commands}`,
67
+ `max_execution_time = "${policy.shell.max_execution_time}"`,
68
+ '',
69
+ '[actions]',
70
+ `reversible = ${JSON.stringify(policy.actions.reversible)}`,
71
+ `irreversible = ${JSON.stringify(policy.actions.irreversible)}`,
72
+ `always_flag = ${JSON.stringify(policy.actions.always_flag)}`,
73
+ '',
74
+ '[network]',
75
+ `allowed_domains = ${JSON.stringify(policy.network.allowed_domains)}`,
76
+ `denied_domains = ${JSON.stringify(policy.network.denied_domains)}`,
77
+ `max_request_size = "${policy.network.max_request_size}"`,
78
+ '',
79
+ ];
80
+ // Serialize budget section if present
81
+ if (policy.budget) {
82
+ const b = policy.budget;
83
+ lines.push('[budget]', `max_actions_per_session = ${b.max_actions_per_session}`, `token_budget = ${b.token_budget}`, `on_exceed = "${b.on_exceed}"`, '', '[budget.max_actions_per_type]');
84
+ for (const [type, limit] of Object.entries(b.max_actions_per_type)) {
85
+ lines.push(`${type} = ${limit}`);
86
+ }
87
+ lines.push('');
88
+ }
89
+ // Serialize dry_run section if present
90
+ if (policy.dry_run) {
91
+ const dr = policy.dry_run;
92
+ lines.push('[dry_run]', `enabled = ${dr.enabled}`, `tools = ${JSON.stringify(dr.tools)}`, `audit_dry_runs = ${dr.audit_dry_runs}`, '');
93
+ }
94
+ fs.writeFileSync(filePath, lines.join('\n'), 'utf-8');
95
+ }
96
+ catch (err) {
97
+ log.error({ err: err instanceof Error ? err.message : String(err) }, 'Failed to persist policy expansion');
98
+ }
99
+ }
100
+ //# sourceMappingURL=policy-serializer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy-serializer.js","sourceRoot":"","sources":["../../src/security/policy-serializer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Shell command parsing and validation utilities.
3
+ *
4
+ * Pure functions extracted from PolicyEngine for shell tokenization,
5
+ * command splitting, base command extraction, and read-only detection.
6
+ *
7
+ * These are stateless string parsers with no class dependencies.
8
+ */
9
+ /**
10
+ * Tokenize a shell command string into individual arguments.
11
+ *
12
+ * Handles POSIX shell quoting rules:
13
+ * - Double quotes: interprets \\", \\\\, \\$, \\` as escape sequences.
14
+ * - Single quotes: all characters are literal (no escape sequences).
15
+ * - Backslash outside quotes: next character is taken literally.
16
+ * - Whitespace outside quotes: terminates the current token.
17
+ *
18
+ * Returns unquoted token values (quotes and escapes are resolved).
19
+ * Used by validateCommand to extract the base command name, and by
20
+ * _checkCommandPaths to find path-like arguments.
21
+ */
22
+ export declare function shellTokenize(input: string): string[];
23
+ /**
24
+ * Splits command chains on operators (&&, ||, ;, |) while respecting:
25
+ * - Quoted strings (single and double) -- operators inside quotes are literal.
26
+ * - Escape sequences -- backslash-escaped characters are not treated as operators.
27
+ * - Command substitution -- $(...) and backtick blocks are treated as opaque.
28
+ * Nested $() is tracked via parenDepth to avoid premature splitting.
29
+ *
30
+ * Each returned string is a standalone command to validate independently.
31
+ */
32
+ export declare function splitChainedCommands(command: string): string[];
33
+ /**
34
+ * Extracts the base binary name from a command string, respecting quotes
35
+ * and escape sequences.
36
+ */
37
+ export declare function extractBaseCommand(command: string): string;
38
+ /**
39
+ * Determine if a bash command is read-only.
40
+ */
41
+ export declare function isReadOnlyCommand(command: string): boolean;
42
+ //# sourceMappingURL=shell-validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell-validator.d.ts","sourceRoot":"","sources":["../../src/security/shell-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAYH;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAsErD;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAgG9D;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAe1D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAY1D"}
@@ -0,0 +1,231 @@
1
+ /**
2
+ * Shell command parsing and validation utilities.
3
+ *
4
+ * Pure functions extracted from PolicyEngine for shell tokenization,
5
+ * command splitting, base command extraction, and read-only detection.
6
+ *
7
+ * These are stateless string parsers with no class dependencies.
8
+ */
9
+ import path from 'node:path';
10
+ /**
11
+ * Set of commands considered read-only (safe to execute even in dry-run).
12
+ */
13
+ const READ_ONLY_COMMANDS = new Set([
14
+ 'ls', 'cat', 'head', 'tail', 'grep', 'rg', 'find', 'which', 'pwd',
15
+ 'wc', 'diff', 'file', 'stat', 'echo', 'env', 'printenv', 'date', 'whoami',
16
+ ]);
17
+ /**
18
+ * Tokenize a shell command string into individual arguments.
19
+ *
20
+ * Handles POSIX shell quoting rules:
21
+ * - Double quotes: interprets \\", \\\\, \\$, \\` as escape sequences.
22
+ * - Single quotes: all characters are literal (no escape sequences).
23
+ * - Backslash outside quotes: next character is taken literally.
24
+ * - Whitespace outside quotes: terminates the current token.
25
+ *
26
+ * Returns unquoted token values (quotes and escapes are resolved).
27
+ * Used by validateCommand to extract the base command name, and by
28
+ * _checkCommandPaths to find path-like arguments.
29
+ */
30
+ export function shellTokenize(input) {
31
+ const tokens = [];
32
+ let current = '';
33
+ let inToken = false;
34
+ let i = 0;
35
+ const finishToken = () => {
36
+ if (inToken) {
37
+ tokens.push(current);
38
+ current = '';
39
+ inToken = false;
40
+ }
41
+ };
42
+ while (i < input.length) {
43
+ const ch = input[i];
44
+ // Whitespace outside quotes ends the current token
45
+ if (/\s/.test(ch)) {
46
+ finishToken();
47
+ i++;
48
+ continue;
49
+ }
50
+ inToken = true;
51
+ if (ch === '\\' && i + 1 < input.length) {
52
+ // Backslash escape outside quotes: take next char literally
53
+ current += input[i + 1];
54
+ i += 2;
55
+ continue;
56
+ }
57
+ if (ch === '"') {
58
+ // Double-quoted string: handle \", \\, \$, \`
59
+ i++; // skip opening "
60
+ while (i < input.length && input[i] !== '"') {
61
+ if (input[i] === '\\' && i + 1 < input.length) {
62
+ const next = input[i + 1];
63
+ if (next === '"' || next === '\\' || next === '$' || next === '`') {
64
+ current += next;
65
+ i += 2;
66
+ continue;
67
+ }
68
+ }
69
+ current += input[i];
70
+ i++;
71
+ }
72
+ i++; // skip closing "
73
+ continue;
74
+ }
75
+ if (ch === "'") {
76
+ // Single-quoted string: everything is literal, no escape sequences
77
+ i++; // skip opening '
78
+ while (i < input.length && input[i] !== "'") {
79
+ current += input[i];
80
+ i++;
81
+ }
82
+ i++; // skip closing '
83
+ continue;
84
+ }
85
+ // Regular character
86
+ current += ch;
87
+ i++;
88
+ }
89
+ finishToken();
90
+ return tokens;
91
+ }
92
+ /**
93
+ * Splits command chains on operators (&&, ||, ;, |) while respecting:
94
+ * - Quoted strings (single and double) -- operators inside quotes are literal.
95
+ * - Escape sequences -- backslash-escaped characters are not treated as operators.
96
+ * - Command substitution -- $(...) and backtick blocks are treated as opaque.
97
+ * Nested $() is tracked via parenDepth to avoid premature splitting.
98
+ *
99
+ * Each returned string is a standalone command to validate independently.
100
+ */
101
+ export function splitChainedCommands(command) {
102
+ const commands = [];
103
+ let current = '';
104
+ let inQuote = null;
105
+ let parenDepth = 0; // Track $(...) nesting
106
+ let backtickDepth = 0;
107
+ for (let i = 0; i < command.length; i++) {
108
+ const char = command[i];
109
+ const nextChar = command[i + 1];
110
+ // Handle escape sequences
111
+ if (char === '\\' && !inQuote && i + 1 < command.length) {
112
+ current += char + (nextChar ?? '');
113
+ i++;
114
+ continue;
115
+ }
116
+ if (char === '\\' && inQuote === '"' && i + 1 < command.length) {
117
+ const next = nextChar ?? '';
118
+ if (next === '"' || next === '\\' || next === '$' || next === '`') {
119
+ current += char + next;
120
+ i++;
121
+ continue;
122
+ }
123
+ }
124
+ // Track quote state
125
+ if (char === '"' && inQuote !== "'") {
126
+ inQuote = inQuote === '"' ? null : '"';
127
+ current += char;
128
+ continue;
129
+ }
130
+ if (char === "'" && inQuote !== '"') {
131
+ inQuote = inQuote === "'" ? null : "'";
132
+ current += char;
133
+ continue;
134
+ }
135
+ // Track command substitution: $( ... )
136
+ if (!inQuote && char === '$' && nextChar === '(') {
137
+ // Enter command substitution and consume both "$("
138
+ parenDepth++;
139
+ current += '$(';
140
+ i++;
141
+ continue;
142
+ }
143
+ if (!inQuote && parenDepth > 0 && char === '(') {
144
+ // Nested parentheses inside $(...) - increment depth
145
+ parenDepth++;
146
+ current += char;
147
+ continue;
148
+ }
149
+ if (!inQuote && char === ')' && parenDepth > 0) {
150
+ parenDepth--;
151
+ current += char;
152
+ continue;
153
+ }
154
+ // Track backtick command substitution
155
+ if (!inQuote && char === '`') {
156
+ backtickDepth = backtickDepth > 0 ? 0 : 1;
157
+ current += char;
158
+ continue;
159
+ }
160
+ // Only split on operators when not inside quotes or substitutions
161
+ if (!inQuote && parenDepth === 0 && backtickDepth === 0) {
162
+ if (char === ';') {
163
+ if (current.trim())
164
+ commands.push(current.trim());
165
+ current = '';
166
+ continue;
167
+ }
168
+ if (char === '&' && nextChar === '&') {
169
+ if (current.trim())
170
+ commands.push(current.trim());
171
+ current = '';
172
+ i++; // Skip second &
173
+ continue;
174
+ }
175
+ if (char === '|' && nextChar === '|') {
176
+ if (current.trim())
177
+ commands.push(current.trim());
178
+ current = '';
179
+ i++; // Skip second |
180
+ continue;
181
+ }
182
+ if (char === '|') {
183
+ if (current.trim())
184
+ commands.push(current.trim());
185
+ current = '';
186
+ continue;
187
+ }
188
+ }
189
+ current += char;
190
+ }
191
+ if (current.trim())
192
+ commands.push(current.trim());
193
+ return commands;
194
+ }
195
+ /**
196
+ * Extracts the base binary name from a command string, respecting quotes
197
+ * and escape sequences.
198
+ */
199
+ export function extractBaseCommand(command) {
200
+ const tokens = shellTokenize(command.trim());
201
+ if (tokens.length === 0)
202
+ return '';
203
+ // Skip common variable assignments (e.g., "FOO=bar cmd")
204
+ let cmdToken = tokens[0];
205
+ let idx = 0;
206
+ while (idx < tokens.length && /^[A-Za-z_][A-Za-z0-9_]*=/.test(tokens[idx])) {
207
+ idx++;
208
+ }
209
+ if (idx < tokens.length) {
210
+ cmdToken = tokens[idx];
211
+ }
212
+ return path.basename(cmdToken);
213
+ }
214
+ /**
215
+ * Determine if a bash command is read-only.
216
+ */
217
+ export function isReadOnlyCommand(command) {
218
+ const base = extractBaseCommand(command);
219
+ if (READ_ONLY_COMMANDS.has(base))
220
+ return true;
221
+ // git status, git log, git diff are read-only
222
+ if (base === 'git') {
223
+ const parts = command.trim().split(/\s+/);
224
+ const subCommand = parts[1] ?? '';
225
+ if (['status', 'log', 'diff', 'show', 'branch', 'remote', 'tag'].includes(subCommand)) {
226
+ return true;
227
+ }
228
+ }
229
+ return false;
230
+ }
231
+ //# sourceMappingURL=shell-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell-validator.js","sourceRoot":"","sources":["../../src/security/shell-validator.ts"],"names":[],"mappings":"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"}
@@ -2,4 +2,5 @@
2
2
  * Skills barrel exports.
3
3
  */
4
4
  export * from './skill-loader.js';
5
+ export * from './subagent-loader.js';
5
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/skills/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/skills/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC"}
@@ -2,4 +2,5 @@
2
2
  * Skills barrel exports.
3
3
  */
4
4
  export * from './skill-loader.js';
5
+ export * from './subagent-loader.js';
5
6
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/skills/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/skills/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC"}
@@ -1,15 +1,23 @@
1
1
  /**
2
- * SkillLoader — Scans ~/.claude/skills/ for available skills.
2
+ * SkillLoader — Scans skill directories for available skills.
3
3
  *
4
- * Zora v0.6: Skills are .claude/skills/<name>/SKILL.md markdown files.
4
+ * Zora v0.6: Skills are .zora/skills/<name>/SKILL.md markdown files.
5
5
  * The SDK loads and invokes them automatically via settingSources.
6
6
  * This loader provides CLI introspection (list, info).
7
+ *
8
+ * TYPE-09: Three-layer precedence — project > global > built-in.
9
+ * First-match-wins deduplication ensures project skills override global,
10
+ * and global overrides built-in.
7
11
  */
12
+ export type SkillLayer = 'project' | 'global' | 'builtin';
8
13
  export interface SkillInfo {
9
14
  name: string;
10
15
  description: string;
11
16
  path: string;
12
17
  }
18
+ export interface LayeredSkillInfo extends SkillInfo {
19
+ layer: SkillLayer;
20
+ }
13
21
  /**
14
22
  * Extracts a description from SKILL.md YAML frontmatter.
15
23
  */
@@ -22,4 +30,32 @@ export declare function parseSkillFrontmatter(content: string): {
22
30
  * @returns Sorted array of SkillInfo
23
31
  */
24
32
  export declare function loadSkills(skillsDir: string): Promise<SkillInfo[]>;
33
+ /**
34
+ * Returns the default skill layer directories in precedence order.
35
+ * 1. Project — `.zora/skills/` relative to cwd
36
+ * 2. Global — `~/.zora/skills/`
37
+ * 3. Built-in — `skills/` inside the package root
38
+ *
39
+ * @param cwd Override for the current working directory (useful for testing)
40
+ */
41
+ export declare function getSkillLayers(cwd?: string): Array<{
42
+ dir: string;
43
+ layer: SkillLayer;
44
+ }>;
45
+ /**
46
+ * Loads skills from all three precedence layers (project > global > built-in).
47
+ * First-match-wins: if a skill name appears in a higher-precedence layer,
48
+ * the lower-precedence version is excluded.
49
+ *
50
+ * @param options.cwd Override for project directory (defaults to process.cwd())
51
+ * @param options.layers Override the layer directories (useful for testing)
52
+ * @returns Sorted array of LayeredSkillInfo with layer annotation
53
+ */
54
+ export declare function loadSkillsLayered(options?: {
55
+ cwd?: string;
56
+ layers?: Array<{
57
+ dir: string;
58
+ layer: SkillLayer;
59
+ }>;
60
+ }): Promise<LayeredSkillInfo[]>;
25
61
  //# sourceMappingURL=skill-loader.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"skill-loader.d.ts","sourceRoot":"","sources":["../../src/skills/skill-loader.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;CACd;AAID;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,CAe9E;AAID;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CA6BxE"}
1
+ {"version":3,"file":"skill-loader.d.ts","sourceRoot":"","sources":["../../src/skills/skill-loader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAQH,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE1D,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,gBAAiB,SAAQ,SAAS;IACjD,KAAK,EAAE,UAAU,CAAC;CACnB;AAID;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,CAe9E;AAID;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CA6BxE;AAID;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,UAAU,CAAA;CAAE,CAAC,CAUtF;AAqCD;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,CAAC,EAAE;IAChD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,UAAU,CAAA;KAAE,CAAC,CAAC;CACpD,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAgB9B"}
@@ -1,12 +1,17 @@
1
1
  /**
2
- * SkillLoader — Scans ~/.claude/skills/ for available skills.
2
+ * SkillLoader — Scans skill directories for available skills.
3
3
  *
4
- * Zora v0.6: Skills are .claude/skills/<name>/SKILL.md markdown files.
4
+ * Zora v0.6: Skills are .zora/skills/<name>/SKILL.md markdown files.
5
5
  * The SDK loads and invokes them automatically via settingSources.
6
6
  * This loader provides CLI introspection (list, info).
7
+ *
8
+ * TYPE-09: Three-layer precedence — project > global > built-in.
9
+ * First-match-wins deduplication ensures project skills override global,
10
+ * and global overrides built-in.
7
11
  */
8
12
  import fs from 'node:fs/promises';
9
13
  import path from 'node:path';
14
+ import os from 'node:os';
10
15
  // ─── Frontmatter Parser ─────────────────────────────────────────────
11
16
  /**
12
17
  * Extracts a description from SKILL.md YAML frontmatter.
@@ -61,4 +66,80 @@ export async function loadSkills(skillsDir) {
61
66
  }
62
67
  return skills.sort((a, b) => a.name.localeCompare(b.name));
63
68
  }
69
+ // ─── Three-Layer Skill Precedence (TYPE-09) ─────────────────────────
70
+ /**
71
+ * Returns the default skill layer directories in precedence order.
72
+ * 1. Project — `.zora/skills/` relative to cwd
73
+ * 2. Global — `~/.zora/skills/`
74
+ * 3. Built-in — `skills/` inside the package root
75
+ *
76
+ * @param cwd Override for the current working directory (useful for testing)
77
+ */
78
+ export function getSkillLayers(cwd) {
79
+ const projectDir = path.join(cwd ?? process.cwd(), '.zora', 'skills');
80
+ const globalDir = path.join(os.homedir(), '.zora', 'skills');
81
+ const builtinDir = path.resolve(path.join(path.dirname(import.meta.url.replace('file://', '')), '..', 'skills'));
82
+ return [
83
+ { dir: projectDir, layer: 'project' },
84
+ { dir: globalDir, layer: 'global' },
85
+ { dir: builtinDir, layer: 'builtin' },
86
+ ];
87
+ }
88
+ /**
89
+ * Scans a single skills directory and returns LayeredSkillInfo entries.
90
+ */
91
+ async function scanSkillLayer(skillsDir, layer) {
92
+ const skills = [];
93
+ let dirs;
94
+ try {
95
+ dirs = await fs.readdir(skillsDir);
96
+ }
97
+ catch {
98
+ return skills; // Directory doesn't exist
99
+ }
100
+ for (const dir of dirs) {
101
+ const skillPath = path.join(skillsDir, dir, 'SKILL.md');
102
+ try {
103
+ const stat = await fs.stat(path.join(skillsDir, dir));
104
+ if (!stat.isDirectory())
105
+ continue;
106
+ const content = await fs.readFile(skillPath, 'utf-8');
107
+ const { description } = parseSkillFrontmatter(content);
108
+ skills.push({
109
+ name: dir,
110
+ description: description || `Skill: ${dir}`,
111
+ path: skillPath,
112
+ layer,
113
+ });
114
+ }
115
+ catch {
116
+ // Skip directories without SKILL.md
117
+ }
118
+ }
119
+ return skills;
120
+ }
121
+ /**
122
+ * Loads skills from all three precedence layers (project > global > built-in).
123
+ * First-match-wins: if a skill name appears in a higher-precedence layer,
124
+ * the lower-precedence version is excluded.
125
+ *
126
+ * @param options.cwd Override for project directory (defaults to process.cwd())
127
+ * @param options.layers Override the layer directories (useful for testing)
128
+ * @returns Sorted array of LayeredSkillInfo with layer annotation
129
+ */
130
+ export async function loadSkillsLayered(options) {
131
+ const layers = options?.layers ?? getSkillLayers(options?.cwd);
132
+ const seen = new Set();
133
+ const result = [];
134
+ for (const { dir, layer } of layers) {
135
+ const skills = await scanSkillLayer(dir, layer);
136
+ for (const skill of skills) {
137
+ if (!seen.has(skill.name)) {
138
+ seen.add(skill.name);
139
+ result.push(skill);
140
+ }
141
+ }
142
+ }
143
+ return result.sort((a, b) => a.name.localeCompare(b.name));
144
+ }
64
145
  //# sourceMappingURL=skill-loader.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"skill-loader.js","sourceRoot":"","sources":["../../src/skills/skill-loader.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAU7B,uEAAuE;AAEvE;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAAe;IACnD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;IACrD,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC;IAEvC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,CAAC,CAAE,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;YACjB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC;YAC3C,IAAI,GAAG,KAAK,aAAa,EAAE,CAAC;gBAC1B,OAAO,EAAE,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;YAC1D,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC;AAC7B,CAAC;AAED,uEAAuE;AAEvE;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,SAAiB;IAChD,MAAM,MAAM,GAAgB,EAAE,CAAC;IAE/B,IAAI,IAAc,CAAC;IACnB,IAAI,CAAC;QACH,IAAI,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,MAAM,CAAC,CAAC,0BAA0B;IAC3C,CAAC;IAED,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;QACxD,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC;YACtD,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE;gBAAE,SAAS;YAElC,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YACtD,MAAM,EAAE,WAAW,EAAE,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;YACvD,MAAM,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,GAAG;gBACT,WAAW,EAAE,WAAW,IAAI,UAAU,GAAG,EAAE;gBAC3C,IAAI,EAAE,SAAS;aAChB,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,oCAAoC;QACtC,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAC7D,CAAC"}
1
+ {"version":3,"file":"skill-loader.js","sourceRoot":"","sources":["../../src/skills/skill-loader.ts"],"names":[],"mappings":"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"}