byterover-cli 2.0.0 → 2.1.0

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 (181) hide show
  1. package/README.md +6 -81
  2. package/dist/agent/core/domain/llm/index.d.ts +1 -1
  3. package/dist/agent/core/domain/llm/index.js +1 -1
  4. package/dist/agent/core/domain/llm/registry.d.ts +8 -0
  5. package/dist/agent/core/domain/llm/registry.js +34 -0
  6. package/dist/agent/core/domain/sandbox/types.d.ts +2 -0
  7. package/dist/agent/core/domain/tools/constants.d.ts +3 -0
  8. package/dist/agent/core/domain/tools/constants.js +3 -0
  9. package/dist/agent/core/interfaces/cipher-services.d.ts +2 -4
  10. package/dist/agent/core/interfaces/i-cipher-agent.d.ts +9 -1
  11. package/dist/agent/core/interfaces/i-sandbox-service.d.ts +8 -0
  12. package/dist/agent/core/interfaces/i-tool-provider.d.ts +10 -0
  13. package/dist/agent/core/interfaces/i-tool-scheduler.d.ts +9 -0
  14. package/dist/agent/infra/agent/agent-schemas.d.ts +0 -9
  15. package/dist/agent/infra/agent/agent-schemas.js +0 -3
  16. package/dist/agent/infra/agent/cipher-agent.d.ts +25 -1
  17. package/dist/agent/infra/agent/cipher-agent.js +138 -11
  18. package/dist/agent/infra/agent/provider-update-config.d.ts +0 -2
  19. package/dist/agent/infra/agent/service-initializer.d.ts +2 -6
  20. package/dist/agent/infra/agent/service-initializer.js +45 -38
  21. package/dist/agent/infra/blob/blob-storage-factory.d.ts +2 -2
  22. package/dist/agent/infra/blob/blob-storage-factory.js +4 -4
  23. package/dist/agent/infra/blob/file-blob-storage.d.ts +96 -0
  24. package/dist/agent/infra/blob/file-blob-storage.js +454 -0
  25. package/dist/agent/infra/blob/index.d.ts +2 -3
  26. package/dist/agent/infra/blob/index.js +4 -6
  27. package/dist/agent/infra/llm/agent-llm-service.d.ts +3 -0
  28. package/dist/agent/infra/llm/agent-llm-service.js +34 -52
  29. package/dist/agent/infra/llm/context/compression/compression-helpers.d.ts +35 -0
  30. package/dist/agent/infra/llm/context/compression/compression-helpers.js +124 -0
  31. package/dist/agent/infra/llm/context/compression/escalated-compression.d.ts +62 -0
  32. package/dist/agent/infra/llm/context/compression/escalated-compression.js +144 -0
  33. package/dist/agent/infra/llm/context/compression/index.d.ts +3 -0
  34. package/dist/agent/infra/llm/context/compression/index.js +3 -0
  35. package/dist/agent/infra/llm/context/compression/reactive-overflow.d.ts +0 -27
  36. package/dist/agent/infra/llm/context/compression/reactive-overflow.js +5 -122
  37. package/dist/agent/infra/llm/context/context-manager.d.ts +20 -1
  38. package/dist/agent/infra/llm/context/context-manager.js +37 -7
  39. package/dist/agent/infra/llm/providers/index.js +0 -2
  40. package/dist/agent/infra/llm/providers/types.d.ts +1 -5
  41. package/dist/agent/infra/map/agentic-map-service.d.ts +97 -0
  42. package/dist/agent/infra/map/agentic-map-service.js +309 -0
  43. package/dist/agent/infra/map/context-tree-store.d.ts +94 -0
  44. package/dist/agent/infra/map/context-tree-store.js +278 -0
  45. package/dist/agent/infra/map/index.d.ts +4 -0
  46. package/dist/agent/infra/map/index.js +4 -0
  47. package/dist/agent/infra/map/llm-map-memory.d.ts +59 -0
  48. package/dist/agent/infra/map/llm-map-memory.js +187 -0
  49. package/dist/agent/infra/map/llm-map-service.d.ts +36 -0
  50. package/dist/agent/infra/map/llm-map-service.js +118 -0
  51. package/dist/agent/infra/map/map-shared.d.ts +140 -0
  52. package/dist/agent/infra/map/map-shared.js +325 -0
  53. package/dist/agent/infra/map/worker-pool.d.ts +45 -0
  54. package/dist/agent/infra/map/worker-pool.js +73 -0
  55. package/dist/agent/infra/sandbox/curation-helpers.d.ts +62 -0
  56. package/dist/agent/infra/sandbox/curation-helpers.js +219 -0
  57. package/dist/agent/infra/sandbox/sandbox-service.d.ts +12 -0
  58. package/dist/agent/infra/sandbox/sandbox-service.js +39 -7
  59. package/dist/agent/infra/sandbox/tools-sdk.d.ts +48 -1
  60. package/dist/agent/infra/sandbox/tools-sdk.js +52 -1
  61. package/dist/agent/infra/session/session-manager.d.ts +8 -1
  62. package/dist/agent/infra/session/session-manager.js +24 -4
  63. package/dist/agent/infra/storage/file-key-storage.d.ts +142 -0
  64. package/dist/agent/infra/storage/file-key-storage.js +572 -0
  65. package/dist/agent/infra/storage/granular-history-storage.d.ts +1 -1
  66. package/dist/agent/infra/storage/granular-history-storage.js +1 -1
  67. package/dist/agent/infra/system-prompt/contributors/context-tree-structure-contributor.d.ts +4 -0
  68. package/dist/agent/infra/system-prompt/contributors/context-tree-structure-contributor.js +42 -14
  69. package/dist/agent/infra/system-prompt/contributors/map-selection-contributor.d.ts +16 -0
  70. package/dist/agent/infra/system-prompt/contributors/map-selection-contributor.js +47 -0
  71. package/dist/agent/infra/tools/core-tool-scheduler.js +3 -1
  72. package/dist/agent/infra/tools/implementations/agentic-map-tool.d.ts +35 -0
  73. package/dist/agent/infra/tools/implementations/agentic-map-tool.js +156 -0
  74. package/dist/agent/infra/tools/implementations/code-exec-tool.js +1 -0
  75. package/dist/agent/infra/tools/implementations/curate-tool.d.ts +9 -9
  76. package/dist/agent/infra/tools/implementations/expand-knowledge-tool.d.ts +18 -0
  77. package/dist/agent/infra/tools/implementations/expand-knowledge-tool.js +43 -0
  78. package/dist/agent/infra/tools/implementations/llm-map-tool.d.ts +24 -0
  79. package/dist/agent/infra/tools/implementations/llm-map-tool.js +87 -0
  80. package/dist/agent/infra/tools/implementations/memory-symbol-tree.d.ts +28 -1
  81. package/dist/agent/infra/tools/implementations/memory-symbol-tree.js +27 -3
  82. package/dist/agent/infra/tools/implementations/search-knowledge-service.d.ts +1 -0
  83. package/dist/agent/infra/tools/implementations/search-knowledge-service.js +83 -12
  84. package/dist/agent/infra/tools/implementations/search-knowledge-tool.js +2 -2
  85. package/dist/agent/infra/tools/tool-manager.js +6 -0
  86. package/dist/agent/infra/tools/tool-provider.d.ts +12 -0
  87. package/dist/agent/infra/tools/tool-provider.js +78 -0
  88. package/dist/agent/infra/tools/tool-registry.d.ts +14 -0
  89. package/dist/agent/infra/tools/tool-registry.js +32 -0
  90. package/dist/agent/resources/prompts/system-prompt.yml +48 -74
  91. package/dist/agent/resources/tools/expand_knowledge.txt +20 -0
  92. package/dist/oclif/commands/curate/index.js +1 -2
  93. package/dist/oclif/commands/main.js +1 -0
  94. package/dist/oclif/commands/providers/connect.d.ts +1 -3
  95. package/dist/oclif/commands/providers/connect.js +7 -29
  96. package/dist/oclif/commands/query.js +1 -2
  97. package/dist/server/constants.d.ts +7 -0
  98. package/dist/server/constants.js +8 -0
  99. package/dist/server/core/domain/entities/provider-registry.js +1 -15
  100. package/dist/server/core/domain/knowledge/memory-scoring.js +1 -1
  101. package/dist/server/core/domain/knowledge/summary-types.d.ts +126 -0
  102. package/dist/server/core/domain/knowledge/summary-types.js +7 -0
  103. package/dist/server/core/domain/transport/schemas.d.ts +0 -4
  104. package/dist/server/core/interfaces/context-tree/i-context-tree-archive-service.d.ts +30 -0
  105. package/dist/server/core/interfaces/context-tree/i-context-tree-archive-service.js +1 -0
  106. package/dist/server/core/interfaces/context-tree/i-context-tree-manifest-service.d.ts +30 -0
  107. package/dist/server/core/interfaces/context-tree/i-context-tree-manifest-service.js +1 -0
  108. package/dist/server/core/interfaces/context-tree/i-context-tree-summary-service.d.ts +29 -0
  109. package/dist/server/core/interfaces/context-tree/i-context-tree-summary-service.js +1 -0
  110. package/dist/server/infra/cogit/context-tree-to-push-context-mapper.js +10 -3
  111. package/dist/server/infra/connectors/skill/skill-connector.d.ts +4 -0
  112. package/dist/server/infra/connectors/skill/skill-connector.js +4 -0
  113. package/dist/server/infra/context-tree/children-hash.d.ts +20 -0
  114. package/dist/server/infra/context-tree/children-hash.js +22 -0
  115. package/dist/server/infra/context-tree/derived-artifact.d.ts +28 -0
  116. package/dist/server/infra/context-tree/derived-artifact.js +48 -0
  117. package/dist/server/infra/context-tree/file-context-tree-archive-service.d.ts +37 -0
  118. package/dist/server/infra/context-tree/file-context-tree-archive-service.js +219 -0
  119. package/dist/server/infra/context-tree/file-context-tree-manifest-service.d.ts +50 -0
  120. package/dist/server/infra/context-tree/file-context-tree-manifest-service.js +278 -0
  121. package/dist/server/infra/context-tree/file-context-tree-merger.js +4 -0
  122. package/dist/server/infra/context-tree/file-context-tree-snapshot-service.js +12 -4
  123. package/dist/server/infra/context-tree/file-context-tree-summary-service.d.ts +44 -0
  124. package/dist/server/infra/context-tree/file-context-tree-summary-service.js +313 -0
  125. package/dist/server/infra/context-tree/file-context-tree-writer-service.js +5 -0
  126. package/dist/server/infra/context-tree/prompts/summary-generation.d.ts +22 -0
  127. package/dist/server/infra/context-tree/prompts/summary-generation.js +45 -0
  128. package/dist/server/infra/context-tree/snapshot-diff.d.ts +19 -0
  129. package/dist/server/infra/context-tree/snapshot-diff.js +39 -0
  130. package/dist/server/infra/context-tree/summary-frontmatter.d.ts +24 -0
  131. package/dist/server/infra/context-tree/summary-frontmatter.js +111 -0
  132. package/dist/server/infra/daemon/agent-process.js +2 -14
  133. package/dist/server/infra/executor/curate-executor.d.ts +1 -0
  134. package/dist/server/infra/executor/curate-executor.js +82 -34
  135. package/dist/server/infra/executor/folder-pack-executor.js +1 -1
  136. package/dist/server/infra/executor/pre-compaction/compaction-escalation.d.ts +6 -0
  137. package/dist/server/infra/executor/pre-compaction/compaction-escalation.js +6 -0
  138. package/dist/server/infra/executor/pre-compaction/index.d.ts +3 -0
  139. package/dist/server/infra/executor/pre-compaction/index.js +1 -0
  140. package/dist/server/infra/executor/pre-compaction/pre-compaction-service.d.ts +59 -0
  141. package/dist/server/infra/executor/pre-compaction/pre-compaction-service.js +124 -0
  142. package/dist/server/infra/executor/pre-compaction/prompts.d.ts +24 -0
  143. package/dist/server/infra/executor/pre-compaction/prompts.js +47 -0
  144. package/dist/server/infra/executor/query-executor.d.ts +3 -0
  145. package/dist/server/infra/executor/query-executor.js +39 -4
  146. package/dist/server/infra/http/authenticated-http-client.js +4 -0
  147. package/dist/server/infra/http/provider-model-fetcher-registry.js +1 -5
  148. package/dist/server/infra/http/provider-model-fetchers.d.ts +0 -14
  149. package/dist/server/infra/http/provider-model-fetchers.js +0 -132
  150. package/dist/server/infra/provider/provider-config-resolver.js +0 -55
  151. package/dist/server/utils/curate-result-parser.d.ts +4 -4
  152. package/dist/shared/constants/curation.d.ts +6 -0
  153. package/dist/shared/constants/curation.js +6 -0
  154. package/dist/shared/utils/escalation-utils.d.ts +59 -0
  155. package/dist/shared/utils/escalation-utils.js +141 -0
  156. package/dist/tui/components/command-input.js +1 -1
  157. package/dist/tui/components/inline-prompts/inline-confirm.js +6 -1
  158. package/dist/tui/features/commands/definitions/exit.d.ts +2 -0
  159. package/dist/tui/features/commands/definitions/exit.js +9 -0
  160. package/dist/tui/features/commands/definitions/index.js +3 -0
  161. package/dist/tui/features/exit/components/exit-flow.d.ts +10 -0
  162. package/dist/tui/features/exit/components/exit-flow.js +19 -0
  163. package/dist/tui/features/provider/components/provider-flow.js +1 -21
  164. package/oclif.manifest.json +100 -109
  165. package/package.json +11 -4
  166. package/dist/agent/infra/blob/migrations.d.ts +0 -63
  167. package/dist/agent/infra/blob/migrations.js +0 -148
  168. package/dist/agent/infra/blob/sqlite-blob-storage.d.ts +0 -82
  169. package/dist/agent/infra/blob/sqlite-blob-storage.js +0 -307
  170. package/dist/agent/infra/llm/providers/google-vertex.d.ts +0 -15
  171. package/dist/agent/infra/llm/providers/google-vertex.js +0 -36
  172. package/dist/agent/infra/storage/blob-history-storage.d.ts +0 -81
  173. package/dist/agent/infra/storage/blob-history-storage.js +0 -193
  174. package/dist/agent/infra/storage/dual-format-history-storage.d.ts +0 -83
  175. package/dist/agent/infra/storage/dual-format-history-storage.js +0 -165
  176. package/dist/agent/infra/storage/sqlite-key-storage.d.ts +0 -113
  177. package/dist/agent/infra/storage/sqlite-key-storage.js +0 -438
  178. package/dist/server/infra/provider/vertex-ai-utils.d.ts +0 -10
  179. package/dist/server/infra/provider/vertex-ai-utils.js +0 -28
  180. package/dist/tui/features/provider/components/credential-path-dialog.d.ts +0 -30
  181. package/dist/tui/features/provider/components/credential-path-dialog.js +0 -85
@@ -0,0 +1,16 @@
1
+ import type { ContributorContext, SystemPromptContributor } from '../../../core/domain/system-prompt/types.js';
2
+ /**
3
+ * System prompt contributor that injects tool selection guidance for
4
+ * parallel map tools (llm_map, agentic_map).
5
+ *
6
+ * Only active for 'curate' and 'curate-folder' commands, and only when
7
+ * the map tools are available in the current tool set.
8
+ *
9
+ * Based on VoltCode's subagent-rules.txt and symbolic-recursion.txt.
10
+ */
11
+ export declare class MapSelectionContributor implements SystemPromptContributor {
12
+ readonly id: string;
13
+ readonly priority: number;
14
+ constructor(id: string, priority: number);
15
+ getContent(context: ContributorContext): Promise<string>;
16
+ }
@@ -0,0 +1,47 @@
1
+ import { ToolName } from '../../../core/domain/tools/constants.js';
2
+ /**
3
+ * System prompt contributor that injects tool selection guidance for
4
+ * parallel map tools (llm_map, agentic_map).
5
+ *
6
+ * Only active for 'curate' and 'curate-folder' commands, and only when
7
+ * the map tools are available in the current tool set.
8
+ *
9
+ * Based on VoltCode's subagent-rules.txt and symbolic-recursion.txt.
10
+ */
11
+ export class MapSelectionContributor {
12
+ id;
13
+ priority;
14
+ constructor(id, priority) {
15
+ this.id = id;
16
+ this.priority = priority;
17
+ }
18
+ async getContent(context) {
19
+ // Only inject for curate commands
20
+ if (context.commandType !== 'curate') {
21
+ return '';
22
+ }
23
+ const tools = context.availableTools ?? [];
24
+ const hasLlmMap = tools.includes(ToolName.LLM_MAP);
25
+ const hasAgenticMap = tools.includes(ToolName.AGENTIC_MAP);
26
+ // Only inject if at least one map tool is available
27
+ if (!hasLlmMap && !hasAgenticMap) {
28
+ return '';
29
+ }
30
+ const lines = [
31
+ '<parallel-processing-guidance>',
32
+ 'When processing multiple items during curation, choose the right approach:',
33
+ '',
34
+ '| Scenario | Tool | Why |',
35
+ '|----------|------|-----|',
36
+ '| 1-5 items, context-dependent decisions | Direct curate tool | Cross-item awareness needed |',
37
+ ];
38
+ if (hasLlmMap) {
39
+ lines.push('| 5+ items, independent extraction/classification | llm_map | Parallel stateless LLM calls, fast |');
40
+ }
41
+ if (hasAgenticMap) {
42
+ lines.push('| 5+ items, need file reads or tool access | agentic_map | Parallel sub-agents with tools |');
43
+ }
44
+ lines.push('| Cross-item dedup/merge decisions | Always direct curate | Needs full context tree visibility |', '', 'Key rules:', '- Map tools process items in COMPLETE ISOLATION — each item cannot see others.', '- Use map tools for the extraction/classification PHASE, then curate tool for final decisions.', '- Two-phase pattern for folder curation: (1) llm_map to extract knowledge from each file, (2) curate to deduplicate and organize.', '- Input/output for map tools: JSONL files (one JSON object per line).', '', 'Map tool output behavior:', '- Map tools may return a `summaryHandle` field — bounded continuation context summarizing processed items.', '- `summaryHandle` is optional helper context; its absence is non-fatal (fail-open design).', '- The JSONL output file is always the source of truth for per-item results.', '- Cross-item deduplication must happen in the curate phase, not during map processing.', '</parallel-processing-guidance>');
45
+ return lines.join('\n');
46
+ }
47
+ }
@@ -91,8 +91,10 @@ export class CoreToolScheduler {
91
91
  this.updateStatus(execution, 'executing');
92
92
  execution.startedAt = new Date();
93
93
  try {
94
- // Pass full context (including taskId) to toolProvider for subagent billing
94
+ // Pass full context (including taskId, commandType, metadata) to toolProvider
95
95
  const result = await this.toolProvider.executeTool(toolName, args, context.sessionId, {
96
+ commandType: context.commandType,
97
+ metadata: context.metadata,
96
98
  sessionId: context.sessionId,
97
99
  taskId: context.taskId,
98
100
  });
@@ -0,0 +1,35 @@
1
+ import type { Tool } from '../../../core/domain/tools/types.js';
2
+ import type { ICipherAgent } from '../../../core/interfaces/i-cipher-agent.js';
3
+ import type { IContentGenerator } from '../../../core/interfaces/i-content-generator.js';
4
+ import type { ILogger } from '../../../core/interfaces/i-logger.js';
5
+ import type { ITokenizer } from '../../../core/interfaces/i-tokenizer.js';
6
+ import { executeAgenticMap } from '../../map/agentic-map-service.js';
7
+ /**
8
+ * Create the agentic_map tool.
9
+ *
10
+ * Runs a parallel map over a JSONL file. For each item (line), spawns a
11
+ * sub-agent that receives the prompt plus a standardized metadata block.
12
+ * The sub-agent must output a JSON value that validates against the provided
13
+ * output schema.
14
+ *
15
+ * Use this instead of llm_map when items need tool access (file reads,
16
+ * code execution, knowledge search). Use llm_map when items don't need
17
+ * tools — it's faster and cheaper.
18
+ *
19
+ * @param agent - The cipher agent for creating sub-sessions
20
+ * @param workingDirectory - Project root directory
21
+ * @param options - Optional dependencies for ContextTreeStore
22
+ * @param options.executeAgenticMapImpl - Test seam override for executeAgenticMap
23
+ * @param options.generator - Content generator for context compaction summaries
24
+ * @param options.logger - Logger for fail-open warnings
25
+ * @param options.maxContextTokens - Model context window used to size context tree threshold
26
+ * @param options.tokenizer - Tokenizer used by ContextTreeStore
27
+ */
28
+ export declare function createAgenticMapTool(agent: ICipherAgent, workingDirectory: string, options?: {
29
+ /** Test seam: replaces executeAgenticMap for unit tests. Do not set in production. */
30
+ executeAgenticMapImpl?: typeof executeAgenticMap;
31
+ generator?: IContentGenerator;
32
+ logger?: ILogger;
33
+ maxContextTokens?: number;
34
+ tokenizer?: ITokenizer;
35
+ }): Tool;
@@ -0,0 +1,156 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { executeAgenticMap, getNestingRecord, HARD_MAX_DEPTH } from '../../map/agentic-map-service.js';
3
+ import { ContextTreeStore } from '../../map/context-tree-store.js';
4
+ import { AgenticMapParametersSchema } from '../../map/map-shared.js';
5
+ /**
6
+ * Create the agentic_map tool.
7
+ *
8
+ * Runs a parallel map over a JSONL file. For each item (line), spawns a
9
+ * sub-agent that receives the prompt plus a standardized metadata block.
10
+ * The sub-agent must output a JSON value that validates against the provided
11
+ * output schema.
12
+ *
13
+ * Use this instead of llm_map when items need tool access (file reads,
14
+ * code execution, knowledge search). Use llm_map when items don't need
15
+ * tools — it's faster and cheaper.
16
+ *
17
+ * @param agent - The cipher agent for creating sub-sessions
18
+ * @param workingDirectory - Project root directory
19
+ * @param options - Optional dependencies for ContextTreeStore
20
+ * @param options.executeAgenticMapImpl - Test seam override for executeAgenticMap
21
+ * @param options.generator - Content generator for context compaction summaries
22
+ * @param options.logger - Logger for fail-open warnings
23
+ * @param options.maxContextTokens - Model context window used to size context tree threshold
24
+ * @param options.tokenizer - Tokenizer used by ContextTreeStore
25
+ */
26
+ export function createAgenticMapTool(agent, workingDirectory, options) {
27
+ const _executeAgenticMap = options?.executeAgenticMapImpl ?? executeAgenticMap;
28
+ return {
29
+ description: [
30
+ 'Run a parallel map over a JSONL file using sub-agent sessions.',
31
+ 'For each item (line), spawn a sub-agent that receives your prompt',
32
+ 'plus a standardized metadata block containing the item.',
33
+ 'The sub-agent must output a JSON value conforming to the output schema.',
34
+ '',
35
+ 'Each sub-agent has full tool access (read files, search, code execution)',
36
+ 'unless read_only is set to true (which disables write operations).',
37
+ '',
38
+ 'Use this tool when items need tool access during processing.',
39
+ 'Use llm_map instead if items only need LLM intelligence — it is faster and cheaper.',
40
+ '',
41
+ 'Concurrency is capped at 4 parallel sub-agents.',
42
+ 'Input: JSONL file (one JSON object per line)',
43
+ 'Output: JSONL file with one result per line, ordered by input line.',
44
+ '',
45
+ 'Results include an optional summaryHandle — a compact summary of processed items.',
46
+ 'The JSONL output file is always the source of truth for per-item results.',
47
+ ].join('\n'),
48
+ async execute(input, context) {
49
+ const params = AgenticMapParametersSchema.parse(input);
50
+ // [Guard A] Write-enabled + missing sessionId.
51
+ // In standard ToolManager execution this is unreachable: ToolManager always injects
52
+ // sessionId (tool-manager.ts:159). Only reachable via direct tool invocation
53
+ // that bypasses ToolManager (tests, headless).
54
+ if (params.read_only === false && !context?.sessionId) {
55
+ throw new Error('agentic_map: session ID unavailable for write-enabled call. ' +
56
+ 'Cannot determine nesting depth. This is a bug — please report it.');
57
+ }
58
+ const callerRecord = context?.sessionId ? getNestingRecord(context.sessionId) : undefined;
59
+ // [Guard B] Hard assertion: non-write-enabled call inside a write-enabled sub-session.
60
+ // Catches both explicit read_only=true and omitted read_only (defaults to true in service).
61
+ // Decoupled from allowlist — catches read_only recursion even if allowlist changes.
62
+ if (params.read_only !== false && callerRecord !== undefined && !callerRecord.isRootCaller) {
63
+ throw new Error('agentic_map: read_only=false is required for recursive (nested) calls. ' +
64
+ 'Recursive composition requires read_only=false.');
65
+ }
66
+ // [Guard C] Universal fail-closed: sessionId present but no registry record.
67
+ // All legitimate sessions are registered at creation (CipherAgent.createSession/start/
68
+ // getOrCreateSession/stream). An unregistered session with a known ID is either:
69
+ // (a) an orphaned sub-session whose record was cleaned by cleanupMapRun, or
70
+ // (b) a session created outside the registered paths (unexpected).
71
+ // Both cases are rejected regardless of read_only.
72
+ if (context?.sessionId && callerRecord === undefined) {
73
+ throw new Error('agentic_map: session has no nesting context. ' +
74
+ 'Session may be orphaned (post-cleanup timeout race) or created outside ' +
75
+ 'CipherAgent.createSession()/start(). Aborting to preserve ancestor invariants.');
76
+ }
77
+ // [Guard D] Prevent write escalation from query context.
78
+ // Sub-session commandType is derived from params.read_only, not from caller commandType.
79
+ // Without this guard, a query session could pass read_only=false and spawn curate
80
+ // children regardless of whether agentic_map is in the query allowlist.
81
+ if (params.read_only === false && context?.commandType === 'query') {
82
+ throw new Error('agentic_map: read_only=false is not permitted from a query context. ' +
83
+ 'Query sessions are restricted to read-only operations.');
84
+ }
85
+ // Three-way nesting branch
86
+ let nestingDepth;
87
+ let effectiveMaxDepth;
88
+ let mapRunId;
89
+ let ancestorInputPaths;
90
+ if (callerRecord !== undefined && !callerRecord.isRootCaller) {
91
+ // ── Sub-session path ──────────────────────────────────────────────
92
+ // callerRecord was set by processItem in a write-enabled parent run.
93
+ // LLM cannot override inherited depth limit.
94
+ nestingDepth = callerRecord.nestingDepth;
95
+ effectiveMaxDepth = callerRecord.absoluteMaxDepth;
96
+ mapRunId = callerRecord.mapRunId;
97
+ ancestorInputPaths = callerRecord.ancestorInputPaths;
98
+ }
99
+ else {
100
+ // ── Root path ─────────────────────────────────────────────────────
101
+ // callerRecord.isRootCaller === true (pre-registered by CipherAgent.start/createSession)
102
+ // OR no sessionId (read_only=true direct invocation — structurally unreachable via ToolManager)
103
+ nestingDepth = 0;
104
+ effectiveMaxDepth = Math.min(params.max_depth ?? 1, HARD_MAX_DEPTH);
105
+ mapRunId = randomUUID();
106
+ ancestorInputPaths = new Set();
107
+ }
108
+ // ContextTreeStore construction — UNCHANGED from today
109
+ const contextTreeStore = options?.generator && options?.tokenizer
110
+ ? new ContextTreeStore({
111
+ generator: options.generator,
112
+ tauHard: Math.floor((options.maxContextTokens ?? 100_000) * 0.5),
113
+ tokenizer: options.tokenizer,
114
+ })
115
+ : undefined;
116
+ const result = await _executeAgenticMap({
117
+ abortSignal: context?.signal,
118
+ agent,
119
+ ancestorInputPaths,
120
+ contextTreeStore,
121
+ effectiveMaxDepth,
122
+ logger: options?.logger,
123
+ mapRunId,
124
+ nestingDepth,
125
+ onProgress: context?.metadata
126
+ ? (progress) => {
127
+ context.metadata({
128
+ description: `Processing items: ${progress.succeeded + progress.failed}/${progress.total}`,
129
+ progress: Math.round(((progress.succeeded + progress.failed) / Math.max(progress.total, 1)) * 100),
130
+ });
131
+ }
132
+ : undefined,
133
+ params,
134
+ taskId: context?.taskId,
135
+ workingDirectory,
136
+ });
137
+ return {
138
+ failed: result.failed,
139
+ mapId: result.mapId,
140
+ outputPath: params.output_path,
141
+ succeeded: result.succeeded,
142
+ ...(result.summaryHandle && { summaryHandle: result.summaryHandle }),
143
+ total: result.total,
144
+ };
145
+ },
146
+ getMetadata(args) {
147
+ return {
148
+ affectedLocations: [args.output_path],
149
+ category: 'execute',
150
+ riskLevel: 'medium',
151
+ };
152
+ },
153
+ id: 'agentic_map',
154
+ inputSchema: AgenticMapParametersSchema,
155
+ };
156
+ }
@@ -79,6 +79,7 @@ export function createCodeExecTool(sandboxService) {
79
79
  : context?.commandType === 'query' ? 8000
80
80
  : undefined;
81
81
  const result = await sandboxService.executeCode(code, sessionId, {
82
+ commandType: context?.commandType,
82
83
  contextPayload,
83
84
  language,
84
85
  maxStdoutChars,
@@ -124,13 +124,13 @@ export declare const CurateInputSchema: z.ZodObject<{
124
124
  }, "strip", z.ZodTypeAny, {
125
125
  tags: string[];
126
126
  keywords: string[];
127
- relations?: string[] | undefined;
128
127
  facts?: {
129
128
  statement: string;
130
129
  value?: string | undefined;
131
130
  subject?: string | undefined;
132
131
  category?: "environment" | "convention" | "other" | "personal" | "preference" | "project" | "team" | undefined;
133
132
  }[] | undefined;
133
+ relations?: string[] | undefined;
134
134
  narrative?: {
135
135
  structure?: string | undefined;
136
136
  dependencies?: string | undefined;
@@ -159,14 +159,14 @@ export declare const CurateInputSchema: z.ZodObject<{
159
159
  snippets?: string[] | undefined;
160
160
  }, {
161
161
  tags?: string[] | undefined;
162
- keywords?: string[] | undefined;
163
- relations?: string[] | undefined;
164
162
  facts?: {
165
163
  statement: string;
166
164
  value?: string | undefined;
167
165
  subject?: string | undefined;
168
166
  category?: "environment" | "convention" | "other" | "personal" | "preference" | "project" | "team" | undefined;
169
167
  }[] | undefined;
168
+ keywords?: string[] | undefined;
169
+ relations?: string[] | undefined;
170
170
  narrative?: {
171
171
  structure?: string | undefined;
172
172
  dependencies?: string | undefined;
@@ -262,13 +262,13 @@ export declare const CurateInputSchema: z.ZodObject<{
262
262
  content?: {
263
263
  tags: string[];
264
264
  keywords: string[];
265
- relations?: string[] | undefined;
266
265
  facts?: {
267
266
  statement: string;
268
267
  value?: string | undefined;
269
268
  subject?: string | undefined;
270
269
  category?: "environment" | "convention" | "other" | "personal" | "preference" | "project" | "team" | undefined;
271
270
  }[] | undefined;
271
+ relations?: string[] | undefined;
272
272
  narrative?: {
273
273
  structure?: string | undefined;
274
274
  dependencies?: string | undefined;
@@ -323,14 +323,14 @@ export declare const CurateInputSchema: z.ZodObject<{
323
323
  title?: string | undefined;
324
324
  content?: {
325
325
  tags?: string[] | undefined;
326
- keywords?: string[] | undefined;
327
- relations?: string[] | undefined;
328
326
  facts?: {
329
327
  statement: string;
330
328
  value?: string | undefined;
331
329
  subject?: string | undefined;
332
330
  category?: "environment" | "convention" | "other" | "personal" | "preference" | "project" | "team" | undefined;
333
331
  }[] | undefined;
332
+ keywords?: string[] | undefined;
333
+ relations?: string[] | undefined;
334
334
  narrative?: {
335
335
  structure?: string | undefined;
336
336
  dependencies?: string | undefined;
@@ -389,13 +389,13 @@ export declare const CurateInputSchema: z.ZodObject<{
389
389
  content?: {
390
390
  tags: string[];
391
391
  keywords: string[];
392
- relations?: string[] | undefined;
393
392
  facts?: {
394
393
  statement: string;
395
394
  value?: string | undefined;
396
395
  subject?: string | undefined;
397
396
  category?: "environment" | "convention" | "other" | "personal" | "preference" | "project" | "team" | undefined;
398
397
  }[] | undefined;
398
+ relations?: string[] | undefined;
399
399
  narrative?: {
400
400
  structure?: string | undefined;
401
401
  dependencies?: string | undefined;
@@ -452,14 +452,14 @@ export declare const CurateInputSchema: z.ZodObject<{
452
452
  title?: string | undefined;
453
453
  content?: {
454
454
  tags?: string[] | undefined;
455
- keywords?: string[] | undefined;
456
- relations?: string[] | undefined;
457
455
  facts?: {
458
456
  statement: string;
459
457
  value?: string | undefined;
460
458
  subject?: string | undefined;
461
459
  category?: "environment" | "convention" | "other" | "personal" | "preference" | "project" | "team" | undefined;
462
460
  }[] | undefined;
461
+ keywords?: string[] | undefined;
462
+ relations?: string[] | undefined;
463
463
  narrative?: {
464
464
  structure?: string | undefined;
465
465
  dependencies?: string | undefined;
@@ -0,0 +1,18 @@
1
+ import type { Tool } from '../../../core/domain/tools/types.js';
2
+ /**
3
+ * Configuration for expand knowledge tool.
4
+ */
5
+ export interface ExpandKnowledgeToolConfig {
6
+ baseDirectory?: string;
7
+ }
8
+ /**
9
+ * Creates the expand knowledge tool.
10
+ *
11
+ * Retrieves full content from archived knowledge entries by reading the
12
+ * lossless .full.md file that the stub points to. No LLM call needed —
13
+ * purely file-based lookup.
14
+ *
15
+ * @param config - Optional configuration
16
+ * @returns Configured expand knowledge tool
17
+ */
18
+ export declare function createExpandKnowledgeTool(config?: ExpandKnowledgeToolConfig): Tool;
@@ -0,0 +1,43 @@
1
+ import { z } from 'zod';
2
+ import { FileContextTreeArchiveService } from '../../../../server/infra/context-tree/file-context-tree-archive-service.js';
3
+ import { ToolName } from '../../../core/domain/tools/constants.js';
4
+ /**
5
+ * Input schema for expand knowledge tool.
6
+ */
7
+ const ExpandKnowledgeInputSchema = z
8
+ .object({
9
+ stubPath: z
10
+ .string()
11
+ .min(1)
12
+ .describe('Path to the .stub.md file in _archived/. ' +
13
+ 'This is the `path` field from search results where symbolKind === "archive_stub".'),
14
+ })
15
+ .strict();
16
+ /**
17
+ * Creates the expand knowledge tool.
18
+ *
19
+ * Retrieves full content from archived knowledge entries by reading the
20
+ * lossless .full.md file that the stub points to. No LLM call needed —
21
+ * purely file-based lookup.
22
+ *
23
+ * @param config - Optional configuration
24
+ * @returns Configured expand knowledge tool
25
+ */
26
+ export function createExpandKnowledgeTool(config = {}) {
27
+ const archiveService = new FileContextTreeArchiveService();
28
+ return {
29
+ description: 'Retrieve full content from archived knowledge entries. ' +
30
+ 'Use when search results include an archive_stub that you need to drill into.',
31
+ async execute(input, _context) {
32
+ const parsed = ExpandKnowledgeInputSchema.parse(input);
33
+ const result = await archiveService.drillDown(parsed.stubPath, config.baseDirectory);
34
+ return {
35
+ fullContent: result.fullContent,
36
+ originalPath: result.originalPath,
37
+ tokenCount: result.tokenCount,
38
+ };
39
+ },
40
+ id: ToolName.EXPAND_KNOWLEDGE,
41
+ inputSchema: ExpandKnowledgeInputSchema,
42
+ };
43
+ }
@@ -0,0 +1,24 @@
1
+ import type { Tool } from '../../../core/domain/tools/types.js';
2
+ import type { IContentGenerator } from '../../../core/interfaces/i-content-generator.js';
3
+ import type { ILogger } from '../../../core/interfaces/i-logger.js';
4
+ import type { ITokenizer } from '../../../core/interfaces/i-tokenizer.js';
5
+ /**
6
+ * Create the llm_map tool.
7
+ *
8
+ * Runs a parallel, non-agentic map over a JSONL file. For each item (line),
9
+ * makes a single LLM API call (no tools, no file I/O, no code execution)
10
+ * that must return one JSON value conforming to the provided output schema.
11
+ *
12
+ * Best for high-throughput, side-effect-free tasks (classification, scoring,
13
+ * extraction, summarization) where the full context can be included in the
14
+ * prompt and item JSON.
15
+ *
16
+ * @param generator - IContentGenerator for LLM calls
17
+ * @param workingDirectory - Project root directory
18
+ * @param options - Optional dependencies for ContextTreeStore
19
+ */
20
+ export declare function createLlmMapTool(generator: IContentGenerator, workingDirectory: string, options?: {
21
+ logger?: ILogger;
22
+ maxContextTokens?: number;
23
+ tokenizer?: ITokenizer;
24
+ }): Tool;
@@ -0,0 +1,87 @@
1
+ import { ContextTreeStore } from '../../map/context-tree-store.js';
2
+ import { executeLlmMap } from '../../map/llm-map-service.js';
3
+ import { LlmMapParametersSchema } from '../../map/map-shared.js';
4
+ /**
5
+ * Create the llm_map tool.
6
+ *
7
+ * Runs a parallel, non-agentic map over a JSONL file. For each item (line),
8
+ * makes a single LLM API call (no tools, no file I/O, no code execution)
9
+ * that must return one JSON value conforming to the provided output schema.
10
+ *
11
+ * Best for high-throughput, side-effect-free tasks (classification, scoring,
12
+ * extraction, summarization) where the full context can be included in the
13
+ * prompt and item JSON.
14
+ *
15
+ * @param generator - IContentGenerator for LLM calls
16
+ * @param workingDirectory - Project root directory
17
+ * @param options - Optional dependencies for ContextTreeStore
18
+ */
19
+ export function createLlmMapTool(generator, workingDirectory, options) {
20
+ return {
21
+ description: [
22
+ 'Run a parallel, non-agentic map over a JSONL file.',
23
+ 'For each item (line), make a single LLM API call (no tools, no file I/O)',
24
+ 'that must return one JSON value conforming to the provided output schema.',
25
+ '',
26
+ 'Best for high-throughput, side-effect-free tasks:',
27
+ '- Classification and scoring',
28
+ '- Data extraction and transformation',
29
+ '- Summarization',
30
+ '- Content analysis',
31
+ '',
32
+ 'Each item is processed in complete isolation — the LLM cannot see other items.',
33
+ 'If per-item processing requires file reads or tool access, use agentic_map instead.',
34
+ '',
35
+ 'Input: JSONL file (one JSON object per line)',
36
+ 'Output: JSONL file with one result per line, ordered by input line.',
37
+ '',
38
+ 'Results include an optional summaryHandle — a compact summary of processed items.',
39
+ 'The JSONL output file is always the source of truth for per-item results.',
40
+ ].join('\n'),
41
+ async execute(input, context) {
42
+ const params = LlmMapParametersSchema.parse(input);
43
+ // Construct ContextTreeStore if tokenizer available
44
+ const contextTreeStore = options?.tokenizer
45
+ ? new ContextTreeStore({
46
+ generator,
47
+ tauHard: Math.floor((options.maxContextTokens ?? 100_000) * 0.5),
48
+ tokenizer: options.tokenizer,
49
+ })
50
+ : undefined;
51
+ const result = await executeLlmMap({
52
+ abortSignal: context?.signal,
53
+ contextTreeStore,
54
+ generator,
55
+ logger: options?.logger,
56
+ onProgress: context?.metadata
57
+ ? (progress) => {
58
+ context.metadata({
59
+ description: `Processing items: ${progress.succeeded + progress.failed}/${progress.total} (${progress.succeeded} ok, ${progress.failed} failed)`,
60
+ progress: Math.round(((progress.succeeded + progress.failed) / Math.max(progress.total, 1)) * 100),
61
+ });
62
+ }
63
+ : undefined,
64
+ params,
65
+ taskId: context?.taskId,
66
+ workingDirectory,
67
+ });
68
+ return {
69
+ failed: result.failed,
70
+ mapId: result.mapId,
71
+ outputPath: params.output_path,
72
+ succeeded: result.succeeded,
73
+ ...(result.summaryHandle && { summaryHandle: result.summaryHandle }),
74
+ total: result.total,
75
+ };
76
+ },
77
+ getMetadata(args) {
78
+ return {
79
+ affectedLocations: [args.output_path],
80
+ category: 'execute',
81
+ riskLevel: 'low',
82
+ };
83
+ },
84
+ id: 'llm_map',
85
+ inputSchema: LlmMapParametersSchema,
86
+ };
87
+ }
@@ -7,8 +7,16 @@ export declare enum MemorySymbolKind {
7
7
  Context = 4,
8
8
  Domain = 1,
9
9
  Subtopic = 3,
10
+ Summary = 5,
10
11
  Topic = 2
11
12
  }
13
+ /**
14
+ * Summary metadata attached to folder nodes that have an _index.md file.
15
+ */
16
+ export interface SummaryInfo {
17
+ condensationOrder: number;
18
+ tokenCount: number;
19
+ }
12
20
  /**
13
21
  * A node in the memory symbol tree.
14
22
  * Represents a domain, topic, subtopic, or individual context entry.
@@ -21,6 +29,8 @@ export interface MemorySymbol {
21
29
  parent: MemorySymbol | undefined;
22
30
  /** Relative path within context-tree, e.g. "auth/jwt-tokens/refresh.md" */
23
31
  path: string;
32
+ /** Present when this folder has an _index.md summary */
33
+ summaryInfo?: SummaryInfo;
24
34
  }
25
35
  export interface SymbolMetadata {
26
36
  importance: number;
@@ -28,6 +38,16 @@ export interface SymbolMetadata {
28
38
  maturity: string;
29
39
  tags: string[];
30
40
  }
41
+ /**
42
+ * Minimal summary document shape for attaching summary info to folder nodes.
43
+ * Built from _index.md files during search indexing.
44
+ */
45
+ export interface SummaryDocLike {
46
+ condensationOrder: number;
47
+ /** Path to the _index.md file, e.g. "domain/topic/_index.md" */
48
+ path: string;
49
+ tokenCount: number;
50
+ }
31
51
  /**
32
52
  * The complete memory symbol tree, built from the context-tree filesystem.
33
53
  */
@@ -42,11 +62,15 @@ export interface MemorySymbolTree {
42
62
  */
43
63
  export interface OverviewEntry {
44
64
  childCount: number;
65
+ /** Present for folder nodes with _index.md summaries */
66
+ condensationOrder?: number;
45
67
  importance: number;
46
68
  kind: string;
47
69
  maturity: string;
48
70
  name: string;
49
71
  path: string;
72
+ /** Present for folder nodes with _index.md summaries */
73
+ tokenCount?: number;
50
74
  }
51
75
  /**
52
76
  * Bidirectional reference index built from @relation annotations.
@@ -74,8 +98,11 @@ interface DocumentLike {
74
98
  *
75
99
  * context.md files are absorbed into their parent folder node (enriching its metadata)
76
100
  * rather than being treated as leaf Context nodes.
101
+ *
102
+ * @param documentMap - Indexed documents (excludes _index.md, includes stubs)
103
+ * @param summaryMap - Optional map of _index.md summary documents for folder annotation
77
104
  */
78
- export declare function buildSymbolTree(documentMap: Map<string, DocumentLike>): MemorySymbolTree;
105
+ export declare function buildSymbolTree(documentMap: Map<string, DocumentLike>, summaryMap?: Map<string, SummaryDocLike>): MemorySymbolTree;
79
106
  /**
80
107
  * Get a structural overview of the symbol tree at configurable depth.
81
108
  *