byterover-cli 3.11.0 → 3.13.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 (102) hide show
  1. package/.env.production +2 -1
  2. package/dist/agent/infra/tools/implementations/curate-tool.js +18 -8
  3. package/dist/oclif/commands/curate/index.js +6 -0
  4. package/dist/oclif/commands/providers/connect.d.ts +26 -1
  5. package/dist/oclif/commands/providers/connect.js +95 -17
  6. package/dist/oclif/commands/providers/list.d.ts +10 -1
  7. package/dist/oclif/commands/providers/list.js +35 -3
  8. package/dist/oclif/commands/query.js +6 -0
  9. package/dist/oclif/commands/status.js +4 -0
  10. package/dist/oclif/lib/billing-line.d.ts +8 -0
  11. package/dist/oclif/lib/billing-line.js +45 -0
  12. package/dist/oclif/lib/format-billing-line.d.ts +2 -0
  13. package/dist/oclif/lib/format-billing-line.js +19 -0
  14. package/dist/oclif/lib/insufficient-credits.d.ts +11 -0
  15. package/dist/oclif/lib/insufficient-credits.js +36 -0
  16. package/dist/server/config/environment.d.ts +1 -0
  17. package/dist/server/config/environment.js +3 -0
  18. package/dist/server/constants.d.ts +6 -0
  19. package/dist/server/constants.js +11 -0
  20. package/dist/server/core/domain/entities/task-history-entry.d.ts +775 -0
  21. package/dist/server/core/domain/entities/task-history-entry.js +88 -0
  22. package/dist/server/core/domain/transport/schemas.d.ts +1420 -11
  23. package/dist/server/core/domain/transport/schemas.js +160 -6
  24. package/dist/server/core/domain/transport/task-info.d.ts +18 -0
  25. package/dist/server/core/interfaces/process/i-task-lifecycle-hook.d.ts +7 -0
  26. package/dist/server/core/interfaces/services/i-billing-service.d.ts +26 -0
  27. package/dist/server/core/interfaces/services/i-billing-service.js +1 -0
  28. package/dist/server/core/interfaces/storage/i-billing-config-store.d.ts +4 -0
  29. package/dist/server/core/interfaces/storage/i-billing-config-store.js +1 -0
  30. package/dist/server/core/interfaces/storage/i-task-history-store.d.ts +62 -0
  31. package/dist/server/core/interfaces/storage/i-task-history-store.js +1 -0
  32. package/dist/server/infra/billing/billing-state-endpoint.d.ts +4 -0
  33. package/dist/server/infra/billing/billing-state-endpoint.js +7 -0
  34. package/dist/server/infra/billing/build-status-billing.d.ts +9 -0
  35. package/dist/server/infra/billing/build-status-billing.js +36 -0
  36. package/dist/server/infra/billing/http-billing-service.d.ts +19 -0
  37. package/dist/server/infra/billing/http-billing-service.js +57 -0
  38. package/dist/server/infra/billing/paid-organizations-endpoint.d.ts +8 -0
  39. package/dist/server/infra/billing/paid-organizations-endpoint.js +18 -0
  40. package/dist/server/infra/billing/resolve-billing-source.d.ts +13 -0
  41. package/dist/server/infra/billing/resolve-billing-source.js +36 -0
  42. package/dist/server/infra/billing/resolve-billing-team.d.ts +5 -0
  43. package/dist/server/infra/billing/resolve-billing-team.js +8 -0
  44. package/dist/server/infra/connectors/rules/rules-connector.js +7 -2
  45. package/dist/server/infra/connectors/shared/constants.d.ts +9 -0
  46. package/dist/server/infra/connectors/shared/constants.js +31 -5
  47. package/dist/server/infra/daemon/agent-process.js +10 -8
  48. package/dist/server/infra/daemon/brv-server.js +48 -18
  49. package/dist/server/infra/dream/dream-response-schemas.d.ts +24 -0
  50. package/dist/server/infra/dream/dream-response-schemas.js +7 -0
  51. package/dist/server/infra/dream/operations/consolidate.js +21 -8
  52. package/dist/server/infra/dream/operations/synthesize.js +35 -8
  53. package/dist/server/infra/http/provider-model-fetchers.js +10 -4
  54. package/dist/server/infra/process/feature-handlers.d.ts +3 -1
  55. package/dist/server/infra/process/feature-handlers.js +26 -2
  56. package/dist/server/infra/process/task-history-entry-builder.d.ts +36 -0
  57. package/dist/server/infra/process/task-history-entry-builder.js +101 -0
  58. package/dist/server/infra/process/task-history-hook.d.ts +37 -0
  59. package/dist/server/infra/process/task-history-hook.js +70 -0
  60. package/dist/server/infra/process/task-history-store-cache.d.ts +25 -0
  61. package/dist/server/infra/process/task-history-store-cache.js +106 -0
  62. package/dist/server/infra/process/task-router.d.ts +72 -0
  63. package/dist/server/infra/process/task-router.js +690 -15
  64. package/dist/server/infra/process/transport-handlers.d.ts +8 -0
  65. package/dist/server/infra/process/transport-handlers.js +2 -0
  66. package/dist/server/infra/storage/file-billing-config-store.d.ts +13 -0
  67. package/dist/server/infra/storage/file-billing-config-store.js +55 -0
  68. package/dist/server/infra/storage/file-task-history-store.d.ts +294 -0
  69. package/dist/server/infra/storage/file-task-history-store.js +912 -0
  70. package/dist/server/infra/transport/handlers/auth-handler.d.ts +4 -0
  71. package/dist/server/infra/transport/handlers/auth-handler.js +20 -2
  72. package/dist/server/infra/transport/handlers/billing-handler.d.ts +30 -0
  73. package/dist/server/infra/transport/handlers/billing-handler.js +132 -0
  74. package/dist/server/infra/transport/handlers/index.d.ts +4 -0
  75. package/dist/server/infra/transport/handlers/index.js +2 -0
  76. package/dist/server/infra/transport/handlers/init-handler.js +2 -0
  77. package/dist/server/infra/transport/handlers/status-handler.d.ts +14 -0
  78. package/dist/server/infra/transport/handlers/status-handler.js +16 -0
  79. package/dist/server/infra/transport/handlers/team-handler.d.ts +19 -0
  80. package/dist/server/infra/transport/handlers/team-handler.js +40 -0
  81. package/dist/shared/transport/events/auth-events.d.ts +3 -0
  82. package/dist/shared/transport/events/billing-events.d.ts +48 -0
  83. package/dist/shared/transport/events/billing-events.js +8 -0
  84. package/dist/shared/transport/events/index.d.ts +16 -0
  85. package/dist/shared/transport/events/index.js +6 -0
  86. package/dist/shared/transport/events/task-events.d.ts +204 -1
  87. package/dist/shared/transport/events/task-events.js +11 -0
  88. package/dist/shared/transport/events/team-events.d.ts +8 -0
  89. package/dist/shared/transport/events/team-events.js +3 -0
  90. package/dist/shared/transport/types/dto.d.ts +80 -0
  91. package/dist/tui/features/tasks/hooks/use-task-subscriptions.js +7 -0
  92. package/dist/tui/features/tasks/stores/tasks-store.d.ts +4 -16
  93. package/dist/tui/features/tasks/stores/tasks-store.js +7 -0
  94. package/dist/tui/types/messages.d.ts +2 -9
  95. package/dist/webui/assets/index-B9JmEFOK.js +130 -0
  96. package/dist/webui/assets/index-CMIKsBMr.css +1 -0
  97. package/dist/webui/index.html +2 -2
  98. package/dist/webui/sw.js +1 -1
  99. package/oclif.manifest.json +653 -645
  100. package/package.json +1 -1
  101. package/dist/webui/assets/index--sXE__bc.css +0 -1
  102. package/dist/webui/assets/index-Bkkx961b.js +0 -130
@@ -1,11 +1,22 @@
1
+ /**
2
+ * Persisted-entry schema version. Bumped only on shape-breaking changes to
3
+ * `TaskHistoryEntry`. The Zod schema in `server/core/domain/entities/` uses
4
+ * `z.literal(TASK_HISTORY_SCHEMA_VERSION)` to refuse mismatched on-disk lines.
5
+ */
6
+ export declare const TASK_HISTORY_SCHEMA_VERSION = 1;
1
7
  export declare const TaskEvents: {
2
8
  readonly ACK: "task:ack";
3
9
  readonly CANCEL: "task:cancel";
4
10
  readonly CANCELLED: "task:cancelled";
11
+ readonly CLEAR_COMPLETED: "task:clearCompleted";
5
12
  readonly COMPLETED: "task:completed";
6
13
  readonly CREATE: "task:create";
7
14
  readonly CREATED: "task:created";
15
+ readonly DELETE: "task:delete";
16
+ readonly DELETE_BULK: "task:deleteBulk";
17
+ readonly DELETED: "task:deleted";
8
18
  readonly ERROR: "task:error";
19
+ readonly GET: "task:get";
9
20
  readonly LIST: "task:list";
10
21
  readonly STARTED: "task:started";
11
22
  };
@@ -30,6 +41,33 @@ export interface TaskCancelResponse {
30
41
  success: boolean;
31
42
  }
32
43
  export type TaskListItemStatus = 'cancelled' | 'completed' | 'created' | 'error' | 'started';
44
+ /**
45
+ * Reasoning/thinking content item with timestamp for ordering.
46
+ * Shared between webui, tui, and the server-side TaskHistoryEntry.
47
+ */
48
+ export type ReasoningContentItem = {
49
+ content: string;
50
+ /** Whether this reasoning item is still being streamed */
51
+ isThinking?: boolean;
52
+ timestamp: number;
53
+ };
54
+ /**
55
+ * Persisted tool-call lifecycle entry — distinct from the wire-payload
56
+ * `LlmToolCallEventSchema` in `core/domain/transport/schemas.ts`. This shape
57
+ * carries the `running | completed | error` state machine and is the form
58
+ * stored in `TaskHistoryEntry.toolCalls`.
59
+ */
60
+ export type ToolCallEvent = {
61
+ args: Record<string, unknown>;
62
+ callId?: string;
63
+ error?: string;
64
+ errorType?: string;
65
+ result?: unknown;
66
+ sessionId: string;
67
+ status: 'completed' | 'error' | 'running';
68
+ timestamp: number;
69
+ toolName: string;
70
+ };
33
71
  export interface TaskListItem {
34
72
  completedAt?: number;
35
73
  content: string;
@@ -37,22 +75,187 @@ export interface TaskListItem {
37
75
  error?: {
38
76
  code?: string;
39
77
  message: string;
40
- name?: string;
78
+ name: string;
41
79
  };
42
80
  /** Optional file paths from `curate --files` */
43
81
  files?: string[];
44
82
  /** Folder path for `curate-folder` tasks */
45
83
  folderPath?: string;
84
+ /** Active model id at task creation time */
85
+ model?: string;
46
86
  projectPath?: string;
87
+ /** Active provider id at task creation time */
88
+ provider?: string;
47
89
  result?: string;
48
90
  startedAt?: number;
49
91
  status: TaskListItemStatus;
50
92
  taskId: string;
51
93
  type: string;
52
94
  }
95
+ /**
96
+ * task:list request — numbered pagination + filter/search (M2.16).
97
+ * All filter dims are optional; AND-combined when multiple are set.
98
+ */
53
99
  export interface TaskListRequest {
100
+ /** createdAt >= this epoch ms */
101
+ createdAfter?: number;
102
+ /** createdAt <= this epoch ms */
103
+ createdBefore?: number;
104
+ /** Maximum elapsed time (ms) for terminal tasks. */
105
+ maxDurationMs?: number;
106
+ /** Minimum elapsed time (ms); only matches startedAt+completedAt rows. */
107
+ minDurationMs?: number;
108
+ /** Filter to these model ids (exact match). */
109
+ model?: string[];
110
+ /** 1-based page index; defaults to 1. */
111
+ page?: number;
112
+ /** Page size 1..1000; defaults to 50. */
113
+ pageSize?: number;
54
114
  projectPath?: string;
115
+ /** Filter to these provider ids (exact match). */
116
+ provider?: string[];
117
+ /** Case-insensitive substring on content + result + error.message. */
118
+ searchText?: string;
119
+ status?: TaskListItemStatus[];
120
+ type?: string[];
121
+ }
122
+ /** Status histogram used by FE filter-bar breakdown (M2.16). */
123
+ export interface TaskListCounts {
124
+ all: number;
125
+ cancelled: number;
126
+ completed: number;
127
+ /** Tasks with status === 'error'. */
128
+ failed: number;
129
+ /** Tasks with status === 'created' || 'started'. */
130
+ running: number;
131
+ }
132
+ /** (providerId, modelId) pair from history (M2.16). */
133
+ export interface TaskListAvailableModel {
134
+ modelId: string;
135
+ providerId: string;
55
136
  }
56
137
  export interface TaskListResponse {
138
+ /** Distinct (providerId, modelId) pairs seen in candidate set. */
139
+ availableModels: TaskListAvailableModel[];
140
+ /** Distinct providerId values seen in candidate set. */
141
+ availableProviders: string[];
142
+ /**
143
+ * Status histogram matching current filter scope (Model A — post-filter).
144
+ * `counts.all === total` invariant. When user picks `status: ['error']`,
145
+ * `counts.failed === total` and other buckets are 0.
146
+ */
147
+ counts: TaskListCounts;
148
+ /**
149
+ * 1-based page index, echoed back as-sent. Server clamps the LOWER bound
150
+ * (page < 1 → 1) but does NOT clamp against `pageCount`. A request with
151
+ * `page=9999` against a 1-page result returns `page: 9999, tasks: []` so
152
+ * the caller can detect an out-of-range page.
153
+ */
154
+ page: number;
155
+ /** ceil(total / pageSize), min 1. */
156
+ pageCount: number;
157
+ /** Page size echoed back, clamped to [1, 1000]. */
158
+ pageSize: number;
57
159
  tasks: TaskListItem[];
160
+ /** Total items matching ALL filters (incl. status). */
161
+ total: number;
58
162
  }
163
+ export type TaskClearCompletedRequest = {
164
+ projectPath?: string;
165
+ };
166
+ export type TaskClearCompletedResponse = {
167
+ deletedCount: number;
168
+ error?: string;
169
+ };
170
+ export type TaskDeleteBulkRequest = {
171
+ taskIds: string[];
172
+ };
173
+ export type TaskDeleteBulkResponse = {
174
+ deletedCount: number;
175
+ error?: string;
176
+ };
177
+ export type TaskDeleteRequest = {
178
+ taskId: string;
179
+ };
180
+ export type TaskDeleteResponse = {
181
+ error?: string;
182
+ /**
183
+ * `true` when the task was actually removed (was live or persisted),
184
+ * `false` when the call was a no-op (taskId unknown or already tombstoned).
185
+ * `task:deleteBulk` uses this to compute an accurate `deletedCount`.
186
+ */
187
+ removed?: boolean;
188
+ success: boolean;
189
+ };
190
+ export type TaskDeletedEvent = {
191
+ taskId: string;
192
+ };
193
+ export type TaskGetRequest = {
194
+ taskId: string;
195
+ };
196
+ export type TaskGetResponse = {
197
+ task: null | TaskHistoryEntry;
198
+ };
199
+ /**
200
+ * Full per-task error payload — superset of `TaskListItem.error`, adds the
201
+ * optional `details` bag. Mirrors `TaskErrorDataSchema` in
202
+ * `src/server/core/domain/entities/task-history-entry.ts`; the server schema
203
+ * carries `satisfies z.ZodType<TaskErrorData>` to keep them aligned.
204
+ */
205
+ export type TaskErrorData = {
206
+ code?: string;
207
+ details?: Record<string, unknown>;
208
+ message: string;
209
+ name: string;
210
+ };
211
+ /**
212
+ * Discriminated-union shape for a persisted task. The server-side Zod schema
213
+ * (`TaskHistoryEntrySchema`) is the runtime source of truth and carries
214
+ * `satisfies z.ZodType<TaskHistoryEntry>` so any drift between the two
215
+ * representations is a typecheck error.
216
+ *
217
+ * Lives in `shared/` so webui + tui can consume it without inverting the
218
+ * dependency direction onto `server/`.
219
+ */
220
+ type TaskHistoryEntryBase = {
221
+ clientCwd?: string;
222
+ content: string;
223
+ createdAt: number;
224
+ files?: string[];
225
+ folderPath?: string;
226
+ id: string;
227
+ logId?: string;
228
+ model?: string;
229
+ projectPath: string;
230
+ provider?: string;
231
+ reasoningContents?: ReasoningContentItem[];
232
+ responseContent?: string;
233
+ schemaVersion: typeof TASK_HISTORY_SCHEMA_VERSION;
234
+ sessionId?: string;
235
+ taskId: string;
236
+ toolCalls?: ToolCallEvent[];
237
+ type: string;
238
+ worktreeRoot?: string;
239
+ };
240
+ export type TaskHistoryEntry = (TaskHistoryEntryBase & {
241
+ completedAt: number;
242
+ error: TaskErrorData;
243
+ startedAt?: number;
244
+ status: 'error';
245
+ }) | (TaskHistoryEntryBase & {
246
+ completedAt: number;
247
+ result?: string;
248
+ startedAt?: number;
249
+ status: 'completed';
250
+ }) | (TaskHistoryEntryBase & {
251
+ completedAt: number;
252
+ startedAt?: number;
253
+ status: 'cancelled';
254
+ }) | (TaskHistoryEntryBase & {
255
+ startedAt: number;
256
+ status: 'started';
257
+ }) | (TaskHistoryEntryBase & {
258
+ status: 'created';
259
+ });
260
+ export type TaskHistoryStatus = TaskHistoryEntry['status'];
261
+ export {};
@@ -1,11 +1,22 @@
1
+ /**
2
+ * Persisted-entry schema version. Bumped only on shape-breaking changes to
3
+ * `TaskHistoryEntry`. The Zod schema in `server/core/domain/entities/` uses
4
+ * `z.literal(TASK_HISTORY_SCHEMA_VERSION)` to refuse mismatched on-disk lines.
5
+ */
6
+ export const TASK_HISTORY_SCHEMA_VERSION = 1;
1
7
  export const TaskEvents = {
2
8
  ACK: 'task:ack',
3
9
  CANCEL: 'task:cancel',
4
10
  CANCELLED: 'task:cancelled',
11
+ CLEAR_COMPLETED: 'task:clearCompleted',
5
12
  COMPLETED: 'task:completed',
6
13
  CREATE: 'task:create',
7
14
  CREATED: 'task:created',
15
+ DELETE: 'task:delete',
16
+ DELETE_BULK: 'task:deleteBulk',
17
+ DELETED: 'task:deleted',
8
18
  ERROR: 'task:error',
19
+ GET: 'task:get',
9
20
  LIST: 'task:list',
10
21
  STARTED: 'task:started',
11
22
  };
@@ -0,0 +1,8 @@
1
+ import type { TeamDTO } from '../types/dto.js';
2
+ export declare const TeamEvents: {
3
+ readonly LIST: "team:list";
4
+ };
5
+ export interface TeamListResponse {
6
+ error?: string;
7
+ teams?: TeamDTO[];
8
+ }
@@ -0,0 +1,3 @@
1
+ export const TeamEvents = {
2
+ LIST: 'team:list',
3
+ };
@@ -25,10 +25,12 @@ export interface BrvConfigDTO {
25
25
  version: string;
26
26
  }
27
27
  export interface TeamDTO {
28
+ avatarUrl: string;
28
29
  displayName: string;
29
30
  id: string;
30
31
  isDefault: boolean;
31
32
  name: string;
33
+ slug: string;
32
34
  }
33
35
  export interface SpaceDTO {
34
36
  id: string;
@@ -49,6 +51,66 @@ export interface ConnectorDTO {
49
51
  defaultType: ConnectorType;
50
52
  supportedTypes: ConnectorType[];
51
53
  }
54
+ /**
55
+ * Mirror of the upstream ByteRover billing API
56
+ * (`GET /api/v1/billing/usage/{organizationId}/by-projects`).
57
+ *
58
+ * Field shape is preserved so the daemon can pass through without remapping.
59
+ */
60
+ export type BillingTier = 'FREE' | 'PRO' | 'TEAM';
61
+ export interface BillingOrganizationTierDTO {
62
+ /** True while the org is in a trial window for `tier`. */
63
+ isTrialing: boolean;
64
+ organizationId: string;
65
+ tier: BillingTier;
66
+ }
67
+ /**
68
+ * Per-organization billing usage. Joins `/billing/usages` org entries with
69
+ * `/billing/organizations/tiers` so consumers see one DTO per org.
70
+ */
71
+ export interface BillingUsageDTO {
72
+ /** Add-on credits remaining beyond the base `limit`. */
73
+ addOnRemaining: number;
74
+ /** True while the org is in a trial window for `tier`. */
75
+ isTrialing: boolean;
76
+ /** Base compute-unit limit for the current billing period. */
77
+ limit: number;
78
+ /** True when the organization has consumed >= `totalLimit`. */
79
+ limitExceeded: boolean;
80
+ organizationId: string;
81
+ /** Display name from the billing service (typically matches the team display name). */
82
+ organizationName: string;
83
+ /** Free-form status string from the billing service (e.g. 'ACTIVE', 'SUSPENDED'). */
84
+ organizationStatus: string;
85
+ /** Percentage of `totalLimit` consumed (0–100). */
86
+ percentUsed: number;
87
+ /** Compute units still available this period (counting add-ons). */
88
+ remaining: number;
89
+ /** Defaults to `FREE` when the tiers endpoint omits the org. */
90
+ tier: BillingTier;
91
+ /** `limit + addOnRemaining` — total credits available this period. */
92
+ totalLimit: number;
93
+ /** Compute units consumed so far this period. */
94
+ used: number;
95
+ }
96
+ /**
97
+ * Free-tier limit for users without a paid organization. Daily and monthly
98
+ * caps are reported separately so the UI can surface whichever is closer to
99
+ * exhaustion.
100
+ */
101
+ export interface BillingFreeUserLimitWindowDTO {
102
+ limit: number;
103
+ limitExceeded: boolean;
104
+ percentUsed: number;
105
+ remaining: number;
106
+ used: number;
107
+ }
108
+ export interface BillingFreeUserLimitDTO {
109
+ daily: BillingFreeUserLimitWindowDTO;
110
+ /** True when either window is exhausted. Mirrors the upstream top-level field. */
111
+ limitExceeded: boolean;
112
+ monthly: BillingFreeUserLimitWindowDTO;
113
+ }
52
114
  export interface ProviderDTO {
53
115
  /** Currently selected model for this provider, if any. Absent means connected but model not yet picked. */
54
116
  activeModel?: string;
@@ -122,6 +184,22 @@ export interface ProjectLocationDTO {
122
184
  isInitialized: boolean;
123
185
  projectPath: string;
124
186
  }
187
+ export type StatusBillingSource = 'free' | 'other-provider' | 'paid';
188
+ export type StatusBillingDTO = {
189
+ activeProvider?: string;
190
+ source: 'other-provider';
191
+ } | {
192
+ organizationId: string;
193
+ organizationName?: string;
194
+ remaining?: number;
195
+ source: 'paid';
196
+ tier?: BillingTier;
197
+ total?: number;
198
+ } | {
199
+ remaining?: number;
200
+ source: 'free';
201
+ total?: number;
202
+ };
125
203
  export interface StatusDTO {
126
204
  /** Current state of the background abstract generation queue, if active */
127
205
  abstractQueue?: {
@@ -131,6 +209,8 @@ export interface StatusDTO {
131
209
  processing: boolean;
132
210
  };
133
211
  authStatus: 'expired' | 'logged_in' | 'not_logged_in' | 'unknown';
212
+ /** Resolved billing source for the byterover provider (omitted on transport/billing failure). */
213
+ billing?: StatusBillingDTO;
134
214
  contextTreeChanges?: ContextTreeChanges;
135
215
  /** Absolute path to the context tree directory (e.g., '/Users/foo/project/.brv/context-tree') */
136
216
  contextTreeDir?: string;
@@ -23,6 +23,13 @@ export function useTaskSubscriptions() {
23
23
  store.setError(data.taskId, data.error);
24
24
  }), client.on('task:cancelled', (data) => {
25
25
  store.setCancelled(data.taskId);
26
+ }),
27
+ // task:deleted is broadcast by the daemon when ANY client (this TUI, the
28
+ // WebUI, or another tab) removes a task via task:delete /
29
+ // task:deleteBulk / task:clearCompleted. Drop the row locally so all
30
+ // surfaces stay in sync without polling.
31
+ client.on('task:deleted', (data) => {
32
+ store.removeTask(data.taskId);
26
33
  }), client.on('llmservice:toolCall', (data) => {
27
34
  if (!data.taskId)
28
35
  return;
@@ -4,24 +4,10 @@
4
4
  * Zustand store for task lifecycle state.
5
5
  * Subscribes to task:* and llmservice:* transport events.
6
6
  */
7
+ import type { ReasoningContentItem, ToolCallEvent } from '../../../../shared/transport/events/task-events.js';
7
8
  import type { TaskStats } from '../../../types/ui.js';
8
9
  export type TaskStatus = 'cancelled' | 'completed' | 'created' | 'error' | 'started';
9
- export interface ToolCallEvent {
10
- args: Record<string, unknown>;
11
- callId?: string;
12
- error?: string;
13
- errorType?: string;
14
- result?: unknown;
15
- sessionId: string;
16
- status: 'completed' | 'error' | 'running';
17
- timestamp: number;
18
- toolName: string;
19
- }
20
- export interface ReasoningContentItem {
21
- content: string;
22
- isThinking?: boolean;
23
- timestamp: number;
24
- }
10
+ export type { ReasoningContentItem, ToolCallEvent } from '../../../../shared/transport/events/task-events.js';
25
11
  export interface TaskErrorData {
26
12
  code?: string;
27
13
  message: string;
@@ -76,6 +62,8 @@ export interface TasksActions {
76
62
  createTask: (taskId: string, type: 'curate' | 'query', content: string, files?: string[]) => void;
77
63
  /** Get a task by ID */
78
64
  getTask: (taskId: string) => Task | undefined;
65
+ /** Remove a task from local state (driven by `task:deleted` broadcast). */
66
+ removeTask: (taskId: string) => void;
79
67
  /** Set task to cancelled */
80
68
  setCancelled: (taskId: string) => void;
81
69
  /** Set task to completed with result */
@@ -127,6 +127,13 @@ export const useTasksStore = create()((set, get) => ({
127
127
  return { stats: computeStats(tasks), tasks };
128
128
  }),
129
129
  getTask: (taskId) => get().tasks.get(taskId),
130
+ removeTask: (taskId) => set((state) => {
131
+ if (!state.tasks.has(taskId))
132
+ return state;
133
+ const tasks = new Map(state.tasks);
134
+ tasks.delete(taskId);
135
+ return { stats: computeStats(tasks), tasks };
136
+ }),
130
137
  setCancelled: (taskId) => set((state) => {
131
138
  const task = state.tasks.get(taskId);
132
139
  if (!task) {
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * Message and activity log types
3
3
  */
4
+ import type { ReasoningContentItem } from '../../shared/transport/events/task-events.js';
4
5
  /**
5
6
  * Status of an execution (curate/query job)
6
7
  */
@@ -54,15 +55,7 @@ export interface ToolProgressItem {
54
55
  /** Tool name */
55
56
  toolCallName: string;
56
57
  }
57
- /**
58
- * Reasoning content item with timestamp for sorting
59
- */
60
- export interface ReasoningContentItem {
61
- content: string;
62
- /** Whether this reasoning item is still being streamed */
63
- isThinking?: boolean;
64
- timestamp: number;
65
- }
58
+ export type { ReasoningContentItem } from '../../shared/transport/events/task-events.js';
66
59
  /**
67
60
  * Activity log item for displaying in logs view
68
61
  */