@pellux/goodvibes-tui 1.27.1 → 2.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 +116 -2
- package/README.md +7 -9
- package/bin/goodvibes +2 -2
- package/bin/launcher-support.js +8 -4
- package/docs/README.md +11 -2
- package/docs/foundation-artifacts/operator-contract.json +6403 -2347
- package/package.json +14 -25
- package/scripts/postinstall.js +35 -35
- package/src/audio/spoken-turn-model-routing.ts +1 -1
- package/src/cli/bundle-command.ts +5 -5
- package/src/cli/completions/generate.ts +1 -1
- package/src/cli/doctor.ts +3 -3
- package/src/cli/entrypoint.ts +12 -7
- package/src/cli/help.ts +4 -5
- package/src/cli/hooks-command.ts +1 -1
- package/src/cli/index.ts +1 -4
- package/src/cli/launch-auto-update.ts +59 -7
- package/src/cli/management-commands.ts +6 -6
- package/src/cli/management-utils.ts +5 -5
- package/src/cli/management.ts +7 -7
- package/src/cli/network-posture.ts +1 -1
- package/src/cli/package-verification.ts +7 -6
- package/src/cli/plugin-bundles-command.ts +1 -1
- package/src/cli/plugin-command.ts +2 -2
- package/src/cli/service-command.ts +2 -2
- package/src/cli/service-posture.ts +4 -4
- package/src/cli/status.ts +9 -8
- package/src/cli/surface-command.ts +4 -4
- package/src/cli/tui-startup.ts +3 -3
- package/src/cli-flags.ts +3 -3
- package/src/config/goodvibes-home-audit.ts +0 -2
- package/src/config/secret-config.ts +37 -5
- package/src/config/tui-extension-settings.ts +1 -1
- package/src/core/approval-alert.ts +2 -2
- package/src/core/budget-breach-notifier.ts +3 -3
- package/src/core/conversation-compaction-render.ts +1 -1
- package/src/core/conversation-line-cache.ts +1 -1
- package/src/core/conversation-render-context.ts +1 -1
- package/src/core/conversation-rendering.ts +2 -2
- package/src/core/conversation.ts +10 -10
- package/src/core/long-task-notifier.ts +2 -2
- package/src/core/memory-diagnostics-gateway.ts +1 -1
- package/src/core/scriptable-statusline.ts +1 -1
- package/src/core/session-auto-titler.ts +1 -1
- package/src/core/session-resume-core.ts +2 -2
- package/src/core/stream-event-wiring.ts +24 -44
- package/src/core/terminal-notifier.ts +3 -3
- package/src/core/turn-cancellation.ts +1 -1
- package/src/core/turn-event-wiring.ts +5 -5
- package/src/input/command-registry.ts +6 -6
- package/src/input/commands/channel-pairing.ts +1 -1
- package/src/input/commands/cluster-runtime.ts +1 -1
- package/src/input/commands/codebase-runtime.ts +1 -1
- package/src/input/commands/devices-runtime.ts +1 -1
- package/src/input/commands/hosted-runtime.ts +330 -0
- package/src/input/commands/local-setup-review.ts +1 -1
- package/src/input/commands/local-setup-transfer.ts +2 -2
- package/src/input/commands/local-setup.ts +3 -3
- package/src/input/commands/managed-runtime.ts +2 -2
- package/src/input/commands/operator-rpc.ts +24 -110
- package/src/input/commands/payment-card-intake.ts +1 -1
- package/src/input/commands/permissions-provenance.ts +2 -2
- package/src/input/commands/plugin-runtime.ts +1 -1
- package/src/input/commands/provider.ts +1 -1
- package/src/input/commands/relay-runtime.ts +18 -9
- package/src/input/commands/rewind-runtime.ts +1 -1
- package/src/input/commands/runtime-services.ts +1 -1
- package/src/input/commands/services-runtime.ts +1 -1
- package/src/input/commands/session-workflow.ts +1 -1
- package/src/input/commands/settings-sync-runtime.ts +2 -2
- package/src/input/commands/share-runtime.ts +1 -1
- package/src/input/commands/tasks-runtime.ts +145 -55
- package/src/input/commands/update-runtime.ts +31 -28
- package/src/input/commands/work-plan-runtime.ts +2 -2
- package/src/input/commands/workstream-attempts.ts +1 -1
- package/src/input/commands/workstream-runtime.ts +2 -2
- package/src/input/commands.ts +2 -0
- package/src/input/feature-unit-layout.ts +1 -1
- package/src/input/feed-context-factory.ts +3 -3
- package/src/input/handler-content-actions.ts +2 -2
- package/src/input/handler-feed-routes.ts +1 -1
- package/src/input/handler-feed.ts +3 -3
- package/src/input/handler-modal-token-routes.ts +1 -1
- package/src/input/handler-onboarding-daemon-adopt.ts +3 -2
- package/src/input/handler-onboarding.ts +1 -1
- package/src/input/handler-types.ts +2 -2
- package/src/input/handler-ui-state.ts +1 -1
- package/src/input/handler.ts +4 -4
- package/src/input/input-history.ts +1 -1
- package/src/input/onboarding/onboarding-feature-units.ts +2 -2
- package/src/input/onboarding/onboarding-runtime-status.ts +15 -1
- package/src/input/onboarding/onboarding-wizard-apply.ts +17 -8
- package/src/input/onboarding/onboarding-wizard-cloudflare-step.ts +5 -3
- package/src/input/onboarding/onboarding-wizard-external-surfaces.ts +1 -1
- package/src/input/onboarding/onboarding-wizard-types.ts +1 -1
- package/src/input/payments-config.ts +6 -6
- package/src/input/search.ts +1 -1
- package/src/input/session-picker-modal.ts +46 -0
- package/src/input/settings-modal-activation.ts +1 -1
- package/src/input/settings-modal-behavior.ts +4 -4
- package/src/input/settings-modal-commit.ts +11 -0
- package/src/input/settings-modal-data.ts +13 -80
- package/src/input/settings-modal-mutations.ts +33 -0
- package/src/input/settings-modal-secrets.ts +34 -0
- package/src/input/settings-modal-subscriptions.ts +1 -1
- package/src/input/settings-modal-types.ts +15 -1
- package/src/input/settings-modal.ts +28 -3
- package/src/input/worktree-setup-config.ts +1 -1
- package/src/main.ts +11 -9
- package/src/panels/agent-inspector-shared.ts +2 -2
- package/src/panels/base-panel.ts +2 -2
- package/src/panels/builtin/operations.ts +6 -8
- package/src/panels/builtin/session.ts +17 -0
- package/src/panels/builtin/shared.ts +5 -5
- package/src/panels/builtin-modals.ts +3 -3
- package/src/panels/confirm-state.ts +1 -1
- package/src/panels/cost-tracker-panel.ts +4 -4
- package/src/panels/diff-panel.ts +2 -2
- package/src/panels/diff-review-panel.ts +2 -2
- package/src/panels/expandable-list-panel.ts +2 -2
- package/src/panels/fleet-acts.ts +1 -1
- package/src/panels/fleet-observed-render.ts +1 -1
- package/src/panels/fleet-panel-format.ts +1 -1
- package/src/panels/fleet-panel.ts +1 -1
- package/src/panels/fleet-spawn.ts +1 -1
- package/src/panels/fleet-steer.ts +1 -1
- package/src/panels/fleet-transcript.ts +1 -1
- package/src/panels/git-panel.ts +1 -1
- package/src/panels/hosted-session-feed.ts +352 -0
- package/src/panels/hosted-session-panel.ts +221 -0
- package/src/panels/local-auth-panel.ts +3 -3
- package/src/panels/modals/devices-modal.ts +1 -1
- package/src/panels/modals/local-auth-modal.ts +1 -1
- package/src/panels/modals/pairing-modal.ts +1 -1
- package/src/panels/modals/services-modal.ts +1 -1
- package/src/panels/modals/settings-sync-modal.ts +1 -1
- package/src/panels/modals/subscription-modal.ts +1 -1
- package/src/panels/modals/work-plan-modal.ts +1 -1
- package/src/panels/notifications-panel.ts +1 -1
- package/src/panels/panel-confirm-overlay.ts +1 -1
- package/src/panels/plugins-panel.ts +2 -2
- package/src/panels/polish-core.ts +2 -2
- package/src/panels/polish-tables.ts +1 -1
- package/src/panels/polish.ts +2 -2
- package/src/panels/scrollable-list-panel.ts +3 -3
- package/src/panels/skills-panel.ts +3 -3
- package/src/panels/token-budget-panel.ts +5 -5
- package/src/panels/types.ts +1 -2
- package/src/permissions/prompt.ts +1 -1
- package/src/renderer/autocomplete-overlay.ts +1 -1
- package/src/renderer/block-actions-overlay.ts +1 -1
- package/src/renderer/bookmark-modal.ts +1 -1
- package/src/renderer/buffer.ts +1 -1
- package/src/renderer/code-block.ts +1 -1
- package/src/renderer/composer-fragments.ts +1 -1
- package/src/renderer/compositor.ts +2 -2
- package/src/renderer/config-modal.ts +1 -1
- package/src/renderer/context-inspector.ts +1 -1
- package/src/renderer/conversation-layout.ts +2 -2
- package/src/renderer/conversation-overlays.ts +1 -1
- package/src/renderer/conversation-surface.ts +2 -2
- package/src/renderer/diff-view.ts +1 -1
- package/src/renderer/diff.ts +1 -1
- package/src/renderer/file-picker-overlay.ts +1 -1
- package/src/renderer/fleet-tab-strip.ts +1 -1
- package/src/renderer/fullscreen-primitives.ts +2 -2
- package/src/renderer/fullscreen-workspace.ts +1 -1
- package/src/renderer/header-line.ts +1 -1
- package/src/renderer/help-overlay.ts +1 -1
- package/src/renderer/history-search-overlay.ts +2 -2
- package/src/renderer/layout.ts +5 -8
- package/src/renderer/markdown-inline.ts +1 -1
- package/src/renderer/markdown-table.ts +1 -1
- package/src/renderer/markdown.ts +1 -1
- package/src/renderer/mcp-workspace.ts +1 -1
- package/src/renderer/modal-factory.ts +2 -2
- package/src/renderer/model-workspace.ts +2 -2
- package/src/renderer/onboarding/onboarding-wizard.ts +1 -1
- package/src/renderer/overlay-box.ts +1 -1
- package/src/renderer/panel-composite.ts +1 -1
- package/src/renderer/panel-workspace-bar.ts +1 -1
- package/src/renderer/process-indicator.ts +1 -1
- package/src/renderer/profile-picker-modal.ts +1 -1
- package/src/renderer/search-overlay.ts +2 -2
- package/src/renderer/selection-modal-overlay.ts +1 -1
- package/src/renderer/session-picker-modal.ts +124 -3
- package/src/renderer/settings-modal-helpers.ts +2 -0
- package/src/renderer/settings-modal.ts +2 -2
- package/src/renderer/shell-surface.ts +2 -2
- package/src/renderer/system-message.ts +1 -1
- package/src/renderer/tab-strip.ts +1 -1
- package/src/renderer/theme-mode-config.ts +1 -1
- package/src/renderer/theme.ts +11 -12
- package/src/renderer/thinking.ts +1 -1
- package/src/renderer/tool-call.ts +2 -2
- package/src/renderer/tool-result-expanded-lines.ts +1 -1
- package/src/renderer/turn-injection.ts +7 -8
- package/src/renderer/ui-factory.ts +3 -3
- package/src/runtime/bootstrap-command-context.ts +4 -4
- package/src/runtime/bootstrap-command-parts.ts +5 -5
- package/src/runtime/bootstrap-core.ts +30 -30
- package/src/runtime/bootstrap-shell.ts +4 -4
- package/src/runtime/bootstrap.ts +128 -157
- package/src/runtime/client/approval-updates.ts +82 -0
- package/src/runtime/client/build-floors.ts +167 -0
- package/src/runtime/client/daemon-attach-handshake.ts +115 -0
- package/src/runtime/client/fleet-union.ts +147 -0
- package/src/runtime/client/host-service-status.ts +71 -0
- package/src/runtime/client/hosted-exit.ts +86 -0
- package/src/runtime/client/hosted-roster.ts +110 -0
- package/src/runtime/client/hosted-session-stream.ts +178 -0
- package/src/runtime/client/hosted-sessions.ts +187 -0
- package/src/runtime/client/operator-endpoint.ts +213 -0
- package/src/runtime/client/spine-adoption.ts +99 -0
- package/src/runtime/cloudflare-control-plane.ts +1 -1
- package/src/runtime/context-accounting-source.ts +1 -1
- package/src/runtime/context.ts +2 -2
- package/src/runtime/conversation-rewind-port.ts +42 -14
- package/src/runtime/daemon-attach-notices.ts +55 -19
- package/src/runtime/diagnostics/panels/ops.ts +1 -1
- package/src/runtime/disposal-wiring.ts +4 -24
- package/src/runtime/index.ts +119 -105
- package/src/runtime/install-self-check-startup.ts +2 -2
- package/src/runtime/interaction-seams.ts +1 -1
- package/src/runtime/knowledge-services.ts +8 -2
- package/src/runtime/legacy-daemon-migration.ts +4 -3
- package/src/runtime/legacy-daemon-reconcile.ts +3 -2
- package/src/runtime/memory-spine-transport.ts +37 -267
- package/src/runtime/notification-dispatch.ts +2 -2
- package/src/runtime/onboarding/apply.ts +2 -2
- package/src/runtime/onboarding/derivation.ts +2 -2
- package/src/runtime/onboarding/markers.ts +2 -2
- package/src/runtime/onboarding/progress.ts +2 -2
- package/src/runtime/onboarding/snapshot.ts +1 -1
- package/src/runtime/onboarding/state.ts +2 -2
- package/src/runtime/onboarding/types.ts +2 -2
- package/src/runtime/orchestrator-core-services.ts +1 -1
- package/src/runtime/path-shadow-startup.ts +28 -221
- package/src/runtime/power-keepawake-remote.ts +3 -2
- package/src/runtime/process-lifecycle.ts +2 -2
- package/src/runtime/provider-fallback.ts +10 -66
- package/src/runtime/recovery-autosave.ts +1 -1
- package/src/runtime/recovery-offer-wiring.ts +39 -23
- package/src/runtime/recovery-prompt.ts +31 -17
- package/src/runtime/relay-reachability-bridge.ts +53 -42
- package/src/runtime/release-artifacts.ts +2 -1
- package/src/runtime/runtime-services-types.ts +82 -35
- package/src/runtime/services.ts +305 -300
- package/src/runtime/session-resume-liveness-confirm.ts +1 -1
- package/src/runtime/ui-services.ts +7 -6
- package/src/runtime/update-check.ts +23 -43
- package/src/runtime/workspace-checkpointing.ts +1 -1
- package/src/runtime/wrfc-persistence.ts +2 -2
- package/src/shell/ui-openers.ts +30 -7
- package/src/utils/clipboard.ts +1 -1
- package/src/verification/verification-ledger.ts +10 -8
- package/src/version.ts +1 -1
- package/bin/goodvibes-daemon +0 -90
- package/src/cli/config-overrides.ts +0 -267
- package/src/cli/endpoints.ts +0 -109
- package/src/cli/parser.ts +0 -395
- package/src/cli/redaction.ts +0 -170
- package/src/cli/types.ts +0 -84
- package/src/cluster/commands.ts +0 -382
- package/src/cluster/remote-daemon-target.ts +0 -225
- package/src/cluster/render.ts +0 -268
- package/src/config/atomic-write.ts +0 -70
- package/src/config/credential-availability.ts +0 -122
- package/src/config/goodvibes-home.ts +0 -149
- package/src/config/index.ts +0 -88
- package/src/config/provider-model.ts +0 -23
- package/src/config/read-versioned.ts +0 -228
- package/src/core/alert-gating.ts +0 -67
- package/src/core/consolidation-receipt.ts +0 -41
- package/src/core/focus-tracker.ts +0 -41
- package/src/core/history.ts +0 -45
- package/src/core/memory-status.ts +0 -118
- package/src/core/orchestrator.ts +0 -7
- package/src/core/pairing-devices.ts +0 -49
- package/src/core/pairing-handoff.ts +0 -101
- package/src/core/pairing-offers.ts +0 -83
- package/src/core/pairing-origin.ts +0 -78
- package/src/core/rewind-turn-anchors.ts +0 -311
- package/src/core/session-recovery.ts +0 -210
- package/src/core/stable-host.ts +0 -171
- package/src/core/transcript-journal.ts +0 -503
- package/src/daemon/cli.ts +0 -693
- package/src/daemon/fatal-boot-report.ts +0 -111
- package/src/daemon/handlers/context.ts +0 -29
- package/src/daemon/handlers/contracts.ts +0 -77
- package/src/daemon/handlers/credentials.ts +0 -139
- package/src/daemon/handlers/drafts/draft-store.ts +0 -427
- package/src/daemon/handlers/drafts/index.ts +0 -17
- package/src/daemon/handlers/drafts/register.ts +0 -331
- package/src/daemon/handlers/errors.ts +0 -18
- package/src/daemon/handlers/inbox/cursor-store.ts +0 -457
- package/src/daemon/handlers/inbox/index.ts +0 -284
- package/src/daemon/handlers/inbox/mapping.ts +0 -192
- package/src/daemon/handlers/inbox/poller.ts +0 -212
- package/src/daemon/handlers/inbox/provider-adapter.ts +0 -156
- package/src/daemon/handlers/inbox/providers/discord.ts +0 -252
- package/src/daemon/handlers/inbox/providers/email.ts +0 -152
- package/src/daemon/handlers/inbox/providers/imap-client.ts +0 -300
- package/src/daemon/handlers/inbox/providers/route-util.ts +0 -24
- package/src/daemon/handlers/inbox/providers/slack.ts +0 -263
- package/src/daemon/handlers/index.ts +0 -117
- package/src/daemon/handlers/register.ts +0 -168
- package/src/daemon/handlers/remote/backends/cloud-terminal.ts +0 -142
- package/src/daemon/handlers/remote/backends/docker.ts +0 -79
- package/src/daemon/handlers/remote/backends/index.ts +0 -40
- package/src/daemon/handlers/remote/backends/local-process.ts +0 -113
- package/src/daemon/handlers/remote/backends/process-runner.ts +0 -127
- package/src/daemon/handlers/remote/backends/ssh.ts +0 -125
- package/src/daemon/handlers/remote/backends/types.ts +0 -97
- package/src/daemon/handlers/remote/dispatcher.ts +0 -181
- package/src/daemon/handlers/remote/index.ts +0 -119
- package/src/daemon/handlers/remote/peer-registry.ts +0 -357
- package/src/daemon/handlers/remote/service.ts +0 -191
- package/src/daemon/handlers/routing/inbox-bridge.ts +0 -71
- package/src/daemon/handlers/routing/index.ts +0 -261
- package/src/daemon/handlers/routing/route-store.ts +0 -319
- package/src/daemon/handlers/routing/routing-resolver.ts +0 -75
- package/src/daemon/handlers/sqlite-store.ts +0 -278
- package/src/daemon/handlers/triage/index.ts +0 -57
- package/src/daemon/handlers/triage/integration.ts +0 -213
- package/src/daemon/handlers/triage/pipeline.ts +0 -274
- package/src/daemon/handlers/triage/scorer.ts +0 -287
- package/src/daemon/handlers/triage/tagger/discord.ts +0 -187
- package/src/daemon/handlers/triage/tagger/imap.ts +0 -384
- package/src/daemon/handlers/triage/tagger/index.ts +0 -184
- package/src/daemon/handlers/triage/tagger/shared.ts +0 -70
- package/src/daemon/handlers/triage/tagger/slack.ts +0 -69
- package/src/daemon/handlers/triage/types.ts +0 -50
- package/src/daemon/lifecycle.ts +0 -41
- package/src/daemon/provision-wake-model.ts +0 -81
- package/src/daemon/safe-serve.ts +0 -61
- package/src/daemon/send/channels.ts +0 -200
- package/src/daemon/send/command.ts +0 -332
- package/src/daemon/send/composition.ts +0 -99
- package/src/daemon/send/failure-text.ts +0 -93
- package/src/daemon/send/inert-text.ts +0 -225
- package/src/daemon/send/stdin.ts +0 -24
- package/src/daemon/service-commands.ts +0 -329
- package/src/export/cost-utils.ts +0 -319
- package/src/input/selection.ts +0 -135
- package/src/plugins/loader.ts +0 -15
- package/src/renderer/bottom-bar.ts +0 -58
- package/src/renderer/conversation-tree.ts +0 -228
- package/src/runtime/agent-graph-composition.ts +0 -78
- package/src/runtime/channel-composition.ts +0 -46
- package/src/runtime/cluster-composition.ts +0 -124
- package/src/runtime/cluster-group-composition.ts +0 -284
- package/src/runtime/code-index-services.ts +0 -167
- package/src/runtime/daemon-handler-composition.ts +0 -76
- package/src/runtime/device-posture-composition.ts +0 -110
- package/src/runtime/durability-housekeeping.ts +0 -183
- package/src/runtime/durability-services.ts +0 -155
- package/src/runtime/embedded-service-factories.ts +0 -74
- package/src/runtime/feature-settings.ts +0 -154
- package/src/runtime/fleet-needs-input-push.ts +0 -70
- package/src/runtime/fleet-services.ts +0 -41
- package/src/runtime/idle-power-services.ts +0 -85
- package/src/runtime/mail-composition.ts +0 -65
- package/src/runtime/memory-fold.ts +0 -55
- package/src/runtime/operator-token-cleanup.ts +0 -109
- package/src/runtime/path-shadow.ts +0 -418
- package/src/runtime/perf/panel-health-monitor.ts +0 -18
- package/src/runtime/provider-optimizer-wiring.ts +0 -55
- package/src/runtime/reachability-notice.ts +0 -100
- package/src/runtime/remote-execution-composition.ts +0 -62
- package/src/runtime/session-liveness-marker.ts +0 -257
- package/src/runtime/session-pointer-surface.ts +0 -22
- package/src/runtime/session-storage-services.ts +0 -41
- package/src/runtime/surface-feature-flags.ts +0 -96
- package/src/runtime/terminal-output-guard.ts +0 -235
- package/src/runtime/trust/workspace-registration.ts +0 -192
- package/src/runtime/trust/workspace-trust.ts +0 -229
- package/src/runtime/ui/index.ts +0 -39
- package/src/runtime/ui/model-picker/data-provider.ts +0 -182
- package/src/runtime/ui/model-picker/health-enrichment.ts +0 -231
- package/src/runtime/ui/model-picker/index.ts +0 -59
- package/src/runtime/ui/model-picker/types.ts +0 -153
- package/src/runtime/ui/provider-health/data-provider.ts +0 -244
- package/src/runtime/ui/provider-health/fallback-visualizer.ts +0 -71
- package/src/runtime/ui/provider-health/index.ts +0 -46
- package/src/runtime/ui/provider-health/types.ts +0 -146
- package/src/runtime/ui-events.ts +0 -1
- package/src/runtime/ui-read-model-helpers.ts +0 -1
- package/src/runtime/ui-read-models-observability-maintenance.ts +0 -1
- package/src/runtime/ui-read-models-observability-options.ts +0 -1
- package/src/runtime/ui-read-models-observability-remote.ts +0 -1
- package/src/runtime/ui-read-models-observability-security.ts +0 -1
- package/src/runtime/ui-read-models-observability-system.ts +0 -1
- package/src/runtime/ui-read-models-observability.ts +0 -1
- package/src/runtime/ui-service-queries.ts +0 -1
- package/src/runtime/voice-setup-services.ts +0 -98
- package/src/runtime/workstream-attempts-validation.ts +0 -77
- package/src/runtime/workstream-draft-edits.ts +0 -95
- package/src/runtime/workstream-draft-store.ts +0 -274
- package/src/runtime/workstream-draft-types.ts +0 -42
- package/src/runtime/workstream-services.ts +0 -373
- package/src/tools/index.ts +0 -1
- package/src/types/grid.ts +0 -48
- package/src/types/sql-js.d.ts +0 -15
- package/src/work-plans/work-plan-store.ts +0 -702
package/src/config/index.ts
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Config system barrel export.
|
|
3
|
-
*
|
|
4
|
-
* Provides:
|
|
5
|
-
* - ConfigManager class and all schema types
|
|
6
|
-
* - Pure helpers that derive values from an explicit ConfigManager instance
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
export { ConfigManager } from '@pellux/goodvibes-sdk/platform/config';
|
|
10
|
-
export type { DeepReadonly } from '@pellux/goodvibes-sdk/platform/config';
|
|
11
|
-
export type { GoodVibesConfig, ConfigKey, ConfigValue, ConfigSetting, PermissionMode, PermissionAction, PermissionsToolConfig, NotificationsConfig } from '@pellux/goodvibes-sdk/platform/config';
|
|
12
|
-
export { DEFAULT_CONFIG, CONFIG_SCHEMA } from '@pellux/goodvibes-sdk/platform/config';
|
|
13
|
-
export { ConfigError } from '@pellux/goodvibes-sdk/platform/types';
|
|
14
|
-
|
|
15
|
-
import { readFileSync } from 'fs';
|
|
16
|
-
import { ConfigManager } from '@pellux/goodvibes-sdk/platform/config';
|
|
17
|
-
import type { GoodVibesConfig } from '@pellux/goodvibes-sdk/platform/config';
|
|
18
|
-
import { logger } from '@pellux/goodvibes-sdk/platform/utils';
|
|
19
|
-
import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils';
|
|
20
|
-
import { getProviderIdFromModel } from './provider-model.ts';
|
|
21
|
-
|
|
22
|
-
export function getConfigSnapshot(configManager: Pick<ConfigManager, 'getRaw'>): Readonly<GoodVibesConfig> {
|
|
23
|
-
return configManager.getRaw();
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export function getConfiguredModelId(configManager: Pick<ConfigManager, 'get'>): string {
|
|
27
|
-
return configManager.get('provider.model');
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export function getConfiguredProviderId(configManager: Pick<ConfigManager, 'get'>): string {
|
|
31
|
-
return getProviderIdFromModel(configManager.get('provider.model'));
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export function getConfiguredEmbeddingProviderId(configManager: Pick<ConfigManager, 'get'>): string {
|
|
35
|
-
return configManager.get('provider.embeddingProvider');
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export function isAutoApproveEnabled(configManager: Pick<ConfigManager, 'get'>): boolean {
|
|
39
|
-
return configManager.get('behavior.autoApprove');
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* True when the current permission posture effectively auto-approves everything:
|
|
44
|
-
* auto-approve on, permission mode `allow-all`, or a `custom` mode whose every
|
|
45
|
-
* tool action is `allow`. Drives the footer's danger indicator.
|
|
46
|
-
*/
|
|
47
|
-
export function isEffectiveDangerMode(configManager: Pick<ConfigManager, 'get' | 'getCategory'>): boolean {
|
|
48
|
-
if (configManager.get('behavior.autoApprove')) return true;
|
|
49
|
-
const permMode = configManager.get('permissions.mode');
|
|
50
|
-
if (permMode === 'allow-all') return true;
|
|
51
|
-
if (permMode === 'custom') {
|
|
52
|
-
const tools = configManager.getCategory('permissions').tools;
|
|
53
|
-
if (Object.values(tools).every((action) => action === 'allow')) return true;
|
|
54
|
-
}
|
|
55
|
-
return false;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export function getWorkingDirectory(configManager: Pick<ConfigManager, 'getWorkingDirectory'>): string | null {
|
|
59
|
-
return configManager.getWorkingDirectory();
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export function getConfiguredSystemPrompt(configManager: Pick<ConfigManager, 'get'>): string | undefined {
|
|
63
|
-
const file = configManager.get('provider.systemPromptFile');
|
|
64
|
-
if (!file) return undefined;
|
|
65
|
-
try {
|
|
66
|
-
return readFileSync(file, 'utf-8');
|
|
67
|
-
} catch (err) {
|
|
68
|
-
logger.debug('systemPrompt file read failed (non-fatal)', { file, error: summarizeError(err) });
|
|
69
|
-
return undefined;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export { getConfiguredApiKeys, resolveApiKeys } from '@pellux/goodvibes-sdk/platform/config';
|
|
74
|
-
|
|
75
|
-
// Client-side credential-status read (honest-degrade, status-only). When the
|
|
76
|
-
// TUI acts as a client of an adopted external daemon it reads provider/model/secret
|
|
77
|
-
// STATUS from that daemon's `credentials.get`, never from its own surfaceRoot store.
|
|
78
|
-
export {
|
|
79
|
-
credentialReadModeFromHostMode,
|
|
80
|
-
deriveCredentialAvailability,
|
|
81
|
-
readClientCredentialStatus,
|
|
82
|
-
} from './credential-availability.ts';
|
|
83
|
-
export type {
|
|
84
|
-
CredentialAvailability,
|
|
85
|
-
CredentialReadMode,
|
|
86
|
-
CredentialStatusEntry,
|
|
87
|
-
CredentialStatusOutcome,
|
|
88
|
-
} from './credential-availability.ts';
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { DEFAULT_CONFIG } from '@pellux/goodvibes-sdk/platform/config';
|
|
2
|
-
|
|
3
|
-
export function getProviderIdFromModel(model: unknown): string {
|
|
4
|
-
const raw = String(model ?? '').trim();
|
|
5
|
-
if (!raw) return getProviderIdFromModel(DEFAULT_CONFIG.provider.model);
|
|
6
|
-
const separator = raw.indexOf(':');
|
|
7
|
-
return separator > 0 ? raw.slice(0, separator) : raw;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export function getModelIdFromProviderModel(model: unknown): string {
|
|
11
|
-
const raw = String(model ?? '').trim();
|
|
12
|
-
if (!raw) return String(DEFAULT_CONFIG.provider.model);
|
|
13
|
-
const separator = raw.indexOf(':');
|
|
14
|
-
return separator > 0 ? raw.slice(separator + 1) : raw;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export function formatProviderModel(providerId: string, modelId: string): string {
|
|
18
|
-
const provider = providerId.trim();
|
|
19
|
-
const model = modelId.trim();
|
|
20
|
-
if (!provider) return model;
|
|
21
|
-
if (!model) return `${provider}:`;
|
|
22
|
-
return model.includes(':') ? model : `${provider}:${model}`;
|
|
23
|
-
}
|
|
@@ -1,228 +0,0 @@
|
|
|
1
|
-
import { existsSync, readFileSync, readdirSync, renameSync, statSync, unlinkSync } from 'node:fs';
|
|
2
|
-
import { join } from 'node:path';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* The suffix every quarantined file in this codebase gets. Exported so the
|
|
6
|
-
* other producer of these files (the transcript journal's corrupt-tail
|
|
7
|
-
* quarantine) and the reclaim sweep below all agree on one spelling.
|
|
8
|
-
*/
|
|
9
|
-
export const UNRECOGNIZED_SUFFIX = '.unrecognized';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* A migration function that transforms data from version N to N+1.
|
|
13
|
-
* Receives the raw parsed object and must return the upgraded object.
|
|
14
|
-
*/
|
|
15
|
-
export type VersionMigration = (data: Record<string, unknown>) => Record<string, unknown>;
|
|
16
|
-
|
|
17
|
-
export interface ReadVersionedOptions {
|
|
18
|
-
/**
|
|
19
|
-
* The version number this reader expects. When the file version equals
|
|
20
|
-
* `currentVersion`, no migrations are run. When it is lower, migrations
|
|
21
|
-
* are applied stepwise. When it is higher or unrecognised, `onUnknown`
|
|
22
|
-
* behaviour fires.
|
|
23
|
-
*/
|
|
24
|
-
readonly currentVersion: number;
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Optional stepwise migrations indexed by the FROM version.
|
|
28
|
-
* `migrations[1]` upgrades version-1 data to version-2 data.
|
|
29
|
-
* Applied in ascending order until `currentVersion` is reached.
|
|
30
|
-
*/
|
|
31
|
-
readonly migrations?: Readonly<Record<number, VersionMigration>>;
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* What to do when the file version is unrecognised (higher than
|
|
35
|
-
* `currentVersion` or missing/non-numeric).
|
|
36
|
-
*
|
|
37
|
-
* `'quarantine'` — rename the file to `<path>.unrecognized` and return null.
|
|
38
|
-
*/
|
|
39
|
-
readonly onUnknown: 'quarantine';
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Migration-aware, quarantine-on-failure versioned file reader.
|
|
44
|
-
*
|
|
45
|
-
* Parse flow:
|
|
46
|
-
* 1. If the file does not exist → return null.
|
|
47
|
-
* 2. If JSON is corrupt → quarantine to `<path>.unrecognized`, return null.
|
|
48
|
-
* 3. If the version field is missing or higher than currentVersion →
|
|
49
|
-
* quarantine, return null.
|
|
50
|
-
* 4. If the version is lower than currentVersion → apply stepwise migrations.
|
|
51
|
-
* If no migration exists for a version gap, or a migration throws,
|
|
52
|
-
* quarantine and return null.
|
|
53
|
-
* 5. Return the (possibly migrated) object. Callers are responsible for
|
|
54
|
-
* narrowing the returned value — this helper handles versioning and
|
|
55
|
-
* corruption only, not schema validation.
|
|
56
|
-
*/
|
|
57
|
-
export function readVersioned<T extends { version: number }>(
|
|
58
|
-
path: string,
|
|
59
|
-
options: ReadVersionedOptions,
|
|
60
|
-
): T | null {
|
|
61
|
-
if (!existsSync(path)) return null;
|
|
62
|
-
|
|
63
|
-
let raw: unknown;
|
|
64
|
-
try {
|
|
65
|
-
raw = JSON.parse(readFileSync(path, 'utf-8'));
|
|
66
|
-
} catch {
|
|
67
|
-
quarantine(path);
|
|
68
|
-
return null;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
if (!isPlainObject(raw)) {
|
|
72
|
-
quarantine(path);
|
|
73
|
-
return null;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const fileVersion = raw['version'];
|
|
77
|
-
if (typeof fileVersion !== 'number' || !Number.isFinite(fileVersion)) {
|
|
78
|
-
quarantine(path);
|
|
79
|
-
return null;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if (fileVersion > options.currentVersion) {
|
|
83
|
-
// Produced by a newer process — quarantine rather than corrupt.
|
|
84
|
-
quarantine(path);
|
|
85
|
-
return null;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
let data: Record<string, unknown> = raw;
|
|
89
|
-
|
|
90
|
-
if (fileVersion < options.currentVersion) {
|
|
91
|
-
const migrations = options.migrations ?? {};
|
|
92
|
-
for (let v = fileVersion; v < options.currentVersion; v++) {
|
|
93
|
-
const migrate = migrations[v];
|
|
94
|
-
if (!migrate) {
|
|
95
|
-
// No migration path for this version gap — quarantine.
|
|
96
|
-
quarantine(path);
|
|
97
|
-
return null;
|
|
98
|
-
}
|
|
99
|
-
try {
|
|
100
|
-
data = migrate(data);
|
|
101
|
-
} catch {
|
|
102
|
-
quarantine(path);
|
|
103
|
-
return null;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
return data as T;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// ─── Internal helpers ─────────────────────────────────────────────────────────
|
|
112
|
-
|
|
113
|
-
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
114
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
function quarantine(path: string): void {
|
|
118
|
-
try {
|
|
119
|
-
renameSync(path, `${path}${UNRECOGNIZED_SUFFIX}`);
|
|
120
|
-
} catch {
|
|
121
|
-
// Best-effort — if rename fails (e.g. race), proceed silently.
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// ─── Quarantine reclaim ───────────────────────────────────────────────────────
|
|
126
|
-
//
|
|
127
|
-
// Quarantining renames a bad file out of the way so a human can inspect it,
|
|
128
|
-
// and until now nothing ever removed the result — every corrupt config file
|
|
129
|
-
// and every torn journal tail left a `.unrecognized` file behind permanently.
|
|
130
|
-
// Forensic value is real, so the retention window below is deliberately long,
|
|
131
|
-
// but "keep forever" is a leak.
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* How long a quarantined file is kept before it is reclaimed: 30 days
|
|
135
|
-
* (2_592_000_000 ms). These files exist so a person can look at what went
|
|
136
|
-
* wrong, so the window is a month rather than the hours-to-days retention the
|
|
137
|
-
* live durability artefacts get — long enough to survive a holiday, short
|
|
138
|
-
* enough that a recurring corruption cannot fill a disk.
|
|
139
|
-
*/
|
|
140
|
-
export const QUARANTINE_RETENTION_MS = 30 * 24 * 60 * 60 * 1000;
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Hard ceiling on quarantined files kept per swept directory, newest kept.
|
|
144
|
-
* The age rule alone cannot bound a fast repeating corruption (a boot loop
|
|
145
|
-
* quarantining the same file every restart), so a count cap runs alongside it.
|
|
146
|
-
*/
|
|
147
|
-
export const QUARANTINE_MAX_FILES_PER_DIR = 50;
|
|
148
|
-
|
|
149
|
-
export interface QuarantineReapResult {
|
|
150
|
-
/** Quarantined files examined across every directory. */
|
|
151
|
-
readonly scanned: number;
|
|
152
|
-
/** Quarantined files deleted. */
|
|
153
|
-
readonly reaped: number;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
export interface QuarantineReapOptions {
|
|
157
|
-
readonly now?: () => number;
|
|
158
|
-
/** Override the age window (tests). */
|
|
159
|
-
readonly maxAgeMs?: number;
|
|
160
|
-
/** Override the per-directory count cap (tests). */
|
|
161
|
-
readonly maxFilesPerDir?: number;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* Delete `.unrecognized` quarantine files that are past the retention window,
|
|
166
|
-
* plus any beyond the per-directory count cap (newest kept).
|
|
167
|
-
*
|
|
168
|
-
* Each directory is scanned non-recursively; a missing or unreadable directory
|
|
169
|
-
* contributes nothing and is not an error. Idempotent, and safe to run
|
|
170
|
-
* concurrently from several processes — a file another sweeper already
|
|
171
|
-
* unlinked (ENOENT) counts as reclaimed rather than failing the sweep.
|
|
172
|
-
*/
|
|
173
|
-
export function reapQuarantinedFiles(
|
|
174
|
-
directories: readonly string[],
|
|
175
|
-
options: QuarantineReapOptions = {},
|
|
176
|
-
): QuarantineReapResult {
|
|
177
|
-
const now = options.now?.() ?? Date.now();
|
|
178
|
-
const maxAgeMs = options.maxAgeMs ?? QUARANTINE_RETENTION_MS;
|
|
179
|
-
const maxFilesPerDir = options.maxFilesPerDir ?? QUARANTINE_MAX_FILES_PER_DIR;
|
|
180
|
-
|
|
181
|
-
let scanned = 0;
|
|
182
|
-
let reaped = 0;
|
|
183
|
-
|
|
184
|
-
for (const dir of new Set(directories)) {
|
|
185
|
-
let names: string[];
|
|
186
|
-
try {
|
|
187
|
-
names = readdirSync(dir).filter((name) => name.endsWith(UNRECOGNIZED_SUFFIX));
|
|
188
|
-
} catch {
|
|
189
|
-
continue;
|
|
190
|
-
}
|
|
191
|
-
scanned += names.length;
|
|
192
|
-
|
|
193
|
-
const survivors: { readonly path: string; readonly mtimeMs: number }[] = [];
|
|
194
|
-
for (const name of names) {
|
|
195
|
-
const path = join(dir, name);
|
|
196
|
-
let mtimeMs: number;
|
|
197
|
-
try {
|
|
198
|
-
mtimeMs = statSync(path).mtimeMs;
|
|
199
|
-
} catch {
|
|
200
|
-
// Vanished under us (another sweeper) — nothing left to reclaim.
|
|
201
|
-
continue;
|
|
202
|
-
}
|
|
203
|
-
if (now - mtimeMs > maxAgeMs) {
|
|
204
|
-
if (unlinkQuarantined(path)) reaped++;
|
|
205
|
-
continue;
|
|
206
|
-
}
|
|
207
|
-
survivors.push({ path, mtimeMs });
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
if (survivors.length > maxFilesPerDir) {
|
|
211
|
-
survivors.sort((a, b) => a.mtimeMs - b.mtimeMs); // oldest first
|
|
212
|
-
for (const victim of survivors.slice(0, survivors.length - maxFilesPerDir)) {
|
|
213
|
-
if (unlinkQuarantined(victim.path)) reaped++;
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
return { scanned, reaped };
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
function unlinkQuarantined(path: string): boolean {
|
|
222
|
-
try {
|
|
223
|
-
unlinkSync(path);
|
|
224
|
-
return true;
|
|
225
|
-
} catch (err) {
|
|
226
|
-
return (err as NodeJS.ErrnoException | undefined)?.code === 'ENOENT';
|
|
227
|
-
}
|
|
228
|
-
}
|
package/src/core/alert-gating.ts
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* alert-gating — shared config + focus gating logic for the unfocused-user
|
|
3
|
-
* alert classes (budget-breach, long-task, agent/chain failure,
|
|
4
|
-
* awaiting-approval). Each alert class has its own on/off config key
|
|
5
|
-
* (default true); a single master key, `behavior.notifyOnlyWhenUnfocused`
|
|
6
|
-
* (default true), decides whether any of them additionally require the
|
|
7
|
-
* terminal to be unfocused-or-unknown before firing.
|
|
8
|
-
*
|
|
9
|
-
* Extracted so every alert-class module (long-task-notifier.ts,
|
|
10
|
-
* budget-breach-notifier.ts, approval-alert.ts, and the agent/chain-failure
|
|
11
|
-
* wiring in turn-event-wiring.ts) shares one implementation of "should this
|
|
12
|
-
* fire right now" instead of re-deriving the same two config reads and the
|
|
13
|
-
* same focus check.
|
|
14
|
-
*/
|
|
15
|
-
import type { FocusTracker } from './focus-tracker.ts';
|
|
16
|
-
|
|
17
|
-
/** Minimal config-read surface every gating check needs. */
|
|
18
|
-
export type ConfigGet = (key: string) => unknown;
|
|
19
|
-
|
|
20
|
-
/** Read a TUI-local synthetic boolean setting, defaulting when absent/invalid. */
|
|
21
|
-
export function readBooleanConfig(configGet: ConfigGet, key: string, defaultValue: boolean): boolean {
|
|
22
|
-
const raw = configGet(key);
|
|
23
|
-
if (typeof raw === 'boolean') return raw;
|
|
24
|
-
if (raw === undefined || raw === null) return defaultValue;
|
|
25
|
-
// Tolerate string/number forms the same way the rest of the config layer does
|
|
26
|
-
// (settings-modal writes real booleans, but env/file edits may not).
|
|
27
|
-
if (raw === 'true' || raw === 1) return true;
|
|
28
|
-
if (raw === 'false' || raw === 0) return false;
|
|
29
|
-
return defaultValue;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/** `behavior.notifyOnlyWhenUnfocused` — master gate, default on. */
|
|
33
|
-
export function readNotifyOnlyWhenUnfocused(configGet: ConfigGet): boolean {
|
|
34
|
-
return readBooleanConfig(configGet, 'behavior.notifyOnlyWhenUnfocused', true);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Decide whether a given alert class should fire right now.
|
|
39
|
-
*
|
|
40
|
-
* `classConfigKey` is the per-class on/off switch (e.g.
|
|
41
|
-
* 'behavior.notifyOnBudgetBreach'); default true when absent. When that key
|
|
42
|
-
* is off, the class never fires regardless of focus. When it's on, the
|
|
43
|
-
* result additionally depends on the master `notifyOnlyWhenUnfocused` gate:
|
|
44
|
-
* if that master gate is off, the class fires unconditionally (today's
|
|
45
|
-
* pre-focus-tracking behavior); if on (the default), it only fires when the
|
|
46
|
-
* terminal is unfocused or focus state was never observed (see
|
|
47
|
-
* FocusTracker.shouldAlertWhenUnfocused).
|
|
48
|
-
*/
|
|
49
|
-
export function shouldFireAlert(
|
|
50
|
-
focusTracker: Pick<FocusTracker, 'shouldAlertWhenUnfocused'>,
|
|
51
|
-
configGet: ConfigGet,
|
|
52
|
-
classConfigKey: string,
|
|
53
|
-
): boolean {
|
|
54
|
-
if (!readBooleanConfig(configGet, classConfigKey, true)) return false;
|
|
55
|
-
if (!readNotifyOnlyWhenUnfocused(configGet)) return true;
|
|
56
|
-
return focusTracker.shouldAlertWhenUnfocused();
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* notifyCompletion (SDK platform/utils) only rings the bell above 5s of
|
|
61
|
-
* "duration" and only pops a desktop notification above 30s — a heuristic
|
|
62
|
-
* tuned for long-running-turn notifications. The alert classes in this
|
|
63
|
-
* directory are point-in-time events with no natural duration, so they pass
|
|
64
|
-
* this constant as the `durationMs` argument to force both the bell and the
|
|
65
|
-
* desktop popup unconditionally.
|
|
66
|
-
*/
|
|
67
|
-
export const FORCE_NOTIFY_DURATION_MS = 30_001;
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
// ---------------------------------------------------------------------------
|
|
2
|
-
// consolidation-receipt.ts — the one-line notice for an idle-time memory
|
|
3
|
-
// consolidation run.
|
|
4
|
-
//
|
|
5
|
-
// The SDK's MemoryConsolidationScheduler runs at idle and produces a
|
|
6
|
-
// MemoryConsolidationRunReceipt (merged / archived / decayed / proposed). This
|
|
7
|
-
// formats it into the same one-line shape every other attach-time receipt
|
|
8
|
-
// uses, so a run that changed something surfaces on the next attach like a
|
|
9
|
-
// crash/update/migration receipt. A pure no-op run yields null — no noise.
|
|
10
|
-
//
|
|
11
|
-
// A run that PROPOSED something (a contradiction or cross-scope-duplicate
|
|
12
|
-
// awaiting human judgment — never auto-applied) names where to actually look:
|
|
13
|
-
// the Memory modal's Proposals tab (`/memory`, then the Proposals tab —
|
|
14
|
-
// memory-modal.ts's proposalsTab()), which lists each proposal's kind,
|
|
15
|
-
// reason, and affected record ids and jumps to them in the Review Queue.
|
|
16
|
-
// Without this pointer the receipt line was the only trace a proposal ever
|
|
17
|
-
// existed — a count with nowhere to go.
|
|
18
|
-
// ---------------------------------------------------------------------------
|
|
19
|
-
|
|
20
|
-
import type { MemoryConsolidationRunReceipt } from '@pellux/goodvibes-sdk/platform/state';
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* A one-line receipt for a consolidation run that changed something, or null
|
|
24
|
-
* when the run merged/archived/decayed/proposed nothing (a quiet idle pass —
|
|
25
|
-
* no notice, matching the check-in "stayed quiet" discipline).
|
|
26
|
-
*/
|
|
27
|
-
export function formatConsolidationReceipt(receipt: MemoryConsolidationRunReceipt): string | null {
|
|
28
|
-
const merged = receipt.merged.length;
|
|
29
|
-
const archived = receipt.archived.length;
|
|
30
|
-
const decayed = receipt.decayed.length;
|
|
31
|
-
const proposed = receipt.proposed.length;
|
|
32
|
-
if (merged + archived + decayed + proposed === 0) return null;
|
|
33
|
-
const parts: string[] = [];
|
|
34
|
-
if (merged) parts.push(`${merged} merged`);
|
|
35
|
-
if (archived) parts.push(`${archived} archived`);
|
|
36
|
-
if (decayed) parts.push(`${decayed} decayed`);
|
|
37
|
-
if (proposed) parts.push(`${proposed} proposed`);
|
|
38
|
-
const base = `Memory consolidation: ${parts.join(', ')} (scanned ${receipt.scanned}).`;
|
|
39
|
-
if (proposed === 0) return base;
|
|
40
|
-
return `${base} Review the ${proposed} proposed change${proposed === 1 ? '' : 's'} with /memory (Proposals tab).`;
|
|
41
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* focus-tracker — tracks whether the terminal window currently has OS-level
|
|
3
|
-
* input focus, using the terminal focus-reporting protocol (DECSET ?1004h,
|
|
4
|
-
* enabled at terminal setup in main.ts). The SDK's InputTokenizer already
|
|
5
|
-
* parses the resulting `\x1b[I` (focus-in) / `\x1b[O` (focus-out) sequences
|
|
6
|
-
* into `{ type: 'focus', action }` tokens (platform/core/tokenizer.ts); this
|
|
7
|
-
* module is the single place those tokens land (consumed in
|
|
8
|
-
* src/input/handler-feed.ts's feedInputTokens()).
|
|
9
|
-
*
|
|
10
|
-
* Honest degradation: a terminal that does not implement focus reporting
|
|
11
|
-
* (or a multiplexer that swallows the sequences) never sends focus tokens.
|
|
12
|
-
* In that case `isFocused()` stays `null` forever — "unknown", never a
|
|
13
|
-
* guessed `true`/`false`. Callers that gate a user-facing behavior on focus
|
|
14
|
-
* (e.g. the unfocused-alert notifiers in this directory) must treat `null`
|
|
15
|
-
* the same as "not focused" per the fallback rule: alerts fire when the
|
|
16
|
-
* terminal is definitely unfocused OR when focus state was never observed.
|
|
17
|
-
*/
|
|
18
|
-
export class FocusTracker {
|
|
19
|
-
private focused: boolean | null = null;
|
|
20
|
-
|
|
21
|
-
/** True/false once at least one focus token has arrived; null if none ever has. */
|
|
22
|
-
isFocused(): boolean | null {
|
|
23
|
-
return this.focused;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/** Called from the input pipeline on every focus token. */
|
|
27
|
-
setFocused(value: boolean): void {
|
|
28
|
-
this.focused = value;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* The alert-gating rule shared by every unfocused-alert notifier: fire
|
|
33
|
-
* when the terminal is known to be unfocused, or when focus was never
|
|
34
|
-
* observed (honest fallback — never silently suppress on an unknown
|
|
35
|
-
* terminal). Only `isFocused() === true` (a real, observed focus-in with
|
|
36
|
-
* no observed focus-out since) suppresses an alert.
|
|
37
|
-
*/
|
|
38
|
-
shouldAlertWhenUnfocused(): boolean {
|
|
39
|
-
return this.focused !== true;
|
|
40
|
-
}
|
|
41
|
-
}
|
package/src/core/history.ts
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { type Line, createEmptyLine } from '../types/grid.ts';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* InfiniteBuffer - Manages the complete conversation history as a list of lines.
|
|
5
|
-
*/
|
|
6
|
-
export class InfiniteBuffer {
|
|
7
|
-
private lines: Line[] = [];
|
|
8
|
-
|
|
9
|
-
public addLine(line: Line): void {
|
|
10
|
-
this.lines.push(line);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
public addLines(lines: Line[]): void {
|
|
14
|
-
this.lines.push(...lines);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
public getLineCount(): number {
|
|
18
|
-
return this.lines.length;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
public getAllLines(): Line[] {
|
|
22
|
-
return this.lines;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
public getSnapshot(startLine: number, height: number, width: number): Line[] {
|
|
26
|
-
const end = Math.min(this.lines.length, startLine + height);
|
|
27
|
-
const slice = this.lines.slice(startLine, end);
|
|
28
|
-
|
|
29
|
-
while (slice.length < height) {
|
|
30
|
-
slice.unshift(createEmptyLine(width));
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return slice;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
public clear(): void {
|
|
37
|
-
this.lines = [];
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
public truncateToLine(lineIndex: number): void {
|
|
41
|
-
if (lineIndex >= 0 && lineIndex < this.lines.length) {
|
|
42
|
-
this.lines.length = lineIndex;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
// ---------------------------------------------------------------------------
|
|
2
|
-
// memory-status.ts — the surface-facing projection of the daemon's memory
|
|
3
|
-
// governance (ops.memory.get + OPS_MEMORY_PRESSURE).
|
|
4
|
-
//
|
|
5
|
-
// The SDK's MemoryGovernor owns the policy: it samples RSS/heap against a
|
|
6
|
-
// budget, sheds memory by tier (trimming registered caches, pausing deferrable
|
|
7
|
-
// background jobs), refuses new expensive work at the critical tier, and trips
|
|
8
|
-
// on a genuine leak before the OS OOM-kills it. This module is the read-only
|
|
9
|
-
// projection the /health memory (doctor) surface renders from — the snapshot
|
|
10
|
-
// rows — and the attention line OPS_MEMORY_PRESSURE produces when the tier
|
|
11
|
-
// changes or the tripwire fires.
|
|
12
|
-
//
|
|
13
|
-
// Pure formatting only (no I/O): the command fetches the typed verb response
|
|
14
|
-
// over the operator invoke seam (memory-diagnostics-gateway.ts) and hands it
|
|
15
|
-
// here, so these builders are unit-testable against fixture shapes.
|
|
16
|
-
// ---------------------------------------------------------------------------
|
|
17
|
-
|
|
18
|
-
import type { OperatorMethodOutput } from '@pellux/goodvibes-sdk';
|
|
19
|
-
import type { OpsEvent } from '@/runtime/index.ts';
|
|
20
|
-
|
|
21
|
-
/** ops.memory.get output — the full governor snapshot. */
|
|
22
|
-
export type MemoryGovernorSnapshotResult = OperatorMethodOutput<'ops.memory.get'>;
|
|
23
|
-
/** The OPS_MEMORY_PRESSURE event payload (a tier change or a tripwire firing). */
|
|
24
|
-
export type MemoryPressurePayload = Extract<OpsEvent, { type: 'OPS_MEMORY_PRESSURE' }>;
|
|
25
|
-
|
|
26
|
-
/** Human MB (the governor already reports MB as numbers; round to 1 decimal). */
|
|
27
|
-
export function formatMb(mb: number | null | undefined): string {
|
|
28
|
-
if (mb === null || mb === undefined || !Number.isFinite(mb)) return 'unknown';
|
|
29
|
-
return `${mb >= 100 ? Math.round(mb) : Math.round(mb * 10) / 10} MB`;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/** Human byte size for a cache footprint estimate. */
|
|
33
|
-
export function formatMemoryBytes(bytes: number | null | undefined): string {
|
|
34
|
-
if (bytes === null || bytes === undefined || !Number.isFinite(bytes) || bytes < 0) return 'size n/a';
|
|
35
|
-
if (bytes < 1024) return `${bytes} B`;
|
|
36
|
-
const units = ['KB', 'MB', 'GB'];
|
|
37
|
-
let value = bytes / 1024;
|
|
38
|
-
let unit = 0;
|
|
39
|
-
while (value >= 1024 && unit < units.length - 1) {
|
|
40
|
-
value /= 1024;
|
|
41
|
-
unit += 1;
|
|
42
|
-
}
|
|
43
|
-
return `${value >= 10 ? value.toFixed(0) : value.toFixed(1)} ${units[unit]}`;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/** A plain-language note for the current tier (the governor's posture at this tier). */
|
|
47
|
-
export function memoryTierNote(tier: MemoryGovernorSnapshotResult['tier']): string {
|
|
48
|
-
switch (tier) {
|
|
49
|
-
case 'normal': return 'footprint is comfortably within budget';
|
|
50
|
-
case 'elevated': return 'trimming caches to a floor and running gc';
|
|
51
|
-
case 'high': return 'flushing caches and pausing deferrable background jobs';
|
|
52
|
-
case 'critical': return 'refusing new expensive work until the footprint recovers';
|
|
53
|
-
default: return '';
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* The /health memory (doctor) rows — the honest account of the daemon defending
|
|
59
|
-
* its footprint. Order: tier + posture, budget vs RSS, heap, tier thresholds,
|
|
60
|
-
* per-cache footprints the governor can shrink, which deferrable jobs are
|
|
61
|
-
* paused, and the leak-tripwire state.
|
|
62
|
-
*/
|
|
63
|
-
export function memoryStatusLines(snapshot: MemoryGovernorSnapshotResult): string[] {
|
|
64
|
-
const lines: string[] = [];
|
|
65
|
-
lines.push(` tier: ${snapshot.tier} — ${memoryTierNote(snapshot.tier)}`);
|
|
66
|
-
if (snapshot.refusingExpensiveWork) {
|
|
67
|
-
lines.push(' expensive work: REFUSED (critical tier) — new ingestion / reindex / voice install is declined until RSS recovers');
|
|
68
|
-
}
|
|
69
|
-
lines.push(` budget: ${formatMb(snapshot.rssMb)} rss / ${formatMb(snapshot.budgetMb)} budget (${Math.round(snapshot.usedPct)}%)`);
|
|
70
|
-
const heap = snapshot.heapTotalMb !== undefined
|
|
71
|
-
? `${formatMb(snapshot.heapUsedMb)} used / ${formatMb(snapshot.heapTotalMb)} total`
|
|
72
|
-
: formatMb(snapshot.heapUsedMb);
|
|
73
|
-
lines.push(` heap: ${heap}`);
|
|
74
|
-
lines.push(` tiers: elevated ${snapshot.thresholds.elevatedPct}% · high ${snapshot.thresholds.highPct}% · critical ${snapshot.thresholds.criticalPct}%`);
|
|
75
|
-
|
|
76
|
-
if (snapshot.caches.length === 0) {
|
|
77
|
-
lines.push(' caches: none registered');
|
|
78
|
-
} else {
|
|
79
|
-
lines.push(` caches: ${snapshot.caches.length}`);
|
|
80
|
-
for (const cache of snapshot.caches) {
|
|
81
|
-
const size = cache.estimatedBytes !== undefined ? `, ~${formatMemoryBytes(cache.estimatedBytes)}` : '';
|
|
82
|
-
lines.push(` ${cache.id} (${cache.name}): ${cache.entries} entries${size}`);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
lines.push(snapshot.pausedJobs.length === 0
|
|
87
|
-
? ' paused jobs: none'
|
|
88
|
-
: ` paused jobs: ${snapshot.pausedJobs.join(', ')}`);
|
|
89
|
-
|
|
90
|
-
if (snapshot.tripwire.armed) {
|
|
91
|
-
lines.push(` tripwire: ARMED — watching for a sustained >${snapshot.tripwire.rateMbPerSec} MB/s post-flush leak (held ${Math.round(snapshot.tripwire.sustainedSec)}s)`);
|
|
92
|
-
} else {
|
|
93
|
-
lines.push(' tripwire: disarmed (no post-flush leak growth under watch)');
|
|
94
|
-
}
|
|
95
|
-
return lines;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* The attention line OPS_MEMORY_PRESSURE produces: a one-liner naming the new
|
|
100
|
-
* tier and the RSS/budget, plus a distinct escalation when the leak tripwire
|
|
101
|
-
* fires (the daemon is about to exit for a clean supervisor restart). Returned
|
|
102
|
-
* as a single string so the notice/attention surface can push it directly.
|
|
103
|
-
*/
|
|
104
|
-
export function memoryPressureLine(event: MemoryPressurePayload): string {
|
|
105
|
-
const base = `memory pressure: ${event.previousTier} → ${event.tier} (${formatMb(event.rssMb)} rss / ${formatMb(event.budgetMb)} budget, ${Math.round(event.usedPct)}%)`;
|
|
106
|
-
if (event.tripwire) {
|
|
107
|
-
return `${base} — leak tripwire fired (${event.tripwire.rateMbPerSec} MB/s sustained ${Math.round(event.tripwire.sustainedSec)}s); the daemon will exit for a clean restart`;
|
|
108
|
-
}
|
|
109
|
-
if (event.note) return `${base} — ${event.note}`;
|
|
110
|
-
return base;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/** Severity for the notice feed: critical tier (or a tripwire) is critical; high is a warning. */
|
|
114
|
-
export function memoryPressureLevel(event: MemoryPressurePayload): 'info' | 'warning' | 'critical' {
|
|
115
|
-
if (event.tripwire || event.tier === 'critical') return 'critical';
|
|
116
|
-
if (event.tier === 'high') return 'warning';
|
|
117
|
-
return 'info';
|
|
118
|
-
}
|
package/src/core/orchestrator.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
// Thin TUI wrapper — re-exports the SDK Orchestrator unchanged.
|
|
2
|
-
// The SDK class already contains all behaviour including getSpinner().
|
|
3
|
-
export {
|
|
4
|
-
Orchestrator,
|
|
5
|
-
type OrchestratorOptions,
|
|
6
|
-
type OrchestratorUserInputOptions,
|
|
7
|
-
} from '@pellux/goodvibes-sdk/platform/core';
|