crow-central-agency 0.26.13 → 0.26.15

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 (67) hide show
  1. package/dist/_shared/auto-approve/auto-approve-rule-set.js +30 -0
  2. package/dist/_shared/auto-approve/auto-approve-rule.types.js +2 -0
  3. package/dist/_shared/auto-approve/command-decomposition.js +238 -0
  4. package/dist/_shared/auto-approve/rule-format.js +79 -0
  5. package/dist/_shared/auto-approve/rule-strategies.js +72 -0
  6. package/dist/_shared/auto-approve/rule-strategy-registry.js +7 -0
  7. package/dist/_shared/index.js +6 -1
  8. package/dist/_shared/schemas/websocket.schema.js +20 -12
  9. package/dist/bootstrap.js +2 -0
  10. package/dist/feed/feed-search-index.js +211 -0
  11. package/dist/feed/feed-search-index.types.js +2 -0
  12. package/dist/feed/simply-feed-manager.js +92 -58
  13. package/dist/mcp/agents/invoke-agent.js +10 -7
  14. package/dist/mcp/tasks/get-task-result.js +4 -3
  15. package/dist/mcp/tasks/get-task.js +1 -1
  16. package/dist/mcp/tasks/tasks-mcp-server-utils.js +25 -26
  17. package/dist/mcp/tasks/tasks-mcp-server.js +1 -1
  18. package/dist/public/assets/{architectureDiagram-3BPJPVTR-Bt4tuNX8.js → architectureDiagram-3BPJPVTR-Dc2HHLfZ.js} +1 -1
  19. package/dist/public/assets/{blockDiagram-GPEHLZMM-B8TiZHkt.js → blockDiagram-GPEHLZMM-DXGYsvdc.js} +1 -1
  20. package/dist/public/assets/{c4Diagram-AAUBKEIU-C7EL8BgS.js → c4Diagram-AAUBKEIU-ztTqSRMY.js} +1 -1
  21. package/dist/public/assets/{chunk-3OPIFGDE-MQSAwWWp.js → chunk-3OPIFGDE-Bxujc1Rt.js} +1 -1
  22. package/dist/public/assets/chunk-5ZQYHXKU-BjSbc4aL.js +2 -0
  23. package/dist/public/assets/{chunk-727SXJPM-BjjXmWC5.js → chunk-727SXJPM-0bRbHW5O.js} +1 -1
  24. package/dist/public/assets/{chunk-AQP2D5EJ-DjJ_-SOd.js → chunk-AQP2D5EJ-DaeOiJU5.js} +1 -1
  25. package/dist/public/assets/{chunk-L5ZTLDWV-qldrlPBQ.js → chunk-L5ZTLDWV-DB34dWa1.js} +1 -1
  26. package/dist/public/assets/{chunk-O5CBEL6O-IrQhDPxX.js → chunk-O5CBEL6O-DX0VXF6r.js} +1 -1
  27. package/dist/public/assets/classDiagram-4FO5ZUOK-C9lygaqs.js +1 -0
  28. package/dist/public/assets/classDiagram-v2-Q7XG4LA2-C9lygaqs.js +1 -0
  29. package/dist/public/assets/{dagre-BM42HDAG-CZBf8H9_.js → dagre-BM42HDAG-DqVKySqC.js} +1 -1
  30. package/dist/public/assets/{diagram-2AECGRRQ-C_U6a4go.js → diagram-2AECGRRQ-CVUv7XJt.js} +1 -1
  31. package/dist/public/assets/{diagram-5GNKFQAL-Bk-3tHvA.js → diagram-5GNKFQAL-CT4Y1CVA.js} +1 -1
  32. package/dist/public/assets/{diagram-KO2AKTUF-l-G_fXJx.js → diagram-KO2AKTUF-Bw_mRWA5.js} +1 -1
  33. package/dist/public/assets/{diagram-LMA3HP47-JxZtWEor.js → diagram-LMA3HP47-Dztpjf4g.js} +1 -1
  34. package/dist/public/assets/{diagram-OG6HWLK6-BJ1F3Sxu.js → diagram-OG6HWLK6-DV_q-OZa.js} +1 -1
  35. package/dist/public/assets/{erDiagram-TEJ5UH35-BJBHxTf8.js → erDiagram-TEJ5UH35-mPcGMeKH.js} +1 -1
  36. package/dist/public/assets/{flowDiagram-I6XJVG4X-DJ3nm5z7.js → flowDiagram-I6XJVG4X-DmxQZdeo.js} +1 -1
  37. package/dist/public/assets/{ganttDiagram-6RSMTGT7-DcrRy6MU.js → ganttDiagram-6RSMTGT7-CQRvJhaK.js} +1 -1
  38. package/dist/public/assets/{gitGraphDiagram-PVQCEYII-C2wZyHYx.js → gitGraphDiagram-PVQCEYII-DWInzrI1.js} +1 -1
  39. package/dist/public/assets/index-CP4ovXTR.css +1 -0
  40. package/dist/public/assets/index-DFUlHQ5X.js +506 -0
  41. package/dist/public/assets/{infoDiagram-5YYISTIA-Cc1k7k1c.js → infoDiagram-5YYISTIA-CpsxcJxm.js} +1 -1
  42. package/dist/public/assets/{ishikawaDiagram-YF4QCWOH-DrDraHBD.js → ishikawaDiagram-YF4QCWOH-QmavmNDi.js} +1 -1
  43. package/dist/public/assets/{kanban-definition-UN3LZRKU-CNUMfAVC.js → kanban-definition-UN3LZRKU-BuuL7oE9.js} +1 -1
  44. package/dist/public/assets/{line-kwTiCfuG.js → line-TBAqc70M.js} +1 -1
  45. package/dist/public/assets/{mindmap-definition-RKZ34NQL-DOeL-Iu4.js → mindmap-definition-RKZ34NQL-DBeaQV46.js} +1 -1
  46. package/dist/public/assets/{pieDiagram-4H26LBE5-DCP9wuZK.js → pieDiagram-4H26LBE5-BSsLa7YW.js} +1 -1
  47. package/dist/public/assets/{requirementDiagram-4Y6WPE33-7UzZpq-C.js → requirementDiagram-4Y6WPE33-Dh16xOM7.js} +1 -1
  48. package/dist/public/assets/{sequenceDiagram-3UESZ5HK-D5alEu9E.js → sequenceDiagram-3UESZ5HK-BGoVAFFE.js} +1 -1
  49. package/dist/public/assets/{stateDiagram-AJRCARHV-EkSeb-RA.js → stateDiagram-AJRCARHV-B8WOoix_.js} +1 -1
  50. package/dist/public/assets/stateDiagram-v2-BHNVJYJU-CpeZMh5R.js +1 -0
  51. package/dist/public/assets/{timeline-definition-PNZ67QCA-B4oLmMT1.js → timeline-definition-PNZ67QCA-2JpHUZHd.js} +1 -1
  52. package/dist/public/assets/{vennDiagram-CIIHVFJN-DgiGQ7rE.js → vennDiagram-CIIHVFJN-ByGRIXN1.js} +1 -1
  53. package/dist/public/assets/{wardleyDiagram-YWT4CUSO-dDWLWZoc.js → wardleyDiagram-YWT4CUSO-BorZAZSf.js} +1 -1
  54. package/dist/public/assets/{xychartDiagram-2RQKCTM6-TOELm0t1.js → xychartDiagram-2RQKCTM6-BPQY7Tb7.js} +1 -1
  55. package/dist/public/index.html +7 -7
  56. package/dist/routines/inter-agent-task-routine.js +8 -11
  57. package/dist/runner/claude-code-agent-runner.js +18 -10
  58. package/dist/runner/github-copilot-agent-runner.js +21 -23
  59. package/dist/services/agent-registry.js +15 -5
  60. package/dist/services/runtime/agent-runtime-manager.js +2 -2
  61. package/package.json +7 -4
  62. package/dist/public/assets/chunk-5ZQYHXKU-DjjMoQy4.js +0 -2
  63. package/dist/public/assets/classDiagram-4FO5ZUOK-DVPqtO0x.js +0 -1
  64. package/dist/public/assets/classDiagram-v2-Q7XG4LA2-DVPqtO0x.js +0 -1
  65. package/dist/public/assets/index-BJmLehUe.js +0 -505
  66. package/dist/public/assets/index-BqakLGSS.css +0 -1
  67. package/dist/public/assets/stateDiagram-v2-BHNVJYJU-DmpUDd8s.js +0 -1
@@ -0,0 +1,30 @@
1
+ import { parseRule } from "./rule-format.js";
2
+ import { getRuleStrategy } from "./rule-strategy-registry.js";
3
+ /**
4
+ * A mutable set of auto-approve rule strings that parses each rule once and caches the result, so
5
+ * permission checks match against the pre-parsed rules instead of re-parsing the whole list per call.
6
+ * Raw strings are deduped; malformed rules are dropped on add (same as `parseRules`).
7
+ */
8
+ export class AutoApproveRuleSet {
9
+ raw = new Set();
10
+ parsed = [];
11
+ constructor(initialRules = []) {
12
+ this.add(initialRules);
13
+ }
14
+ add(rules) {
15
+ for (const rule of rules) {
16
+ if (this.raw.has(rule)) {
17
+ continue;
18
+ }
19
+ this.raw.add(rule);
20
+ const parsedRule = parseRule(rule);
21
+ if (parsedRule !== undefined) {
22
+ this.parsed.push(parsedRule);
23
+ }
24
+ }
25
+ }
26
+ matches(toolName, input) {
27
+ return getRuleStrategy(toolName).matches(toolName, input, this.parsed);
28
+ }
29
+ }
30
+ //# sourceMappingURL=auto-approve-rule-set.js.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=auto-approve-rule.types.js.map
@@ -0,0 +1,238 @@
1
+ import { matchesSpecifier, WORD_BOUNDARY_SUFFIX } from "./rule-format.js";
2
+ /** Prefix depth for derived rules (first N tokens of a subcommand). */
3
+ export const DEFAULT_PREFIX_DEPTH = 2;
4
+ /** Maximum number of rules derived from a single compound command, mirroring the SDK cap. */
5
+ export const MAX_DERIVED_RULES = 5;
6
+ /**
7
+ * Shell separators that decompose a compound command. Two-character separators are matched before
8
+ * the single-character ones so `&&`/`||`/`|&` win over `&`/`|`.
9
+ */
10
+ export const TWO_CHAR_SEPARATORS = ["&&", "||", "|&"];
11
+ export const SINGLE_CHAR_SEPARATORS = [";", "|", "&", "\n", "\r"];
12
+ /**
13
+ * Process wrappers stripped from the front of a subcommand before matching. `timeout`/`nice` also
14
+ * consume a leading numeric argument (duration / priority).
15
+ */
16
+ export const PROCESS_WRAPPERS = new Set(["timeout", "time", "nice", "nohup", "stdbuf"]);
17
+ const WRAPPERS_WITH_NUMERIC_ARG = new Set(["timeout", "nice"]);
18
+ const XARGS_WRAPPER = "xargs";
19
+ /**
20
+ * Read-only shell builtins that run with no prompt. `cd` and `git` are handled separately
21
+ * (in-cwd `cd` only; read-only `git` subcommands only).
22
+ */
23
+ export const READ_ONLY_BUILTINS = new Set([
24
+ "ls",
25
+ "cat",
26
+ "echo",
27
+ "pwd",
28
+ "head",
29
+ "tail",
30
+ "grep",
31
+ "find",
32
+ "wc",
33
+ "which",
34
+ "diff",
35
+ "stat",
36
+ "du",
37
+ ]);
38
+ const CD_COMMAND = "cd";
39
+ const IN_CWD_CD_ARGS = new Set([".", "./"]);
40
+ const GIT_COMMAND = "git";
41
+ const READ_ONLY_GIT_SUBCOMMANDS = new Set(["status", "log", "diff", "show"]);
42
+ const SINGLE_QUOTE = "'";
43
+ const DOUBLE_QUOTE = '"';
44
+ const REDIRECT_CHAR = ">";
45
+ /** Split a command string into whitespace-delimited tokens, respecting single/double quotes. */
46
+ function tokenize(command) {
47
+ const tokens = [];
48
+ let current = "";
49
+ let hasToken = false;
50
+ let quote;
51
+ for (const char of command) {
52
+ if (quote !== undefined) {
53
+ if (char === quote) {
54
+ quote = undefined;
55
+ }
56
+ else {
57
+ current += char;
58
+ }
59
+ continue;
60
+ }
61
+ if (char === SINGLE_QUOTE || char === DOUBLE_QUOTE) {
62
+ quote = char;
63
+ hasToken = true;
64
+ continue;
65
+ }
66
+ if (char === " " || char === "\t") {
67
+ if (hasToken) {
68
+ tokens.push(current);
69
+ current = "";
70
+ hasToken = false;
71
+ }
72
+ continue;
73
+ }
74
+ current += char;
75
+ hasToken = true;
76
+ }
77
+ if (hasToken) {
78
+ tokens.push(current);
79
+ }
80
+ return tokens;
81
+ }
82
+ /** Return the shell separator starting at `index`, or `undefined` if none. */
83
+ function separatorAt(command, index) {
84
+ const twoChar = command.slice(index, index + 2);
85
+ for (const separator of TWO_CHAR_SEPARATORS) {
86
+ if (twoChar === separator) {
87
+ return separator;
88
+ }
89
+ }
90
+ const char = command[index];
91
+ if (char === "&") {
92
+ // Guard shell redirects (`2>&1`, `&>file`) from being read as a background separator.
93
+ if (command[index - 1] === REDIRECT_CHAR || command[index + 1] === REDIRECT_CHAR) {
94
+ return undefined;
95
+ }
96
+ }
97
+ for (const separator of SINGLE_CHAR_SEPARATORS) {
98
+ if (char === separator) {
99
+ return separator;
100
+ }
101
+ }
102
+ return undefined;
103
+ }
104
+ /** Strip leading process wrappers (and their option/numeric args) from a token list. */
105
+ function stripWrappers(tokens) {
106
+ let remaining = tokens;
107
+ while (remaining.length > 0) {
108
+ const head = remaining[0];
109
+ if (head === XARGS_WRAPPER) {
110
+ // Only bare `xargs` (no flags) is transparent; flagged xargs stays and simply won't match.
111
+ const next = remaining[1];
112
+ if (next !== undefined && next.startsWith("-")) {
113
+ break;
114
+ }
115
+ remaining = remaining.slice(1);
116
+ continue;
117
+ }
118
+ if (!PROCESS_WRAPPERS.has(head)) {
119
+ break;
120
+ }
121
+ remaining = remaining.slice(1);
122
+ while (remaining.length > 0 && remaining[0].startsWith("-")) {
123
+ remaining = remaining.slice(1);
124
+ }
125
+ if (WRAPPERS_WITH_NUMERIC_ARG.has(head) && remaining.length > 0 && /^[0-9]/.test(remaining[0])) {
126
+ remaining = remaining.slice(1);
127
+ }
128
+ }
129
+ return remaining;
130
+ }
131
+ /**
132
+ * Split a compound command into its normalized subcommands. Splits on shell separators outside
133
+ * quotes, strips process wrappers, and drops empty segments. The returned strings are re-joined
134
+ * from parsed tokens (quotes removed, whitespace collapsed) for stable matching.
135
+ */
136
+ export function splitSubcommands(command) {
137
+ const rawSegments = [];
138
+ let current = "";
139
+ let quote;
140
+ let index = 0;
141
+ while (index < command.length) {
142
+ const char = command[index];
143
+ if (quote !== undefined) {
144
+ current += char;
145
+ if (char === quote) {
146
+ quote = undefined;
147
+ }
148
+ index += 1;
149
+ continue;
150
+ }
151
+ if (char === SINGLE_QUOTE || char === DOUBLE_QUOTE) {
152
+ quote = char;
153
+ current += char;
154
+ index += 1;
155
+ continue;
156
+ }
157
+ const separator = separatorAt(command, index);
158
+ if (separator !== undefined) {
159
+ rawSegments.push(current);
160
+ current = "";
161
+ index += separator.length;
162
+ continue;
163
+ }
164
+ current += char;
165
+ index += 1;
166
+ }
167
+ rawSegments.push(current);
168
+ const subcommands = [];
169
+ for (const segment of rawSegments) {
170
+ const tokens = stripWrappers(tokenize(segment));
171
+ if (tokens.length > 0) {
172
+ subcommands.push(tokens.join(" "));
173
+ }
174
+ }
175
+ return subcommands;
176
+ }
177
+ /** Whether a normalized subcommand is a read-only builtin, in-cwd `cd`, or read-only `git`. */
178
+ export function isReadOnlyCommand(subcommand) {
179
+ const tokens = tokenize(subcommand);
180
+ const head = tokens[0];
181
+ if (head === undefined) {
182
+ return false;
183
+ }
184
+ if (head === CD_COMMAND) {
185
+ const target = tokens[1];
186
+ return target === undefined || IN_CWD_CD_ARGS.has(target);
187
+ }
188
+ if (head === GIT_COMMAND) {
189
+ const gitSubcommand = tokens[1];
190
+ return gitSubcommand !== undefined && READ_ONLY_GIT_SUBCOMMANDS.has(gitSubcommand);
191
+ }
192
+ return READ_ONLY_BUILTINS.has(head);
193
+ }
194
+ /**
195
+ * Capture side: derive one prefix-`depth` specifier per non-read-only subcommand (in-cwd `cd` and
196
+ * read-only builtins contribute nothing), deduped and capped at {@link MAX_DERIVED_RULES}.
197
+ */
198
+ export function deriveRules(command, depth = DEFAULT_PREFIX_DEPTH) {
199
+ const specifiers = [];
200
+ for (const subcommand of splitSubcommands(command)) {
201
+ if (specifiers.length >= MAX_DERIVED_RULES) {
202
+ break;
203
+ }
204
+ if (isReadOnlyCommand(subcommand)) {
205
+ continue;
206
+ }
207
+ const tokens = tokenize(subcommand);
208
+ if (tokens.length === 0) {
209
+ continue;
210
+ }
211
+ const prefix = tokens.slice(0, depth).join(" ");
212
+ const specifier = `${prefix}${WORD_BOUNDARY_SUFFIX}`;
213
+ if (!specifiers.includes(specifier)) {
214
+ specifiers.push(specifier);
215
+ }
216
+ }
217
+ return specifiers;
218
+ }
219
+ /**
220
+ * Match side: fails closed. Every subcommand must be a read-only builtin or match one of the
221
+ * specifiers. Empty/unparseable input yields `false`.
222
+ */
223
+ export function matchesRules(command, specifiers) {
224
+ const subcommands = splitSubcommands(command);
225
+ if (subcommands.length === 0) {
226
+ return false;
227
+ }
228
+ for (const subcommand of subcommands) {
229
+ if (isReadOnlyCommand(subcommand)) {
230
+ continue;
231
+ }
232
+ if (!specifiers.some((specifier) => matchesSpecifier(subcommand, specifier))) {
233
+ return false;
234
+ }
235
+ }
236
+ return true;
237
+ }
238
+ //# sourceMappingURL=command-decomposition.js.map
@@ -0,0 +1,79 @@
1
+ /** Glob wildcard used in rule specifiers. */
2
+ export const GLOB_STAR = "*";
3
+ /**
4
+ * A space before a trailing `*` enforces a word boundary: `ls *` matches `ls` and `ls -la`,
5
+ * but never `lsof`.
6
+ */
7
+ export const WORD_BOUNDARY_SUFFIX = " *";
8
+ /** Claude's `:*` prefix suffix, treated as equivalent to a trailing ` *`. */
9
+ export const PREFIX_STAR_SUFFIX = ":*";
10
+ const RULE_PATTERN = /^([^()]+)(?:\((.*)\))?$/;
11
+ const REGEXP_SPECIAL_CHARS = /[.+?^${}()|[\]\\]/g;
12
+ /**
13
+ * Parse a rule string into its tool + optional specifier. Fails closed: any malformed rule
14
+ * (unbalanced parentheses, empty tool, stray `(` in the tool name) yields `undefined`.
15
+ */
16
+ export function parseRule(rule) {
17
+ const trimmed = rule.trim();
18
+ if (trimmed.length === 0) {
19
+ return undefined;
20
+ }
21
+ const match = RULE_PATTERN.exec(trimmed);
22
+ if (!match) {
23
+ return undefined;
24
+ }
25
+ const tool = match[1];
26
+ const specifier = match[2]?.trim();
27
+ if (tool.length === 0) {
28
+ return undefined;
29
+ }
30
+ return specifier === undefined ? { tool } : { tool, specifier };
31
+ }
32
+ /** Parse a list of rule strings, discarding any that fail to parse. */
33
+ export function parseRules(rules) {
34
+ const parsed = [];
35
+ for (const rule of rules) {
36
+ const result = parseRule(rule);
37
+ if (result !== undefined) {
38
+ parsed.push(result);
39
+ }
40
+ }
41
+ return parsed;
42
+ }
43
+ /** Format a parsed rule back into its canonical string form. */
44
+ export function formatRule(rule) {
45
+ return rule.specifier === undefined ? rule.tool : `${rule.tool}(${rule.specifier})`;
46
+ }
47
+ /** Normalize Claude's `:*` prefix suffix into the equivalent word-boundary ` *` form. */
48
+ function normalizeSpecifier(specifier) {
49
+ if (specifier.endsWith(PREFIX_STAR_SUFFIX)) {
50
+ return `${specifier.slice(0, -PREFIX_STAR_SUFFIX.length)}${WORD_BOUNDARY_SUFFIX}`;
51
+ }
52
+ return specifier;
53
+ }
54
+ function globToRegExp(pattern) {
55
+ const source = pattern
56
+ .split(GLOB_STAR)
57
+ .map((segment) => segment.replace(REGEXP_SPECIAL_CHARS, "\\$&"))
58
+ .join(".*");
59
+ return new RegExp(`^${source}$`);
60
+ }
61
+ /**
62
+ * Whether a single command/value matches a rule specifier under glob semantics. A specifier
63
+ * ending in a word-boundary ` *` (or `:*`) matches the exact prefix or the prefix followed by a
64
+ * space; any other `*` is a general wildcard. No wildcard means an exact match.
65
+ */
66
+ export function matchesSpecifier(value, specifier) {
67
+ const normalized = normalizeSpecifier(specifier);
68
+ if (normalized.endsWith(WORD_BOUNDARY_SUFFIX)) {
69
+ const base = normalized.slice(0, -WORD_BOUNDARY_SUFFIX.length);
70
+ if (!base.includes(GLOB_STAR)) {
71
+ return value === base || value.startsWith(`${base} `);
72
+ }
73
+ }
74
+ if (normalized.includes(GLOB_STAR)) {
75
+ return globToRegExp(normalized).test(value);
76
+ }
77
+ return value === normalized;
78
+ }
79
+ //# sourceMappingURL=rule-format.js.map
@@ -0,0 +1,72 @@
1
+ import { CLAUDE_CODE_TOOL } from "../schemas/agent.schema.js";
2
+ import { deriveRules as deriveCommandRules, matchesRules as matchesCommandRules } from "./command-decomposition.js";
3
+ import { formatRule, GLOB_STAR } from "./rule-format.js";
4
+ /** Input field carrying the shell command for Bash/PowerShell tools. */
5
+ const COMMAND_INPUT_KEY = "command";
6
+ /**
7
+ * Command-scoped tools, compared case-insensitively to cover Claude (`Bash`, `PowerShell`) and
8
+ * GitHub Copilot (`bash`, `powershell`).
9
+ */
10
+ const COMMAND_TOOL_BASE_NAMES = new Set([
11
+ CLAUDE_CODE_TOOL.BASH.toLowerCase(),
12
+ CLAUDE_CODE_TOOL.POWER_SHELL.toLowerCase(),
13
+ ]);
14
+ /**
15
+ * Whole-tool matching, preserving the legacy `isToolAutoApproved` behavior: exact tool-name match,
16
+ * plus a trailing `*` (including a bare `*` and MCP prefixes like `mcp__crow-artifacts__*`) as a
17
+ * prefix match.
18
+ */
19
+ function wholeToolMatches(toolName, rules) {
20
+ for (const rule of rules) {
21
+ if (rule.specifier !== undefined) {
22
+ continue;
23
+ }
24
+ const pattern = rule.tool;
25
+ if (pattern === toolName) {
26
+ return true;
27
+ }
28
+ if (pattern.endsWith(GLOB_STAR) && toolName.startsWith(pattern.slice(0, -GLOB_STAR.length))) {
29
+ return true;
30
+ }
31
+ }
32
+ return false;
33
+ }
34
+ function extractCommand(input) {
35
+ const command = input[COMMAND_INPUT_KEY];
36
+ return typeof command === "string" ? command : undefined;
37
+ }
38
+ /** Default strategy: today's whole-tool behavior, used for any tool without a specialization. */
39
+ export const defaultRuleStrategy = {
40
+ appliesTo: () => true,
41
+ deriveRules: (toolName) => [toolName],
42
+ matches: (toolName, _input, rules) => wholeToolMatches(toolName, rules),
43
+ };
44
+ /** Command strategy: Bash/PowerShell decomposition on top of the whole-tool behavior. */
45
+ export const commandRuleStrategy = {
46
+ appliesTo: (toolName) => COMMAND_TOOL_BASE_NAMES.has(toolName.toLowerCase()),
47
+ deriveRules: (toolName, input) => {
48
+ const command = extractCommand(input);
49
+ if (command === undefined) {
50
+ return [];
51
+ }
52
+ return deriveCommandRules(command).map((specifier) => formatRule({ tool: toolName, specifier }));
53
+ },
54
+ matches: (toolName, input, rules) => {
55
+ if (wholeToolMatches(toolName, rules)) {
56
+ return true;
57
+ }
58
+ const command = extractCommand(input);
59
+ if (command === undefined) {
60
+ return false;
61
+ }
62
+ const targetTool = toolName.toLowerCase();
63
+ const specifiers = [];
64
+ for (const rule of rules) {
65
+ if (rule.specifier !== undefined && rule.tool.toLowerCase() === targetTool) {
66
+ specifiers.push(rule.specifier);
67
+ }
68
+ }
69
+ return matchesCommandRules(command, specifiers);
70
+ },
71
+ };
72
+ //# sourceMappingURL=rule-strategies.js.map
@@ -0,0 +1,7 @@
1
+ import { commandRuleStrategy, defaultRuleStrategy } from "./rule-strategies.js";
2
+ const REGISTERED_STRATEGIES = [commandRuleStrategy];
3
+ /** Resolve the auto-approve strategy for a tool, falling back to the default whole-tool strategy. */
4
+ export function getRuleStrategy(toolName) {
5
+ return REGISTERED_STRATEGIES.find((strategy) => strategy.appliesTo(toolName)) ?? defaultRuleStrategy;
6
+ }
7
+ //# sourceMappingURL=rule-strategy-registry.js.map
@@ -2,7 +2,7 @@ export { CLAUDE_MODELS, GITHUB_COPILOT_MODELS, CLAUDE_CODE_MODEL_OPTIONS, ModelO
2
2
  export { SchedulerTimeSchema, DAY_OF_WEEK, DayOfWeekSchema, TimeModeSchema, TIME_MODE, } from "./schemas/scheduler.schema.js";
3
3
  export { createApiSuccessSchema, ApiErrorSchema, } from "./schemas/api-response.schema.js";
4
4
  export { SessionUsageSchema, PendingPermissionInfoSchema, PendingInstructionReminderSchema, AgentRuntimeStateSchema, AgentActivitySchema, AGENT_ACTIVITY_TYPE, AGENT_STATUS, MAX_INPUT_HISTORY, } from "./schemas/agent-runtime-state.schema.js";
5
- export { ClientMessageSchema, ServerMessageSchema, SendMessageSchema, InjectMessageSchema, PermissionResponseWsSchema, CommandMessageSchema, AgentTextWsMessageSchema, AgentActivityWsMessageSchema, AgentResultWsMessageSchema, AgentStatusWsMessageSchema, AgentCreatedWsMessageSchema, AgentUpdatedWsMessageSchema, AgentDeletedWsMessageSchema, AgentUsageWsMessageSchema, PermissionRequestWsMessageSchema, PermissionCancelledWsMessageSchema, ErrorWsMessageSchema, AgentMessageWsMessageSchema, AgentToolProgressWsMessageSchema, TaskAddedWsMessageSchema, TaskUpdatedWsMessageSchema, TaskAssignedWsMessageSchema, TaskStateChangedWsMessageSchema, TaskDeletedWsMessageSchema, CircleCreatedWsMessageSchema, CircleUpdatedWsMessageSchema, CircleDeletedWsMessageSchema, RelationshipCreatedWsMessageSchema, RelationshipDeletedWsMessageSchema, AgentBuilderDraftUpdatedWsMessageSchema, isAgentServerMessage, CLIENT_MESSAGE_TYPE, SERVER_MESSAGE_TYPE, } from "./schemas/websocket.schema.js";
5
+ export { ClientMessageSchema, ServerMessageSchema, SendMessageSchema, InjectMessageSchema, PermissionResponseWsSchema, CommandMessageSchema, AgentTextWsMessageSchema, AgentActivityWsMessageSchema, AgentResultWsMessageSchema, AgentStatusWsMessageSchema, AgentCreatedWsMessageSchema, AgentUpdatedWsMessageSchema, AgentDeletedWsMessageSchema, AgentUsageWsMessageSchema, PermissionRequestWsMessageSchema, PermissionCancelledWsMessageSchema, ErrorWsMessageSchema, AgentMessageWsMessageSchema, AgentToolProgressWsMessageSchema, TaskAddedWsMessageSchema, TaskUpdatedWsMessageSchema, TaskAssignedWsMessageSchema, TaskStateChangedWsMessageSchema, TaskDeletedWsMessageSchema, CircleCreatedWsMessageSchema, CircleUpdatedWsMessageSchema, CircleDeletedWsMessageSchema, RelationshipCreatedWsMessageSchema, RelationshipDeletedWsMessageSchema, AgentBuilderDraftUpdatedWsMessageSchema, isAgentServerMessage, isAgentLifecycleServerMessage, CLIENT_MESSAGE_TYPE, SERVER_MESSAGE_TYPE, } from "./schemas/websocket.schema.js";
6
6
  export { PERMISSION_DECISION, PermissionRequestSchema, PermissionResponseSchema, } from "./schemas/permission.schema.js";
7
7
  export { AgentMessageSchema, MessageAnnotationSchema, AGENT_MESSAGE_ROLE, AGENT_MESSAGE_TYPE, } from "./schemas/agent-message.schema.js";
8
8
  export { ARTIFACT_TYPE, ARTIFACT_CONTENT_TYPE, ArtifactTypeSchema, ArtifactContentTypeSchema, ArtifactMetadataSchema, ArtifactUpdateSchema, } from "./schemas/artifact.schema.js";
@@ -24,4 +24,9 @@ export { MESSAGE_SOURCE_TYPE, MessageSourceSchema, } from "./schemas/message-sou
24
24
  export { AGENT_COMMAND, AgentCommandSchema } from "./schemas/agent-command.schema.js";
25
25
  export { GraphNodeSchema, GraphEdgeSchema, GraphDataSchema, } from "./schemas/graph.schema.js";
26
26
  export { ConnectorConnectionSchema, ConnectorInfoSchema, ConnectConnectorResponseSchema, } from "./schemas/connector.schema.js";
27
+ export { parseRule, parseRules, formatRule, matchesSpecifier, GLOB_STAR, WORD_BOUNDARY_SUFFIX, PREFIX_STAR_SUFFIX, } from "./auto-approve/rule-format.js";
28
+ export { splitSubcommands, deriveRules, matchesRules, isReadOnlyCommand, DEFAULT_PREFIX_DEPTH, MAX_DERIVED_RULES, READ_ONLY_BUILTINS, PROCESS_WRAPPERS, } from "./auto-approve/command-decomposition.js";
29
+ export { defaultRuleStrategy, commandRuleStrategy } from "./auto-approve/rule-strategies.js";
30
+ export { getRuleStrategy } from "./auto-approve/rule-strategy-registry.js";
31
+ export { AutoApproveRuleSet } from "./auto-approve/auto-approve-rule-set.js";
27
32
  //# sourceMappingURL=index.js.map
@@ -47,7 +47,7 @@ export const SERVER_MESSAGE_TYPE = {
47
47
  AGENT_BUILDER_DRAFT_UPDATED: "agent_builder_draft_updated",
48
48
  };
49
49
  export const SendMessageSchema = z.object({
50
- type: z.literal("send_message"),
50
+ type: z.literal(CLIENT_MESSAGE_TYPE.SEND_MESSAGE),
51
51
  agentId: z.string(),
52
52
  message: z.string(),
53
53
  });
@@ -57,7 +57,7 @@ export const InjectMessageSchema = z.object({
57
57
  message: z.string(),
58
58
  });
59
59
  export const PermissionResponseWsSchema = z.object({
60
- type: z.literal("permission_response"),
60
+ type: z.literal(CLIENT_MESSAGE_TYPE.PERMISSION_RESPONSE),
61
61
  agentId: z.string(),
62
62
  toolUseId: z.string(),
63
63
  decision: z.enum([PERMISSION_DECISION.ALLOW, PERMISSION_DECISION.DENY, PERMISSION_DECISION.ALLOW_ALWAYS]),
@@ -76,24 +76,24 @@ export const ClientMessageSchema = z.discriminatedUnion("type", [
76
76
  CommandMessageSchema,
77
77
  ]);
78
78
  export const AgentTextWsMessageSchema = z.object({
79
- type: z.literal("agent_text"),
79
+ type: z.literal(SERVER_MESSAGE_TYPE.AGENT_TEXT),
80
80
  agentId: z.string(),
81
81
  text: z.string(),
82
82
  });
83
83
  export const AgentActivityWsMessageSchema = z.object({
84
- type: z.literal("agent_activity"),
84
+ type: z.literal(SERVER_MESSAGE_TYPE.AGENT_ACTIVITY),
85
85
  agentId: z.string(),
86
86
  agentActivity: AgentActivitySchema,
87
87
  });
88
88
  export const AgentResultWsMessageSchema = z.object({
89
- type: z.literal("agent_result"),
89
+ type: z.literal(SERVER_MESSAGE_TYPE.AGENT_RESULT),
90
90
  agentId: z.string(),
91
91
  subtype: z.string(),
92
92
  totalCostUsd: z.number().optional(),
93
93
  durationMs: z.number().optional(),
94
94
  });
95
95
  export const AgentStatusWsMessageSchema = z.object({
96
- type: z.literal("agent_status"),
96
+ type: z.literal(SERVER_MESSAGE_TYPE.AGENT_STATUS),
97
97
  agentId: z.string(),
98
98
  status: z.enum([AGENT_STATUS.IDLE, AGENT_STATUS.ACTIVATING, AGENT_STATUS.STREAMING, AGENT_STATUS.COMPACTING]),
99
99
  messageSource: MessageSourceSchema.optional(),
@@ -113,7 +113,7 @@ export const AgentDeletedWsMessageSchema = z.object({
113
113
  agentId: z.string(),
114
114
  });
115
115
  export const AgentUsageWsMessageSchema = z.object({
116
- type: z.literal("agent_usage"),
116
+ type: z.literal(SERVER_MESSAGE_TYPE.AGENT_USAGE),
117
117
  agentId: z.string(),
118
118
  inputTokens: z.number(),
119
119
  outputTokens: z.number(),
@@ -122,7 +122,7 @@ export const AgentUsageWsMessageSchema = z.object({
122
122
  contextTotal: z.number(),
123
123
  });
124
124
  export const PermissionRequestWsMessageSchema = z.object({
125
- type: z.literal("permission_request"),
125
+ type: z.literal(SERVER_MESSAGE_TYPE.PERMISSION_REQUEST),
126
126
  agentId: z.string(),
127
127
  toolUseId: z.string(),
128
128
  toolName: z.string(),
@@ -130,23 +130,23 @@ export const PermissionRequestWsMessageSchema = z.object({
130
130
  decisionReason: z.string().optional(),
131
131
  });
132
132
  export const PermissionCancelledWsMessageSchema = z.object({
133
- type: z.literal("permission_cancelled"),
133
+ type: z.literal(SERVER_MESSAGE_TYPE.PERMISSION_CANCELLED),
134
134
  agentId: z.string(),
135
135
  toolUseId: z.string(),
136
136
  });
137
137
  export const ErrorWsMessageSchema = z.object({
138
- type: z.literal("error"),
138
+ type: z.literal(SERVER_MESSAGE_TYPE.ERROR),
139
139
  agentId: z.string().optional(),
140
140
  code: z.string(),
141
141
  message: z.string(),
142
142
  });
143
143
  export const AgentMessageWsMessageSchema = z.object({
144
- type: z.literal("agent_message"),
144
+ type: z.literal(SERVER_MESSAGE_TYPE.AGENT_MESSAGE),
145
145
  agentId: z.string(),
146
146
  message: AgentMessageSchema,
147
147
  });
148
148
  export const AgentToolProgressWsMessageSchema = z.object({
149
- type: z.literal("agent_tool_progress"),
149
+ type: z.literal(SERVER_MESSAGE_TYPE.AGENT_TOOL_PROGRESS),
150
150
  agentId: z.string(),
151
151
  toolName: z.string(),
152
152
  elapsedTimeSeconds: z.number(),
@@ -227,4 +227,12 @@ export const ServerMessageSchema = z.discriminatedUnion("type", [
227
227
  export function isAgentServerMessage(message) {
228
228
  return "agentId" in message && typeof message.agentId === "string";
229
229
  }
230
+ const AGENT_LIFECYCLE_MESSAGE_TYPES = new Set([
231
+ SERVER_MESSAGE_TYPE.AGENT_CREATED,
232
+ SERVER_MESSAGE_TYPE.AGENT_UPDATED,
233
+ SERVER_MESSAGE_TYPE.AGENT_DELETED,
234
+ ]);
235
+ export function isAgentLifecycleServerMessage(message) {
236
+ return AGENT_LIFECYCLE_MESSAGE_TYPES.has(message.type);
237
+ }
230
238
  //# sourceMappingURL=websocket.schema.js.map
package/dist/bootstrap.js CHANGED
@@ -91,6 +91,7 @@ export async function bootstrap(options) {
91
91
  const taskManager = new AgentTaskManager(storeProvider, broadcaster, circleManager);
92
92
  await taskManager.initialize();
93
93
  const feedManager = new SimplyFeedManager(storeProvider, folderFileProvider, crowScheduler);
94
+ await feedManager.initialize();
94
95
  const artifactManager = new ArtifactManager(storeProvider, registry, circleManager);
95
96
  await artifactManager.initialize();
96
97
  const documentSearchService = new DocumentSearchService(artifactManager, taskManager, registry, circleManager);
@@ -175,6 +176,7 @@ export async function bootstrap(options) {
175
176
  const shutdown = async () => {
176
177
  logger.info("Shutting down...");
177
178
  crowScheduler.stop();
179
+ await feedManager.dispose();
178
180
  await discordBotManager.destroy();
179
181
  await server.close();
180
182
  await copilotClientManager.dispose();