@pellux/goodvibes-tui 0.18.13 → 0.18.18

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 (71) hide show
  1. package/CHANGELOG.md +139 -0
  2. package/README.md +1 -1
  3. package/docs/foundation-artifacts/operator-contract.json +1 -1
  4. package/package.json +3 -2
  5. package/src/daemon/cli.ts +82 -6
  6. package/src/input/command-registry.ts +2 -0
  7. package/src/input/commands/control-room-runtime.ts +1 -1
  8. package/src/input/commands/health-runtime.ts +1 -1
  9. package/src/input/commands/local-setup-review.ts +1 -1
  10. package/src/input/commands/platform-access-runtime.ts +1 -1
  11. package/src/input/commands/qrcode-runtime.ts +20 -0
  12. package/src/input/commands/subscription-runtime.ts +1 -1
  13. package/src/input/commands.ts +2 -0
  14. package/src/input/handler-feed.ts +6 -0
  15. package/src/input/handler-modal-routes.ts +19 -2
  16. package/src/input/handler-modal-token-routes.ts +3 -0
  17. package/src/input/handler-picker-routes.ts +4 -2
  18. package/src/input/model-picker.ts +11 -0
  19. package/src/input/settings-modal.ts +31 -3
  20. package/src/panels/agent-logs-panel.ts +23 -24
  21. package/src/panels/base-panel.ts +6 -0
  22. package/src/panels/builtin/session.ts +66 -0
  23. package/src/panels/builtin/shared.ts +1 -1
  24. package/src/panels/provider-account-snapshot.ts +1 -1
  25. package/src/panels/provider-accounts-panel.ts +23 -27
  26. package/src/panels/qr-panel.ts +182 -0
  27. package/src/panels/scrollable-list-panel.ts +407 -0
  28. package/src/panels/services-panel.ts +1 -1
  29. package/src/panels/subscription-panel.ts +1 -1
  30. package/src/panels/types.ts +6 -0
  31. package/src/panels/worktree-panel.ts +20 -19
  32. package/src/renderer/buffer.ts +19 -0
  33. package/src/renderer/compositor.ts +19 -6
  34. package/src/renderer/panel-composite.ts +24 -3
  35. package/src/renderer/qr-renderer.ts +117 -0
  36. package/src/renderer/settings-modal-helpers.ts +122 -0
  37. package/src/renderer/settings-modal.ts +147 -111
  38. package/src/runtime/bootstrap-command-context.ts +1 -1
  39. package/src/runtime/bootstrap-command-parts.ts +31 -15
  40. package/src/runtime/bootstrap-core.ts +23 -1
  41. package/src/runtime/bootstrap.ts +6 -1
  42. package/src/runtime/diagnostics/panels/index.ts +5 -5
  43. package/src/runtime/services.ts +1 -1
  44. package/src/runtime/store/domains/domain-read-matrix.ts +0 -2
  45. package/src/runtime/ui-events.ts +1 -46
  46. package/src/runtime/ui-read-model-helpers.ts +1 -32
  47. package/src/runtime/ui-read-models-observability-maintenance.ts +1 -81
  48. package/src/runtime/ui-read-models-observability-options.ts +1 -5
  49. package/src/runtime/ui-read-models-observability-remote.ts +1 -73
  50. package/src/runtime/ui-read-models-observability-security.ts +1 -172
  51. package/src/runtime/ui-read-models-observability-system.ts +1 -217
  52. package/src/runtime/ui-read-models-observability.ts +1 -59
  53. package/src/runtime/ui-service-queries.ts +1 -114
  54. package/src/version.ts +1 -1
  55. package/src/config/service-registry.ts +0 -1
  56. package/src/config/subscription-providers.ts +0 -1
  57. package/src/runtime/diagnostics/actions.ts +0 -776
  58. package/src/runtime/diagnostics/index.ts +0 -99
  59. package/src/runtime/diagnostics/panels/agents.ts +0 -252
  60. package/src/runtime/diagnostics/panels/events.ts +0 -188
  61. package/src/runtime/diagnostics/panels/health.ts +0 -242
  62. package/src/runtime/diagnostics/panels/tasks.ts +0 -251
  63. package/src/runtime/diagnostics/panels/tool-calls.ts +0 -267
  64. package/src/runtime/diagnostics/provider.ts +0 -262
  65. package/src/runtime/store/domains/conversation.ts +0 -1
  66. package/src/runtime/store/domains/permissions.ts +0 -1
  67. package/src/runtime/store/helpers/reducers/conversation.ts +0 -1
  68. package/src/runtime/store/helpers/reducers/lifecycle.ts +0 -1
  69. package/src/runtime/store/helpers/reducers/shared.ts +0 -60
  70. package/src/runtime/store/helpers/reducers/sync.ts +0 -555
  71. package/src/runtime/store/helpers/reducers.ts +0 -30
@@ -1,267 +0,0 @@
1
- /**
2
- * Tool Calls diagnostic panel data provider.
3
- *
4
- * Subscribes to tool lifecycle events via the RuntimeEventBus and maintains
5
- * a bounded buffer of ToolCallEntry records. Provides filtered snapshots
6
- * for the tool-calls diagnostics panel.
7
- *
8
- * Phase timeline tracking allows the panel to render latency breakdowns
9
- * and highlight failures at any lifecycle phase.
10
- */
11
- import type { RuntimeEventBus, EnvelopeListener } from '@pellux/goodvibes-sdk/platform/runtime/events/index';
12
- import type { AnyRuntimeEvent } from '@pellux/goodvibes-sdk/platform/runtime/events/domain-map';
13
- import type { RuntimeEventEnvelope } from '@pellux/goodvibes-sdk/platform/runtime/events/envelope';
14
- import {
15
- type ToolCallEntry,
16
- type ToolCallPhase,
17
- type DiagnosticFilter,
18
- type PanelConfig,
19
- DEFAULT_PANEL_CONFIG,
20
- applyFilter,
21
- appendBounded,
22
- } from '@pellux/goodvibes-sdk/platform/runtime/diagnostics/types';
23
-
24
- /** Internal mutable tool call record used while the call is in progress. */
25
- interface MutableToolCallRecord {
26
- callId: string;
27
- turnId: string;
28
- tool: string;
29
- args: Record<string, unknown>;
30
- phase: ToolCallPhase;
31
- receivedAt: number;
32
- completedAt?: number;
33
- durationMs?: number;
34
- error?: string;
35
- cancelReason?: string;
36
- permissionApproved?: boolean;
37
- traceId: string;
38
- sessionId: string;
39
- }
40
-
41
- /**
42
- * ToolCallsPanel — diagnostic data provider for tool call telemetry.
43
- *
44
- * Listens to all tool domain events and builds a per-call timeline.
45
- * Completed calls are transferred to a bounded history buffer.
46
- */
47
- export class ToolCallsPanel {
48
- private readonly _config: PanelConfig;
49
- private readonly _eventBus: RuntimeEventBus;
50
- /** Active calls keyed by callId. */
51
- private readonly _active = new Map<string, MutableToolCallRecord>();
52
- /** Completed call history (oldest first). */
53
- private readonly _history: ToolCallEntry[] = [];
54
- /** Registered change notification callbacks. */
55
- private readonly _subscribers = new Set<() => void>();
56
- /** Unsubscribe function returned by the event bus. */
57
- private _unsub: (() => void) | null = null;
58
-
59
- constructor(eventBus: RuntimeEventBus, config: PanelConfig = DEFAULT_PANEL_CONFIG) {
60
- this._eventBus = eventBus;
61
- this._config = config;
62
- this._start();
63
- }
64
-
65
- /**
66
- * Subscribe to the tool domain and wire up event handlers.
67
- * @internal
68
- */
69
- private _start(): void {
70
- const handler: EnvelopeListener<AnyRuntimeEvent> = (
71
- envelope: RuntimeEventEnvelope<AnyRuntimeEvent['type'], AnyRuntimeEvent>
72
- ) => {
73
- this._handleEnvelope(envelope);
74
- };
75
- this._unsub = this._eventBus.onDomain('tools', handler as EnvelopeListener);
76
- }
77
-
78
- /**
79
- * Handle a tool domain envelope, routing to the appropriate update method.
80
- */
81
- private _handleEnvelope(
82
- envelope: RuntimeEventEnvelope<AnyRuntimeEvent['type'], AnyRuntimeEvent>
83
- ): void {
84
- const p = envelope.payload;
85
- // Type narrowing is done by checking the discriminant field on payload.
86
- if (!('type' in p)) return;
87
- const type = (p as { type: string }).type;
88
- const traceId = envelope.traceId;
89
- const sessionId = envelope.sessionId;
90
-
91
- switch (type) {
92
- case 'TOOL_RECEIVED': {
93
- const evt = p as { type: 'TOOL_RECEIVED'; callId: string; turnId: string; tool: string; args: Record<string, unknown> };
94
- this._active.set(evt.callId, {
95
- callId: evt.callId,
96
- turnId: evt.turnId,
97
- tool: evt.tool,
98
- args: evt.args,
99
- phase: 'received',
100
- receivedAt: envelope.ts,
101
- traceId,
102
- sessionId,
103
- });
104
- this._notify();
105
- break;
106
- }
107
- case 'TOOL_VALIDATED':
108
- case 'TOOL_PREHOOKED':
109
- case 'TOOL_EXECUTING':
110
- case 'TOOL_MAPPED':
111
- case 'TOOL_POSTHOOKED': {
112
- const evt = p as { type: string; callId: string };
113
- const phaseMap: Record<string, ToolCallPhase> = {
114
- TOOL_VALIDATED: 'validated',
115
- TOOL_PREHOOKED: 'prehooked',
116
- TOOL_EXECUTING: 'executing',
117
- TOOL_MAPPED: 'mapped',
118
- TOOL_POSTHOOKED: 'posthooked',
119
- };
120
- const record = this._active.get(evt.callId);
121
- if (record) {
122
- record.phase = phaseMap[type]!;
123
- this._notify();
124
- }
125
- break;
126
- }
127
- case 'TOOL_PERMISSIONED': {
128
- const evt = p as { type: 'TOOL_PERMISSIONED'; callId: string; approved: boolean };
129
- const record = this._active.get(evt.callId);
130
- if (record) {
131
- record.phase = 'permissioned';
132
- record.permissionApproved = evt.approved;
133
- this._notify();
134
- }
135
- break;
136
- }
137
- case 'TOOL_SUCCEEDED': {
138
- const evt = p as { type: 'TOOL_SUCCEEDED'; callId: string; durationMs: number };
139
- const record = this._active.get(evt.callId);
140
- if (record) {
141
- record.phase = 'succeeded';
142
- record.completedAt = envelope.ts;
143
- record.durationMs = evt.durationMs;
144
- this._finalize(record);
145
- }
146
- break;
147
- }
148
- case 'TOOL_FAILED': {
149
- const evt = p as { type: 'TOOL_FAILED'; callId: string; error: string; durationMs: number };
150
- const record = this._active.get(evt.callId);
151
- if (record) {
152
- record.phase = 'failed';
153
- record.completedAt = envelope.ts;
154
- record.durationMs = evt.durationMs;
155
- record.error = evt.error;
156
- this._finalize(record);
157
- }
158
- break;
159
- }
160
- case 'TOOL_CANCELLED': {
161
- const evt = p as { type: 'TOOL_CANCELLED'; callId: string; reason?: string };
162
- const record = this._active.get(evt.callId);
163
- if (record) {
164
- record.phase = 'cancelled';
165
- record.completedAt = envelope.ts;
166
- record.cancelReason = evt.reason;
167
- this._finalize(record);
168
- }
169
- break;
170
- }
171
- default:
172
- break;
173
- }
174
- }
175
-
176
- /**
177
- * Move a completed record from active to history.
178
- */
179
- private _finalize(record: MutableToolCallRecord): void {
180
- this._active.delete(record.callId);
181
- const entry: ToolCallEntry = {
182
- callId: record.callId,
183
- turnId: record.turnId,
184
- tool: record.tool,
185
- args: record.args,
186
- phase: record.phase,
187
- receivedAt: record.receivedAt,
188
- completedAt: record.completedAt,
189
- durationMs: record.durationMs,
190
- error: record.error,
191
- cancelReason: record.cancelReason,
192
- permission: record.permissionApproved !== undefined
193
- ? { approved: record.permissionApproved }
194
- : undefined,
195
- traceId: record.traceId,
196
- sessionId: record.sessionId,
197
- };
198
- appendBounded(this._history, entry, this._config.bufferLimit);
199
- this._notify();
200
- }
201
-
202
- /**
203
- * Return a filtered snapshot of tool call entries.
204
- * Active calls are included as their current in-progress state.
205
- * History is ordered most-recent first.
206
- *
207
- * @param filter - Optional filter to restrict entries.
208
- */
209
- public getSnapshot(filter?: DiagnosticFilter): ToolCallEntry[] {
210
- // Convert active records to ToolCallEntry for inclusion
211
- const activeEntries: ToolCallEntry[] = [];
212
- for (const record of this._active.values()) {
213
- activeEntries.push({
214
- callId: record.callId,
215
- turnId: record.turnId,
216
- tool: record.tool,
217
- args: record.args,
218
- phase: record.phase,
219
- receivedAt: record.receivedAt,
220
- completedAt: record.completedAt,
221
- durationMs: record.durationMs,
222
- error: record.error,
223
- cancelReason: record.cancelReason,
224
- permission: record.permissionApproved !== undefined
225
- ? { approved: record.permissionApproved }
226
- : undefined,
227
- traceId: record.traceId,
228
- sessionId: record.sessionId,
229
- });
230
- }
231
-
232
- // Combine: history (oldest-first) + active, then apply filter
233
- const combined: ToolCallEntry[] = [...this._history, ...activeEntries];
234
- return applyFilter(combined, filter, (e) => e.receivedAt);
235
- }
236
-
237
- /**
238
- * Register a callback invoked whenever the data changes.
239
- * @returns An unsubscribe function.
240
- */
241
- public subscribe(callback: () => void): () => void {
242
- this._subscribers.add(callback);
243
- return () => this._subscribers.delete(callback);
244
- }
245
-
246
- /**
247
- * Release all event bus subscriptions and clear internal state.
248
- * After disposal the panel will no longer receive new events.
249
- */
250
- public dispose(): void {
251
- if (this._unsub) {
252
- this._unsub();
253
- this._unsub = null;
254
- }
255
- this._subscribers.clear();
256
- }
257
-
258
- private _notify(): void {
259
- for (const cb of this._subscribers) {
260
- try {
261
- cb();
262
- } catch {
263
- // Non-fatal: subscriber errors must not crash the provider
264
- }
265
- }
266
- }
267
- }
@@ -1,262 +0,0 @@
1
- /**
2
- * DiagnosticsProvider — aggregates all diagnostic panel data providers
3
- * into a single unified interface.
4
- *
5
- * Implements the provider contract for diagnostics and the state inspector.
6
- * Wire this up once during runtime initialization and pass it to all
7
- * panels that need diagnostic data.
8
- *
9
- * Usage:
10
- * ```ts
11
- * import { createDiagnosticsProvider } from './diagnostics/index.ts';
12
- *
13
- * const provider = createDiagnosticsProvider({
14
- * eventBus,
15
- * healthAggregator,
16
- * domains: [...],
17
- * });
18
- *
19
- * const toolCalls = provider.getToolCalls({ limit: 50 });
20
- * const unsubscribe = provider.subscribe('tool-calls', () => render());
21
- * ```
22
- */
23
- import type { RuntimeEventBus } from '@pellux/goodvibes-sdk/platform/runtime/events/index';
24
- import type { RuntimeHealthAggregator } from '@pellux/goodvibes-sdk/platform/runtime/health/aggregator';
25
- import type {
26
- ToolCallEntry,
27
- AgentEntry,
28
- TaskEntry,
29
- EventEntry,
30
- RuntimeStateSnapshot,
31
- HealthDashboardData,
32
- DiagnosticFilter,
33
- PanelConfig,
34
- ToolContractEntry,
35
- } from '@pellux/goodvibes-sdk/platform/runtime/diagnostics/types';
36
- import { ToolCallsPanel } from './panels/tool-calls.ts';
37
- import { AgentsPanel } from './panels/agents.ts';
38
- import { TasksPanel } from './panels/tasks.ts';
39
- import { EventsPanel } from './panels/events.ts';
40
- import { StateInspectorPanel, type InspectableDomain } from '@pellux/goodvibes-sdk/platform/runtime/diagnostics/panels/state-inspector';
41
- import { HealthPanel } from './panels/health.ts';
42
- import { ToolContractsPanel } from '@pellux/goodvibes-sdk/platform/runtime/diagnostics/panels/tool-contracts';
43
- import type { ContractVerificationResult } from '@pellux/goodvibes-sdk/platform/runtime/tools/contract-verifier';
44
-
45
- /** Configuration for creating a DiagnosticsProvider. */
46
- export interface DiagnosticsProviderConfig {
47
- /** The runtime event bus to subscribe to. */
48
- readonly eventBus: RuntimeEventBus;
49
- /** The runtime health aggregator to monitor. */
50
- readonly healthAggregator: RuntimeHealthAggregator;
51
- /**
52
- * Domain adapters to expose in the state inspector.
53
- * Pass one adapter per runtime store domain.
54
- */
55
- readonly domains?: readonly InspectableDomain[];
56
- /** Optional per-panel buffer configuration. */
57
- readonly panelConfig?: PanelConfig;
58
- }
59
-
60
- /** Panel name literals for use with subscribe(). */
61
- export type DiagnosticPanelName =
62
- | 'tool-calls'
63
- | 'agents'
64
- | 'tasks'
65
- | 'events'
66
- | 'state-inspector'
67
- | 'health'
68
- | 'tool-contracts';
69
-
70
- /**
71
- * DiagnosticsProvider — unified data access layer for all diagnostic panels.
72
- *
73
- * Each panel is self-contained and subscribes to its own event sources.
74
- * The provider exposes a stable interface for retrieving snapshots and
75
- * registering change listeners.
76
- */
77
- export class DiagnosticsProvider {
78
- private readonly _toolCalls: ToolCallsPanel;
79
- private readonly _agents: AgentsPanel;
80
- private readonly _tasks: TasksPanel;
81
- private readonly _events: EventsPanel;
82
- private readonly _stateInspector: StateInspectorPanel;
83
- private readonly _health: HealthPanel;
84
- private readonly _toolContracts: ToolContractsPanel;
85
-
86
- constructor(config: DiagnosticsProviderConfig) {
87
- const pc = config.panelConfig;
88
- this._toolCalls = new ToolCallsPanel(config.eventBus, pc);
89
- this._agents = new AgentsPanel(config.eventBus, pc);
90
- this._tasks = new TasksPanel(config.eventBus, pc);
91
- this._events = new EventsPanel(config.eventBus, pc);
92
- this._stateInspector = new StateInspectorPanel(
93
- config.domains ? [...config.domains] : []
94
- );
95
- this._health = new HealthPanel(config.healthAggregator);
96
- this._toolContracts = new ToolContractsPanel(pc);
97
- }
98
-
99
- // ── Data access ──────────────────────────────────────────────────────────────
100
-
101
- /**
102
- * Retrieve tool call diagnostic entries.
103
- *
104
- * @param filter - Optional filter for domain, time range, trace/session/turn/task IDs, and limit.
105
- * @returns Filtered tool call entries, most recent first.
106
- */
107
- public getToolCalls(filter?: DiagnosticFilter): ToolCallEntry[] {
108
- return this._toolCalls.getSnapshot(filter);
109
- }
110
-
111
- /**
112
- * Retrieve agent diagnostic entries.
113
- *
114
- * @param filter - Optional filter.
115
- * @returns Filtered agent entries, most recent first.
116
- */
117
- public getAgents(filter?: DiagnosticFilter): AgentEntry[] {
118
- return this._agents.getSnapshot(filter);
119
- }
120
-
121
- /**
122
- * Retrieve task diagnostic entries.
123
- *
124
- * @param filter - Optional filter.
125
- * @returns Filtered task entries, most recent first.
126
- */
127
- public getTasks(filter?: DiagnosticFilter): TaskEntry[] {
128
- return this._tasks.getSnapshot(filter);
129
- }
130
-
131
- /**
132
- * Retrieve event timeline entries.
133
- *
134
- * @param filter - Optional filter. The `domains` field filters by domain name.
135
- * @returns Filtered event entries, most recent first.
136
- */
137
- public getEvents(filter?: DiagnosticFilter): EventEntry[] {
138
- return this._events.getSnapshot(filter);
139
- }
140
-
141
- /**
142
- * Capture a point-in-time snapshot of all registered runtime domain states.
143
- *
144
- * @returns A RuntimeStateSnapshot with all domain states serialized.
145
- */
146
- public getStateSnapshot(): RuntimeStateSnapshot {
147
- return this._stateInspector.getSnapshot();
148
- }
149
-
150
- /**
151
- * Retrieve the current health dashboard data.
152
- *
153
- * @returns Aggregated health data sorted by severity.
154
- */
155
- public getHealthDashboard(): HealthDashboardData {
156
- return this._health.getSnapshot();
157
- }
158
-
159
- /**
160
- * Register a domain adapter for inclusion in state inspector snapshots.
161
- *
162
- * @param domain - Domain adapter implementing InspectableDomain.
163
- */
164
- public registerDomain(domain: InspectableDomain): void {
165
- this._stateInspector.registerDomain(domain);
166
- }
167
-
168
- // ── Tool contracts ────────────────────────────────────────────────────────────
169
-
170
- /**
171
- * Load (or reload) all tool contract verification results.
172
- * Replaces any previously loaded results.
173
- *
174
- * @param results - Map of tool name → ContractVerificationResult from ToolContractVerifier.
175
- */
176
- public loadToolContracts(results: Map<string, ContractVerificationResult>): void {
177
- this._toolContracts.load(results);
178
- }
179
-
180
- /**
181
- * Upsert a single tool contract verification result.
182
- * Use this for live updates when a single tool is re-verified.
183
- *
184
- * @param result - The ContractVerificationResult to upsert.
185
- */
186
- public upsertToolContract(result: ContractVerificationResult): void {
187
- this._toolContracts.upsert(result);
188
- }
189
-
190
- /**
191
- * Get the contract entry for a specific tool by name.
192
- *
193
- * @param toolName - Tool name to look up.
194
- * @returns The entry or undefined if not verified.
195
- */
196
- public getToolContract(toolName: string): ToolContractEntry | undefined {
197
- return this._toolContracts.get(toolName);
198
- }
199
-
200
- /**
201
- * Get all tool contract entries, sorted by tool name.
202
- */
203
- public getToolContracts(): ToolContractEntry[] {
204
- return this._toolContracts.getAll();
205
- }
206
-
207
- /**
208
- * Get only tools that failed their contract checks.
209
- */
210
- public getToolContractFailures(): ToolContractEntry[] {
211
- return this._toolContracts.getFailures();
212
- }
213
-
214
- /**
215
- * Get summary counts across all tool contract results.
216
- */
217
- public getToolContractSummary(): ReturnType<ToolContractsPanel['getSummary']> {
218
- return this._toolContracts.getSummary();
219
- }
220
-
221
- // ── Change subscriptions ──────────────────────────────────────────────────────
222
-
223
- /**
224
- * Subscribe to change notifications for a specific panel.
225
- *
226
- * The callback is invoked whenever the panel's data changes. Call the
227
- * corresponding `get*` method inside the callback to retrieve the latest data.
228
- *
229
- * @param panel - The panel to subscribe to.
230
- * @param callback - Called whenever the panel's data updates.
231
- * @returns An unsubscribe function; call it to stop receiving notifications.
232
- */
233
- public subscribe(panel: DiagnosticPanelName, callback: () => void): () => void {
234
- switch (panel) {
235
- case 'tool-calls': return this._toolCalls.subscribe(callback);
236
- case 'agents': return this._agents.subscribe(callback);
237
- case 'tasks': return this._tasks.subscribe(callback);
238
- case 'events': return this._events.subscribe(callback);
239
- case 'state-inspector': return this._stateInspector.subscribe(callback);
240
- case 'health': return this._health.subscribe(callback);
241
- case 'tool-contracts': return this._toolContracts.subscribe(callback);
242
- }
243
- }
244
-
245
- // ── Lifecycle ─────────────────────────────────────────────────────────────────
246
-
247
- /**
248
- * Dispose all panel data providers, releasing event bus subscriptions
249
- * and clearing all internal buffers.
250
- *
251
- * Call this when the diagnostics system is shut down.
252
- */
253
- public dispose(): void {
254
- this._toolCalls.dispose();
255
- this._agents.dispose();
256
- this._tasks.dispose();
257
- this._events.dispose();
258
- this._health.dispose();
259
- this._toolContracts.dispose();
260
- // StateInspectorPanel has no disposable resources (no event bus subscriptions)
261
- }
262
- }
@@ -1 +0,0 @@
1
- export * from '@pellux/goodvibes-sdk/platform/runtime/store/domains/conversation';
@@ -1 +0,0 @@
1
- export * from '@pellux/goodvibes-sdk/platform/runtime/store/domains/permissions';
@@ -1 +0,0 @@
1
- export * from '@pellux/goodvibes-sdk/platform/runtime/store/helpers/reducers/conversation';
@@ -1 +0,0 @@
1
- export * from '@pellux/goodvibes-sdk/platform/runtime/store/helpers/reducers/lifecycle';
@@ -1,60 +0,0 @@
1
- import type { PartialToolCall } from '@pellux/goodvibes-sdk/platform/providers/interface';
2
- import type { ConversationDomainState } from '@pellux/goodvibes-sdk/platform/runtime/store/domains/conversation';
3
-
4
- export function uniq<T>(items: T[]): T[] {
5
- return [...new Set(items)];
6
- }
7
-
8
- export function now(): number {
9
- return Date.now();
10
- }
11
-
12
- export function updateDomainMetadata<T extends { revision: number; lastUpdatedAt: number; source: string }>(
13
- domain: T,
14
- source: string,
15
- ): T {
16
- return {
17
- ...domain,
18
- revision: domain.revision + 1,
19
- lastUpdatedAt: now(),
20
- source,
21
- };
22
- }
23
-
24
- export function isTerminalTurnState(state: ConversationDomainState['turnState']): boolean {
25
- return state === 'completed' || state === 'failed' || state === 'cancelled';
26
- }
27
-
28
- export function canStartNewTurn(domain: ConversationDomainState): boolean {
29
- return domain.turnState === 'idle' || isTerminalTurnState(domain.turnState);
30
- }
31
-
32
- export function isCurrentTurnEvent(domain: ConversationDomainState, turnId: string): boolean {
33
- return domain.currentTurnId !== undefined && domain.currentTurnId === turnId;
34
- }
35
-
36
- export function formatPartialToolPreview(toolCalls?: PartialToolCall[]): string | undefined {
37
- if (!toolCalls || toolCalls.length === 0) return undefined;
38
- const last = toolCalls[toolCalls.length - 1] as { name?: unknown; arguments?: unknown };
39
- const name = typeof last.name === 'string' ? last.name : '';
40
- const args =
41
- typeof last.arguments === 'string'
42
- ? last.arguments
43
- : last.arguments !== undefined
44
- ? JSON.stringify(last.arguments)
45
- : '';
46
- if (!name) return undefined;
47
- const preview = args.length > 60 ? `${args.slice(0, 57)}...` : args;
48
- return `${name}(${preview})`;
49
- }
50
-
51
- export function resetStreamState(): ConversationDomainState['stream'] {
52
- return {
53
- accumulated: '',
54
- reasoningAccumulated: '',
55
- partialToolPreview: undefined,
56
- deltaCount: 0,
57
- firstDeltaAt: undefined,
58
- lastDeltaAt: undefined,
59
- };
60
- }