@pellux/goodvibes-agent 0.1.117 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -4
- package/README.md +35 -14
- package/bin/goodvibes-agent.ts +16 -2
- package/dist/package/main.js +176093 -171065
- package/docs/README.md +11 -5
- package/docs/channels-remote-and-api.md +50 -0
- package/docs/connected-host.md +3 -3
- package/docs/getting-started.md +29 -15
- package/docs/knowledge-artifacts-and-multimodal.md +91 -0
- package/docs/project-planning.md +79 -0
- package/docs/providers-and-routing.md +46 -0
- package/docs/release-and-publishing.md +44 -9
- package/docs/tools-and-commands.md +123 -0
- package/docs/voice-and-live-tts.md +51 -0
- package/package.json +2 -5
- package/src/agent/channel-delivery.ts +201 -0
- package/src/agent/media-generation.ts +159 -0
- package/src/agent/memory-prompt.ts +0 -1
- package/src/agent/note-registry.ts +329 -0
- package/src/agent/operator-actions.ts +343 -0
- package/src/agent/persona-registry.ts +15 -14
- package/src/agent/record-labels.ts +107 -0
- package/src/agent/reminder-schedule-format.ts +33 -24
- package/src/agent/reminder-schedule.ts +26 -25
- package/src/agent/routine-registry.ts +13 -12
- package/src/agent/routine-schedule-args.ts +2 -1
- package/src/agent/routine-schedule-format.ts +77 -53
- package/src/agent/routine-schedule-promotion.ts +34 -32
- package/src/agent/routine-schedule-receipts.ts +28 -26
- package/src/agent/runtime-profile-starters.ts +2 -2
- package/src/agent/runtime-profile.ts +18 -17
- package/src/agent/skill-registry.ts +25 -24
- package/src/cli/agent-knowledge-args.ts +5 -1
- package/src/cli/agent-knowledge-command.ts +39 -33
- package/src/cli/agent-knowledge-format.ts +80 -67
- package/src/cli/agent-knowledge-methods.ts +1 -1
- package/src/cli/agent-knowledge-runtime.ts +32 -26
- package/src/cli/bundle-command.ts +13 -8
- package/src/cli/config-overrides.ts +37 -36
- package/src/cli/external-runtime.ts +10 -4
- package/src/cli/help.ts +29 -11
- package/src/cli/local-library-command.ts +159 -73
- package/src/cli/management-commands.ts +98 -62
- package/src/cli/management.ts +52 -26
- package/src/cli/memory-command.ts +66 -32
- package/src/cli/parser.ts +37 -24
- package/src/cli/profiles-command.ts +52 -35
- package/src/cli/provider-auth-routes.ts +2 -1
- package/src/cli/routines-command.ts +59 -39
- package/src/cli/service-posture.ts +6 -6
- package/src/cli/status.ts +46 -121
- package/src/core/conversation-message-snapshot.ts +131 -0
- package/src/input/agent-workspace-activation.ts +33 -7
- package/src/input/agent-workspace-basic-command-editor-submission.ts +7 -3
- package/src/input/agent-workspace-basic-command-editors.ts +30 -10
- package/src/input/agent-workspace-categories.ts +276 -64
- package/src/input/agent-workspace-channel-command-editor-submission.ts +34 -0
- package/src/input/agent-workspace-channel-command-editors.ts +23 -5
- package/src/input/agent-workspace-channels.ts +35 -2
- package/src/input/agent-workspace-command-editor.ts +18 -2
- package/src/input/agent-workspace-config-reader.ts +16 -0
- package/src/input/agent-workspace-delegation-editor-submission.ts +1 -1
- package/src/input/agent-workspace-editors.ts +140 -2
- package/src/input/agent-workspace-knowledge-query-editor.ts +1 -1
- package/src/input/agent-workspace-knowledge-url-editor.ts +4 -11
- package/src/input/agent-workspace-learned-behavior.ts +2 -2
- package/src/input/agent-workspace-library-command-editor-submission.ts +1 -1
- package/src/input/agent-workspace-library-command-editors.ts +2 -2
- package/src/input/agent-workspace-local-operations.ts +218 -0
- package/src/input/agent-workspace-local-selection.ts +75 -0
- package/src/input/agent-workspace-media-command-editor-submission.ts +62 -0
- package/src/input/agent-workspace-media-command-editors.ts +27 -0
- package/src/input/agent-workspace-memory-command-editors.ts +1 -1
- package/src/input/agent-workspace-memory-editor.ts +2 -2
- package/src/input/agent-workspace-navigation.ts +38 -2
- package/src/input/agent-workspace-notify-editor-submission.ts +16 -2
- package/src/input/agent-workspace-operations-command-editor-submission.ts +63 -1
- package/src/input/agent-workspace-operations-command-editors.ts +80 -3
- package/src/input/agent-workspace-panel-route.ts +43 -0
- package/src/input/agent-workspace-reminder-schedule-editor.ts +1 -1
- package/src/input/agent-workspace-routine-schedule-editor.ts +2 -2
- package/src/input/agent-workspace-search.ts +169 -0
- package/src/input/agent-workspace-setup.ts +22 -11
- package/src/input/agent-workspace-skill-bundle-command-editor-submission.ts +6 -6
- package/src/input/agent-workspace-skill-bundle-command-editors.ts +10 -10
- package/src/input/agent-workspace-snapshot.ts +112 -13
- package/src/input/agent-workspace-task-command-editors.ts +4 -4
- package/src/input/agent-workspace-token.ts +18 -2
- package/src/input/agent-workspace-types.ts +92 -4
- package/src/input/agent-workspace-voice-media.ts +3 -6
- package/src/input/agent-workspace-web-research-editor.ts +104 -0
- package/src/input/agent-workspace.ts +136 -208
- package/src/input/command-registry.ts +4 -1
- package/src/input/commands/agent-local-library-args.ts +52 -0
- package/src/input/commands/agent-runtime-profile-runtime.ts +45 -41
- package/src/input/commands/agent-skills-runtime.ts +87 -99
- package/src/input/commands/agent-workspace-runtime.ts +23 -7
- package/src/input/commands/brief-runtime.ts +25 -24
- package/src/input/commands/channels-runtime.ts +145 -31
- package/src/input/commands/delegation-runtime.ts +29 -23
- package/src/input/commands/experience-runtime.ts +6 -4
- package/src/input/commands/guidance-runtime.ts +4 -4
- package/src/input/commands/health-runtime.ts +140 -115
- package/src/input/commands/knowledge.ts +57 -56
- package/src/input/commands/local-provider-runtime.ts +36 -18
- package/src/input/commands/local-runtime.ts +138 -16
- package/src/input/commands/local-setup-review.ts +7 -7
- package/src/input/commands/mcp-runtime.ts +118 -50
- package/src/input/commands/notify-runtime.ts +38 -9
- package/src/input/commands/operator-actions-runtime.ts +138 -0
- package/src/input/commands/operator-runtime.ts +6 -17
- package/src/input/commands/personas-runtime.ts +49 -59
- package/src/input/commands/planning-runtime.ts +1 -1
- package/src/input/commands/platform-access-runtime.ts +29 -29
- package/src/input/commands/provider-accounts-runtime.ts +60 -39
- package/src/input/commands/qrcode-runtime.ts +45 -6
- package/src/input/commands/recall-bundle.ts +11 -11
- package/src/input/commands/recall-capture.ts +13 -11
- package/src/input/commands/recall-query.ts +29 -21
- package/src/input/commands/recall-review.ts +2 -1
- package/src/input/commands/routines-runtime.ts +63 -72
- package/src/input/commands/schedule-runtime.ts +33 -20
- package/src/input/commands/security-runtime.ts +4 -4
- package/src/input/commands/session-content.ts +80 -78
- package/src/input/commands/session-workflow.ts +132 -93
- package/src/input/commands/session.ts +3 -174
- package/src/input/commands/shell-core.ts +32 -17
- package/src/input/commands/subscription-runtime.ts +53 -179
- package/src/input/commands/tasks-runtime.ts +20 -20
- package/src/input/commands/work-plan-runtime.ts +33 -8
- package/src/input/commands.ts +2 -2
- package/src/input/feed-context-factory.ts +2 -1
- package/src/input/file-picker.ts +3 -2
- package/src/input/handler-command-route.ts +4 -7
- package/src/input/handler-content-actions.ts +89 -1
- package/src/input/handler-feed-routes.ts +19 -12
- package/src/input/handler-feed.ts +6 -3
- package/src/input/handler-interactions.ts +7 -5
- package/src/input/handler-modal-stack.ts +3 -3
- package/src/input/handler-onboarding.ts +24 -80
- package/src/input/handler-shortcuts.ts +15 -4
- package/src/input/handler.ts +47 -17
- package/src/input/input-history.ts +5 -6
- package/src/input/keybindings.ts +22 -11
- package/src/input/onboarding/onboarding-wizard-apply.ts +13 -0
- package/src/input/onboarding/onboarding-wizard-constants.ts +1 -0
- package/src/input/onboarding/onboarding-wizard-operator-steps.ts +147 -57
- package/src/input/onboarding/onboarding-wizard-steps.ts +46 -29
- package/src/input/onboarding/onboarding-wizard-types.ts +3 -1
- package/src/input/onboarding/onboarding-wizard.ts +68 -0
- package/src/input/profile-picker-modal.ts +31 -12
- package/src/input/session-picker-modal.ts +22 -4
- package/src/input/settings-modal-behavior.ts +0 -3
- package/src/input/settings-modal-subscriptions.ts +3 -3
- package/src/input/settings-modal-types.ts +2 -13
- package/src/input/settings-modal.ts +6 -52
- package/src/input/submission-intent.ts +0 -1
- package/src/input/submission-router.ts +3 -3
- package/src/main.ts +18 -8
- package/src/panels/approval-panel.ts +8 -8
- package/src/panels/automation-control-panel.ts +2 -2
- package/src/panels/base-panel.ts +1 -1
- package/src/panels/builtin/agent.ts +1 -1
- package/src/panels/builtin/operations.ts +1 -10
- package/src/panels/builtin/session.ts +9 -9
- package/src/panels/builtin/shared.ts +2 -2
- package/src/panels/cost-tracker-panel.ts +1 -1
- package/src/panels/docs-panel.ts +5 -3
- package/src/panels/index.ts +0 -1
- package/src/panels/knowledge-panel.ts +6 -5
- package/src/panels/memory-panel.ts +7 -6
- package/src/panels/panel-list-panel.ts +36 -80
- package/src/panels/project-planning-panel.ts +18 -11
- package/src/panels/provider-account-snapshot.ts +51 -25
- package/src/panels/provider-accounts-panel.ts +33 -18
- package/src/panels/provider-health-domains.ts +45 -4
- package/src/panels/provider-health-panel.ts +5 -4
- package/src/panels/qr-panel.ts +1 -1
- package/src/panels/schedule-panel.ts +9 -17
- package/src/panels/security-panel.ts +8 -8
- package/src/panels/session-browser-panel.ts +10 -10
- package/src/panels/subscription-panel.ts +3 -3
- package/src/panels/system-messages-panel.ts +1 -1
- package/src/panels/tasks-panel.ts +20 -13
- package/src/panels/tool-inspector-panel.ts +19 -12
- package/src/panels/work-plan-panel.ts +5 -5
- package/src/planning/project-planning-coordinator.ts +1 -1
- package/src/provider-auth-route-display.ts +9 -0
- package/src/renderer/agent-workspace-style.ts +34 -0
- package/src/renderer/agent-workspace.ts +228 -52
- package/src/renderer/autocomplete-overlay.ts +25 -6
- package/src/renderer/bookmark-modal.ts +19 -4
- package/src/renderer/buffer.ts +4 -2
- package/src/renderer/context-inspector.ts +50 -13
- package/src/renderer/diff.ts +1 -1
- package/src/renderer/file-picker-overlay.ts +19 -6
- package/src/renderer/help-overlay.ts +106 -33
- package/src/renderer/history-search-overlay.ts +19 -4
- package/src/renderer/live-tail-modal.ts +27 -5
- package/src/renderer/mcp-workspace.ts +164 -50
- package/src/renderer/model-picker-overlay.ts +58 -2
- package/src/renderer/model-workspace.ts +104 -20
- package/src/renderer/process-modal.ts +27 -6
- package/src/renderer/profile-picker-modal.ts +20 -4
- package/src/renderer/search-overlay.ts +25 -5
- package/src/renderer/selection-modal-overlay.ts +46 -14
- package/src/renderer/session-picker-modal.ts +18 -1
- package/src/renderer/settings-modal-helpers.ts +2 -40
- package/src/renderer/settings-modal.ts +83 -50
- package/src/renderer/tool-call.ts +20 -11
- package/src/runtime/agent-runtime-events.ts +6 -6
- package/src/runtime/bootstrap-command-context.ts +7 -1
- package/src/runtime/bootstrap-command-parts.ts +9 -7
- package/src/runtime/bootstrap-core.ts +19 -1
- package/src/runtime/bootstrap-hook-bridge.ts +7 -18
- package/src/runtime/bootstrap-shell.ts +4 -4
- package/src/runtime/bootstrap.ts +31 -22
- package/src/runtime/connected-host-auth.ts +7 -2
- package/src/runtime/diagnostics/panels/index.ts +2 -2
- package/src/runtime/diagnostics/panels/policy.ts +7 -7
- package/src/runtime/index.ts +2 -1
- package/src/runtime/onboarding/apply-file-helpers.ts +66 -0
- package/src/runtime/onboarding/apply.ts +80 -79
- package/src/runtime/onboarding/derivation.ts +5 -8
- package/src/runtime/onboarding/snapshot.ts +0 -15
- package/src/runtime/onboarding/types.ts +8 -19
- package/src/runtime/onboarding/verify.ts +32 -10
- package/src/runtime/operator-token-cleanup.ts +1 -1
- package/src/runtime/services.ts +91 -22
- package/src/runtime/store/selectors/index.ts +3 -3
- package/src/runtime/store/state.ts +1 -4
- package/src/runtime/surface-feature-flags.ts +41 -6
- package/src/runtime/ui-read-models.ts +3 -4
- package/src/runtime/ui-services.ts +6 -6
- package/src/shell/blocking-input.ts +2 -1
- package/src/shell/ui-openers.ts +3 -13
- package/src/tools/agent-analysis-registry-policy.ts +0 -1
- package/src/tools/agent-channel-send-tool.ts +133 -0
- package/src/tools/agent-context-policy.ts +1 -1
- package/src/tools/agent-knowledge-ingest-tool.ts +405 -0
- package/src/tools/agent-knowledge-tool.ts +170 -0
- package/src/tools/agent-local-registry-tool.ts +269 -69
- package/src/tools/agent-media-generate-tool.ts +133 -0
- package/src/tools/agent-notify-tool.ts +143 -0
- package/src/tools/agent-operator-action-tool.ts +137 -0
- package/src/tools/agent-operator-briefing-tool.ts +217 -0
- package/src/tools/agent-reminder-schedule-tool.ts +237 -0
- package/src/tools/agent-tool-policy-guard.ts +8 -8
- package/src/tools/agent-work-plan-tool.ts +256 -0
- package/src/version.ts +1 -1
- package/src/input/commands/policy-dispatch.ts +0 -339
- package/src/input/commands/policy.ts +0 -13
- package/src/panels/panel-picker.ts +0 -105
- package/src/panels/policy-panel.ts +0 -308
- package/src/renderer/panel-picker-overlay.ts +0 -202
|
@@ -28,6 +28,47 @@ export interface ProviderHealthDomainInputs {
|
|
|
28
28
|
readonly session: UiSessionSnapshot;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
type ProviderHealthMcpServer = UiSecuritySnapshot['mcpServers'][number];
|
|
32
|
+
type ProviderHealthRemoteSession = UiRemoteSnapshot['supervisor']['sessions'][number];
|
|
33
|
+
type ProviderHealthStatusValue =
|
|
34
|
+
| ProviderHealthMcpServer['schemaFreshness']
|
|
35
|
+
| ProviderHealthMcpServer['trustMode']
|
|
36
|
+
| ProviderHealthRemoteSession['transportState']
|
|
37
|
+
| ProviderHealthRemoteSession['heartbeat']['status'];
|
|
38
|
+
|
|
39
|
+
function formatProviderHealthStatus(value: ProviderHealthStatusValue): string {
|
|
40
|
+
if (value === 'quarantined') return 'needs review';
|
|
41
|
+
return value.replace(/[_-]+/g, ' ');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function formatProviderHealthTrustMode(mode: ProviderHealthMcpServer['trustMode']): string {
|
|
45
|
+
if (mode === 'ask-on-risk') return 'ask on risky actions';
|
|
46
|
+
if (mode === 'allow-all') return 'allow all actions';
|
|
47
|
+
return formatProviderHealthStatus(mode);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function formatMcpServerDetail(server: ProviderHealthMcpServer): string {
|
|
51
|
+
const parts = [
|
|
52
|
+
`${server.name}: trust ${formatProviderHealthTrustMode(server.trustMode)}`,
|
|
53
|
+
`status ${formatProviderHealthStatus(server.schemaFreshness)}`,
|
|
54
|
+
];
|
|
55
|
+
if (server.quarantineReason) {
|
|
56
|
+
parts.push(`review reason ${server.quarantineReason}`);
|
|
57
|
+
}
|
|
58
|
+
return parts.join('; ');
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function formatRemoteSessionDetail(session: ProviderHealthRemoteSession): string {
|
|
62
|
+
const parts = [
|
|
63
|
+
`${session.runnerId}: transport ${formatProviderHealthStatus(session.transportState)}`,
|
|
64
|
+
`heartbeat ${formatProviderHealthStatus(session.heartbeat.status)}`,
|
|
65
|
+
];
|
|
66
|
+
if (session.lastError) {
|
|
67
|
+
parts.push(`error ${session.lastError}`);
|
|
68
|
+
}
|
|
69
|
+
return parts.join('; ');
|
|
70
|
+
}
|
|
71
|
+
|
|
31
72
|
export function buildProviderHealthDomainSummaries(
|
|
32
73
|
input: ProviderHealthDomainInputs,
|
|
33
74
|
): HealthDomainSummary[] {
|
|
@@ -66,13 +107,13 @@ export function buildProviderHealthDomainSummaries(
|
|
|
66
107
|
summary: !settings.available
|
|
67
108
|
? 'settings API unavailable'
|
|
68
109
|
: settingIssueCount > 0
|
|
69
|
-
? `${settings.conflictCount} conflicts / ${settings.recentFailureCount} failures${settings.hasStagedManagedBundle ? ' /
|
|
110
|
+
? `${settings.conflictCount} conflicts / ${settings.recentFailureCount} failures${settings.hasStagedManagedBundle ? ' / pending managed bundle' : ''}`
|
|
70
111
|
: 'settings API clean',
|
|
71
112
|
next: settingIssueCount > 0 ? '/settings' : '/config <key>',
|
|
72
113
|
details: [
|
|
73
114
|
settings.conflictCount > 0 ? `${settings.conflictCount} unresolved import conflict(s)` : '',
|
|
74
115
|
settings.recentFailureCount > 0 ? `${settings.recentFailureCount} recent sync or managed failure(s)` : '',
|
|
75
|
-
settings.hasStagedManagedBundle ? '
|
|
116
|
+
settings.hasStagedManagedBundle ? 'pending managed settings bundle awaits apply or rollback' : '',
|
|
76
117
|
settings.managedLockCount > 0 ? `${settings.managedLockCount} managed lock(s) enforced` : '',
|
|
77
118
|
].filter(Boolean),
|
|
78
119
|
nextSteps: settingIssueCount > 0
|
|
@@ -97,7 +138,7 @@ export function buildProviderHealthDomainSummaries(
|
|
|
97
138
|
|| entry.heartbeat.status !== 'fresh'
|
|
98
139
|
|| Boolean(entry.lastError))
|
|
99
140
|
.slice(0, 3)
|
|
100
|
-
.map(
|
|
141
|
+
.map(formatRemoteSessionDetail),
|
|
101
142
|
nextSteps: remote.supervisor.degradedConnections > 0
|
|
102
143
|
? ['/delegate <build/fix/review task>', '/health remote']
|
|
103
144
|
: ['/health remote'],
|
|
@@ -120,7 +161,7 @@ export function buildProviderHealthDomainSummaries(
|
|
|
120
161
|
? (security.mcpServers.length === 0 ? ['no MCP servers registered'] : ['all MCP servers are healthy'])
|
|
121
162
|
: degradedServers
|
|
122
163
|
.slice(0, 3)
|
|
123
|
-
.map(
|
|
164
|
+
.map(formatMcpServerDetail),
|
|
124
165
|
nextSteps: degradedServers.length > 0
|
|
125
166
|
? ['/mcp review', '/mcp auth-review', '/mcp repair']
|
|
126
167
|
: ['/mcp review'],
|
|
@@ -37,6 +37,7 @@ import {
|
|
|
37
37
|
resolvePrimaryScrollableSection,
|
|
38
38
|
type PanelWorkspaceSection,
|
|
39
39
|
} from './polish.ts';
|
|
40
|
+
import { formatProviderAuthRouteId } from '../provider-auth-route-display.ts';
|
|
40
41
|
|
|
41
42
|
// ---------------------------------------------------------------------------
|
|
42
43
|
// Types
|
|
@@ -646,17 +647,17 @@ export class ProviderHealthPanel extends BasePanel {
|
|
|
646
647
|
}
|
|
647
648
|
if (selectedAccount) {
|
|
648
649
|
selectedLines.push(buildKeyValueLine(width, [
|
|
649
|
-
{ label: 'route', value: selectedAccount.activeRoute, valueColor: routeColor(selectedAccount.activeRoute) },
|
|
650
|
-
{ label: 'preferred', value: selectedAccount.preferredRoute, valueColor: C.dim },
|
|
650
|
+
{ label: 'route', value: formatProviderAuthRouteId(selectedAccount.activeRoute), valueColor: routeColor(selectedAccount.activeRoute) },
|
|
651
|
+
{ label: 'preferred', value: formatProviderAuthRouteId(selectedAccount.preferredRoute), valueColor: C.dim },
|
|
651
652
|
{ label: 'freshness', value: selectedAccount.authFreshness, valueColor: freshnessColor(selectedAccount.authFreshness) },
|
|
652
653
|
], { ...DEFAULT_PANEL_PALETTE, header: C.title, headerBg: '#0f172a' }));
|
|
653
654
|
selectedLines.push(buildKeyValueLine(width, [
|
|
654
655
|
{ label: 'models', value: String(selectedAccount.modelCount), valueColor: C.value },
|
|
655
656
|
{ label: 'active', value: selectedAccount.active ? 'yes' : 'no', valueColor: selectedAccount.active ? C.online : C.dim },
|
|
656
657
|
], { ...DEFAULT_PANEL_PALETTE, header: C.title, headerBg: '#0f172a' }));
|
|
657
|
-
selectedLines.push(...buildBodyText(width, `
|
|
658
|
+
selectedLines.push(...buildBodyText(width, `Route reason: ${selectedAccount.activeRouteReason}`, { ...DEFAULT_PANEL_PALETTE, header: C.title, headerBg: '#0f172a' }, C.dim));
|
|
658
659
|
if (selectedAccount.fallbackRisk) {
|
|
659
|
-
selectedLines.push(...buildBodyText(width, `
|
|
660
|
+
selectedLines.push(...buildBodyText(width, `Routing risk: ${selectedAccount.fallbackRisk}`, { ...DEFAULT_PANEL_PALETTE, header: C.title, headerBg: '#0f172a' }, C.rateLimit));
|
|
660
661
|
}
|
|
661
662
|
if (selectedAccount.issues.length > 0) {
|
|
662
663
|
selectedLines.push(...buildBodyText(width, `Issue: ${selectedAccount.issues[0]!}`, { ...DEFAULT_PANEL_PALETTE, header: C.title, headerBg: '#0f172a' }, C.errMsg));
|
package/src/panels/qr-panel.ts
CHANGED
|
@@ -163,7 +163,7 @@ export class QrPanel extends BasePanel {
|
|
|
163
163
|
);
|
|
164
164
|
lines.push(
|
|
165
165
|
buildPanelLine(width, [
|
|
166
|
-
['
|
|
166
|
+
[' Provision or repair connected-host access through the owning GoodVibes host, then reopen this panel. ', C.dim],
|
|
167
167
|
]),
|
|
168
168
|
);
|
|
169
169
|
}
|
|
@@ -80,14 +80,13 @@ function formatEveryInterval(intervalMs: number): string {
|
|
|
80
80
|
// ---------------------------------------------------------------------------
|
|
81
81
|
|
|
82
82
|
/**
|
|
83
|
-
* SchedulePanel — displays
|
|
84
|
-
* enable
|
|
83
|
+
* SchedulePanel — displays connected schedule posture with next run time and run history.
|
|
84
|
+
* It does not create, enable, disable, or run schedules from panel keypresses.
|
|
85
85
|
*/
|
|
86
86
|
export class SchedulePanel extends BasePanel {
|
|
87
87
|
private items: ViewItem[] = [];
|
|
88
88
|
private selectedIndex = 0;
|
|
89
89
|
private scrollOffset = 0;
|
|
90
|
-
private refreshTimerId: ReturnType<typeof setInterval> | null = null;
|
|
91
90
|
private readonly automationManager: ScheduleAutomationManager;
|
|
92
91
|
|
|
93
92
|
constructor(automationManager: ScheduleAutomationManager) {
|
|
@@ -102,17 +101,10 @@ export class SchedulePanel extends BasePanel {
|
|
|
102
101
|
override onActivate(): void {
|
|
103
102
|
super.onActivate();
|
|
104
103
|
this.rebuild();
|
|
105
|
-
this.refreshTimerId = this.registerTimer(setInterval(() => {
|
|
106
|
-
this.rebuild();
|
|
107
|
-
this.markDirty();
|
|
108
|
-
}, 5_000));
|
|
109
104
|
}
|
|
110
105
|
|
|
111
106
|
override onDeactivate(): void {
|
|
112
|
-
|
|
113
|
-
this.clearTimer(this.refreshTimerId);
|
|
114
|
-
this.refreshTimerId = null;
|
|
115
|
-
}
|
|
107
|
+
this.scrollOffset = 0;
|
|
116
108
|
}
|
|
117
109
|
|
|
118
110
|
override onDestroy(): void {
|
|
@@ -171,11 +163,11 @@ export class SchedulePanel extends BasePanel {
|
|
|
171
163
|
}
|
|
172
164
|
case 'return':
|
|
173
165
|
case ' ': {
|
|
174
|
-
this.setError('Schedule mutation is read-only in GoodVibes Agent;
|
|
166
|
+
this.setError('Schedule mutation is read-only in GoodVibes Agent. Schedule changes require an exact command with --yes; panel keypresses never mutate connected schedules.');
|
|
175
167
|
return true;
|
|
176
168
|
}
|
|
177
169
|
case 'r': {
|
|
178
|
-
this.setError('Schedule run is blocked in GoodVibes Agent
|
|
170
|
+
this.setError('Schedule run is blocked in GoodVibes Agent. Use /schedule run <schedule-id> --yes only when you explicitly want to run that connected schedule.');
|
|
179
171
|
return true;
|
|
180
172
|
}
|
|
181
173
|
case 'R': {
|
|
@@ -205,7 +197,7 @@ export class SchedulePanel extends BasePanel {
|
|
|
205
197
|
lines: buildEmptyState(
|
|
206
198
|
width,
|
|
207
199
|
' No scheduled tasks',
|
|
208
|
-
'Schedule mutation and run controls are blocked
|
|
200
|
+
'Schedule mutation and run controls are blocked. Use /schedule list for read-only history, or exact --yes commands for connected schedule actions.',
|
|
209
201
|
[],
|
|
210
202
|
DEFAULT_PANEL_PALETTE,
|
|
211
203
|
),
|
|
@@ -213,7 +205,7 @@ export class SchedulePanel extends BasePanel {
|
|
|
213
205
|
],
|
|
214
206
|
footerLines: [
|
|
215
207
|
...(this.renderErrorLine(width) ? [this.renderErrorLine(width)!] : []),
|
|
216
|
-
buildPanelLine(width, [[' Up/Down', DEFAULT_PANEL_PALETTE.info], [' navigate', DEFAULT_PANEL_PALETTE.dim], [' R', DEFAULT_PANEL_PALETTE.info], [' refresh', DEFAULT_PANEL_PALETTE.dim], ['
|
|
208
|
+
buildPanelLine(width, [[' Up/Down', DEFAULT_PANEL_PALETTE.info], [' navigate', DEFAULT_PANEL_PALETTE.dim], [' R', DEFAULT_PANEL_PALETTE.info], [' refresh', DEFAULT_PANEL_PALETTE.dim], [' no keypress mutations', DEFAULT_PANEL_PALETTE.warn]]),
|
|
217
209
|
],
|
|
218
210
|
palette: DEFAULT_PANEL_PALETTE,
|
|
219
211
|
});
|
|
@@ -236,7 +228,7 @@ export class SchedulePanel extends BasePanel {
|
|
|
236
228
|
intro: 'Review recurring scheduled tasks, next run timing, recent history, and enablement state.',
|
|
237
229
|
footerLines: [
|
|
238
230
|
...(this.renderErrorLine(width) ? [this.renderErrorLine(width)!] : []),
|
|
239
|
-
buildPanelLine(width, [[' Up/Down', DEFAULT_PANEL_PALETTE.info], [' navigate', DEFAULT_PANEL_PALETTE.dim], [' R', DEFAULT_PANEL_PALETTE.info], [' refresh', DEFAULT_PANEL_PALETTE.dim], ['
|
|
231
|
+
buildPanelLine(width, [[' Up/Down', DEFAULT_PANEL_PALETTE.info], [' navigate', DEFAULT_PANEL_PALETTE.dim], [' R', DEFAULT_PANEL_PALETTE.info], [' refresh', DEFAULT_PANEL_PALETTE.dim], [' no keypress mutations', DEFAULT_PANEL_PALETTE.warn]]),
|
|
240
232
|
],
|
|
241
233
|
palette: DEFAULT_PANEL_PALETTE,
|
|
242
234
|
beforeSections: [summarySection],
|
|
@@ -260,7 +252,7 @@ export class SchedulePanel extends BasePanel {
|
|
|
260
252
|
sections,
|
|
261
253
|
footerLines: [
|
|
262
254
|
...(this.renderErrorLine(width) ? [this.renderErrorLine(width)!] : []),
|
|
263
|
-
buildPanelLine(width, [[' Up/Down', DEFAULT_PANEL_PALETTE.info], [' navigate', DEFAULT_PANEL_PALETTE.dim], [' R', DEFAULT_PANEL_PALETTE.info], [' refresh', DEFAULT_PANEL_PALETTE.dim], ['
|
|
255
|
+
buildPanelLine(width, [[' Up/Down', DEFAULT_PANEL_PALETTE.info], [' navigate', DEFAULT_PANEL_PALETTE.dim], [' R', DEFAULT_PANEL_PALETTE.info], [' refresh', DEFAULT_PANEL_PALETTE.dim], [' no keypress mutations', DEFAULT_PANEL_PALETTE.warn]]),
|
|
264
256
|
],
|
|
265
257
|
palette: DEFAULT_PANEL_PALETTE,
|
|
266
258
|
});
|
|
@@ -71,12 +71,12 @@ export class SecurityPanel extends ScrollableListPanel<TokenAuditResult> {
|
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
protected override getPalette() { return C; }
|
|
74
|
-
protected override getEmptyStateMessage() { return ' No API tokens are registered
|
|
74
|
+
protected override getEmptyStateMessage() { return ' No API tokens are registered for security review yet.'; }
|
|
75
75
|
protected override getEmptyStateActions() {
|
|
76
76
|
return [
|
|
77
|
-
{ command: '/
|
|
78
|
-
{ command: '/
|
|
79
|
-
{ command: '/mcp
|
|
77
|
+
{ command: '/secrets list', summary: 'inspect stored secret references without printing values' },
|
|
78
|
+
{ command: '/security review', summary: 'review token, policy, MCP, plugin, and incident posture' },
|
|
79
|
+
{ command: '/mcp auth-review', summary: 'inspect active MCP trust and quarantine posture' },
|
|
80
80
|
];
|
|
81
81
|
}
|
|
82
82
|
|
|
@@ -117,8 +117,8 @@ export class SecurityPanel extends ScrollableListPanel<TokenAuditResult> {
|
|
|
117
117
|
const quarantinedPlugins = snapshot.quarantinedPlugins;
|
|
118
118
|
const untrustedPlugins = snapshot.untrustedPlugins;
|
|
119
119
|
const attackPathReview = snapshot.attackPathReview;
|
|
120
|
-
const intro = 'Token
|
|
121
|
-
const footerLine = buildGuidanceLine(width, '/
|
|
120
|
+
const intro = 'Token review, policy posture, MCP attack-path review, plugin trust, and incident pressure.';
|
|
121
|
+
const footerLine = buildGuidanceLine(width, '/security review', 'review proactive policy posture before risky work starts', C);
|
|
122
122
|
|
|
123
123
|
const governanceLines: Line[] = [
|
|
124
124
|
buildPanelLine(width, [
|
|
@@ -179,7 +179,7 @@ export class SecurityPanel extends ScrollableListPanel<TokenAuditResult> {
|
|
|
179
179
|
...buildEmptyState(
|
|
180
180
|
width,
|
|
181
181
|
this.getEmptyStateMessage(),
|
|
182
|
-
'The security control room can already review policy, MCP, plugin, and incident posture, but token-specific scope and rotation
|
|
182
|
+
'The security control room can already review policy, MCP, plugin, and incident posture, but token-specific scope and rotation data has not been registered.',
|
|
183
183
|
this.getEmptyStateActions(),
|
|
184
184
|
C,
|
|
185
185
|
),
|
|
@@ -245,7 +245,7 @@ export class SecurityPanel extends ScrollableListPanel<TokenAuditResult> {
|
|
|
245
245
|
[String(Math.floor(selected.rotation.ageMs / (24 * 60 * 60 * 1000))), C.value],
|
|
246
246
|
]));
|
|
247
247
|
detailLines.push(buildPanelLine(width, [[
|
|
248
|
-
`Last
|
|
248
|
+
`Last review: ${view.lastAuditAt ? new Date(view.lastAuditAt).toISOString() : 'never'} Press r to refresh.`,
|
|
249
249
|
C.dim,
|
|
250
250
|
]]));
|
|
251
251
|
if (preflightStatus !== 'n/a') {
|
|
@@ -63,13 +63,13 @@ function formatReturnContextLines(returnContext: SessionInfo['returnContext']):
|
|
|
63
63
|
if (returnContext.activityLabel) lines.push(`activity: ${returnContext.activityLabel}`);
|
|
64
64
|
if (returnContext.statusLabel) lines.push(`status: ${returnContext.statusLabel}`);
|
|
65
65
|
if (returnContext.activeTasks || returnContext.blockedTasks || returnContext.pendingApprovals) {
|
|
66
|
-
lines.push(`tasks: active
|
|
66
|
+
lines.push(`tasks: active ${returnContext.activeTasks ?? 0}; blocked ${returnContext.blockedTasks ?? 0}; approvals ${returnContext.pendingApprovals ?? 0}`);
|
|
67
67
|
}
|
|
68
68
|
if (returnContext.remoteRunners?.length) {
|
|
69
|
-
lines.push(`remote
|
|
69
|
+
lines.push(`remote build hosts: ${returnContext.remoteRunners.join(', ')}`);
|
|
70
70
|
}
|
|
71
71
|
if (returnContext.openPanels?.length) {
|
|
72
|
-
lines.push(`
|
|
72
|
+
lines.push(`saved panels ignored: ${returnContext.openPanels.join(', ')}`);
|
|
73
73
|
}
|
|
74
74
|
return lines;
|
|
75
75
|
}
|
|
@@ -177,14 +177,14 @@ export class SessionBrowserPanel extends BasePanel {
|
|
|
177
177
|
const count = this.filtered.length;
|
|
178
178
|
const total = this.sessions.length;
|
|
179
179
|
const searchLine = this.searching
|
|
180
|
-
? ` Search
|
|
180
|
+
? ` Search ${this.searchQuery}_`
|
|
181
181
|
: this.loadError
|
|
182
|
-
? ` Error
|
|
182
|
+
? ` Error ${this.loadError}`
|
|
183
183
|
: this.deleteError
|
|
184
|
-
? ` Error
|
|
184
|
+
? ` Error ${this.deleteError}`
|
|
185
185
|
: this.searchQuery
|
|
186
|
-
? ` Filter
|
|
187
|
-
: ` / or up at top to search Enter
|
|
186
|
+
? ` Filter ${this.searchQuery} (/ or up at top to edit)`
|
|
187
|
+
: ` / or up at top to search Enter resume d delete r refresh`;
|
|
188
188
|
const statusFg = this.loadError || this.deleteError ? DEFAULT_PANEL_PALETTE.bad : this.searching ? DEFAULT_PANEL_PALETTE.info : DEFAULT_PANEL_PALETTE.dim;
|
|
189
189
|
const footerLines = [
|
|
190
190
|
buildSearchInputLine(width, '', searchLine.trimStart(), DEFAULT_PANEL_PALETTE, { active: this.searching, valueColor: statusFg }),
|
|
@@ -260,8 +260,8 @@ export class SessionBrowserPanel extends BasePanel {
|
|
|
260
260
|
buildPanelLine(width, [
|
|
261
261
|
[' Remote ', DEFAULT_PANEL_PALETTE.label],
|
|
262
262
|
[String(selected.returnContext?.remoteRunners?.length ?? 0), (selected.returnContext?.remoteRunners?.length ?? 0) > 0 ? DEFAULT_PANEL_PALETTE.info : DEFAULT_PANEL_PALETTE.dim],
|
|
263
|
-
[' Panels ', DEFAULT_PANEL_PALETTE.label],
|
|
264
|
-
[String(selected.returnContext?.openPanels?.length ?? 0), (selected.returnContext?.openPanels?.length ?? 0) > 0 ? DEFAULT_PANEL_PALETTE.
|
|
263
|
+
[' Saved Panels ', DEFAULT_PANEL_PALETTE.label],
|
|
264
|
+
[String(selected.returnContext?.openPanels?.length ?? 0), (selected.returnContext?.openPanels?.length ?? 0) > 0 ? DEFAULT_PANEL_PALETTE.warn : DEFAULT_PANEL_PALETTE.dim],
|
|
265
265
|
]),
|
|
266
266
|
...formatReturnContextLines(selected.returnContext).map((line) =>
|
|
267
267
|
buildPanelLine(width, [[' ', DEFAULT_PANEL_PALETTE.dim], [truncateDisplay(line, Math.max(0, width - 2)), DEFAULT_PANEL_PALETTE.dim]])
|
|
@@ -172,7 +172,7 @@ export class SubscriptionPanel extends ScrollableListPanel<SubscriptionRow> {
|
|
|
172
172
|
public render(width: number, height: number): Line[] {
|
|
173
173
|
this.refresh();
|
|
174
174
|
this.clampSelection();
|
|
175
|
-
const intro = 'Review provider login state, subscription-backed routing, and pending browser
|
|
175
|
+
const intro = 'Review provider login state, subscription-backed routing, and pending browser sign-ins.';
|
|
176
176
|
|
|
177
177
|
const activeCount = this.rows.filter((row) => row.subscription).length;
|
|
178
178
|
const pendingCount = this.rows.filter((row) => row.pending).length;
|
|
@@ -187,7 +187,7 @@ export class SubscriptionPanel extends ScrollableListPanel<SubscriptionRow> {
|
|
|
187
187
|
{ label: 'selected', value: (this.rows[this.selectedIndex]?.provider ?? 'none'), valueColor: this.rows[this.selectedIndex] ? C.value : C.dim },
|
|
188
188
|
{ label: 'status', value: this.rows[this.selectedIndex] ? statusOf(this.rows[this.selectedIndex]!) : 'n/a', valueColor: this.rows[this.selectedIndex] ? statusColor(statusOf(this.rows[this.selectedIndex]!)) : C.dim },
|
|
189
189
|
], C),
|
|
190
|
-
buildGuidanceLine(width, '/subscription login <provider> start --yes', 'start
|
|
190
|
+
buildGuidanceLine(width, '/subscription login <provider> start --yes', 'start browser login, then finish manually with the callback code or URL', C),
|
|
191
191
|
];
|
|
192
192
|
|
|
193
193
|
// Empty state: render posture + base empty state
|
|
@@ -205,7 +205,7 @@ export class SubscriptionPanel extends ScrollableListPanel<SubscriptionRow> {
|
|
|
205
205
|
intro,
|
|
206
206
|
sections: [{ lines: [...summaryLines, ...emptyLines] }],
|
|
207
207
|
footerLines: [
|
|
208
|
-
buildGuidanceLine(width, '/subscription login <provider> start --yes', 'start browser
|
|
208
|
+
buildGuidanceLine(width, '/subscription login <provider> start --yes', 'start browser login, then finish explicitly from the Agent command or workspace form', C),
|
|
209
209
|
buildPanelLine(width, [[' Up/Down move Enter/X sign out selected provider r refresh', C.dim]]),
|
|
210
210
|
],
|
|
211
211
|
palette: C,
|
|
@@ -145,7 +145,7 @@ export class SystemMessagesPanel extends ScrollableListPanel<SystemMessageEntry>
|
|
|
145
145
|
'Model switches, scan notices, provider/system state, and other operational updates will appear here once the runtime starts emitting them.',
|
|
146
146
|
[
|
|
147
147
|
{ command: '/help', summary: 'review commands and operator workflows' },
|
|
148
|
-
{ command: '/
|
|
148
|
+
{ command: '/agent', summary: 'open the Agent operator workspace' },
|
|
149
149
|
],
|
|
150
150
|
C,
|
|
151
151
|
),
|
|
@@ -46,16 +46,23 @@ function formatDuration(startedAt?: number, endedAt?: number): string {
|
|
|
46
46
|
function kindLabel(kind: RuntimeTask['kind']): string {
|
|
47
47
|
switch (kind) {
|
|
48
48
|
case 'exec': return 'exec';
|
|
49
|
-
case 'agent': return '
|
|
50
|
-
case 'acp': return '
|
|
49
|
+
case 'agent': return 'task';
|
|
50
|
+
case 'acp': return 'delegate';
|
|
51
51
|
case 'scheduler': return 'scheduler';
|
|
52
|
-
case 'daemon': return '
|
|
52
|
+
case 'daemon': return 'host';
|
|
53
53
|
case 'mcp': return 'mcp';
|
|
54
54
|
case 'plugin': return 'plugin';
|
|
55
55
|
case 'integration': return 'integration';
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
function descriptorOriginLabel(source: string | undefined): string {
|
|
60
|
+
const normalized = source?.trim();
|
|
61
|
+
if (!normalized || normalized === 'builtin/runtime') return 'runtime';
|
|
62
|
+
if (normalized === 'daemon' || normalized === 'daemon-runtime') return 'host';
|
|
63
|
+
return normalized.replace(/[-_/]+/g, ' ');
|
|
64
|
+
}
|
|
65
|
+
|
|
59
66
|
function statusColor(status: TaskLifecycleState): string {
|
|
60
67
|
switch (status) {
|
|
61
68
|
case 'queued':
|
|
@@ -137,7 +144,7 @@ export class TasksPanel extends ScrollableListPanel<RuntimeTask> {
|
|
|
137
144
|
protected override getEmptyStateMessage() { return ' No tasks recorded yet.'; }
|
|
138
145
|
protected override getEmptyStateActions() {
|
|
139
146
|
return [
|
|
140
|
-
{ command: '/
|
|
147
|
+
{ command: '/workplan', summary: 'track visible Agent work in the workspace' },
|
|
141
148
|
{ command: '/delegate <task>', summary: 'send explicit build/fix/review work to GoodVibes TUI' },
|
|
142
149
|
];
|
|
143
150
|
}
|
|
@@ -173,7 +180,7 @@ export class TasksPanel extends ScrollableListPanel<RuntimeTask> {
|
|
|
173
180
|
|
|
174
181
|
public render(width: number, height: number): Line[] {
|
|
175
182
|
this.clampSelection();
|
|
176
|
-
const intro = '
|
|
183
|
+
const intro = 'Connected-host task lifecycle, ownership, retries, and result/error details for operator visibility.';
|
|
177
184
|
const footerLines = [buildPanelLine(width, [[' Up/Down move Home/End jump', C.dim]])];
|
|
178
185
|
|
|
179
186
|
if (!this.readModel) {
|
|
@@ -184,8 +191,8 @@ export class TasksPanel extends ScrollableListPanel<RuntimeTask> {
|
|
|
184
191
|
lines: buildEmptyState(
|
|
185
192
|
width,
|
|
186
193
|
' Connected-host task state is unavailable.',
|
|
187
|
-
'Use /tasks list for
|
|
188
|
-
[{ command: '/tasks', summary: '
|
|
194
|
+
'This operator view is read-only. Use /tasks list for compact transcript output; task execution stays unchanged.',
|
|
195
|
+
[{ command: '/tasks', summary: 'review connected-host tasks without changing execution' }],
|
|
189
196
|
C,
|
|
190
197
|
),
|
|
191
198
|
}],
|
|
@@ -229,13 +236,13 @@ export class TasksPanel extends ScrollableListPanel<RuntimeTask> {
|
|
|
229
236
|
[' status ', C.label],
|
|
230
237
|
[selected.status, statusColor(selected.status)],
|
|
231
238
|
[' kind ', C.label],
|
|
232
|
-
[selected.kind, C.value],
|
|
239
|
+
[kindLabel(selected.kind), C.value],
|
|
233
240
|
[' owner ', C.label],
|
|
234
241
|
[selected.owner.slice(0, Math.max(0, width - 46)), C.dim],
|
|
235
242
|
]));
|
|
236
243
|
}
|
|
237
244
|
postureLines.push(
|
|
238
|
-
buildGuidanceLine(width, '/tasks', '
|
|
245
|
+
buildGuidanceLine(width, '/tasks', 'review connected-host task posture without changing execution', C),
|
|
239
246
|
buildGuidanceLine(width, '/delegate <task>', 'delegate explicit build/fix/review work to GoodVibes TUI when code execution is required', C),
|
|
240
247
|
);
|
|
241
248
|
|
|
@@ -248,7 +255,7 @@ export class TasksPanel extends ScrollableListPanel<RuntimeTask> {
|
|
|
248
255
|
[' Status: ', C.label],
|
|
249
256
|
[selected.status, statusColor(selected.status)],
|
|
250
257
|
[' Kind: ', C.label],
|
|
251
|
-
[selected.kind, C.value],
|
|
258
|
+
[kindLabel(selected.kind), C.value],
|
|
252
259
|
]));
|
|
253
260
|
detailRows.push(buildPanelLine(width, [
|
|
254
261
|
[' Owner: ', C.label],
|
|
@@ -272,8 +279,8 @@ export class TasksPanel extends ScrollableListPanel<RuntimeTask> {
|
|
|
272
279
|
[descriptor?.mode ?? 'n/a', C.value],
|
|
273
280
|
[' Family: ', C.label],
|
|
274
281
|
[descriptor?.family ?? 'n/a', C.info],
|
|
275
|
-
['
|
|
276
|
-
[descriptor?.source
|
|
282
|
+
[' Origin: ', C.label],
|
|
283
|
+
[descriptorOriginLabel(descriptor?.source), C.dim],
|
|
277
284
|
]));
|
|
278
285
|
}
|
|
279
286
|
if (descriptor?.reviewMode || descriptor?.executionProtocol || descriptor?.template) {
|
|
@@ -310,7 +317,7 @@ export class TasksPanel extends ScrollableListPanel<RuntimeTask> {
|
|
|
310
317
|
}
|
|
311
318
|
if (selected.error) {
|
|
312
319
|
detailRows.push(buildPanelLine(width, [
|
|
313
|
-
[' Error
|
|
320
|
+
[' Error ', C.label],
|
|
314
321
|
[selected.error.slice(0, Math.max(0, width - 10)), C.failed],
|
|
315
322
|
]));
|
|
316
323
|
}
|
|
@@ -74,17 +74,24 @@ function truncateJson(val: unknown, maxLen = 120): string {
|
|
|
74
74
|
return s.length > maxLen ? s.slice(0, maxLen - 1) + '\u2026' : s;
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
function isResultSummaryRecord(value: unknown): value is {
|
|
78
|
+
readonly preview?: unknown;
|
|
79
|
+
readonly kind?: unknown;
|
|
80
|
+
readonly byteSize?: unknown;
|
|
81
|
+
} {
|
|
82
|
+
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
83
|
+
}
|
|
84
|
+
|
|
77
85
|
function summarizeResult(result: unknown): string | undefined {
|
|
78
86
|
// SDK OBS-05 (0.21.31+): TOOL_SUCCEEDED/TOOL_FAILED.result is a ToolResultSummary
|
|
79
87
|
// { kind: 'text' | 'json' | 'binary' | 'error' | 'empty'; byteSize: number; preview?: string }.
|
|
80
|
-
if (!result
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
const compact = record.preview.replace(/\s+/g, ' ').trim();
|
|
88
|
+
if (!isResultSummaryRecord(result)) return undefined;
|
|
89
|
+
if (typeof result.preview === 'string' && result.preview.trim()) {
|
|
90
|
+
const compact = result.preview.replace(/\s+/g, ' ').trim();
|
|
84
91
|
return compact.length > 72 ? `${compact.slice(0, 69)}\u2026` : compact;
|
|
85
92
|
}
|
|
86
|
-
if (typeof
|
|
87
|
-
return `${
|
|
93
|
+
if (typeof result.kind === 'string' && typeof result.byteSize === 'number') {
|
|
94
|
+
return `${result.kind} (${result.byteSize}B)`;
|
|
88
95
|
}
|
|
89
96
|
return undefined;
|
|
90
97
|
}
|
|
@@ -303,23 +310,23 @@ export class ToolInspectorPanel extends BasePanel {
|
|
|
303
310
|
|
|
304
311
|
if (rec.expanded) {
|
|
305
312
|
const argsStr = truncateJson(rec.args, 200);
|
|
306
|
-
flat.push({ kind: 'detail', text: `Args
|
|
307
|
-
flat.push({ kind: 'detail', text: `Risk
|
|
313
|
+
flat.push({ kind: 'detail', text: `Args ${argsStr}`, isError: false });
|
|
314
|
+
flat.push({ kind: 'detail', text: `Risk ${risk}${rec.approved === undefined ? '' : ` Approved ${rec.approved ? 'yes' : 'no'}`}`, isError: false });
|
|
308
315
|
if (rec.policyAction || rec.spillBackend) {
|
|
309
316
|
flat.push({
|
|
310
317
|
kind: 'detail',
|
|
311
|
-
text: `Output policy
|
|
318
|
+
text: `Output policy ${rec.policyAction ?? 'none'}${rec.spillBackend ? ` Spill ${rec.spillBackend}` : ''}`,
|
|
312
319
|
isError: false,
|
|
313
320
|
});
|
|
314
321
|
}
|
|
315
322
|
if (rec.resultSummary) {
|
|
316
|
-
flat.push({ kind: 'detail', text: `Summary
|
|
323
|
+
flat.push({ kind: 'detail', text: `Summary ${rec.resultSummary}`, isError: false });
|
|
317
324
|
}
|
|
318
325
|
if (rec.result !== undefined) {
|
|
319
|
-
flat.push({ kind: 'detail', text: `Result
|
|
326
|
+
flat.push({ kind: 'detail', text: `Result ${truncateJson(rec.result, 200)}`, isError: false });
|
|
320
327
|
}
|
|
321
328
|
if (rec.error) {
|
|
322
|
-
flat.push({ kind: 'detail', text: `Error
|
|
329
|
+
flat.push({ kind: 'detail', text: `Error ${rec.error}`, isError: true });
|
|
323
330
|
}
|
|
324
331
|
}
|
|
325
332
|
}
|
|
@@ -151,18 +151,18 @@ export class WorkPlanPanel extends ScrollableListPanel<WorkPlanItem> {
|
|
|
151
151
|
const active = this.items[this.selectedIndex];
|
|
152
152
|
const header = [
|
|
153
153
|
line(`Persistent Work Plan`, width, { fg: '#22d3ee', bold: true }),
|
|
154
|
-
line(`Project
|
|
154
|
+
line(`Project ${plan.projectRoot}`, width, { fg: '#cbd5e1' }),
|
|
155
155
|
line(
|
|
156
|
-
`Items
|
|
156
|
+
`Items ${plan.items.length} pending ${counts.get('pending') ?? 0} active ${counts.get('in_progress') ?? 0} blocked ${counts.get('blocked') ?? 0} done ${counts.get('done') ?? 0}`,
|
|
157
157
|
width,
|
|
158
158
|
{ fg: '#94a3b8' },
|
|
159
159
|
),
|
|
160
|
-
line(`Saved
|
|
160
|
+
line(`Saved ${this.store.filePath}`, width, { fg: '#64748b' }),
|
|
161
161
|
];
|
|
162
162
|
if (active) {
|
|
163
163
|
header.push(line('', width));
|
|
164
|
-
header.push(line(`Selected
|
|
165
|
-
if (active.notes) header.push(line(`Notes
|
|
164
|
+
header.push(line(`Selected ${active.id} ${statusName(active.status)} updated ${compactDate(active.updatedAt)}`, width, { fg: '#a5b4fc' }));
|
|
165
|
+
if (active.notes) header.push(line(`Notes ${active.notes}`, width, { fg: '#cbd5e1' }));
|
|
166
166
|
}
|
|
167
167
|
return header;
|
|
168
168
|
}
|
|
@@ -472,7 +472,7 @@ export class ProjectPlanningCoordinator {
|
|
|
472
472
|
|
|
473
473
|
return [
|
|
474
474
|
'Agent-owned planning loop is active for this turn.',
|
|
475
|
-
'Do not execute code changes,
|
|
475
|
+
'Do not execute code changes, create separate Agent jobs, or claim implementation is complete unless the user explicitly approves execution after the plan is structurally ready.',
|
|
476
476
|
'Be relentless and thorough: challenge vague wording, inspect relevant context before proposing execution, and ask exactly one focused question when information is missing.',
|
|
477
477
|
'Do not ask broad questions like "what is in scope?" without examples. Break broad planning gaps into concrete choices, explain tradeoffs, and recommend a default the user can accept or correct.',
|
|
478
478
|
'',
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export function formatProviderAuthRouteId(route: string): string {
|
|
2
|
+
return route === 'service-oauth' ? 'provider-oauth' : route;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function formatProviderAuthRouteLabel(route: string, label?: string): string {
|
|
6
|
+
if (route === 'service-oauth') return 'Provider OAuth';
|
|
7
|
+
const trimmed = label?.trim();
|
|
8
|
+
return trimmed && trimmed.length > 0 ? trimmed : formatProviderAuthRouteId(route);
|
|
9
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AgentWorkspaceAction,
|
|
3
|
+
AgentWorkspaceActionResult,
|
|
4
|
+
AgentWorkspaceRuntimeSnapshot,
|
|
5
|
+
} from '../input/agent-workspace.ts';
|
|
6
|
+
import { WORKSPACE_PALETTE as PALETTE } from './fullscreen-workspace.ts';
|
|
7
|
+
|
|
8
|
+
export type AgentWorkspaceContextLine = {
|
|
9
|
+
readonly text: string;
|
|
10
|
+
readonly fg?: string;
|
|
11
|
+
readonly bold?: boolean;
|
|
12
|
+
readonly dim?: boolean;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export function safetyColor(action: AgentWorkspaceAction): string {
|
|
16
|
+
if (action.safety === 'safe') return PALETTE.good;
|
|
17
|
+
if (action.safety === 'read-only') return PALETTE.info;
|
|
18
|
+
if (action.safety === 'delegates') return PALETTE.warn;
|
|
19
|
+
return PALETTE.bad;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function actionResultColor(result: AgentWorkspaceActionResult): string {
|
|
23
|
+
if (result.kind === 'blocked' || result.kind === 'error') return PALETTE.bad;
|
|
24
|
+
if (result.kind === 'dispatched') return PALETTE.info;
|
|
25
|
+
if (result.kind === 'refreshed') return PALETTE.good;
|
|
26
|
+
return PALETTE.muted;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function setupStatusColor(status: AgentWorkspaceRuntimeSnapshot['setupChecklist'][number]['status']): string {
|
|
30
|
+
if (status === 'ready') return PALETTE.good;
|
|
31
|
+
if (status === 'recommended') return PALETTE.warn;
|
|
32
|
+
if (status === 'blocked') return PALETTE.bad;
|
|
33
|
+
return PALETTE.muted;
|
|
34
|
+
}
|