byterover-cli 3.10.3 → 3.12.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 (75) hide show
  1. package/README.md +4 -2
  2. package/dist/agent/core/domain/llm/registry.d.ts +12 -0
  3. package/dist/agent/core/domain/llm/registry.js +49 -0
  4. package/dist/agent/core/domain/llm/types.d.ts +6 -0
  5. package/dist/agent/core/interfaces/i-content-generator.d.ts +8 -0
  6. package/dist/agent/infra/llm/agent-llm-service.js +18 -6
  7. package/dist/agent/infra/llm/context/context-manager.d.ts +4 -1
  8. package/dist/agent/infra/llm/context/context-manager.js +5 -1
  9. package/dist/agent/infra/llm/generators/ai-sdk-content-generator.d.ts +13 -0
  10. package/dist/agent/infra/llm/generators/ai-sdk-content-generator.js +19 -6
  11. package/dist/agent/infra/llm/generators/ai-sdk-message-converter.js +16 -4
  12. package/dist/agent/infra/llm/generators/byterover-content-generator.d.ts +1 -0
  13. package/dist/agent/infra/llm/generators/byterover-content-generator.js +4 -1
  14. package/dist/agent/infra/llm/model-capabilities.d.ts +2 -1
  15. package/dist/agent/infra/llm/model-capabilities.js +6 -4
  16. package/dist/agent/infra/llm/providers/anthropic.js +2 -0
  17. package/dist/agent/infra/llm/providers/deepseek.d.ts +10 -0
  18. package/dist/agent/infra/llm/providers/deepseek.js +33 -0
  19. package/dist/agent/infra/llm/providers/glm-coding-plan.d.ts +9 -0
  20. package/dist/agent/infra/llm/providers/glm-coding-plan.js +32 -0
  21. package/dist/agent/infra/llm/providers/index.js +4 -0
  22. package/dist/agent/infra/llm/providers/openrouter.js +2 -0
  23. package/dist/agent/infra/tools/implementations/curate-tool.js +18 -8
  24. package/dist/oclif/commands/query.js +7 -1
  25. package/dist/oclif/lib/task-client.d.ts +9 -0
  26. package/dist/oclif/lib/task-client.js +11 -1
  27. package/dist/server/constants.d.ts +6 -0
  28. package/dist/server/constants.js +11 -0
  29. package/dist/server/core/domain/entities/provider-registry.js +26 -0
  30. package/dist/server/core/domain/entities/task-history-entry.d.ts +775 -0
  31. package/dist/server/core/domain/entities/task-history-entry.js +88 -0
  32. package/dist/server/core/domain/transport/schemas.d.ts +1403 -11
  33. package/dist/server/core/domain/transport/schemas.js +157 -6
  34. package/dist/server/core/domain/transport/task-info.d.ts +18 -0
  35. package/dist/server/core/interfaces/process/i-task-lifecycle-hook.d.ts +7 -0
  36. package/dist/server/core/interfaces/storage/i-task-history-store.d.ts +62 -0
  37. package/dist/server/core/interfaces/storage/i-task-history-store.js +1 -0
  38. package/dist/server/infra/daemon/brv-server.js +43 -18
  39. package/dist/server/infra/dream/dream-response-schemas.d.ts +24 -0
  40. package/dist/server/infra/dream/dream-response-schemas.js +7 -0
  41. package/dist/server/infra/dream/operations/consolidate.js +21 -8
  42. package/dist/server/infra/dream/operations/synthesize.js +35 -8
  43. package/dist/server/infra/http/provider-model-fetcher-registry.js +5 -0
  44. package/dist/server/infra/http/provider-model-fetchers.js +54 -27
  45. package/dist/server/infra/process/query-log-handler.d.ts +6 -0
  46. package/dist/server/infra/process/query-log-handler.js +23 -0
  47. package/dist/server/infra/process/task-history-entry-builder.d.ts +36 -0
  48. package/dist/server/infra/process/task-history-entry-builder.js +101 -0
  49. package/dist/server/infra/process/task-history-hook.d.ts +37 -0
  50. package/dist/server/infra/process/task-history-hook.js +70 -0
  51. package/dist/server/infra/process/task-history-store-cache.d.ts +25 -0
  52. package/dist/server/infra/process/task-history-store-cache.js +106 -0
  53. package/dist/server/infra/process/task-router.d.ts +72 -0
  54. package/dist/server/infra/process/task-router.js +690 -15
  55. package/dist/server/infra/process/transport-handlers.d.ts +8 -0
  56. package/dist/server/infra/process/transport-handlers.js +2 -0
  57. package/dist/server/infra/storage/file-task-history-store.d.ts +294 -0
  58. package/dist/server/infra/storage/file-task-history-store.js +912 -0
  59. package/dist/shared/transport/events/index.d.ts +5 -0
  60. package/dist/shared/transport/events/task-events.d.ts +204 -1
  61. package/dist/shared/transport/events/task-events.js +11 -0
  62. package/dist/tui/features/tasks/hooks/use-task-subscriptions.js +7 -0
  63. package/dist/tui/features/tasks/stores/tasks-store.d.ts +4 -16
  64. package/dist/tui/features/tasks/stores/tasks-store.js +7 -0
  65. package/dist/tui/types/messages.d.ts +2 -9
  66. package/dist/webui/assets/index-DyVvFoM6.css +1 -0
  67. package/dist/webui/assets/index-lr0byHh9.js +130 -0
  68. package/dist/webui/index.html +2 -2
  69. package/dist/webui/sw.js +1 -1
  70. package/dist/webui/workbox-9c191d2f.js +1 -0
  71. package/oclif.manifest.json +985 -985
  72. package/package.json +1 -1
  73. package/dist/webui/assets/index-CvcqpMYn.css +0 -1
  74. package/dist/webui/assets/index-thSZZahh.js +0 -130
  75. package/dist/webui/workbox-8c29f6e4.js +0 -1
@@ -6,6 +6,7 @@ import { MarkdownWriter, parseCreatedAt } from '../../../../server/core/domain/k
6
6
  import { determineTier, mergeScoring, recordCurateUpdate, } from '../../../../server/core/domain/knowledge/memory-scoring.js';
7
7
  import { createDefaultRuntimeSignals, } from '../../../../server/core/domain/knowledge/runtime-signals-schema.js';
8
8
  import { warnSidecarFailure } from '../../../../server/core/domain/knowledge/sidecar-logging.js';
9
+ import { isExcludedFromSync } from '../../../../server/infra/context-tree/derived-artifact.js';
9
10
  import { toSnakeCase } from '../../../../server/utils/file-helpers.js';
10
11
  import { deriveImpactFromLoss, detectStructuralLoss } from '../../../core/domain/knowledge/conflict-detector.js';
11
12
  import { resolveStructuralLoss } from '../../../core/domain/knowledge/conflict-resolver.js';
@@ -268,14 +269,19 @@ const OperationSchema = z.object({
268
269
  type: OperationType.describe('Operation type: ADD, UPDATE, MERGE, or DELETE'),
269
270
  });
270
271
  /**
271
- * Filter out non-existent files from rawConcept.files.
272
- * Returns a new content object with only valid file paths.
272
+ * Filter out non-existent files from rawConcept.files and derived-artifact
273
+ * paths from relations.
273
274
  */
274
275
  async function filterValidFiles(content) {
275
- if (!content.rawConcept?.files || content.rawConcept.files.length === 0) {
276
- return content;
276
+ // Drop relations that won't be pushed — they'd be dangling refs on remote.
277
+ const cleanedRelations = content.relations?.filter((r) => !isExcludedFromSync(r));
278
+ const withCleanRelations = cleanedRelations === content.relations
279
+ ? content
280
+ : { ...content, relations: cleanedRelations };
281
+ if (!withCleanRelations.rawConcept?.files || withCleanRelations.rawConcept.files.length === 0) {
282
+ return withCleanRelations;
277
283
  }
278
- const checks = await Promise.all(content.rawConcept.files.map(async (filePath) => {
284
+ const checks = await Promise.all(withCleanRelations.rawConcept.files.map(async (filePath) => {
279
285
  // Skip filesystem validation for URLs and document references
280
286
  if (filePath.includes('://'))
281
287
  return true;
@@ -284,12 +290,12 @@ async function filterValidFiles(content) {
284
290
  return true;
285
291
  return DirectoryManager.fileExists(filePath);
286
292
  }));
287
- const validFiles = content.rawConcept.files.filter((_, i) => checks[i]);
293
+ const validFiles = withCleanRelations.rawConcept.files.filter((_, i) => checks[i]);
288
294
  // Return content with filtered files (empty array if none exist)
289
295
  return {
290
- ...content,
296
+ ...withCleanRelations,
291
297
  rawConcept: {
292
- ...content.rawConcept,
298
+ ...withCleanRelations.rawConcept,
293
299
  files: validFiles.length > 0 ? validFiles : undefined,
294
300
  },
295
301
  };
@@ -730,6 +736,10 @@ async function executeUpdate(basePath, operation, reviewDisabled, onAfterWrite,
730
736
  const filteredContent = await filterValidFiles(content);
731
737
  // Extract previous summary from existing file's frontmatter (for review UI)
732
738
  const existingParsed = existingContent ? MarkdownWriter.parseContent(existingContent, title) : null;
739
+ if (existingParsed?.relations?.length) {
740
+ // Drop legacy dangling refs before conflict-detection; otherwise resolver unions them back.
741
+ existingParsed.relations = existingParsed.relations.filter((r) => !isExcludedFromSync(r));
742
+ }
733
743
  const previousSummary = existingParsed?.summary;
734
744
  // Detect structural loss and auto-resolve: merge back anything the LLM dropped
735
745
  const proposedContextData = {
@@ -110,7 +110,7 @@ Bad:
110
110
  client,
111
111
  command: 'query',
112
112
  format,
113
- onCompleted: ({ result, taskId: tid }) => {
113
+ onCompleted: ({ durationMs, matchedDocs, result, taskId: tid, tier, topScore }) => {
114
114
  const previousResult = finalResult;
115
115
  // Always prefer the completed payload — it carries the attribution footer
116
116
  // that may not be present in the earlier llmservice:response event.
@@ -133,11 +133,17 @@ Bad:
133
133
  if (format === 'json') {
134
134
  writeJsonResponse({
135
135
  command: 'query',
136
+ // Recall metadata is only present on query tasks; older daemons omit it. Spread
137
+ // conditionally so JSON consumers do not see undefined keys.
136
138
  data: {
139
+ ...(durationMs === undefined ? {} : { durationMs }),
137
140
  event: 'completed',
141
+ ...(matchedDocs === undefined ? {} : { matchedDocs }),
138
142
  result: finalResult,
139
143
  status: 'completed',
140
144
  taskId: tid,
145
+ ...(tier === undefined ? {} : { tier }),
146
+ ...(topScore === undefined ? {} : { topScore }),
141
147
  },
142
148
  success: true,
143
149
  });
@@ -7,6 +7,7 @@
7
7
  * Used by: curate, query commands.
8
8
  */
9
9
  import type { ITransportClient } from '@campfirein/brv-transport-client';
10
+ import type { QueryLogMatchedDoc, QueryLogTier } from '../../server/core/domain/entities/query-log-entry.js';
10
11
  /** Collected tool call with result (mirrors TUI ToolCallEvent) */
11
12
  export interface ToolCallRecord {
12
13
  args: Record<string, unknown>;
@@ -19,7 +20,11 @@ export interface ToolCallRecord {
19
20
  }
20
21
  /** Completion result passed to onCompleted callback */
21
22
  export interface TaskCompletionResult {
23
+ /** Wall-clock execution time for query tasks, in milliseconds. Absent for non-query tasks. */
24
+ durationMs?: number;
22
25
  logId?: string;
26
+ /** Documents matched by the query. Empty array on cache hits; absent for non-query tasks. */
27
+ matchedDocs?: QueryLogMatchedDoc[];
23
28
  /** Pending review notification from the server, present when review is required after task completion. */
24
29
  pendingReview?: {
25
30
  pendingCount: number;
@@ -27,7 +32,11 @@ export interface TaskCompletionResult {
27
32
  };
28
33
  result?: string;
29
34
  taskId: string;
35
+ /** Resolution tier for query tasks. Absent for non-query tasks. */
36
+ tier?: QueryLogTier;
30
37
  toolCalls: ToolCallRecord[];
38
+ /** Top compound score across matchedDocs. Absent for cache hits and non-query tasks. */
39
+ topScore?: number;
31
40
  }
32
41
  /** Error result passed to onError callback */
33
42
  export interface TaskErrorResult {
@@ -195,7 +195,17 @@ export function waitForTaskCompletion(options, log) {
195
195
  const resolvedPendingReview = payload.pendingReviewCount !== undefined && payload.pendingReviewCount > 0
196
196
  ? { pendingCount: payload.pendingReviewCount, reviewUrl: pendingReview?.reviewUrl ?? '' }
197
197
  : pendingReview;
198
- onCompleted({ logId: payload.logId, pendingReview: resolvedPendingReview, result: payload.result, taskId, toolCalls });
198
+ onCompleted({
199
+ durationMs: payload.durationMs,
200
+ logId: payload.logId,
201
+ matchedDocs: payload.matchedDocs,
202
+ pendingReview: resolvedPendingReview,
203
+ result: payload.result,
204
+ taskId,
205
+ tier: payload.tier,
206
+ toolCalls,
207
+ topScore: payload.topScore,
208
+ });
199
209
  resolve();
200
210
  }),
201
211
  // Task error
@@ -63,6 +63,12 @@ export declare const QUERY_LOG_DIR = "query-log";
63
63
  export declare const QUERY_LOG_ID_PREFIX = "qry";
64
64
  export declare const DREAM_LOG_DIR = "dream-log";
65
65
  export declare const DREAM_LOG_ID_PREFIX = "drm";
66
+ export declare const TASK_HISTORY_DIR = "task-history";
67
+ export declare const TASK_HISTORY_ID_PREFIX = "tsk";
68
+ export declare const TASK_HISTORY_DEFAULT_MAX_AGE_DAYS = 0;
69
+ export declare const TASK_HISTORY_DEFAULT_MAX_ENTRIES = 1000;
70
+ export declare const TASK_HISTORY_DEFAULT_MAX_INDEX_BLOAT_RATIO = 2;
71
+ export declare const TASK_HISTORY_STALE_THRESHOLD_MS = 600000;
66
72
  export declare const REVIEW_BACKUPS_DIR = "review-backups";
67
73
  export declare const SUMMARY_INDEX_FILE = "_index.md";
68
74
  export declare const ARCHIVE_DIR = "_archived";
@@ -86,6 +86,17 @@ export const QUERY_LOG_ID_PREFIX = 'qry';
86
86
  // Dream log
87
87
  export const DREAM_LOG_DIR = 'dream-log';
88
88
  export const DREAM_LOG_ID_PREFIX = 'drm';
89
+ // Task history (per-project on-disk task journal — see M2 milestone)
90
+ export const TASK_HISTORY_DIR = 'task-history';
91
+ export const TASK_HISTORY_ID_PREFIX = 'tsk';
92
+ // Age-based prune is disabled by default. Task history is a business artifact
93
+ // (audit/review), not a log — count-based rotation is the sole retention policy.
94
+ // Override per-store via `maxAgeDays` constructor option if a deployment ever
95
+ // needs time-based eviction.
96
+ export const TASK_HISTORY_DEFAULT_MAX_AGE_DAYS = 0;
97
+ export const TASK_HISTORY_DEFAULT_MAX_ENTRIES = 1000;
98
+ export const TASK_HISTORY_DEFAULT_MAX_INDEX_BLOAT_RATIO = 2;
99
+ export const TASK_HISTORY_STALE_THRESHOLD_MS = 600_000;
89
100
  // Review backups (stores pre-curate file content for local HITL review diffs)
90
101
  export const REVIEW_BACKUPS_DIR = 'review-backups';
91
102
  // === Hierarchical DAG (summary, archive, manifest) ===
@@ -72,6 +72,19 @@ export const PROVIDER_REGISTRY = {
72
72
  name: 'DeepInfra',
73
73
  priority: 10,
74
74
  },
75
+ deepseek: {
76
+ apiKeyUrl: 'https://platform.deepseek.com/api_keys',
77
+ baseUrl: 'https://api.deepseek.com/v1',
78
+ category: 'other',
79
+ defaultModel: 'deepseek-chat',
80
+ description: 'DeepSeek V3 and R1 reasoning models',
81
+ envVars: ['DEEPSEEK_API_KEY'],
82
+ headers: {},
83
+ id: 'deepseek',
84
+ modelsEndpoint: '/models',
85
+ name: 'DeepSeek',
86
+ priority: 19,
87
+ },
75
88
  glm: {
76
89
  apiKeyUrl: 'https://open.z.ai',
77
90
  baseUrl: 'https://api.z.ai/api/paas/v4',
@@ -85,6 +98,19 @@ export const PROVIDER_REGISTRY = {
85
98
  name: 'GLM (Z.AI)',
86
99
  priority: 17,
87
100
  },
101
+ 'glm-coding-plan': {
102
+ apiKeyUrl: 'https://z.ai/manage-apikey/apikey-list',
103
+ baseUrl: 'https://api.z.ai/api/coding/paas/v4',
104
+ category: 'other',
105
+ defaultModel: 'glm-4.7',
106
+ description: 'GLM models on the Z.AI Coding Plan subscription',
107
+ envVars: ['ZHIPU_API_KEY'],
108
+ headers: {},
109
+ id: 'glm-coding-plan',
110
+ modelsEndpoint: '',
111
+ name: 'GLM Coding Plan (Z.AI)',
112
+ priority: 17.5,
113
+ },
88
114
  google: {
89
115
  apiKeyUrl: 'https://aistudio.google.com/apikey',
90
116
  baseUrl: '',