byterover-cli 3.3.0 → 3.5.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 (106) hide show
  1. package/dist/agent/core/domain/swarm/types.d.ts +132 -0
  2. package/dist/agent/core/domain/swarm/types.js +128 -0
  3. package/dist/agent/core/domain/tools/constants.d.ts +2 -0
  4. package/dist/agent/core/domain/tools/constants.js +2 -0
  5. package/dist/agent/core/interfaces/i-memory-provider.d.ts +45 -0
  6. package/dist/agent/core/interfaces/i-memory-provider.js +1 -0
  7. package/dist/agent/core/interfaces/i-sandbox-service.d.ts +8 -0
  8. package/dist/agent/core/interfaces/i-swarm-coordinator.d.ts +127 -0
  9. package/dist/agent/core/interfaces/i-swarm-coordinator.js +1 -0
  10. package/dist/agent/infra/agent/service-initializer.js +48 -0
  11. package/dist/agent/infra/map/map-shared.d.ts +2 -2
  12. package/dist/agent/infra/sandbox/sandbox-service.d.ts +10 -0
  13. package/dist/agent/infra/sandbox/sandbox-service.js +13 -0
  14. package/dist/agent/infra/sandbox/tools-sdk.d.ts +25 -0
  15. package/dist/agent/infra/sandbox/tools-sdk.js +24 -1
  16. package/dist/agent/infra/swarm/adapters/byterover-adapter.d.ts +39 -0
  17. package/dist/agent/infra/swarm/adapters/byterover-adapter.js +62 -0
  18. package/dist/agent/infra/swarm/adapters/gbrain-adapter.d.ts +63 -0
  19. package/dist/agent/infra/swarm/adapters/gbrain-adapter.js +209 -0
  20. package/dist/agent/infra/swarm/adapters/local-markdown-adapter.d.ts +41 -0
  21. package/dist/agent/infra/swarm/adapters/local-markdown-adapter.js +256 -0
  22. package/dist/agent/infra/swarm/adapters/memory-wiki-adapter.d.ts +29 -0
  23. package/dist/agent/infra/swarm/adapters/memory-wiki-adapter.js +244 -0
  24. package/dist/agent/infra/swarm/adapters/obsidian-adapter.d.ts +37 -0
  25. package/dist/agent/infra/swarm/adapters/obsidian-adapter.js +201 -0
  26. package/dist/agent/infra/swarm/cli/query-renderer.d.ts +15 -0
  27. package/dist/agent/infra/swarm/cli/query-renderer.js +126 -0
  28. package/dist/agent/infra/swarm/config/swarm-config-loader.d.ts +14 -0
  29. package/dist/agent/infra/swarm/config/swarm-config-loader.js +82 -0
  30. package/dist/agent/infra/swarm/config/swarm-config-schema.d.ts +667 -0
  31. package/dist/agent/infra/swarm/config/swarm-config-schema.js +305 -0
  32. package/dist/agent/infra/swarm/provider-factory.d.ts +21 -0
  33. package/dist/agent/infra/swarm/provider-factory.js +67 -0
  34. package/dist/agent/infra/swarm/search-precision.d.ts +95 -0
  35. package/dist/agent/infra/swarm/search-precision.js +141 -0
  36. package/dist/agent/infra/swarm/swarm-coordinator.d.ts +59 -0
  37. package/dist/agent/infra/swarm/swarm-coordinator.js +436 -0
  38. package/dist/agent/infra/swarm/swarm-graph.d.ts +63 -0
  39. package/dist/agent/infra/swarm/swarm-graph.js +167 -0
  40. package/dist/agent/infra/swarm/swarm-merger.d.ts +29 -0
  41. package/dist/agent/infra/swarm/swarm-merger.js +66 -0
  42. package/dist/agent/infra/swarm/swarm-router.d.ts +12 -0
  43. package/dist/agent/infra/swarm/swarm-router.js +40 -0
  44. package/dist/agent/infra/swarm/swarm-write-router.d.ts +23 -0
  45. package/dist/agent/infra/swarm/swarm-write-router.js +45 -0
  46. package/dist/agent/infra/swarm/validation/config-validator.d.ts +16 -0
  47. package/dist/agent/infra/swarm/validation/config-validator.js +402 -0
  48. package/dist/agent/infra/swarm/validation/memory-swarm-validation-error.d.ts +33 -0
  49. package/dist/agent/infra/swarm/validation/memory-swarm-validation-error.js +27 -0
  50. package/dist/agent/infra/swarm/wizard/config-scaffolder.d.ts +36 -0
  51. package/dist/agent/infra/swarm/wizard/config-scaffolder.js +96 -0
  52. package/dist/agent/infra/swarm/wizard/provider-detector.d.ts +54 -0
  53. package/dist/agent/infra/swarm/wizard/provider-detector.js +153 -0
  54. package/dist/agent/infra/swarm/wizard/swarm-wizard.d.ts +61 -0
  55. package/dist/agent/infra/swarm/wizard/swarm-wizard.js +187 -0
  56. package/dist/agent/infra/system-prompt/contributors/index.d.ts +1 -0
  57. package/dist/agent/infra/system-prompt/contributors/index.js +1 -0
  58. package/dist/agent/infra/system-prompt/contributors/swarm-state-contributor.d.ts +15 -0
  59. package/dist/agent/infra/system-prompt/contributors/swarm-state-contributor.js +65 -0
  60. package/dist/agent/infra/tools/implementations/curate-tool.d.ts +14 -14
  61. package/dist/agent/infra/tools/implementations/curate-tool.js +2 -0
  62. package/dist/agent/infra/tools/implementations/swarm-query-tool.d.ts +9 -0
  63. package/dist/agent/infra/tools/implementations/swarm-query-tool.js +44 -0
  64. package/dist/agent/infra/tools/implementations/swarm-store-tool.d.ts +9 -0
  65. package/dist/agent/infra/tools/implementations/swarm-store-tool.js +43 -0
  66. package/dist/agent/infra/tools/tool-provider.js +1 -0
  67. package/dist/agent/infra/tools/tool-registry.d.ts +3 -0
  68. package/dist/agent/infra/tools/tool-registry.js +25 -1
  69. package/dist/agent/resources/tools/code_exec.txt +2 -0
  70. package/dist/agent/resources/tools/swarm_query.txt +38 -0
  71. package/dist/agent/resources/tools/swarm_store.txt +35 -0
  72. package/dist/oclif/commands/connectors/install.d.ts +2 -2
  73. package/dist/oclif/commands/connectors/install.js +15 -7
  74. package/dist/oclif/commands/swarm/curate.d.ts +13 -0
  75. package/dist/oclif/commands/swarm/curate.js +81 -0
  76. package/dist/oclif/commands/swarm/onboard.d.ts +6 -0
  77. package/dist/oclif/commands/swarm/onboard.js +233 -0
  78. package/dist/oclif/commands/swarm/query.d.ts +14 -0
  79. package/dist/oclif/commands/swarm/query.js +84 -0
  80. package/dist/oclif/commands/swarm/status.d.ts +41 -0
  81. package/dist/oclif/commands/swarm/status.js +278 -0
  82. package/dist/server/constants.d.ts +3 -2
  83. package/dist/server/constants.js +10 -9
  84. package/dist/server/core/domain/entities/agent.js +4 -0
  85. package/dist/server/core/domain/source/source-schema.d.ts +6 -6
  86. package/dist/server/core/domain/transport/schemas.d.ts +4 -4
  87. package/dist/server/infra/connectors/mcp/claude-desktop-config-path.d.ts +20 -0
  88. package/dist/server/infra/connectors/mcp/claude-desktop-config-path.js +47 -0
  89. package/dist/server/infra/connectors/mcp/mcp-connector-config.d.ts +19 -0
  90. package/dist/server/infra/connectors/mcp/mcp-connector-config.js +9 -0
  91. package/dist/server/infra/connectors/mcp/mcp-connector.js +12 -3
  92. package/dist/server/infra/http/provider-model-fetchers.js +1 -0
  93. package/dist/server/infra/process/feature-handlers.js +13 -0
  94. package/dist/server/infra/project/project-registry.js +13 -1
  95. package/dist/server/infra/transport/handlers/locations-handler.d.ts +2 -0
  96. package/dist/server/infra/transport/handlers/locations-handler.js +16 -1
  97. package/dist/server/infra/transport/handlers/vc-handler.d.ts +0 -4
  98. package/dist/server/infra/transport/handlers/vc-handler.js +5 -16
  99. package/dist/server/templates/skill/SKILL.md +163 -0
  100. package/dist/server/utils/gitignore.d.ts +1 -0
  101. package/dist/server/utils/gitignore.js +36 -4
  102. package/dist/shared/types/agent.d.ts +2 -1
  103. package/dist/shared/types/agent.js +2 -0
  104. package/dist/tui/features/connectors/components/connectors-flow.js +7 -2
  105. package/oclif.manifest.json +503 -323
  106. package/package.json +2 -2
@@ -14,7 +14,7 @@ type OperationType = z.infer<typeof OperationType>;
14
14
  export declare const CurateInputSchema: z.ZodObject<{
15
15
  basePath: z.ZodDefault<z.ZodString>;
16
16
  operations: z.ZodArray<z.ZodObject<{
17
- confidence: z.ZodEnum<["high", "low"]>;
17
+ confidence: z.ZodDefault<z.ZodEnum<["high", "low"]>>;
18
18
  content: z.ZodOptional<z.ZodObject<{
19
19
  facts: z.ZodOptional<z.ZodArray<z.ZodObject<{
20
20
  category: z.ZodOptional<z.ZodEnum<["personal", "project", "preference", "convention", "team", "environment", "other"]>>;
@@ -24,12 +24,12 @@ export declare const CurateInputSchema: z.ZodObject<{
24
24
  }, "strip", z.ZodTypeAny, {
25
25
  statement: string;
26
26
  value?: string | undefined;
27
- category?: "environment" | "convention" | "other" | "personal" | "preference" | "project" | "team" | undefined;
27
+ category?: "personal" | "environment" | "convention" | "other" | "preference" | "project" | "team" | undefined;
28
28
  subject?: string | undefined;
29
29
  }, {
30
30
  statement: string;
31
31
  value?: string | undefined;
32
- category?: "environment" | "convention" | "other" | "personal" | "preference" | "project" | "team" | undefined;
32
+ category?: "personal" | "environment" | "convention" | "other" | "preference" | "project" | "team" | undefined;
33
33
  subject?: string | undefined;
34
34
  }>, "many">>;
35
35
  keywords: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
@@ -130,7 +130,7 @@ export declare const CurateInputSchema: z.ZodObject<{
130
130
  facts?: {
131
131
  statement: string;
132
132
  value?: string | undefined;
133
- category?: "environment" | "convention" | "other" | "personal" | "preference" | "project" | "team" | undefined;
133
+ category?: "personal" | "environment" | "convention" | "other" | "preference" | "project" | "team" | undefined;
134
134
  subject?: string | undefined;
135
135
  }[] | undefined;
136
136
  narrative?: {
@@ -166,7 +166,7 @@ export declare const CurateInputSchema: z.ZodObject<{
166
166
  facts?: {
167
167
  statement: string;
168
168
  value?: string | undefined;
169
- category?: "environment" | "convention" | "other" | "personal" | "preference" | "project" | "team" | undefined;
169
+ category?: "personal" | "environment" | "convention" | "other" | "preference" | "project" | "team" | undefined;
170
170
  subject?: string | undefined;
171
171
  }[] | undefined;
172
172
  narrative?: {
@@ -227,7 +227,7 @@ export declare const CurateInputSchema: z.ZodObject<{
227
227
  usage?: string | undefined;
228
228
  ownership?: string | undefined;
229
229
  }>>;
230
- impact: z.ZodEnum<["high", "low"]>;
230
+ impact: z.ZodDefault<z.ZodEnum<["high", "low"]>>;
231
231
  mergeTarget: z.ZodOptional<z.ZodString>;
232
232
  mergeTargetTitle: z.ZodOptional<z.ZodString>;
233
233
  path: z.ZodString;
@@ -273,7 +273,7 @@ export declare const CurateInputSchema: z.ZodObject<{
273
273
  facts?: {
274
274
  statement: string;
275
275
  value?: string | undefined;
276
- category?: "environment" | "convention" | "other" | "personal" | "preference" | "project" | "team" | undefined;
276
+ category?: "personal" | "environment" | "convention" | "other" | "preference" | "project" | "team" | undefined;
277
277
  subject?: string | undefined;
278
278
  }[] | undefined;
279
279
  narrative?: {
@@ -327,8 +327,6 @@ export declare const CurateInputSchema: z.ZodObject<{
327
327
  path: string;
328
328
  type: "ADD" | "DELETE" | "MERGE" | "UPDATE" | "UPSERT";
329
329
  reason: string;
330
- confidence: "high" | "low";
331
- impact: "high" | "low";
332
330
  summary?: string | undefined;
333
331
  title?: string | undefined;
334
332
  content?: {
@@ -338,7 +336,7 @@ export declare const CurateInputSchema: z.ZodObject<{
338
336
  facts?: {
339
337
  statement: string;
340
338
  value?: string | undefined;
341
- category?: "environment" | "convention" | "other" | "personal" | "preference" | "project" | "team" | undefined;
339
+ category?: "personal" | "environment" | "convention" | "other" | "preference" | "project" | "team" | undefined;
342
340
  subject?: string | undefined;
343
341
  }[] | undefined;
344
342
  narrative?: {
@@ -368,6 +366,7 @@ export declare const CurateInputSchema: z.ZodObject<{
368
366
  } | undefined;
369
367
  snippets?: string[] | undefined;
370
368
  } | undefined;
369
+ confidence?: "high" | "low" | undefined;
371
370
  domainContext?: {
372
371
  scope: {
373
372
  included: string[];
@@ -377,6 +376,7 @@ export declare const CurateInputSchema: z.ZodObject<{
377
376
  usage?: string | undefined;
378
377
  ownership?: string | undefined;
379
378
  } | undefined;
379
+ impact?: "high" | "low" | undefined;
380
380
  mergeTarget?: string | undefined;
381
381
  mergeTargetTitle?: string | undefined;
382
382
  subtopicContext?: {
@@ -406,7 +406,7 @@ export declare const CurateInputSchema: z.ZodObject<{
406
406
  facts?: {
407
407
  statement: string;
408
408
  value?: string | undefined;
409
- category?: "environment" | "convention" | "other" | "personal" | "preference" | "project" | "team" | undefined;
409
+ category?: "personal" | "environment" | "convention" | "other" | "preference" | "project" | "team" | undefined;
410
410
  subject?: string | undefined;
411
411
  }[] | undefined;
412
412
  narrative?: {
@@ -462,8 +462,6 @@ export declare const CurateInputSchema: z.ZodObject<{
462
462
  path: string;
463
463
  type: "ADD" | "DELETE" | "MERGE" | "UPDATE" | "UPSERT";
464
464
  reason: string;
465
- confidence: "high" | "low";
466
- impact: "high" | "low";
467
465
  summary?: string | undefined;
468
466
  title?: string | undefined;
469
467
  content?: {
@@ -473,7 +471,7 @@ export declare const CurateInputSchema: z.ZodObject<{
473
471
  facts?: {
474
472
  statement: string;
475
473
  value?: string | undefined;
476
- category?: "environment" | "convention" | "other" | "personal" | "preference" | "project" | "team" | undefined;
474
+ category?: "personal" | "environment" | "convention" | "other" | "preference" | "project" | "team" | undefined;
477
475
  subject?: string | undefined;
478
476
  }[] | undefined;
479
477
  narrative?: {
@@ -503,6 +501,7 @@ export declare const CurateInputSchema: z.ZodObject<{
503
501
  } | undefined;
504
502
  snippets?: string[] | undefined;
505
503
  } | undefined;
504
+ confidence?: "high" | "low" | undefined;
506
505
  domainContext?: {
507
506
  scope: {
508
507
  included: string[];
@@ -512,6 +511,7 @@ export declare const CurateInputSchema: z.ZodObject<{
512
511
  usage?: string | undefined;
513
512
  ownership?: string | undefined;
514
513
  } | undefined;
514
+ impact?: "high" | "low" | undefined;
515
515
  mergeTarget?: string | undefined;
516
516
  mergeTargetTitle?: string | undefined;
517
517
  subtopicContext?: {
@@ -162,11 +162,13 @@ const SubtopicContextSchema = z.object({
162
162
  const OperationSchema = z.object({
163
163
  confidence: z
164
164
  .enum(['high', 'low'])
165
+ .default('low')
165
166
  .describe('Your confidence in the accuracy and completeness of this operation. Use "high" when you have direct evidence from the source material; use "low" when the information is inferred, uncertain, or incomplete.'),
166
167
  content: ContentSchema.optional().describe('Content for ADD/UPDATE operations'),
167
168
  domainContext: DomainContextSchema.optional().describe('Domain-level context for new domains. When creating content in a NEW domain, provide this to auto-generate domain/context.md with purpose, scope, ownership, and usage. Only needed when the domain does not exist yet.'),
168
169
  impact: z
169
170
  .enum(['high', 'low'])
171
+ .default('high')
170
172
  .describe('Estimated scope of impact of this knowledge change. "high": Changes that alter core decisions, strategies, tools, or established approaches. Any change that contradicts or reverses previously curated knowledge. Updates to existing knowledge that change its core substance. Deletions are always high impact. "low": New additions to previously undocumented topics, minor corrections, supplementary details like examples and clarifications, or updates that extend existing knowledge without changing its core substance.'),
171
173
  mergeTarget: z.string().optional().describe('Target path for MERGE operation'),
172
174
  mergeTargetTitle: z.string().optional().describe('Title of the target file for MERGE operation'),
@@ -0,0 +1,9 @@
1
+ import type { Tool } from '../../../core/domain/tools/types.js';
2
+ import type { ISwarmCoordinator } from '../../../core/interfaces/i-swarm-coordinator.js';
3
+ /**
4
+ * Creates the swarm_query tool for the agent to search across memory providers.
5
+ *
6
+ * @param coordinator - The swarm coordinator instance
7
+ * @returns Configured swarm query tool
8
+ */
9
+ export declare function createSwarmQueryTool(coordinator: ISwarmCoordinator): Tool;
@@ -0,0 +1,44 @@
1
+ import { z } from 'zod';
2
+ import { ToolName } from '../../../core/domain/tools/constants.js';
3
+ const SwarmQueryInputSchema = z
4
+ .object({
5
+ maxResults: z
6
+ .number()
7
+ .int()
8
+ .positive()
9
+ .optional()
10
+ .describe('Maximum number of results to return (default: 10)'),
11
+ query: z
12
+ .string()
13
+ .min(1)
14
+ .describe('Natural language query to search across all active memory providers'),
15
+ scope: z
16
+ .string()
17
+ .optional()
18
+ .describe('Optional scope to restrict search (e.g., "auth", "architecture")'),
19
+ })
20
+ .strict();
21
+ /**
22
+ * Creates the swarm_query tool for the agent to search across memory providers.
23
+ *
24
+ * @param coordinator - The swarm coordinator instance
25
+ * @returns Configured swarm query tool
26
+ */
27
+ export function createSwarmQueryTool(coordinator) {
28
+ return {
29
+ description: 'Search across all active memory providers in the memory swarm. ' +
30
+ 'Routes the query to relevant providers based on query type classification, ' +
31
+ 'executes in parallel, and returns fused, ranked results. ' +
32
+ 'Use this when you need information that may be spread across multiple knowledge sources.',
33
+ async execute(input, _context) {
34
+ const parsed = SwarmQueryInputSchema.parse(input);
35
+ return coordinator.execute({
36
+ maxResults: parsed.maxResults,
37
+ query: parsed.query,
38
+ scope: parsed.scope,
39
+ });
40
+ },
41
+ id: ToolName.SWARM_QUERY,
42
+ inputSchema: SwarmQueryInputSchema,
43
+ };
44
+ }
@@ -0,0 +1,9 @@
1
+ import type { Tool } from '../../../core/domain/tools/types.js';
2
+ import type { ISwarmCoordinator } from '../../../core/interfaces/i-swarm-coordinator.js';
3
+ /**
4
+ * Creates the swarm_store tool for the agent to write knowledge to swarm providers.
5
+ *
6
+ * @param coordinator - The swarm coordinator instance
7
+ * @returns Configured swarm store tool
8
+ */
9
+ export declare function createSwarmStoreTool(coordinator: ISwarmCoordinator): Tool;
@@ -0,0 +1,43 @@
1
+ import { z } from 'zod';
2
+ import { ToolName } from '../../../core/domain/tools/constants.js';
3
+ const SwarmStoreInputSchema = z
4
+ .object({
5
+ content: z
6
+ .string()
7
+ .min(1)
8
+ .describe('Knowledge content to store in a swarm provider'),
9
+ contentType: z
10
+ .enum(['entity', 'general', 'note'])
11
+ .optional()
12
+ .describe('Content type hint for routing: entity (people/companies), note (drafts/meetings), general'),
13
+ provider: z
14
+ .string()
15
+ .optional()
16
+ .describe('Explicit target provider ID (e.g., gbrain, local-markdown:notes). Auto-routed if omitted.'),
17
+ })
18
+ .strict();
19
+ /**
20
+ * Creates the swarm_store tool for the agent to write knowledge to swarm providers.
21
+ *
22
+ * @param coordinator - The swarm coordinator instance
23
+ * @returns Configured swarm store tool
24
+ */
25
+ export function createSwarmStoreTool(coordinator) {
26
+ return {
27
+ description: 'Store knowledge in a swarm provider (GBrain, local markdown). ' +
28
+ 'Routes by content type: entities (people, companies) go to GBrain, ' +
29
+ 'notes and drafts go to local markdown. Use the provider parameter to ' +
30
+ 'target a specific provider. Use the curate tool for project-specific ' +
31
+ 'knowledge that belongs in the context tree.',
32
+ async execute(input, _context) {
33
+ const parsed = SwarmStoreInputSchema.parse(input);
34
+ return coordinator.store({
35
+ content: parsed.content,
36
+ contentType: parsed.contentType,
37
+ provider: parsed.provider,
38
+ });
39
+ },
40
+ id: ToolName.SWARM_STORE,
41
+ inputSchema: SwarmStoreInputSchema,
42
+ };
43
+ }
@@ -29,6 +29,7 @@ export class ToolProvider {
29
29
  memoryManager: 0,
30
30
  processService: 0,
31
31
  sandboxService: 0,
32
+ swarmCoordinator: 0,
32
33
  todoStorage: 0,
33
34
  tokenizer: 0,
34
35
  }));
@@ -7,6 +7,7 @@ import type { IFileSystem } from '../../core/interfaces/i-file-system.js';
7
7
  import type { ILogger } from '../../core/interfaces/i-logger.js';
8
8
  import type { IProcessService } from '../../core/interfaces/i-process-service.js';
9
9
  import type { ISandboxService } from '../../core/interfaces/i-sandbox-service.js';
10
+ import type { ISwarmCoordinator } from '../../core/interfaces/i-swarm-coordinator.js';
10
11
  import type { ITodoStorage } from '../../core/interfaces/i-todo-storage.js';
11
12
  import type { ITokenizer } from '../../core/interfaces/i-tokenizer.js';
12
13
  import type { AbstractGenerationQueue } from '../map/abstract-queue.js';
@@ -43,6 +44,8 @@ export interface ToolServices {
43
44
  processService?: IProcessService;
44
45
  /** Sandbox service for code execution */
45
46
  sandboxService?: ISandboxService;
47
+ /** Swarm coordinator for cross-provider memory queries */
48
+ swarmCoordinator?: ISwarmCoordinator;
46
49
  /** Todo storage service for session-based todo persistence */
47
50
  todoStorage?: ITodoStorage;
48
51
  /** Tokenizer for ContextTreeStore token counting */
@@ -12,6 +12,8 @@ import { createLlmMapTool } from './implementations/llm-map-tool.js';
12
12
  import { createReadFileTool } from './implementations/read-file-tool.js';
13
13
  import { createSearchKnowledgeService } from './implementations/search-knowledge-service.js';
14
14
  import { createSearchKnowledgeTool } from './implementations/search-knowledge-tool.js';
15
+ import { createSwarmQueryTool } from './implementations/swarm-query-tool.js';
16
+ import { createSwarmStoreTool } from './implementations/swarm-store-tool.js';
15
17
  import { createWriteFileTool } from './implementations/write-file-tool.js';
16
18
  import { ToolMarker } from './tool-markers.js';
17
19
  /**
@@ -55,7 +57,7 @@ export const TOOL_REGISTRY = {
55
57
  },
56
58
  [ToolName.CODE_EXEC]: {
57
59
  descriptionFile: 'code_exec',
58
- factory({ abstractQueue, environmentContext, fileSystemService, sandboxService }) {
60
+ factory({ abstractQueue, environmentContext, fileSystemService, sandboxService, swarmCoordinator }) {
59
61
  const sandbox = getRequiredService(sandboxService, 'sandboxService');
60
62
  // Inject file system service into sandbox for Tools SDK
61
63
  if (fileSystemService && sandbox.setFileSystem) {
@@ -75,6 +77,10 @@ export const TOOL_REGISTRY = {
75
77
  if (environmentContext && sandbox.setEnvironmentContext) {
76
78
  sandbox.setEnvironmentContext(environmentContext);
77
79
  }
80
+ // Inject swarm coordinator into sandbox for tools.swarmQuery/swarmStore
81
+ if (swarmCoordinator && sandbox.setSwarmCoordinator) {
82
+ sandbox.setSwarmCoordinator(swarmCoordinator);
83
+ }
78
84
  return createCodeExecTool(sandbox);
79
85
  },
80
86
  markers: [ToolMarker.Execution],
@@ -142,6 +148,24 @@ export const TOOL_REGISTRY = {
142
148
  markers: [ToolMarker.ContextBuilding, ToolMarker.Discovery],
143
149
  requiredServices: ['fileSystemService'],
144
150
  },
151
+ [ToolName.SWARM_QUERY]: {
152
+ descriptionFile: 'swarm_query',
153
+ factory(services) {
154
+ const coordinator = getRequiredService(services.swarmCoordinator, 'swarmCoordinator');
155
+ return createSwarmQueryTool(coordinator);
156
+ },
157
+ markers: [ToolMarker.Discovery],
158
+ requiredServices: ['swarmCoordinator'],
159
+ },
160
+ [ToolName.SWARM_STORE]: {
161
+ descriptionFile: 'swarm_store',
162
+ factory(services) {
163
+ const coordinator = getRequiredService(services.swarmCoordinator, 'swarmCoordinator');
164
+ return createSwarmStoreTool(coordinator);
165
+ },
166
+ markers: [ToolMarker.Modification],
167
+ requiredServices: ['swarmCoordinator'],
168
+ },
145
169
  [ToolName.WRITE_FILE]: {
146
170
  descriptionFile: 'write_file',
147
171
  factory: (services) => createWriteFileTool(getRequiredService(services.fileSystemService, 'fileSystemService'), services.environmentContext),
@@ -156,6 +156,8 @@ All methods are async and require the async IIFE wrapper.
156
156
  - **tools.curate(operations[], options?)** — Curate knowledge (ADD/UPDATE/UPSERT/MERGE/DELETE)
157
157
  - **tools.searchKnowledge(query, options?)** — Search curated knowledge
158
158
  - **tools.detectDomains(domains[])** — Detect domains from text
159
+ - **tools.swarmQuery(query, {limit?, scope?})** — Search across all swarm memory providers (when configured)
160
+ - **tools.swarmStore({content, contentType?, provider?})** — Store knowledge in GBrain/local markdown (when configured)
159
161
 
160
162
  ## Available Globals
161
163
 
@@ -0,0 +1,38 @@
1
+ Search across all active memory providers in the memory swarm.
2
+
3
+ This tool routes your query to multiple knowledge sources (ByteRover context tree, Obsidian vaults, local markdown folders, and cloud providers), executes them in parallel, and returns fused, ranked results using Reciprocal Rank Fusion.
4
+
5
+ **When to use:**
6
+ - When information may be spread across multiple knowledge sources
7
+ - When you need a broader search than `search_knowledge` (which only searches `.brv/context-tree/`)
8
+ - When you want results from Obsidian vaults, local markdown folders, or cloud memory providers
9
+
10
+ **Parameters:**
11
+ - `query` (required): Natural language query to search across providers
12
+ - `maxResults` (optional): Maximum results to return (default: 10)
13
+ - `scope` (optional): Restrict search to a namespace/subtree
14
+
15
+ **Returns:**
16
+ - `results`: Array of ranked results with:
17
+ - `content`: The matching content
18
+ - `provider`: Which provider returned this result
19
+ - `score`: Fused relevance score (higher is better)
20
+ - `metadata.source`: Source file or identifier
21
+ - `metadata.matchType`: How the match was found (keyword, semantic, graph, temporal)
22
+ - `meta`: Execution metadata with:
23
+ - `queryType`: How the query was classified (factual, temporal, personal, relational)
24
+ - `providers`: Per-provider latency and result counts
25
+ - `totalLatencyMs`: End-to-end latency
26
+ - `costCents`: Total cost for cloud providers
27
+
28
+ **Query routing:**
29
+ - Queries are automatically classified and routed to relevant providers
30
+ - "yesterday", "last week" → temporal providers
31
+ - "I prefer", "my style" → personal/user-modeling providers
32
+ - "related to", "depends on" → relational/graph providers
33
+ - General queries → factual providers (all local sources)
34
+
35
+ **Examples:**
36
+ - Query: "auth tokens" → searches ByteRover + Obsidian + local markdown
37
+ - Query: "what changed yesterday" → routes to temporal-capable providers
38
+ - Query: "how do I usually handle errors" → routes to personal memory providers
@@ -0,0 +1,35 @@
1
+ Store knowledge in a swarm provider (GBrain, local markdown).
2
+
3
+ This tool writes knowledge to external memory providers. It auto-routes based on content type, or you can target a specific provider.
4
+
5
+ **When to use:**
6
+ - Storing structured entities (people, companies, concepts) → routes to GBrain
7
+ - Storing notes, drafts, meeting summaries → routes to local markdown
8
+ - When knowledge belongs outside the project context tree
9
+
10
+ **When NOT to use:**
11
+ - For project-specific knowledge (architecture, decisions, code patterns) → use `curate` instead
12
+ - The `curate` tool writes to .brv/context-tree with FinMem scoring and domain structure
13
+
14
+ **Parameters:**
15
+ - `content` (required): The knowledge to store
16
+ - `provider` (optional): Target provider ID (e.g., "gbrain", "local-markdown:notes"). Auto-routed if omitted.
17
+ - `contentType` (optional): Hint for routing — "entity", "note", or "general"
18
+
19
+ **Returns:**
20
+ - `success`: Whether the store succeeded
21
+ - `provider`: Which provider stored the content
22
+ - `id`: ID assigned by the provider (slug for GBrain, filename for local markdown)
23
+ - `latencyMs`: Store latency
24
+ - `error`: Error message if store failed
25
+
26
+ **Routing logic:**
27
+ - Content mentioning people, companies, roles → "entity" → GBrain
28
+ - Content with meeting notes, TODOs, drafts → "note" → local markdown
29
+ - Ambiguous content → first available writable provider
30
+ - Explicit `provider` parameter overrides all routing
31
+
32
+ **Examples:**
33
+ - Store entity: `swarm_store({ content: "Dario Amodei is CEO of Anthropic" })`
34
+ - Store note: `swarm_store({ content: "Meeting: decided to use JWT refresh rotation" })`
35
+ - Explicit target: `swarm_store({ content: "...", provider: "gbrain" })`
@@ -15,13 +15,13 @@ export default class ConnectorsInstall extends Command {
15
15
  agentId: string;
16
16
  connectorType?: string;
17
17
  }, options?: DaemonClientOptions): Promise<{
18
- agentId: "Amp" | "Antigravity" | "Auggie CLI" | "Augment Code" | "Claude Code" | "Cline" | "Codex" | "Cursor" | "Gemini CLI" | "Github Copilot" | "Junie" | "Kilo Code" | "Kiro" | "OpenClaw" | "OpenCode" | "Qoder" | "Qwen Code" | "Roo Code" | "Trae.ai" | "Warp" | "Windsurf" | "Zed";
18
+ agentId: "Amp" | "Antigravity" | "Auggie CLI" | "Augment Code" | "Claude Code" | "Claude Desktop" | "Cline" | "Codex" | "Cursor" | "Gemini CLI" | "Github Copilot" | "Junie" | "Kilo Code" | "Kiro" | "OpenClaw" | "OpenCode" | "Qoder" | "Qwen Code" | "Roo Code" | "Trae.ai" | "Warp" | "Windsurf" | "Zed";
19
19
  alreadySameType: boolean;
20
20
  connectorType: "rules" | "hook" | "mcp" | "skill";
21
21
  fromType?: undefined;
22
22
  result?: undefined;
23
23
  } | {
24
- agentId: "Amp" | "Antigravity" | "Auggie CLI" | "Augment Code" | "Claude Code" | "Cline" | "Codex" | "Cursor" | "Gemini CLI" | "Github Copilot" | "Junie" | "Kilo Code" | "Kiro" | "OpenClaw" | "OpenCode" | "Qoder" | "Qwen Code" | "Roo Code" | "Trae.ai" | "Warp" | "Windsurf" | "Zed";
24
+ agentId: "Amp" | "Antigravity" | "Auggie CLI" | "Augment Code" | "Claude Code" | "Claude Desktop" | "Cline" | "Codex" | "Cursor" | "Gemini CLI" | "Github Copilot" | "Junie" | "Kilo Code" | "Kiro" | "OpenClaw" | "OpenCode" | "Qoder" | "Qwen Code" | "Roo Code" | "Trae.ai" | "Warp" | "Windsurf" | "Zed";
25
25
  alreadySameType: boolean;
26
26
  connectorType: "rules" | "hook" | "mcp" | "skill";
27
27
  fromType: "rules" | "hook" | "mcp" | "skill" | undefined;
@@ -2,7 +2,7 @@ import { select } from '@inquirer/prompts';
2
2
  import { Args, Command, Flags } from '@oclif/core';
3
3
  import { AGENT_CONNECTOR_CONFIG } from '../../../server/core/domain/entities/agent.js';
4
4
  import { ConnectorEvents, } from '../../../shared/transport/events/connector-events.js';
5
- import { AGENT_VALUES } from '../../../shared/types/agent.js';
5
+ import { AGENT_VALUES, CLAUDE_DESKTOP } from '../../../shared/types/agent.js';
6
6
  import { isConnectorType, requiresAgentRestart } from '../../../shared/types/connector-type.js';
7
7
  import { getConnectorName } from '../../../tui/features/connectors/utils/get-connector-name.js';
8
8
  import { withDaemonRetry } from '../../lib/daemon-client.js';
@@ -70,7 +70,10 @@ ${agentTable}`;
70
70
  return { agentId: matchedAgent.id, alreadySameType: true, connectorType: resolvedType };
71
71
  }
72
72
  // 5. Install or switch
73
- const result = await client.requestWithAck(ConnectorEvents.INSTALL, { agentId: matchedAgent.id, connectorType: resolvedType });
73
+ const result = await client.requestWithAck(ConnectorEvents.INSTALL, {
74
+ agentId: matchedAgent.id,
75
+ connectorType: resolvedType,
76
+ });
74
77
  if (!result.success) {
75
78
  throw new Error(result.message);
76
79
  }
@@ -132,10 +135,12 @@ ${agentTable}`;
132
135
  configPath: installResult.result?.configPath,
133
136
  connectorType: installResult.connectorType,
134
137
  ...(installResult.alreadySameType ? { message: 'Already using this connector type' } : {}),
135
- ...(installResult.result?.requiresManualSetup ? {
136
- manualInstructions: installResult.result.manualInstructions,
137
- requiresManualSetup: true,
138
- } : {}),
138
+ ...(installResult.result?.requiresManualSetup
139
+ ? {
140
+ manualInstructions: installResult.result.manualInstructions,
141
+ requiresManualSetup: true,
142
+ }
143
+ : {}),
139
144
  },
140
145
  success: true,
141
146
  });
@@ -167,7 +172,10 @@ ${agentTable}`;
167
172
  this.log(`Location: ${installResult.result.configPath}`);
168
173
  }
169
174
  if (requiresAgentRestart(installResult.connectorType)) {
170
- this.log(`\nPlease restart ${installResult.agentId} to apply the new ${getConnectorName(installResult.connectorType)}.`);
175
+ const hint = installResult.agentId === CLAUDE_DESKTOP
176
+ ? `\nQuit ${installResult.agentId} from the system tray (Win) or menu bar (Mac), then reopen it.`
177
+ : `\nPlease restart ${installResult.agentId} to apply the new ${getConnectorName(installResult.connectorType)}.`;
178
+ this.log(hint);
171
179
  }
172
180
  }
173
181
  catch (error) {
@@ -0,0 +1,13 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class SwarmCurate extends Command {
3
+ static args: {
4
+ content: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
5
+ };
6
+ static description: string;
7
+ static examples: string[];
8
+ static flags: {
9
+ format: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
10
+ provider: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
11
+ };
12
+ run(): Promise<void>;
13
+ }
@@ -0,0 +1,81 @@
1
+ import { Args, Command, Flags } from '@oclif/core';
2
+ import { FileSystemService } from '../../../agent/infra/file-system/file-system-service.js';
3
+ import { loadSwarmConfig } from '../../../agent/infra/swarm/config/swarm-config-loader.js';
4
+ import { buildProvidersFromConfig } from '../../../agent/infra/swarm/provider-factory.js';
5
+ import { SwarmCoordinator } from '../../../agent/infra/swarm/swarm-coordinator.js';
6
+ import { validateSwarmProviders } from '../../../agent/infra/swarm/validation/config-validator.js';
7
+ import { createSearchKnowledgeService } from '../../../agent/infra/tools/implementations/search-knowledge-service.js';
8
+ export default class SwarmCurate extends Command {
9
+ static args = {
10
+ content: Args.string({ description: 'Knowledge content to store in a swarm provider', required: true }),
11
+ };
12
+ static description = 'Store knowledge in a swarm provider (GBrain, local markdown)';
13
+ static examples = [
14
+ '<%= config.bin %> swarm curate "Dario Amodei is CEO of Anthropic"',
15
+ '<%= config.bin %> swarm curate "meeting notes: decided on JWT" --provider local-markdown:notes',
16
+ '<%= config.bin %> swarm curate "Architecture uses event sourcing" --provider gbrain',
17
+ ];
18
+ static flags = {
19
+ format: Flags.string({
20
+ char: 'f',
21
+ default: 'text',
22
+ description: 'Output format',
23
+ options: ['text', 'json'],
24
+ }),
25
+ provider: Flags.string({
26
+ char: 'p',
27
+ description: 'Target provider ID (e.g., gbrain, local-markdown:notes)',
28
+ }),
29
+ };
30
+ async run() {
31
+ const { args, flags } = await this.parse(SwarmCurate);
32
+ const isJson = flags.format === 'json';
33
+ try {
34
+ const config = await loadSwarmConfig(process.cwd());
35
+ // Validate enrichment topology only (provider errors handled by health checks)
36
+ const validation = await validateSwarmProviders(config);
37
+ const topologyErrors = validation.errors.filter((e) => e.provider === 'enrichment');
38
+ if (topologyErrors.length > 0) {
39
+ const messages = topologyErrors.map((e) => e.message);
40
+ throw new Error(`Invalid enrichment topology:\n ${messages.join('\n ')}`);
41
+ }
42
+ const workingDirectory = process.cwd();
43
+ const fileSystemService = new FileSystemService({ workingDirectory });
44
+ await fileSystemService.initialize();
45
+ const searchService = createSearchKnowledgeService(fileSystemService, {
46
+ baseDirectory: workingDirectory,
47
+ });
48
+ const providers = buildProvidersFromConfig(config, { searchService });
49
+ const coordinator = new SwarmCoordinator(providers, config);
50
+ await coordinator.refreshHealth();
51
+ const result = await coordinator.store({
52
+ content: args.content,
53
+ provider: flags.provider,
54
+ });
55
+ if (isJson) {
56
+ this.log(JSON.stringify(result, undefined, 2));
57
+ }
58
+ else if (result.success && result.fallback) {
59
+ const idPart = result.id ? ` as ${result.id}` : '';
60
+ this.log(`Stored to ${result.provider} (fallback — no external providers available)${idPart}`);
61
+ }
62
+ else if (result.success) {
63
+ this.log(`Stored to ${result.provider} as ${result.id}`);
64
+ }
65
+ else {
66
+ this.logToStderr(`Error: ${result.error ?? 'Store failed'}`);
67
+ this.exit(2);
68
+ }
69
+ }
70
+ catch (error) {
71
+ const message = error instanceof Error ? error.message : String(error);
72
+ if (isJson) {
73
+ this.log(JSON.stringify({ error: message, success: false }));
74
+ }
75
+ else {
76
+ this.logToStderr(`Error: ${message}`);
77
+ this.exit(2);
78
+ }
79
+ }
80
+ }
81
+ }
@@ -0,0 +1,6 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class SwarmOnboard extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ run(): Promise<void>;
6
+ }