@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.
@@ -17,7 +17,7 @@ import {
17
17
  WORKSPACE_PALETTE as PALETTE,
18
18
  type WorkspaceRow,
19
19
  } from './fullscreen-workspace.ts';
20
- import { actionResultColor, safetyColor, setupStatusColor, type AgentWorkspaceContextLine as ContextLine } from './agent-workspace-style.ts';
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 action.targetCategoryId ? `open ${action.targetCategoryId}` : '(workspace)';
59
- if (action.kind === 'editor') return action.editorKind ? `edit ${action.editorKind}` : '(editor)';
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: `${actionCommand(action)}; ${action.safety}`,
95
- fg: action.kind === 'command' ? PALETTE.info : safetyColor(action),
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: 'Setup Overview', fg: PALETTE.title, bold: true },
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: 'Safety: secrets hidden; sends require explicit action.', fg: PALETTE.warn },
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(28, Math.max(16, Math.floor(width * 0.30)));
540
- const safetyWidth = 10;
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('Safety', safetyWidth)} ${padDisplay('Command', commandWidth)}`,
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(action.safety, safetyWidth)} ${padDisplay(actionCommand(action), commandWidth)}`,
633
+ text: `${marker} ${padDisplay(label, labelWidth)} ${padDisplay(actionCommand(action), commandWidth)}`,
568
634
  selected: selected && workspace.focusPane === 'actions',
569
- fg: safetyColor(action),
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} · ${category.actions.length} action(s)`,
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 createAgentWorkspaceFullscreenComposite(
20
- workspace: AgentWorkspace,
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(renderAgentWorkspace(workspace, width, height), width, height),
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(500, Math.trunc(parsed)));
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, 500);
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.3';
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;