@pellux/goodvibes-agent 1.1.7 → 1.2.0
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 +170 -0
- package/README.md +46 -30
- package/dist/package/{ast-grep-napi.linux-x64-gnu-mkk8xwww.node → ast-grep-napi.linux-x64-gnu-swtppvy9.node} +0 -0
- package/dist/package/{ast-grep-napi.linux-x64-musl-ryqtgdv6.node → ast-grep-napi.linux-x64-musl-ttfcdtap.node} +0 -0
- package/dist/package/main.js +132577 -91483
- package/docs/README.md +14 -7
- package/docs/channels-remote-and-api.md +8 -5
- package/docs/connected-host.md +14 -12
- package/docs/getting-started.md +56 -30
- package/docs/knowledge-artifacts-and-multimodal.md +7 -5
- package/docs/project-planning.md +2 -2
- package/docs/providers-and-routing.md +11 -3
- package/docs/tools-and-commands.md +114 -45
- package/docs/voice-and-live-tts.md +3 -1
- package/package.json +3 -2
- package/release/release-notes.md +130 -5
- package/release/release-readiness.json +120 -90
- package/src/agent/assistant-cockpit.ts +247 -0
- package/src/agent/autonomy-schedule-format.ts +96 -0
- package/src/agent/autonomy-schedule.ts +514 -0
- package/src/agent/channel-delivery-receipts.ts +292 -0
- package/src/agent/competitive-feature-inventory.ts +296 -0
- package/src/agent/document-registry-types.ts +106 -0
- package/src/agent/document-registry.ts +734 -0
- package/src/agent/harness-control.ts +2 -2
- package/src/agent/memory-prompt.ts +2 -2
- package/src/agent/operator-actions.ts +50 -6
- package/src/agent/persona-registry.ts +8 -0
- package/src/agent/project-context-files.ts +273 -0
- package/src/agent/prompt-context-receipts.ts +502 -0
- package/src/agent/reminder-schedule-format.ts +16 -2
- package/src/agent/research-run-registry.ts +582 -0
- package/src/agent/research-source-registry.ts +441 -0
- package/src/agent/routine-registry.ts +19 -3
- package/src/agent/routine-schedule-format.ts +27 -2
- package/src/agent/runtime-profile-starters.ts +7 -0
- package/src/agent/runtime-profile.ts +106 -4
- package/src/agent/schedule-edit-format.ts +129 -0
- package/src/agent/schedule-edit.ts +496 -0
- package/src/agent/schedule-next-routes.ts +42 -0
- package/src/agent/setup-wizard-checkpoint.ts +140 -0
- package/src/agent/setup-wizard.ts +447 -0
- package/src/agent/skill-registry-types.ts +102 -0
- package/src/agent/skill-registry.ts +81 -107
- package/src/agent/vibe-confirmation-routes.ts +62 -0
- package/src/agent/vibe-file.ts +285 -0
- package/src/cli/agent-knowledge-command.ts +45 -2
- package/src/cli/help.ts +3 -0
- package/src/cli/profiles-command.ts +25 -11
- package/src/config/agent-settings-policy.ts +1 -18
- package/src/input/agent-workspace-activation.ts +53 -0
- package/src/input/agent-workspace-artifact-browser-editor.ts +494 -0
- package/src/input/agent-workspace-artifact-metadata.ts +17 -0
- package/src/input/agent-workspace-basic-command-editors.ts +5 -1
- package/src/input/agent-workspace-categories.ts +153 -155
- package/src/input/agent-workspace-channel-triage.ts +481 -0
- package/src/input/agent-workspace-channels.ts +263 -0
- package/src/input/agent-workspace-command-editor.ts +152 -0
- package/src/input/agent-workspace-context-snapshot.ts +349 -0
- package/src/input/agent-workspace-delegation-editor-submission.ts +8 -0
- package/src/input/agent-workspace-document-editor.ts +502 -0
- package/src/input/agent-workspace-document-ops-editor.ts +523 -0
- package/src/input/agent-workspace-host-category.ts +1 -1
- package/src/input/agent-workspace-local-library-snapshot.ts +167 -0
- package/src/input/agent-workspace-model-compare-editor.ts +376 -0
- package/src/input/agent-workspace-model-compare-prompt-submission.ts +552 -0
- package/src/input/agent-workspace-model-compare-types.ts +82 -0
- package/src/input/agent-workspace-model-compare-utils.ts +35 -0
- package/src/input/agent-workspace-onboarding-categories.ts +141 -0
- package/src/input/agent-workspace-operations-command-editor-submission.ts +53 -0
- package/src/input/agent-workspace-operations-command-editors.ts +22 -0
- package/src/input/agent-workspace-research-report-editor.ts +212 -0
- package/src/input/agent-workspace-research-run-editor.ts +144 -0
- package/src/input/agent-workspace-research-source-editor.ts +167 -0
- package/src/input/agent-workspace-review-packet-snapshot.ts +593 -0
- package/src/input/agent-workspace-review-packet-utils.ts +265 -0
- package/src/input/agent-workspace-settings.ts +262 -30
- package/src/input/agent-workspace-setup-checkpoint-action.ts +127 -0
- package/src/input/agent-workspace-setup-snapshot.ts +198 -0
- package/src/input/agent-workspace-setup.ts +34 -1
- package/src/input/agent-workspace-snapshot.ts +162 -147
- package/src/input/agent-workspace-types.ts +287 -2
- package/src/input/agent-workspace.ts +18 -0
- package/src/input/command-registry.ts +9 -2
- package/src/input/commands/agent-runtime-profile-runtime.ts +28 -13
- package/src/input/commands/channels-runtime.ts +102 -114
- package/src/input/commands/delegation-runtime.ts +87 -24
- package/src/input/commands/knowledge-browser-flags.ts +12 -0
- package/src/input/commands/knowledge.ts +28 -14
- package/src/input/commands/operator-actions-runtime.ts +6 -3
- package/src/input/commands/schedule-runtime.ts +71 -14
- package/src/input/commands/session-content.ts +2 -2
- package/src/input/commands/shell-core.ts +2 -0
- package/src/input/commands/vibe-runtime.ts +140 -0
- package/src/input/commands.ts +2 -0
- package/src/input/connected-host-routes.ts +123 -0
- package/src/input/settings-modal-types.ts +14 -0
- package/src/main.ts +15 -15
- package/src/panels/qr-panel.ts +2 -2
- package/src/renderer/agent-workspace-context-lines.ts +686 -0
- package/src/renderer/agent-workspace.ts +30 -419
- package/src/renderer/settings-modal-helpers.ts +12 -0
- package/src/renderer/settings-modal.ts +12 -0
- package/src/runtime/bootstrap-command-context.ts +11 -1
- package/src/runtime/bootstrap-command-parts.ts +14 -3
- package/src/runtime/bootstrap-core.ts +39 -1
- package/src/runtime/bootstrap-shell.ts +6 -0
- package/src/runtime/bootstrap.ts +113 -30
- package/src/runtime/connected-host-auth.ts +3 -2
- package/src/runtime/execution-ledger.ts +231 -0
- package/src/runtime/services.ts +88 -10
- package/src/runtime/tool-permission-safety.ts +199 -5
- package/src/shell/session-continuity-hints.ts +39 -0
- package/src/tools/agent-artifacts-tool.ts +606 -0
- package/src/tools/agent-audit-tool.ts +155 -0
- package/src/tools/agent-autonomy-schedule-tool.ts +238 -0
- package/src/tools/agent-autonomy-tool.ts +140 -0
- package/src/tools/agent-channel-send-tool.ts +24 -2
- package/src/tools/agent-channels-tool.ts +140 -0
- package/src/tools/agent-computer-tool.ts +168 -0
- package/src/tools/agent-context-policy.ts +137 -7
- package/src/tools/agent-context-tool.ts +143 -0
- package/src/tools/agent-delegation-tool.ts +128 -0
- package/src/tools/agent-device-tool.ts +240 -0
- package/src/tools/agent-documents-tool.ts +684 -0
- package/src/tools/agent-execution-tool.ts +230 -0
- package/src/tools/agent-harness-agent-orchestration.ts +703 -0
- package/src/tools/agent-harness-autonomy-intake.ts +785 -0
- package/src/tools/agent-harness-autonomy-live-records.ts +588 -0
- package/src/tools/agent-harness-autonomy-queue-types.ts +88 -0
- package/src/tools/agent-harness-autonomy-queue.ts +560 -0
- package/src/tools/agent-harness-background-processes-types.ts +35 -0
- package/src/tools/agent-harness-background-processes.ts +794 -0
- package/src/tools/agent-harness-browser-cockpit-route.ts +219 -0
- package/src/tools/agent-harness-browser-control.ts +338 -0
- package/src/tools/agent-harness-channel-metadata.ts +168 -10
- package/src/tools/agent-harness-cli-command-policy.ts +110 -0
- package/src/tools/agent-harness-command-catalog.ts +4 -2
- package/src/tools/agent-harness-command-runner.ts +42 -0
- package/src/tools/agent-harness-connected-host-status.ts +7 -4
- package/src/tools/agent-harness-delegation-posture.ts +234 -19
- package/src/tools/agent-harness-document-ops-reviewer-readiness.ts +234 -0
- package/src/tools/agent-harness-document-ops-types.ts +72 -0
- package/src/tools/agent-harness-document-ops.ts +671 -0
- package/src/tools/agent-harness-execution-history.ts +489 -0
- package/src/tools/agent-harness-execution-posture.ts +382 -0
- package/src/tools/agent-harness-file-recovery.ts +135 -0
- package/src/tools/agent-harness-keybinding-metadata.ts +16 -12
- package/src/tools/agent-harness-learning-curator-common.ts +102 -0
- package/src/tools/agent-harness-learning-curator-consolidation.ts +295 -0
- package/src/tools/agent-harness-learning-curator-proposals.ts +606 -0
- package/src/tools/agent-harness-learning-curator-types.ts +151 -0
- package/src/tools/agent-harness-learning-curator.ts +417 -0
- package/src/tools/agent-harness-local-model-benchmarks.ts +199 -0
- package/src/tools/agent-harness-local-model-cookbook.ts +238 -0
- package/src/tools/agent-harness-local-model-endpoints.ts +673 -0
- package/src/tools/agent-harness-media-posture.ts +208 -2
- package/src/tools/agent-harness-memory-posture.ts +556 -0
- package/src/tools/agent-harness-metadata.ts +100 -168
- package/src/tools/agent-harness-mode-catalog.ts +84 -33
- package/src/tools/agent-harness-model-catalog.ts +162 -0
- package/src/tools/agent-harness-model-provider-health.ts +186 -0
- package/src/tools/agent-harness-model-readiness.ts +406 -0
- package/src/tools/agent-harness-model-routing-types.ts +266 -0
- package/src/tools/agent-harness-model-routing-utils.ts +30 -0
- package/src/tools/agent-harness-model-routing.ts +137 -190
- package/src/tools/agent-harness-operator-methods.ts +115 -133
- package/src/tools/agent-harness-pairing-posture.ts +431 -18
- package/src/tools/agent-harness-personal-ops-discovery.ts +533 -0
- package/src/tools/agent-harness-personal-ops-intake.ts +385 -0
- package/src/tools/agent-harness-personal-ops-lanes.ts +204 -0
- package/src/tools/agent-harness-personal-ops-records.ts +732 -0
- package/src/tools/agent-harness-personal-ops-runner.ts +637 -0
- package/src/tools/agent-harness-personal-ops-types.ts +222 -0
- package/src/tools/agent-harness-personal-ops.ts +606 -0
- package/src/tools/agent-harness-project-context.ts +144 -0
- package/src/tools/agent-harness-prompt-context.ts +589 -0
- package/src/tools/agent-harness-provider-account-metadata.ts +2 -2
- package/src/tools/agent-harness-release-evidence.ts +9 -7
- package/src/tools/agent-harness-release-readiness.ts +9 -7
- package/src/tools/agent-harness-research-briefing.ts +427 -0
- package/src/tools/agent-harness-research-queue.ts +250 -0
- package/src/tools/agent-harness-research-runs.ts +295 -0
- package/src/tools/agent-harness-research-workflow.ts +322 -0
- package/src/tools/agent-harness-security-posture.ts +2 -2
- package/src/tools/agent-harness-service-posture.ts +9 -9
- package/src/tools/agent-harness-session-metadata.ts +3 -3
- package/src/tools/agent-harness-setup-connected-host.ts +501 -0
- package/src/tools/agent-harness-setup-describe.ts +557 -0
- package/src/tools/agent-harness-setup-handoffs.ts +502 -0
- package/src/tools/agent-harness-setup-model-helpers.ts +101 -0
- package/src/tools/agent-harness-setup-plan.ts +253 -0
- package/src/tools/agent-harness-setup-posture-types.ts +218 -0
- package/src/tools/agent-harness-setup-posture-utils.ts +173 -0
- package/src/tools/agent-harness-setup-posture.ts +449 -221
- package/src/tools/agent-harness-setup-smoke.ts +508 -0
- package/src/tools/agent-harness-sudo-posture.ts +114 -0
- package/src/tools/agent-harness-tool-schema.ts +120 -7
- package/src/tools/agent-harness-tool-types.ts +78 -0
- package/src/tools/agent-harness-tool-utils.ts +43 -0
- package/src/tools/agent-harness-tool.ts +311 -370
- package/src/tools/agent-harness-ui-surface-metadata.ts +76 -69
- package/src/tools/agent-harness-ui-surface-types.ts +46 -0
- package/src/tools/agent-harness-vibe-health.ts +105 -0
- package/src/tools/agent-harness-workspace-action-runner.ts +149 -0
- package/src/tools/agent-harness-workspace-actions.ts +114 -8
- package/src/tools/agent-harness-workspace-editor-execution.ts +214 -0
- package/src/tools/agent-harness-workspace-editor-runner.ts +755 -0
- package/src/tools/agent-host-tool.ts +159 -0
- package/src/tools/agent-knowledge-ingest-tool.ts +34 -1
- package/src/tools/agent-learning-consolidation-core.ts +327 -0
- package/src/tools/agent-learning-consolidation-tool.ts +758 -0
- package/src/tools/agent-memory-tool.ts +214 -0
- package/src/tools/agent-model-compare-export.ts +315 -0
- package/src/tools/agent-model-compare-handoff.ts +592 -0
- package/src/tools/agent-model-compare-judgment.ts +633 -0
- package/src/tools/agent-model-compare-run.ts +722 -0
- package/src/tools/agent-model-compare-tool.ts +698 -0
- package/src/tools/agent-model-compare-types.ts +191 -0
- package/src/tools/agent-model-compare-utils.ts +93 -0
- package/src/tools/agent-models-tool.ts +208 -0
- package/src/tools/agent-operator-action-tool.ts +1 -1
- package/src/tools/agent-operator-method-tool.ts +643 -0
- package/src/tools/agent-personal-ops-tool.ts +197 -0
- package/src/tools/agent-policy-explanation.ts +415 -0
- package/src/tools/agent-research-report-tool.ts +608 -0
- package/src/tools/agent-research-runs-tool.ts +434 -0
- package/src/tools/agent-research-sources-tool.ts +443 -0
- package/src/tools/agent-research-tool.ts +687 -0
- package/src/tools/agent-review-packet-presets-core.ts +757 -0
- package/src/tools/agent-review-packet-presets-tool.ts +466 -0
- package/src/tools/agent-review-packet-share-tool.ts +305 -0
- package/src/tools/agent-route-planner-candidates-setup.ts +411 -0
- package/src/tools/agent-route-planner-candidates-surfaces.ts +432 -0
- package/src/tools/agent-route-planner-candidates-work.ts +251 -0
- package/src/tools/agent-route-planner-helpers.ts +667 -0
- package/src/tools/agent-route-planner.ts +185 -0
- package/src/tools/agent-route-tool.ts +105 -0
- package/src/tools/agent-schedule-edit-tool.ts +210 -0
- package/src/tools/agent-schedule-tool.ts +282 -0
- package/src/tools/agent-security-tool.ts +145 -0
- package/src/tools/agent-sessions-tool.ts +122 -0
- package/src/tools/agent-settings-import-tool.ts +104 -0
- package/src/tools/agent-settings-tool.ts +176 -0
- package/src/tools/agent-setup-tool.ts +226 -0
- package/src/tools/agent-support-tool.ts +122 -0
- package/src/tools/agent-terminal-process-tools.ts +167 -0
- package/src/tools/agent-tool-policy-guard-types.ts +77 -0
- package/src/tools/agent-tool-policy-guard.ts +106 -85
- package/src/tools/agent-vibe-tool.ts +297 -0
- package/src/tools/agent-work-plan-tool.ts +265 -6
- package/src/tools/agent-workspace-tool.ts +305 -0
- package/src/tools/artifact-archive.ts +169 -0
- package/src/tools/tool-definition-compaction.ts +36 -0
- package/src/version.ts +1 -1
|
@@ -0,0 +1,686 @@
|
|
|
1
|
+
import type { AgentWorkspace, AgentWorkspaceCategory, AgentWorkspaceLocalEditor, AgentWorkspaceRuntimeSnapshot } from '../input/agent-workspace.ts';
|
|
2
|
+
import { buildAssistantCockpitFromWorkspaceSnapshot, type AssistantCockpitLane, type AssistantCockpitLaneState, type AssistantCockpitStatus } from '../agent/assistant-cockpit.ts';
|
|
3
|
+
import { formatAgentRecordReviewState } from '../agent/record-labels.ts';
|
|
4
|
+
import { truncateDisplay } from '../utils/terminal-width.ts';
|
|
5
|
+
import { WORKSPACE_PALETTE as PALETTE } from './fullscreen-workspace.ts';
|
|
6
|
+
import { setupStatusColor, type AgentWorkspaceContextLine as ContextLine } from './agent-workspace-style.ts';
|
|
7
|
+
function setupCounts(snapshot: AgentWorkspaceRuntimeSnapshot): { ready: number; recommended: number; optional: number; blocked: number } {
|
|
8
|
+
return {
|
|
9
|
+
ready: snapshot.setupChecklist.filter((item) => item.status === 'ready').length,
|
|
10
|
+
recommended: snapshot.setupChecklist.filter((item) => item.status === 'recommended').length,
|
|
11
|
+
optional: snapshot.setupChecklist.filter((item) => item.status === 'optional').length,
|
|
12
|
+
blocked: snapshot.setupChecklist.filter((item) => item.status === 'blocked').length,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function setupStatusLabel(status: AgentWorkspaceRuntimeSnapshot['setupChecklist'][number]['status']): string {
|
|
17
|
+
return status === 'ready'
|
|
18
|
+
? 'Ready'
|
|
19
|
+
: status === 'recommended'
|
|
20
|
+
? 'Recommended'
|
|
21
|
+
: status === 'blocked'
|
|
22
|
+
? 'Blocked'
|
|
23
|
+
: 'Optional';
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function formatMegabytes(bytes: number): string {
|
|
27
|
+
if (!Number.isFinite(bytes) || bytes <= 0) return '0 MB';
|
|
28
|
+
return `${Math.round(bytes / (1024 * 1024))} MB`;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function compactText(text: string, maxWidth = 104): string {
|
|
32
|
+
const normalized = text.replace(/\s+/g, ' ').trim();
|
|
33
|
+
if (normalized.length === 0) return '';
|
|
34
|
+
const firstSentence = normalized.match(/^.*?[.!?](?:\s|$)/)?.[0]?.trim();
|
|
35
|
+
const source = firstSentence && firstSentence.length <= maxWidth ? firstSentence : normalized;
|
|
36
|
+
return truncateDisplay(source, maxWidth, '...');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function setupAttentionItems(snapshot: AgentWorkspaceRuntimeSnapshot, limit: number): AgentWorkspaceRuntimeSnapshot['setupChecklist'] {
|
|
40
|
+
return [
|
|
41
|
+
...snapshot.setupChecklist.filter((item) => item.status === 'blocked'),
|
|
42
|
+
...snapshot.setupChecklist.filter((item) => item.status === 'recommended'),
|
|
43
|
+
...snapshot.setupChecklist.filter((item) => item.status === 'optional'),
|
|
44
|
+
].slice(0, limit);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function setupOverviewLines(snapshot: AgentWorkspaceRuntimeSnapshot): ContextLine[] {
|
|
48
|
+
const counts = setupCounts(snapshot);
|
|
49
|
+
const nextItems = setupAttentionItems(snapshot, 3);
|
|
50
|
+
const wizard = snapshot.setupWizard;
|
|
51
|
+
const lines: ContextLine[] = [
|
|
52
|
+
{ text: 'Onboarding', fg: PALETTE.title, bold: true },
|
|
53
|
+
{ text: `${counts.ready}/${snapshot.setupChecklist.length} ready; ${counts.recommended} recommended; ${counts.optional} optional; ${counts.blocked} blocked.`, fg: counts.blocked > 0 ? PALETTE.warn : PALETTE.info },
|
|
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 },
|
|
57
|
+
{ text: `Chat: ${snapshot.provider} / ${snapshot.modelDisplayName}.`, fg: PALETTE.info },
|
|
58
|
+
{ text: `Local: ${snapshot.localPersonaCount} personas, ${snapshot.localSkillCount} skills, ${snapshot.localRoutineCount} routines, ${snapshot.localMemoryCount} memories.`, fg: PALETTE.info },
|
|
59
|
+
];
|
|
60
|
+
if (nextItems.length > 0) {
|
|
61
|
+
const item = nextItems[0]!;
|
|
62
|
+
lines.push({
|
|
63
|
+
text: `Next: ${item.label} (${setupStatusLabel(item.status).toLowerCase()})`,
|
|
64
|
+
fg: setupStatusColor(item.status),
|
|
65
|
+
bold: item.status === 'blocked',
|
|
66
|
+
});
|
|
67
|
+
}
|
|
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
|
+
return lines;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function cockpitStatusColor(status: AssistantCockpitStatus): string {
|
|
90
|
+
return status === 'attention' ? PALETTE.warn : status === 'ready-with-optional-setup' ? PALETTE.info : PALETTE.good;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function cockpitLaneColor(state: AssistantCockpitLaneState): string {
|
|
94
|
+
return state === 'attention' ? PALETTE.warn : state === 'setup' ? PALETTE.info : PALETTE.good;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function cockpitLaneLine(lane: AssistantCockpitLane): ContextLine {
|
|
98
|
+
const state = lane.state === 'attention' ? 'Attention' : lane.state === 'setup' ? 'Setup' : 'Ready';
|
|
99
|
+
return {
|
|
100
|
+
text: `${state}: ${lane.label} - ${compactText(lane.summary, 40)}`,
|
|
101
|
+
fg: cockpitLaneColor(lane.state),
|
|
102
|
+
bold: lane.state === 'attention',
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function homeAssistantCockpitLines(snapshot: AgentWorkspaceRuntimeSnapshot): ContextLine[] {
|
|
107
|
+
const cockpit = buildAssistantCockpitFromWorkspaceSnapshot(snapshot);
|
|
108
|
+
return [
|
|
109
|
+
{
|
|
110
|
+
text: `Assistant: ${cockpit.status}; chat route ${snapshot.provider} / ${snapshot.modelDisplayName}.`,
|
|
111
|
+
fg: cockpitStatusColor(cockpit.status),
|
|
112
|
+
bold: cockpit.status === 'attention',
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
text: `Next: ${compactText(cockpit.primaryNextAction, 86)}`,
|
|
116
|
+
fg: cockpitStatusColor(cockpit.status),
|
|
117
|
+
bold: cockpit.status === 'attention',
|
|
118
|
+
},
|
|
119
|
+
...cockpit.lanes.map(cockpitLaneLine),
|
|
120
|
+
];
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function companionAccessLine(snapshot: AgentWorkspaceRuntimeSnapshot): ContextLine {
|
|
124
|
+
const access = snapshot.companionAccess;
|
|
125
|
+
const tokenState = access.tokenReadable
|
|
126
|
+
? `ready sha256:${access.tokenFingerprint ?? 'unknown'}`
|
|
127
|
+
: access.tokenPresent
|
|
128
|
+
? 'present but unreadable'
|
|
129
|
+
: 'missing';
|
|
130
|
+
const error = access.tokenError ? `; token read error ${access.tokenError}` : '';
|
|
131
|
+
return {
|
|
132
|
+
text: `Companion: ${access.surface}; token ${tokenState}; QR ${access.qrCommand}${error}.`,
|
|
133
|
+
fg: access.pairingReady ? PALETTE.good : PALETTE.warn,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function compactLocalLibraryLines(
|
|
138
|
+
title: string,
|
|
139
|
+
items: readonly AgentWorkspaceRuntimeSnapshot['localPersonas'][number][],
|
|
140
|
+
emptyText: string,
|
|
141
|
+
selectedId: string | null,
|
|
142
|
+
): ContextLine[] {
|
|
143
|
+
const lines: ContextLine[] = [];
|
|
144
|
+
if (items.length === 0) {
|
|
145
|
+
lines.push({ text: `${title}: 0. ${emptyText}`, fg: PALETTE.warn });
|
|
146
|
+
return lines;
|
|
147
|
+
}
|
|
148
|
+
const selected = items.find((item) => item.id === selectedId) ?? items[0]!;
|
|
149
|
+
const status = [
|
|
150
|
+
selected.active ? 'active' : '',
|
|
151
|
+
selected.enabled === true ? 'enabled' : selected.enabled === false ? 'disabled' : '',
|
|
152
|
+
selected.scope && selected.cls ? `${selected.scope}/${selected.cls}` : '',
|
|
153
|
+
selected.confidence !== undefined ? `${selected.confidence}%` : '',
|
|
154
|
+
selected.requirementCount !== undefined && selected.requirementCount > 0
|
|
155
|
+
? (selected.missingRequirementCount && selected.missingRequirementCount > 0 ? `needs ${selected.missingRequirementCount}/${selected.requirementCount}` : `ready ${selected.requirementCount}/${selected.requirementCount}`)
|
|
156
|
+
: '',
|
|
157
|
+
formatAgentRecordReviewState(selected.reviewState),
|
|
158
|
+
selected.startCount !== undefined ? `starts ${selected.startCount}` : '',
|
|
159
|
+
].filter(Boolean).join(', ');
|
|
160
|
+
lines.push({
|
|
161
|
+
text: `${title}: ${items.length}; selected ${selected.name}${status ? ` (${status})` : ''}.`,
|
|
162
|
+
fg: selected.reviewState === 'stale' ? PALETTE.warn : PALETTE.info,
|
|
163
|
+
bold: selected.active === true,
|
|
164
|
+
});
|
|
165
|
+
if (selected.missingRequirements && selected.missingRequirements.length > 0) {
|
|
166
|
+
lines.push({ text: `Missing setup: ${selected.missingRequirements.join(', ')}`, fg: PALETTE.warn });
|
|
167
|
+
}
|
|
168
|
+
return lines;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
type LocalRoutineItem = AgentWorkspaceRuntimeSnapshot['localRoutines'][number];
|
|
172
|
+
|
|
173
|
+
function readyRoutineItems(snapshot: AgentWorkspaceRuntimeSnapshot): readonly LocalRoutineItem[] {
|
|
174
|
+
return snapshot.localRoutines.filter((routine) =>
|
|
175
|
+
routine.enabled === true
|
|
176
|
+
&& routine.reviewState === 'reviewed'
|
|
177
|
+
&& (routine.missingRequirementCount ?? 0) === 0
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function routinesNeedingSetup(snapshot: AgentWorkspaceRuntimeSnapshot): readonly LocalRoutineItem[] {
|
|
182
|
+
return snapshot.localRoutines.filter((routine) => (routine.missingRequirementCount ?? 0) > 0);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function routinesNeedingReview(snapshot: AgentWorkspaceRuntimeSnapshot): readonly LocalRoutineItem[] {
|
|
186
|
+
return snapshot.localRoutines.filter((routine) => routine.reviewState !== 'reviewed');
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function routineNextActionLine(snapshot: AgentWorkspaceRuntimeSnapshot): ContextLine {
|
|
190
|
+
const discovered = snapshot.discoveredBehavior.routines.count;
|
|
191
|
+
const ready = readyRoutineItems(snapshot);
|
|
192
|
+
const needsSetup = routinesNeedingSetup(snapshot);
|
|
193
|
+
const needsReview = routinesNeedingReview(snapshot);
|
|
194
|
+
|
|
195
|
+
if (snapshot.localRoutineCount === 0 && discovered > 0) {
|
|
196
|
+
return { text: 'Next routine action: Discover routine files, preview one, then import it from this workspace.', fg: PALETTE.warn, bold: true };
|
|
197
|
+
}
|
|
198
|
+
if (snapshot.localRoutineCount === 0) {
|
|
199
|
+
return { text: 'Next routine action: Create routine for a repeatable main-conversation workflow.', fg: PALETTE.warn, bold: true };
|
|
200
|
+
}
|
|
201
|
+
if (needsSetup.length > 0) {
|
|
202
|
+
return { text: `Next routine action: Needs setup for ${needsSetup[0]?.id ?? 'a routine'} before it can be trusted for schedule promotion.`, fg: PALETTE.warn, bold: true };
|
|
203
|
+
}
|
|
204
|
+
if (needsReview.length > 0) {
|
|
205
|
+
return { text: `Next routine action: Review selected or inspect ${needsReview[0]?.id ?? 'a routine'} before schedule promotion.`, fg: PALETTE.warn, bold: true };
|
|
206
|
+
}
|
|
207
|
+
if (ready.length > 0 && snapshot.routineScheduleReceiptCount === 0) {
|
|
208
|
+
return { text: `Next routine action: Promote ${ready[0]?.id ?? 'a reviewed routine'} to a connected schedule when you have a real cadence.`, fg: PALETTE.good, bold: true };
|
|
209
|
+
}
|
|
210
|
+
return { text: 'Next routine action: Start selected in the main conversation, inspect receipts, or reconcile connected schedules.', fg: PALETTE.info, bold: true };
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function compactRoutineReceiptLine(snapshot: AgentWorkspaceRuntimeSnapshot): ContextLine {
|
|
214
|
+
const latest = snapshot.latestRoutineScheduleReceipt;
|
|
215
|
+
if (!latest) {
|
|
216
|
+
return {
|
|
217
|
+
text: `Promotion receipts: ${snapshot.routineScheduleReceiptCount}; none created yet.`,
|
|
218
|
+
fg: PALETTE.muted,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
return {
|
|
222
|
+
text: `Promotion receipts: ${snapshot.routineScheduleReceiptCount}; latest ${latest.status} ${latest.routineId}.`,
|
|
223
|
+
fg: latest.status === 'failed' ? PALETTE.warn : PALETTE.good,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function promptReceiptOutcomeColor(status: AgentWorkspaceRuntimeSnapshot['promptContextReceipts']['items'][number]['outcomeStatus']): string {
|
|
228
|
+
if (status === 'completed') return PALETTE.good;
|
|
229
|
+
if (status === 'error' || status === 'cancelled') return PALETTE.warn;
|
|
230
|
+
return PALETTE.info;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function promptReceiptTimelineLines(snapshot: AgentWorkspaceRuntimeSnapshot): ContextLine[] {
|
|
234
|
+
const timeline = snapshot.promptContextReceipts;
|
|
235
|
+
if (timeline.status === 'unavailable') {
|
|
236
|
+
return [
|
|
237
|
+
{ text: 'Prompt receipt timeline: unavailable in this runtime.', fg: PALETTE.warn },
|
|
238
|
+
{ text: `Next: ${compactText(timeline.next, 104)}`, fg: PALETTE.warn },
|
|
239
|
+
];
|
|
240
|
+
}
|
|
241
|
+
const lines: ContextLine[] = [
|
|
242
|
+
{
|
|
243
|
+
text: `Prompt receipt timeline: ${timeline.count} total; completed ${timeline.completedCount}; errors ${timeline.errorCount}; cancelled ${timeline.cancelledCount}; pending ${timeline.pendingCount}.`,
|
|
244
|
+
fg: timeline.errorCount > 0 || timeline.cancelledCount > 0 ? PALETTE.warn : timeline.count > 0 ? PALETTE.good : PALETTE.muted,
|
|
245
|
+
bold: timeline.errorCount > 0 || timeline.cancelledCount > 0,
|
|
246
|
+
},
|
|
247
|
+
];
|
|
248
|
+
const latest = timeline.items[0] ?? null;
|
|
249
|
+
if (!latest) {
|
|
250
|
+
lines.push({ text: `Next: ${compactText(timeline.next, 104)}`, fg: PALETTE.info });
|
|
251
|
+
return lines;
|
|
252
|
+
}
|
|
253
|
+
const turnLabel = latest.turnId ?? 'manual/no-turn';
|
|
254
|
+
const stop = latest.stopReason ? `; stop ${latest.stopReason}` : '';
|
|
255
|
+
lines.push({
|
|
256
|
+
text: `Latest prompt receipt: ${latest.outcomeStatus} turn ${turnLabel}; ${latest.activeRecords} applied / ${latest.suppressedRecords} suppressed; ${latest.approxPromptTokens} tokens${stop}.`,
|
|
257
|
+
fg: promptReceiptOutcomeColor(latest.outcomeStatus),
|
|
258
|
+
bold: latest.outcomeStatus === 'error' || latest.outcomeStatus === 'cancelled',
|
|
259
|
+
});
|
|
260
|
+
lines.push({ text: `Inspect latest prompt receipt: ${latest.inspectRoute}`, fg: PALETTE.good });
|
|
261
|
+
if (timeline.errorCount > 0) {
|
|
262
|
+
lines.push({ text: `Filter prompt receipt errors: ${timeline.filterRoutes.error}`, fg: PALETTE.warn });
|
|
263
|
+
} else if (timeline.cancelledCount > 0) {
|
|
264
|
+
lines.push({ text: `Filter cancelled prompt receipts: ${timeline.filterRoutes.cancelled}`, fg: PALETTE.warn });
|
|
265
|
+
} else if (timeline.pendingCount > 0) {
|
|
266
|
+
lines.push({ text: `Filter pending prompt receipts: ${timeline.filterRoutes.pending}`, fg: PALETTE.info });
|
|
267
|
+
}
|
|
268
|
+
for (const receipt of timeline.items.slice(0, 3)) {
|
|
269
|
+
lines.push({
|
|
270
|
+
text: `- ${receipt.receiptId}: ${receipt.outcomeStatus}; ${receipt.provider}/${receipt.model}; ${receipt.segmentCount} segment(s), ${receipt.activeRecords} active, ${receipt.suppressedRecords} suppressed.`,
|
|
271
|
+
fg: promptReceiptOutcomeColor(receipt.outcomeStatus),
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
if (latest.detail) {
|
|
275
|
+
lines.push({ text: `Latest outcome detail: ${compactText(latest.detail, 104)}`, fg: PALETTE.warn });
|
|
276
|
+
}
|
|
277
|
+
lines.push({ text: `Inspect: ${timeline.inspectRoute}`, fg: PALETTE.good });
|
|
278
|
+
return lines;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
function automationNextActionLine(snapshot: AgentWorkspaceRuntimeSnapshot): ContextLine {
|
|
282
|
+
const ready = readyRoutineItems(snapshot);
|
|
283
|
+
const needsSetup = routinesNeedingSetup(snapshot);
|
|
284
|
+
const needsReview = routinesNeedingReview(snapshot);
|
|
285
|
+
if (snapshot.routineScheduleReceiptCount > 0) {
|
|
286
|
+
return { text: 'Next automation action: Reconcile schedules to compare local receipts with the connected host.', fg: PALETTE.info, bold: true };
|
|
287
|
+
}
|
|
288
|
+
if (ready.length > 0) {
|
|
289
|
+
return { text: `Next automation action: Promote ${ready[0]?.id ?? 'a reviewed routine'} or create a one-off reminder.`, fg: PALETTE.good, bold: true };
|
|
290
|
+
}
|
|
291
|
+
if (needsSetup.length > 0) {
|
|
292
|
+
return { text: `Next automation action: Resolve routine setup gaps in ${needsSetup[0]?.id ?? 'Routines'} before promotion, or create a reminder.`, fg: PALETTE.warn, bold: true };
|
|
293
|
+
}
|
|
294
|
+
if (needsReview.length > 0) {
|
|
295
|
+
return { text: `Next automation action: Review ${needsReview[0]?.id ?? 'a routine'} in Routines before schedule promotion, or create a reminder.`, fg: PALETTE.warn, bold: true };
|
|
296
|
+
}
|
|
297
|
+
return { text: 'Next automation action: Create a reminder, or create/import a routine before recurring workflow promotion.', fg: PALETTE.warn, bold: true };
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function reviewerHandoffArtifactLine(snapshot: AgentWorkspaceRuntimeSnapshot): ContextLine {
|
|
301
|
+
const recent = snapshot.recentReviewerHandoffArtifacts;
|
|
302
|
+
if (recent.length >= 2) {
|
|
303
|
+
const newer = recent[0]!;
|
|
304
|
+
const older = recent[1]!;
|
|
305
|
+
return {
|
|
306
|
+
text: `Reviewer handoffs: ${snapshot.recentReviewerHandoffArtifactCount} saved; diff defaults ${older.id} -> ${newer.id}.`,
|
|
307
|
+
fg: PALETTE.good,
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
if (recent.length === 1) {
|
|
311
|
+
return {
|
|
312
|
+
text: `Reviewer handoffs: 1 saved (${recent[0]!.id}); create one more handoff or leave diff ids blank to list choices.`,
|
|
313
|
+
fg: PALETTE.info,
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
return {
|
|
317
|
+
text: 'Reviewer handoffs: none saved yet; create a comparison handoff before diffing or archiving.',
|
|
318
|
+
fg: PALETTE.muted,
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
function reviewPacketTimelineStatusColor(status: AgentWorkspaceRuntimeSnapshot['reviewPacketTimeline']['items'][number]['status']): string {
|
|
323
|
+
if (status === 'attention') return PALETTE.warn;
|
|
324
|
+
if (status === 'ready' || status === 'complete') return PALETTE.good;
|
|
325
|
+
return PALETTE.info;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
function reviewPacketTimelineLines(snapshot: AgentWorkspaceRuntimeSnapshot): ContextLine[] {
|
|
329
|
+
const timeline = snapshot.reviewPacketTimeline;
|
|
330
|
+
if (timeline.items.length === 0) {
|
|
331
|
+
return [
|
|
332
|
+
{
|
|
333
|
+
text: timeline.available
|
|
334
|
+
? 'Review packet timeline: no document, artifact, comparison, judgment, handoff, or archive events yet.'
|
|
335
|
+
: 'Review packet timeline: artifact history unavailable; no document-local events yet.',
|
|
336
|
+
fg: timeline.available ? PALETTE.muted : PALETTE.warn,
|
|
337
|
+
},
|
|
338
|
+
{ text: `Packet next: ${compactText(timeline.next, 110)}`, fg: timeline.available ? PALETTE.info : PALETTE.warn },
|
|
339
|
+
];
|
|
340
|
+
}
|
|
341
|
+
const visible = timeline.items.slice(0, 3);
|
|
342
|
+
return [
|
|
343
|
+
{
|
|
344
|
+
text: `Review packet timeline: ${timeline.count} event(s); showing ${visible.length} latest${timeline.available ? '' : '; artifacts unavailable'}.`,
|
|
345
|
+
fg: timeline.available ? PALETTE.info : PALETTE.warn,
|
|
346
|
+
},
|
|
347
|
+
...visible.map((event): ContextLine => ({
|
|
348
|
+
text: `Packet ${event.kind}: ${compactText(`${event.label} - ${event.detail}`, 116)}`,
|
|
349
|
+
fg: reviewPacketTimelineStatusColor(event.status),
|
|
350
|
+
bold: event.status === 'attention',
|
|
351
|
+
})),
|
|
352
|
+
{ text: `Packet next: ${compactText(timeline.next, 110)}`, fg: timeline.items.some((event) => event.status === 'attention') ? PALETTE.warn : PALETTE.good },
|
|
353
|
+
];
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
function reviewerReadinessBadgeColor(status: AgentWorkspaceRuntimeSnapshot['reviewerReadinessBadge']['status']): string {
|
|
357
|
+
if (status === 'ready') return PALETTE.good;
|
|
358
|
+
if (status === 'attention') return PALETTE.warn;
|
|
359
|
+
return PALETTE.warn;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
function reviewerReadinessBadgeLabel(status: AgentWorkspaceRuntimeSnapshot['reviewerReadinessBadge']['status']): string {
|
|
363
|
+
if (status === 'ready') return 'ready';
|
|
364
|
+
if (status === 'attention') return 'attention';
|
|
365
|
+
return 'setup needed';
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
function researchContractColor(status: string): string {
|
|
369
|
+
if (status === 'ready-with-confirmation' || status === 'visual-report-packet-ready') return PALETTE.good;
|
|
370
|
+
if (status === 'needs-review') return PALETTE.warn;
|
|
371
|
+
return PALETTE.info;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
export function reviewerReadinessContextLines(editor: AgentWorkspaceLocalEditor, snapshot: AgentWorkspaceRuntimeSnapshot | null): ContextLine[] {
|
|
375
|
+
if (!snapshot) return [];
|
|
376
|
+
if (
|
|
377
|
+
editor.kind !== 'document-export'
|
|
378
|
+
&& editor.kind !== 'model-compare-export'
|
|
379
|
+
&& editor.kind !== 'model-compare-apply'
|
|
380
|
+
) {
|
|
381
|
+
return [];
|
|
382
|
+
}
|
|
383
|
+
const badge = snapshot.reviewerReadinessBadge;
|
|
384
|
+
const reportKind = editor.kind === 'model-compare-export'
|
|
385
|
+
? editor.fields.find((field) => field.id === 'reportKind')?.value.trim().toLowerCase()
|
|
386
|
+
: '';
|
|
387
|
+
const scope = editor.kind === 'document-export'
|
|
388
|
+
? 'Document export'
|
|
389
|
+
: editor.kind === 'model-compare-apply'
|
|
390
|
+
? 'Route apply'
|
|
391
|
+
: reportKind === 'archive' || reportKind === 'handoffarchive'
|
|
392
|
+
? 'Handoff archive'
|
|
393
|
+
: reportKind === 'handoff'
|
|
394
|
+
? 'Reviewer handoff'
|
|
395
|
+
: 'Compare export';
|
|
396
|
+
return [
|
|
397
|
+
{
|
|
398
|
+
text: `${scope} readiness: ${reviewerReadinessBadgeLabel(badge.status)} - ${badge.summary}`,
|
|
399
|
+
fg: reviewerReadinessBadgeColor(badge.status),
|
|
400
|
+
bold: badge.status !== 'ready',
|
|
401
|
+
},
|
|
402
|
+
{
|
|
403
|
+
text: `Preflight next: ${compactText(badge.next, 110)}`,
|
|
404
|
+
fg: badge.status === 'ready' ? PALETTE.good : PALETTE.info,
|
|
405
|
+
},
|
|
406
|
+
];
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
export function snapshotLines(workspace: AgentWorkspace, category: AgentWorkspaceCategory, snapshot: AgentWorkspaceRuntimeSnapshot | null): ContextLine[] {
|
|
410
|
+
if (!snapshot) return [{ text: 'Runtime context is not loaded yet.', fg: PALETTE.warn }];
|
|
411
|
+
const base: ContextLine[] = [];
|
|
412
|
+
if (category.id === 'home') {
|
|
413
|
+
base.push(
|
|
414
|
+
...homeAssistantCockpitLines(snapshot),
|
|
415
|
+
);
|
|
416
|
+
} else if (category.id === 'setup') {
|
|
417
|
+
base.push(
|
|
418
|
+
...setupOverviewLines(snapshot),
|
|
419
|
+
);
|
|
420
|
+
} else if (category.id === 'account-model') {
|
|
421
|
+
base.push(
|
|
422
|
+
{ text: `Chat route: ${snapshot.provider} / ${snapshot.modelDisplayName}`, fg: PALETTE.info },
|
|
423
|
+
{ text: `Subscriptions: ${snapshot.activeSubscriptionCount} active; ${snapshot.pendingSubscriptionCount} pending; ${snapshot.availableSubscriptionProviderCount} available.`, fg: snapshot.activeSubscriptionCount > 0 ? PALETTE.good : snapshot.pendingSubscriptionCount > 0 ? PALETTE.warn : PALETTE.muted },
|
|
424
|
+
{ text: `Embedding: ${snapshot.embeddingProvider}; reasoning ${snapshot.reasoningEffort}.`, fg: PALETTE.info },
|
|
425
|
+
{ text: `Helper: ${snapshot.helperEnabled ? 'enabled' : 'disabled'}; Tool LLM: ${snapshot.toolLlmEnabled ? 'enabled' : 'disabled'}.`, fg: snapshot.helperEnabled || snapshot.toolLlmEnabled ? PALETTE.good : PALETTE.muted },
|
|
426
|
+
{ text: 'Route readiness: scores, missing signals, pinned state, and safe route keys via models action:"status".', fg: PALETTE.good },
|
|
427
|
+
{ text: 'Local cookbook: Ollama first, llama.cpp offline, vLLM for GPU throughput.', fg: PALETTE.good },
|
|
428
|
+
{ text: 'Local servers: endpoint map, model-list smoke checks, and refresh routes before benchmarks.', fg: PALETTE.good },
|
|
429
|
+
{ text: 'Benchmark evidence: run local compare, review saved judgments, then apply routes separately.', fg: PALETTE.info },
|
|
430
|
+
{ 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 },
|
|
431
|
+
);
|
|
432
|
+
} else if (category.id === 'assistant-behavior') {
|
|
433
|
+
base.push(
|
|
434
|
+
{ text: `Interaction: ${snapshot.hitlMode}; guidance ${snapshot.guidanceMode}; history ${snapshot.saveHistory ? 'saved' : 'off'}.`, fg: PALETTE.info },
|
|
435
|
+
{ text: `Context: compact at ${snapshot.autoCompactThreshold}; stale warnings ${snapshot.staleContextWarnings ? 'on' : 'off'}.`, fg: PALETTE.info },
|
|
436
|
+
{ text: `Reasoning display: thinking ${snapshot.showThinking ? 'on' : 'off'}; summaries ${snapshot.showReasoningSummary ? 'on' : 'off'}.`, fg: PALETTE.muted },
|
|
437
|
+
);
|
|
438
|
+
} else if (category.id === 'tools-permissions') {
|
|
439
|
+
base.push(
|
|
440
|
+
{ text: `Permission mode: ${snapshot.permissionMode}.`, fg: snapshot.permissionMode === 'allow-all' ? PALETTE.warn : PALETTE.info },
|
|
441
|
+
{ 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 },
|
|
442
|
+
{ text: `Artifact limit ${formatMegabytes(snapshot.artifactMaxBytes)}; raw prompt telemetry ${snapshot.rawPromptTelemetry ? 'on' : 'off'}.`, fg: snapshot.rawPromptTelemetry ? PALETTE.warn : PALETTE.muted },
|
|
443
|
+
{ text: `MCP servers: ${snapshot.mcpConnectedServerCount}/${snapshot.mcpServerCount} connected; quarantined ${snapshot.mcpQuarantinedServerCount}.`, fg: snapshot.mcpQuarantinedServerCount > 0 ? PALETTE.warn : PALETTE.info },
|
|
444
|
+
{ text: 'MCP and secret setup use forms; selecting a row does not run arbitrary tools.', fg: PALETTE.good },
|
|
445
|
+
);
|
|
446
|
+
} else if (category.id === 'onboarding-display') {
|
|
447
|
+
base.push(
|
|
448
|
+
{ text: `Theme: ${snapshot.theme}; streaming ${snapshot.stream ? 'on' : 'off'}; line numbers ${snapshot.lineNumbers}.`, fg: PALETTE.info },
|
|
449
|
+
{ text: `Messages: operational ${snapshot.operationalMessages}; system ${snapshot.systemMessages}.`, fg: PALETTE.info },
|
|
450
|
+
{ text: `Release channel: ${snapshot.releaseChannel}.`, fg: PALETTE.muted },
|
|
451
|
+
);
|
|
452
|
+
} else if (category.id === 'onboarding-channels') {
|
|
453
|
+
const enabledCount = snapshot.channels.filter((channel) => channel.enabled).length;
|
|
454
|
+
const readyCount = snapshot.channels.filter((channel) => channel.ready).length;
|
|
455
|
+
const needsConfig = snapshot.channels.filter((channel) => channel.setupState === 'needs-config');
|
|
456
|
+
const needsTarget = snapshot.channels.filter((channel) => channel.setupState === 'needs-target');
|
|
457
|
+
const guide = snapshot.channelSetupGuide;
|
|
458
|
+
base.push(
|
|
459
|
+
{ text: `Channels: ${readyCount}/${snapshot.channels.length} ready; ${enabledCount} enabled.`, fg: enabledCount > 0 ? PALETTE.info : PALETTE.muted },
|
|
460
|
+
{ text: `Needs config: ${needsConfig.length}; needs target: ${needsTarget.length}.`, fg: needsConfig.length > 0 || needsTarget.length > 0 ? PALETTE.warn : PALETTE.good },
|
|
461
|
+
{ text: `Setup guide: ${guide.progressLabel}; ${guide.currentChannelLabel ?? 'choose a channel'}.`, fg: guide.status === 'ready' ? PALETTE.good : PALETTE.warn },
|
|
462
|
+
{ text: 'Enable only the channels you want; hidden channel fields appear after the channel is enabled.', fg: PALETTE.good },
|
|
463
|
+
);
|
|
464
|
+
} else if (category.id === 'onboarding-voice-media') {
|
|
465
|
+
const readiness = snapshot.voiceMediaReadiness;
|
|
466
|
+
base.push(
|
|
467
|
+
{ text: `Voice: ${snapshot.voiceSurfaceEnabled ? 'enabled' : 'disabled'}; TTS ${snapshot.ttsProvider}; voice ${snapshot.ttsVoice}.`, fg: snapshot.voiceSurfaceEnabled ? PALETTE.good : PALETTE.info },
|
|
468
|
+
{ text: `Media readiness: ${readiness.readyMediaProviderCount}/${snapshot.mediaProviderCount}; generation providers ${snapshot.mediaGenerationProviderCount}.`, fg: readiness.readyMediaProviderCount > 0 ? PALETTE.good : PALETTE.muted },
|
|
469
|
+
{ text: `Telephony channel: ${snapshot.channels.find((channel) => channel.id === 'telephony')?.setupState ?? 'disabled'}.`, fg: PALETTE.info },
|
|
470
|
+
);
|
|
471
|
+
} else if (category.id === 'onboarding-context') {
|
|
472
|
+
const vibe = snapshot.vibe;
|
|
473
|
+
const projectContext = snapshot.projectContext;
|
|
474
|
+
base.push(
|
|
475
|
+
{ text: `Local context: ${snapshot.localMemoryCount} memories, ${snapshot.localNoteCount} notes, ${snapshot.localPersonaCount} personas.`, fg: PALETTE.info },
|
|
476
|
+
{ text: `Skills: ${snapshot.enabledSkillCount}/${snapshot.localSkillCount} enabled; routines ${snapshot.enabledRoutineCount}/${snapshot.localRoutineCount} enabled.`, fg: PALETTE.info },
|
|
477
|
+
{ text: `Discovered files: personas ${snapshot.discoveredBehavior.personas.count}, skills ${snapshot.discoveredBehavior.skills.count}, routines ${snapshot.discoveredBehavior.routines.count}.`, fg: PALETTE.muted },
|
|
478
|
+
{ 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
|
+
{ 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
|
+
...promptReceiptTimelineLines(snapshot),
|
|
481
|
+
{ text: 'Context routes: context prompt/files/file/receipt, /vibe status.', fg: PALETTE.good },
|
|
482
|
+
);
|
|
483
|
+
} else if (category.id === 'onboarding-automation') {
|
|
484
|
+
base.push(
|
|
485
|
+
{ text: `Automation: ${snapshot.automationEnabled ? 'enabled' : 'disabled'}; max ${snapshot.automationMaxConcurrentRuns} concurrent; history ${snapshot.automationRunHistoryLimit}.`, fg: snapshot.automationEnabled ? PALETTE.good : PALETTE.muted },
|
|
486
|
+
{ text: `Timeout ${snapshot.automationDefaultTimeoutMs} ms; catch-up ${snapshot.automationCatchUpWindowMinutes} min; cooldown ${snapshot.automationFailureCooldownMs} ms.`, fg: PALETTE.info },
|
|
487
|
+
{ text: `Delete one-shot jobs after success: ${snapshot.automationDeleteAfterRun ? 'yes' : 'no'}.`, fg: snapshot.automationDeleteAfterRun ? PALETTE.info : PALETTE.muted },
|
|
488
|
+
);
|
|
489
|
+
} else if (category.id === 'research') {
|
|
490
|
+
const runnerContract = snapshot.researchBrowserRunnerContract;
|
|
491
|
+
const visualContract = snapshot.researchVisualReportContract;
|
|
492
|
+
base.push(
|
|
493
|
+
{ text: `Research route: ${snapshot.provider} / ${snapshot.modelDisplayName}; Knowledge: ${snapshot.knowledgeRoute}.`, fg: PALETTE.info },
|
|
494
|
+
{ text: 'Model route: research action:"briefing|plan|search|runner|runs|sources|reports|report".', fg: PALETTE.good },
|
|
495
|
+
{ text: `Browser runner contract: ${runnerContract.label}; ${compactText(runnerContract.next, 64)}`, fg: researchContractColor(runnerContract.status), bold: runnerContract.status !== 'ready-with-confirmation' },
|
|
496
|
+
{ text: `Runner requires: ${runnerContract.details.join(', ')}.`, fg: PALETTE.muted },
|
|
497
|
+
{ text: 'Briefing: one read-only next-action queue with confirmed routes.', fg: PALETTE.good },
|
|
498
|
+
{ text: `Research runs: ${snapshot.researchRunRunningCount} running; ${snapshot.researchRunPausedCount} paused; ${snapshot.researchRunBlockedCount} blocked; ${snapshot.researchRunPlannedCount} planned.`, fg: snapshot.researchRunRunningCount > 0 || snapshot.researchRunBlockedCount > 0 ? PALETTE.warn : snapshot.researchRunPausedCount > 0 || snapshot.researchRunPlannedCount > 0 ? PALETTE.info : PALETTE.muted },
|
|
499
|
+
{ text: `Source queue: ${snapshot.researchSourceCandidateCount} candidate; ${snapshot.researchSourceReviewedCount} reviewed; ${snapshot.researchSourceRejectedCount} rejected; ${snapshot.researchSourceUsedCount} used.`, fg: snapshot.researchSourceCandidateCount > 0 ? PALETTE.warn : snapshot.researchSourceReviewedCount > 0 ? PALETTE.good : PALETTE.muted },
|
|
500
|
+
{ text: `Visual report contract: ${visualContract.label}; ${compactText(visualContract.next, 64)}`, fg: researchContractColor(visualContract.status), bold: visualContract.status !== 'visual-report-packet-ready' },
|
|
501
|
+
{ text: `Report requires: ${visualContract.details.join(', ')}.`, fg: PALETTE.muted },
|
|
502
|
+
{ text: 'Web and URL inspection stay read-only until the user confirms source ingest.', fg: PALETTE.good },
|
|
503
|
+
);
|
|
504
|
+
} else if (category.id === 'personal-ops') {
|
|
505
|
+
const ready = readyRoutineItems(snapshot);
|
|
506
|
+
const readyChannels = snapshot.channels.filter((channel) => channel.ready).length;
|
|
507
|
+
const enabledChannels = snapshot.channels.filter((channel) => channel.enabled).length;
|
|
508
|
+
const configuredTargets = snapshot.channels.filter((channel) => channel.defaultTarget === 'configured').length;
|
|
509
|
+
base.push(
|
|
510
|
+
{ text: `Personal Ops: notes ${snapshot.localNoteCount}; routines ${snapshot.localRoutineCount}/${snapshot.enabledRoutineCount}; schedule-ready ${ready.length}.`, fg: PALETTE.info },
|
|
511
|
+
{ text: 'Daily brief: plan inbox, agenda, tasks, reminders, routines, delivery, notes, and autonomy before live reads or effects.', fg: PALETTE.good },
|
|
512
|
+
{ text: `Tasks: work plan and host task inspection; reminders via confirmed schedules; receipts ${snapshot.routineScheduleReceiptCount}.`, fg: PALETTE.good },
|
|
513
|
+
{ text: 'Review queue: saved inbox threads/calendar events, refresh routes, and follow-up boundaries stay in one read-only list.', fg: PALETTE.good },
|
|
514
|
+
{ text: 'Autonomy queue: inspect owners, status, and cancel/recovery routes before adding background work.', fg: PALETTE.good },
|
|
515
|
+
{ text: `Delivery: ${readyChannels}/${snapshot.channels.length} channels ready; ${enabledChannels} enabled; ${configuredTargets} configured target(s).`, fg: readyChannels > 0 ? PALETTE.good : PALETTE.warn },
|
|
516
|
+
{ text: 'Email/calendar: connector setup needed before inbox triage or agenda workflows are first-class.', fg: PALETTE.warn },
|
|
517
|
+
{ text: 'Model route: personal_ops action:"briefing|status|queue|intake|lane|read".', fg: PALETTE.muted },
|
|
518
|
+
);
|
|
519
|
+
} else if (category.id === 'artifacts') {
|
|
520
|
+
const mediaReady = snapshot.voiceMediaReadiness.readyMediaProviderCount;
|
|
521
|
+
base.push(
|
|
522
|
+
{ text: `Chat: ${snapshot.provider} / ${snapshot.modelDisplayName}; Knowledge: ${snapshot.knowledgeRoute}`, fg: PALETTE.info },
|
|
523
|
+
{ text: `Media: ${mediaReady}/${snapshot.mediaProviderCount} ready; generation ${snapshot.mediaGenerationProviderCount}.`, fg: mediaReady > 0 ? PALETTE.good : PALETTE.warn },
|
|
524
|
+
reviewerHandoffArtifactLine(snapshot),
|
|
525
|
+
{ text: 'Files: attach, export, inspect, ingest reviewed sources, or generate media.', fg: PALETTE.good },
|
|
526
|
+
{ text: 'Knowledge ingest and media generation require explicit actions.', fg: PALETTE.warn },
|
|
527
|
+
);
|
|
528
|
+
} else if (category.id === 'channels') {
|
|
529
|
+
const enabledCount = snapshot.channels.filter((channel) => channel.enabled).length;
|
|
530
|
+
const readyCount = snapshot.channels.filter((channel) => channel.ready).length;
|
|
531
|
+
const configuredDefaults = snapshot.channels.filter((channel) => channel.defaultTarget === 'configured').length;
|
|
532
|
+
const guide = snapshot.channelSetupGuide;
|
|
533
|
+
const currentGuideStep = guide.steps.find((step) => step.status === 'current') ?? null;
|
|
534
|
+
base.push(
|
|
535
|
+
{ text: `API: ${snapshot.runtimeBaseUrl}`, fg: PALETTE.info },
|
|
536
|
+
companionAccessLine(snapshot),
|
|
537
|
+
{ text: `Channels: ${readyCount}/${snapshot.channels.length} ready; ${enabledCount} enabled; ${configuredDefaults} target(s).`, fg: PALETTE.info },
|
|
538
|
+
{ text: `Setup guide: ${guide.progressLabel}; ${guide.currentChannelLabel ?? 'choose a channel'}.`, fg: guide.status === 'ready' ? PALETTE.good : PALETTE.warn },
|
|
539
|
+
{ text: `Next: ${currentGuideStep ? `${currentGuideStep.label} - ${compactText(currentGuideStep.userRoute)}` : 'All enabled channels ready.'}`, fg: currentGuideStep ? PALETTE.warn : PALETTE.good },
|
|
540
|
+
{ text: 'Guide checks setup schema, accounts, allowlist policy, live status, and explicit test sends.', fg: PALETTE.good },
|
|
541
|
+
{ text: 'Triage: /channels triage shows blockers, delivery retries, surface messages, route bindings, and receipts.', fg: PALETTE.good },
|
|
542
|
+
{ text: 'Secrets hidden; sends require explicit action.', fg: PALETTE.warn },
|
|
543
|
+
);
|
|
544
|
+
} else if (category.id === 'knowledge') {
|
|
545
|
+
base.push(
|
|
546
|
+
{ text: `Route: ${snapshot.knowledgeRoute}; isolation ${snapshot.knowledgeIsolation}.`, fg: PALETTE.info },
|
|
547
|
+
{ text: 'Ask/search, ingest, review, reindex, and reports stay Agent-owned.', fg: PALETTE.good },
|
|
548
|
+
{ text: 'Ingest requires explicit confirmation.', fg: PALETTE.warn },
|
|
549
|
+
);
|
|
550
|
+
} else if (category.id === 'documents') {
|
|
551
|
+
const mediaReady = snapshot.voiceMediaReadiness.readyMediaProviderCount;
|
|
552
|
+
base.push(
|
|
553
|
+
{ text: `Document route: ${snapshot.provider} / ${snapshot.modelDisplayName}; Knowledge: ${snapshot.knowledgeRoute}`, fg: PALETTE.info },
|
|
554
|
+
{ text: `Files: attach, paste, source ingest, export-to-file/package/ZIP; artifact limit ${formatMegabytes(snapshot.artifactMaxBytes)}.`, fg: PALETTE.good },
|
|
555
|
+
{ text: `Media artifacts: ${mediaReady}/${snapshot.mediaProviderCount} providers ready; generation ${snapshot.mediaGenerationProviderCount}.`, fg: mediaReady > 0 ? PALETTE.good : PALETTE.warn },
|
|
556
|
+
reviewerHandoffArtifactLine(snapshot),
|
|
557
|
+
{ text: 'Model route: agent_harness mode:"document_ops" or document_ops_lane.', fg: PALETTE.muted },
|
|
558
|
+
...reviewPacketTimelineLines(snapshot),
|
|
559
|
+
{ text: `Packet wizard: ${snapshot.reviewPacketWizard.completedSteps}/${snapshot.reviewPacketWizard.totalSteps} done; ${snapshot.reviewPacketWizard.currentStepLabel ? `current ${snapshot.reviewPacketWizard.currentStepLabel}` : snapshot.reviewPacketWizard.status}.`, fg: snapshot.reviewPacketWizard.status === 'complete' ? PALETTE.good : snapshot.reviewPacketWizard.status === 'blocked' ? PALETTE.warn : PALETTE.info },
|
|
560
|
+
{ text: `Packet defaults: ${snapshot.reviewPacketDefaults.summary}.`, fg: snapshot.reviewPacketDefaults.documentId || snapshot.reviewPacketDefaults.comparisonArtifactId || snapshot.reviewPacketDefaults.handoffArtifactId ? PALETTE.info : PALETTE.muted },
|
|
561
|
+
...(snapshot.reviewPacketDefaults.reviewPacketPresetLineage
|
|
562
|
+
? [{ text: `Preset lineage: ${compactText(snapshot.reviewPacketDefaults.reviewPacketPresetLineage.summary, 128)}.`, fg: snapshot.reviewPacketDefaults.reviewPacketPresetLineage.refreshed ? PALETTE.good : PALETTE.muted }]
|
|
563
|
+
: []),
|
|
564
|
+
{ text: 'Versioned drafts, review comments, AI suggestion review, artifact attachment/insertion, artifact browser, and Knowledge promotion are available.', fg: PALETTE.good },
|
|
565
|
+
{ text: 'Compare: reuse, review/side-by-side/judgment, analytics/synthesis, handoff diff, export/archive, and route update.', fg: PALETTE.good },
|
|
566
|
+
);
|
|
567
|
+
} else if (category.id === 'tools') {
|
|
568
|
+
base.push(
|
|
569
|
+
{ text: `MCP servers: ${snapshot.mcpConnectedServerCount}/${snapshot.mcpServerCount} connected; quarantined ${snapshot.mcpQuarantinedServerCount}; allow-all ${snapshot.mcpAllowAllServerCount}.`, fg: snapshot.mcpQuarantinedServerCount > 0 || snapshot.mcpAllowAllServerCount > 0 ? PALETTE.warn : PALETTE.info },
|
|
570
|
+
{ text: 'Add/update/reload and trust changes require confirmation.', fg: PALETTE.good },
|
|
571
|
+
{ text: 'Start: /mcp review, /mcp tools, /mcp config, Add MCP server.', fg: PALETTE.muted },
|
|
572
|
+
);
|
|
573
|
+
} else if (category.id === 'voice-media') {
|
|
574
|
+
const readiness = snapshot.voiceMediaReadiness;
|
|
575
|
+
base.push(
|
|
576
|
+
{ text: `Voice: ${readiness.readyVoiceProviderCount}/${snapshot.voiceProviderCount} ready; TTS ${snapshot.ttsProvider}; voice ${snapshot.ttsVoice}.`, fg: readiness.readyVoiceProviderCount > 0 ? PALETTE.good : PALETTE.warn },
|
|
577
|
+
{ text: `Media: ${readiness.readyMediaProviderCount}/${snapshot.mediaProviderCount} ready; generation ${snapshot.mediaGenerationProviderCount}.`, fg: readiness.readyMediaProviderCount > 0 ? PALETTE.good : PALETTE.warn },
|
|
578
|
+
{ text: `Browser: ${readiness.browserToolState}; public URL ${snapshot.browserToolPublicBaseUrl}.`, fg: snapshot.browserToolExposureEnabled ? PALETTE.warn : PALETTE.muted },
|
|
579
|
+
{ text: 'Model route: device action:"voice|status"; computer action:"plan|browser|open_browser".', fg: PALETTE.info },
|
|
580
|
+
{ text: 'Device map: pairing, mobile/PWA, notifications, browser/desktop, camera/location via device.', fg: PALETTE.info },
|
|
581
|
+
{ text: readiness.nextSteps[0] ? `Next: ${compactText(readiness.nextSteps[0])}` : 'Next: voice/media setup is ready.', fg: readiness.nextSteps.length > 0 ? PALETTE.info : PALETTE.good },
|
|
582
|
+
{ text: 'Secrets hidden; voice, browser, and media side effects require explicit action.', fg: PALETTE.warn },
|
|
583
|
+
);
|
|
584
|
+
} else if (category.id === 'profiles') {
|
|
585
|
+
const defaultProfile = snapshot.selectedRuntimeProfile
|
|
586
|
+
? `${snapshot.selectedRuntimeProfile}${snapshot.selectedRuntimeProfileExists ? '' : ' (missing)'}`
|
|
587
|
+
: '(base Agent home)';
|
|
588
|
+
base.push(
|
|
589
|
+
{ text: `Profiles: active ${snapshot.activeRuntimeProfile}; default ${defaultProfile}.`, fg: snapshot.selectedRuntimeProfileExists || !snapshot.selectedRuntimeProfile ? PALETTE.info : PALETTE.warn },
|
|
590
|
+
{ text: `Local profiles: ${snapshot.runtimeProfileCount}; starters ${snapshot.runtimeStarterTemplateCount}; custom ${snapshot.localStarterTemplateCount}.`, fg: PALETTE.info },
|
|
591
|
+
{ text: `Starter ids: ${truncateDisplay(snapshot.runtimeStarterTemplates.map((template) => template.id).join(', ') || 'none', 96, '...')}`, fg: PALETTE.muted },
|
|
592
|
+
{ text: 'Profiles isolate local Agent config, sessions, memory, personas, skills, routines, setup, and bundles.', fg: PALETTE.good },
|
|
593
|
+
);
|
|
594
|
+
} else if (category.id === 'memory') {
|
|
595
|
+
const behaviorNeedsSetup = [
|
|
596
|
+
...snapshot.localSkills,
|
|
597
|
+
...snapshot.localSkillBundles,
|
|
598
|
+
...snapshot.localRoutines,
|
|
599
|
+
].filter((item) => (item.missingRequirementCount ?? 0) > 0).length;
|
|
600
|
+
const injectedNeedsReview = [
|
|
601
|
+
...snapshot.localPersonas.filter((item) => item.active),
|
|
602
|
+
...snapshot.localSkills.filter((item) => item.enabled),
|
|
603
|
+
...snapshot.localSkillBundles.filter((item) => item.enabled),
|
|
604
|
+
...snapshot.localRoutines.filter((item) => item.enabled),
|
|
605
|
+
].filter((item) => item.reviewState !== 'reviewed').length;
|
|
606
|
+
base.push(
|
|
607
|
+
{ text: `Memory: ${snapshot.localMemoryCount}; prompt ${snapshot.localMemoryPromptActiveCount}; queue ${snapshot.localMemoryReviewQueueCount}; session ${snapshot.sessionMemoryCount}.`, fg: PALETTE.info },
|
|
608
|
+
{ text: `Notes: ${snapshot.localNoteCount}; skills ${snapshot.localSkillCount}/${snapshot.enabledSkillCount}; routines ${snapshot.localRoutineCount}/${snapshot.enabledRoutineCount}; personas ${snapshot.localPersonaCount}.`, fg: PALETTE.info },
|
|
609
|
+
{ text: `Learning curator: memory queue ${snapshot.localMemoryReviewQueueCount}; note queue ${snapshot.localNoteReviewQueueCount}; setup gaps ${behaviorNeedsSetup}; injected review ${injectedNeedsReview}.`, fg: behaviorNeedsSetup > 0 || injectedNeedsReview > 0 ? PALETTE.warn : PALETTE.good },
|
|
610
|
+
{ text: 'Prompt plan: score reviewed context, show suppressed records, and route review before behavior expands.', fg: PALETTE.good },
|
|
611
|
+
{ text: `Active persona: ${snapshot.activePersonaName}.`, fg: PALETTE.info },
|
|
612
|
+
...compactLocalLibraryLines('Agent Memory', snapshot.localMemories, 'Create one with Create memory.', workspace.selectedLocalLibraryItem('memory')?.id ?? null),
|
|
613
|
+
{ text: 'Secrets are rejected or redacted; use secret references.', fg: PALETTE.warn },
|
|
614
|
+
);
|
|
615
|
+
} else if (category.id === 'notes') {
|
|
616
|
+
base.push(
|
|
617
|
+
{ text: `Scratchpad notes: ${snapshot.localNoteCount}; review queue: ${snapshot.localNoteReviewQueueCount}`, fg: PALETTE.info },
|
|
618
|
+
...compactLocalLibraryLines('Scratchpad Notes', snapshot.localNotes, 'Create one with Create note.', workspace.selectedLocalLibraryItem('note')?.id ?? null),
|
|
619
|
+
{ text: 'Notes stay local unless promoted by explicit action.', fg: PALETTE.warn },
|
|
620
|
+
);
|
|
621
|
+
} else if (category.id === 'personas') {
|
|
622
|
+
const vibe = snapshot.vibe;
|
|
623
|
+
base.push(
|
|
624
|
+
{ 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 },
|
|
625
|
+
{ text: `Personas: ${snapshot.localPersonaCount}; active: ${snapshot.activePersonaName}`, fg: PALETTE.info },
|
|
626
|
+
...compactLocalLibraryLines('Persona Library', snapshot.localPersonas, 'Create one with Create persona.', workspace.selectedLocalLibraryItem('persona')?.id ?? null),
|
|
627
|
+
{ text: 'VIBE.md is personality; project context files are separate workspace instructions.', fg: PALETTE.good },
|
|
628
|
+
{ text: 'Personas shape the serial main-conversation assistant.', fg: PALETTE.good },
|
|
629
|
+
);
|
|
630
|
+
} else if (category.id === 'skills') {
|
|
631
|
+
base.push(
|
|
632
|
+
{ text: `Skills: ${snapshot.localSkillCount}; enabled: ${snapshot.enabledSkillCount}; bundles: ${snapshot.localSkillBundleCount}; enabled bundles: ${snapshot.enabledSkillBundleCount}; active skills: ${snapshot.activeSkillCount}`, fg: PALETTE.info },
|
|
633
|
+
...compactLocalLibraryLines('Skill Library', snapshot.localSkills, 'Create one with Create skill.', workspace.selectedLocalLibraryItem('skill')?.id ?? null),
|
|
634
|
+
...compactLocalLibraryLines('Skill Bundles', snapshot.localSkillBundles, 'Create one after adding skills.', null),
|
|
635
|
+
{ text: 'Enabled skills/bundles become operating guidance; secrets are rejected.', fg: PALETTE.warn },
|
|
636
|
+
);
|
|
637
|
+
} else if (category.id === 'routines') {
|
|
638
|
+
const ready = readyRoutineItems(snapshot);
|
|
639
|
+
const needsSetup = routinesNeedingSetup(snapshot);
|
|
640
|
+
const needsReview = routinesNeedingReview(snapshot);
|
|
641
|
+
base.push(
|
|
642
|
+
{ text: `Routines: ${snapshot.localRoutineCount}; enabled: ${snapshot.enabledRoutineCount}`, fg: PALETTE.info },
|
|
643
|
+
{ text: `Schedule-ready routines: ${ready.length}; setup gaps: ${needsSetup.length}; review needed: ${needsReview.length}`, fg: needsSetup.length > 0 || needsReview.length > 0 ? PALETTE.warn : PALETTE.good },
|
|
644
|
+
routineNextActionLine(snapshot),
|
|
645
|
+
compactRoutineReceiptLine(snapshot),
|
|
646
|
+
...compactLocalLibraryLines('Routine Library', snapshot.localRoutines, 'Create one with Create routine.', workspace.selectedLocalLibraryItem('routine')?.id ?? null),
|
|
647
|
+
{ text: 'Scheduling requires a confirmed action.', fg: PALETTE.warn },
|
|
648
|
+
);
|
|
649
|
+
} else if (category.id === 'work') {
|
|
650
|
+
const processSupervision = snapshot.processSupervision;
|
|
651
|
+
base.push(
|
|
652
|
+
{ text: 'Work plans and approvals are read or explicitly confirmed.', fg: PALETTE.info },
|
|
653
|
+
{ text: `Process supervision: ${processSupervision.status}; ${processSupervision.tracked} tracked; ${processSupervision.running} running; ${processSupervision.completed} completed.`, fg: processSupervision.running > 0 ? PALETTE.warn : processSupervision.status === 'available' ? PALETTE.good : PALETTE.warn },
|
|
654
|
+
{ text: `Process parity: stdin ${processSupervision.stdinWriteStatus}; PTY ${processSupervision.ptyStatus}; sudo ${processSupervision.sudoStatus}.`, fg: processSupervision.stdinWriteStatus === 'supported-with-confirmation' || processSupervision.ptyStatus === 'contract-discovered' ? PALETTE.info : PALETTE.warn },
|
|
655
|
+
{ text: 'Process routes: execution / capabilities / process monitor / live tail.', fg: PALETTE.good },
|
|
656
|
+
{ text: 'Autonomy queue covers work plan, host tasks, approvals, automation, schedules, routines, delegation, and delivery.', fg: PALETTE.good },
|
|
657
|
+
{ text: 'Selection alone does not approve, deny, cancel, or mutate requests.', fg: PALETTE.good },
|
|
658
|
+
{ text: 'Approval actions require id plus typed confirmation.', fg: PALETTE.warn },
|
|
659
|
+
);
|
|
660
|
+
} else if (category.id === 'automation') {
|
|
661
|
+
const ready = readyRoutineItems(snapshot);
|
|
662
|
+
base.push(
|
|
663
|
+
{ text: `Automation: ${ready.length} schedule-ready routine(s); receipts ${snapshot.routineScheduleReceiptCount}.`, fg: ready.length > 0 ? PALETTE.good : PALETTE.warn },
|
|
664
|
+
automationNextActionLine(snapshot),
|
|
665
|
+
compactRoutineReceiptLine(snapshot),
|
|
666
|
+
{ text: 'Autonomy queue: review visible schedules, runs, receipts, and cancel routes first.', fg: PALETTE.good },
|
|
667
|
+
{ text: 'Reminders and routine promotion require confirmation.', fg: PALETTE.warn },
|
|
668
|
+
);
|
|
669
|
+
} else if (category.id === 'delegate') {
|
|
670
|
+
base.push(
|
|
671
|
+
{ text: 'Build/fix/review work is handed to GoodVibes TUI.', fg: PALETTE.info },
|
|
672
|
+
{ text: `Delegated review policy: ${snapshot.delegatedReviewPolicy}`, fg: PALETTE.warn },
|
|
673
|
+
{ text: 'No coding-role Agent jobs are created here.', fg: PALETTE.good },
|
|
674
|
+
);
|
|
675
|
+
} else if (category.id === 'finish') {
|
|
676
|
+
base.push(
|
|
677
|
+
{ text: 'Apply & close marks onboarding finished for this user.', fg: PALETTE.good },
|
|
678
|
+
{ text: 'Future normal launches start in the main conversation.', fg: PALETTE.info },
|
|
679
|
+
{ text: 'Use /agent, /setup, or /onboarding to reopen this workspace later.', fg: PALETTE.muted },
|
|
680
|
+
);
|
|
681
|
+
}
|
|
682
|
+
if (snapshot.warnings.length > 0) {
|
|
683
|
+
base.push({ text: `Warnings: ${snapshot.warnings.map((warning) => compactText(warning, 60)).join('; ')}`, fg: PALETTE.warn });
|
|
684
|
+
}
|
|
685
|
+
return base;
|
|
686
|
+
}
|