byterover-cli 3.2.0 → 3.4.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 (127) hide show
  1. package/.env.production +0 -4
  2. package/dist/agent/core/domain/swarm/types.d.ts +132 -0
  3. package/dist/agent/core/domain/swarm/types.js +128 -0
  4. package/dist/agent/core/domain/tools/constants.d.ts +2 -0
  5. package/dist/agent/core/domain/tools/constants.js +2 -0
  6. package/dist/agent/core/interfaces/i-memory-provider.d.ts +45 -0
  7. package/dist/agent/core/interfaces/i-memory-provider.js +1 -0
  8. package/dist/agent/core/interfaces/i-sandbox-service.d.ts +8 -0
  9. package/dist/agent/core/interfaces/i-swarm-coordinator.d.ts +127 -0
  10. package/dist/agent/core/interfaces/i-swarm-coordinator.js +1 -0
  11. package/dist/agent/infra/agent/service-initializer.js +48 -0
  12. package/dist/agent/infra/map/map-shared.d.ts +2 -2
  13. package/dist/agent/infra/sandbox/sandbox-service.d.ts +10 -0
  14. package/dist/agent/infra/sandbox/sandbox-service.js +13 -0
  15. package/dist/agent/infra/sandbox/tools-sdk.d.ts +25 -0
  16. package/dist/agent/infra/sandbox/tools-sdk.js +24 -1
  17. package/dist/agent/infra/swarm/adapters/byterover-adapter.d.ts +39 -0
  18. package/dist/agent/infra/swarm/adapters/byterover-adapter.js +62 -0
  19. package/dist/agent/infra/swarm/adapters/gbrain-adapter.d.ts +63 -0
  20. package/dist/agent/infra/swarm/adapters/gbrain-adapter.js +209 -0
  21. package/dist/agent/infra/swarm/adapters/local-markdown-adapter.d.ts +41 -0
  22. package/dist/agent/infra/swarm/adapters/local-markdown-adapter.js +256 -0
  23. package/dist/agent/infra/swarm/adapters/memory-wiki-adapter.d.ts +29 -0
  24. package/dist/agent/infra/swarm/adapters/memory-wiki-adapter.js +244 -0
  25. package/dist/agent/infra/swarm/adapters/obsidian-adapter.d.ts +37 -0
  26. package/dist/agent/infra/swarm/adapters/obsidian-adapter.js +201 -0
  27. package/dist/agent/infra/swarm/cli/query-renderer.d.ts +15 -0
  28. package/dist/agent/infra/swarm/cli/query-renderer.js +126 -0
  29. package/dist/agent/infra/swarm/config/swarm-config-loader.d.ts +14 -0
  30. package/dist/agent/infra/swarm/config/swarm-config-loader.js +82 -0
  31. package/dist/agent/infra/swarm/config/swarm-config-schema.d.ts +667 -0
  32. package/dist/agent/infra/swarm/config/swarm-config-schema.js +305 -0
  33. package/dist/agent/infra/swarm/provider-factory.d.ts +21 -0
  34. package/dist/agent/infra/swarm/provider-factory.js +67 -0
  35. package/dist/agent/infra/swarm/search-precision.d.ts +95 -0
  36. package/dist/agent/infra/swarm/search-precision.js +141 -0
  37. package/dist/agent/infra/swarm/swarm-coordinator.d.ts +59 -0
  38. package/dist/agent/infra/swarm/swarm-coordinator.js +436 -0
  39. package/dist/agent/infra/swarm/swarm-graph.d.ts +63 -0
  40. package/dist/agent/infra/swarm/swarm-graph.js +167 -0
  41. package/dist/agent/infra/swarm/swarm-merger.d.ts +29 -0
  42. package/dist/agent/infra/swarm/swarm-merger.js +66 -0
  43. package/dist/agent/infra/swarm/swarm-router.d.ts +12 -0
  44. package/dist/agent/infra/swarm/swarm-router.js +40 -0
  45. package/dist/agent/infra/swarm/swarm-write-router.d.ts +23 -0
  46. package/dist/agent/infra/swarm/swarm-write-router.js +45 -0
  47. package/dist/agent/infra/swarm/validation/config-validator.d.ts +16 -0
  48. package/dist/agent/infra/swarm/validation/config-validator.js +402 -0
  49. package/dist/agent/infra/swarm/validation/memory-swarm-validation-error.d.ts +33 -0
  50. package/dist/agent/infra/swarm/validation/memory-swarm-validation-error.js +27 -0
  51. package/dist/agent/infra/swarm/wizard/config-scaffolder.d.ts +36 -0
  52. package/dist/agent/infra/swarm/wizard/config-scaffolder.js +96 -0
  53. package/dist/agent/infra/swarm/wizard/provider-detector.d.ts +54 -0
  54. package/dist/agent/infra/swarm/wizard/provider-detector.js +153 -0
  55. package/dist/agent/infra/swarm/wizard/swarm-wizard.d.ts +61 -0
  56. package/dist/agent/infra/swarm/wizard/swarm-wizard.js +187 -0
  57. package/dist/agent/infra/system-prompt/contributors/index.d.ts +1 -0
  58. package/dist/agent/infra/system-prompt/contributors/index.js +1 -0
  59. package/dist/agent/infra/system-prompt/contributors/swarm-state-contributor.d.ts +15 -0
  60. package/dist/agent/infra/system-prompt/contributors/swarm-state-contributor.js +65 -0
  61. package/dist/agent/infra/tools/implementations/curate-tool.d.ts +14 -14
  62. package/dist/agent/infra/tools/implementations/curate-tool.js +2 -0
  63. package/dist/agent/infra/tools/implementations/search-knowledge-service.js +12 -2
  64. package/dist/agent/infra/tools/implementations/swarm-query-tool.d.ts +9 -0
  65. package/dist/agent/infra/tools/implementations/swarm-query-tool.js +44 -0
  66. package/dist/agent/infra/tools/implementations/swarm-store-tool.d.ts +9 -0
  67. package/dist/agent/infra/tools/implementations/swarm-store-tool.js +43 -0
  68. package/dist/agent/infra/tools/tool-provider.js +1 -0
  69. package/dist/agent/infra/tools/tool-registry.d.ts +3 -0
  70. package/dist/agent/infra/tools/tool-registry.js +25 -1
  71. package/dist/agent/resources/tools/code_exec.txt +2 -0
  72. package/dist/agent/resources/tools/swarm_query.txt +38 -0
  73. package/dist/agent/resources/tools/swarm_store.txt +35 -0
  74. package/dist/oclif/commands/curate/index.d.ts +1 -0
  75. package/dist/oclif/commands/curate/index.js +15 -1
  76. package/dist/oclif/commands/query.d.ts +1 -0
  77. package/dist/oclif/commands/query.js +17 -3
  78. package/dist/oclif/commands/search.d.ts +20 -0
  79. package/dist/oclif/commands/search.js +186 -0
  80. package/dist/oclif/commands/status.js +4 -0
  81. package/dist/oclif/commands/swarm/curate.d.ts +13 -0
  82. package/dist/oclif/commands/swarm/curate.js +81 -0
  83. package/dist/oclif/commands/swarm/onboard.d.ts +6 -0
  84. package/dist/oclif/commands/swarm/onboard.js +233 -0
  85. package/dist/oclif/commands/swarm/query.d.ts +14 -0
  86. package/dist/oclif/commands/swarm/query.js +84 -0
  87. package/dist/oclif/commands/swarm/status.d.ts +41 -0
  88. package/dist/oclif/commands/swarm/status.js +278 -0
  89. package/dist/oclif/lib/daemon-client.js +0 -1
  90. package/dist/oclif/lib/search-format.d.ts +10 -0
  91. package/dist/oclif/lib/search-format.js +25 -0
  92. package/dist/oclif/lib/task-client.d.ts +6 -0
  93. package/dist/oclif/lib/task-client.js +10 -3
  94. package/dist/server/constants.d.ts +3 -2
  95. package/dist/server/constants.js +10 -7
  96. package/dist/server/core/domain/errors/task-error.d.ts +2 -2
  97. package/dist/server/core/domain/errors/task-error.js +5 -4
  98. package/dist/server/core/domain/source/source-schema.d.ts +6 -6
  99. package/dist/server/core/domain/transport/schemas.d.ts +14 -14
  100. package/dist/server/core/domain/transport/schemas.js +3 -3
  101. package/dist/server/core/interfaces/executor/i-search-executor.d.ts +34 -0
  102. package/dist/server/core/interfaces/executor/i-search-executor.js +1 -0
  103. package/dist/server/core/interfaces/executor/index.d.ts +1 -0
  104. package/dist/server/core/interfaces/executor/index.js +1 -0
  105. package/dist/server/infra/daemon/agent-process.js +20 -7
  106. package/dist/server/infra/executor/search-executor.d.ts +17 -0
  107. package/dist/server/infra/executor/search-executor.js +30 -0
  108. package/dist/server/infra/http/provider-model-fetchers.js +1 -0
  109. package/dist/server/infra/process/feature-handlers.js +13 -0
  110. package/dist/server/infra/project/project-registry.js +13 -1
  111. package/dist/server/infra/transport/handlers/locations-handler.d.ts +2 -0
  112. package/dist/server/infra/transport/handlers/locations-handler.js +16 -1
  113. package/dist/server/infra/transport/handlers/pull-handler.js +3 -3
  114. package/dist/server/infra/transport/handlers/push-handler.js +3 -3
  115. package/dist/server/infra/transport/handlers/status-handler.js +25 -18
  116. package/dist/server/infra/transport/handlers/vc-handler.d.ts +0 -4
  117. package/dist/server/infra/transport/handlers/vc-handler.js +5 -16
  118. package/dist/server/templates/skill/SKILL.md +188 -5
  119. package/dist/server/utils/gitignore.d.ts +1 -0
  120. package/dist/server/utils/gitignore.js +36 -4
  121. package/dist/shared/transport/search-content.d.ts +28 -0
  122. package/dist/shared/transport/search-content.js +38 -0
  123. package/dist/shared/transport/types/dto.d.ts +1 -1
  124. package/dist/tui/features/status/utils/format-status.js +5 -0
  125. package/dist/tui/utils/error-messages.js +2 -2
  126. package/oclif.manifest.json +581 -317
  127. package/package.json +2 -2
@@ -0,0 +1,278 @@
1
+ import { Command, Flags } from '@oclif/core';
2
+ import chalk from 'chalk';
3
+ import { loadSwarmConfig } from '../../../agent/infra/swarm/config/swarm-config-loader.js';
4
+ import { validateSwarmProviders } from '../../../agent/infra/swarm/validation/config-validator.js';
5
+ import { detectProviders } from '../../../agent/infra/swarm/wizard/provider-detector.js';
6
+ /**
7
+ * Format enrichment edges for display.
8
+ */
9
+ export function formatEnrichmentEdges(edges) {
10
+ return edges.map((e) => `${e.from} → ${e.to}`);
11
+ }
12
+ /**
13
+ * Collect configured paths for path-based providers so we can detect
14
+ * newly discovered paths that aren't in the config yet.
15
+ */
16
+ export function getConfiguredSwarmPaths(config) {
17
+ const paths = new Set();
18
+ const { providers } = config;
19
+ if (providers.obsidian?.vaultPath) {
20
+ paths.add(providers.obsidian.vaultPath);
21
+ }
22
+ if (providers.localMarkdown?.folders) {
23
+ for (const folder of providers.localMarkdown.folders) {
24
+ paths.add(folder.path);
25
+ }
26
+ }
27
+ // GBrain: repoPath is the brain data repo, not the detected CLI checkout path — do not add here.
28
+ return paths;
29
+ }
30
+ /**
31
+ * Build user-facing suggestions for detected providers that are not yet configured.
32
+ */
33
+ export function findSwarmStatusSuggestions(config, detected) {
34
+ const suggestions = [];
35
+ const configuredPaths = getConfiguredSwarmPaths(config);
36
+ for (const provider of detected) {
37
+ if (!provider.detected)
38
+ continue;
39
+ if (provider.id === 'byterover')
40
+ continue;
41
+ // GBrain: `provider.path` is the CLI/source checkout; config uses `repoPath` for brain data — never compare.
42
+ if (provider.id === 'gbrain') {
43
+ if (!config.providers.gbrain) {
44
+ const detail = provider.path ? ` at ${provider.path}` : '';
45
+ suggestions.push(`Found gbrain${detail} — not in config. Run \`brv swarm onboard\` to add it.`);
46
+ }
47
+ continue;
48
+ }
49
+ if (provider.path) {
50
+ if (!configuredPaths.has(provider.path)) {
51
+ suggestions.push(`Found ${provider.id} at ${provider.path} — not in config. Run \`brv swarm onboard\` to add it.`);
52
+ }
53
+ continue;
54
+ }
55
+ const providerKey = provider.id === 'local-markdown' ? 'localMarkdown' : provider.id;
56
+ const configured = config.providers[providerKey];
57
+ if (!configured) {
58
+ const detail = provider.envVar ? `(${provider.envVar} is set)` : '';
59
+ suggestions.push(`Found ${provider.id} ${detail} — not in config. Run \`brv swarm onboard\` to add it.`);
60
+ }
61
+ }
62
+ return suggestions;
63
+ }
64
+ export default class SwarmStatus extends Command {
65
+ static description = 'Show memory swarm provider health and connection status';
66
+ static examples = [
67
+ '<%= config.bin %> swarm status',
68
+ '<%= config.bin %> swarm status --format json',
69
+ ];
70
+ static flags = {
71
+ format: Flags.string({
72
+ char: 'f',
73
+ default: 'text',
74
+ description: 'Output format',
75
+ options: ['text', 'json'],
76
+ }),
77
+ };
78
+ async run() {
79
+ const { flags } = await this.parse(SwarmStatus);
80
+ const isJson = flags.format === 'json';
81
+ try {
82
+ // Load config
83
+ const config = await loadSwarmConfig(process.cwd());
84
+ // Run runtime validation
85
+ const validation = await validateSwarmProviders(config);
86
+ // Detect unconfigured providers (proactive suggestions)
87
+ const detected = await detectProviders();
88
+ const suggestions = findSwarmStatusSuggestions(config, detected);
89
+ if (isJson) {
90
+ this.logJson({
91
+ config: {
92
+ enrichment: { edges: config.enrichment?.edges ?? [] },
93
+ providers: Object.keys(config.providers).filter((k) => config.providers[k]?.enabled),
94
+ },
95
+ errors: validation.errors,
96
+ suggestions,
97
+ warnings: validation.warnings,
98
+ });
99
+ }
100
+ else {
101
+ this.renderTextOutput(config, validation, suggestions);
102
+ }
103
+ }
104
+ catch (error) {
105
+ if (isJson) {
106
+ this.logJson({ error: error.message, success: false });
107
+ }
108
+ else {
109
+ this.log(chalk.red(error.message));
110
+ }
111
+ }
112
+ }
113
+ findSuggestions(config, detected) {
114
+ return findSwarmStatusSuggestions(config, detected);
115
+ }
116
+ renderCascadeNote(validation) {
117
+ if (!validation.cascadeNote)
118
+ return;
119
+ this.log(`\n${chalk.dim('Note:')} ${validation.cascadeNote}`);
120
+ }
121
+ renderEnrichmentTopology(config) {
122
+ const edges = config.enrichment?.edges ?? [];
123
+ if (edges.length === 0)
124
+ return;
125
+ const lines = formatEnrichmentEdges(edges);
126
+ this.log(`\n${chalk.cyan('Enrichment Topology')}:`);
127
+ for (const line of lines) {
128
+ this.log(` ${line}`);
129
+ }
130
+ }
131
+ renderProviderLine(name, ok, detail, status) {
132
+ if (status === 'disabled') {
133
+ this.log(` ${chalk.dim('—')} ${name.padEnd(15)} ${chalk.dim(detail)}`);
134
+ }
135
+ else if (status === 'warning') {
136
+ this.log(` ${chalk.yellow('⚠')} ${name.padEnd(15)} ${detail}`);
137
+ }
138
+ else if (ok) {
139
+ this.log(` ${chalk.green('✓')} ${name.padEnd(15)} ${detail}`);
140
+ }
141
+ else {
142
+ this.log(` ${chalk.red('✗')} ${name.padEnd(15)} ${detail}`);
143
+ }
144
+ }
145
+ renderProviderStatusLines(config, validation) {
146
+ const { providers } = config;
147
+ this.renderProviderLine('ByteRover', providers.byterover.enabled, 'context-tree (always on)');
148
+ if (providers.obsidian) {
149
+ const hasError = validation.errors.some((e) => e.provider === 'obsidian');
150
+ const hasWarning = validation.warnings.some((w) => w.provider === 'obsidian');
151
+ this.renderProviderLine('Obsidian', providers.obsidian.enabled && !hasError, providers.obsidian.vaultPath, hasWarning ? 'warning' : undefined);
152
+ }
153
+ else {
154
+ this.renderProviderLine('Obsidian', false, 'not configured', 'disabled');
155
+ }
156
+ if (providers.localMarkdown) {
157
+ const hasError = validation.errors.some((e) => e.provider === 'local-markdown');
158
+ const folderCount = providers.localMarkdown.folders.length;
159
+ this.renderProviderLine('Local .md', providers.localMarkdown.enabled && !hasError, `${folderCount} folder(s)`);
160
+ }
161
+ else {
162
+ this.renderProviderLine('Local .md', false, 'not configured', 'disabled');
163
+ }
164
+ // Honcho and Hindsight temporarily disabled — adapters coming in Phase 3.
165
+ // When re-enabled, uncomment these blocks:
166
+ // if (providers.honcho) {
167
+ // const hasError = validation.errors.some((e) => e.provider === 'honcho')
168
+ // this.renderProviderLine('Honcho', providers.honcho.enabled && !hasError, 'cloud API')
169
+ // } else {
170
+ // this.renderProviderLine('Honcho', false, 'not configured', 'disabled')
171
+ // }
172
+ // if (providers.hindsight) {
173
+ // const hasError = validation.errors.some((e) => e.provider === 'hindsight')
174
+ // this.renderProviderLine('Hindsight', providers.hindsight.enabled && !hasError, 'Postgres')
175
+ // } else {
176
+ // this.renderProviderLine('Hindsight', false, 'not configured', 'disabled')
177
+ // }
178
+ if (providers.gbrain) {
179
+ const hasError = validation.errors.some((e) => e.provider === 'gbrain');
180
+ this.renderProviderLine('GBrain', providers.gbrain.enabled && !hasError, providers.gbrain.repoPath);
181
+ }
182
+ else {
183
+ this.renderProviderLine('GBrain', false, 'not configured', 'disabled');
184
+ }
185
+ if (providers.memoryWiki) {
186
+ const hasError = validation.errors.some((e) => e.provider === 'memory-wiki');
187
+ this.renderProviderLine('Memory Wiki', providers.memoryWiki.enabled && !hasError, providers.memoryWiki.vaultPath);
188
+ }
189
+ else {
190
+ this.renderProviderLine('Memory Wiki', false, 'not configured', 'disabled');
191
+ }
192
+ }
193
+ renderSuggestionLines(suggestions) {
194
+ if (suggestions.length === 0)
195
+ return;
196
+ this.log(`\n${chalk.cyan('Suggestions')}:`);
197
+ for (const suggestion of suggestions) {
198
+ this.log(` • ${suggestion}`);
199
+ }
200
+ }
201
+ renderSwarmSummary(config, validation) {
202
+ const { providers } = config;
203
+ const enabledCount = [
204
+ providers.byterover.enabled,
205
+ providers.obsidian?.enabled,
206
+ providers.localMarkdown?.enabled,
207
+ // Honcho and Hindsight temporarily disabled
208
+ providers.gbrain?.enabled,
209
+ providers.memoryWiki?.enabled,
210
+ ].filter(Boolean).length;
211
+ const totalProviders = [
212
+ true, // byterover always counts
213
+ providers.obsidian !== undefined,
214
+ providers.localMarkdown !== undefined,
215
+ providers.gbrain !== undefined,
216
+ providers.memoryWiki !== undefined,
217
+ ].filter(Boolean).length;
218
+ const errorCount = validation.errors.length;
219
+ const status = errorCount === 0
220
+ ? chalk.green('operational')
221
+ : chalk.yellow('degraded');
222
+ this.log(`\nSwarm is ${status} (${enabledCount}/${totalProviders} providers configured).`);
223
+ }
224
+ renderTextOutput(config, validation, suggestions) {
225
+ this.log(chalk.bold('\nMemory Swarm Health Check'));
226
+ this.log('═'.repeat(40));
227
+ this.renderProviderStatusLines(config, validation);
228
+ this.renderEnrichmentTopology(config);
229
+ this.renderWriteTargets(config);
230
+ this.renderValidationErrors(validation);
231
+ this.renderValidationWarnings(validation);
232
+ this.renderCascadeNote(validation);
233
+ this.renderSuggestionLines(suggestions);
234
+ this.renderSwarmSummary(config, validation);
235
+ }
236
+ renderValidationErrors(validation) {
237
+ if (validation.errors.length === 0)
238
+ return;
239
+ this.log(`\n${chalk.red('Errors')} (${validation.errors.length}):`);
240
+ for (const [i, error] of validation.errors.entries()) {
241
+ this.log(` ${i + 1}. ${error.provider ?? 'config'}: ${error.message}`);
242
+ if (error.suggestion) {
243
+ this.log(` ${chalk.dim(error.suggestion)}`);
244
+ }
245
+ }
246
+ }
247
+ renderValidationWarnings(validation) {
248
+ if (validation.warnings.length === 0)
249
+ return;
250
+ this.log(`\n${chalk.yellow('Warnings')} (${validation.warnings.length}):`);
251
+ for (const [i, warning] of validation.warnings.entries()) {
252
+ this.log(` ${i + 1}. ${warning.provider ?? 'config'}: ${warning.message}`);
253
+ }
254
+ }
255
+ renderWriteTargets(config) {
256
+ const { providers } = config;
257
+ const targets = [];
258
+ if (providers.gbrain?.enabled) {
259
+ targets.push('gbrain (entity, general)');
260
+ }
261
+ if (providers.localMarkdown?.enabled) {
262
+ for (const folder of providers.localMarkdown.folders) {
263
+ if (!folder.readOnly) {
264
+ targets.push(`local-markdown:${folder.name} (note, general)`);
265
+ }
266
+ }
267
+ }
268
+ if (providers.memoryWiki?.enabled) {
269
+ targets.push(`memory-wiki (${providers.memoryWiki.writePageType ?? 'concept'}, entity)`);
270
+ }
271
+ if (targets.length === 0)
272
+ return;
273
+ this.log(`\n${chalk.cyan('Write Targets')}:`);
274
+ for (const target of targets) {
275
+ this.log(` ${target}`);
276
+ }
277
+ }
278
+ }
@@ -18,7 +18,6 @@ const USER_FRIENDLY_MESSAGES = {
18
18
  [TaskErrorCode.OAUTH_TOKEN_EXPIRED]: 'OAuth token has expired. Run "brv providers connect <provider> --oauth" to reconnect.',
19
19
  [TaskErrorCode.PROJECT_NOT_INIT]: 'Project not initialized. Run "brv restart" to reinitialize.',
20
20
  [TaskErrorCode.PROVIDER_NOT_CONFIGURED]: 'No provider connected. Run "brv providers connect byterover" to use the free built-in provider, or connect another provider.',
21
- [TaskErrorCode.SPACE_NOT_CONFIGURED]: 'No space configured. Run "brv space list" to see available spaces, then "brv space switch --team <team> --name <space>" to select one.',
22
21
  [TaskErrorCode.SPACE_NOT_FOUND]: 'Space not found. Check your configuration.',
23
22
  [TaskErrorCode.VC_GIT_INITIALIZED]: 'ByteRover version control is active. Use brv vc commands instead of legacy sync commands.',
24
23
  [VcErrorCode.AUTH_FAILED]: 'Authentication failed. Run brv login.',
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Text formatting for the `brv search` CLI command.
3
+ * Pure function — no oclif, transport, or daemon dependencies.
4
+ */
5
+ import type { SearchKnowledgeResult } from '../../agent/infra/sandbox/tools-sdk.js';
6
+ /**
7
+ * Format search results for terminal display.
8
+ * Returns an array of lines (without trailing newlines).
9
+ */
10
+ export declare function formatSearchTextOutput(searchResult: SearchKnowledgeResult): string[];
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Text formatting for the `brv search` CLI command.
3
+ * Pure function — no oclif, transport, or daemon dependencies.
4
+ */
5
+ /**
6
+ * Format search results for terminal display.
7
+ * Returns an array of lines (without trailing newlines).
8
+ */
9
+ export function formatSearchTextOutput(searchResult) {
10
+ const lines = [];
11
+ if (searchResult.totalFound === 0) {
12
+ lines.push('', 'No results found.', '');
13
+ return lines;
14
+ }
15
+ const displayed = searchResult.results.length;
16
+ const total = searchResult.totalFound;
17
+ const countLabel = displayed < total ? `Showing ${displayed} of ${total} results` : `Found ${total} result${total === 1 ? '' : 's'}`;
18
+ lines.push('', `${countLabel}:`, '');
19
+ for (const [i, result] of searchResult.results.entries()) {
20
+ const scoreStr = (result.score * 100).toFixed(0);
21
+ const excerpt = result.excerpt && result.excerpt.length > 120 ? `${result.excerpt.slice(0, 117)}...` : result.excerpt;
22
+ lines.push(` ${i + 1}. ${result.title} [${scoreStr}%]`, ` Path: ${result.path}`, ...(excerpt ? [` ${excerpt}`] : []), ...(result.backlinkCount ? [` Backlinks: ${result.backlinkCount}`] : []), '');
23
+ }
24
+ return lines;
25
+ }
@@ -58,6 +58,12 @@ export interface WaitForTaskOptions {
58
58
  /** Timeout in ms (default: 5 minutes) */
59
59
  timeoutMs?: number;
60
60
  }
61
+ /** Default timeout for task completion (seconds) — shared across curate/query commands. */
62
+ export declare const DEFAULT_TIMEOUT_SECONDS = 300;
63
+ /** Minimum --timeout value accepted from the CLI (seconds). */
64
+ export declare const MIN_TIMEOUT_SECONDS = 10;
65
+ /** Maximum --timeout value accepted from the CLI (seconds). */
66
+ export declare const MAX_TIMEOUT_SECONDS = 3600;
61
67
  /**
62
68
  * Format tool call for CLI display (simplified version of TUI formatToolDisplay).
63
69
  */
@@ -4,8 +4,14 @@ import { ReviewEvents } from '../../shared/transport/events/review-events.js';
4
4
  import { writeJsonResponse } from './json-response.js';
5
5
  /** Grace period before treating 'reconnecting' as daemon death (ms) */
6
6
  const DISCONNECT_GRACE_MS = 10_000;
7
+ /** Default timeout for task completion (seconds) — shared across curate/query commands. */
8
+ export const DEFAULT_TIMEOUT_SECONDS = 300;
9
+ /** Minimum --timeout value accepted from the CLI (seconds). */
10
+ export const MIN_TIMEOUT_SECONDS = 10;
11
+ /** Maximum --timeout value accepted from the CLI (seconds). */
12
+ export const MAX_TIMEOUT_SECONDS = 3600;
7
13
  /** Default timeout for task completion (ms) */
8
- const DEFAULT_TIMEOUT_MS = 5 * 60 * 1000;
14
+ const DEFAULT_TIMEOUT_MS = DEFAULT_TIMEOUT_SECONDS * 1000;
9
15
  /**
10
16
  * Format tool call for CLI display (simplified version of TUI formatToolDisplay).
11
17
  */
@@ -70,13 +76,14 @@ export function waitForTaskCompletion(options, log) {
70
76
  if (!completed) {
71
77
  completed = true;
72
78
  cleanup();
79
+ const timeoutMessage = `Task timed out after ${timeoutMs / 1000}s`;
73
80
  if (isText) {
74
- reject(new Error('Task timed out after 5 minutes'));
81
+ reject(new Error(timeoutMessage));
75
82
  }
76
83
  else {
77
84
  writeJsonResponse({
78
85
  command,
79
- data: { event: 'error', message: 'Task timed out after 5 minutes', status: 'error' },
86
+ data: { event: 'error', message: timeoutMessage, status: 'error' },
80
87
  success: false,
81
88
  });
82
89
  resolve();
@@ -66,5 +66,6 @@ export declare const OVERVIEW_EXTENSION = ".overview.md";
66
66
  export declare const MANIFEST_FILE = "_manifest.json";
67
67
  export declare const ARCHIVE_IMPORTANCE_THRESHOLD = 35;
68
68
  export declare const DEFAULT_GHOST_CUE_MAX_TOKENS = 220;
69
- /** .gitignore content for the context tree ignore derived artifacts only */
70
- export declare const CONTEXT_TREE_GITIGNORE = "# Derived artifacts \u2014 do not track\n.gitignore\n.snapshot.json\n_manifest.json\n_index.md\n";
69
+ /** Patterns the context-tree .gitignore must contain (derived artifacts only). */
70
+ export declare const CONTEXT_TREE_GITIGNORE_PATTERNS: string[];
71
+ export declare const CONTEXT_TREE_GITIGNORE_HEADER = "# Derived artifacts \u2014 do not track";
@@ -88,10 +88,13 @@ export const OVERVIEW_EXTENSION = '.overview.md';
88
88
  export const MANIFEST_FILE = '_manifest.json';
89
89
  export const ARCHIVE_IMPORTANCE_THRESHOLD = 35;
90
90
  export const DEFAULT_GHOST_CUE_MAX_TOKENS = 220;
91
- /** .gitignore content for the context tree ignore derived artifacts only */
92
- export const CONTEXT_TREE_GITIGNORE = `# Derived artifacts — do not track
93
- .gitignore
94
- .snapshot.json
95
- _manifest.json
96
- _index.md
97
- `;
91
+ /** Patterns the context-tree .gitignore must contain (derived artifacts only). */
92
+ export const CONTEXT_TREE_GITIGNORE_PATTERNS = [
93
+ '.gitignore',
94
+ '.snapshot.json',
95
+ '_manifest.json',
96
+ '_index.md',
97
+ '*.abstract.md',
98
+ '*.overview.md',
99
+ ];
100
+ export const CONTEXT_TREE_GITIGNORE_HEADER = '# Derived artifacts — do not track';
@@ -7,6 +7,7 @@ export declare const TaskErrorCode: {
7
7
  readonly AGENT_NOT_AVAILABLE: "ERR_AGENT_NOT_AVAILABLE";
8
8
  readonly AGENT_NOT_INITIALIZED: "ERR_AGENT_NOT_INITIALIZED";
9
9
  readonly CONTEXT_TREE_NOT_INITIALIZED: "ERR_CONTEXT_TREE_NOT_INIT";
10
+ readonly LEGACY_SYNC_UNAVAILABLE: "ERR_LEGACY_SYNC_UNAVAILABLE";
10
11
  readonly LLM_ERROR: "ERR_LLM_ERROR";
11
12
  readonly LLM_RATE_LIMIT: "ERR_LLM_RATE_LIMIT";
12
13
  readonly LOCAL_CHANGES_EXIST: "ERR_LOCAL_CHANGES_EXIST";
@@ -15,7 +16,6 @@ export declare const TaskErrorCode: {
15
16
  readonly OAUTH_TOKEN_EXPIRED: "ERR_OAUTH_TOKEN_EXPIRED";
16
17
  readonly PROJECT_NOT_INIT: "ERR_PROJECT_NOT_INIT";
17
18
  readonly PROVIDER_NOT_CONFIGURED: "ERR_PROVIDER_NOT_CONFIGURED";
18
- readonly SPACE_NOT_CONFIGURED: "ERR_SPACE_NOT_CONFIGURED";
19
19
  readonly SPACE_NOT_FOUND: "ERR_SPACE_NOT_FOUND";
20
20
  readonly TASK_CANCELLED: "ERR_TASK_CANCELLED";
21
21
  readonly TASK_EXECUTION: "ERR_TASK_EXECUTION";
@@ -73,7 +73,7 @@ export declare class FileValidationError extends Error {
73
73
  export declare class LocalChangesExistError extends TaskError {
74
74
  constructor(message?: string);
75
75
  }
76
- export declare class SpaceNotConfiguredError extends TaskError {
76
+ export declare class LegacySyncUnavailableError extends TaskError {
77
77
  constructor();
78
78
  }
79
79
  export declare class GitVcInitializedError extends TaskError {
@@ -9,6 +9,8 @@ export const TaskErrorCode = {
9
9
  AGENT_NOT_INITIALIZED: 'ERR_AGENT_NOT_INITIALIZED',
10
10
  // Context tree errors
11
11
  CONTEXT_TREE_NOT_INITIALIZED: 'ERR_CONTEXT_TREE_NOT_INIT',
12
+ // Legacy sync (brv push/pull) no longer available because project has no team+space configured
13
+ LEGACY_SYNC_UNAVAILABLE: 'ERR_LEGACY_SYNC_UNAVAILABLE',
12
14
  // LLM errors
13
15
  LLM_ERROR: 'ERR_LLM_ERROR',
14
16
  LLM_RATE_LIMIT: 'ERR_LLM_RATE_LIMIT',
@@ -21,7 +23,6 @@ export const TaskErrorCode = {
21
23
  // Execution errors
22
24
  PROJECT_NOT_INIT: 'ERR_PROJECT_NOT_INIT',
23
25
  PROVIDER_NOT_CONFIGURED: 'ERR_PROVIDER_NOT_CONFIGURED',
24
- SPACE_NOT_CONFIGURED: 'ERR_SPACE_NOT_CONFIGURED',
25
26
  SPACE_NOT_FOUND: 'ERR_SPACE_NOT_FOUND',
26
27
  TASK_CANCELLED: 'ERR_TASK_CANCELLED',
27
28
  TASK_EXECUTION: 'ERR_TASK_EXECUTION',
@@ -153,10 +154,10 @@ export class LocalChangesExistError extends TaskError {
153
154
  this.name = 'LocalChangesExistError';
154
155
  }
155
156
  }
156
- export class SpaceNotConfiguredError extends TaskError {
157
+ export class LegacySyncUnavailableError extends TaskError {
157
158
  constructor() {
158
- super('No space configured. Run "brv space list" to see available spaces, then "brv space switch --team <team> --name <space>" to select one.', TaskErrorCode.SPACE_NOT_CONFIGURED);
159
- this.name = 'SpaceNotConfiguredError';
159
+ super('Command brv push and brv pull are deprecated. Run `brv vc init` to start using Byterover version control.', TaskErrorCode.LEGACY_SYNC_UNAVAILABLE);
160
+ this.name = 'LegacySyncUnavailableError';
160
161
  }
161
162
  }
162
163
  export class GitVcInitializedError extends TaskError {
@@ -5,15 +5,15 @@ export declare const SourceSchema: z.ZodObject<{
5
5
  projectRoot: z.ZodString;
6
6
  readOnly: z.ZodLiteral<true>;
7
7
  }, "strip", z.ZodTypeAny, {
8
+ readOnly: true;
8
9
  addedAt: string;
9
10
  alias: string;
10
11
  projectRoot: string;
11
- readOnly: true;
12
12
  }, {
13
+ readOnly: true;
13
14
  addedAt: string;
14
15
  alias: string;
15
16
  projectRoot: string;
16
- readOnly: true;
17
17
  }>;
18
18
  export declare const SourcesFileSchema: z.ZodObject<{
19
19
  sources: z.ZodArray<z.ZodObject<{
@@ -22,32 +22,32 @@ export declare const SourcesFileSchema: z.ZodObject<{
22
22
  projectRoot: z.ZodString;
23
23
  readOnly: z.ZodLiteral<true>;
24
24
  }, "strip", z.ZodTypeAny, {
25
+ readOnly: true;
25
26
  addedAt: string;
26
27
  alias: string;
27
28
  projectRoot: string;
28
- readOnly: true;
29
29
  }, {
30
+ readOnly: true;
30
31
  addedAt: string;
31
32
  alias: string;
32
33
  projectRoot: string;
33
- readOnly: true;
34
34
  }>, "many">;
35
35
  version: z.ZodLiteral<1>;
36
36
  }, "strip", z.ZodTypeAny, {
37
37
  version: 1;
38
38
  sources: {
39
+ readOnly: true;
39
40
  addedAt: string;
40
41
  alias: string;
41
42
  projectRoot: string;
42
- readOnly: true;
43
43
  }[];
44
44
  }, {
45
45
  version: 1;
46
46
  sources: {
47
+ readOnly: true;
47
48
  addedAt: string;
48
49
  alias: string;
49
50
  projectRoot: string;
50
- readOnly: true;
51
51
  }[];
52
52
  }>;
53
53
  export type Source = z.infer<typeof SourceSchema>;
@@ -514,11 +514,11 @@ export declare const TaskExecuteSchema: z.ZodObject<{
514
514
  /** Unique task identifier */
515
515
  taskId: z.ZodString;
516
516
  /** Task type */
517
- type: z.ZodEnum<["curate", "curate-folder", "query"]>;
517
+ type: z.ZodEnum<["curate", "curate-folder", "query", "search"]>;
518
518
  /** Workspace root for scoped query/curate */
519
519
  worktreeRoot: z.ZodOptional<z.ZodString>;
520
520
  }, "strip", z.ZodTypeAny, {
521
- type: "curate" | "query" | "curate-folder";
521
+ type: "curate" | "query" | "search" | "curate-folder";
522
522
  content: string;
523
523
  taskId: string;
524
524
  clientId: string;
@@ -528,7 +528,7 @@ export declare const TaskExecuteSchema: z.ZodObject<{
528
528
  projectPath?: string | undefined;
529
529
  worktreeRoot?: string | undefined;
530
530
  }, {
531
- type: "curate" | "query" | "curate-folder";
531
+ type: "curate" | "query" | "search" | "curate-folder";
532
532
  content: string;
533
533
  taskId: string;
534
534
  clientId: string;
@@ -687,16 +687,16 @@ export declare const TaskCreatedSchema: z.ZodObject<{
687
687
  /** Unique task identifier */
688
688
  taskId: z.ZodString;
689
689
  /** Task type */
690
- type: z.ZodEnum<["curate", "curate-folder", "query"]>;
690
+ type: z.ZodEnum<["curate", "curate-folder", "query", "search"]>;
691
691
  }, "strip", z.ZodTypeAny, {
692
- type: "curate" | "query" | "curate-folder";
692
+ type: "curate" | "query" | "search" | "curate-folder";
693
693
  content: string;
694
694
  taskId: string;
695
695
  files?: string[] | undefined;
696
696
  clientCwd?: string | undefined;
697
697
  folderPath?: string | undefined;
698
698
  }, {
699
- type: "curate" | "query" | "curate-folder";
699
+ type: "curate" | "query" | "search" | "curate-folder";
700
700
  content: string;
701
701
  taskId: string;
702
702
  files?: string[] | undefined;
@@ -755,13 +755,13 @@ export declare const TaskCompletedEventSchema: z.ZodObject<{
755
755
  }, "strip", z.ZodTypeAny, {
756
756
  result: string;
757
757
  taskId: string;
758
- clientId?: string | undefined;
759
758
  logId?: string | undefined;
759
+ clientId?: string | undefined;
760
760
  }, {
761
761
  result: string;
762
762
  taskId: string;
763
- clientId?: string | undefined;
764
763
  logId?: string | undefined;
764
+ clientId?: string | undefined;
765
765
  }>;
766
766
  /**
767
767
  * Structured error object
@@ -815,8 +815,8 @@ export declare const TaskErrorEventSchema: z.ZodObject<{
815
815
  details?: Record<string, unknown> | undefined;
816
816
  };
817
817
  taskId: string;
818
- clientId?: string | undefined;
819
818
  logId?: string | undefined;
819
+ clientId?: string | undefined;
820
820
  }, {
821
821
  error: {
822
822
  message: string;
@@ -825,8 +825,8 @@ export declare const TaskErrorEventSchema: z.ZodObject<{
825
825
  details?: Record<string, unknown> | undefined;
826
826
  };
827
827
  taskId: string;
828
- clientId?: string | undefined;
829
828
  logId?: string | undefined;
829
+ clientId?: string | undefined;
830
830
  }>;
831
831
  /**
832
832
  * llmservice:response - LLM text output
@@ -945,7 +945,7 @@ export type TaskStartedEvent = z.infer<typeof TaskStartedEventSchema>;
945
945
  export type TaskCompletedEvent = z.infer<typeof TaskCompletedEventSchema>;
946
946
  export type TaskErrorData = z.infer<typeof TaskErrorDataSchema>;
947
947
  export type TaskErrorEvent = z.infer<typeof TaskErrorEventSchema>;
948
- export declare const TaskTypeSchema: z.ZodEnum<["curate", "curate-folder", "query"]>;
948
+ export declare const TaskTypeSchema: z.ZodEnum<["curate", "curate-folder", "query", "search"]>;
949
949
  /**
950
950
  * Request to create a new task
951
951
  */
@@ -963,11 +963,11 @@ export declare const TaskCreateRequestSchema: z.ZodObject<{
963
963
  /** Task ID - generated by Client UseCase (UUID v4) */
964
964
  taskId: z.ZodString;
965
965
  /** Task type */
966
- type: z.ZodEnum<["curate", "curate-folder", "query"]>;
966
+ type: z.ZodEnum<["curate", "curate-folder", "query", "search"]>;
967
967
  /** Workspace root for scoped query/curate (stable linked root or projectRoot if unlinked) */
968
968
  worktreeRoot: z.ZodOptional<z.ZodString>;
969
969
  }, "strip", z.ZodTypeAny, {
970
- type: "curate" | "query" | "curate-folder";
970
+ type: "curate" | "query" | "search" | "curate-folder";
971
971
  content: string;
972
972
  taskId: string;
973
973
  files?: string[] | undefined;
@@ -976,7 +976,7 @@ export declare const TaskCreateRequestSchema: z.ZodObject<{
976
976
  projectPath?: string | undefined;
977
977
  worktreeRoot?: string | undefined;
978
978
  }, {
979
- type: "curate" | "query" | "curate-folder";
979
+ type: "curate" | "query" | "search" | "curate-folder";
980
980
  content: string;
981
981
  taskId: string;
982
982
  files?: string[] | undefined;
@@ -314,7 +314,7 @@ export const TaskExecuteSchema = z.object({
314
314
  /** Unique task identifier */
315
315
  taskId: z.string(),
316
316
  /** Task type */
317
- type: z.enum(['curate', 'curate-folder', 'query']),
317
+ type: z.enum(['curate', 'curate-folder', 'query', 'search']),
318
318
  /** Workspace root for scoped query/curate */
319
319
  worktreeRoot: z.string().optional(),
320
320
  });
@@ -374,7 +374,7 @@ export const TaskCreatedSchema = z.object({
374
374
  /** Unique task identifier */
375
375
  taskId: z.string(),
376
376
  /** Task type */
377
- type: z.enum(['curate', 'curate-folder', 'query']),
377
+ type: z.enum(['curate', 'curate-folder', 'query', 'search']),
378
378
  });
379
379
  /**
380
380
  * task:started - Agent begins processing the task
@@ -475,7 +475,7 @@ export const LlmToolResultEventSchema = z.object({
475
475
  // ============================================================================
476
476
  // Request/Response Schemas (for client → server commands)
477
477
  // ============================================================================
478
- export const TaskTypeSchema = z.enum(['curate', 'curate-folder', 'query']);
478
+ export const TaskTypeSchema = z.enum(['curate', 'curate-folder', 'query', 'search']);
479
479
  /**
480
480
  * Request to create a new task
481
481
  */