@pellux/goodvibes-agent 1.3.0 → 1.4.2
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 +45 -0
- package/README.md +0 -1
- package/dist/package/{ast-grep-napi.linux-x64-gnu-swtppvy9.node → ast-grep-napi.linux-x64-gnu-mkk8xwww.node} +0 -0
- package/dist/package/{ast-grep-napi.linux-x64-musl-ttfcdtap.node → ast-grep-napi.linux-x64-musl-ryqtgdv6.node} +0 -0
- package/dist/package/main.js +55623 -55535
- package/docs/README.md +0 -1
- package/docs/tools-and-commands.md +0 -3
- package/package.json +1 -1
- package/release/release-notes.md +7 -156
- package/src/agent/competitive-feature-inventory.ts +1 -1
- package/src/agent/setup-wizard.ts +28 -21
- package/src/cli/tui-startup.ts +2 -2
- package/src/input/agent-workspace-activation.ts +2 -2
- package/src/input/agent-workspace-categories.ts +3 -20
- package/src/input/agent-workspace-onboarding-finish.ts +21 -0
- package/src/input/agent-workspace-settings.ts +14 -19
- package/src/input/agent-workspace-setup-snapshot.ts +2 -10
- package/src/input/agent-workspace-setup.ts +14 -47
- package/src/input/agent-workspace-snapshot.ts +0 -7
- package/src/input/agent-workspace-types.ts +5 -2
- package/src/input/agent-workspace.ts +19 -8
- package/src/input/commands.ts +0 -4
- package/src/input/handler.ts +70 -5
- package/src/main.ts +1 -40
- package/src/panels/builtin/agent.ts +0 -28
- package/src/renderer/agent-workspace-context-lines.ts +11 -42
- package/src/renderer/agent-workspace.ts +414 -31
- package/src/renderer/help-overlay.ts +0 -2
- package/src/tools/agent-harness-setup-posture.ts +7 -7
- package/src/version.ts +1 -1
- package/docs/project-planning.md +0 -81
- package/src/input/commands/planning-runtime.ts +0 -215
- package/src/input/commands/work-plan-runtime.ts +0 -191
- package/src/panels/plan-dashboard-panel.ts +0 -274
- package/src/panels/project-planning-panel.ts +0 -721
- package/src/panels/work-plan-panel.ts +0 -175
- package/src/planning/project-planning-coordinator.ts +0 -543
|
@@ -46,58 +46,27 @@ function setupAttentionItems(snapshot: AgentWorkspaceRuntimeSnapshot, limit: num
|
|
|
46
46
|
|
|
47
47
|
function setupOverviewLines(snapshot: AgentWorkspaceRuntimeSnapshot): ContextLine[] {
|
|
48
48
|
const counts = setupCounts(snapshot);
|
|
49
|
-
const
|
|
50
|
-
const
|
|
49
|
+
const attentionItems = setupAttentionItems(snapshot, 1);
|
|
50
|
+
const doneCount = counts.ready;
|
|
51
|
+
const totalCount = snapshot.setupChecklist.length;
|
|
52
|
+
const attentionCount = counts.blocked + counts.recommended;
|
|
53
|
+
const progressDetail = attentionCount > 0
|
|
54
|
+
? `${doneCount} of ${totalCount} done — ${attentionCount} need attention`
|
|
55
|
+
: `${doneCount} of ${totalCount} done`;
|
|
51
56
|
const lines: ContextLine[] = [
|
|
52
57
|
{ text: 'Onboarding', fg: PALETTE.title, bold: true },
|
|
53
|
-
{ text:
|
|
54
|
-
{ text: `Setup wizard: ${wizard.completedSteps}/${wizard.totalSteps} done; ${wizard.currentStepLabel ? `current ${wizard.currentStepLabel}` : wizard.status}.`, fg: wizard.status === 'complete' ? PALETTE.good : wizard.status === 'blocked' ? PALETTE.warn : PALETTE.info },
|
|
55
|
-
{ text: `Wizard next: ${compactText(wizard.next, 112)}`, fg: wizard.status === 'complete' ? PALETTE.good : wizard.status === 'blocked' ? PALETTE.warn : PALETTE.info },
|
|
56
|
-
{ text: `Setup closeout: ${wizard.closeout.label}; ${compactText(wizard.closeout.nextAction, 104)}`, fg: wizard.closeout.status === 'complete' || wizard.closeout.status === 'ready-to-finish' ? PALETTE.good : wizard.closeout.status === 'blocked' ? PALETTE.warn : PALETTE.info },
|
|
58
|
+
{ text: progressDetail, fg: counts.blocked > 0 ? PALETTE.warn : doneCount === totalCount ? PALETTE.good : PALETTE.info },
|
|
57
59
|
{ text: `Chat: ${snapshot.provider} / ${snapshot.modelDisplayName}.`, fg: PALETTE.info },
|
|
58
60
|
{ text: `Local: ${snapshot.localPersonaCount} personas, ${snapshot.localSkillCount} skills, ${snapshot.localRoutineCount} routines, ${snapshot.localMemoryCount} memories.`, fg: PALETTE.info },
|
|
59
61
|
];
|
|
60
|
-
if (
|
|
61
|
-
const item =
|
|
62
|
+
if (attentionItems.length > 0) {
|
|
63
|
+
const item = attentionItems[0]!;
|
|
62
64
|
lines.push({
|
|
63
65
|
text: `Next: ${item.label} (${setupStatusLabel(item.status).toLowerCase()})`,
|
|
64
66
|
fg: setupStatusColor(item.status),
|
|
65
67
|
bold: item.status === 'blocked',
|
|
66
68
|
});
|
|
67
69
|
}
|
|
68
|
-
if (wizard.repeatedBlocker) {
|
|
69
|
-
lines.push({
|
|
70
|
-
text: `Repeated blocker: ${wizard.repeatedBlocker.checkId} in ${wizard.repeatedBlocker.count} saved smoke run(s).`,
|
|
71
|
-
fg: PALETTE.warn,
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
if (wizard.checkpoint.status !== 'none') {
|
|
75
|
-
lines.push({
|
|
76
|
-
text: `Setup checkpoint: ${compactText(wizard.checkpoint.summary, 112)}`,
|
|
77
|
-
fg: wizard.checkpoint.status === 'stale' || wizard.checkpoint.status === 'unavailable' ? PALETTE.warn : PALETTE.info,
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
if (wizard.smokeHistory.status === 'available') {
|
|
81
|
-
lines.push({
|
|
82
|
-
text: `Smoke history: ${wizard.smokeHistory.total} run(s); trend ${wizard.smokeHistory.trend}; latest ${wizard.smokeHistory.latestResult ?? 'unknown'}.`,
|
|
83
|
-
fg: wizard.smokeHistory.latestResult === 'blocked' ? PALETTE.warn : PALETTE.info,
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
if (wizard.stepHistory.length > 0) {
|
|
87
|
-
const latest = wizard.stepHistory[0]!;
|
|
88
|
-
lines.push({
|
|
89
|
-
text: `Step history: ${wizard.stepHistory.length} recorded; latest ${latest.stepLabel} ${latest.kind} at ${latest.recordedAt}.`,
|
|
90
|
-
fg: PALETTE.good,
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
if (wizard.receiptGaps.length > 0) {
|
|
94
|
-
const labels = wizard.receiptGaps.slice(0, 3).map((gap) => gap.stepLabel).join(', ');
|
|
95
|
-
const suffix = wizard.receiptGaps.length > 3 ? `, +${wizard.receiptGaps.length - 3} more` : '';
|
|
96
|
-
lines.push({
|
|
97
|
-
text: `Receipt gaps: ${labels}${suffix} still need durable setup receipt ids.`,
|
|
98
|
-
fg: PALETTE.warn,
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
70
|
return lines;
|
|
102
71
|
}
|
|
103
72
|
|
|
@@ -551,7 +520,7 @@ export function snapshotLines(workspace: AgentWorkspace, category: AgentWorkspac
|
|
|
551
520
|
companionAccessLine(snapshot),
|
|
552
521
|
{ text: `Channels: ${readyCount}/${snapshot.channels.length} ready; ${enabledCount} enabled; ${configuredDefaults} target(s).`, fg: PALETTE.info },
|
|
553
522
|
{ text: `Setup guide: ${guide.progressLabel}; ${guide.currentChannelLabel ?? 'choose a channel'}.`, fg: guide.status === 'ready' ? PALETTE.good : PALETTE.warn },
|
|
554
|
-
{ text: `Next: ${currentGuideStep ?
|
|
523
|
+
{ text: `Next: ${currentGuideStep ? currentGuideStep.label : 'All enabled channels ready.'}`, fg: currentGuideStep ? PALETTE.warn : PALETTE.good },
|
|
555
524
|
{ text: 'Guide checks setup schema, accounts, allowlist policy, live status, and explicit test sends.', fg: PALETTE.good },
|
|
556
525
|
{ text: 'Triage: /channels triage shows blockers, delivery retries, surface messages, route bindings, and receipts.', fg: PALETTE.good },
|
|
557
526
|
{ text: 'Secrets hidden; sends require explicit action.', fg: PALETTE.warn },
|
|
@@ -5,6 +5,8 @@ import type {
|
|
|
5
5
|
AgentWorkspaceLocalEditor,
|
|
6
6
|
AgentWorkspaceRuntimeSnapshot,
|
|
7
7
|
} from '../input/agent-workspace.ts';
|
|
8
|
+
import type { AgentWorkspaceEditorKind } from '../input/agent-workspace-types.ts';
|
|
9
|
+
import type { AgentWorkspaceSetupChecklistItem } from '../input/agent-workspace-setup.ts';
|
|
8
10
|
import type { Line } from '../types/grid.ts';
|
|
9
11
|
import { wrapText } from '../utils/terminal-width.ts';
|
|
10
12
|
import { GLYPHS } from './ui-primitives.ts';
|
|
@@ -18,11 +20,36 @@ import {
|
|
|
18
20
|
} from './fullscreen-workspace.ts';
|
|
19
21
|
import { actionResultColor, type AgentWorkspaceContextLine as ContextLine } from './agent-workspace-style.ts';
|
|
20
22
|
import { compactText, reviewerReadinessContextLines, snapshotLines } from './agent-workspace-context-lines.ts';
|
|
23
|
+
import { ONBOARDING_COMPLETE_SYNTHETIC_ACTION, ONBOARDING_CRITICAL_STEP_IDS } from '../input/agent-workspace-onboarding-finish.ts';
|
|
24
|
+
|
|
25
|
+
function onboardingCategoryReadiness(
|
|
26
|
+
category: AgentWorkspaceCategory,
|
|
27
|
+
checklist: readonly AgentWorkspaceSetupChecklistItem[],
|
|
28
|
+
): 'ready' | 'attention' | 'optional' {
|
|
29
|
+
const CATEGORY_CHECKLIST_MAP: Record<string, readonly string[]> = {
|
|
30
|
+
'setup': ['provider-model', 'connected-host-auth', 'runtime'],
|
|
31
|
+
'account-model': ['provider-model', 'subscriptions'],
|
|
32
|
+
'assistant-behavior': [],
|
|
33
|
+
'tools-permissions': [],
|
|
34
|
+
'onboarding-display': [],
|
|
35
|
+
'onboarding-channels': ['channels'],
|
|
36
|
+
'onboarding-voice-media': ['voice-media'],
|
|
37
|
+
'onboarding-context': ['agent-knowledge', 'persona', 'skills', 'routines', 'memory', 'notes', 'profile'],
|
|
38
|
+
'onboarding-automation': [],
|
|
39
|
+
};
|
|
40
|
+
const itemIds = CATEGORY_CHECKLIST_MAP[category.id];
|
|
41
|
+
if (!itemIds || itemIds.length === 0) return 'optional';
|
|
42
|
+
const mapped = itemIds.map((id) => checklist.find((item) => item.id === id));
|
|
43
|
+
if (mapped.every((item) => item?.status === 'ready')) return 'ready';
|
|
44
|
+
if (mapped.some((item) => item?.status === 'blocked' || item?.status === 'recommended')) return 'attention';
|
|
45
|
+
return 'optional';
|
|
46
|
+
}
|
|
21
47
|
|
|
22
48
|
function buildLeftRows(workspace: AgentWorkspace, height: number): WorkspaceRow[] {
|
|
23
49
|
const rows: WorkspaceRow[] = [];
|
|
24
50
|
let selectedRenderedIndex = 0;
|
|
25
51
|
let lastGroup = '';
|
|
52
|
+
const checklist = workspace.runtimeSnapshot?.setupChecklist ?? [];
|
|
26
53
|
|
|
27
54
|
workspace.categories.forEach((category, index) => {
|
|
28
55
|
if (category.group !== lastGroup) {
|
|
@@ -32,11 +59,24 @@ function buildLeftRows(workspace: AgentWorkspace, height: number): WorkspaceRow[
|
|
|
32
59
|
const selected = index === workspace.selectedCategoryIndex;
|
|
33
60
|
if (selected) selectedRenderedIndex = rows.length;
|
|
34
61
|
const marker = selected ? GLYPHS.navigation.selected : ' ';
|
|
62
|
+
let readinessGlyph = '';
|
|
63
|
+
let readinessFg: string | undefined;
|
|
64
|
+
if (isOnboardingCategory(category)) {
|
|
65
|
+
const readiness = onboardingCategoryReadiness(category, checklist);
|
|
66
|
+
if (readiness === 'ready') {
|
|
67
|
+
readinessGlyph = GLYPHS.status.success;
|
|
68
|
+
readinessFg = PALETTE.good;
|
|
69
|
+
} else if (readiness === 'attention') {
|
|
70
|
+
readinessGlyph = '!';
|
|
71
|
+
readinessFg = PALETTE.warn;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const readinessMark = readinessGlyph ? `${readinessGlyph} ` : ' ';
|
|
35
75
|
rows.push({
|
|
36
|
-
text: ` ${marker} ${category.label}`,
|
|
76
|
+
text: ` ${marker} ${readinessMark}${category.label}`,
|
|
37
77
|
selected: selected && workspace.focusPane === 'categories',
|
|
38
78
|
kind: 'item',
|
|
39
|
-
fg: selected ? PALETTE.text : PALETTE.muted,
|
|
79
|
+
fg: selected ? PALETTE.text : readinessFg ?? PALETTE.muted,
|
|
40
80
|
bold: selected,
|
|
41
81
|
});
|
|
42
82
|
});
|
|
@@ -72,41 +112,323 @@ function isOnboardingCategory(category: AgentWorkspaceCategory): boolean {
|
|
|
72
112
|
return category.group === 'ONBOARDING';
|
|
73
113
|
}
|
|
74
114
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
115
|
+
interface OnboardingActionColumns {
|
|
116
|
+
readonly setting: string;
|
|
117
|
+
readonly defaultValue: string;
|
|
118
|
+
readonly currentValue: string;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function editorPurposeLabel(editorKind: AgentWorkspaceEditorKind): string {
|
|
122
|
+
switch (editorKind) {
|
|
123
|
+
case 'mcp-server': return 'Edit MCP server';
|
|
124
|
+
case 'mcp-tools-server': return 'Edit MCP tools server';
|
|
125
|
+
case 'mcp-repair': return 'Repair MCP connection';
|
|
126
|
+
case 'secret-link': return 'Link secret reference';
|
|
127
|
+
case 'secret-set': return 'Store secret';
|
|
128
|
+
case 'secret-test': return 'Test secret reference';
|
|
129
|
+
case 'secret-delete': return 'Delete secret';
|
|
130
|
+
case 'subscription-login-start': return 'Sign in to provider';
|
|
131
|
+
case 'subscription-login-finish': return 'Finish provider sign-in';
|
|
132
|
+
case 'subscription-logout': return 'Sign out of provider';
|
|
133
|
+
case 'subscription-inspect': return 'Inspect subscription';
|
|
134
|
+
case 'provider-add': return 'Add custom provider';
|
|
135
|
+
case 'provider-remove': return 'Remove custom provider';
|
|
136
|
+
case 'provider-use': return 'Choose provider';
|
|
137
|
+
case 'provider-inspect': return 'Inspect provider';
|
|
138
|
+
case 'provider-routes': return 'Edit provider routes';
|
|
139
|
+
case 'provider-account-repair': return 'Repair provider account';
|
|
140
|
+
case 'memory': return 'Edit memory';
|
|
141
|
+
case 'memory-search': return 'Search memory';
|
|
142
|
+
case 'memory-get': return 'Get memory record';
|
|
143
|
+
case 'memory-explain': return 'Explain memory';
|
|
144
|
+
case 'memory-promote': return 'Promote memory';
|
|
145
|
+
case 'memory-link': return 'Link memory';
|
|
146
|
+
case 'memory-export': return 'Export memory';
|
|
147
|
+
case 'memory-import': return 'Import memory';
|
|
148
|
+
case 'memory-handoff-export': return 'Export memory handoff';
|
|
149
|
+
case 'memory-handoff-inspect': return 'Inspect memory handoff';
|
|
150
|
+
case 'memory-handoff-import': return 'Import memory handoff';
|
|
151
|
+
case 'memory-vector-rebuild': return 'Rebuild memory vectors';
|
|
152
|
+
case 'note': return 'Edit note';
|
|
153
|
+
case 'persona': return 'Edit persona';
|
|
154
|
+
case 'persona-search': return 'Search personas';
|
|
155
|
+
case 'persona-show': return 'Show persona';
|
|
156
|
+
case 'persona-discovery-import': return 'Import persona files';
|
|
157
|
+
case 'skill': return 'Edit skill';
|
|
158
|
+
case 'skill-search': return 'Search skills';
|
|
159
|
+
case 'skill-show': return 'Show skill';
|
|
160
|
+
case 'skill-discovery-import': return 'Import skill files';
|
|
161
|
+
case 'routine': return 'Edit routine';
|
|
162
|
+
case 'routine-search': return 'Search routines';
|
|
163
|
+
case 'routine-show': return 'Show routine';
|
|
164
|
+
case 'routine-discovery-import': return 'Import routine files';
|
|
165
|
+
case 'profile': return 'Edit profile';
|
|
166
|
+
case 'profile-from-discovered': return 'Create profile from files';
|
|
167
|
+
case 'profile-show': return 'Show profile';
|
|
168
|
+
case 'profile-default': return 'Set default profile';
|
|
169
|
+
case 'profile-default-clear': return 'Clear default profile';
|
|
170
|
+
case 'profile-delete': return 'Delete profile';
|
|
171
|
+
case 'profile-template-export': return 'Export profile template';
|
|
172
|
+
case 'profile-template-import': return 'Import profile template';
|
|
173
|
+
case 'profile-template-show': return 'Show profile template';
|
|
174
|
+
case 'profile-template-from-discovered': return 'Create template from files';
|
|
175
|
+
case 'knowledge-url': return 'Ingest URL';
|
|
176
|
+
case 'knowledge-urls': return 'Ingest URLs';
|
|
177
|
+
case 'knowledge-file': return 'Ingest file';
|
|
178
|
+
case 'knowledge-bookmarks': return 'Import bookmarks';
|
|
179
|
+
case 'knowledge-browser-history': return 'Import browser history';
|
|
180
|
+
case 'knowledge-connector-ingest': return 'Run connector ingest';
|
|
181
|
+
case 'knowledge-connector-show': return 'Show connector';
|
|
182
|
+
case 'knowledge-connector-doctor': return 'Check connector health';
|
|
183
|
+
case 'knowledge-reindex': return 'Reindex knowledge';
|
|
184
|
+
case 'knowledge-search': return 'Search knowledge';
|
|
185
|
+
case 'knowledge-ask': return 'Ask knowledge';
|
|
186
|
+
case 'knowledge-get': return 'Get knowledge record';
|
|
187
|
+
case 'knowledge-map': return 'Map knowledge';
|
|
188
|
+
case 'knowledge-review-issue': return 'Review knowledge issue';
|
|
189
|
+
case 'knowledge-consolidate': return 'Consolidate knowledge';
|
|
190
|
+
case 'knowledge-packet': return 'Build knowledge packet';
|
|
191
|
+
case 'knowledge-explain': return 'Explain knowledge';
|
|
192
|
+
case 'delegate-task': return 'Delegate build task';
|
|
193
|
+
case 'document-browse': return 'Browse documents';
|
|
194
|
+
case 'document-show': return 'Show document';
|
|
195
|
+
case 'document-create': return 'Create document';
|
|
196
|
+
case 'document-update': return 'Revise document';
|
|
197
|
+
case 'document-review': return 'Review document';
|
|
198
|
+
case 'document-comment': return 'Add comment';
|
|
199
|
+
case 'document-resolve-comment': return 'Resolve comment';
|
|
200
|
+
case 'document-suggest': return 'Propose suggestion';
|
|
201
|
+
case 'document-accept-suggestion': return 'Accept suggestion';
|
|
202
|
+
case 'document-reject-suggestion': return 'Reject suggestion';
|
|
203
|
+
case 'document-insert-artifact': return 'Insert artifact';
|
|
204
|
+
case 'document-attach-artifact': return 'Attach artifact';
|
|
205
|
+
case 'document-export': return 'Export document';
|
|
206
|
+
case 'document-reviewer-readiness': return 'Review readiness preflight';
|
|
207
|
+
case 'document-review-packet-wizard': return 'Run packet wizard';
|
|
208
|
+
case 'document-review-packet-preset': return 'Save packet preset';
|
|
209
|
+
case 'document-review-packet-preset-refresh': return 'Refresh packet preset';
|
|
210
|
+
case 'document-review-packet-share': return 'Share review packet';
|
|
211
|
+
case 'model-compare': return 'Compare models';
|
|
212
|
+
case 'model-compare-review': return 'Review comparison';
|
|
213
|
+
case 'model-compare-handoff-diff': return 'Diff reviewer handoffs';
|
|
214
|
+
case 'model-compare-judge': return 'Judge comparison';
|
|
215
|
+
case 'model-compare-apply': return 'Apply comparison winner';
|
|
216
|
+
case 'model-compare-route-decision': return 'Record route decision';
|
|
217
|
+
case 'model-compare-export': return 'Export comparison';
|
|
218
|
+
case 'model-compare-analytics': return 'View comparison analytics';
|
|
219
|
+
case 'local-model-benchmark': return 'Run local benchmark';
|
|
220
|
+
case 'auth-show': return 'Show auth status';
|
|
221
|
+
case 'auth-repair': return 'Repair auth';
|
|
222
|
+
case 'auth-bundle-export': return 'Export auth bundle';
|
|
223
|
+
case 'auth-bundle-inspect': return 'Inspect auth bundle';
|
|
224
|
+
case 'trust-bundle-export': return 'Export trust bundle';
|
|
225
|
+
case 'trust-bundle-inspect': return 'Inspect trust bundle';
|
|
226
|
+
case 'support-bundle-export': return 'Export support bundle';
|
|
227
|
+
case 'support-bundle-inspect': return 'Inspect support bundle';
|
|
228
|
+
case 'support-bundle-import': return 'Import support bundle';
|
|
229
|
+
case 'subscription-bundle-export': return 'Export subscription bundle';
|
|
230
|
+
case 'subscription-bundle-inspect': return 'Inspect subscription bundle';
|
|
231
|
+
case 'voice-enable': return 'Enable voice';
|
|
232
|
+
case 'voice-disable': return 'Disable voice';
|
|
233
|
+
case 'voice-bundle-export': return 'Export voice bundle';
|
|
234
|
+
case 'voice-bundle-inspect': return 'Inspect voice bundle';
|
|
235
|
+
case 'tts-prompt': return 'Test TTS prompt';
|
|
236
|
+
case 'image-input': return 'Attach image';
|
|
237
|
+
case 'artifact-browser': return 'Browse artifacts';
|
|
238
|
+
case 'artifact-show': return 'Show artifact';
|
|
239
|
+
case 'artifact-export-file': return 'Export artifact to file';
|
|
240
|
+
case 'artifact-export-package': return 'Export artifact package';
|
|
241
|
+
case 'artifact-promote-knowledge': return 'Promote artifact to knowledge';
|
|
242
|
+
case 'media-generate': return 'Generate media';
|
|
243
|
+
case 'conversation-export': return 'Export conversation';
|
|
244
|
+
case 'conversation-events': return 'Show conversation events';
|
|
245
|
+
case 'conversation-groups': return 'Show conversation groups';
|
|
246
|
+
case 'conversation-find': return 'Find conversation';
|
|
247
|
+
case 'effort-level': return 'Set effort level';
|
|
248
|
+
case 'channel-show': return 'Show channel';
|
|
249
|
+
case 'channel-doctor': return 'Check channel health';
|
|
250
|
+
case 'channel-setup': return 'Set up channel';
|
|
251
|
+
case 'channel-send': return 'Send to channel';
|
|
252
|
+
case 'session-save': return 'Save session';
|
|
253
|
+
case 'session-load': return 'Load session';
|
|
254
|
+
case 'session-rename': return 'Rename session';
|
|
255
|
+
case 'session-resume': return 'Resume session';
|
|
256
|
+
case 'session-info': return 'Inspect session';
|
|
257
|
+
case 'session-export-saved': return 'Export saved session';
|
|
258
|
+
case 'session-search': return 'Search sessions';
|
|
259
|
+
case 'session-delete': return 'Delete session';
|
|
260
|
+
case 'session-fork': return 'Fork session';
|
|
261
|
+
case 'session-graph': return 'Inspect session graph';
|
|
262
|
+
case 'task-list-filter': return 'Filter task list';
|
|
263
|
+
case 'task-show': return 'Show task';
|
|
264
|
+
case 'task-output': return 'View task output';
|
|
265
|
+
case 'plan-seed': return 'Seed plan';
|
|
266
|
+
case 'plan-show': return 'Show plan';
|
|
267
|
+
case 'plan-approve': return 'Approve plan';
|
|
268
|
+
case 'plan-override': return 'Override plan';
|
|
269
|
+
case 'plan-clear': return 'Clear plan';
|
|
270
|
+
case 'health-repair': return 'Repair health issue';
|
|
271
|
+
case 'approval-review': return 'Review approval';
|
|
272
|
+
case 'approval-approve': return 'Approve request';
|
|
273
|
+
case 'approval-deny': return 'Deny request';
|
|
274
|
+
case 'approval-cancel': return 'Cancel approval';
|
|
275
|
+
case 'automation-job-run': return 'Run automation job';
|
|
276
|
+
case 'automation-job-pause': return 'Pause automation job';
|
|
277
|
+
case 'automation-job-resume': return 'Resume automation job';
|
|
278
|
+
case 'automation-run-cancel': return 'Cancel automation run';
|
|
279
|
+
case 'automation-run-retry': return 'Retry automation run';
|
|
280
|
+
case 'schedule-run': return 'Run schedule';
|
|
281
|
+
case 'schedule-edit': return 'Edit schedule';
|
|
282
|
+
case 'routine-receipt': return 'View routine receipt';
|
|
283
|
+
case 'schedule-receipt': return 'View schedule receipt';
|
|
284
|
+
case 'mode-preset': return 'Set mode preset';
|
|
285
|
+
case 'mode-domain': return 'Set mode domain';
|
|
286
|
+
case 'setting-set': return 'Set setting';
|
|
287
|
+
case 'model-pin': return 'Pin model';
|
|
288
|
+
case 'model-unpin': return 'Unpin model';
|
|
289
|
+
case 'workplan-add': return 'Add work item';
|
|
290
|
+
case 'workplan-show': return 'Show work plan';
|
|
291
|
+
case 'workplan-status': return 'Check work plan status';
|
|
292
|
+
case 'workplan-delete': return 'Delete work item';
|
|
293
|
+
case 'workplan-clear-completed': return 'Clear completed items';
|
|
294
|
+
case 'routine-schedule': return 'Schedule routine';
|
|
295
|
+
case 'reminder-schedule': return 'Schedule reminder';
|
|
296
|
+
case 'skill-bundle': return 'Edit skill bundle';
|
|
297
|
+
case 'skill-bundle-search': return 'Search skill bundles';
|
|
298
|
+
case 'skill-bundle-show': return 'Show skill bundle';
|
|
299
|
+
case 'skill-bundle-update': return 'Update skill bundle';
|
|
300
|
+
case 'skill-bundle-enable': return 'Enable skill bundle';
|
|
301
|
+
case 'skill-bundle-disable': return 'Disable skill bundle';
|
|
302
|
+
case 'skill-bundle-review': return 'Review skill bundle';
|
|
303
|
+
case 'skill-bundle-stale': return 'Mark bundle stale';
|
|
304
|
+
case 'skill-bundle-delete': return 'Delete skill bundle';
|
|
305
|
+
case 'learned-behavior': return 'Review learned behavior';
|
|
306
|
+
case 'web-research': return 'Run web research';
|
|
307
|
+
case 'web-fetch': return 'Fetch from web';
|
|
308
|
+
case 'research-run': return 'Run research';
|
|
309
|
+
case 'research-source': return 'Manage research source';
|
|
310
|
+
case 'research-report': return 'Show research report';
|
|
311
|
+
case 'notify-webhook': return 'Add notification webhook';
|
|
312
|
+
case 'notify-webhook-remove': return 'Remove notification webhook';
|
|
313
|
+
case 'notify-webhook-clear': return 'Clear notification webhooks';
|
|
314
|
+
case 'notify-webhook-test': return 'Test notification webhook';
|
|
315
|
+
case 'notify-send': return 'Send notification';
|
|
316
|
+
default: return `Edit ${editorKind}`;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
function localOperationLabel(localOperation: string): string {
|
|
321
|
+
switch (localOperation) {
|
|
322
|
+
case 'routine-start': return 'Start routine';
|
|
323
|
+
case 'persona-activate':
|
|
324
|
+
case 'persona-use': return 'Activate persona';
|
|
325
|
+
case 'persona-clear': return 'Deactivate persona';
|
|
326
|
+
case 'persona-edit': return 'Edit persona';
|
|
327
|
+
case 'persona-review': return 'Review persona';
|
|
328
|
+
case 'persona-delete': return 'Delete persona';
|
|
329
|
+
case 'memory-edit': return 'Edit memory';
|
|
330
|
+
case 'memory-review': return 'Review memory';
|
|
331
|
+
case 'memory-stale': return 'Mark memory stale';
|
|
332
|
+
case 'memory-delete': return 'Delete memory';
|
|
333
|
+
case 'note-edit': return 'Edit note';
|
|
334
|
+
case 'note-review': return 'Review note';
|
|
335
|
+
case 'note-stale': return 'Mark note stale';
|
|
336
|
+
case 'note-delete': return 'Delete note';
|
|
337
|
+
case 'note-promote-memory': return 'Promote note to memory';
|
|
338
|
+
case 'note-promote-persona': return 'Promote note to persona';
|
|
339
|
+
case 'note-promote-skill': return 'Promote note to skill';
|
|
340
|
+
case 'note-promote-routine': return 'Promote note to routine';
|
|
341
|
+
case 'note-promote-knowledge-url': return 'Promote note to knowledge';
|
|
342
|
+
case 'skill-edit': return 'Edit skill';
|
|
343
|
+
case 'skill-enable': return 'Enable skill';
|
|
344
|
+
case 'skill-disable': return 'Disable skill';
|
|
345
|
+
case 'skill-review': return 'Review skill';
|
|
346
|
+
case 'skill-delete': return 'Delete skill';
|
|
347
|
+
case 'routine-edit': return 'Edit routine';
|
|
348
|
+
case 'routine-enable': return 'Enable routine';
|
|
349
|
+
case 'routine-disable': return 'Disable routine';
|
|
350
|
+
case 'routine-review': return 'Review routine';
|
|
351
|
+
case 'routine-delete': return 'Delete routine';
|
|
352
|
+
default: return 'Apply local action';
|
|
78
353
|
}
|
|
79
|
-
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
function onboardingActionLabel(workspace: AgentWorkspace, action: AgentWorkspaceAction): string {
|
|
357
|
+
if (action.kind === 'settings-import') return 'Import GoodVibes preferences';
|
|
80
358
|
if (action.kind === 'setup-checkpoint') {
|
|
81
|
-
if (action.setupCheckpointOperation === 'show') return '
|
|
82
|
-
if (action.setupCheckpointOperation === 'mark-current') return 'Save
|
|
83
|
-
if (action.setupCheckpointOperation === 'clear') return 'Clear saved
|
|
359
|
+
if (action.setupCheckpointOperation === 'show') return 'Review saved progress';
|
|
360
|
+
if (action.setupCheckpointOperation === 'mark-current') return 'Save progress';
|
|
361
|
+
if (action.setupCheckpointOperation === 'clear') return 'Clear saved progress';
|
|
84
362
|
return 'Review setup progress';
|
|
85
363
|
}
|
|
86
|
-
if (action.kind === 'model-picker') return action.modelPickerFlow === 'model' ? 'Choose
|
|
364
|
+
if (action.kind === 'model-picker') return action.modelPickerFlow === 'model' ? 'Choose model' : 'Choose provider and model';
|
|
87
365
|
if (action.kind === 'settings-modal') return 'Open settings';
|
|
88
|
-
if (action.kind === 'workspace')
|
|
89
|
-
|
|
366
|
+
if (action.kind === 'workspace') {
|
|
367
|
+
if (action.targetCategoryId) {
|
|
368
|
+
const target = workspace.categories.find((c) => c.id === action.targetCategoryId);
|
|
369
|
+
const label = target ? target.label : action.targetCategoryId;
|
|
370
|
+
return `Switch to ${label}`;
|
|
371
|
+
}
|
|
372
|
+
return 'Switch to setup area';
|
|
373
|
+
}
|
|
374
|
+
if (action.kind === 'editor') return action.editorKind ? editorPurposeLabel(action.editorKind) : 'Open form';
|
|
90
375
|
if (action.kind === 'local-selection') return 'Move selection';
|
|
91
|
-
if (action.kind === 'local-operation') return 'Apply
|
|
92
|
-
if (action.kind === 'onboarding-complete') return '
|
|
93
|
-
if (action.
|
|
376
|
+
if (action.kind === 'local-operation') return action.localOperation ? localOperationLabel(action.localOperation) : 'Apply local action';
|
|
377
|
+
if (action.kind === 'onboarding-complete') return 'Finish setup';
|
|
378
|
+
if (action.kind === 'command') {
|
|
379
|
+
const cmd = action.command ?? '';
|
|
380
|
+
return action.commandBehavior === 'inline' ? `Run: ${cmd}` : `Open: ${cmd}`;
|
|
381
|
+
}
|
|
382
|
+
if (action.safety === 'read-only') return 'Review';
|
|
94
383
|
if (action.safety === 'blocked') return 'Unavailable in this setup step';
|
|
95
|
-
return 'Open
|
|
384
|
+
return 'Open';
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
function onboardingActionColumns(workspace: AgentWorkspace, action: AgentWorkspaceAction): OnboardingActionColumns {
|
|
388
|
+
if (action.kind === 'setting') {
|
|
389
|
+
return workspace.settingActionDisplay(action) ?? {
|
|
390
|
+
setting: action.label,
|
|
391
|
+
defaultValue: '(unknown)',
|
|
392
|
+
currentValue: '(unknown)',
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
// Non-setting rows keep the 3-column layout but use placeholders for Default and Current,
|
|
396
|
+
// since those concepts only make sense for actual settings. The action label carries
|
|
397
|
+
// the meaning of the row.
|
|
398
|
+
return {
|
|
399
|
+
setting: action.label,
|
|
400
|
+
defaultValue: '—',
|
|
401
|
+
currentValue: '—',
|
|
402
|
+
};
|
|
96
403
|
}
|
|
97
404
|
|
|
98
405
|
function actionChange(workspace: AgentWorkspace, category: AgentWorkspaceCategory, action: AgentWorkspaceAction): string {
|
|
99
|
-
return isOnboardingCategory(category) ?
|
|
406
|
+
return isOnboardingCategory(category) ? onboardingActionColumns(workspace, action).setting : actionCommand(action);
|
|
100
407
|
}
|
|
101
408
|
|
|
102
409
|
function actionMetaLine(workspace: AgentWorkspace, category: AgentWorkspaceCategory, action: AgentWorkspaceAction): ContextLine {
|
|
103
410
|
const onboarding = isOnboardingCategory(category);
|
|
411
|
+
if (onboarding) {
|
|
412
|
+
return {
|
|
413
|
+
text: `About: ${compactText(action.detail, 100)}`,
|
|
414
|
+
fg: action.safety === 'blocked' ? PALETTE.warn : PALETTE.muted,
|
|
415
|
+
};
|
|
416
|
+
}
|
|
104
417
|
return {
|
|
105
|
-
text:
|
|
106
|
-
fg: action.safety === 'blocked' ? PALETTE.warn :
|
|
418
|
+
text: `Does: ${actionChange(workspace, category, action)}`,
|
|
419
|
+
fg: action.safety === 'blocked' ? PALETTE.warn : action.kind === 'command' ? PALETTE.info : PALETTE.muted,
|
|
107
420
|
};
|
|
108
421
|
}
|
|
109
422
|
|
|
423
|
+
function shouldRenderOnboardingSettingsTable(actions: readonly AgentWorkspaceAction[]): boolean {
|
|
424
|
+
// Always use the Setting/Default/Current 3-column layout on ONBOARDING pages so the
|
|
425
|
+
// user gets a consistent visual structure across every category, even ones that mix
|
|
426
|
+
// settings with editors, guidance, or pickers. Non-setting rows fill Default/Current
|
|
427
|
+
// with placeholders via onboardingActionColumns().
|
|
428
|
+
const nonFinish = actions.filter((a) => a.kind !== 'onboarding-complete');
|
|
429
|
+
return nonFinish.length > 0;
|
|
430
|
+
}
|
|
431
|
+
|
|
110
432
|
function editorContextLines(editor: AgentWorkspaceLocalEditor, snapshot: AgentWorkspaceRuntimeSnapshot | null): ContextLine[] {
|
|
111
433
|
const selected = editor.fields[editor.selectedFieldIndex];
|
|
112
434
|
const lines: ContextLine[] = [
|
|
@@ -244,12 +566,25 @@ function buildEditorFieldRows(editor: AgentWorkspaceLocalEditor, index: number,
|
|
|
244
566
|
return rows;
|
|
245
567
|
}
|
|
246
568
|
|
|
569
|
+
function onboardingFinishPrerequisitesMet(workspace: AgentWorkspace): boolean {
|
|
570
|
+
const checklist = workspace.runtimeSnapshot?.setupChecklist ?? [];
|
|
571
|
+
return ONBOARDING_CRITICAL_STEP_IDS.every((id) => checklist.find((item) => item.id === id)?.status === 'ready');
|
|
572
|
+
}
|
|
573
|
+
|
|
247
574
|
function buildActionRows(workspace: AgentWorkspace, width: number, height: number): WorkspaceRow[] {
|
|
248
575
|
if (workspace.localEditor) return buildEditorRows(workspace.localEditor, width, height);
|
|
249
576
|
const category = workspace.selectedActionCategory;
|
|
250
577
|
const onboarding = isOnboardingCategory(category);
|
|
578
|
+
const settingTable = onboarding
|
|
579
|
+
&& !workspace.actionSearchActive
|
|
580
|
+
&& shouldRenderOnboardingSettingsTable(workspace.actions);
|
|
251
581
|
const rows: WorkspaceRow[] = [];
|
|
252
|
-
const
|
|
582
|
+
const valueWidth = settingTable
|
|
583
|
+
? Math.min(22, Math.max(10, Math.floor(width * 0.18)))
|
|
584
|
+
: 0;
|
|
585
|
+
const labelWidth = settingTable
|
|
586
|
+
? Math.max(18, width - (valueWidth * 2) - 6)
|
|
587
|
+
: Math.min(34, Math.max(18, Math.floor(width * 0.38)));
|
|
253
588
|
const commandWidth = Math.max(10, width - labelWidth - 6);
|
|
254
589
|
if (workspace.actionSearchActive) {
|
|
255
590
|
rows.push({
|
|
@@ -259,32 +594,80 @@ function buildActionRows(workspace: AgentWorkspace, width: number, height: numbe
|
|
|
259
594
|
});
|
|
260
595
|
}
|
|
261
596
|
rows.push({
|
|
262
|
-
text:
|
|
597
|
+
text: settingTable
|
|
598
|
+
? ` ${padDisplay(workspace.actionSearchActive ? 'Result' : 'Setting', labelWidth)} ${padDisplay('Default', valueWidth)} ${padDisplay('Current', valueWidth)}`
|
|
599
|
+
: ` ${padDisplay(workspace.actionSearchActive ? 'Result' : onboarding ? 'Option' : 'Action', labelWidth)} ${padDisplay('Does', commandWidth)}`,
|
|
263
600
|
fg: PALETTE.muted,
|
|
264
601
|
bold: true,
|
|
265
602
|
});
|
|
266
603
|
|
|
267
|
-
|
|
604
|
+
// The finish footer row is appended to workspace.actions by the input layer
|
|
605
|
+
// (shouldShowOnboardingFinishFooter). Detect it here by action id for special styling.
|
|
606
|
+
const allActions = workspace.actions;
|
|
607
|
+
const finishActionIndex = allActions.findIndex((a) => a.id === ONBOARDING_COMPLETE_SYNTHETIC_ACTION.id);
|
|
608
|
+
|
|
268
609
|
const visible = Math.max(1, height - (workspace.actionSearchActive ? 3 : 2));
|
|
269
|
-
const window = stableWindow(
|
|
610
|
+
const window = stableWindow(allActions.length, workspace.selectedActionIndex, visible);
|
|
270
611
|
if (window.start > 0) rows.push({ text: `${GLYPHS.navigation.moreAbove} ${window.start} more action(s) above`, kind: 'more', fg: PALETTE.dim, dim: true });
|
|
271
612
|
|
|
272
613
|
for (let index = window.start; index < window.end; index += 1) {
|
|
273
|
-
const action =
|
|
614
|
+
const action = allActions[index]!;
|
|
615
|
+
const isFinishFooterRow = finishActionIndex >= 0 && index === finishActionIndex;
|
|
274
616
|
const selected = index === workspace.selectedActionIndex;
|
|
275
617
|
const searchResult = workspace.actionSearchActive ? workspace.actionSearchResults[index] : null;
|
|
276
618
|
const actionCategory = searchResult?.category ?? category;
|
|
277
619
|
const label = searchResult ? `${searchResult.category.label} / ${action.label}` : action.label;
|
|
278
620
|
const marker = selected ? GLYPHS.navigation.selected : ' ';
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
621
|
+
|
|
622
|
+
if (isFinishFooterRow) {
|
|
623
|
+
// Sticky Finish setup footer row
|
|
624
|
+
const prereqsMet = onboardingFinishPrerequisitesMet(workspace);
|
|
625
|
+
const sep = `${GLYPHS.frame.horizontal.repeat(3)} Finish setup ${GLYPHS.frame.horizontal.repeat(3)}`;
|
|
626
|
+
if (!selected) {
|
|
627
|
+
rows.push({
|
|
628
|
+
text: ` ${sep}`,
|
|
629
|
+
kind: 'item',
|
|
630
|
+
fg: PALETTE.dim,
|
|
631
|
+
dim: true,
|
|
632
|
+
});
|
|
633
|
+
}
|
|
634
|
+
const finishDetail = prereqsMet
|
|
635
|
+
? 'Finish setup'
|
|
636
|
+
: (() => {
|
|
637
|
+
const checklist = workspace.runtimeSnapshot?.setupChecklist ?? [];
|
|
638
|
+
const unmet = [...ONBOARDING_CRITICAL_STEP_IDS]
|
|
639
|
+
.filter((id) => checklist.find((item) => item.id === id)?.status !== 'ready')
|
|
640
|
+
.map((id) => checklist.find((item) => item.id === id)?.label ?? id)
|
|
641
|
+
.join(', ');
|
|
642
|
+
return `Finish needs: ${unmet}`;
|
|
643
|
+
})();
|
|
644
|
+
const text = settingTable
|
|
645
|
+
? `${marker} ${padDisplay('Finish setup', labelWidth)} ${padDisplay('', valueWidth)} ${padDisplay('', valueWidth)}`
|
|
646
|
+
: `${marker} ${padDisplay('Finish setup', labelWidth)} ${padDisplay(finishDetail, commandWidth)}`;
|
|
647
|
+
rows.push({
|
|
648
|
+
text,
|
|
649
|
+
selected: selected && workspace.focusPane === 'actions',
|
|
650
|
+
fg: prereqsMet ? PALETTE.good : PALETTE.warn,
|
|
651
|
+
bold: selected,
|
|
652
|
+
kind: 'item',
|
|
653
|
+
});
|
|
654
|
+
} else {
|
|
655
|
+
const text = settingTable
|
|
656
|
+
? (() => {
|
|
657
|
+
const columns = onboardingActionColumns(workspace, action);
|
|
658
|
+
return `${marker} ${padDisplay(columns.setting, labelWidth)} ${padDisplay(columns.defaultValue, valueWidth)} ${padDisplay(columns.currentValue, valueWidth)}`;
|
|
659
|
+
})()
|
|
660
|
+
: `${marker} ${padDisplay(label, labelWidth)} ${padDisplay(actionChange(workspace, actionCategory, action), commandWidth)}`;
|
|
661
|
+
rows.push({
|
|
662
|
+
text,
|
|
663
|
+
selected: selected && workspace.focusPane === 'actions',
|
|
664
|
+
fg: action.safety === 'blocked' ? PALETTE.warn : selected ? PALETTE.text : PALETTE.info,
|
|
665
|
+
bold: selected,
|
|
666
|
+
});
|
|
667
|
+
}
|
|
285
668
|
}
|
|
286
669
|
|
|
287
|
-
if (window.end <
|
|
670
|
+
if (window.end < allActions.length) rows.push({ text: `${GLYPHS.navigation.moreBelow} ${allActions.length - window.end} more action(s) below`, kind: 'more', fg: PALETTE.dim, dim: true });
|
|
288
671
|
rows.push({ text: '' });
|
|
289
672
|
rows.push({ text: `Status: ${workspace.status}`, fg: PALETTE.muted });
|
|
290
673
|
if (workspace.lastActionResult) {
|
|
@@ -22,7 +22,6 @@ const FEATURED_HELP_COMMANDS: Array<[name: string, argHint: string, desc: string
|
|
|
22
22
|
['personas', '', 'Manage serial Agent operating personas'],
|
|
23
23
|
['skills', '', 'Manage Agent-local skills and bundles'],
|
|
24
24
|
['routines', '', 'Manage reusable main-conversation routines'],
|
|
25
|
-
['workplan', '', 'Inspect shared work-plan state'],
|
|
26
25
|
['approval', '', 'Review and explicitly act on approvals'],
|
|
27
26
|
['automation', '', 'Run confirmed connected-host automation actions'],
|
|
28
27
|
['schedule', 'remind', 'Create confirmed reminders or inspect schedules'],
|
|
@@ -202,7 +201,6 @@ export function renderHelpOverlay(
|
|
|
202
201
|
'personas',
|
|
203
202
|
'skills',
|
|
204
203
|
'routines',
|
|
205
|
-
'workplan',
|
|
206
204
|
'approval',
|
|
207
205
|
'schedule',
|
|
208
206
|
'delegate',
|