@pellux/goodvibes-agent 1.1.3 → 1.1.5
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 +13 -0
- package/dist/package/main.js +1780 -939
- package/package.json +1 -1
- package/src/input/agent-workspace-activation.ts +21 -1
- package/src/input/agent-workspace-basic-command-editors.ts +8 -9
- package/src/input/agent-workspace-categories.ts +263 -115
- package/src/input/agent-workspace-category-actions.ts +25 -0
- package/src/input/agent-workspace-host-category.ts +57 -0
- package/src/input/agent-workspace-local-editor-submission.ts +193 -0
- package/src/input/agent-workspace-search.ts +6 -0
- package/src/input/agent-workspace-settings.ts +314 -0
- package/src/input/agent-workspace-setup.ts +20 -0
- package/src/input/agent-workspace-snapshot.ts +89 -0
- package/src/input/agent-workspace-subscription-editor.ts +214 -0
- package/src/input/agent-workspace-types.ts +56 -1
- package/src/input/agent-workspace.ts +139 -164
- package/src/input/handler-modal-token-routes.ts +12 -12
- package/src/input/handler.ts +2 -1
- package/src/main.ts +11 -7
- package/src/renderer/agent-workspace.ts +80 -14
- package/src/shell/agent-workspace-fullscreen.ts +11 -3
- package/src/tools/agent-harness-ui-surface-metadata.ts +1 -1
- package/src/tools/agent-harness-workspace-actions.ts +2 -2
- package/src/version.ts +1 -1
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
WORKSPACE_PALETTE as PALETTE,
|
|
18
18
|
type WorkspaceRow,
|
|
19
19
|
} from './fullscreen-workspace.ts';
|
|
20
|
-
import { actionResultColor,
|
|
20
|
+
import { actionResultColor, setupStatusColor, type AgentWorkspaceContextLine as ContextLine } from './agent-workspace-style.ts';
|
|
21
21
|
|
|
22
22
|
function buildLeftRows(workspace: AgentWorkspace, height: number): WorkspaceRow[] {
|
|
23
23
|
const rows: WorkspaceRow[] = [];
|
|
@@ -55,10 +55,15 @@ function buildLeftRows(workspace: AgentWorkspace, height: number): WorkspaceRow[
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
function actionCommand(action: AgentWorkspaceAction): string {
|
|
58
|
-
if (action.kind === 'workspace') return
|
|
59
|
-
if (action.kind === 'editor') return action.editorKind ? `edit ${action.editorKind}` : '
|
|
58
|
+
if (action.kind === 'workspace') return 'open area';
|
|
59
|
+
if (action.kind === 'editor') return action.editorKind ? `edit ${action.editorKind}` : 'edit form';
|
|
60
|
+
if (action.kind === 'setting') return action.settingKey ? `setting ${action.settingKey}` : 'setting';
|
|
61
|
+
if (action.kind === 'settings-import') return 'import GoodVibes settings';
|
|
62
|
+
if (action.kind === 'model-picker') return action.modelPickerFlow === 'model' ? 'model picker' : 'provider/model picker';
|
|
63
|
+
if (action.kind === 'settings-modal') return action.settingsTarget ? `settings ${action.settingsTarget}` : 'settings';
|
|
60
64
|
if (action.kind === 'local-selection') return action.selectionDelta && action.selectionDelta < 0 ? 'select previous' : 'select next';
|
|
61
65
|
if (action.kind === 'local-operation') return action.localOperation ?? '(local action)';
|
|
66
|
+
if (action.kind === 'onboarding-complete') return 'apply and close';
|
|
62
67
|
return action.command ?? '(guidance)';
|
|
63
68
|
}
|
|
64
69
|
|
|
@@ -81,6 +86,11 @@ function setupStatusLabel(status: AgentWorkspaceRuntimeSnapshot['setupChecklist'
|
|
|
81
86
|
: 'Optional';
|
|
82
87
|
}
|
|
83
88
|
|
|
89
|
+
function formatMegabytes(bytes: number): string {
|
|
90
|
+
if (!Number.isFinite(bytes) || bytes <= 0) return '0 MB';
|
|
91
|
+
return `${Math.round(bytes / (1024 * 1024))} MB`;
|
|
92
|
+
}
|
|
93
|
+
|
|
84
94
|
function compactText(text: string, maxWidth = 104): string {
|
|
85
95
|
const normalized = text.replace(/\s+/g, ' ').trim();
|
|
86
96
|
if (normalized.length === 0) return '';
|
|
@@ -91,8 +101,8 @@ function compactText(text: string, maxWidth = 104): string {
|
|
|
91
101
|
|
|
92
102
|
function actionMetaLine(action: AgentWorkspaceAction): ContextLine {
|
|
93
103
|
return {
|
|
94
|
-
text:
|
|
95
|
-
fg: action.kind === 'command' ? PALETTE.info :
|
|
104
|
+
text: `Does: ${actionCommand(action)}`,
|
|
105
|
+
fg: action.safety === 'blocked' ? PALETTE.warn : action.kind === 'command' ? PALETTE.info : PALETTE.muted,
|
|
96
106
|
};
|
|
97
107
|
}
|
|
98
108
|
|
|
@@ -116,7 +126,7 @@ function setupOverviewLines(snapshot: AgentWorkspaceRuntimeSnapshot): ContextLin
|
|
|
116
126
|
const counts = setupCounts(snapshot);
|
|
117
127
|
const nextItems = setupAttentionItems(snapshot, 3);
|
|
118
128
|
const lines: ContextLine[] = [
|
|
119
|
-
{ text: '
|
|
129
|
+
{ text: 'Onboarding', fg: PALETTE.title, bold: true },
|
|
120
130
|
{ text: `${counts.ready}/${snapshot.setupChecklist.length} ready; ${counts.recommended} recommended; ${counts.optional} optional; ${counts.blocked} blocked.`, fg: counts.blocked > 0 ? PALETTE.warn : PALETTE.info },
|
|
121
131
|
{ text: `Chat: ${snapshot.provider} / ${snapshot.modelDisplayName}.`, fg: PALETTE.info },
|
|
122
132
|
{ text: `Local: ${snapshot.localPersonaCount} personas, ${snapshot.localSkillCount} skills, ${snapshot.localRoutineCount} routines, ${snapshot.localMemoryCount} memories.`, fg: PALETTE.info },
|
|
@@ -289,6 +299,63 @@ function snapshotLines(workspace: AgentWorkspace, category: AgentWorkspaceCatego
|
|
|
289
299
|
base.push(
|
|
290
300
|
...setupOverviewLines(snapshot),
|
|
291
301
|
);
|
|
302
|
+
} else if (category.id === 'account-model') {
|
|
303
|
+
base.push(
|
|
304
|
+
{ text: `Chat route: ${snapshot.provider} / ${snapshot.modelDisplayName}`, fg: PALETTE.info },
|
|
305
|
+
{ text: `Subscriptions: ${snapshot.activeSubscriptionCount} active; ${snapshot.pendingSubscriptionCount} pending; ${snapshot.availableSubscriptionProviderCount} available.`, fg: snapshot.activeSubscriptionCount > 0 ? PALETTE.good : snapshot.pendingSubscriptionCount > 0 ? PALETTE.warn : PALETTE.muted },
|
|
306
|
+
{ text: `Embedding: ${snapshot.embeddingProvider}; reasoning ${snapshot.reasoningEffort}.`, fg: PALETTE.info },
|
|
307
|
+
{ text: `Helper: ${snapshot.helperEnabled ? 'enabled' : 'disabled'}; Tool LLM: ${snapshot.toolLlmEnabled ? 'enabled' : 'disabled'}.`, fg: snapshot.helperEnabled || snapshot.toolLlmEnabled ? PALETTE.good : PALETTE.muted },
|
|
308
|
+
{ text: `Cache: ${snapshot.cacheEnabled ? snapshot.cacheStableTtl : 'off'}; monitor ${snapshot.cacheMonitorHitRate ? snapshot.cacheHitRateWarningThreshold : 'off'}; failure hints ${snapshot.providerFailureHints ? 'on' : 'off'}.`, fg: snapshot.cacheEnabled ? PALETTE.info : PALETTE.muted },
|
|
309
|
+
);
|
|
310
|
+
} else if (category.id === 'assistant-behavior') {
|
|
311
|
+
base.push(
|
|
312
|
+
{ text: `Interaction: ${snapshot.hitlMode}; guidance ${snapshot.guidanceMode}; history ${snapshot.saveHistory ? 'saved' : 'off'}.`, fg: PALETTE.info },
|
|
313
|
+
{ text: `Context: compact at ${snapshot.autoCompactThreshold}; stale warnings ${snapshot.staleContextWarnings ? 'on' : 'off'}.`, fg: PALETTE.info },
|
|
314
|
+
{ text: `Reasoning display: thinking ${snapshot.showThinking ? 'on' : 'off'}; summaries ${snapshot.showReasoningSummary ? 'on' : 'off'}.`, fg: PALETTE.muted },
|
|
315
|
+
);
|
|
316
|
+
} else if (category.id === 'tools-permissions') {
|
|
317
|
+
base.push(
|
|
318
|
+
{ text: `Permission mode: ${snapshot.permissionMode}.`, fg: snapshot.permissionMode === 'allow-all' ? PALETTE.warn : PALETTE.info },
|
|
319
|
+
{ text: `Auto-approve ${snapshot.autoApprove ? 'on' : 'off'}; tool auto-heal ${snapshot.toolAutoHeal ? 'on' : 'off'}; token budget ${snapshot.toolsDefaultTokenBudget}.`, fg: snapshot.autoApprove ? PALETTE.warn : PALETTE.info },
|
|
320
|
+
{ text: `Artifact limit ${formatMegabytes(snapshot.artifactMaxBytes)}; raw prompt telemetry ${snapshot.rawPromptTelemetry ? 'on' : 'off'}.`, fg: snapshot.rawPromptTelemetry ? PALETTE.warn : PALETTE.muted },
|
|
321
|
+
{ text: `MCP servers: ${snapshot.mcpConnectedServerCount}/${snapshot.mcpServerCount} connected; quarantined ${snapshot.mcpQuarantinedServerCount}.`, fg: snapshot.mcpQuarantinedServerCount > 0 ? PALETTE.warn : PALETTE.info },
|
|
322
|
+
{ text: 'MCP and secret setup use forms; selecting a row does not run arbitrary tools.', fg: PALETTE.good },
|
|
323
|
+
);
|
|
324
|
+
} else if (category.id === 'onboarding-display') {
|
|
325
|
+
base.push(
|
|
326
|
+
{ text: `Theme: ${snapshot.theme}; streaming ${snapshot.stream ? 'on' : 'off'}; line numbers ${snapshot.lineNumbers}.`, fg: PALETTE.info },
|
|
327
|
+
{ text: `Messages: operational ${snapshot.operationalMessages}; system ${snapshot.systemMessages}.`, fg: PALETTE.info },
|
|
328
|
+
{ text: `Release channel: ${snapshot.releaseChannel}.`, fg: PALETTE.muted },
|
|
329
|
+
);
|
|
330
|
+
} else if (category.id === 'onboarding-channels') {
|
|
331
|
+
const enabledCount = snapshot.channels.filter((channel) => channel.enabled).length;
|
|
332
|
+
const readyCount = snapshot.channels.filter((channel) => channel.ready).length;
|
|
333
|
+
const needsConfig = snapshot.channels.filter((channel) => channel.setupState === 'needs-config');
|
|
334
|
+
const needsTarget = snapshot.channels.filter((channel) => channel.setupState === 'needs-target');
|
|
335
|
+
base.push(
|
|
336
|
+
{ text: `Channels: ${readyCount}/${snapshot.channels.length} ready; ${enabledCount} enabled.`, fg: enabledCount > 0 ? PALETTE.info : PALETTE.muted },
|
|
337
|
+
{ text: `Needs config: ${needsConfig.length}; needs target: ${needsTarget.length}.`, fg: needsConfig.length > 0 || needsTarget.length > 0 ? PALETTE.warn : PALETTE.good },
|
|
338
|
+
{ text: 'Enable only the channels you want; hidden channel fields appear after the channel is enabled.', fg: PALETTE.good },
|
|
339
|
+
);
|
|
340
|
+
} else if (category.id === 'onboarding-voice-media') {
|
|
341
|
+
const readiness = snapshot.voiceMediaReadiness;
|
|
342
|
+
base.push(
|
|
343
|
+
{ text: `Voice: ${snapshot.voiceSurfaceEnabled ? 'enabled' : 'disabled'}; TTS ${snapshot.ttsProvider}; voice ${snapshot.ttsVoice}.`, fg: snapshot.voiceSurfaceEnabled ? PALETTE.good : PALETTE.info },
|
|
344
|
+
{ text: `Media readiness: ${readiness.readyMediaProviderCount}/${snapshot.mediaProviderCount}; generation providers ${snapshot.mediaGenerationProviderCount}.`, fg: readiness.readyMediaProviderCount > 0 ? PALETTE.good : PALETTE.muted },
|
|
345
|
+
{ text: `Telephony channel: ${snapshot.channels.find((channel) => channel.id === 'telephony')?.setupState ?? 'disabled'}.`, fg: PALETTE.info },
|
|
346
|
+
);
|
|
347
|
+
} else if (category.id === 'onboarding-context') {
|
|
348
|
+
base.push(
|
|
349
|
+
{ text: `Local context: ${snapshot.localMemoryCount} memories, ${snapshot.localNoteCount} notes, ${snapshot.localPersonaCount} personas.`, fg: PALETTE.info },
|
|
350
|
+
{ text: `Skills: ${snapshot.enabledSkillCount}/${snapshot.localSkillCount} enabled; routines ${snapshot.enabledRoutineCount}/${snapshot.localRoutineCount} enabled.`, fg: PALETTE.info },
|
|
351
|
+
{ text: `Discovered files: personas ${snapshot.discoveredBehavior.personas.count}, skills ${snapshot.discoveredBehavior.skills.count}, routines ${snapshot.discoveredBehavior.routines.count}.`, fg: PALETTE.muted },
|
|
352
|
+
);
|
|
353
|
+
} else if (category.id === 'onboarding-automation') {
|
|
354
|
+
base.push(
|
|
355
|
+
{ text: `Automation: ${snapshot.automationEnabled ? 'enabled' : 'disabled'}; max ${snapshot.automationMaxConcurrentRuns} concurrent; history ${snapshot.automationRunHistoryLimit}.`, fg: snapshot.automationEnabled ? PALETTE.good : PALETTE.muted },
|
|
356
|
+
{ text: `Timeout ${snapshot.automationDefaultTimeoutMs} ms; catch-up ${snapshot.automationCatchUpWindowMinutes} min; cooldown ${snapshot.automationFailureCooldownMs} ms.`, fg: PALETTE.info },
|
|
357
|
+
{ text: `Delete one-shot jobs after success: ${snapshot.automationDeleteAfterRun ? 'yes' : 'no'}.`, fg: snapshot.automationDeleteAfterRun ? PALETTE.info : PALETTE.muted },
|
|
358
|
+
);
|
|
292
359
|
} else if (category.id === 'artifacts') {
|
|
293
360
|
const mediaReady = snapshot.voiceMediaReadiness.readyMediaProviderCount;
|
|
294
361
|
base.push(
|
|
@@ -309,7 +376,7 @@ function snapshotLines(workspace: AgentWorkspace, category: AgentWorkspaceCatego
|
|
|
309
376
|
companionAccessLine(snapshot),
|
|
310
377
|
{ text: `Channels: ${readyCount}/${snapshot.channels.length} ready; ${enabledCount} enabled; ${configuredDefaults} target(s).`, fg: PALETTE.info },
|
|
311
378
|
{ text: `Next: ${nextAttentionChannel ? `${nextAttentionChannel.label} - ${compactText(nextAttentionChannel.nextStep)}` : 'All enabled channels ready.'}`, fg: nextAttentionChannel ? PALETTE.warn : PALETTE.good },
|
|
312
|
-
{ text: '
|
|
379
|
+
{ text: 'Secrets hidden; sends require explicit action.', fg: PALETTE.warn },
|
|
313
380
|
);
|
|
314
381
|
} else if (category.id === 'knowledge') {
|
|
315
382
|
base.push(
|
|
@@ -536,9 +603,8 @@ function buildEditorFieldRows(editor: AgentWorkspaceLocalEditor, index: number,
|
|
|
536
603
|
function buildActionRows(workspace: AgentWorkspace, width: number, height: number): WorkspaceRow[] {
|
|
537
604
|
if (workspace.localEditor) return buildEditorRows(workspace.localEditor, width, height);
|
|
538
605
|
const rows: WorkspaceRow[] = [];
|
|
539
|
-
const labelWidth = Math.min(
|
|
540
|
-
const
|
|
541
|
-
const commandWidth = Math.max(10, width - labelWidth - safetyWidth - 9);
|
|
606
|
+
const labelWidth = Math.min(34, Math.max(18, Math.floor(width * 0.38)));
|
|
607
|
+
const commandWidth = Math.max(10, width - labelWidth - 6);
|
|
542
608
|
if (workspace.actionSearchActive) {
|
|
543
609
|
rows.push({
|
|
544
610
|
text: ` Search: ${workspace.actionSearchQuery || '(type to filter actions)'}`,
|
|
@@ -547,7 +613,7 @@ function buildActionRows(workspace: AgentWorkspace, width: number, height: numbe
|
|
|
547
613
|
});
|
|
548
614
|
}
|
|
549
615
|
rows.push({
|
|
550
|
-
text: ` ${padDisplay(workspace.actionSearchActive ? 'Result' : 'Action', labelWidth)} ${padDisplay('
|
|
616
|
+
text: ` ${padDisplay(workspace.actionSearchActive ? 'Result' : 'Action', labelWidth)} ${padDisplay('Does', commandWidth)}`,
|
|
551
617
|
fg: PALETTE.muted,
|
|
552
618
|
bold: true,
|
|
553
619
|
});
|
|
@@ -564,9 +630,9 @@ function buildActionRows(workspace: AgentWorkspace, width: number, height: numbe
|
|
|
564
630
|
const label = searchResult ? `${searchResult.category.label} / ${action.label}` : action.label;
|
|
565
631
|
const marker = selected ? GLYPHS.navigation.selected : ' ';
|
|
566
632
|
rows.push({
|
|
567
|
-
text: `${marker} ${padDisplay(label, labelWidth)} ${padDisplay(
|
|
633
|
+
text: `${marker} ${padDisplay(label, labelWidth)} ${padDisplay(actionCommand(action), commandWidth)}`,
|
|
568
634
|
selected: selected && workspace.focusPane === 'actions',
|
|
569
|
-
fg:
|
|
635
|
+
fg: action.safety === 'blocked' ? PALETTE.warn : selected ? PALETTE.text : PALETTE.info,
|
|
570
636
|
bold: selected,
|
|
571
637
|
});
|
|
572
638
|
}
|
|
@@ -620,7 +686,7 @@ export function renderAgentWorkspace(workspace: AgentWorkspace, width: number, h
|
|
|
620
686
|
leftHeader: 'Operator Areas',
|
|
621
687
|
mainHeader: workspace.actionSearchActive
|
|
622
688
|
? `Search actions · ${workspace.actions.length} result(s)`
|
|
623
|
-
: `${category.label} · ${
|
|
689
|
+
: `${category.label} · ${workspace.actions.length} action(s)`,
|
|
624
690
|
leftRows: buildLeftRows(workspace, metrics.bodyRows),
|
|
625
691
|
contextRows: buildContextRows(workspace, category, action, metrics.contextWidth),
|
|
626
692
|
controlRows: buildActionRows(workspace, metrics.contextWidth, metrics.controlRows),
|
|
@@ -16,8 +16,8 @@ function normalizeFullscreenViewport(lines: readonly Line[], width: number, heig
|
|
|
16
16
|
return viewport;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
export function
|
|
20
|
-
|
|
19
|
+
export function createFullscreenCompositeFromLines(
|
|
20
|
+
lines: readonly Line[],
|
|
21
21
|
width: number,
|
|
22
22
|
height: number,
|
|
23
23
|
): CompositeRequest {
|
|
@@ -25,9 +25,17 @@ export function createAgentWorkspaceFullscreenComposite(
|
|
|
25
25
|
width,
|
|
26
26
|
height,
|
|
27
27
|
header: [],
|
|
28
|
-
viewport: normalizeFullscreenViewport(
|
|
28
|
+
viewport: normalizeFullscreenViewport(lines, width, height),
|
|
29
29
|
footer: [],
|
|
30
30
|
forceFullRedraw: true,
|
|
31
31
|
panelWidth: 0,
|
|
32
32
|
};
|
|
33
33
|
}
|
|
34
|
+
|
|
35
|
+
export function createAgentWorkspaceFullscreenComposite(
|
|
36
|
+
workspace: AgentWorkspace,
|
|
37
|
+
width: number,
|
|
38
|
+
height: number,
|
|
39
|
+
): CompositeRequest {
|
|
40
|
+
return createFullscreenCompositeFromLines(renderAgentWorkspace(workspace, width, height), width, height);
|
|
41
|
+
}
|
|
@@ -327,7 +327,7 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
|
|
|
327
327
|
kind: 'picker',
|
|
328
328
|
summary: 'Reasoning-effort selector for models that expose effort levels.',
|
|
329
329
|
command: '/effort',
|
|
330
|
-
preferredModelRoute: `Use ${agentHarnessModes('settings', 'get_setting', 'set_setting')} for provider.reasoningEffort when a concrete level is known, or mode:"run_workspace_action" setup-effort with confirmation.`,
|
|
330
|
+
preferredModelRoute: `Use ${agentHarnessModes('settings', 'get_setting', 'set_setting')} for provider.reasoningEffort when a concrete level is known, or mode:"run_workspace_action" setup-reasoning-effort with confirmation.`,
|
|
331
331
|
available: (context) => typeof context.openReasoningEffortPicker === 'function',
|
|
332
332
|
open: (context) => {
|
|
333
333
|
const surface = findSurfaceById('reasoning-effort-picker')!;
|
|
@@ -55,7 +55,7 @@ function readString(value: unknown): string {
|
|
|
55
55
|
function readLimit(value: unknown, fallback: number): number {
|
|
56
56
|
const parsed = typeof value === 'string' && value.trim() ? Number(value) : value;
|
|
57
57
|
if (typeof parsed !== 'number' || !Number.isFinite(parsed)) return fallback;
|
|
58
|
-
return Math.max(1, Math.min(
|
|
58
|
+
return Math.max(1, Math.min(1000, Math.trunc(parsed)));
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
function readFieldMap(value: unknown): Readonly<Record<string, string>> {
|
|
@@ -256,7 +256,7 @@ export function listWorkspaceActions(
|
|
|
256
256
|
): readonly Record<string, unknown>[] {
|
|
257
257
|
const query = readString(args.query);
|
|
258
258
|
const categoryId = readString(args.categoryId || args.category);
|
|
259
|
-
const limit = readLimit(args.limit,
|
|
259
|
+
const limit = readLimit(args.limit, 1000);
|
|
260
260
|
const includeEditor = args.includeParameters === true;
|
|
261
261
|
const editorContext = includeEditor ? buildWorkspaceEditorContext(context, args) : null;
|
|
262
262
|
const source = query
|
package/src/version.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { join } from 'node:path';
|
|
|
6
6
|
// The prebuild script updates the fallback value before compilation.
|
|
7
7
|
// Uses import.meta.dir (Bun) to locate package.json relative to this file,
|
|
8
8
|
// which is correct regardless of the process working directory.
|
|
9
|
-
let _version = '1.1.
|
|
9
|
+
let _version = '1.1.5';
|
|
10
10
|
try {
|
|
11
11
|
const pkg = JSON.parse(readFileSync(join(import.meta.dir, '..', 'package.json'), 'utf-8')) as {
|
|
12
12
|
readonly version?: unknown;
|