@pellux/goodvibes-agent 1.4.3 → 1.5.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 +24 -0
- package/README.md +7 -7
- package/dist/package/main.js +7450 -12285
- package/docs/README.md +2 -2
- package/docs/channels-remote-and-api.md +1 -1
- package/docs/getting-started.md +2 -2
- package/docs/release-and-publishing.md +1 -1
- package/docs/tools-and-commands.md +5 -5
- package/package.json +4 -2
- package/release/performance-snapshot.json +2 -2
- package/release/release-notes.md +11 -7
- package/release/release-readiness.json +6 -6
- package/src/agent/behavior-discovery-summary.ts +4 -18
- package/src/agent/calendar-registry.ts +322 -0
- package/src/agent/competitive-feature-inventory.ts +268 -130
- package/src/agent/document-registry.ts +5 -1
- package/src/agent/email/email-service.ts +350 -0
- package/src/agent/email/imap-client.ts +596 -0
- package/src/agent/email/smtp-client.ts +453 -0
- package/src/agent/ics-calendar.ts +662 -0
- package/src/agent/ics-timezone.ts +172 -0
- package/src/agent/markdown-frontmatter.ts +31 -0
- package/src/agent/memory-safety.ts +1 -1
- package/src/agent/note-registry.ts +3 -9
- package/src/agent/persona-discovery.ts +3 -15
- package/src/agent/persona-registry.ts +1 -10
- package/src/agent/research-source-registry.ts +5 -1
- package/src/agent/routine-discovery.ts +3 -15
- package/src/agent/runtime-profile.ts +3 -0
- package/src/agent/skill-discovery.ts +3 -15
- package/src/agent/skill-draft-proposer.ts +203 -0
- package/src/agent/skill-draft-runner.ts +201 -0
- package/src/agent/skill-registry.ts +36 -1
- package/src/agent/skill-standard.ts +99 -0
- package/src/agent/vibe-file.ts +7 -22
- package/src/cli/completion.ts +1 -1
- package/src/cli/config-overrides.ts +10 -1
- package/src/cli/redaction.ts +17 -5
- package/src/config/provider-model.ts +2 -1
- package/src/config/secret-config.ts +13 -6
- package/src/core/activity-feed.ts +97 -0
- package/src/core/away-digest.ts +161 -0
- package/src/core/conversation-rendering.ts +7 -3
- package/src/core/conversation.ts +22 -15
- package/src/core/hardware-profile.ts +362 -0
- package/src/core/last-seen-store.ts +78 -0
- package/src/core/plain-language.ts +52 -0
- package/src/core/setup-incomplete-hint.ts +90 -0
- package/src/core/system-message-router.ts +38 -87
- package/src/input/agent-workspace-basic-command-editor-submission.ts +60 -220
- package/src/input/agent-workspace-basic-command-editors.ts +39 -141
- package/src/input/agent-workspace-categories.ts +63 -158
- package/src/input/agent-workspace-command-editor.ts +4 -0
- package/src/input/agent-workspace-host-category.ts +0 -5
- package/src/input/agent-workspace-local-editor-submission.ts +3 -1
- package/src/input/agent-workspace-navigation.ts +10 -3
- package/src/input/agent-workspace-onboarding-actions.ts +132 -0
- package/src/input/agent-workspace-onboarding-categories.ts +29 -26
- package/src/input/agent-workspace-onboarding-finish.ts +11 -4
- package/src/input/agent-workspace-onboarding-state.ts +111 -0
- package/src/input/agent-workspace-profile-editor-submission.ts +260 -0
- package/src/input/agent-workspace-profile-editors.ts +155 -0
- package/src/input/agent-workspace-subscription-editor.ts +7 -0
- package/src/input/agent-workspace-types.ts +5 -1
- package/src/input/agent-workspace.ts +65 -39
- package/src/input/command-registry.ts +18 -5
- package/src/input/commands/agent-runtime-profile-runtime.ts +2 -1
- package/src/input/commands/agent-skills-runtime.ts +60 -3
- package/src/input/commands/calendar-runtime.ts +209 -0
- package/src/input/commands/channels-runtime.ts +1 -0
- package/src/input/commands/command-error.ts +9 -0
- package/src/input/commands/compat-runtime.ts +1 -0
- package/src/input/commands/config.ts +1 -0
- package/src/input/commands/conversation-runtime.ts +1 -1
- package/src/input/commands/delegation-runtime.ts +5 -6
- package/src/input/commands/email-runtime.ts +387 -0
- package/src/input/commands/experience-runtime.ts +17 -4
- package/src/input/commands/guidance-runtime.ts +1 -1
- package/src/input/commands/health-runtime.ts +6 -1
- package/src/input/commands/knowledge-format.ts +73 -0
- package/src/input/commands/knowledge.ts +9 -74
- package/src/input/commands/local-provider-runtime.ts +2 -1
- package/src/input/commands/local-runtime.ts +10 -4
- package/src/input/commands/mcp-runtime.ts +7 -0
- package/src/input/commands/notify-runtime.ts +17 -1
- package/src/input/commands/onboarding-runtime.ts +1 -0
- package/src/input/commands/operator-actions-runtime.ts +1 -0
- package/src/input/commands/operator-runtime.ts +3 -0
- package/src/input/commands/personas-runtime.ts +1 -0
- package/src/input/commands/platform-access-runtime.ts +40 -17
- package/src/input/commands/product-runtime.ts +6 -1
- package/src/input/commands/provider-accounts-runtime.ts +3 -2
- package/src/input/commands/qrcode-runtime.ts +1 -0
- package/src/input/commands/routines-runtime.ts +1 -0
- package/src/input/commands/runtime-services.ts +0 -13
- package/src/input/commands/security-runtime.ts +1 -0
- package/src/input/commands/session-content.ts +1 -0
- package/src/input/commands/shell-core.ts +5 -2
- package/src/input/commands/subscription-runtime.ts +33 -9
- package/src/input/commands/support-bundle-runtime.ts +8 -1
- package/src/input/commands/tasks-runtime.ts +1 -0
- package/src/input/commands/tts-runtime.ts +1 -0
- package/src/input/commands/vibe-runtime.ts +1 -0
- package/src/input/commands.ts +4 -0
- package/src/input/feed-context-factory.ts +3 -12
- package/src/input/handler-command-route.ts +7 -60
- package/src/input/handler-feed-routes.ts +0 -194
- package/src/input/handler-feed.ts +2 -54
- package/src/input/handler-interactions.ts +0 -2
- package/src/input/handler-modal-stack.ts +0 -9
- package/src/input/handler-picker-routes.ts +24 -1
- package/src/input/handler-shortcuts.ts +11 -40
- package/src/input/handler-ui-state.ts +13 -0
- package/src/input/handler.ts +8 -35
- package/src/input/keybindings.ts +40 -17
- package/src/input/model-picker-local-fit.ts +130 -0
- package/src/input/submission-router.ts +0 -5
- package/src/main.ts +111 -89
- package/src/renderer/activity-sidebar.ts +186 -0
- package/src/renderer/agent-workspace-context-lines.ts +5 -48
- package/src/renderer/agent-workspace-style.ts +1 -1
- package/src/renderer/agent-workspace.ts +14 -2
- package/src/renderer/compositor.ts +37 -125
- package/src/renderer/conversation-overlays.ts +3 -3
- package/src/renderer/help-overlay.ts +7 -5
- package/src/renderer/model-workspace.ts +101 -86
- package/src/{panels → renderer}/polish.ts +3 -3
- package/src/renderer/shell-surface.ts +4 -5
- package/src/renderer/status-token.ts +31 -11
- package/src/renderer/tab-strip.ts +1 -1
- package/src/renderer/tool-call.ts +7 -8
- package/src/renderer/tool-labels.ts +92 -0
- package/src/renderer/ui-factory.ts +48 -96
- package/src/runtime/bootstrap-command-context.ts +0 -5
- package/src/runtime/bootstrap-command-parts.ts +6 -15
- package/src/runtime/bootstrap-core.ts +34 -13
- package/src/runtime/bootstrap-hook-bridge.ts +3 -1
- package/src/runtime/bootstrap-shell.ts +3 -50
- package/src/runtime/bootstrap.ts +3 -4
- package/src/runtime/context.ts +1 -1
- package/src/runtime/diagnostics/panels/index.ts +0 -1
- package/src/runtime/diagnostics/panels/policy.ts +1 -1
- package/src/runtime/execution-ledger.ts +16 -1
- package/src/runtime/index.ts +6 -1
- package/src/runtime/onboarding/index.ts +1 -0
- package/src/runtime/onboarding/onboarding-state.ts +200 -0
- package/src/{panels → runtime}/provider-account-snapshot.ts +5 -2
- package/src/runtime/services.ts +16 -4
- package/src/runtime/terminal-output-guard.ts +7 -0
- package/src/runtime/tool-permission-safety.ts +1 -1
- package/src/runtime/ui/model-picker/data-provider.ts +1 -1
- package/src/runtime/ui/model-picker/health-enrichment.ts +2 -2
- package/src/runtime/ui/model-picker/types.ts +2 -2
- package/src/runtime/ui/provider-health/data-provider.ts +3 -3
- package/src/runtime/ui/provider-health/types.ts +2 -2
- package/src/runtime/ui-services.ts +0 -2
- package/src/shell/agent-workspace-fullscreen.ts +0 -1
- package/src/shell/autonomy-surfacing.ts +272 -0
- package/src/shell/session-continuity-hints.ts +0 -6
- package/src/shell/startup-wiring.ts +221 -0
- package/src/shell/ui-openers.ts +18 -29
- package/src/tools/agent-context-policy.ts +1 -1
- package/src/tools/agent-harness-background-processes.ts +4 -4
- package/src/tools/agent-harness-browser-cockpit-route.ts +3 -3
- package/src/tools/agent-harness-command-runner.ts +6 -1
- package/src/tools/agent-harness-document-ops.ts +26 -53
- package/src/tools/agent-harness-execution-history.ts +1 -13
- package/src/tools/agent-harness-execution-posture.ts +0 -15
- package/src/tools/agent-harness-keybinding-metadata.ts +28 -29
- package/src/tools/agent-harness-local-model-cookbook.ts +24 -1
- package/src/tools/agent-harness-metadata.ts +16 -0
- package/src/tools/agent-harness-mode-catalog.ts +2 -9
- package/src/tools/agent-harness-provider-account-metadata.ts +2 -2
- package/src/tools/agent-harness-setup-posture-utils.ts +1 -1
- package/src/tools/agent-harness-tool-schema.ts +13 -14
- package/src/tools/agent-harness-tool.ts +27 -23
- package/src/tools/agent-harness-ui-surface-metadata.ts +10 -20
- package/src/tools/agent-harness-workspace-action-runner.ts +3 -4
- package/src/tools/agent-workspace-tool.ts +2 -33
- package/src/utils/terminal-width.ts +9 -3
- package/src/version.ts +1 -1
- package/src/input/agent-workspace-panel-route.ts +0 -44
- package/src/input/panel-integration-actions.ts +0 -26
- package/src/panels/approval-panel.ts +0 -149
- package/src/panels/automation-control-panel.ts +0 -212
- package/src/panels/base-panel.ts +0 -254
- package/src/panels/builtin/agent.ts +0 -58
- package/src/panels/builtin/knowledge.ts +0 -26
- package/src/panels/builtin/operations.ts +0 -121
- package/src/panels/builtin/session.ts +0 -138
- package/src/panels/builtin/shared.ts +0 -275
- package/src/panels/builtin/usage.ts +0 -21
- package/src/panels/builtin-panels.ts +0 -23
- package/src/panels/confirm-state.ts +0 -61
- package/src/panels/context-visualizer-panel.ts +0 -204
- package/src/panels/cost-tracker-panel.ts +0 -444
- package/src/panels/docs-panel.ts +0 -285
- package/src/panels/index.ts +0 -25
- package/src/panels/knowledge-panel.ts +0 -417
- package/src/panels/memory-panel.ts +0 -226
- package/src/panels/panel-list-panel.ts +0 -464
- package/src/panels/panel-manager.ts +0 -570
- package/src/panels/provider-accounts-panel.ts +0 -233
- package/src/panels/provider-health-domains.ts +0 -208
- package/src/panels/provider-health-panel.ts +0 -720
- package/src/panels/provider-health-tracker.ts +0 -115
- package/src/panels/provider-stats-panel.ts +0 -366
- package/src/panels/qr-panel.ts +0 -207
- package/src/panels/schedule-panel.ts +0 -321
- package/src/panels/scrollable-list-panel.ts +0 -491
- package/src/panels/search-focus.ts +0 -32
- package/src/panels/security-panel.ts +0 -295
- package/src/panels/session-browser-panel.ts +0 -395
- package/src/panels/session-maintenance.ts +0 -125
- package/src/panels/subscription-panel.ts +0 -263
- package/src/panels/system-messages-panel.ts +0 -230
- package/src/panels/tasks-panel.ts +0 -344
- package/src/panels/thinking-panel.ts +0 -304
- package/src/panels/token-budget-panel.ts +0 -475
- package/src/panels/tool-inspector-panel.ts +0 -436
- package/src/panels/types.ts +0 -54
- package/src/renderer/panel-composite.ts +0 -158
- package/src/renderer/panel-tab-bar.ts +0 -69
- package/src/renderer/panel-workspace-bar.ts +0 -42
- package/src/runtime/diagnostics/panels/panel-resources.ts +0 -118
- package/src/tools/agent-harness-panel-metadata.ts +0 -211
- /package/src/runtime/perf/{panel-health-monitor.ts → component-health.ts} +0 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LastSeenStore — persists the timestamp of the user's last TUI session.
|
|
3
|
+
*
|
|
4
|
+
* Used by the away-digest feature to know what happened since the user was
|
|
5
|
+
* last present. Follows the same file-backed JSON pattern as the agent
|
|
6
|
+
* registries (see src/agent/routine-registry.ts).
|
|
7
|
+
*
|
|
8
|
+
* File layout:
|
|
9
|
+
* { version: 1, lastSeenAt: <epoch-ms> }
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
13
|
+
import { dirname } from 'node:path';
|
|
14
|
+
import type { ShellPathService } from '@/runtime/index.ts';
|
|
15
|
+
import { GOODVIBES_AGENT_SURFACE_ROOT } from '../config/surface.ts';
|
|
16
|
+
|
|
17
|
+
interface LastSeenFile {
|
|
18
|
+
readonly version: 1;
|
|
19
|
+
readonly lastSeenAt: number;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
23
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function parseFile(raw: string): LastSeenFile | null {
|
|
27
|
+
try {
|
|
28
|
+
const parsed: unknown = JSON.parse(raw);
|
|
29
|
+
if (!isRecord(parsed)) return null;
|
|
30
|
+
if (parsed['version'] !== 1) return null;
|
|
31
|
+
const ts = parsed['lastSeenAt'];
|
|
32
|
+
if (typeof ts !== 'number' || !Number.isFinite(ts) || ts <= 0) return null;
|
|
33
|
+
return { version: 1, lastSeenAt: ts };
|
|
34
|
+
} catch {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
type AgentLocalStorePaths = Pick<ShellPathService, 'resolveUserPath'>;
|
|
40
|
+
|
|
41
|
+
export function lastSeenStorePath(shellPaths: AgentLocalStorePaths): string {
|
|
42
|
+
return shellPaths.resolveUserPath(GOODVIBES_AGENT_SURFACE_ROOT, 'last-seen.json');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export class LastSeenStore {
|
|
46
|
+
public constructor(private readonly storePath: string) {}
|
|
47
|
+
|
|
48
|
+
public static fromShellPaths(shellPaths: AgentLocalStorePaths): LastSeenStore {
|
|
49
|
+
return new LastSeenStore(lastSeenStorePath(shellPaths));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Read the persisted lastSeenAt value.
|
|
54
|
+
* Returns null when the file doesn't exist or is corrupt (first run).
|
|
55
|
+
*/
|
|
56
|
+
public read(): number | null {
|
|
57
|
+
try {
|
|
58
|
+
const raw = readFileSync(this.storePath, 'utf-8');
|
|
59
|
+
return parseFile(raw)?.lastSeenAt ?? null;
|
|
60
|
+
} catch {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Persist the current time as the new lastSeenAt.
|
|
67
|
+
* Silently ignores write errors to avoid crashing on shutdown.
|
|
68
|
+
*/
|
|
69
|
+
public save(at: number = Date.now()): void {
|
|
70
|
+
try {
|
|
71
|
+
mkdirSync(dirname(this.storePath), { recursive: true });
|
|
72
|
+
const data: LastSeenFile = { version: 1, lastSeenAt: at };
|
|
73
|
+
writeFileSync(this.storePath, JSON.stringify(data, null, 2), 'utf-8');
|
|
74
|
+
} catch {
|
|
75
|
+
// Silently ignore — last-seen is a best-effort hint, not critical state.
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plain-language vocabulary gate.
|
|
3
|
+
*
|
|
4
|
+
* Exports the banned-term lists and a validate helper so that the release-gate
|
|
5
|
+
* test and any future caller share a single definition.
|
|
6
|
+
*
|
|
7
|
+
* WHY EACH TERM IS BANNED
|
|
8
|
+
* ───────────────────────
|
|
9
|
+
* FIRST_GLANCE_BANNED — terms the user sees on labels, summaries, and action
|
|
10
|
+
* labels (the copy they read without clicking through). These must never appear
|
|
11
|
+
* in first-glance copy because they are internal implementation vocabulary that
|
|
12
|
+
* a non-technical user would not understand or would find confusing:
|
|
13
|
+
*
|
|
14
|
+
* WRFC — internal code-review workflow acronym, never user-facing
|
|
15
|
+
* daemon — Unix process jargon; user-facing name is "assistant service"
|
|
16
|
+
* posture — internal policy/config term; meaningless to end users
|
|
17
|
+
* modelRoute — internal routing key; end users pick a "model", not a "route"
|
|
18
|
+
* agent_harness — raw tool identifier; end users never see tool names
|
|
19
|
+
* action:" — raw tool parameter syntax that leaks protocol details
|
|
20
|
+
* mode:" — raw tool parameter syntax that leaks protocol details
|
|
21
|
+
* cli — developer-facing term; never appears on operator UX labels
|
|
22
|
+
*
|
|
23
|
+
* EVERYWHERE_BANNED — terms that must not appear even in action detail copy
|
|
24
|
+
* (which technical users may read after clicking through):
|
|
25
|
+
*
|
|
26
|
+
* WRFC — internal workflow acronym with no end-user meaning
|
|
27
|
+
* modelRoute — internal routing key never intended for user-facing copy
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
export const FIRST_GLANCE_BANNED: readonly RegExp[] = [
|
|
31
|
+
/\bWRFC\b/,
|
|
32
|
+
/\bdaemon\b/i,
|
|
33
|
+
/\bposture\b/i,
|
|
34
|
+
/\bmodelRoute\b/,
|
|
35
|
+
/\bagent_harness\b/,
|
|
36
|
+
/action:"/,
|
|
37
|
+
/mode:"/,
|
|
38
|
+
/\bcli\b/i,
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
export const EVERYWHERE_BANNED: readonly RegExp[] = [
|
|
42
|
+
/\bWRFC\b/,
|
|
43
|
+
/\bmodelRoute\b/,
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Return the subset of rules that match `text`.
|
|
48
|
+
* Returns an empty array when there are no violations.
|
|
49
|
+
*/
|
|
50
|
+
export function validate(text: string, rules: readonly RegExp[]): RegExp[] {
|
|
51
|
+
return rules.filter((rule) => rule.test(text));
|
|
52
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure builder for the "setup not finished" hint shown once at startup
|
|
3
|
+
* when the user has started but not completed onboarding.
|
|
4
|
+
*
|
|
5
|
+
* No side effects, no imports from the runtime or shell — testable in isolation.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { OnboardingState } from '../runtime/onboarding/onboarding-state.ts';
|
|
9
|
+
|
|
10
|
+
export interface SetupIncompleteHintResult {
|
|
11
|
+
readonly lines: string[];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Build a plain-language hint reminding the user that setup isn't finished
|
|
16
|
+
* and pointing them at /agent.
|
|
17
|
+
*
|
|
18
|
+
* Returns null when:
|
|
19
|
+
* - phase === 'complete' — setup is done, no nag needed
|
|
20
|
+
* - phase === 'fresh' — first-run users get the full workspace, not a nag
|
|
21
|
+
*
|
|
22
|
+
* Only phase === 'in-progress' produces a hint (the user has opened /agent
|
|
23
|
+
* at least once but hasn't finished).
|
|
24
|
+
*
|
|
25
|
+
* @param state The current OnboardingState (from deriveOnboardingState).
|
|
26
|
+
* @param hostReady True = assistant service is reachable; false = not yet running;
|
|
27
|
+
* null/undefined = unknown (omit the host line entirely).
|
|
28
|
+
*/
|
|
29
|
+
export function buildSetupIncompleteHint(
|
|
30
|
+
state: OnboardingState,
|
|
31
|
+
hostReady?: boolean | null,
|
|
32
|
+
): SetupIncompleteHintResult | null {
|
|
33
|
+
if (state.phase !== 'in-progress') return null;
|
|
34
|
+
|
|
35
|
+
const lines: string[] = [];
|
|
36
|
+
|
|
37
|
+
// ── Line 1: readiness / chat availability ────────────────────────────────
|
|
38
|
+
if (!state.readyToChat) {
|
|
39
|
+
// Model not configured — that's the most urgent thing.
|
|
40
|
+
lines.push('Pick a model to start — run /agent to continue setup.');
|
|
41
|
+
} else {
|
|
42
|
+
// Chat works but setup isn't done.
|
|
43
|
+
// NOTE: progressLabel is intentionally omitted here — the hint's plan may be
|
|
44
|
+
// a reduced subset of the full setup plan, so any 'N of M' count would
|
|
45
|
+
// misrepresent real progress and mislead the user.
|
|
46
|
+
const nextStep = pickNextStep(state);
|
|
47
|
+
if (nextStep) {
|
|
48
|
+
lines.push(
|
|
49
|
+
`You can chat now. Still finishing setup — ${nextStep} — run /agent to complete it.`,
|
|
50
|
+
);
|
|
51
|
+
} else {
|
|
52
|
+
lines.push(
|
|
53
|
+
'You can chat now. Some background features still need setup — run /agent to finish.',
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// ── Line 2 (optional): assistant service / background work status ─────────
|
|
59
|
+
// Only append when the caller has a reliable live signal. Never fabricate.
|
|
60
|
+
if (hostReady === true) {
|
|
61
|
+
lines.push('Background work (reminders, schedules) is active.');
|
|
62
|
+
} else if (hostReady === false) {
|
|
63
|
+
lines.push('Background work (reminders, schedules) is not running yet.');
|
|
64
|
+
}
|
|
65
|
+
// hostReady === null or undefined → omit line entirely.
|
|
66
|
+
|
|
67
|
+
return { lines };
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Pick the single most actionable next-step phrase from the state.
|
|
72
|
+
* Prefers the first autonomy-blocking step, then the first non-ready step.
|
|
73
|
+
* Returns undefined when no useful step hint is available.
|
|
74
|
+
*/
|
|
75
|
+
function pickNextStep(state: OnboardingState): string | undefined {
|
|
76
|
+
const step =
|
|
77
|
+
state.blockers[0] ??
|
|
78
|
+
state.steps.find((s) => s.status !== 'ready');
|
|
79
|
+
|
|
80
|
+
if (!step) return undefined;
|
|
81
|
+
|
|
82
|
+
// Use the step's nextLabel if it reads like plain language (no slash syntax).
|
|
83
|
+
// Fall back to the step's label.
|
|
84
|
+
const label = step.nextLabel && !step.nextLabel.startsWith('/') && !step.nextLabel.includes('action:')
|
|
85
|
+
? step.nextLabel
|
|
86
|
+
: step.label;
|
|
87
|
+
|
|
88
|
+
// Truncate to keep the hint compact (max ~60 chars for the next-step phrase).
|
|
89
|
+
return label.length > 60 ? `${label.slice(0, 58)}…` : label;
|
|
90
|
+
}
|
|
@@ -1,37 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* SystemMessageRouter — routes system messages to the
|
|
3
|
-
* based on priority.
|
|
2
|
+
* SystemMessageRouter — routes system messages to the right surfaces.
|
|
4
3
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* - 'low' — appears in the SystemMessagesPanel only (panel-only routing).
|
|
10
|
-
* Use for: scan results, provider discovery, plugin load/unload, feature
|
|
11
|
-
* flag changes, tool execution status, permission decisions,
|
|
12
|
-
* health/cascade events, debug/operational info.
|
|
13
|
-
*
|
|
14
|
-
* Usage:
|
|
15
|
-
* ```ts
|
|
16
|
-
* const router = createSystemMessageRouter(conversation, panel);
|
|
17
|
-
* router.routeSystemMessage('[Provider] anthropic registered', 'low');
|
|
18
|
-
* router.routeSystemMessage('[Session] Saved session abc123', 'high');
|
|
19
|
-
* ```
|
|
4
|
+
* Every message lands in the ActivityFeed (the ambient "Recent" record shown
|
|
5
|
+
* in the Activity sidebar). High-priority messages — errors, confirmations the
|
|
6
|
+
* user explicitly caused, session lifecycle — additionally land in the main
|
|
7
|
+
* conversation so they are impossible to miss.
|
|
20
8
|
*
|
|
21
|
-
*
|
|
22
|
-
* conversation
|
|
23
|
-
*
|
|
9
|
+
* Two tiers:
|
|
10
|
+
* - 'high' — conversation AND activity feed. Use for: fatal errors,
|
|
11
|
+
* model/provider confirmations, session save/load, compaction events.
|
|
12
|
+
* - 'low' — activity feed only. Use for: scan results, provider discovery,
|
|
13
|
+
* plugin load/unload, tool execution status, permission decisions,
|
|
14
|
+
* health events, debug/operational info.
|
|
24
15
|
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* notifications with policy-based routing.
|
|
16
|
+
* The `ui.systemMessages` / `ui.operationalMessages` settings keep their
|
|
17
|
+
* historical values ('panel' | 'conversation' | 'both'); 'panel' now means
|
|
18
|
+
* "activity feed only".
|
|
29
19
|
*/
|
|
30
20
|
|
|
31
|
-
import { getConfigSnapshot } from '../config/index.ts';
|
|
32
|
-
import type { ConfigManager } from '@pellux/goodvibes-sdk/platform/config';
|
|
33
21
|
import type { ConversationManager } from './conversation';
|
|
34
|
-
import type {
|
|
22
|
+
import type { ActivityFeed } from './activity-feed.ts';
|
|
35
23
|
import {
|
|
36
24
|
classifySystemMessageKind,
|
|
37
25
|
classifySystemMessagePriority,
|
|
@@ -46,51 +34,30 @@ export type {
|
|
|
46
34
|
SystemMessageTarget,
|
|
47
35
|
} from '@/runtime/index.ts';
|
|
48
36
|
|
|
49
|
-
|
|
50
|
-
configManager: Pick<ConfigManager, 'getRaw'>,
|
|
51
|
-
kind: SystemMessageKind,
|
|
52
|
-
): SystemMessageTarget {
|
|
53
|
-
const ui = getConfigSnapshot(configManager).ui;
|
|
54
|
-
if (kind === 'wrfc') return ui.wrfcMessages;
|
|
55
|
-
if (kind === 'operational') return ui.operationalMessages;
|
|
56
|
-
return ui.systemMessages;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// ---------------------------------------------------------------------------
|
|
60
|
-
// SystemMessageRouter
|
|
61
|
-
// ---------------------------------------------------------------------------
|
|
37
|
+
export type SystemMessagePriority = 'high' | 'low';
|
|
62
38
|
|
|
63
39
|
/**
|
|
64
|
-
* Routes system messages to the conversation and/or the
|
|
65
|
-
* based on priority level.
|
|
40
|
+
* Routes system messages to the conversation and/or the ActivityFeed
|
|
41
|
+
* based on priority level and per-kind targets.
|
|
66
42
|
*/
|
|
67
43
|
export class SystemMessageRouter {
|
|
68
44
|
constructor(
|
|
69
45
|
private readonly conversation: ConversationManager,
|
|
70
|
-
private
|
|
46
|
+
private feed: ActivityFeed | null,
|
|
71
47
|
private readonly getTargetForKind: (kind: SystemMessageKind) => SystemMessageTarget = defaultSystemMessageTarget,
|
|
72
48
|
) {}
|
|
73
49
|
|
|
74
|
-
// ── Public API
|
|
50
|
+
// ── Public API ────────────────────────────────────────────────────────────────
|
|
75
51
|
|
|
76
|
-
/**
|
|
77
|
-
* Route a system message with explicit priority.
|
|
78
|
-
*
|
|
79
|
-
* - 'high': delivered to both conversation AND panel.
|
|
80
|
-
* - 'low': delivered to panel only (conversation is not touched).
|
|
81
|
-
*
|
|
82
|
-
* @param message - Message text.
|
|
83
|
-
* @param priority - 'high' | 'low'.
|
|
84
|
-
*/
|
|
85
52
|
routeTypedSystemMessage(
|
|
86
53
|
message: string,
|
|
87
54
|
priority: SystemMessagePriority,
|
|
88
55
|
kind: SystemMessageKind,
|
|
89
56
|
): void {
|
|
90
57
|
const target = this.getTargetForKind(kind);
|
|
91
|
-
const delivery = resolveSystemMessageDelivery(target, this.
|
|
58
|
+
const delivery = resolveSystemMessageDelivery(target, this.feed !== null);
|
|
92
59
|
if (delivery.toPanel) {
|
|
93
|
-
this.
|
|
60
|
+
this.feed?.push(message, priority);
|
|
94
61
|
}
|
|
95
62
|
if (delivery.toConversation) {
|
|
96
63
|
this.conversation.addSystemMessage(message);
|
|
@@ -103,29 +70,19 @@ export class SystemMessageRouter {
|
|
|
103
70
|
|
|
104
71
|
/**
|
|
105
72
|
* Automatically classify the message priority by content and route.
|
|
106
|
-
*
|
|
107
|
-
* Useful as a drop-in replacement for conversation.addSystemMessage()
|
|
108
|
-
* when you want the router to determine priority.
|
|
109
|
-
*
|
|
110
|
-
* @param message - Message text.
|
|
73
|
+
* Drop-in replacement for conversation.addSystemMessage().
|
|
111
74
|
*/
|
|
112
75
|
routeAuto(message: string): void {
|
|
113
76
|
const priority: SystemMessagePriority = classifySystemMessagePriority(message);
|
|
114
77
|
this.routeTypedSystemMessage(message, priority, classifySystemMessageKind(message));
|
|
115
78
|
}
|
|
116
79
|
|
|
117
|
-
/**
|
|
118
|
-
* High-priority convenience shortcut.
|
|
119
|
-
* Equivalent to routeSystemMessage(message, 'high').
|
|
120
|
-
*/
|
|
80
|
+
/** High-priority shortcut — conversation + activity feed. */
|
|
121
81
|
high(message: string): void {
|
|
122
82
|
this.routeSystemMessage(message, 'high');
|
|
123
83
|
}
|
|
124
84
|
|
|
125
|
-
/**
|
|
126
|
-
* Low-priority convenience shortcut.
|
|
127
|
-
* Equivalent to routeSystemMessage(message, 'low').
|
|
128
|
-
*/
|
|
85
|
+
/** Low-priority shortcut — activity feed only. */
|
|
129
86
|
low(message: string): void {
|
|
130
87
|
this.routeSystemMessage(message, 'low');
|
|
131
88
|
}
|
|
@@ -134,38 +91,32 @@ export class SystemMessageRouter {
|
|
|
134
91
|
this.routeTypedSystemMessage(message, priority, 'wrfc');
|
|
135
92
|
}
|
|
136
93
|
|
|
137
|
-
/**
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
getPanel(): SystemMessagesPanel | null {
|
|
141
|
-
return this.panel;
|
|
94
|
+
/** Returns the current activity feed reference. */
|
|
95
|
+
getFeed(): ActivityFeed | null {
|
|
96
|
+
return this.feed;
|
|
142
97
|
}
|
|
143
98
|
|
|
144
99
|
/**
|
|
145
|
-
* Replace the
|
|
146
|
-
* Pass null to detach
|
|
100
|
+
* Replace the feed reference after construction (late binding).
|
|
101
|
+
* Pass null to detach.
|
|
147
102
|
*/
|
|
148
|
-
|
|
149
|
-
this.
|
|
103
|
+
setFeed(feed: ActivityFeed | null): void {
|
|
104
|
+
this.feed = feed;
|
|
150
105
|
}
|
|
151
106
|
}
|
|
152
107
|
|
|
153
|
-
// ---------------------------------------------------------------------------
|
|
154
|
-
// Factory
|
|
155
|
-
// ---------------------------------------------------------------------------
|
|
156
|
-
|
|
157
108
|
/**
|
|
158
|
-
* Create a SystemMessageRouter wired to the given conversation and
|
|
109
|
+
* Create a SystemMessageRouter wired to the given conversation and feed.
|
|
159
110
|
*
|
|
160
111
|
* @param conversation - The ConversationManager for high-priority messages.
|
|
161
|
-
* @param
|
|
162
|
-
* (router still works;
|
|
163
|
-
*
|
|
112
|
+
* @param feed - The ActivityFeed for ambient traffic. Can be null
|
|
113
|
+
* (router still works; feed routing is dropped until
|
|
114
|
+
* a feed is attached).
|
|
164
115
|
*/
|
|
165
116
|
export function createSystemMessageRouter(
|
|
166
117
|
conversation: ConversationManager,
|
|
167
|
-
|
|
118
|
+
feed: ActivityFeed | null = null,
|
|
168
119
|
getTargetForKind: (kind: SystemMessageKind) => SystemMessageTarget = defaultSystemMessageTarget,
|
|
169
120
|
): SystemMessageRouter {
|
|
170
|
-
return new SystemMessageRouter(conversation,
|
|
121
|
+
return new SystemMessageRouter(conversation, feed, getTargetForKind);
|
|
171
122
|
}
|