crow-central-agency 0.26.15 → 0.27.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.
Files changed (97) hide show
  1. package/README.md +1 -0
  2. package/dist/_shared/auto-approve/auto-approve-rule-set.js +3 -2
  3. package/dist/_shared/auto-approve/command-decomposition.js +47 -63
  4. package/dist/_shared/auto-approve/rule-strategies.js +10 -8
  5. package/dist/_shared/constants/system-agent.js +1 -0
  6. package/dist/_shared/index.js +7 -4
  7. package/dist/_shared/schemas/agent-circle.schema.js +12 -3
  8. package/dist/_shared/schemas/agent-runtime-state.schema.js +1 -1
  9. package/dist/_shared/schemas/artifact.schema.js +4 -2
  10. package/dist/_shared/schemas/fragment-reflection.schema.js +62 -0
  11. package/dist/_shared/schemas/fragment.schema.js +47 -0
  12. package/dist/_shared/schemas/graph.schema.js +3 -1
  13. package/dist/_shared/schemas/websocket.schema.js +18 -0
  14. package/dist/_shared/utils/mcp-utils.js +4 -0
  15. package/dist/agents/crow-fragment-reflection-agent.js +98 -0
  16. package/dist/bootstrap.js +22 -5
  17. package/dist/config/env.js +1 -0
  18. package/dist/core/error/app-error.types.js +1 -0
  19. package/dist/feed/simply-feed-manager.js +1 -2
  20. package/dist/mcp/agents/agents-mcp-server.js +4 -4
  21. package/dist/mcp/agents/search-workspace.js +25 -8
  22. package/dist/mcp/artifacts/artifacts-mcp-server.js +7 -2
  23. package/dist/mcp/audio/audio-mcp-server.js +7 -2
  24. package/dist/mcp/crow-mcp-manager.js +2 -5
  25. package/dist/mcp/fragments/active-domain-signal.js +8 -0
  26. package/dist/mcp/fragments/fragment-tool-utils.js +12 -0
  27. package/dist/mcp/fragments/fragments-mcp-server.js +28 -0
  28. package/dist/mcp/fragments/fragments-reflection-mcp-server.js +21 -0
  29. package/dist/mcp/fragments/link-fragment.js +82 -0
  30. package/dist/mcp/fragments/read-fragment.js +43 -0
  31. package/dist/mcp/fragments/search-fragment.js +51 -0
  32. package/dist/mcp/fragments/unlink-fragment.js +53 -0
  33. package/dist/mcp/fragments/update-fragment.js +52 -0
  34. package/dist/mcp/fragments/write-fragment.js +45 -0
  35. package/dist/mcp/reminders/reminders-mcp-server.js +7 -2
  36. package/dist/mcp/tasks/tasks-mcp-server.js +2 -2
  37. package/dist/public/assets/{architectureDiagram-3BPJPVTR-Dc2HHLfZ.js → architectureDiagram-3BPJPVTR-BqWT9ZDQ.js} +1 -1
  38. package/dist/public/assets/{chunk-727SXJPM-0bRbHW5O.js → chunk-727SXJPM-BA3qHD_x.js} +1 -1
  39. package/dist/public/assets/{chunk-AQP2D5EJ-DaeOiJU5.js → chunk-AQP2D5EJ-zdvb5fBV.js} +1 -1
  40. package/dist/public/assets/{classDiagram-v2-Q7XG4LA2-C9lygaqs.js → classDiagram-4FO5ZUOK-Dyg2jQFl.js} +1 -1
  41. package/dist/public/assets/{classDiagram-4FO5ZUOK-C9lygaqs.js → classDiagram-v2-Q7XG4LA2-Dyg2jQFl.js} +1 -1
  42. package/dist/public/assets/{dagre-BM42HDAG-DqVKySqC.js → dagre-BM42HDAG-BSetBJNw.js} +1 -1
  43. package/dist/public/assets/{diagram-2AECGRRQ-CVUv7XJt.js → diagram-2AECGRRQ-CAayLeKt.js} +1 -1
  44. package/dist/public/assets/{diagram-5GNKFQAL-CT4Y1CVA.js → diagram-5GNKFQAL-CyMCIpgc.js} +1 -1
  45. package/dist/public/assets/{diagram-LMA3HP47-Dztpjf4g.js → diagram-LMA3HP47-C9X8CzJj.js} +1 -1
  46. package/dist/public/assets/{diagram-OG6HWLK6-DV_q-OZa.js → diagram-OG6HWLK6-aAQDv7jZ.js} +1 -1
  47. package/dist/public/assets/{erDiagram-TEJ5UH35-mPcGMeKH.js → erDiagram-TEJ5UH35-DvzOycvc.js} +1 -1
  48. package/dist/public/assets/{flowDiagram-I6XJVG4X-DmxQZdeo.js → flowDiagram-I6XJVG4X-COh-Jf3n.js} +1 -1
  49. package/dist/public/assets/index-DeT_l7Tr.js +506 -0
  50. package/dist/public/assets/index-TfuJyPCv.css +1 -0
  51. package/dist/public/assets/{infoDiagram-5YYISTIA-CpsxcJxm.js → infoDiagram-5YYISTIA-C7dnExPQ.js} +1 -1
  52. package/dist/public/assets/{ishikawaDiagram-YF4QCWOH-QmavmNDi.js → ishikawaDiagram-YF4QCWOH-BNDwVLSI.js} +1 -1
  53. package/dist/public/assets/{kanban-definition-UN3LZRKU-BuuL7oE9.js → kanban-definition-UN3LZRKU-N6dBIbQn.js} +1 -1
  54. package/dist/public/assets/{mindmap-definition-RKZ34NQL-DBeaQV46.js → mindmap-definition-RKZ34NQL-BwMnbpAX.js} +1 -1
  55. package/dist/public/assets/{pieDiagram-4H26LBE5-BSsLa7YW.js → pieDiagram-4H26LBE5-Bs1pmEhy.js} +1 -1
  56. package/dist/public/assets/{requirementDiagram-4Y6WPE33-Dh16xOM7.js → requirementDiagram-4Y6WPE33-D_pMqObd.js} +1 -1
  57. package/dist/public/assets/{sequenceDiagram-3UESZ5HK-BGoVAFFE.js → sequenceDiagram-3UESZ5HK-Cpex4RrS.js} +1 -1
  58. package/dist/public/assets/{stateDiagram-AJRCARHV-B8WOoix_.js → stateDiagram-AJRCARHV-CwISO1OR.js} +1 -1
  59. package/dist/public/assets/{stateDiagram-v2-BHNVJYJU-CpeZMh5R.js → stateDiagram-v2-BHNVJYJU-aBNfmqp6.js} +1 -1
  60. package/dist/public/assets/{timeline-definition-PNZ67QCA-2JpHUZHd.js → timeline-definition-PNZ67QCA-Dh6-30fC.js} +1 -1
  61. package/dist/public/assets/{vennDiagram-CIIHVFJN-ByGRIXN1.js → vennDiagram-CIIHVFJN-D3E2_3uF.js} +1 -1
  62. package/dist/public/assets/{wardleyDiagram-YWT4CUSO-BorZAZSf.js → wardleyDiagram-YWT4CUSO-Dm73fHqt.js} +1 -1
  63. package/dist/public/assets/{xychartDiagram-2RQKCTM6-BPQY7Tb7.js → xychartDiagram-2RQKCTM6-BaSUapDJ.js} +1 -1
  64. package/dist/public/index.html +2 -2
  65. package/dist/routes/agent.routes.js +1 -0
  66. package/dist/routes/circle.routes.js +9 -1
  67. package/dist/routes/fragment.routes.js +40 -0
  68. package/dist/routes/graph.routes.js +10 -3
  69. package/dist/routines/fragment-reflection-routine.js +109 -0
  70. package/dist/runner/agent-runner-factory.js +3 -3
  71. package/dist/runner/agent-runner.js +58 -6
  72. package/dist/runner/claude-code-agent-runner.js +3 -2
  73. package/dist/runner/github-copilot-agent-runner.js +46 -23
  74. package/dist/runner/github-copilot-permission.js +50 -0
  75. package/dist/server/error-handler.js +1 -0
  76. package/dist/services/agent-circle-manager.js +30 -93
  77. package/dist/services/agent-registry.js +3 -1
  78. package/dist/services/fragment/fragment-cue-renderer.js +49 -0
  79. package/dist/services/fragment/fragment-manager.js +536 -0
  80. package/dist/services/fragment/fragment-manager.types.js +2 -0
  81. package/dist/services/fragment/fragment-reflection-applier.js +102 -0
  82. package/dist/services/fragment/fragment-reflection-prompts.js +77 -0
  83. package/dist/services/fragment/fragment-reflection-state-store.js +21 -0
  84. package/dist/services/fragment/fragment-reflection.constants.js +8 -0
  85. package/dist/services/relationship-manager.js +140 -0
  86. package/dist/services/relationship-manager.types.js +2 -0
  87. package/dist/services/runtime/agent-runtime-manager.js +38 -3
  88. package/dist/services/search/document-search-service.js +28 -5
  89. package/dist/services/search/document-search-service.types.js +1 -0
  90. package/dist/services/world-builder/world-builder-service.js +4 -3
  91. package/dist/utils/extract-marked.js +31 -0
  92. package/dist/utils/id-utils.js +2 -1
  93. package/dist/utils/logger.js +2 -2
  94. package/package.json +1 -1
  95. package/dist/public/assets/index-CP4ovXTR.css +0 -1
  96. package/dist/public/assets/index-DFUlHQ5X.js +0 -506
  97. package/dist/services/world-builder/extract-marked.js +0 -31
package/README.md CHANGED
@@ -95,6 +95,7 @@ See `.env.example` for the full list, including:
95
95
  - `HOST` / `PORT` — server bind address (defaults: `localhost:3101`). Keep `HOST=localhost` and front the server with a secure tunnel for remote access rather than binding to `0.0.0.0`.
96
96
  - `CORS_ORIGINS` — only needed when the frontend is served from a different origin (e.g. during frontend dev). Single-box deployments can leave it unset.
97
97
  - `LOG_LEVEL` — log verbosity (defaults to `debug` in development, `info` otherwise).
98
+ - `LOG_PRETTY` — force human-readable, colorized logs (pino-pretty) even in production. Enabled automatically in development.
98
99
  - `CROW_SYSTEM_PATH` — directory for Crow's file-based storage. Defaults to `~/.crow`.
99
100
  - `CROW_SYSTEM_AGENT_NAME` — display name for the built-in Crow system agent (default: `Crow`).
100
101
  - `CROW_SYSTEM_AGENT_PROVIDER` — provider backing the built-in system agents: `claude` or `copilot` (default: `claude`). Forced to `claude` when `DISABLE_GITHUB_COPILOT` is set.
@@ -1,3 +1,4 @@
1
+ import { SUBCOMMAND_MATCH_MODE } from "./command-decomposition.js";
1
2
  import { parseRule } from "./rule-format.js";
2
3
  import { getRuleStrategy } from "./rule-strategy-registry.js";
3
4
  /**
@@ -23,8 +24,8 @@ export class AutoApproveRuleSet {
23
24
  }
24
25
  }
25
26
  }
26
- matches(toolName, input) {
27
- return getRuleStrategy(toolName).matches(toolName, input, this.parsed);
27
+ matches(toolName, input, mode = SUBCOMMAND_MATCH_MODE.ALL) {
28
+ return getRuleStrategy(toolName).matches(toolName, input, this.parsed, mode);
28
29
  }
29
30
  }
30
31
  //# sourceMappingURL=auto-approve-rule-set.js.map
@@ -1,6 +1,14 @@
1
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;
2
+ /** Number of non-flag tokens a derived prefix keeps before wildcarding the rest. */
3
+ export const DEFAULT_PREFIX_DEPTH = 3;
4
+ /**
5
+ * How a compound command aggregates per-subcommand matches. `ALL` (approve) requires every
6
+ * subcommand to match a specifier; `ANY` (deny) fires when a single subcommand matches.
7
+ */
8
+ export const SUBCOMMAND_MATCH_MODE = {
9
+ ALL: "all",
10
+ ANY: "any",
11
+ };
4
12
  /** Maximum number of rules derived from a single compound command, mirroring the SDK cap. */
5
13
  export const MAX_DERIVED_RULES = 5;
6
14
  /**
@@ -16,29 +24,7 @@ export const SINGLE_CHAR_SEPARATORS = [";", "|", "&", "\n", "\r"];
16
24
  export const PROCESS_WRAPPERS = new Set(["timeout", "time", "nice", "nohup", "stdbuf"]);
17
25
  const WRAPPERS_WITH_NUMERIC_ARG = new Set(["timeout", "nice"]);
18
26
  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"]);
27
+ const OPTION_PREFIX = "-";
42
28
  const SINGLE_QUOTE = "'";
43
29
  const DOUBLE_QUOTE = '"';
44
30
  const REDIRECT_CHAR = ">";
@@ -109,7 +95,7 @@ function stripWrappers(tokens) {
109
95
  if (head === XARGS_WRAPPER) {
110
96
  // Only bare `xargs` (no flags) is transparent; flagged xargs stays and simply won't match.
111
97
  const next = remaining[1];
112
- if (next !== undefined && next.startsWith("-")) {
98
+ if (next !== undefined && next.startsWith(OPTION_PREFIX)) {
113
99
  break;
114
100
  }
115
101
  remaining = remaining.slice(1);
@@ -119,7 +105,7 @@ function stripWrappers(tokens) {
119
105
  break;
120
106
  }
121
107
  remaining = remaining.slice(1);
122
- while (remaining.length > 0 && remaining[0].startsWith("-")) {
108
+ while (remaining.length > 0 && remaining[0].startsWith(OPTION_PREFIX)) {
123
109
  remaining = remaining.slice(1);
124
110
  }
125
111
  if (WRAPPERS_WITH_NUMERIC_ARG.has(head) && remaining.length > 0 && /^[0-9]/.test(remaining[0])) {
@@ -174,26 +160,31 @@ export function splitSubcommands(command) {
174
160
  }
175
161
  return subcommands;
176
162
  }
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);
163
+ function derivePrefixTokens(tokens, depth) {
164
+ const prefix = [];
165
+ let counted = 0;
166
+ let index = 0;
167
+ while (index < tokens.length && counted < depth) {
168
+ const token = tokens[index];
169
+ if (token.startsWith(OPTION_PREFIX)) {
170
+ prefix.push(token);
171
+ index += 1;
172
+ if (index < tokens.length && !tokens[index].startsWith(OPTION_PREFIX)) {
173
+ prefix.push(tokens[index]);
174
+ index += 1;
175
+ }
176
+ continue;
177
+ }
178
+ prefix.push(token);
179
+ counted += 1;
180
+ index += 1;
191
181
  }
192
- return READ_ONLY_BUILTINS.has(head);
182
+ return counted === 0 ? undefined : prefix;
193
183
  }
194
184
  /**
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}.
185
+ * Capture side: derive one flag-aware prefix specifier per subcommand, deduped and capped at
186
+ * {@link MAX_DERIVED_RULES}. A subcommand with no non-flag token (e.g. a lone `--flag`) contributes
187
+ * nothing. User config is the only auto-approve authority — there is no read-only skip.
197
188
  */
198
189
  export function deriveRules(command, depth = DEFAULT_PREFIX_DEPTH) {
199
190
  const specifiers = [];
@@ -201,15 +192,11 @@ export function deriveRules(command, depth = DEFAULT_PREFIX_DEPTH) {
201
192
  if (specifiers.length >= MAX_DERIVED_RULES) {
202
193
  break;
203
194
  }
204
- if (isReadOnlyCommand(subcommand)) {
205
- continue;
206
- }
207
- const tokens = tokenize(subcommand);
208
- if (tokens.length === 0) {
195
+ const prefixTokens = derivePrefixTokens(tokenize(subcommand), depth);
196
+ if (prefixTokens === undefined) {
209
197
  continue;
210
198
  }
211
- const prefix = tokens.slice(0, depth).join(" ");
212
- const specifier = `${prefix}${WORD_BOUNDARY_SUFFIX}`;
199
+ const specifier = `${prefixTokens.join(" ")}${WORD_BOUNDARY_SUFFIX}`;
213
200
  if (!specifiers.includes(specifier)) {
214
201
  specifiers.push(specifier);
215
202
  }
@@ -217,22 +204,19 @@ export function deriveRules(command, depth = DEFAULT_PREFIX_DEPTH) {
217
204
  return specifiers;
218
205
  }
219
206
  /**
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`.
207
+ * Match side: fails closed. Each raw subcommand is matched against the specifiers via literal-prefix
208
+ * `matchesSpecifier` (no flag logic on this side). `ALL` (approve) requires every subcommand to
209
+ * match; `ANY` (deny) fires when a single subcommand matches. Empty/unparseable input yields `false`
210
+ * in both modes.
222
211
  */
223
- export function matchesRules(command, specifiers) {
212
+ export function matchesRules(command, specifiers, mode = SUBCOMMAND_MATCH_MODE.ALL) {
224
213
  const subcommands = splitSubcommands(command);
225
214
  if (subcommands.length === 0) {
226
215
  return false;
227
216
  }
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;
217
+ const subcommandMatches = (subcommand) => specifiers.some((specifier) => matchesSpecifier(subcommand, specifier));
218
+ return mode === SUBCOMMAND_MATCH_MODE.ANY
219
+ ? subcommands.some(subcommandMatches)
220
+ : subcommands.every(subcommandMatches);
237
221
  }
238
222
  //# sourceMappingURL=command-decomposition.js.map
@@ -12,20 +12,22 @@ const COMMAND_TOOL_BASE_NAMES = new Set([
12
12
  CLAUDE_CODE_TOOL.POWER_SHELL.toLowerCase(),
13
13
  ]);
14
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.
15
+ * Whole-tool matching: case-insensitive exact tool-name match, plus a trailing `*` (including a bare
16
+ * `*` and MCP prefixes like `mcp__crow-artifacts__*`) as a prefix match. Case-insensitivity aligns
17
+ * with the command strategy (which lowercases the tool name) so a `Bash` rule covers Copilot's
18
+ * `bash`, for both allow and deny.
18
19
  */
19
20
  function wholeToolMatches(toolName, rules) {
21
+ const targetTool = toolName.toLowerCase();
20
22
  for (const rule of rules) {
21
23
  if (rule.specifier !== undefined) {
22
24
  continue;
23
25
  }
24
- const pattern = rule.tool;
25
- if (pattern === toolName) {
26
+ const pattern = rule.tool.toLowerCase();
27
+ if (pattern === targetTool) {
26
28
  return true;
27
29
  }
28
- if (pattern.endsWith(GLOB_STAR) && toolName.startsWith(pattern.slice(0, -GLOB_STAR.length))) {
30
+ if (pattern.endsWith(GLOB_STAR) && targetTool.startsWith(pattern.slice(0, -GLOB_STAR.length))) {
29
31
  return true;
30
32
  }
31
33
  }
@@ -51,7 +53,7 @@ export const commandRuleStrategy = {
51
53
  }
52
54
  return deriveCommandRules(command).map((specifier) => formatRule({ tool: toolName, specifier }));
53
55
  },
54
- matches: (toolName, input, rules) => {
56
+ matches: (toolName, input, rules, mode) => {
55
57
  if (wholeToolMatches(toolName, rules)) {
56
58
  return true;
57
59
  }
@@ -66,7 +68,7 @@ export const commandRuleStrategy = {
66
68
  specifiers.push(rule.specifier);
67
69
  }
68
70
  }
69
- return matchesCommandRules(command, specifiers);
71
+ return matchesCommandRules(command, specifiers, mode);
70
72
  },
71
73
  };
72
74
  //# sourceMappingURL=rule-strategies.js.map
@@ -3,4 +3,5 @@ export const CROW_SYSTEM_AGENT_ID = "__super_crow__";
3
3
  export const CROW_TASK_DISPATCHER_AGENT_ID = "__crow_task_dp__";
4
4
  export const CROW_NARRATIVE_ARCHITECT_AGENT_ID = "__crow_narrative_architect__";
5
5
  export const CROW_WORLD_BUILDER_AGENT_ID = "__crow_world_builder__";
6
+ export const FRAGMENT_REFLECTION_AGENT_ID = "__crow_fragment_reflection__";
6
7
  //# sourceMappingURL=system-agent.js.map
@@ -2,10 +2,10 @@ 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, isAgentLifecycleServerMessage, 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, FragmentCreatedWsMessageSchema, FragmentUpdatedWsMessageSchema, FragmentDeletedWsMessageSchema, 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
- export { ARTIFACT_TYPE, ARTIFACT_CONTENT_TYPE, ArtifactTypeSchema, ArtifactContentTypeSchema, ArtifactMetadataSchema, ArtifactUpdateSchema, } from "./schemas/artifact.schema.js";
8
+ export { ARTIFACT_TYPE, ARTIFACT_CONTENT_TYPE, ArtifactTypeSchema, ArtifactContentTypeSchema, ArtifactEntityTypeSchema, ArtifactMetadataSchema, ArtifactUpdateSchema, } from "./schemas/artifact.schema.js";
9
9
  export { AGENT_TASK_STATE, AGENT_TASK_SOURCE_TYPE, AgentTaskStateSchema, AgentTaskSourceSchema, AgentTaskItemSchema, AgentTaskDatabaseSchema, CreateTaskInputSchema, UpdateTaskInputSchema, UpdateTaskStateInputSchema, AssignTaskInputSchema, } from "./schemas/agent-task.schema.js";
10
10
  export { MCP_CONFIG_TYPE, InternalMcpConfigSchema, McpServerConfigSchema, CreateMcpConfigInputSchema, UpdateMcpConfigInputSchema, } from "./schemas/mcp-config.schema.js";
11
11
  export { SensorInfoSchema } from "./schemas/sensor.schema.js";
@@ -19,14 +19,17 @@ export { applyAgentOrder } from "./utils/apply-agent-order.js";
19
19
  export { MODEL_ALIASES, resolveModel, modelSupportsAdaptiveThinking } from "./utils/resolve-model.js";
20
20
  export { BASE_CIRCLE_ID, BASE_CIRCLE_NAME } from "./constants/system-circle.js";
21
21
  export { ENTITY_TYPE, RELATIONSHIP_TYPE, AgentCircleSchema, CreateAgentCircleInputSchema, UpdateAgentCircleInputSchema, EntityTypeSchema, RelationshipTypeSchema, RelationshipSchema, CreateRelationshipInputSchema, CircleMemberSchema, } from "./schemas/agent-circle.schema.js";
22
- export { CROW_SYSTEM_AGENT_ID, CROW_TASK_DISPATCHER_AGENT_ID, CROW_NARRATIVE_ARCHITECT_AGENT_ID, CROW_WORLD_BUILDER_AGENT_ID, } from "./constants/system-agent.js";
22
+ export { CROW_SYSTEM_AGENT_ID, CROW_TASK_DISPATCHER_AGENT_ID, CROW_NARRATIVE_ARCHITECT_AGENT_ID, CROW_WORLD_BUILDER_AGENT_ID, FRAGMENT_REFLECTION_AGENT_ID, } from "./constants/system-agent.js";
23
+ export { CreateFragmentAssociationInputSchema, FRAGMENT_KIND, FRAGMENT_FIRST_LEVEL_TARGET, FRAGMENT_MAX_WORDS, FragmentKindSchema, FragmentSchema, } from "./schemas/fragment.schema.js";
24
+ export { REFLECTION_AGENT_REF, REFLECTION_TEMP_PREFIX, REFLECTION_OP, ReflectionOpSchema, ReflectionPlanSchema, } from "./schemas/fragment-reflection.schema.js";
23
25
  export { MESSAGE_SOURCE_TYPE, MessageSourceSchema, } from "./schemas/message-source.schema.js";
24
26
  export { AGENT_COMMAND, AgentCommandSchema } from "./schemas/agent-command.schema.js";
25
27
  export { GraphNodeSchema, GraphEdgeSchema, GraphDataSchema, } from "./schemas/graph.schema.js";
26
28
  export { ConnectorConnectionSchema, ConnectorInfoSchema, ConnectConnectorResponseSchema, } from "./schemas/connector.schema.js";
27
29
  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";
30
+ export { splitSubcommands, deriveRules, matchesRules, DEFAULT_PREFIX_DEPTH, MAX_DERIVED_RULES, PROCESS_WRAPPERS, SUBCOMMAND_MATCH_MODE, } from "./auto-approve/command-decomposition.js";
29
31
  export { defaultRuleStrategy, commandRuleStrategy } from "./auto-approve/rule-strategies.js";
30
32
  export { getRuleStrategy } from "./auto-approve/rule-strategy-registry.js";
31
33
  export { AutoApproveRuleSet } from "./auto-approve/auto-approve-rule-set.js";
34
+ export { normalizeMcpName } from "./utils/mcp-utils.js";
32
35
  //# sourceMappingURL=index.js.map
@@ -5,13 +5,18 @@ import { z } from "zod";
5
5
  export const ENTITY_TYPE = {
6
6
  AGENT: "AGENT",
7
7
  AGENT_CIRCLE: "AGENT_CIRCLE",
8
+ FRAGMENT: "FRAGMENT",
8
9
  };
9
10
  /**
10
11
  * Relationship types between entities.
11
- * MEMBERSHIP means "source contains target as a member".
12
+ * MEMBERSHIP means "source contains target as a member" (agent ↔ circle only).
13
+ * ASSOCIATION anchors an agent to a fragment (agent → fragment).
14
+ * LINK connects fragments (fragment → fragment).
12
15
  */
13
16
  export const RELATIONSHIP_TYPE = {
14
17
  MEMBERSHIP: "MEMBERSHIP",
18
+ ASSOCIATION: "ASSOCIATION",
19
+ LINK: "LINK",
15
20
  };
16
21
  export const AgentCircleSchema = z.object({
17
22
  /** Unique identifier - UUID for user-created circles, well-known string for system circles */
@@ -37,8 +42,12 @@ export const UpdateAgentCircleInputSchema = z.object({
37
42
  convention: z.string().optional(),
38
43
  displayOrder: z.number().optional(),
39
44
  });
40
- export const EntityTypeSchema = z.enum([ENTITY_TYPE.AGENT, ENTITY_TYPE.AGENT_CIRCLE]);
41
- export const RelationshipTypeSchema = z.enum([RELATIONSHIP_TYPE.MEMBERSHIP]);
45
+ export const EntityTypeSchema = z.enum([ENTITY_TYPE.AGENT, ENTITY_TYPE.AGENT_CIRCLE, ENTITY_TYPE.FRAGMENT]);
46
+ export const RelationshipTypeSchema = z.enum([
47
+ RELATIONSHIP_TYPE.MEMBERSHIP,
48
+ RELATIONSHIP_TYPE.ASSOCIATION,
49
+ RELATIONSHIP_TYPE.LINK,
50
+ ]);
42
51
  export const RelationshipSchema = z.object({
43
52
  /** Unique identifier - UUID except for virtual relationship with system agents */
44
53
  id: z.string().min(1),
@@ -77,13 +77,13 @@ export const AgentRuntimeStateSchema = z.object({
77
77
  messageSource: MessageSourceSchema.optional(),
78
78
  discordDmChannelId: z.string().optional(),
79
79
  sessionId: z.string().optional(),
80
+ activeDomainFragmentIds: z.array(z.string()).default([]),
80
81
  sessionUsage: SessionUsageSchema,
81
82
  prevLoopMessageTimestamp: z.number().optional(),
82
83
  lastGmailCheckTimestamp: z.number().optional(),
83
84
  lastError: z.string().optional(),
84
85
  pendingPermissions: z.array(PendingPermissionInfoSchema).optional(),
85
86
  pendingInstructionReminder: PendingInstructionReminderSchema.optional(),
86
- /** Recent user message inputs (oldest first) for compose-box Up/Down recall; survives new sessions. */
87
87
  inputHistory: z.array(z.string()).optional(),
88
88
  });
89
89
  //# sourceMappingURL=agent-runtime-state.schema.js.map
@@ -1,6 +1,8 @@
1
1
  import { z } from "zod";
2
- import { EntityTypeSchema } from "./agent-circle.schema.js";
2
+ import { ENTITY_TYPE } from "./agent-circle.schema.js";
3
3
  import { AgentTaskSourceSchema } from "./agent-task.schema.js";
4
+ /** Entity types that can own artifacts — fragments are never artifact-bearing */
5
+ export const ArtifactEntityTypeSchema = z.enum([ENTITY_TYPE.AGENT, ENTITY_TYPE.AGENT_CIRCLE]);
4
6
  /**
5
7
  * TODO: layered memory system via artifacts.
6
8
  */
@@ -41,7 +43,7 @@ export const ArtifactMetadataSchema = z.object({
41
43
  type: ArtifactTypeSchema,
42
44
  contentType: ArtifactContentTypeSchema,
43
45
  entityId: z.string(),
44
- entityType: EntityTypeSchema,
46
+ entityType: ArtifactEntityTypeSchema,
45
47
  size: z.number(),
46
48
  tags: z.array(z.string()).optional(),
47
49
  createdTimestamp: z.number(),
@@ -0,0 +1,62 @@
1
+ import { z } from "zod";
2
+ import { FragmentKindSchema } from "./fragment.schema.js";
3
+ /**
4
+ * A plan node reference is a single string.
5
+ * `REFLECTION_AGENT_REF` names the target agent (top-level anchor).
6
+ * A string starting with `REFLECTION_TEMP_PREFIX` names a node created earlier in the same plan by its tempId.
7
+ * Anything else is an existing fragment id.
8
+ */
9
+ export const REFLECTION_AGENT_REF = "agent";
10
+ export const REFLECTION_TEMP_PREFIX = "$";
11
+ const NodeRefSchema = z.string().min(1);
12
+ /**
13
+ * Reflection plan operations, applied in order against the target agent's memory fragments.
14
+ * CREATE - a new node (theme/sub-domain) hanging under `parent`.
15
+ * LINK - add an edge, or move when `from` names the edge to drop.
16
+ * UNLINK - remove one named edge (last-edge removal cascade-deletes).
17
+ * UPDATE - content only (cue/body).
18
+ */
19
+ export const REFLECTION_OP = {
20
+ CREATE: "create",
21
+ LINK: "link",
22
+ UNLINK: "unlink",
23
+ UPDATE: "update",
24
+ };
25
+ const CreateReflectionOpSchema = z.object({
26
+ op: z.literal(REFLECTION_OP.CREATE),
27
+ /** Handle later operations in the same plan use to reference this node — must start with `$` */
28
+ tempId: z.string().regex(/^\$/),
29
+ kind: FragmentKindSchema,
30
+ cue: z.string().min(1),
31
+ body: z.string().min(1),
32
+ parent: NodeRefSchema,
33
+ });
34
+ const LinkReflectionOpSchema = z.object({
35
+ op: z.literal(REFLECTION_OP.LINK),
36
+ fragment: NodeRefSchema,
37
+ parent: NodeRefSchema,
38
+ /** When given, the move drops this original parent edge after the new one is added */
39
+ from: NodeRefSchema.optional(),
40
+ });
41
+ const UnlinkReflectionOpSchema = z.object({
42
+ op: z.literal(REFLECTION_OP.UNLINK),
43
+ fragment: NodeRefSchema,
44
+ parent: NodeRefSchema,
45
+ });
46
+ const UpdateReflectionOpSchema = z.object({
47
+ op: z.literal(REFLECTION_OP.UPDATE),
48
+ fragment: NodeRefSchema,
49
+ cue: z.string().min(1).optional(),
50
+ body: z.string().min(1).optional(),
51
+ });
52
+ export const ReflectionOpSchema = z.discriminatedUnion("op", [
53
+ CreateReflectionOpSchema,
54
+ LinkReflectionOpSchema,
55
+ UnlinkReflectionOpSchema,
56
+ UpdateReflectionOpSchema,
57
+ ]);
58
+ /** The single-pass reorganization plan the reflection agent returns between its output markers */
59
+ export const ReflectionPlanSchema = z.object({
60
+ operations: z.array(ReflectionOpSchema),
61
+ });
62
+ //# sourceMappingURL=fragment-reflection.schema.js.map
@@ -0,0 +1,47 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Fragment kinds.
4
+ * DOMAIN - an organizing topic others nest under.
5
+ * KNOWLEDGE - a fact (even one a user tells you); leaf under a DOMAIN.
6
+ * LESSON - a how-to-act rule from the agent's own reflection.
7
+ * FEEDBACK - a correction or preference from the user.
8
+ */
9
+ export const FRAGMENT_KIND = {
10
+ FEEDBACK: "FEEDBACK",
11
+ LESSON: "LESSON",
12
+ DOMAIN: "DOMAIN",
13
+ KNOWLEDGE: "KNOWLEDGE",
14
+ };
15
+ export const FragmentKindSchema = z.enum([
16
+ FRAGMENT_KIND.FEEDBACK,
17
+ FRAGMENT_KIND.LESSON,
18
+ FRAGMENT_KIND.DOMAIN,
19
+ FRAGMENT_KIND.KNOWLEDGE,
20
+ ]);
21
+ /** Maximum number of words in a fragment body, kind-agnostic, enforced on write */
22
+ export const FRAGMENT_MAX_WORDS = 100;
23
+ /** Target ceiling for a first-level bucket or any parent's direct children before reflection consolidates */
24
+ export const FRAGMENT_FIRST_LEVEL_TARGET = 20;
25
+ /**
26
+ * An atomic unit of agent experience.
27
+ * Pure: no agent reference and no link fields — agent↔fragment and
28
+ * fragment↔fragment relations are relationship-graph edges only.
29
+ */
30
+ export const FragmentSchema = z.object({
31
+ id: z.string().min(1),
32
+ kind: FragmentKindSchema,
33
+ /** Level-1: short one-line relevance descriptor, always cheap to surface */
34
+ cue: z.string().min(1),
35
+ /** Level-2: the lesson itself, pulled on demand */
36
+ body: z.string().min(1),
37
+ /** Times the fragment has been recalled */
38
+ usageCount: z.number(),
39
+ lastRecalledTimestamp: z.number().optional(),
40
+ createdTimestamp: z.number(),
41
+ updatedTimestamp: z.number(),
42
+ });
43
+ /** Input for the user-facing sharing route: associate an agent to a fragment */
44
+ export const CreateFragmentAssociationInputSchema = z.object({
45
+ agentId: z.string().min(1),
46
+ });
47
+ //# sourceMappingURL=fragment.schema.js.map
@@ -1,7 +1,8 @@
1
1
  import { z } from "zod";
2
2
  import { EntityTypeSchema, RelationshipTypeSchema } from "./agent-circle.schema.js";
3
3
  import { AGENT_STATUS } from "./agent-runtime-state.schema.js";
4
- /** A node in the relationship graph — represents either an agent or a circle */
4
+ import { FragmentKindSchema } from "./fragment.schema.js";
5
+ /** A node in the relationship graph — represents an agent, a circle, or a fragment */
5
6
  export const GraphNodeSchema = z.object({
6
7
  id: z.string(),
7
8
  name: z.string(),
@@ -9,6 +10,7 @@ export const GraphNodeSchema = z.object({
9
10
  isSystemAgent: z.boolean().optional(),
10
11
  isPinned: z.boolean().optional(),
11
12
  isSystemCircle: z.boolean().optional(),
13
+ kind: FragmentKindSchema.optional(),
12
14
  status: z
13
15
  .enum([AGENT_STATUS.IDLE, AGENT_STATUS.ACTIVATING, AGENT_STATUS.STREAMING, AGENT_STATUS.COMPACTING])
14
16
  .optional(),
@@ -44,6 +44,9 @@ export const SERVER_MESSAGE_TYPE = {
44
44
  CIRCLE_DELETED: "circle_deleted",
45
45
  RELATIONSHIP_CREATED: "relationship_created",
46
46
  RELATIONSHIP_DELETED: "relationship_deleted",
47
+ FRAGMENT_CREATED: "fragment_created",
48
+ FRAGMENT_UPDATED: "fragment_updated",
49
+ FRAGMENT_DELETED: "fragment_deleted",
47
50
  AGENT_BUILDER_DRAFT_UPDATED: "agent_builder_draft_updated",
48
51
  };
49
52
  export const SendMessageSchema = z.object({
@@ -192,6 +195,18 @@ export const RelationshipDeletedWsMessageSchema = z.object({
192
195
  type: z.literal(SERVER_MESSAGE_TYPE.RELATIONSHIP_DELETED),
193
196
  relationshipId: z.string(),
194
197
  });
198
+ export const FragmentCreatedWsMessageSchema = z.object({
199
+ type: z.literal(SERVER_MESSAGE_TYPE.FRAGMENT_CREATED),
200
+ fragmentId: z.string(),
201
+ });
202
+ export const FragmentUpdatedWsMessageSchema = z.object({
203
+ type: z.literal(SERVER_MESSAGE_TYPE.FRAGMENT_UPDATED),
204
+ fragmentId: z.string(),
205
+ });
206
+ export const FragmentDeletedWsMessageSchema = z.object({
207
+ type: z.literal(SERVER_MESSAGE_TYPE.FRAGMENT_DELETED),
208
+ fragmentId: z.string(),
209
+ });
195
210
  /** The single agent-builder draft changed; carries the resolved view, or null when it was cleared. */
196
211
  export const AgentBuilderDraftUpdatedWsMessageSchema = z.object({
197
212
  type: z.literal(SERVER_MESSAGE_TYPE.AGENT_BUILDER_DRAFT_UPDATED),
@@ -222,6 +237,9 @@ export const ServerMessageSchema = z.discriminatedUnion("type", [
222
237
  CircleDeletedWsMessageSchema,
223
238
  RelationshipCreatedWsMessageSchema,
224
239
  RelationshipDeletedWsMessageSchema,
240
+ FragmentCreatedWsMessageSchema,
241
+ FragmentUpdatedWsMessageSchema,
242
+ FragmentDeletedWsMessageSchema,
225
243
  AgentBuilderDraftUpdatedWsMessageSchema,
226
244
  ]);
227
245
  export function isAgentServerMessage(message) {
@@ -0,0 +1,4 @@
1
+ export function normalizeMcpName(name) {
2
+ return name.toLowerCase().replaceAll(" ", "_");
3
+ }
4
+ //# sourceMappingURL=mcp-utils.js.map
@@ -0,0 +1,98 @@
1
+ import { PERMISSION_MODE, TOOL_MODE, CLAUDE_MODELS, FRAGMENT_REFLECTION_AGENT_ID, FRAGMENT_FIRST_LEVEL_TARGET, FRAGMENT_MAX_WORDS, REFLECTION_AGENT_REF, REFLECTION_TEMP_PREFIX, } from "../_shared/index.js";
2
+ import path from "node:path";
3
+ import { env } from "../config/env.js";
4
+ import { SYSTEM_AGENT_TYPE, resolveSystemAgentModel } from "./system-agent-provider.js";
5
+ import { createMessageContentFromTemplate, getDefaultPromptContext } from "../utils/message-template.js";
6
+ import { SYSTEM_AGENTS_PROJECT_DIR_NAME } from "../config/constants.js";
7
+ import { FRAGMENT_REFLECTION_BEGIN, FRAGMENT_REFLECTION_END, } from "../services/fragment/fragment-reflection.constants.js";
8
+ const CROW_FRAGMENT_REFLECTION_AGENT_NAME = "Crow Fragment Reflection";
9
+ /**
10
+ * Planner charter for the fragment reflection agent. Substituted with
11
+ * {maxWords}/{firstLevelTarget} from the shared fragment constants at agent build time.
12
+ */
13
+ export const CROW_FRAGMENT_REFLECTION_AGENT_PERSONA = {
14
+ role: "system",
15
+ content: [
16
+ {
17
+ content: [
18
+ "You are the reflective memory steward for crow central agency — an invisible background role that reviews another agent's long-term memory. Each run you step back and study ONE target agent's fragments: what it has newly learned, and how that sits against everything it already holds. From that reflection you return a plan that settles each fragment where it truly belongs. You never talk to a user, never mutate the memory yourself, and never emit anything but the plan.",
19
+ "",
20
+ "A fragment is one atomic memory: a short `cue` plus a `body` of at most {maxWords} words, typed DOMAIN, KNOWLEDGE, FEEDBACK, or LESSON. Fragments form a DAG — a fragment can hang under multiple parents by LINK, and top-level fragments are anchored to the agent. KNOWLEDGE is a leaf that only hangs under a DOMAIN.",
21
+ "",
22
+ "Your job: examine every fragment and settle each under the parents where it truly belongs, whether a DOMAIN it concerns or a broader FEEDBACK or LESSON it refines. When any parent's direct children grow past about {firstLevelTarget}, introduce an intermediate parent of the fitting kind and move the related members under it. Merge duplicates by folding unique content into the survivor before removing the loser, and prune stale or superseded fragments. Make minimal, high-confidence changes — under-organizing is far safer than scrambling sound structure.",
23
+ "",
24
+ "Use `read_fragment(id)` to pull any body the context did not front-load, and `search_fragment(targetAgentId, query)` to find near-duplicates elsewhere in the target's memory before you decide.",
25
+ "",
26
+ "## OUTPUT",
27
+ "",
28
+ "Emit exactly one JSON object between the markers below and nothing else — no preamble, no commentary, no code fences.",
29
+ "",
30
+ "Every node reference in the plan is a single string:",
31
+ `- \`"${REFLECTION_AGENT_REF}"\` — the target agent (top-level anchor).`,
32
+ `- \`"${REFLECTION_TEMP_PREFIX}…"\` (starts with \`${REFLECTION_TEMP_PREFIX}\`, e.g. \`"${REFLECTION_TEMP_PREFIX}1"\`) — a node created earlier in this same plan, by the tempId that create gave it.`,
33
+ "- anything else — an existing fragment id.",
34
+ "",
35
+ "Operand names are the same across ops: `fragment` = the node being operated on, `parent` = the node it hangs under, `from` = the old parent in a move.",
36
+ "",
37
+ "The plan:",
38
+ "```",
39
+ '{ "operations": [',
40
+ ` { "op": "create", "tempId": "${REFLECTION_TEMP_PREFIX}1", "kind": "DOMAIN|KNOWLEDGE|FEEDBACK|LESSON", "cue": "...", "body": "...", "parent": <ref> },`,
41
+ ' { "op": "link", "fragment": <ref>, "parent": <ref>, "from": <ref> }, // "from" optional — include to MOVE off that parent',
42
+ ' { "op": "unlink", "fragment": <ref>, "parent": <ref> }, // removing the last parent cascade-deletes the fragment + orphaned children',
43
+ ' { "op": "update", "fragment": <ref>, "cue": "...", "body": "..." } // cue/body optional — include only what changes',
44
+ "] }",
45
+ "```",
46
+ "",
47
+ "Rules:",
48
+ `- \`tempId\` must start with \`${REFLECTION_TEMP_PREFIX}\` and be unique within the plan; reference it in later ops as that same \`"${REFLECTION_TEMP_PREFIX}…"\` string.`,
49
+ "- Respect the structure rules — KNOWLEDGE only under a DOMAIN, bodies within {maxWords} words, no cycles. Invalid ops are rejected on apply, so plan only valid moves.",
50
+ '- If you have no confident changes to make, return `{ "operations": [] }`.',
51
+ "",
52
+ "Shape of every response:",
53
+ FRAGMENT_REFLECTION_BEGIN,
54
+ "<the plan JSON object>",
55
+ FRAGMENT_REFLECTION_END,
56
+ ],
57
+ },
58
+ ],
59
+ keys: ["maxWords", "firstLevelTarget"],
60
+ };
61
+ const CROW_FRAGMENT_REFLECTION_BIRTHDAY = "1970-01-01T00:00:00Z";
62
+ const CROW_FRAGMENT_REFLECTION_TOOLS = [];
63
+ /**
64
+ * Build the fragment reflection agent config - an invisible background agent that performs
65
+ * retrospection on one target agent's long-term memory per run and returns a single
66
+ * marker-wrapped reorganization plan.
67
+ */
68
+ export function getFragmentReflectionAgent() {
69
+ const persona = createMessageContentFromTemplate(CROW_FRAGMENT_REFLECTION_AGENT_PERSONA, getDefaultPromptContext({
70
+ maxWords: String(FRAGMENT_MAX_WORDS),
71
+ firstLevelTarget: String(FRAGMENT_FIRST_LEVEL_TARGET),
72
+ }));
73
+ return {
74
+ id: FRAGMENT_REFLECTION_AGENT_ID,
75
+ type: SYSTEM_AGENT_TYPE,
76
+ name: CROW_FRAGMENT_REFLECTION_AGENT_NAME,
77
+ description: "Reflection agent that reviews a target agent's long-term memory and plans its reorganization. Not user-facing.",
78
+ workspace: path.join(env.CROW_SYSTEM_PATH, SYSTEM_AGENTS_PROJECT_DIR_NAME),
79
+ persona,
80
+ model: resolveSystemAgentModel(CLAUDE_MODELS.SONNET),
81
+ permissionMode: PERMISSION_MODE.DEFAULT,
82
+ settingSources: [],
83
+ availableTools: [],
84
+ toolConfig: {
85
+ mode: TOOL_MODE.RESTRICTED,
86
+ tools: CROW_FRAGMENT_REFLECTION_TOOLS,
87
+ autoApprovedTools: CROW_FRAGMENT_REFLECTION_TOOLS,
88
+ },
89
+ mcpServerIds: [],
90
+ persistSession: false,
91
+ excludeClaudeCodeSystemPrompt: true,
92
+ isSystemAgent: true,
93
+ isBackgroundAgent: true,
94
+ createdAt: CROW_FRAGMENT_REFLECTION_BIRTHDAY,
95
+ updatedAt: CROW_FRAGMENT_REFLECTION_BIRTHDAY,
96
+ };
97
+ }
98
+ //# sourceMappingURL=crow-fragment-reflection-agent.js.map