@pellux/goodvibes-agent 1.2.0 → 1.4.1
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 +194 -0
- 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 +65740 -57156
- package/docs/README.md +3 -3
- package/docs/connected-host.md +2 -2
- package/docs/getting-started.md +11 -9
- package/docs/tools-and-commands.md +12 -10
- package/docs/voice-and-live-tts.md +2 -2
- package/package.json +1 -1
- package/release/release-notes.md +15 -144
- package/release/release-readiness.json +36 -36
- package/src/agent/competitive-feature-inventory.ts +42 -44
- package/src/agent/setup-wizard-artifact-receipts.ts +366 -0
- package/src/agent/setup-wizard.ts +267 -24
- package/src/cli/tui-startup.ts +2 -2
- package/src/input/agent-workspace-activation.ts +2 -2
- package/src/input/agent-workspace-categories.ts +2 -2
- package/src/input/agent-workspace-onboarding-categories.ts +4 -4
- package/src/input/agent-workspace-onboarding-finish.ts +21 -0
- package/src/input/agent-workspace-settings.ts +47 -1
- package/src/input/agent-workspace-setup-snapshot.ts +17 -6
- package/src/input/agent-workspace-setup.ts +20 -26
- package/src/input/agent-workspace-snapshot.ts +16 -3
- package/src/input/agent-workspace-types.ts +5 -2
- package/src/input/agent-workspace.ts +21 -6
- package/src/input/handler.ts +67 -5
- package/src/input/setup-wizard-live-receipts.ts +76 -0
- package/src/renderer/agent-workspace-context-lines.ts +17 -33
- package/src/renderer/agent-workspace.ts +434 -21
- package/src/runtime/tool-permission-safety.ts +1 -1
- package/src/tools/agent-harness-agent-orchestration-policy.ts +75 -0
- package/src/tools/agent-harness-agent-orchestration.ts +216 -128
- package/src/tools/agent-harness-autonomy-live-records.ts +154 -0
- package/src/tools/agent-harness-autonomy-queue-types.ts +1 -1
- package/src/tools/agent-harness-autonomy-queue.ts +19 -8
- package/src/tools/agent-harness-autonomy-watcher-read-models.ts +509 -0
- package/src/tools/agent-harness-background-processes.ts +8 -4
- package/src/tools/agent-harness-browser-cockpit-route.ts +188 -34
- package/src/tools/agent-harness-browser-control.ts +12 -4
- package/src/tools/agent-harness-browser-pwa-read-models.ts +622 -0
- package/src/tools/agent-harness-device-live-read-models.ts +366 -0
- package/src/tools/agent-harness-execution-posture.ts +3 -0
- package/src/tools/agent-harness-interactive-runtime-records.ts +421 -0
- package/src/tools/agent-harness-local-model-benchmarks.ts +71 -1
- package/src/tools/agent-harness-local-model-endpoints.ts +469 -354
- package/src/tools/agent-harness-local-model-smoke.ts +277 -0
- package/src/tools/agent-harness-local-model-url.ts +78 -0
- package/src/tools/agent-harness-media-posture.ts +27 -12
- package/src/tools/agent-harness-memory-external-providers.ts +796 -0
- package/src/tools/agent-harness-memory-posture.ts +253 -137
- package/src/tools/agent-harness-memory-provider-certification.ts +219 -0
- package/src/tools/agent-harness-memory-refinement.ts +340 -0
- package/src/tools/agent-harness-mode-catalog.ts +4 -2
- package/src/tools/agent-harness-model-provider-health.ts +139 -42
- package/src/tools/agent-harness-model-readiness.ts +31 -5
- package/src/tools/agent-harness-model-routing-types.ts +61 -0
- package/src/tools/agent-harness-model-routing.ts +31 -6
- package/src/tools/agent-harness-pairing-posture.ts +30 -9
- package/src/tools/agent-harness-personal-ops-certification.ts +116 -0
- package/src/tools/agent-harness-personal-ops-lanes.ts +81 -15
- package/src/tools/agent-harness-personal-ops-operations.ts +225 -0
- package/src/tools/agent-harness-personal-ops-provider-records.ts +358 -0
- package/src/tools/agent-harness-personal-ops-provider-task-records.ts +321 -0
- package/src/tools/agent-harness-personal-ops-records.ts +176 -224
- package/src/tools/agent-harness-personal-ops-types.ts +19 -1
- package/src/tools/agent-harness-personal-ops.ts +18 -11
- package/src/tools/agent-harness-remote-read-models.ts +541 -0
- package/src/tools/agent-harness-research-briefing.ts +26 -7
- package/src/tools/agent-harness-research-live-read-models.ts +500 -0
- package/src/tools/agent-harness-research-runs.ts +15 -3
- package/src/tools/agent-harness-research-workflow.ts +92 -19
- package/src/tools/agent-harness-setup-model-helpers.ts +1 -0
- package/src/tools/agent-harness-setup-posture.ts +7 -7
- package/src/tools/agent-harness-setup-smoke.ts +26 -1
- package/src/tools/agent-harness-tool-schema.ts +23 -1
- package/src/tools/agent-harness-tool-types.ts +5 -0
- package/src/tools/agent-harness-tool.ts +9 -1
- package/src/tools/agent-harness-workspace-actions.ts +1 -1
- package/src/tools/agent-memory-tool.ts +40 -1
- package/src/tools/agent-model-compare-run.ts +13 -0
- package/src/tools/agent-research-runner.ts +367 -0
- package/src/tools/agent-research-tool.ts +7 -179
- package/src/tools/agent-route-planner-candidates-surfaces.ts +1 -1
- package/src/version.ts +1 -1
|
@@ -7,7 +7,7 @@ export interface AgentWorkspaceSetupChecklistItem {
|
|
|
7
7
|
readonly label: string;
|
|
8
8
|
readonly status: AgentWorkspaceSetupStatus;
|
|
9
9
|
readonly detail: string;
|
|
10
|
-
readonly
|
|
10
|
+
readonly breadcrumb?: string;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export interface AgentWorkspaceSetupChecklistInput {
|
|
@@ -18,6 +18,7 @@ export interface AgentWorkspaceSetupChecklistInput {
|
|
|
18
18
|
readonly connectedHostTokenReadable: boolean;
|
|
19
19
|
readonly connectedHostTokenPath: string;
|
|
20
20
|
readonly connectedHostTokenError?: string | null;
|
|
21
|
+
readonly connectedHostAuthReceiptReady?: boolean;
|
|
21
22
|
readonly activeSubscriptionCount: number;
|
|
22
23
|
readonly pendingSubscriptionCount: number;
|
|
23
24
|
readonly availableSubscriptionProviderCount: number;
|
|
@@ -58,12 +59,12 @@ function sampleNames(summary: AgentBehaviorDiscoverySummary): string {
|
|
|
58
59
|
export function buildAgentWorkspaceSetupChecklist(input: AgentWorkspaceSetupChecklistInput): readonly AgentWorkspaceSetupChecklistItem[] {
|
|
59
60
|
const providerReady = input.provider !== 'unknown' && input.model !== 'unknown';
|
|
60
61
|
const tokenPathKnown = input.connectedHostTokenPath !== '(Agent home unavailable)';
|
|
61
|
-
const
|
|
62
|
+
const connectedHostAuthReceiptReady = input.connectedHostAuthReceiptReady === true;
|
|
63
|
+
const connectedHostAuthStatus: AgentWorkspaceSetupStatus = input.connectedHostTokenReadable || connectedHostAuthReceiptReady
|
|
62
64
|
? 'ready'
|
|
63
65
|
: tokenPathKnown
|
|
64
66
|
? 'blocked'
|
|
65
67
|
: 'recommended';
|
|
66
|
-
const installSmokeReady = providerReady && input.connectedHostTokenReadable;
|
|
67
68
|
const hasActivePersona = input.activePersonaName !== '(none)' && input.activePersonaName !== '(unavailable)';
|
|
68
69
|
const discoveredBehaviorCount = input.discoveredPersonas.count + input.discoveredSkills.count + input.discoveredRoutines.count;
|
|
69
70
|
return [
|
|
@@ -72,20 +73,22 @@ export function buildAgentWorkspaceSetupChecklist(input: AgentWorkspaceSetupChec
|
|
|
72
73
|
label: 'Connected host',
|
|
73
74
|
status: 'ready',
|
|
74
75
|
detail: `Agent will connect to ${input.runtimeBaseUrl}; protected host routes also need the Agent companion token below.`,
|
|
75
|
-
|
|
76
|
+
breadcrumb: 'Home -> Review health',
|
|
76
77
|
},
|
|
77
78
|
{
|
|
78
79
|
id: 'connected-host-auth',
|
|
79
80
|
label: 'Connected-host auth',
|
|
80
81
|
status: connectedHostAuthStatus,
|
|
81
|
-
detail:
|
|
82
|
+
detail: connectedHostAuthReceiptReady
|
|
83
|
+
? `Durable connected-host auth receipt is ready${input.connectedHostTokenReadable ? ` and Agent has a readable operator token at ${input.connectedHostTokenPath}` : ''}.`
|
|
84
|
+
: input.connectedHostTokenReadable
|
|
82
85
|
? `Agent has a readable connected-host operator token at ${input.connectedHostTokenPath}.`
|
|
83
86
|
: input.connectedHostTokenError
|
|
84
87
|
? `The connected-host operator token exists but cannot be read at ${input.connectedHostTokenPath}. Use the confirmed setup token provisioning route, then rerun auth review.`
|
|
85
88
|
: tokenPathKnown
|
|
86
89
|
? `Provision Agent's local connected-host operator token at ${input.connectedHostTokenPath} before pairing channels, Knowledge, schedules, or protected daemon routes.`
|
|
87
90
|
: 'Shell paths are unavailable in this runtime, so connected-host auth cannot be verified from the workspace snapshot.',
|
|
88
|
-
|
|
91
|
+
breadcrumb: 'Host -> Connected-host auth owner',
|
|
89
92
|
},
|
|
90
93
|
{
|
|
91
94
|
id: 'provider-model',
|
|
@@ -94,16 +97,7 @@ export function buildAgentWorkspaceSetupChecklist(input: AgentWorkspaceSetupChec
|
|
|
94
97
|
detail: providerReady
|
|
95
98
|
? `Current chat route is ${input.provider} / ${input.model}.`
|
|
96
99
|
: 'Choose a provider and model before relying on assistant turns.',
|
|
97
|
-
|
|
98
|
-
},
|
|
99
|
-
{
|
|
100
|
-
id: 'install-smoke',
|
|
101
|
-
label: 'Install smoke',
|
|
102
|
-
status: installSmokeReady ? 'recommended' : tokenPathKnown ? 'blocked' : 'recommended',
|
|
103
|
-
detail: installSmokeReady
|
|
104
|
-
? 'Run setup smoke after install or migration to prove package start, connected host, auth, model route, setup posture, and first assistant turn.'
|
|
105
|
-
: 'Resolve connected-host auth and provider/model setup before treating the first assistant turn as install-ready.',
|
|
106
|
-
command: 'Start -> Install smoke',
|
|
100
|
+
breadcrumb: 'Setup -> Provider and model',
|
|
107
101
|
},
|
|
108
102
|
{
|
|
109
103
|
id: 'subscriptions',
|
|
@@ -120,14 +114,14 @@ export function buildAgentWorkspaceSetupChecklist(input: AgentWorkspaceSetupChec
|
|
|
120
114
|
: input.availableSubscriptionProviderCount > 0
|
|
121
115
|
? `${input.availableSubscriptionProviderCount} subscription-capable provider(s) are available. Start login if you want subscription routing.`
|
|
122
116
|
: 'No subscription-capable providers are available yet. Use API keys or add an OAuth provider service.',
|
|
123
|
-
|
|
117
|
+
breadcrumb: 'Start -> Start subscription login',
|
|
124
118
|
},
|
|
125
119
|
{
|
|
126
120
|
id: 'agent-knowledge',
|
|
127
121
|
label: 'Agent Knowledge',
|
|
128
122
|
status: 'recommended',
|
|
129
123
|
detail: 'Check isolated Agent Knowledge status, then ingest source-backed material into the Agent segment only.',
|
|
130
|
-
|
|
124
|
+
breadcrumb: 'Knowledge',
|
|
131
125
|
},
|
|
132
126
|
{
|
|
133
127
|
id: 'profile',
|
|
@@ -138,7 +132,7 @@ export function buildAgentWorkspaceSetupChecklist(input: AgentWorkspaceSetupChec
|
|
|
138
132
|
: discoveredBehaviorCount > 0
|
|
139
133
|
? `${discoveredBehaviorCount} discovered behavior file(s) can seed an isolated Agent profile from the Profiles workspace.`
|
|
140
134
|
: `${input.runtimeStarterTemplateCount} starter template(s) are available if this machine needs separate operator identities.`,
|
|
141
|
-
|
|
135
|
+
breadcrumb: 'Profiles',
|
|
142
136
|
},
|
|
143
137
|
{
|
|
144
138
|
id: 'persona',
|
|
@@ -149,7 +143,7 @@ export function buildAgentWorkspaceSetupChecklist(input: AgentWorkspaceSetupChec
|
|
|
149
143
|
: input.discoveredPersonas.count > 0
|
|
150
144
|
? `${input.discoveredPersonas.count} discovered persona file(s) can be imported into the Agent-local registry.${sampleNames(input.discoveredPersonas)}`
|
|
151
145
|
: 'Create or choose a persona to make the assistant voice and policy explicit.',
|
|
152
|
-
|
|
146
|
+
breadcrumb: 'Personas',
|
|
153
147
|
},
|
|
154
148
|
{
|
|
155
149
|
id: 'skills',
|
|
@@ -166,7 +160,7 @@ export function buildAgentWorkspaceSetupChecklist(input: AgentWorkspaceSetupChec
|
|
|
166
160
|
: input.discoveredSkills.count > 0
|
|
167
161
|
? `${input.discoveredSkills.count} discovered skill file(s) can be imported as local reusable procedures.${sampleNames(input.discoveredSkills)}`
|
|
168
162
|
: 'Create reusable local skills and bundles for repeated workflows.',
|
|
169
|
-
|
|
163
|
+
breadcrumb: 'Skills',
|
|
170
164
|
},
|
|
171
165
|
{
|
|
172
166
|
id: 'routines',
|
|
@@ -179,7 +173,7 @@ export function buildAgentWorkspaceSetupChecklist(input: AgentWorkspaceSetupChec
|
|
|
179
173
|
: input.discoveredRoutines.count > 0
|
|
180
174
|
? `${input.discoveredRoutines.count} discovered routine file(s) can be imported as main-conversation workflows.${sampleNames(input.discoveredRoutines)}`
|
|
181
175
|
: 'Create local routines first; promote schedules only with explicit confirmation.',
|
|
182
|
-
|
|
176
|
+
breadcrumb: 'Routines',
|
|
183
177
|
},
|
|
184
178
|
{
|
|
185
179
|
id: 'memory',
|
|
@@ -188,7 +182,7 @@ export function buildAgentWorkspaceSetupChecklist(input: AgentWorkspaceSetupChec
|
|
|
188
182
|
detail: input.localMemoryCount > 0
|
|
189
183
|
? `${input.localMemoryCount} Agent memory record(s) are available; ${input.localMemoryReviewQueueCount} need review.`
|
|
190
184
|
: 'Memory starts empty; durable facts should be stored deliberately and never include secrets.',
|
|
191
|
-
|
|
185
|
+
breadcrumb: 'Memory',
|
|
192
186
|
},
|
|
193
187
|
{
|
|
194
188
|
id: 'notes',
|
|
@@ -197,7 +191,7 @@ export function buildAgentWorkspaceSetupChecklist(input: AgentWorkspaceSetupChec
|
|
|
197
191
|
detail: input.localNoteCount > 0
|
|
198
192
|
? `${input.localNoteCount} Agent scratchpad note(s) are available; ${input.localNoteReviewQueueCount} need review.`
|
|
199
193
|
: 'Notes start empty; use them for source triage, temporary decisions, and handoff before promoting anything durable.',
|
|
200
|
-
|
|
194
|
+
breadcrumb: 'Notes',
|
|
201
195
|
},
|
|
202
196
|
{
|
|
203
197
|
id: 'channels',
|
|
@@ -206,14 +200,14 @@ export function buildAgentWorkspaceSetupChecklist(input: AgentWorkspaceSetupChec
|
|
|
206
200
|
detail: input.readyChannelCount > 0
|
|
207
201
|
? `${input.readyChannelCount} external channel(s) are ready.`
|
|
208
202
|
: 'Pair or review channels only when you want the assistant reachable outside this terminal.',
|
|
209
|
-
|
|
203
|
+
breadcrumb: 'Channels',
|
|
210
204
|
},
|
|
211
205
|
{
|
|
212
206
|
id: 'voice-media',
|
|
213
207
|
label: 'Voice and media',
|
|
214
208
|
status: input.voiceProviderCount > 0 || input.mediaProviderCount > 0 ? 'ready' : 'optional',
|
|
215
209
|
detail: `${input.voiceProviderCount} voice provider(s), ${input.mediaProviderCount} media provider(s). Configure these only when useful.`,
|
|
216
|
-
|
|
210
|
+
breadcrumb: 'Voice & Media',
|
|
217
211
|
},
|
|
218
212
|
];
|
|
219
213
|
}
|
|
@@ -24,6 +24,8 @@ import type { PromptContextReceipt } from '../agent/prompt-context-receipts.ts';
|
|
|
24
24
|
import { discoverProjectContextFiles } from '../agent/project-context-files.ts';
|
|
25
25
|
import { getAgentRuntimeProfilesRoot, listAgentRuntimeProfiles, listAgentRuntimeProfileTemplates, readAgentRuntimeProfileSelection } from '../agent/runtime-profile.ts';
|
|
26
26
|
import { RoutineScheduleReceiptStore } from '../agent/routine-schedule-receipts.ts';
|
|
27
|
+
import { buildSetupWizardDurableReceipts } from '../agent/setup-wizard-artifact-receipts.ts';
|
|
28
|
+
import { mergeSetupWizardDurableReceipts, setupWizardLiveDurableReceipts } from './setup-wizard-live-receipts.ts';
|
|
27
29
|
import { readSetupWizardCheckpoint } from '../agent/setup-wizard-checkpoint.ts';
|
|
28
30
|
import { discoverVibeFiles } from '../agent/vibe-file.ts';
|
|
29
31
|
import {
|
|
@@ -35,6 +37,7 @@ import {
|
|
|
35
37
|
buildAgentSetupWizard,
|
|
36
38
|
emptyAgentSetupSmokeHistory,
|
|
37
39
|
emptyAgentSetupWizardCheckpoint,
|
|
40
|
+
setupStepHasSatisfyingReceipt,
|
|
38
41
|
type AgentSetupWizard,
|
|
39
42
|
type AgentSetupWizardBlockedCheckFrequency,
|
|
40
43
|
type AgentSetupWizardCheckpoint,
|
|
@@ -266,6 +269,11 @@ export function buildAgentWorkspaceRuntimeSnapshot(context: CommandContext): Age
|
|
|
266
269
|
return { available: false, items: [] };
|
|
267
270
|
}
|
|
268
271
|
})();
|
|
272
|
+
const setupSmokeHistory = buildSetupSmokeHistory(artifactListSnapshot.items, artifactListSnapshot.available);
|
|
273
|
+
const durableSetupReceipts = mergeSetupWizardDurableReceipts(
|
|
274
|
+
buildSetupWizardDurableReceipts(artifactListSnapshot.items),
|
|
275
|
+
setupWizardLiveDurableReceipts(context),
|
|
276
|
+
);
|
|
269
277
|
const recentReviewerHandoffs = (() => {
|
|
270
278
|
try {
|
|
271
279
|
const handoffs = artifactListSnapshot.items
|
|
@@ -452,6 +460,9 @@ export function buildAgentWorkspaceRuntimeSnapshot(context: CommandContext): Age
|
|
|
452
460
|
voiceProviders: voiceProviderDescriptors,
|
|
453
461
|
mediaProviders: mediaProviderDescriptors,
|
|
454
462
|
});
|
|
463
|
+
const browserPwaEnabled = readConfigBoolean(context, 'web.enabled', false);
|
|
464
|
+
const browserPwaPublicBaseUrl = readConfigString(context, 'web.publicBaseUrl', '(not configured)');
|
|
465
|
+
const connectedHostAuthReceiptReady = setupStepHasSatisfyingReceipt(durableSetupReceipts, 'connected-host-auth');
|
|
455
466
|
const setupChecklist = buildAgentWorkspaceSetupChecklist({
|
|
456
467
|
provider,
|
|
457
468
|
model,
|
|
@@ -460,6 +471,7 @@ export function buildAgentWorkspaceRuntimeSnapshot(context: CommandContext): Age
|
|
|
460
471
|
connectedHostTokenReadable: companionAccess.tokenReadable,
|
|
461
472
|
connectedHostTokenPath: companionAccess.tokenPath,
|
|
462
473
|
connectedHostTokenError: companionAccess.tokenError,
|
|
474
|
+
connectedHostAuthReceiptReady,
|
|
463
475
|
activeSubscriptionCount: subscriptionSnapshot.active,
|
|
464
476
|
pendingSubscriptionCount: subscriptionSnapshot.pending,
|
|
465
477
|
availableSubscriptionProviderCount: subscriptionSnapshot.available,
|
|
@@ -488,9 +500,10 @@ export function buildAgentWorkspaceRuntimeSnapshot(context: CommandContext): Age
|
|
|
488
500
|
});
|
|
489
501
|
const setupWizard = buildWorkspaceSetupWizard(
|
|
490
502
|
setupChecklist,
|
|
491
|
-
|
|
503
|
+
setupSmokeHistory,
|
|
492
504
|
buildSetupWizardCheckpoint(context),
|
|
493
505
|
setupCompletionMarkerExists(context),
|
|
506
|
+
durableSetupReceipts,
|
|
494
507
|
);
|
|
495
508
|
const researchBrowserRunnerContract = buildResearchBrowserRunnerContract(context);
|
|
496
509
|
const researchVisualReportContract = buildResearchVisualReportContract(researchSourceSnapshot);
|
|
@@ -619,8 +632,8 @@ export function buildAgentWorkspaceRuntimeSnapshot(context: CommandContext): Age
|
|
|
619
632
|
mcpConnectedServerCount: mcpSnapshot.connectedCount,
|
|
620
633
|
mcpQuarantinedServerCount: mcpSnapshot.quarantinedCount,
|
|
621
634
|
mcpAllowAllServerCount: mcpSnapshot.allowAllCount,
|
|
622
|
-
browserToolExposureEnabled:
|
|
623
|
-
browserToolPublicBaseUrl:
|
|
635
|
+
browserToolExposureEnabled: browserPwaEnabled,
|
|
636
|
+
browserToolPublicBaseUrl: browserPwaPublicBaseUrl,
|
|
624
637
|
activeRuntimeProfile: inferActiveRuntimeProfile(context.workspace?.shellPaths?.homeDirectory ?? ''),
|
|
625
638
|
selectedRuntimeProfile: selectedRuntimeProfile?.id ?? null,
|
|
626
639
|
selectedRuntimeProfileExists: selectedRuntimeProfile?.exists ?? false,
|
|
@@ -7,6 +7,8 @@ import type { AgentSetupWizard } from '../agent/setup-wizard.ts';
|
|
|
7
7
|
|
|
8
8
|
export const AGENT_WORKSPACE_MODAL_NAME = 'agentWorkspace';
|
|
9
9
|
|
|
10
|
+
export type AgentWorkspaceCategoryGroup = 'START' | 'ONBOARDING' | 'DAY-TO-DAY' | 'CAPABILITIES' | 'LOCAL BEHAVIOR' | 'OPERATIONS' | 'FINISH';
|
|
11
|
+
|
|
10
12
|
export type AgentWorkspaceFocusPane = 'categories' | 'actions';
|
|
11
13
|
|
|
12
14
|
export const AGENT_WORKSPACE_CATEGORY_IDS = [
|
|
@@ -310,11 +312,12 @@ export interface AgentWorkspaceAction {
|
|
|
310
312
|
readonly localOperation?: AgentWorkspaceLocalOperation;
|
|
311
313
|
readonly kind: AgentWorkspaceActionKind;
|
|
312
314
|
readonly safety: 'safe' | 'read-only' | 'delegates' | 'blocked';
|
|
315
|
+
readonly commandBehavior?: 'inline' | 'compose' | 'exit';
|
|
313
316
|
}
|
|
314
317
|
|
|
315
318
|
export interface AgentWorkspaceCategory {
|
|
316
319
|
readonly id: AgentWorkspaceCategoryId;
|
|
317
|
-
readonly group:
|
|
320
|
+
readonly group: AgentWorkspaceCategoryGroup;
|
|
318
321
|
readonly label: string;
|
|
319
322
|
readonly summary: string;
|
|
320
323
|
readonly detail: string;
|
|
@@ -328,7 +331,7 @@ export interface AgentWorkspaceActionSearchResult {
|
|
|
328
331
|
readonly actionIndex: number;
|
|
329
332
|
}
|
|
330
333
|
|
|
331
|
-
export type AgentWorkspaceCommandDispatcher = (command: string) => void;
|
|
334
|
+
export type AgentWorkspaceCommandDispatcher = (command: string, behavior?: 'inline' | 'compose' | 'exit') => void;
|
|
332
335
|
export type AgentWorkspacePromptDispatcher = (prompt: string) => void;
|
|
333
336
|
|
|
334
337
|
export type AgentWorkspaceActionResultKind = 'guidance' | 'blocked' | 'dispatched' | 'refreshed' | 'error';
|
|
@@ -19,10 +19,11 @@ import { deleteAgentWorkspaceMemoryEditor, submitAgentWorkspaceMemoryEditor } fr
|
|
|
19
19
|
import { jumpAgentWorkspaceSelection, moveAgentWorkspaceSelection, selectAgentWorkspaceCategory } from './agent-workspace-navigation.ts';
|
|
20
20
|
import { appendAgentWorkspaceActionSearchText, backspaceAgentWorkspaceActionSearch, beginAgentWorkspaceActionSearch, clearAgentWorkspaceActionSearch, commitAgentWorkspaceActionSearchSelection, searchAgentWorkspaceActions } from './agent-workspace-search.ts';
|
|
21
21
|
import { applyAgentWorkspaceSetupCheckpointAction } from './agent-workspace-setup-checkpoint-action.ts';
|
|
22
|
-
import { agentWorkspaceSettingSchema, applyAgentWorkspaceSettingValue, buildAgentWorkspaceSettingActionEffect, importAgentWorkspaceTuiSettings, isAgentWorkspaceActionVisible } from './agent-workspace-settings.ts';
|
|
22
|
+
import { agentWorkspaceSettingSchema, applyAgentWorkspaceSettingValue, buildAgentWorkspaceSettingActionDisplay, buildAgentWorkspaceSettingActionEffect, importAgentWorkspaceTuiSettings, isAgentWorkspaceActionVisible, type AgentWorkspaceSettingActionDisplay } from './agent-workspace-settings.ts';
|
|
23
23
|
import { buildAgentWorkspaceRuntimeSnapshot } from './agent-workspace-snapshot.ts';
|
|
24
24
|
import { submitAgentWorkspaceSubscriptionLoginFinishEditor, submitAgentWorkspaceSubscriptionLoginStartEditor, submitAgentWorkspaceSubscriptionLogoutEditor } from './agent-workspace-subscription-editor.ts';
|
|
25
|
-
import type { AgentWorkspaceAction, AgentWorkspaceActionResult, AgentWorkspaceActionSearchResult, AgentWorkspaceCategory, AgentWorkspaceCommandDispatcher, AgentWorkspaceEditorField, AgentWorkspaceFocusPane, AgentWorkspaceLocalEditor, AgentWorkspaceLocalEditorKind, AgentWorkspaceLocalLibraryItem, AgentWorkspaceLocalOperation, AgentWorkspacePromptDispatcher, AgentWorkspaceRuntimeSnapshot } from './agent-workspace-types.ts';
|
|
25
|
+
import type { AgentWorkspaceAction, AgentWorkspaceActionResult, AgentWorkspaceActionSearchResult, AgentWorkspaceCategory, AgentWorkspaceCategoryGroup, AgentWorkspaceCommandDispatcher, AgentWorkspaceEditorField, AgentWorkspaceFocusPane, AgentWorkspaceLocalEditor, AgentWorkspaceLocalEditorKind, AgentWorkspaceLocalLibraryItem, AgentWorkspaceLocalOperation, AgentWorkspacePromptDispatcher, AgentWorkspaceRuntimeSnapshot } from './agent-workspace-types.ts';
|
|
26
|
+
import { ONBOARDING_COMPLETE_SYNTHETIC_ACTION, shouldShowOnboardingFinishFooter } from './agent-workspace-onboarding-finish.ts';
|
|
26
27
|
import { writeOnboardingCheckMarker, writeOnboardingCompletionMarker } from '../runtime/onboarding/index.ts';
|
|
27
28
|
|
|
28
29
|
export type { AgentWorkspaceChannelRisk, AgentWorkspaceChannelStatus } from './agent-workspace-channels.ts';
|
|
@@ -46,11 +47,13 @@ export class AgentWorkspace {
|
|
|
46
47
|
private context: CommandContext | null = null;
|
|
47
48
|
private dispatchCommand: AgentWorkspaceCommandDispatcher | null = null;
|
|
48
49
|
private dispatchPrompt: AgentWorkspacePromptDispatcher | null = null;
|
|
50
|
+
private _onlyGroup: AgentWorkspaceCategoryGroup | null = null;
|
|
49
51
|
|
|
50
|
-
open(context: CommandContext, dispatchCommand: AgentWorkspaceCommandDispatcher, categoryId?: string, dispatchPrompt?: AgentWorkspacePromptDispatcher): void {
|
|
52
|
+
open(context: CommandContext, dispatchCommand: AgentWorkspaceCommandDispatcher, categoryId?: string, dispatchPrompt?: AgentWorkspacePromptDispatcher, onlyGroup?: AgentWorkspaceCategoryGroup): void {
|
|
51
53
|
this.context = context;
|
|
52
54
|
this.dispatchCommand = dispatchCommand;
|
|
53
55
|
this.dispatchPrompt = dispatchPrompt ?? null;
|
|
56
|
+
this._onlyGroup = onlyGroup ?? null;
|
|
54
57
|
this.runtimeSnapshot = buildAgentWorkspaceRuntimeSnapshot(context);
|
|
55
58
|
this.active = true;
|
|
56
59
|
this.focusPane = 'actions';
|
|
@@ -85,9 +88,13 @@ export class AgentWorkspace {
|
|
|
85
88
|
this.localEditor = null;
|
|
86
89
|
this.actionSearchActive = false;
|
|
87
90
|
this.actionSearchQuery = '';
|
|
91
|
+
this._onlyGroup = null;
|
|
88
92
|
}
|
|
89
93
|
|
|
90
94
|
get categories(): readonly AgentWorkspaceCategory[] {
|
|
95
|
+
if (this._onlyGroup) {
|
|
96
|
+
return AGENT_WORKSPACE_CATEGORIES.filter((category) => category.group === this._onlyGroup);
|
|
97
|
+
}
|
|
91
98
|
return AGENT_WORKSPACE_CATEGORIES;
|
|
92
99
|
}
|
|
93
100
|
|
|
@@ -97,7 +104,11 @@ export class AgentWorkspace {
|
|
|
97
104
|
|
|
98
105
|
get actions(): readonly AgentWorkspaceAction[] {
|
|
99
106
|
if (this.actionSearchActive) return this.actionSearchResults.map((result) => result.action);
|
|
100
|
-
|
|
107
|
+
const base = this.selectedCategory.actions.filter((action) => isAgentWorkspaceActionVisible(this.context, action));
|
|
108
|
+
if (shouldShowOnboardingFinishFooter(this.selectedCategory, base)) {
|
|
109
|
+
return [...base, ONBOARDING_COMPLETE_SYNTHETIC_ACTION];
|
|
110
|
+
}
|
|
111
|
+
return base;
|
|
101
112
|
}
|
|
102
113
|
|
|
103
114
|
get selectedAction(): AgentWorkspaceAction | null {
|
|
@@ -142,6 +153,10 @@ export class AgentWorkspace {
|
|
|
142
153
|
return selectedAgentWorkspaceLocalLibraryItem(this.runtimeSnapshot, this.selectedLibraryItemIndexes, kind);
|
|
143
154
|
}
|
|
144
155
|
|
|
156
|
+
settingActionDisplay(action: AgentWorkspaceAction): AgentWorkspaceSettingActionDisplay | null {
|
|
157
|
+
return buildAgentWorkspaceSettingActionDisplay(this.context, action);
|
|
158
|
+
}
|
|
159
|
+
|
|
145
160
|
focusCategories(): void {
|
|
146
161
|
this.focusPane = 'categories';
|
|
147
162
|
}
|
|
@@ -275,8 +290,8 @@ export class AgentWorkspace {
|
|
|
275
290
|
return Boolean(this.context?.submitInput && this.dispatchPrompt);
|
|
276
291
|
}
|
|
277
292
|
|
|
278
|
-
dispatchWorkspaceCommand(command: string): void {
|
|
279
|
-
this.dispatchCommand?.(command);
|
|
293
|
+
dispatchWorkspaceCommand(command: string, behavior?: 'inline' | 'compose' | 'exit'): void {
|
|
294
|
+
this.dispatchCommand?.(command, behavior);
|
|
280
295
|
}
|
|
281
296
|
|
|
282
297
|
dispatchWorkspacePrompt(prompt: string): void {
|
package/src/input/handler.ts
CHANGED
|
@@ -366,15 +366,16 @@ export class InputHandler {
|
|
|
366
366
|
this.mcpWorkspace.open(context);
|
|
367
367
|
this.requestRender();
|
|
368
368
|
}
|
|
369
|
-
public openAgentWorkspace(context: CommandContext, categoryId?: string): void {
|
|
369
|
+
public openAgentWorkspace(context: CommandContext, categoryId?: string, onlyGroup?: string): void {
|
|
370
370
|
this.panelFocused = false;
|
|
371
371
|
this.indicatorFocused = false;
|
|
372
372
|
this.modalOpened('agentWorkspace');
|
|
373
373
|
this.agentWorkspace.open(
|
|
374
374
|
context,
|
|
375
|
-
(command) => this.dispatchAgentWorkspaceCommand(command, context),
|
|
375
|
+
(command, behavior) => this.dispatchAgentWorkspaceCommand(command, context, behavior),
|
|
376
376
|
categoryId,
|
|
377
377
|
(prompt) => this.dispatchAgentWorkspacePrompt(prompt, context),
|
|
378
|
+
onlyGroup as import('./agent-workspace-types.ts').AgentWorkspaceCategoryGroup | undefined,
|
|
378
379
|
);
|
|
379
380
|
this.requestRender();
|
|
380
381
|
}
|
|
@@ -395,10 +396,71 @@ export class InputHandler {
|
|
|
395
396
|
return true;
|
|
396
397
|
}
|
|
397
398
|
|
|
398
|
-
|
|
399
|
-
|
|
399
|
+
public dispatchAgentWorkspaceCommand(command: string, context: CommandContext, behavior?: 'inline' | 'compose' | 'exit'): void {
|
|
400
|
+
const resolved = behavior ?? 'compose';
|
|
400
401
|
const { name, args } = parseSlashCommand(command);
|
|
401
402
|
if (!name) return;
|
|
403
|
+
if (resolved === 'exit') {
|
|
404
|
+
this.closeAgentWorkspaceModal();
|
|
405
|
+
void context.executeCommand?.(name, [...args]).catch((error: unknown) => {
|
|
406
|
+
context.print(`Agent workspace command failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
407
|
+
this.requestRender();
|
|
408
|
+
});
|
|
409
|
+
this.requestRender();
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
if (resolved === 'inline') {
|
|
413
|
+
const capturedLines: string[] = [];
|
|
414
|
+
const originalPrint = context.print;
|
|
415
|
+
if (typeof context.executeCommand !== 'function') {
|
|
416
|
+
this.agentWorkspace.lastActionResult = {
|
|
417
|
+
kind: 'error',
|
|
418
|
+
title: `Command unavailable: ${command}`,
|
|
419
|
+
detail: 'No command dispatcher is configured for this runtime.',
|
|
420
|
+
command,
|
|
421
|
+
safety: 'safe',
|
|
422
|
+
};
|
|
423
|
+
this.requestRender();
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
context.print = (text: string): void => {
|
|
427
|
+
capturedLines.push(text);
|
|
428
|
+
};
|
|
429
|
+
const buildCapturedDetail = (): string => {
|
|
430
|
+
const MAX_CHARS = 1500;
|
|
431
|
+
const MAX_LINES = 12;
|
|
432
|
+
const lines = capturedLines.slice(-MAX_LINES);
|
|
433
|
+
const joined = lines.join('\n');
|
|
434
|
+
if (joined.length > MAX_CHARS) {
|
|
435
|
+
return joined.slice(0, MAX_CHARS) + '\n… (output truncated)';
|
|
436
|
+
}
|
|
437
|
+
const omitted = capturedLines.length - lines.length;
|
|
438
|
+
return omitted > 0 ? `… (${omitted} line(s) truncated)\n${joined}` : joined || '(no output)';
|
|
439
|
+
};
|
|
440
|
+
void context.executeCommand(name, [...args]).then(() => {
|
|
441
|
+
context.print = originalPrint;
|
|
442
|
+
this.agentWorkspace.lastActionResult = {
|
|
443
|
+
kind: 'dispatched',
|
|
444
|
+
title: `Result: ${command}`,
|
|
445
|
+
detail: buildCapturedDetail(),
|
|
446
|
+
command,
|
|
447
|
+
safety: 'safe',
|
|
448
|
+
};
|
|
449
|
+
this.requestRender();
|
|
450
|
+
}).catch((error: unknown) => {
|
|
451
|
+
context.print = originalPrint;
|
|
452
|
+
this.agentWorkspace.lastActionResult = {
|
|
453
|
+
kind: 'error',
|
|
454
|
+
title: `${command} failed`,
|
|
455
|
+
detail: error instanceof Error ? error.message : String(error),
|
|
456
|
+
command,
|
|
457
|
+
};
|
|
458
|
+
this.requestRender();
|
|
459
|
+
});
|
|
460
|
+
return;
|
|
461
|
+
}
|
|
462
|
+
// compose (default): close workspace then execute
|
|
463
|
+
this.closeAgentWorkspaceModal();
|
|
402
464
|
void context.executeCommand?.(name, [...args]).catch((error: unknown) => {
|
|
403
465
|
context.print(`Agent workspace command failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
404
466
|
this.requestRender();
|
|
@@ -674,7 +736,7 @@ export class InputHandler {
|
|
|
674
736
|
this.modalOpened('agentWorkspace');
|
|
675
737
|
this.agentWorkspace.open(
|
|
676
738
|
context,
|
|
677
|
-
(command) => this.dispatchAgentWorkspaceCommand(command, context),
|
|
739
|
+
(command, behavior) => this.dispatchAgentWorkspaceCommand(command, context, behavior),
|
|
678
740
|
undefined,
|
|
679
741
|
(prompt) => this.dispatchAgentWorkspacePrompt(prompt, context),
|
|
680
742
|
);
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { CommandContext } from './command-registry.ts';
|
|
2
|
+
import { buildSetupWizardDurableReceiptsFromReadModel, mergeSetupWizardDurableReceipts } from '../agent/setup-wizard-artifact-receipts.ts';
|
|
3
|
+
import type { AgentSetupWizardDurableReceipt } from '../agent/setup-wizard.ts';
|
|
4
|
+
|
|
5
|
+
interface SetupReceiptReadModelSource {
|
|
6
|
+
readonly path: string;
|
|
7
|
+
readonly source: unknown;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function readRecord(value: unknown): Record<string, unknown> {
|
|
11
|
+
return value && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : {};
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function setupReceiptReadModelSources(context: CommandContext): readonly SetupReceiptReadModelSource[] {
|
|
15
|
+
const contextRecord = context as unknown as Record<string, unknown>;
|
|
16
|
+
const platform = readRecord(contextRecord.platform);
|
|
17
|
+
const clients = readRecord(contextRecord.clients);
|
|
18
|
+
const readModels = readRecord(platform.readModels);
|
|
19
|
+
const setup = readRecord(readModels.setup);
|
|
20
|
+
const setupWizard = readRecord(readModels.setupWizard);
|
|
21
|
+
const firstRun = readRecord(readModels.firstRun);
|
|
22
|
+
const browserPwa = readRecord(readModels.browserPwa);
|
|
23
|
+
const operator = readRecord(clients.operator);
|
|
24
|
+
return [
|
|
25
|
+
{ path: 'context.platform.readModels.setup.receipts', source: setup.receipts },
|
|
26
|
+
{ path: 'context.platform.readModels.setup.setupReceipts', source: setup.setupReceipts },
|
|
27
|
+
{ path: 'context.platform.readModels.setup.receiptEvents', source: setup.receiptEvents },
|
|
28
|
+
{ path: 'context.platform.readModels.setup.eventStream', source: setup.eventStream },
|
|
29
|
+
{ path: 'context.platform.readModels.setup', source: readModels.setup },
|
|
30
|
+
{ path: 'context.platform.readModels.setupWizard.receipts', source: setupWizard.receipts },
|
|
31
|
+
{ path: 'context.platform.readModels.setupWizard.durableReceipts', source: setupWizard.durableReceipts },
|
|
32
|
+
{ path: 'context.platform.readModels.setupWizard.receiptEvents', source: setupWizard.receiptEvents },
|
|
33
|
+
{ path: 'context.platform.readModels.setupWizard.eventStream', source: setupWizard.eventStream },
|
|
34
|
+
{ path: 'context.platform.readModels.setupReceipts', source: readModels.setupReceipts },
|
|
35
|
+
{ path: 'context.platform.readModels.setupReceiptEvents', source: readModels.setupReceiptEvents },
|
|
36
|
+
{ path: 'context.platform.readModels.setupReceiptEventStream', source: readModels.setupReceiptEventStream },
|
|
37
|
+
{ path: 'context.platform.readModels.durableSetupReceipts', source: readModels.durableSetupReceipts },
|
|
38
|
+
{ path: 'context.platform.readModels.firstRun.receipts', source: firstRun.receipts },
|
|
39
|
+
{ path: 'context.platform.readModels.browserPwa.firstRunReceipts', source: browserPwa.firstRunReceipts },
|
|
40
|
+
{ path: 'context.platform.setupReceipts', source: platform.setupReceipts },
|
|
41
|
+
{ path: 'context.platform.setupReceiptEvents', source: platform.setupReceiptEvents },
|
|
42
|
+
{ path: 'context.clients.operator.setupReceipts', source: operator.setupReceipts },
|
|
43
|
+
{ path: 'context.clients.operator.setupReceiptEvents', source: operator.setupReceiptEvents },
|
|
44
|
+
];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function readSnapshot(source: unknown): unknown {
|
|
48
|
+
if (typeof source === 'function') {
|
|
49
|
+
const result = (source as () => unknown)();
|
|
50
|
+
return result instanceof Promise ? undefined : result;
|
|
51
|
+
}
|
|
52
|
+
const record = readRecord(source);
|
|
53
|
+
for (const methodName of ['getSnapshot', 'snapshot', 'list', 'listReceipts', 'listEvents', 'listReceiptEvents', 'readEvents']) {
|
|
54
|
+
const method = record[methodName];
|
|
55
|
+
if (typeof method === 'function') {
|
|
56
|
+
const result = (method as () => unknown)();
|
|
57
|
+
return result instanceof Promise ? undefined : result;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return source;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function setupWizardLiveDurableReceipts(context: CommandContext): readonly AgentSetupWizardDurableReceipt[] {
|
|
64
|
+
const receipts: AgentSetupWizardDurableReceipt[][] = [];
|
|
65
|
+
for (const entry of setupReceiptReadModelSources(context)) {
|
|
66
|
+
if (entry.source === undefined || entry.source === null) continue;
|
|
67
|
+
try {
|
|
68
|
+
receipts.push([...buildSetupWizardDurableReceiptsFromReadModel(readSnapshot(entry.source), entry.path)]);
|
|
69
|
+
} catch {
|
|
70
|
+
// Broken host read models should not hide local setup posture.
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return mergeSetupWizardDurableReceipts(...receipts);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export { mergeSetupWizardDurableReceipts };
|
|
@@ -46,43 +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
70
|
return lines;
|
|
87
71
|
}
|
|
88
72
|
|
|
@@ -257,13 +241,13 @@ function promptReceiptTimelineLines(snapshot: AgentWorkspaceRuntimeSnapshot): Co
|
|
|
257
241
|
fg: promptReceiptOutcomeColor(latest.outcomeStatus),
|
|
258
242
|
bold: latest.outcomeStatus === 'error' || latest.outcomeStatus === 'cancelled',
|
|
259
243
|
});
|
|
260
|
-
lines.push({ text: `
|
|
244
|
+
lines.push({ text: `Latest prompt receipt: ${latest.receiptId}; inspect it from Prompt context.`, fg: PALETTE.good });
|
|
261
245
|
if (timeline.errorCount > 0) {
|
|
262
|
-
lines.push({ text:
|
|
246
|
+
lines.push({ text: 'Prompt receipt filter: show errors.', fg: PALETTE.warn });
|
|
263
247
|
} else if (timeline.cancelledCount > 0) {
|
|
264
|
-
lines.push({ text:
|
|
248
|
+
lines.push({ text: 'Prompt receipt filter: show cancelled turns.', fg: PALETTE.warn });
|
|
265
249
|
} else if (timeline.pendingCount > 0) {
|
|
266
|
-
lines.push({ text:
|
|
250
|
+
lines.push({ text: 'Prompt receipt filter: show pending turns.', fg: PALETTE.info });
|
|
267
251
|
}
|
|
268
252
|
for (const receipt of timeline.items.slice(0, 3)) {
|
|
269
253
|
lines.push({
|
|
@@ -274,7 +258,7 @@ function promptReceiptTimelineLines(snapshot: AgentWorkspaceRuntimeSnapshot): Co
|
|
|
274
258
|
if (latest.detail) {
|
|
275
259
|
lines.push({ text: `Latest outcome detail: ${compactText(latest.detail, 104)}`, fg: PALETTE.warn });
|
|
276
260
|
}
|
|
277
|
-
lines.push({ text:
|
|
261
|
+
lines.push({ text: 'Prompt context controls stay read-only from this setup page.', fg: PALETTE.good });
|
|
278
262
|
return lines;
|
|
279
263
|
}
|
|
280
264
|
|
|
@@ -478,7 +462,7 @@ export function snapshotLines(workspace: AgentWorkspace, category: AgentWorkspac
|
|
|
478
462
|
{ text: `VIBE.md: ${vibe.applied} applied; ${vibe.blocked} blocked; ${vibe.truncated} truncated.`, fg: vibe.blocked > 0 ? PALETTE.warn : vibe.applied > 0 ? PALETTE.good : PALETTE.muted },
|
|
479
463
|
{ text: `Project context: ${projectContext.loaded} loaded; ${projectContext.blocked} blocked; ${projectContext.truncated} truncated.`, fg: projectContext.blocked > 0 ? PALETTE.warn : projectContext.loaded > 0 ? PALETTE.good : PALETTE.muted },
|
|
480
464
|
...promptReceiptTimelineLines(snapshot),
|
|
481
|
-
{ text: 'Context
|
|
465
|
+
{ text: 'Context controls: prompt receipts, project files, one-file inspection, and VIBE.md review.', fg: PALETTE.good },
|
|
482
466
|
);
|
|
483
467
|
} else if (category.id === 'onboarding-automation') {
|
|
484
468
|
base.push(
|
|
@@ -536,7 +520,7 @@ export function snapshotLines(workspace: AgentWorkspace, category: AgentWorkspac
|
|
|
536
520
|
companionAccessLine(snapshot),
|
|
537
521
|
{ text: `Channels: ${readyCount}/${snapshot.channels.length} ready; ${enabledCount} enabled; ${configuredDefaults} target(s).`, fg: PALETTE.info },
|
|
538
522
|
{ text: `Setup guide: ${guide.progressLabel}; ${guide.currentChannelLabel ?? 'choose a channel'}.`, fg: guide.status === 'ready' ? PALETTE.good : PALETTE.warn },
|
|
539
|
-
{ text: `Next: ${currentGuideStep ?
|
|
523
|
+
{ text: `Next: ${currentGuideStep ? currentGuideStep.label : 'All enabled channels ready.'}`, fg: currentGuideStep ? PALETTE.warn : PALETTE.good },
|
|
540
524
|
{ text: 'Guide checks setup schema, accounts, allowlist policy, live status, and explicit test sends.', fg: PALETTE.good },
|
|
541
525
|
{ text: 'Triage: /channels triage shows blockers, delivery retries, surface messages, route bindings, and receipts.', fg: PALETTE.good },
|
|
542
526
|
{ text: 'Secrets hidden; sends require explicit action.', fg: PALETTE.warn },
|