@pellux/goodvibes-tui 0.18.12 → 0.18.13
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.
- package/CHANGELOG.md +50 -0
- package/README.md +1 -1
- package/docs/foundation-artifacts/operator-contract.json +1 -1
- package/package.json +2 -2
- package/src/config/index.ts +1 -138
- package/src/config/subscription-providers.ts +1 -127
- package/src/core/conversation-rendering.ts +3 -3
- package/src/core/conversation.ts +176 -423
- package/src/core/history.ts +45 -0
- package/src/core/orchestrator.ts +3 -735
- package/src/core/system-message-router.ts +19 -58
- package/src/input/handler-content-actions.ts +2 -2
- package/src/input/handler-feed.ts +1 -1
- package/src/input/handler-modal-token-routes.ts +1 -1
- package/src/input/handler-ui-state.ts +1 -1
- package/src/input/handler.ts +1 -1
- package/src/input/search.ts +1 -1
- package/src/input/selection.ts +2 -2
- package/src/main.ts +1 -1
- package/src/panels/agent-inspector-panel.ts +3 -3
- package/src/panels/agent-logs-panel.ts +3 -3
- package/src/panels/approval-panel.ts +2 -2
- package/src/panels/automation-control-panel.ts +3 -3
- package/src/panels/base-panel.ts +14 -14
- package/src/panels/builtin/operations.ts +1 -1
- package/src/panels/builtin/session.ts +1 -1
- package/src/panels/builtin/shared.ts +3 -3
- package/src/panels/cockpit-panel.ts +2 -2
- package/src/panels/communication-panel.ts +3 -3
- package/src/panels/context-visualizer-panel.ts +2 -2
- package/src/panels/control-plane-panel.ts +3 -3
- package/src/panels/cost-tracker-panel.ts +3 -3
- package/src/panels/debug-panel.ts +2 -2
- package/src/panels/diff-panel.ts +2 -2
- package/src/panels/docs-panel.ts +1 -1
- package/src/panels/eval-panel.ts +2 -2
- package/src/panels/file-explorer-panel.ts +3 -3
- package/src/panels/file-preview-panel.ts +3 -3
- package/src/panels/forensics-panel.ts +2 -2
- package/src/panels/git-panel.ts +1 -1
- package/src/panels/hooks-panel.ts +3 -3
- package/src/panels/incident-review-panel.ts +1 -1
- package/src/panels/intelligence-panel.ts +2 -2
- package/src/panels/knowledge-panel.ts +1 -1
- package/src/panels/local-auth-panel.ts +2 -2
- package/src/panels/marketplace-panel.ts +1 -1
- package/src/panels/mcp-panel.ts +3 -3
- package/src/panels/memory-panel.ts +1 -1
- package/src/panels/ops-control-panel.ts +3 -3
- package/src/panels/ops-strategy-panel.ts +2 -2
- package/src/panels/orchestration-panel.ts +2 -2
- package/src/panels/panel-list-panel.ts +6 -6
- package/src/panels/plan-dashboard-panel.ts +1 -1
- package/src/panels/plugins-panel.ts +2 -2
- package/src/panels/policy-panel.ts +2 -2
- package/src/panels/polish.ts +3 -3
- package/src/panels/provider-accounts-panel.ts +2 -2
- package/src/panels/provider-health-panel.ts +2 -2
- package/src/panels/provider-stats-panel.ts +3 -3
- package/src/panels/remote-panel.ts +3 -3
- package/src/panels/routes-panel.ts +3 -3
- package/src/panels/sandbox-panel.ts +2 -2
- package/src/panels/schedule-panel.ts +1 -1
- package/src/panels/security-panel.ts +2 -2
- package/src/panels/services-panel.ts +2 -2
- package/src/panels/session-browser-panel.ts +2 -2
- package/src/panels/settings-sync-panel.ts +2 -2
- package/src/panels/skills-panel.ts +6 -6
- package/src/panels/subscription-panel.ts +2 -2
- package/src/panels/symbol-outline-panel.ts +3 -3
- package/src/panels/system-messages-panel.ts +4 -4
- package/src/panels/tasks-panel.ts +2 -2
- package/src/panels/thinking-panel.ts +3 -3
- package/src/panels/token-budget-panel.ts +1 -1
- package/src/panels/tool-inspector-panel.ts +3 -3
- package/src/panels/types.ts +5 -5
- package/src/panels/watchers-panel.ts +3 -3
- package/src/panels/welcome-panel.ts +1 -1
- package/src/panels/worktree-panel.ts +2 -2
- package/src/panels/wrfc-panel.ts +3 -3
- package/src/permissions/prompt.ts +3 -22
- package/src/plugins/loader.ts +15 -304
- package/src/renderer/agent-detail-modal.ts +1 -1
- package/src/renderer/autocomplete-overlay.ts +2 -2
- package/src/renderer/bookmark-modal.ts +1 -1
- package/src/renderer/bottom-bar.ts +2 -2
- package/src/renderer/buffer.ts +1 -1
- package/src/renderer/code-block.ts +2 -2
- package/src/renderer/compositor.ts +2 -2
- package/src/renderer/context-inspector.ts +1 -1
- package/src/renderer/conversation-layout.ts +2 -2
- package/src/renderer/conversation-overlays.ts +1 -1
- package/src/renderer/conversation-surface.ts +2 -2
- package/src/renderer/diff-view.ts +2 -2
- package/src/renderer/diff.ts +1 -1
- package/src/renderer/file-picker-overlay.ts +2 -2
- package/src/renderer/file-tree.ts +2 -2
- package/src/renderer/help-overlay.ts +1 -1
- package/src/renderer/history-search-overlay.ts +2 -2
- package/src/renderer/live-tail-modal.ts +1 -1
- package/src/renderer/markdown.ts +2 -2
- package/src/renderer/modal-factory.ts +3 -3
- package/src/renderer/model-picker-overlay.ts +2 -2
- package/src/renderer/overlay-box.ts +2 -2
- package/src/renderer/panel-composite.ts +1 -1
- package/src/renderer/panel-picker-overlay.ts +2 -2
- package/src/renderer/panel-tab-bar.ts +1 -1
- package/src/renderer/panel-workspace-bar.ts +1 -1
- package/src/renderer/process-indicator.ts +2 -2
- package/src/renderer/process-modal.ts +1 -1
- package/src/renderer/profile-picker-modal.ts +2 -2
- package/src/renderer/progress.ts +2 -2
- package/src/renderer/search-overlay.ts +2 -2
- package/src/renderer/selection-modal-overlay.ts +2 -2
- package/src/renderer/session-picker-modal.ts +2 -2
- package/src/renderer/settings-modal.ts +2 -2
- package/src/renderer/shell-surface.ts +1 -1
- package/src/renderer/system-message.ts +1 -1
- package/src/renderer/tab-strip.ts +2 -2
- package/src/renderer/text-layout.ts +1 -1
- package/src/renderer/thinking.ts +1 -1
- package/src/renderer/tool-call.ts +2 -2
- package/src/renderer/ui-factory.ts +2 -2
- package/src/runtime/bootstrap-command-context.ts +4 -5
- package/src/runtime/bootstrap-command-parts.ts +1 -3
- package/src/runtime/bootstrap-core.ts +3 -2
- package/src/runtime/bootstrap-hook-bridge.ts +15 -174
- package/src/runtime/bootstrap-shell.ts +4 -4
- package/src/runtime/bootstrap.ts +1 -1
- package/src/runtime/context.ts +4 -20
- package/src/runtime/diagnostics/panels/index.ts +1 -1
- package/src/runtime/diagnostics/panels/ops.ts +1 -1
- package/src/runtime/diagnostics/panels/panel-resources.ts +118 -0
- package/src/runtime/perf/panel-contracts.ts +32 -0
- package/src/runtime/perf/panel-health-monitor.ts +18 -0
- package/src/runtime/services.ts +4 -4
- package/src/runtime/store/domains/conversation.ts +1 -181
- package/src/runtime/store/domains/permissions.ts +1 -143
- package/src/runtime/store/helpers/reducers/conversation.ts +1 -228
- package/src/runtime/store/helpers/reducers/lifecycle.ts +1 -440
- package/src/runtime/store/selectors/index.ts +11 -6
- package/src/runtime/store/state.ts +12 -4
- package/src/runtime/ui-events.ts +46 -0
- package/src/runtime/ui-services.ts +1 -1
- package/src/shell/ui-openers.ts +1 -1
- package/src/tools/index.ts +1 -186
- package/src/types/grid.ts +48 -0
- package/src/utils/clipboard.ts +21 -0
- package/src/utils/splash-lines.ts +1 -1
- package/src/utils/terminal-width.ts +185 -0
- package/src/version.ts +1 -1
- package/src/daemon/facade-composition.ts +0 -398
- package/src/daemon/facade.ts +0 -638
- package/src/daemon/surface-policy.ts +0 -60
- package/src/daemon/types.ts +0 -191
- package/src/runtime/ui-read-models-core.ts +0 -95
- package/src/runtime/ui-read-models-operations.ts +0 -203
|
@@ -1,440 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import type { PermissionEvent } from '@pellux/goodvibes-sdk/platform/runtime/events/permissions';
|
|
3
|
-
import type { TaskEvent } from '@pellux/goodvibes-sdk/platform/runtime/events/tasks';
|
|
4
|
-
import type { AgentEvent } from '@pellux/goodvibes-sdk/platform/runtime/events/agents';
|
|
5
|
-
import type { OrchestrationEvent } from '@pellux/goodvibes-sdk/platform/runtime/events/orchestration';
|
|
6
|
-
import type { SessionDomainState } from '@pellux/goodvibes-sdk/platform/runtime/store/domains/session';
|
|
7
|
-
import type {
|
|
8
|
-
PermissionDomainState,
|
|
9
|
-
PermissionDecisionMachineState,
|
|
10
|
-
PermissionDecision,
|
|
11
|
-
} from '@pellux/goodvibes-sdk/platform/runtime/store/domains/permissions';
|
|
12
|
-
import type { TaskDomainState, RuntimeTask, TaskLifecycleState } from '@pellux/goodvibes-sdk/platform/runtime/store/domains/tasks';
|
|
13
|
-
import type { AgentDomainState, RuntimeAgent, AgentLifecycleState } from '@pellux/goodvibes-sdk/platform/runtime/store/domains/agents';
|
|
14
|
-
import type {
|
|
15
|
-
OrchestrationDomainState,
|
|
16
|
-
OrchestrationGraphRecord,
|
|
17
|
-
OrchestrationNodeRecord,
|
|
18
|
-
} from '@pellux/goodvibes-sdk/platform/runtime/store/domains/orchestration';
|
|
19
|
-
import type { PermissionCategory } from '@pellux/goodvibes-sdk/platform/permissions/manager';
|
|
20
|
-
import { now, uniq, updateDomainMetadata } from '@pellux/goodvibes-sdk/platform/runtime/store/helpers/reducers/shared';
|
|
21
|
-
|
|
22
|
-
function permissionMachineStateForEvent(event: PermissionEvent): PermissionDecisionMachineState {
|
|
23
|
-
switch (event.type) {
|
|
24
|
-
case 'PERMISSION_REQUESTED':
|
|
25
|
-
return 'collect_rules';
|
|
26
|
-
case 'RULES_COLLECTED':
|
|
27
|
-
return 'normalize_input';
|
|
28
|
-
case 'INPUT_NORMALIZED':
|
|
29
|
-
return 'evaluate_policy';
|
|
30
|
-
case 'POLICY_EVALUATED':
|
|
31
|
-
return 'evaluate_runtime_mode';
|
|
32
|
-
case 'MODE_EVALUATED':
|
|
33
|
-
return 'evaluate_session_override';
|
|
34
|
-
case 'SESSION_OVERRIDE_EVALUATED':
|
|
35
|
-
return 'final_safety_checks';
|
|
36
|
-
case 'SAFETY_CHECKED':
|
|
37
|
-
case 'DECISION_EMITTED':
|
|
38
|
-
return 'decision_emitted';
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function inferPermissionCategory(toolName: string): PermissionCategory {
|
|
43
|
-
if (toolName === 'agent' || toolName === 'delegate') return 'delegate';
|
|
44
|
-
if (toolName === 'write' || toolName === 'edit' || toolName === 'apply_patch') return 'write';
|
|
45
|
-
if (toolName === 'exec' || toolName === 'precision_exec' || toolName === 'bash') return 'execute';
|
|
46
|
-
return 'read';
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export function updateSessionState(
|
|
50
|
-
domain: SessionDomainState,
|
|
51
|
-
event: CompactionEvent,
|
|
52
|
-
): SessionDomainState {
|
|
53
|
-
const base = updateDomainMetadata(domain, event.type);
|
|
54
|
-
switch (event.type) {
|
|
55
|
-
case 'COMPACTION_CHECK':
|
|
56
|
-
return { ...base, compactionState: 'checking_threshold' };
|
|
57
|
-
case 'COMPACTION_MICROCOMPACT':
|
|
58
|
-
return { ...base, compactionState: 'microcompact' };
|
|
59
|
-
case 'COMPACTION_COLLAPSE':
|
|
60
|
-
return { ...base, compactionState: 'collapse', compactionMessageCount: event.messageCount };
|
|
61
|
-
case 'COMPACTION_AUTOCOMPACT':
|
|
62
|
-
return { ...base, compactionState: 'autocompact' };
|
|
63
|
-
case 'COMPACTION_REACTIVE':
|
|
64
|
-
return { ...base, compactionState: 'reactive_compact' };
|
|
65
|
-
case 'COMPACTION_BOUNDARY_COMMIT':
|
|
66
|
-
return { ...base, compactionState: 'boundary_commit' };
|
|
67
|
-
case 'COMPACTION_DONE':
|
|
68
|
-
return { ...base, compactionState: 'done', lastCompactedAt: now() };
|
|
69
|
-
case 'COMPACTION_FAILED':
|
|
70
|
-
return { ...base, compactionState: 'failed', recoveryError: event.error };
|
|
71
|
-
case 'COMPACTION_RESUME_REPAIR':
|
|
72
|
-
return { ...base, wasRepaired: event.repaired, recoveryState: event.safeToResume ? 'ready' : domain.recoveryState };
|
|
73
|
-
case 'COMPACTION_QUALITY_SCORE':
|
|
74
|
-
case 'COMPACTION_STRATEGY_SWITCH':
|
|
75
|
-
return base;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export function updatePermissionState(
|
|
80
|
-
domain: PermissionDomainState,
|
|
81
|
-
event: PermissionEvent,
|
|
82
|
-
): PermissionDomainState {
|
|
83
|
-
const base = updateDomainMetadata(domain, event.type);
|
|
84
|
-
switch (event.type) {
|
|
85
|
-
case 'PERMISSION_REQUESTED':
|
|
86
|
-
return { ...base, awaitingDecision: true, decisionMachineState: permissionMachineStateForEvent(event), totalChecks: domain.totalChecks + 1 };
|
|
87
|
-
case 'RULES_COLLECTED':
|
|
88
|
-
case 'INPUT_NORMALIZED':
|
|
89
|
-
case 'POLICY_EVALUATED':
|
|
90
|
-
case 'MODE_EVALUATED':
|
|
91
|
-
case 'SESSION_OVERRIDE_EVALUATED':
|
|
92
|
-
case 'SAFETY_CHECKED':
|
|
93
|
-
return { ...base, awaitingDecision: true, decisionMachineState: permissionMachineStateForEvent(event) };
|
|
94
|
-
case 'DECISION_EMITTED':
|
|
95
|
-
return {
|
|
96
|
-
...base,
|
|
97
|
-
awaitingDecision: false,
|
|
98
|
-
decisionMachineState: permissionMachineStateForEvent(event),
|
|
99
|
-
approvalCount: domain.approvalCount + (event.approved ? 1 : 0),
|
|
100
|
-
denialCount: domain.denialCount + (event.approved ? 0 : 1),
|
|
101
|
-
lastDecision: {
|
|
102
|
-
callId: event.callId,
|
|
103
|
-
toolName: event.tool,
|
|
104
|
-
category: inferPermissionCategory(event.tool),
|
|
105
|
-
machineState: 'decision_emitted',
|
|
106
|
-
outcome: event.approved ? 'approved' : 'denied',
|
|
107
|
-
reason: (event.reasonCode as PermissionDecision['reason']) ?? (event.approved ? 'user_approved' : 'user_denied'),
|
|
108
|
-
sourceLayer: (event.sourceLayer as PermissionDecision['sourceLayer']) ?? (event.source as PermissionDecision['sourceLayer']) ?? 'config_policy',
|
|
109
|
-
persisted: event.persisted ?? false,
|
|
110
|
-
classification: event.classification,
|
|
111
|
-
riskLevel: event.riskLevel as PermissionDecision['riskLevel'],
|
|
112
|
-
summary: event.summary,
|
|
113
|
-
decidedAt: now(),
|
|
114
|
-
},
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
function updateTaskIndexes(tasks: Map<string, RuntimeTask>) {
|
|
120
|
-
const queuedIds: string[] = [];
|
|
121
|
-
const runningIds: string[] = [];
|
|
122
|
-
const blockedIds: string[] = [];
|
|
123
|
-
for (const [taskId, task] of tasks.entries()) {
|
|
124
|
-
if (task.status === 'queued') queuedIds.push(taskId);
|
|
125
|
-
if (task.status === 'running') runningIds.push(taskId);
|
|
126
|
-
if (task.status === 'blocked') blockedIds.push(taskId);
|
|
127
|
-
}
|
|
128
|
-
return { queuedIds, runningIds, blockedIds };
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
export function updateTaskState(domain: TaskDomainState, event: TaskEvent): TaskDomainState {
|
|
132
|
-
const tasks = new Map(domain.tasks);
|
|
133
|
-
const existing = tasks.get(event.taskId);
|
|
134
|
-
const timestamp = now();
|
|
135
|
-
const task: RuntimeTask =
|
|
136
|
-
existing ??
|
|
137
|
-
{
|
|
138
|
-
id: event.taskId,
|
|
139
|
-
kind: 'agentId' in event && event.agentId ? 'agent' : 'exec',
|
|
140
|
-
title: 'description' in event ? event.description : `task:${event.taskId}`,
|
|
141
|
-
status: 'queued',
|
|
142
|
-
owner: event.agentId ?? 'runtime',
|
|
143
|
-
cancellable: true,
|
|
144
|
-
childTaskIds: [],
|
|
145
|
-
queuedAt: timestamp,
|
|
146
|
-
};
|
|
147
|
-
switch (event.type) {
|
|
148
|
-
case 'TASK_CREATED':
|
|
149
|
-
tasks.set(event.taskId, task);
|
|
150
|
-
break;
|
|
151
|
-
case 'TASK_STARTED':
|
|
152
|
-
tasks.set(event.taskId, { ...task, status: 'running', startedAt: task.startedAt ?? timestamp });
|
|
153
|
-
break;
|
|
154
|
-
case 'TASK_BLOCKED':
|
|
155
|
-
tasks.set(event.taskId, { ...task, status: 'blocked', error: event.reason });
|
|
156
|
-
break;
|
|
157
|
-
case 'TASK_PROGRESS':
|
|
158
|
-
tasks.set(event.taskId, { ...task, description: event.message ?? task.description });
|
|
159
|
-
break;
|
|
160
|
-
case 'TASK_COMPLETED':
|
|
161
|
-
tasks.set(event.taskId, { ...task, status: 'completed', endedAt: timestamp, result: { durationMs: event.durationMs } });
|
|
162
|
-
break;
|
|
163
|
-
case 'TASK_FAILED':
|
|
164
|
-
tasks.set(event.taskId, { ...task, status: 'failed', endedAt: timestamp, error: event.error });
|
|
165
|
-
break;
|
|
166
|
-
case 'TASK_CANCELLED':
|
|
167
|
-
tasks.set(event.taskId, { ...task, status: 'cancelled', endedAt: timestamp, error: event.reason });
|
|
168
|
-
break;
|
|
169
|
-
}
|
|
170
|
-
const indexes = updateTaskIndexes(tasks);
|
|
171
|
-
return {
|
|
172
|
-
...updateDomainMetadata(domain, event.type),
|
|
173
|
-
tasks,
|
|
174
|
-
...indexes,
|
|
175
|
-
totalCreated: domain.totalCreated + (event.type === 'TASK_CREATED' ? 1 : 0),
|
|
176
|
-
totalCompleted: domain.totalCompleted + (event.type === 'TASK_COMPLETED' ? 1 : 0),
|
|
177
|
-
totalFailed: domain.totalFailed + (event.type === 'TASK_FAILED' ? 1 : 0),
|
|
178
|
-
totalCancelled: domain.totalCancelled + (event.type === 'TASK_CANCELLED' ? 1 : 0),
|
|
179
|
-
};
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
function updateTaskDomainFromRecord(domain: TaskDomainState, task: RuntimeTask, source: string): TaskDomainState {
|
|
183
|
-
const tasks = new Map(domain.tasks);
|
|
184
|
-
const previous = tasks.get(task.id);
|
|
185
|
-
tasks.set(task.id, task);
|
|
186
|
-
const indexes = updateTaskIndexes(tasks);
|
|
187
|
-
|
|
188
|
-
let { totalCreated, totalCompleted, totalFailed, totalCancelled } = domain;
|
|
189
|
-
if (!previous) totalCreated += 1;
|
|
190
|
-
if (previous?.status !== task.status) {
|
|
191
|
-
if (task.status === 'completed') totalCompleted += 1;
|
|
192
|
-
else if (task.status === 'failed') totalFailed += 1;
|
|
193
|
-
else if (task.status === 'cancelled') totalCancelled += 1;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
return { ...updateDomainMetadata(domain, source), tasks, ...indexes, totalCreated, totalCompleted, totalFailed, totalCancelled };
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
function transitionTaskDomainRecord(
|
|
200
|
-
domain: TaskDomainState,
|
|
201
|
-
taskId: string,
|
|
202
|
-
status: TaskLifecycleState,
|
|
203
|
-
patch: Partial<RuntimeTask> | undefined,
|
|
204
|
-
source: string,
|
|
205
|
-
): TaskDomainState {
|
|
206
|
-
const existing = domain.tasks.get(taskId);
|
|
207
|
-
if (!existing) return domain;
|
|
208
|
-
return updateTaskDomainFromRecord(domain, { ...existing, ...patch, status }, source);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
export function updateAgentState(domain: AgentDomainState, event: AgentEvent): AgentDomainState {
|
|
212
|
-
const agents = new Map(domain.agents);
|
|
213
|
-
const timestamp = now();
|
|
214
|
-
const existing = agents.get(event.agentId);
|
|
215
|
-
const statusMap: Partial<Record<AgentEvent['type'], AgentLifecycleState>> = {
|
|
216
|
-
AGENT_SPAWNING: 'spawning',
|
|
217
|
-
AGENT_RUNNING: 'running',
|
|
218
|
-
AGENT_PROGRESS: 'running',
|
|
219
|
-
AGENT_STREAM_DELTA: 'running',
|
|
220
|
-
AGENT_AWAITING_MESSAGE: 'awaiting_message',
|
|
221
|
-
AGENT_AWAITING_TOOL: 'awaiting_tool',
|
|
222
|
-
AGENT_FINALIZING: 'finalizing',
|
|
223
|
-
AGENT_COMPLETED: 'completed',
|
|
224
|
-
AGENT_FAILED: 'failed',
|
|
225
|
-
AGENT_CANCELLED: 'cancelled',
|
|
226
|
-
};
|
|
227
|
-
const agent: RuntimeAgent =
|
|
228
|
-
existing ??
|
|
229
|
-
{
|
|
230
|
-
id: event.agentId,
|
|
231
|
-
label: 'task' in event ? event.task : event.agentId,
|
|
232
|
-
role: 'subagent',
|
|
233
|
-
status: statusMap[event.type] ?? 'running',
|
|
234
|
-
providerId: 'unknown',
|
|
235
|
-
modelId: 'unknown',
|
|
236
|
-
childAgentIds: [],
|
|
237
|
-
taskId: event.taskId,
|
|
238
|
-
turnCount: 0,
|
|
239
|
-
toolCallCount: 0,
|
|
240
|
-
latestOutput: '',
|
|
241
|
-
spawnedAt: timestamp,
|
|
242
|
-
};
|
|
243
|
-
agents.set(event.agentId, {
|
|
244
|
-
...agent,
|
|
245
|
-
status: statusMap[event.type] ?? agent.status,
|
|
246
|
-
taskId: event.taskId ?? agent.taskId,
|
|
247
|
-
latestProgress:
|
|
248
|
-
event.type === 'AGENT_PROGRESS'
|
|
249
|
-
? event.progress
|
|
250
|
-
: event.type === 'AGENT_AWAITING_TOOL'
|
|
251
|
-
? `${event.tool}:${event.callId}`
|
|
252
|
-
: agent.latestProgress,
|
|
253
|
-
latestOutput:
|
|
254
|
-
event.type === 'AGENT_STREAM_DELTA'
|
|
255
|
-
? event.accumulated
|
|
256
|
-
: event.type === 'AGENT_COMPLETED' && event.output !== undefined
|
|
257
|
-
? event.output
|
|
258
|
-
: agent.latestOutput,
|
|
259
|
-
endedAt:
|
|
260
|
-
event.type === 'AGENT_COMPLETED' || event.type === 'AGENT_FAILED' || event.type === 'AGENT_CANCELLED'
|
|
261
|
-
? timestamp
|
|
262
|
-
: agent.endedAt,
|
|
263
|
-
error: event.type === 'AGENT_FAILED' ? event.error : agent.error,
|
|
264
|
-
toolCallCount:
|
|
265
|
-
event.type === 'AGENT_COMPLETED' && event.toolCallsMade !== undefined
|
|
266
|
-
? event.toolCallsMade
|
|
267
|
-
: agent.toolCallCount,
|
|
268
|
-
result:
|
|
269
|
-
event.type === 'AGENT_COMPLETED'
|
|
270
|
-
? {
|
|
271
|
-
durationMs: event.durationMs,
|
|
272
|
-
...(event.output !== undefined ? { output: event.output } : {}),
|
|
273
|
-
...(event.toolCallsMade !== undefined ? { toolCallsMade: event.toolCallsMade } : {}),
|
|
274
|
-
}
|
|
275
|
-
: agent.result,
|
|
276
|
-
});
|
|
277
|
-
const activeAgentIds = [...agents.values()].filter((value) => !['completed', 'failed', 'cancelled'].includes(value.status)).map((value) => value.id);
|
|
278
|
-
return {
|
|
279
|
-
...updateDomainMetadata(domain, event.type),
|
|
280
|
-
agents,
|
|
281
|
-
activeAgentIds,
|
|
282
|
-
totalSpawned: domain.totalSpawned + (event.type === 'AGENT_SPAWNING' ? 1 : 0),
|
|
283
|
-
totalCompleted: domain.totalCompleted + (event.type === 'AGENT_COMPLETED' ? 1 : 0),
|
|
284
|
-
totalFailed: domain.totalFailed + (event.type === 'AGENT_FAILED' ? 1 : 0),
|
|
285
|
-
peakConcurrency: Math.max(domain.peakConcurrency, activeAgentIds.length),
|
|
286
|
-
};
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
function transitionAgentDomainRecord(
|
|
290
|
-
domain: AgentDomainState,
|
|
291
|
-
agentId: string,
|
|
292
|
-
status: AgentLifecycleState,
|
|
293
|
-
patch: Partial<RuntimeAgent> | undefined,
|
|
294
|
-
source: string,
|
|
295
|
-
): AgentDomainState {
|
|
296
|
-
const existing = domain.agents.get(agentId);
|
|
297
|
-
if (!existing) return domain;
|
|
298
|
-
|
|
299
|
-
const agents = new Map(domain.agents);
|
|
300
|
-
agents.set(agentId, { ...existing, ...patch, status });
|
|
301
|
-
const activeAgentIds = [...agents.values()].filter((value) => !['completed', 'failed', 'cancelled'].includes(value.status)).map((value) => value.id);
|
|
302
|
-
|
|
303
|
-
return {
|
|
304
|
-
...updateDomainMetadata(domain, source),
|
|
305
|
-
agents,
|
|
306
|
-
activeAgentIds,
|
|
307
|
-
totalCompleted: domain.totalCompleted + (existing.status !== 'completed' && status === 'completed' ? 1 : 0),
|
|
308
|
-
totalFailed: domain.totalFailed + (existing.status !== 'failed' && status === 'failed' ? 1 : 0),
|
|
309
|
-
peakConcurrency: Math.max(domain.peakConcurrency, activeAgentIds.length),
|
|
310
|
-
};
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
function orchestrationGraphStatus(graph: OrchestrationGraphRecord): OrchestrationGraphRecord['status'] {
|
|
314
|
-
const nodes = [...graph.nodes.values()];
|
|
315
|
-
if (nodes.length === 0) return 'planning';
|
|
316
|
-
if (nodes.some((node) => node.status === 'failed')) return 'failed';
|
|
317
|
-
if (nodes.some((node) => node.status === 'blocked')) return 'blocked';
|
|
318
|
-
if (nodes.some((node) => node.status === 'running')) return 'running';
|
|
319
|
-
if (nodes.every((node) => node.status === 'cancelled')) return 'cancelled';
|
|
320
|
-
if (nodes.every((node) => node.status === 'completed')) return 'completed';
|
|
321
|
-
if (nodes.every((node) => node.status === 'pending' || node.status === 'ready')) {
|
|
322
|
-
return nodes.some((node) => node.status === 'ready') ? 'ready' : 'planning';
|
|
323
|
-
}
|
|
324
|
-
return 'running';
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
export function updateOrchestrationState(
|
|
328
|
-
domain: OrchestrationDomainState,
|
|
329
|
-
event: OrchestrationEvent,
|
|
330
|
-
): OrchestrationDomainState {
|
|
331
|
-
const graphs = new Map(domain.graphs);
|
|
332
|
-
const timestamp = now();
|
|
333
|
-
const existing = 'graphId' in event ? graphs.get(event.graphId) : undefined;
|
|
334
|
-
|
|
335
|
-
switch (event.type) {
|
|
336
|
-
case 'ORCHESTRATION_GRAPH_CREATED':
|
|
337
|
-
graphs.set(event.graphId, {
|
|
338
|
-
id: event.graphId,
|
|
339
|
-
title: event.title,
|
|
340
|
-
mode: event.mode,
|
|
341
|
-
status: 'planning',
|
|
342
|
-
nodeOrder: [],
|
|
343
|
-
nodes: new Map(),
|
|
344
|
-
createdAt: timestamp,
|
|
345
|
-
});
|
|
346
|
-
break;
|
|
347
|
-
case 'ORCHESTRATION_NODE_ADDED': {
|
|
348
|
-
if (!existing) return domain;
|
|
349
|
-
const nodes = new Map(existing.nodes);
|
|
350
|
-
const previousParent = event.parentNodeId ? nodes.get(event.parentNodeId) : undefined;
|
|
351
|
-
const nextNode: OrchestrationNodeRecord = {
|
|
352
|
-
id: event.nodeId,
|
|
353
|
-
title: event.title,
|
|
354
|
-
role: event.role,
|
|
355
|
-
status: 'pending',
|
|
356
|
-
parentNodeId: event.parentNodeId,
|
|
357
|
-
childNodeIds: [],
|
|
358
|
-
dependencyNodeIds: event.dependsOn ?? [],
|
|
359
|
-
...(event.taskId !== undefined ? { taskId: event.taskId } : {}),
|
|
360
|
-
...(event.agentId !== undefined ? { agentId: event.agentId } : {}),
|
|
361
|
-
...(event.contract !== undefined ? { contract: event.contract } : {}),
|
|
362
|
-
};
|
|
363
|
-
nodes.set(event.nodeId, nextNode);
|
|
364
|
-
if (previousParent) {
|
|
365
|
-
nodes.set(event.parentNodeId!, { ...previousParent, childNodeIds: uniq([...previousParent.childNodeIds, event.nodeId]) });
|
|
366
|
-
}
|
|
367
|
-
const graph: OrchestrationGraphRecord = { ...existing, nodeOrder: uniq([...existing.nodeOrder, event.nodeId]), nodes };
|
|
368
|
-
graph.status = orchestrationGraphStatus(graph);
|
|
369
|
-
graphs.set(event.graphId, graph);
|
|
370
|
-
break;
|
|
371
|
-
}
|
|
372
|
-
case 'ORCHESTRATION_NODE_READY':
|
|
373
|
-
case 'ORCHESTRATION_NODE_STARTED':
|
|
374
|
-
case 'ORCHESTRATION_NODE_PROGRESS':
|
|
375
|
-
case 'ORCHESTRATION_NODE_BLOCKED':
|
|
376
|
-
case 'ORCHESTRATION_NODE_COMPLETED':
|
|
377
|
-
case 'ORCHESTRATION_NODE_FAILED':
|
|
378
|
-
case 'ORCHESTRATION_NODE_CANCELLED':
|
|
379
|
-
case 'ORCHESTRATION_RECURSION_GUARD_TRIGGERED': {
|
|
380
|
-
if (!existing) return domain;
|
|
381
|
-
const nodes = new Map(existing.nodes);
|
|
382
|
-
const nodeId = 'nodeId' in event ? event.nodeId : undefined;
|
|
383
|
-
if (nodeId) {
|
|
384
|
-
const node = nodes.get(nodeId);
|
|
385
|
-
if (!node) return domain;
|
|
386
|
-
const updatedNode: OrchestrationNodeRecord =
|
|
387
|
-
event.type === 'ORCHESTRATION_NODE_READY'
|
|
388
|
-
? { ...node, status: 'ready' }
|
|
389
|
-
: event.type === 'ORCHESTRATION_NODE_STARTED'
|
|
390
|
-
? { ...node, status: 'running', startedAt: node.startedAt ?? timestamp, ...(event.taskId !== undefined ? { taskId: event.taskId } : {}), ...(event.agentId !== undefined ? { agentId: event.agentId } : {}) }
|
|
391
|
-
: event.type === 'ORCHESTRATION_NODE_PROGRESS'
|
|
392
|
-
? { ...node, latestMessage: event.message }
|
|
393
|
-
: event.type === 'ORCHESTRATION_NODE_BLOCKED'
|
|
394
|
-
? { ...node, status: 'blocked', error: event.reason }
|
|
395
|
-
: event.type === 'ORCHESTRATION_NODE_COMPLETED'
|
|
396
|
-
? { ...node, status: 'completed', endedAt: timestamp, latestMessage: event.summary ?? node.latestMessage }
|
|
397
|
-
: event.type === 'ORCHESTRATION_NODE_FAILED'
|
|
398
|
-
? { ...node, status: 'failed', endedAt: timestamp, error: event.error }
|
|
399
|
-
: { ...node, status: 'cancelled', endedAt: timestamp, error: event.reason };
|
|
400
|
-
nodes.set(nodeId, updatedNode);
|
|
401
|
-
}
|
|
402
|
-
const graph: OrchestrationGraphRecord = {
|
|
403
|
-
...existing,
|
|
404
|
-
nodes,
|
|
405
|
-
...(event.type === 'ORCHESTRATION_NODE_STARTED' ? { startedAt: existing.startedAt ?? timestamp } : {}),
|
|
406
|
-
...(event.type === 'ORCHESTRATION_RECURSION_GUARD_TRIGGERED'
|
|
407
|
-
? {
|
|
408
|
-
lastRecursionGuard: {
|
|
409
|
-
depth: event.depth,
|
|
410
|
-
activeAgents: event.activeAgents,
|
|
411
|
-
reason: event.reason,
|
|
412
|
-
...(event.nodeId !== undefined ? { nodeId: event.nodeId } : {}),
|
|
413
|
-
triggeredAt: timestamp,
|
|
414
|
-
},
|
|
415
|
-
}
|
|
416
|
-
: {}),
|
|
417
|
-
};
|
|
418
|
-
graph.status = orchestrationGraphStatus(graph);
|
|
419
|
-
if (graph.status === 'completed' || graph.status === 'failed' || graph.status === 'cancelled') {
|
|
420
|
-
graph.endedAt = graph.endedAt ?? timestamp;
|
|
421
|
-
}
|
|
422
|
-
graphs.set(graph.id, graph);
|
|
423
|
-
break;
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
const activeGraphIds = [...graphs.values()].filter((graph) => !['completed', 'failed', 'cancelled'].includes(graph.status)).map((graph) => graph.id);
|
|
428
|
-
|
|
429
|
-
return {
|
|
430
|
-
...updateDomainMetadata(domain, event.type),
|
|
431
|
-
graphs,
|
|
432
|
-
activeGraphIds,
|
|
433
|
-
totalGraphs: graphs.size,
|
|
434
|
-
totalCompletedGraphs: [...graphs.values()].filter((graph) => graph.status === 'completed').length,
|
|
435
|
-
totalFailedGraphs: [...graphs.values()].filter((graph) => graph.status === 'failed').length,
|
|
436
|
-
recursionGuardTrips: domain.recursionGuardTrips + (event.type === 'ORCHESTRATION_RECURSION_GUARD_TRIGGERED' ? 1 : 0),
|
|
437
|
-
};
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
export { updateTaskDomainFromRecord, transitionTaskDomainRecord, transitionAgentDomainRecord };
|
|
1
|
+
export * from '@pellux/goodvibes-sdk/platform/runtime/store/helpers/reducers/lifecycle';
|
|
@@ -53,9 +53,9 @@ export function selectOverlays(state: RuntimeState): OverlayDomainState {
|
|
|
53
53
|
return state.overlays;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
/** Select the full panels domain slice. */
|
|
56
|
+
/** Select the full panels domain slice. Casts from Record<string,unknown> to PanelDomainState. */
|
|
57
57
|
export function selectPanels(state: RuntimeState): PanelDomainState {
|
|
58
|
-
return state.panels;
|
|
58
|
+
return state.panels as unknown as PanelDomainState;
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
/** Select the full permissions domain slice. */
|
|
@@ -123,11 +123,14 @@ export function selectIntelligence(state: RuntimeState): IntelligenceDomainState
|
|
|
123
123
|
return state.intelligence;
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
-
/** Select the full UI performance domain slice. */
|
|
126
|
+
/** Select the full surface/UI performance domain slice. */
|
|
127
127
|
export function selectUiPerf(state: RuntimeState): UiPerfDomainState {
|
|
128
|
-
return state.
|
|
128
|
+
return state.surfacePerf;
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
+
/** Select the full surface performance domain slice (SDK-compatible alias). */
|
|
132
|
+
export const selectSurfacePerf = selectUiPerf;
|
|
133
|
+
|
|
131
134
|
// ---------------------------------------------------------------------------
|
|
132
135
|
// Derived selectors
|
|
133
136
|
// ---------------------------------------------------------------------------
|
|
@@ -271,7 +274,8 @@ export function selectPermissionMode(state: RuntimeState): PermissionMode {
|
|
|
271
274
|
*/
|
|
272
275
|
export function selectActivePanels(state: RuntimeState): PanelState[] {
|
|
273
276
|
const result: PanelState[] = [];
|
|
274
|
-
|
|
277
|
+
const panelDomain = state.panels as unknown as PanelDomainState;
|
|
278
|
+
for (const panel of panelDomain.panels.values()) {
|
|
275
279
|
if (panel.open) {
|
|
276
280
|
result.push(panel);
|
|
277
281
|
}
|
|
@@ -283,7 +287,8 @@ export function selectActivePanels(state: RuntimeState): PanelState[] {
|
|
|
283
287
|
* Returns the panel currently holding focus.
|
|
284
288
|
*/
|
|
285
289
|
export function selectFocusedPanel(state: RuntimeState): PanelState | undefined {
|
|
286
|
-
|
|
290
|
+
const panelDomain = state.panels as unknown as PanelDomainState;
|
|
291
|
+
return panelDomain.panels.get(panelDomain.focusedPanelId);
|
|
287
292
|
}
|
|
288
293
|
|
|
289
294
|
/**
|
|
@@ -33,6 +33,9 @@ import type { GitDomainState } from '@pellux/goodvibes-sdk/platform/runtime/stor
|
|
|
33
33
|
import type { DiscoveryDomainState } from '@pellux/goodvibes-sdk/platform/runtime/store/domains/discovery';
|
|
34
34
|
import type { IntelligenceDomainState } from '@pellux/goodvibes-sdk/platform/runtime/store/domains/intelligence';
|
|
35
35
|
import type { UiPerfDomainState } from './domains/ui-perf.ts';
|
|
36
|
+
// UiPerfDomainState is structurally identical to SDK's SurfacePerfDomainState.
|
|
37
|
+
// Export as SurfacePerfDomainState alias for SDK compatibility.
|
|
38
|
+
export type { UiPerfDomainState };
|
|
36
39
|
|
|
37
40
|
import { createInitialSessionState } from '@pellux/goodvibes-sdk/platform/runtime/store/domains/session';
|
|
38
41
|
import { createInitialModelState } from '@pellux/goodvibes-sdk/platform/runtime/store/domains/model';
|
|
@@ -73,7 +76,11 @@ export interface RuntimeState {
|
|
|
73
76
|
model: ModelDomainState;
|
|
74
77
|
conversation: ConversationDomainState;
|
|
75
78
|
overlays: OverlayDomainState;
|
|
76
|
-
|
|
79
|
+
/**
|
|
80
|
+
* TUI panel state. Typed as Record<string,unknown> for SDK RuntimeState
|
|
81
|
+
* compatibility. Use selectPanels() which casts to PanelDomainState.
|
|
82
|
+
*/
|
|
83
|
+
panels: Record<string, unknown>;
|
|
77
84
|
permissions: PermissionDomainState;
|
|
78
85
|
tasks: TaskDomainState;
|
|
79
86
|
agents: AgentDomainState;
|
|
@@ -95,7 +102,8 @@ export interface RuntimeState {
|
|
|
95
102
|
git: GitDomainState;
|
|
96
103
|
discovery: DiscoveryDomainState;
|
|
97
104
|
intelligence: IntelligenceDomainState;
|
|
98
|
-
|
|
105
|
+
/** Surface/UI performance metrics. SDK-compatible field name. */
|
|
106
|
+
surfacePerf: UiPerfDomainState;
|
|
99
107
|
}
|
|
100
108
|
|
|
101
109
|
/**
|
|
@@ -110,7 +118,7 @@ export function createInitialRuntimeState(): RuntimeState {
|
|
|
110
118
|
model: createInitialModelState(),
|
|
111
119
|
conversation: createInitialConversationState(),
|
|
112
120
|
overlays: createInitialOverlaysState(),
|
|
113
|
-
panels: createInitialPanelsState(),
|
|
121
|
+
panels: createInitialPanelsState() as unknown as Record<string, unknown>,
|
|
114
122
|
permissions: createInitialPermissionsState(),
|
|
115
123
|
tasks: createInitialTasksState(),
|
|
116
124
|
agents: createInitialAgentsState(),
|
|
@@ -132,6 +140,6 @@ export function createInitialRuntimeState(): RuntimeState {
|
|
|
132
140
|
git: createInitialGitState(),
|
|
133
141
|
discovery: createInitialDiscoveryState(),
|
|
134
142
|
intelligence: createInitialIntelligenceState(),
|
|
135
|
-
|
|
143
|
+
surfacePerf: createInitialUiPerfState(),
|
|
136
144
|
};
|
|
137
145
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AgentEvent,
|
|
3
|
+
AnyRuntimeEvent,
|
|
4
|
+
OpsEvent,
|
|
5
|
+
PlannerEvent,
|
|
6
|
+
ProviderEvent,
|
|
7
|
+
RuntimeEventBus,
|
|
8
|
+
RuntimeEventEnvelope,
|
|
9
|
+
SessionEvent,
|
|
10
|
+
ToolEvent,
|
|
11
|
+
TurnEvent,
|
|
12
|
+
WorkflowEvent,
|
|
13
|
+
} from '@pellux/goodvibes-sdk/platform/runtime/events/index';
|
|
14
|
+
import { createRuntimeEventFeed, type RuntimeEventFeed } from '@pellux/goodvibes-sdk/platform/runtime/event-feeds';
|
|
15
|
+
|
|
16
|
+
export type UiEventFeed<TEvent extends AnyRuntimeEvent> = RuntimeEventFeed<TEvent>;
|
|
17
|
+
|
|
18
|
+
export interface UiRuntimeEvents {
|
|
19
|
+
readonly sessions: UiEventFeed<SessionEvent>;
|
|
20
|
+
readonly turns: UiEventFeed<TurnEvent>;
|
|
21
|
+
readonly tools: UiEventFeed<ToolEvent>;
|
|
22
|
+
readonly providers: UiEventFeed<ProviderEvent>;
|
|
23
|
+
readonly agents: UiEventFeed<AgentEvent>;
|
|
24
|
+
readonly workflows: UiEventFeed<WorkflowEvent>;
|
|
25
|
+
readonly planner: UiEventFeed<PlannerEvent>;
|
|
26
|
+
readonly ops: UiEventFeed<OpsEvent>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function createUiEventFeed<TEvent extends AnyRuntimeEvent>(runtimeBus: RuntimeEventBus): UiEventFeed<TEvent> {
|
|
30
|
+
return createRuntimeEventFeed<TEvent>((type, listener) => (
|
|
31
|
+
runtimeBus.on(type as TEvent['type'], listener as (envelope: RuntimeEventEnvelope<TEvent['type'], TEvent>) => void)
|
|
32
|
+
));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function createUiRuntimeEvents(runtimeBus: RuntimeEventBus): UiRuntimeEvents {
|
|
36
|
+
return {
|
|
37
|
+
sessions: createUiEventFeed<SessionEvent>(runtimeBus),
|
|
38
|
+
turns: createUiEventFeed<TurnEvent>(runtimeBus),
|
|
39
|
+
tools: createUiEventFeed<ToolEvent>(runtimeBus),
|
|
40
|
+
providers: createUiEventFeed<ProviderEvent>(runtimeBus),
|
|
41
|
+
agents: createUiEventFeed<AgentEvent>(runtimeBus),
|
|
42
|
+
workflows: createUiEventFeed<WorkflowEvent>(runtimeBus),
|
|
43
|
+
planner: createUiEventFeed<PlannerEvent>(runtimeBus),
|
|
44
|
+
ops: createUiEventFeed<OpsEvent>(runtimeBus),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { RuntimeServices } from './services.ts';
|
|
2
2
|
import type { RemoteRunnerRegistry } from '@pellux/goodvibes-sdk/platform/runtime/remote/runner-registry';
|
|
3
3
|
import type { RemoteSupervisor } from '@pellux/goodvibes-sdk/platform/runtime/remote/supervisor';
|
|
4
|
-
import { createUiRuntimeEvents, type UiRuntimeEvents } from '
|
|
4
|
+
import { createUiRuntimeEvents, type UiRuntimeEvents } from './ui-events.ts';
|
|
5
5
|
import { createUiReadModels, type UiReadModels, type UiReadModelOptions } from './ui-read-models.ts';
|
|
6
6
|
import type { ForensicsRegistry } from '@pellux/goodvibes-sdk/platform/runtime/forensics/index';
|
|
7
7
|
import type { ControlPlaneRecentEvent } from '@pellux/goodvibes-sdk/platform/control-plane/index';
|
package/src/shell/ui-openers.ts
CHANGED
|
@@ -4,7 +4,7 @@ import type { CommandContext } from '../input/command-registry.ts';
|
|
|
4
4
|
import type { InputHandler } from '../input/handler.ts';
|
|
5
5
|
import type { PanelManager } from '../panels/panel-manager.ts';
|
|
6
6
|
import type { ProviderRegistry } from '@pellux/goodvibes-sdk/platform/providers/registry';
|
|
7
|
-
import type { MutableRuntimeState } from '
|
|
7
|
+
import type { MutableRuntimeState } from '@pellux/goodvibes-sdk/platform/runtime/mutable-runtime-state';
|
|
8
8
|
import type { FeatureFlagManager } from '@pellux/goodvibes-sdk/platform/runtime/feature-flags/index';
|
|
9
9
|
import type { McpRegistry } from '@pellux/goodvibes-sdk/platform/mcp/registry';
|
|
10
10
|
import type { SubscriptionManager } from '@pellux/goodvibes-sdk/platform/config/subscriptions';
|