@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
|
@@ -128,13 +128,12 @@ export function buildSetupWizardCheckpoint(context: CommandContext): AgentSetupW
|
|
|
128
128
|
}
|
|
129
129
|
|
|
130
130
|
function setupChecklistUserRoute(item: AgentWorkspaceSetupChecklistItem): string {
|
|
131
|
-
return item.
|
|
131
|
+
return item.breadcrumb ?? 'Start';
|
|
132
132
|
}
|
|
133
133
|
|
|
134
134
|
function setupChecklistModelRoute(item: AgentWorkspaceSetupChecklistItem): string {
|
|
135
135
|
if (item.id === 'runtime') return 'agent_harness mode:"setup_item" setupItemId:"connected-host-readiness"';
|
|
136
136
|
if (item.id === 'provider-model') return 'models action:"status"';
|
|
137
|
-
if (item.id === 'install-smoke') return DEFAULT_AGENT_SETUP_WIZARD_RERUN_SMOKE_ROUTE;
|
|
138
137
|
if (item.id === 'subscriptions') return 'models action:"providers"';
|
|
139
138
|
if (item.id === 'agent-knowledge') return 'agent_knowledge mode:"status"';
|
|
140
139
|
if (item.id === 'profile') return 'agent_harness mode:"workspace_action" actionId:"profile-template-show"';
|
|
@@ -144,7 +143,6 @@ function setupChecklistModelRoute(item: AgentWorkspaceSetupChecklistItem): strin
|
|
|
144
143
|
if (item.id === 'memory') return 'memory action:"status"';
|
|
145
144
|
if (item.id === 'notes') return 'personal_ops action:"lane" laneId:"notes"';
|
|
146
145
|
if (item.id === 'channels') return 'channels action:"status"';
|
|
147
|
-
if (item.id === 'browser-pwa') return 'computer action:"browser" includeParameters:true';
|
|
148
146
|
if (item.id === 'voice-media') return 'device action:"voice"';
|
|
149
147
|
return `agent_harness mode:"setup_item" setupItemId:"${item.id}"`;
|
|
150
148
|
}
|
|
@@ -158,18 +156,15 @@ function setupChecklistActionId(item: AgentWorkspaceSetupChecklistItem): string
|
|
|
158
156
|
if (item.id === 'skills') return 'skill-search';
|
|
159
157
|
if (item.id === 'routines') return 'routine-search';
|
|
160
158
|
if (item.id === 'channels') return 'channel-show';
|
|
161
|
-
if (item.id === 'browser-pwa') return 'browser-cockpit-readiness';
|
|
162
159
|
if (item.id === 'voice-media') return 'voice-enable';
|
|
163
160
|
return item.id;
|
|
164
161
|
}
|
|
165
162
|
|
|
166
163
|
const SETUP_WIZARD_SNAPSHOT_BLOCKER_ALIASES: Readonly<Record<string, readonly string[]>> = {
|
|
167
|
-
'agent-binary': ['runtime'
|
|
164
|
+
'agent-binary': ['runtime'],
|
|
168
165
|
'connected-host-status': ['runtime'],
|
|
169
166
|
'connected-host-auth': ['connected-host-auth'],
|
|
170
167
|
'provider-model': ['provider-model'],
|
|
171
|
-
'setup-posture': ['install-smoke'],
|
|
172
|
-
'first-assistant-turn': ['install-smoke'],
|
|
173
168
|
};
|
|
174
169
|
|
|
175
170
|
export function buildWorkspaceSetupWizard(
|
|
@@ -179,7 +174,6 @@ export function buildWorkspaceSetupWizard(
|
|
|
179
174
|
setupMarkerExists: boolean,
|
|
180
175
|
durableReceipts: readonly AgentSetupWizardDurableReceipt[] = [],
|
|
181
176
|
): AgentSetupWizard {
|
|
182
|
-
const browserPwaNeedsReceipt = checklist.some((item) => item.id === 'browser-pwa' && item.status !== 'ready');
|
|
183
177
|
const items: AgentSetupWizardSourceItem[] = checklist.map((item) => ({
|
|
184
178
|
id: item.id,
|
|
185
179
|
label: item.label,
|
|
@@ -197,8 +191,6 @@ export function buildWorkspaceSetupWizard(
|
|
|
197
191
|
receiptRequiredStepIds: [
|
|
198
192
|
'runtime',
|
|
199
193
|
'connected-host-auth',
|
|
200
|
-
'install-smoke',
|
|
201
|
-
...(browserPwaNeedsReceipt ? ['browser-pwa'] : []),
|
|
202
194
|
],
|
|
203
195
|
durableReceipts,
|
|
204
196
|
setupMarkerExists,
|
|
@@ -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 {
|
|
@@ -42,10 +42,6 @@ export interface AgentWorkspaceSetupChecklistInput {
|
|
|
42
42
|
readonly readyChannelCount: number;
|
|
43
43
|
readonly voiceProviderCount: number;
|
|
44
44
|
readonly mediaProviderCount: number;
|
|
45
|
-
readonly installSmokeReceiptReady?: boolean;
|
|
46
|
-
readonly browserPwaEnabled: boolean;
|
|
47
|
-
readonly browserPwaPublicBaseUrl: string;
|
|
48
|
-
readonly browserPwaFirstRunReceiptStatus: 'published' | 'not-published';
|
|
49
45
|
readonly runtimeProfileCount: number;
|
|
50
46
|
readonly runtimeStarterTemplateCount: number;
|
|
51
47
|
}
|
|
@@ -69,20 +65,15 @@ export function buildAgentWorkspaceSetupChecklist(input: AgentWorkspaceSetupChec
|
|
|
69
65
|
: tokenPathKnown
|
|
70
66
|
? 'blocked'
|
|
71
67
|
: 'recommended';
|
|
72
|
-
const installSmokePrerequisitesReady = providerReady && (input.connectedHostTokenReadable || connectedHostAuthReceiptReady);
|
|
73
|
-
const installSmokeReceiptReady = input.installSmokeReceiptReady === true;
|
|
74
68
|
const hasActivePersona = input.activePersonaName !== '(none)' && input.activePersonaName !== '(unavailable)';
|
|
75
69
|
const discoveredBehaviorCount = input.discoveredPersonas.count + input.discoveredSkills.count + input.discoveredRoutines.count;
|
|
76
|
-
const browserPwaUrl = input.browserPwaPublicBaseUrl.trim();
|
|
77
|
-
const browserPwaHasPublicUrl = browserPwaUrl.length > 0 && browserPwaUrl !== '(not configured)';
|
|
78
|
-
const browserPwaReceiptPublished = input.browserPwaFirstRunReceiptStatus === 'published';
|
|
79
70
|
return [
|
|
80
71
|
{
|
|
81
72
|
id: 'runtime',
|
|
82
73
|
label: 'Connected host',
|
|
83
74
|
status: 'ready',
|
|
84
75
|
detail: `Agent will connect to ${input.runtimeBaseUrl}; protected host routes also need the Agent companion token below.`,
|
|
85
|
-
|
|
76
|
+
breadcrumb: 'Home -> Review health',
|
|
86
77
|
},
|
|
87
78
|
{
|
|
88
79
|
id: 'connected-host-auth',
|
|
@@ -97,7 +88,7 @@ export function buildAgentWorkspaceSetupChecklist(input: AgentWorkspaceSetupChec
|
|
|
97
88
|
: tokenPathKnown
|
|
98
89
|
? `Provision Agent's local connected-host operator token at ${input.connectedHostTokenPath} before pairing channels, Knowledge, schedules, or protected daemon routes.`
|
|
99
90
|
: 'Shell paths are unavailable in this runtime, so connected-host auth cannot be verified from the workspace snapshot.',
|
|
100
|
-
|
|
91
|
+
breadcrumb: 'Host -> Connected-host auth owner',
|
|
101
92
|
},
|
|
102
93
|
{
|
|
103
94
|
id: 'provider-model',
|
|
@@ -106,18 +97,7 @@ export function buildAgentWorkspaceSetupChecklist(input: AgentWorkspaceSetupChec
|
|
|
106
97
|
detail: providerReady
|
|
107
98
|
? `Current chat route is ${input.provider} / ${input.model}.`
|
|
108
99
|
: 'Choose a provider and model before relying on assistant turns.',
|
|
109
|
-
|
|
110
|
-
},
|
|
111
|
-
{
|
|
112
|
-
id: 'install-smoke',
|
|
113
|
-
label: 'Install smoke',
|
|
114
|
-
status: installSmokeReceiptReady ? 'ready' : installSmokePrerequisitesReady ? 'recommended' : tokenPathKnown ? 'blocked' : 'recommended',
|
|
115
|
-
detail: installSmokeReceiptReady
|
|
116
|
-
? 'Durable setup smoke receipt is ready for release closeout; rerun smoke only after install, host, auth, or model changes.'
|
|
117
|
-
: installSmokePrerequisitesReady
|
|
118
|
-
? 'Run setup smoke after install or migration to prove package start, connected host, auth, model route, setup posture, and first assistant turn.'
|
|
119
|
-
: 'Resolve connected-host auth and provider/model setup before treating the first assistant turn as install-ready.',
|
|
120
|
-
command: 'Start -> Install smoke',
|
|
100
|
+
breadcrumb: 'Setup -> Provider and model',
|
|
121
101
|
},
|
|
122
102
|
{
|
|
123
103
|
id: 'subscriptions',
|
|
@@ -134,14 +114,14 @@ export function buildAgentWorkspaceSetupChecklist(input: AgentWorkspaceSetupChec
|
|
|
134
114
|
: input.availableSubscriptionProviderCount > 0
|
|
135
115
|
? `${input.availableSubscriptionProviderCount} subscription-capable provider(s) are available. Start login if you want subscription routing.`
|
|
136
116
|
: 'No subscription-capable providers are available yet. Use API keys or add an OAuth provider service.',
|
|
137
|
-
|
|
117
|
+
breadcrumb: 'Start -> Start subscription login',
|
|
138
118
|
},
|
|
139
119
|
{
|
|
140
120
|
id: 'agent-knowledge',
|
|
141
121
|
label: 'Agent Knowledge',
|
|
142
122
|
status: 'recommended',
|
|
143
123
|
detail: 'Check isolated Agent Knowledge status, then ingest source-backed material into the Agent segment only.',
|
|
144
|
-
|
|
124
|
+
breadcrumb: 'Knowledge',
|
|
145
125
|
},
|
|
146
126
|
{
|
|
147
127
|
id: 'profile',
|
|
@@ -152,7 +132,7 @@ export function buildAgentWorkspaceSetupChecklist(input: AgentWorkspaceSetupChec
|
|
|
152
132
|
: discoveredBehaviorCount > 0
|
|
153
133
|
? `${discoveredBehaviorCount} discovered behavior file(s) can seed an isolated Agent profile from the Profiles workspace.`
|
|
154
134
|
: `${input.runtimeStarterTemplateCount} starter template(s) are available if this machine needs separate operator identities.`,
|
|
155
|
-
|
|
135
|
+
breadcrumb: 'Profiles',
|
|
156
136
|
},
|
|
157
137
|
{
|
|
158
138
|
id: 'persona',
|
|
@@ -163,7 +143,7 @@ export function buildAgentWorkspaceSetupChecklist(input: AgentWorkspaceSetupChec
|
|
|
163
143
|
: input.discoveredPersonas.count > 0
|
|
164
144
|
? `${input.discoveredPersonas.count} discovered persona file(s) can be imported into the Agent-local registry.${sampleNames(input.discoveredPersonas)}`
|
|
165
145
|
: 'Create or choose a persona to make the assistant voice and policy explicit.',
|
|
166
|
-
|
|
146
|
+
breadcrumb: 'Personas',
|
|
167
147
|
},
|
|
168
148
|
{
|
|
169
149
|
id: 'skills',
|
|
@@ -180,7 +160,7 @@ export function buildAgentWorkspaceSetupChecklist(input: AgentWorkspaceSetupChec
|
|
|
180
160
|
: input.discoveredSkills.count > 0
|
|
181
161
|
? `${input.discoveredSkills.count} discovered skill file(s) can be imported as local reusable procedures.${sampleNames(input.discoveredSkills)}`
|
|
182
162
|
: 'Create reusable local skills and bundles for repeated workflows.',
|
|
183
|
-
|
|
163
|
+
breadcrumb: 'Skills',
|
|
184
164
|
},
|
|
185
165
|
{
|
|
186
166
|
id: 'routines',
|
|
@@ -193,7 +173,7 @@ export function buildAgentWorkspaceSetupChecklist(input: AgentWorkspaceSetupChec
|
|
|
193
173
|
: input.discoveredRoutines.count > 0
|
|
194
174
|
? `${input.discoveredRoutines.count} discovered routine file(s) can be imported as main-conversation workflows.${sampleNames(input.discoveredRoutines)}`
|
|
195
175
|
: 'Create local routines first; promote schedules only with explicit confirmation.',
|
|
196
|
-
|
|
176
|
+
breadcrumb: 'Routines',
|
|
197
177
|
},
|
|
198
178
|
{
|
|
199
179
|
id: 'memory',
|
|
@@ -202,7 +182,7 @@ export function buildAgentWorkspaceSetupChecklist(input: AgentWorkspaceSetupChec
|
|
|
202
182
|
detail: input.localMemoryCount > 0
|
|
203
183
|
? `${input.localMemoryCount} Agent memory record(s) are available; ${input.localMemoryReviewQueueCount} need review.`
|
|
204
184
|
: 'Memory starts empty; durable facts should be stored deliberately and never include secrets.',
|
|
205
|
-
|
|
185
|
+
breadcrumb: 'Memory',
|
|
206
186
|
},
|
|
207
187
|
{
|
|
208
188
|
id: 'notes',
|
|
@@ -211,7 +191,7 @@ export function buildAgentWorkspaceSetupChecklist(input: AgentWorkspaceSetupChec
|
|
|
211
191
|
detail: input.localNoteCount > 0
|
|
212
192
|
? `${input.localNoteCount} Agent scratchpad note(s) are available; ${input.localNoteReviewQueueCount} need review.`
|
|
213
193
|
: 'Notes start empty; use them for source triage, temporary decisions, and handoff before promoting anything durable.',
|
|
214
|
-
|
|
194
|
+
breadcrumb: 'Notes',
|
|
215
195
|
},
|
|
216
196
|
{
|
|
217
197
|
id: 'channels',
|
|
@@ -220,27 +200,14 @@ export function buildAgentWorkspaceSetupChecklist(input: AgentWorkspaceSetupChec
|
|
|
220
200
|
detail: input.readyChannelCount > 0
|
|
221
201
|
? `${input.readyChannelCount} external channel(s) are ready.`
|
|
222
202
|
: 'Pair or review channels only when you want the assistant reachable outside this terminal.',
|
|
223
|
-
|
|
224
|
-
},
|
|
225
|
-
{
|
|
226
|
-
id: 'browser-pwa',
|
|
227
|
-
label: 'Browser/PWA',
|
|
228
|
-
status: browserPwaReceiptPublished ? 'ready' : 'recommended',
|
|
229
|
-
detail: browserPwaReceiptPublished
|
|
230
|
-
? `Connected-host browser/PWA first-run receipt is published${browserPwaHasPublicUrl ? ` for ${browserPwaUrl}` : ''}.`
|
|
231
|
-
: input.browserPwaEnabled
|
|
232
|
-
? browserPwaHasPublicUrl
|
|
233
|
-
? `Browser cockpit is openable at ${browserPwaUrl}, but the connected-host browser/PWA first-run completion receipt is not published yet. Terminal Agent remains primary until that receipt exists.`
|
|
234
|
-
: 'Browser cockpit is enabled through the connected-host web endpoint, but the connected-host browser/PWA first-run completion receipt is not published yet.'
|
|
235
|
-
: 'Enable the connected-host web endpoint and publish the browser/PWA first-run completion receipt before treating browser access as setup-ready.',
|
|
236
|
-
command: 'Voice & Media -> Browser/PWA readiness',
|
|
203
|
+
breadcrumb: 'Channels',
|
|
237
204
|
},
|
|
238
205
|
{
|
|
239
206
|
id: 'voice-media',
|
|
240
207
|
label: 'Voice and media',
|
|
241
208
|
status: input.voiceProviderCount > 0 || input.mediaProviderCount > 0 ? 'ready' : 'optional',
|
|
242
209
|
detail: `${input.voiceProviderCount} voice provider(s), ${input.mediaProviderCount} media provider(s). Configure these only when useful.`,
|
|
243
|
-
|
|
210
|
+
breadcrumb: 'Voice & Media',
|
|
244
211
|
},
|
|
245
212
|
];
|
|
246
213
|
}
|
|
@@ -463,9 +463,6 @@ export function buildAgentWorkspaceRuntimeSnapshot(context: CommandContext): Age
|
|
|
463
463
|
const browserPwaEnabled = readConfigBoolean(context, 'web.enabled', false);
|
|
464
464
|
const browserPwaPublicBaseUrl = readConfigString(context, 'web.publicBaseUrl', '(not configured)');
|
|
465
465
|
const connectedHostAuthReceiptReady = setupStepHasSatisfyingReceipt(durableSetupReceipts, 'connected-host-auth');
|
|
466
|
-
const installSmokeReceiptReady = setupSmokeHistory.latestResult === 'ready-for-user-run'
|
|
467
|
-
|| setupStepHasSatisfyingReceipt(durableSetupReceipts, 'install-smoke');
|
|
468
|
-
const browserPwaReceiptReady = setupStepHasSatisfyingReceipt(durableSetupReceipts, 'browser-pwa');
|
|
469
466
|
const setupChecklist = buildAgentWorkspaceSetupChecklist({
|
|
470
467
|
provider,
|
|
471
468
|
model,
|
|
@@ -498,10 +495,6 @@ export function buildAgentWorkspaceRuntimeSnapshot(context: CommandContext): Age
|
|
|
498
495
|
readyChannelCount: channels.filter((channel) => channel.ready).length,
|
|
499
496
|
voiceProviderCount: voiceProviders.length,
|
|
500
497
|
mediaProviderCount: mediaProviders.length,
|
|
501
|
-
installSmokeReceiptReady,
|
|
502
|
-
browserPwaEnabled,
|
|
503
|
-
browserPwaPublicBaseUrl,
|
|
504
|
-
browserPwaFirstRunReceiptStatus: browserPwaReceiptReady ? 'published' : 'not-published',
|
|
505
498
|
runtimeProfileCount: runtimeProfiles.length,
|
|
506
499
|
runtimeStarterTemplateCount: runtimeStarterTemplates.length,
|
|
507
500
|
});
|
|
@@ -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,
|
|
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,8 +153,8 @@ export class AgentWorkspace {
|
|
|
142
153
|
return selectedAgentWorkspaceLocalLibraryItem(this.runtimeSnapshot, this.selectedLibraryItemIndexes, kind);
|
|
143
154
|
}
|
|
144
155
|
|
|
145
|
-
|
|
146
|
-
return
|
|
156
|
+
settingActionDisplay(action: AgentWorkspaceAction): AgentWorkspaceSettingActionDisplay | null {
|
|
157
|
+
return buildAgentWorkspaceSettingActionDisplay(this.context, action);
|
|
147
158
|
}
|
|
148
159
|
|
|
149
160
|
focusCategories(): void {
|
|
@@ -279,8 +290,8 @@ export class AgentWorkspace {
|
|
|
279
290
|
return Boolean(this.context?.submitInput && this.dispatchPrompt);
|
|
280
291
|
}
|
|
281
292
|
|
|
282
|
-
dispatchWorkspaceCommand(command: string): void {
|
|
283
|
-
this.dispatchCommand?.(command);
|
|
293
|
+
dispatchWorkspaceCommand(command: string, behavior?: 'inline' | 'compose' | 'exit'): void {
|
|
294
|
+
this.dispatchCommand?.(command, behavior);
|
|
284
295
|
}
|
|
285
296
|
|
|
286
297
|
dispatchWorkspacePrompt(prompt: string): void {
|
package/src/input/commands.ts
CHANGED
|
@@ -6,7 +6,6 @@ import { knowledgeCommand } from './commands/knowledge.ts';
|
|
|
6
6
|
import { registerShellCoreCommands } from './commands/shell-core.ts';
|
|
7
7
|
import { registerConfigCommand } from './commands/config.ts';
|
|
8
8
|
import { registerSessionWorkflowCommands } from './commands/session-workflow.ts';
|
|
9
|
-
import { registerPlanningRuntimeCommands } from './commands/planning-runtime.ts';
|
|
10
9
|
import { registerScheduleRuntimeCommands } from './commands/schedule-runtime.ts';
|
|
11
10
|
import { registerOperatorRuntimeCommands } from './commands/operator-runtime.ts';
|
|
12
11
|
import { registerNotifyRuntimeCommands } from './commands/notify-runtime.ts';
|
|
@@ -27,7 +26,6 @@ import { registerConversationRuntimeCommands } from './commands/conversation-run
|
|
|
27
26
|
import { registerQrcodeRuntimeCommands } from './commands/qrcode-runtime.ts';
|
|
28
27
|
import { registerOnboardingRuntimeCommands } from './commands/onboarding-runtime.ts';
|
|
29
28
|
import { registerTtsRuntimeCommands } from './commands/tts-runtime.ts';
|
|
30
|
-
import { registerWorkPlanRuntimeCommands } from './commands/work-plan-runtime.ts';
|
|
31
29
|
import { registerAgentWorkspaceRuntimeCommands } from './commands/agent-workspace-runtime.ts';
|
|
32
30
|
import { registerAgentRuntimeProfileRuntimeCommands } from './commands/agent-runtime-profile-runtime.ts';
|
|
33
31
|
import { registerDelegationRuntimeCommands } from './commands/delegation-runtime.ts';
|
|
@@ -90,10 +88,8 @@ export function registerBuiltinCommands(registry: CommandRegistry): void {
|
|
|
90
88
|
registerQrcodeRuntimeCommands(registry);
|
|
91
89
|
registerOnboardingRuntimeCommands(registry);
|
|
92
90
|
registerTtsRuntimeCommands(registry);
|
|
93
|
-
registerWorkPlanRuntimeCommands(registry);
|
|
94
91
|
registerLocalRuntimeCommands(registry);
|
|
95
92
|
registerSessionWorkflowCommands(registry);
|
|
96
|
-
registerPlanningRuntimeCommands(registry);
|
|
97
93
|
registerScheduleRuntimeCommands(registry);
|
|
98
94
|
registerSessionContentCommands(registry);
|
|
99
95
|
registerAgentMemoryCommand(registry);
|
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,74 @@ 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
|
+
// Default to 'inline' so editor submissions stay inside the workspace modal.
|
|
401
|
+
// Closing the modal mid-flow (the old 'compose' default) traps users in the
|
|
402
|
+
// wrong context and was the primary symptom of the broken onboarding flow.
|
|
403
|
+
const resolved = behavior ?? 'inline';
|
|
400
404
|
const { name, args } = parseSlashCommand(command);
|
|
401
405
|
if (!name) return;
|
|
406
|
+
if (resolved === 'exit') {
|
|
407
|
+
this.closeAgentWorkspaceModal();
|
|
408
|
+
void context.executeCommand?.(name, [...args]).catch((error: unknown) => {
|
|
409
|
+
context.print(`Agent workspace command failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
410
|
+
this.requestRender();
|
|
411
|
+
});
|
|
412
|
+
this.requestRender();
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
if (resolved === 'inline') {
|
|
416
|
+
const capturedLines: string[] = [];
|
|
417
|
+
const originalPrint = context.print;
|
|
418
|
+
if (typeof context.executeCommand !== 'function') {
|
|
419
|
+
this.agentWorkspace.lastActionResult = {
|
|
420
|
+
kind: 'error',
|
|
421
|
+
title: `Command unavailable: ${command}`,
|
|
422
|
+
detail: 'No command dispatcher is configured for this runtime.',
|
|
423
|
+
command,
|
|
424
|
+
safety: 'safe',
|
|
425
|
+
};
|
|
426
|
+
this.requestRender();
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
context.print = (text: string): void => {
|
|
430
|
+
capturedLines.push(text);
|
|
431
|
+
};
|
|
432
|
+
const buildCapturedDetail = (): string => {
|
|
433
|
+
const MAX_CHARS = 1500;
|
|
434
|
+
const MAX_LINES = 12;
|
|
435
|
+
const lines = capturedLines.slice(-MAX_LINES);
|
|
436
|
+
const joined = lines.join('\n');
|
|
437
|
+
if (joined.length > MAX_CHARS) {
|
|
438
|
+
return joined.slice(0, MAX_CHARS) + '\n… (output truncated)';
|
|
439
|
+
}
|
|
440
|
+
const omitted = capturedLines.length - lines.length;
|
|
441
|
+
return omitted > 0 ? `… (${omitted} line(s) truncated)\n${joined}` : joined || '(no output)';
|
|
442
|
+
};
|
|
443
|
+
void context.executeCommand(name, [...args]).then(() => {
|
|
444
|
+
context.print = originalPrint;
|
|
445
|
+
this.agentWorkspace.lastActionResult = {
|
|
446
|
+
kind: 'dispatched',
|
|
447
|
+
title: `Result: ${command}`,
|
|
448
|
+
detail: buildCapturedDetail(),
|
|
449
|
+
command,
|
|
450
|
+
safety: 'safe',
|
|
451
|
+
};
|
|
452
|
+
this.requestRender();
|
|
453
|
+
}).catch((error: unknown) => {
|
|
454
|
+
context.print = originalPrint;
|
|
455
|
+
this.agentWorkspace.lastActionResult = {
|
|
456
|
+
kind: 'error',
|
|
457
|
+
title: `${command} failed`,
|
|
458
|
+
detail: error instanceof Error ? error.message : String(error),
|
|
459
|
+
command,
|
|
460
|
+
};
|
|
461
|
+
this.requestRender();
|
|
462
|
+
});
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
// compose (default): close workspace then execute
|
|
466
|
+
this.closeAgentWorkspaceModal();
|
|
402
467
|
void context.executeCommand?.(name, [...args]).catch((error: unknown) => {
|
|
403
468
|
context.print(`Agent workspace command failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
404
469
|
this.requestRender();
|
|
@@ -674,7 +739,7 @@ export class InputHandler {
|
|
|
674
739
|
this.modalOpened('agentWorkspace');
|
|
675
740
|
this.agentWorkspace.open(
|
|
676
741
|
context,
|
|
677
|
-
(command) => this.dispatchAgentWorkspaceCommand(command, context),
|
|
742
|
+
(command, behavior) => this.dispatchAgentWorkspaceCommand(command, context, behavior),
|
|
678
743
|
undefined,
|
|
679
744
|
(prompt) => this.dispatchAgentWorkspacePrompt(prompt, context),
|
|
680
745
|
);
|
package/src/main.ts
CHANGED
|
@@ -54,7 +54,6 @@ import { applyInitialTuiCliState, formatFatalStartupErrorForLog, formatFatalStar
|
|
|
54
54
|
import { wireSpokenTurnRuntime } from './audio/spoken-turn-wiring.ts';
|
|
55
55
|
import { attachSpokenTurnModelRouting, createSpokenTurnInputOptions } from './audio/spoken-turn-model-routing.ts';
|
|
56
56
|
import { allowTerminalWrite, installTuiTerminalOutputGuard } from './runtime/terminal-output-guard.ts';
|
|
57
|
-
import { ProjectPlanningCoordinator } from './planning/project-planning-coordinator.ts';
|
|
58
57
|
import { buildCommandArgsHint } from './input/command-args-hint.ts';
|
|
59
58
|
import { GOODVIBES_AGENT_PAIRING_SURFACE } from './config/surface.ts';
|
|
60
59
|
|
|
@@ -262,18 +261,6 @@ async function main() {
|
|
|
262
261
|
configManager,
|
|
263
262
|
notify: (message) => { systemMessageRouter.high(message); render(); },
|
|
264
263
|
}));
|
|
265
|
-
const projectPlanningCoordinator = new ProjectPlanningCoordinator({
|
|
266
|
-
service: ctx.services.projectPlanningService,
|
|
267
|
-
projectId: ctx.services.projectPlanningProjectId,
|
|
268
|
-
workingDirectory: workingDir,
|
|
269
|
-
notify: (message) => { systemMessageRouter.high(message); render(); },
|
|
270
|
-
openPanel: () => {
|
|
271
|
-
panelManager.open('project-planning');
|
|
272
|
-
panelManager.show();
|
|
273
|
-
render();
|
|
274
|
-
},
|
|
275
|
-
});
|
|
276
|
-
|
|
277
264
|
const submitInput = (text: string, content?: ContentPart[], options: { readonly spokenOutput?: boolean } = {}) => {
|
|
278
265
|
input.clearModalStack();
|
|
279
266
|
scrollLocked = true; // Re-lock on user input
|
|
@@ -308,33 +295,7 @@ async function main() {
|
|
|
308
295
|
}
|
|
309
296
|
if (processedText || content) {
|
|
310
297
|
void (async () => {
|
|
311
|
-
|
|
312
|
-
if (!options.spokenOutput && processedText) {
|
|
313
|
-
try {
|
|
314
|
-
const planning = await projectPlanningCoordinator.prepareTurn(processedText);
|
|
315
|
-
if (planning) {
|
|
316
|
-
if (planning.handledLocally) {
|
|
317
|
-
systemMessageRouter.high(planning.statusMessage);
|
|
318
|
-
render();
|
|
319
|
-
return;
|
|
320
|
-
}
|
|
321
|
-
conversation.addSystemMessage(planning.systemMessage);
|
|
322
|
-
inputOptions = {
|
|
323
|
-
origin: {
|
|
324
|
-
source: 'project-planning',
|
|
325
|
-
surface: GOODVIBES_AGENT_PAIRING_SURFACE,
|
|
326
|
-
metadata: {
|
|
327
|
-
projectId: ctx.services.projectPlanningProjectId,
|
|
328
|
-
knowledgeSpaceId: planning.state.knowledgeSpaceId,
|
|
329
|
-
readiness: planning.evaluation.readiness,
|
|
330
|
-
},
|
|
331
|
-
},
|
|
332
|
-
};
|
|
333
|
-
}
|
|
334
|
-
} catch (err) {
|
|
335
|
-
systemMessageRouter.high(`[Planning] ${summarizeError(err)}`);
|
|
336
|
-
}
|
|
337
|
-
}
|
|
298
|
+
const inputOptions = options.spokenOutput ? createSpokenTurnInputOptions() : undefined;
|
|
338
299
|
if (options.spokenOutput && processedText) {
|
|
339
300
|
spokenTurns.submitNextTurn(processedText);
|
|
340
301
|
}
|
|
@@ -3,8 +3,6 @@ import { ContextVisualizerPanel } from '../context-visualizer-panel.ts';
|
|
|
3
3
|
import { ThinkingPanel } from '../thinking-panel.ts';
|
|
4
4
|
import { ToolInspectorPanel } from '../tool-inspector-panel.ts';
|
|
5
5
|
import { SchedulePanel } from '../schedule-panel.ts';
|
|
6
|
-
import { ProjectPlanningPanel } from '../project-planning-panel.ts';
|
|
7
|
-
import { WorkPlanPanel } from '../work-plan-panel.ts';
|
|
8
6
|
import type { ResolvedBuiltinPanelDeps } from './shared.ts';
|
|
9
7
|
import { requireAutomationManager, requireUiServices } from './shared.ts';
|
|
10
8
|
|
|
@@ -49,32 +47,6 @@ export function registerAgentPanels(manager: PanelManager, deps: ResolvedBuiltin
|
|
|
49
47
|
),
|
|
50
48
|
});
|
|
51
49
|
|
|
52
|
-
manager.registerType({
|
|
53
|
-
id: 'work-plan',
|
|
54
|
-
name: 'Work Plan',
|
|
55
|
-
icon: 'L',
|
|
56
|
-
category: 'agent',
|
|
57
|
-
description: 'Persistent workspace checklist for multi-step work and cross-session task tracking',
|
|
58
|
-
preload: true,
|
|
59
|
-
factory: () => new WorkPlanPanel(deps.workPlanStore),
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
manager.registerType({
|
|
63
|
-
id: 'project-planning',
|
|
64
|
-
name: 'Planning',
|
|
65
|
-
icon: 'P',
|
|
66
|
-
category: 'agent',
|
|
67
|
-
description: 'Passive project planning artifacts: readiness, questions, decisions, language, task graph, and agent handoff metadata',
|
|
68
|
-
preload: true,
|
|
69
|
-
factory: () => new ProjectPlanningPanel({
|
|
70
|
-
service: deps.projectPlanningService,
|
|
71
|
-
projectId: deps.projectPlanningProjectId,
|
|
72
|
-
requestRender: deps.requestRender,
|
|
73
|
-
submitAnswer: deps.submitPlanningAnswer,
|
|
74
|
-
dismissPlanning: deps.dismissPlanning,
|
|
75
|
-
}),
|
|
76
|
-
});
|
|
77
|
-
|
|
78
50
|
manager.registerType({
|
|
79
51
|
id: 'schedule',
|
|
80
52
|
name: 'Schedule',
|