@pellux/goodvibes-tui 0.18.4
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/.goodvibes/GOODVIBES.md +35 -0
- package/.goodvibes/agents/reviewer.md +89 -0
- package/.goodvibes/skills/add-provider/SKILL.md +199 -0
- package/CHANGELOG.md +1681 -0
- package/README.md +1607 -0
- package/bin/goodvibes +66 -0
- package/docs/README.md +32 -0
- package/docs/foundation-artifacts/README.md +16 -0
- package/docs/foundation-artifacts/knowledge-graphql.graphql +397 -0
- package/docs/foundation-artifacts/knowledge-store.sql +183 -0
- package/docs/foundation-artifacts/operator-contract.json +55157 -0
- package/docs/foundation-artifacts/peer-contract.json +2384 -0
- package/package.json +114 -0
- package/scripts/postinstall.mjs +203 -0
- package/src/acp/connection.ts +447 -0
- package/src/acp/index.ts +7 -0
- package/src/acp/manager.ts +133 -0
- package/src/adapters/bluebubbles/index.ts +127 -0
- package/src/adapters/discord/index.ts +297 -0
- package/src/adapters/github/index.ts +73 -0
- package/src/adapters/google-chat/index.ts +119 -0
- package/src/adapters/imessage/index.ts +92 -0
- package/src/adapters/index.ts +15 -0
- package/src/adapters/matrix/index.ts +116 -0
- package/src/adapters/mattermost/index.ts +151 -0
- package/src/adapters/msteams/index.ts +180 -0
- package/src/adapters/ntfy/index.ts +118 -0
- package/src/adapters/signal/index.ts +92 -0
- package/src/adapters/slack/index.ts +323 -0
- package/src/adapters/telegram/index.ts +160 -0
- package/src/adapters/types.ts +97 -0
- package/src/adapters/webhook/index.ts +178 -0
- package/src/adapters/whatsapp/index.ts +135 -0
- package/src/agents/message-bus-core.ts +312 -0
- package/src/agents/message-bus.ts +2 -0
- package/src/agents/orchestrator-prompts.ts +351 -0
- package/src/agents/orchestrator-runner.ts +668 -0
- package/src/agents/orchestrator.ts +437 -0
- package/src/agents/session.ts +108 -0
- package/src/agents/worktree.ts +153 -0
- package/src/agents/wrfc-config.ts +47 -0
- package/src/agents/wrfc-controller.ts +747 -0
- package/src/agents/wrfc-gate-runtime.ts +75 -0
- package/src/agents/wrfc-reporting.ts +284 -0
- package/src/agents/wrfc-runtime-events.ts +150 -0
- package/src/agents/wrfc-types.ts +67 -0
- package/src/automation/delivery-manager.ts +368 -0
- package/src/automation/index.ts +72 -0
- package/src/automation/manager-runtime-delivery.ts +139 -0
- package/src/automation/manager-runtime-events.ts +131 -0
- package/src/automation/manager-runtime-execution.ts +511 -0
- package/src/automation/manager-runtime-helpers.ts +433 -0
- package/src/automation/manager-runtime-job-mutations.ts +175 -0
- package/src/automation/manager-runtime-reconcile.ts +148 -0
- package/src/automation/manager-runtime-scheduling.ts +189 -0
- package/src/automation/manager-runtime-sync.ts +54 -0
- package/src/automation/manager-runtime.ts +721 -0
- package/src/automation/manager.ts +10 -0
- package/src/automation/service.ts +242 -0
- package/src/channels/builtin/account-actions.ts +490 -0
- package/src/channels/builtin/accounts.ts +433 -0
- package/src/channels/builtin/contracts.ts +405 -0
- package/src/channels/builtin/plugins.ts +308 -0
- package/src/channels/builtin/rendering.ts +174 -0
- package/src/channels/builtin/setup-schema.ts +504 -0
- package/src/channels/builtin/shared.ts +96 -0
- package/src/channels/builtin/surfaces.ts +57 -0
- package/src/channels/builtin/targets.ts +693 -0
- package/src/channels/builtin-runtime.ts +443 -0
- package/src/channels/delivery/shared.ts +199 -0
- package/src/channels/delivery/strategies-bridge.ts +246 -0
- package/src/channels/delivery/strategies-core.ts +299 -0
- package/src/channels/delivery/strategies-enterprise.ts +178 -0
- package/src/channels/delivery/types.ts +59 -0
- package/src/channels/delivery-router.ts +127 -0
- package/src/channels/index.ts +77 -0
- package/src/channels/plugin-registry.ts +551 -0
- package/src/channels/provider-runtime.ts +330 -0
- package/src/channels/reply-pipeline.ts +522 -0
- package/src/channels/route-manager.ts +340 -0
- package/src/channels/surface-registry.ts +186 -0
- package/src/config/helper-model.ts +233 -0
- package/src/config/index.ts +193 -0
- package/src/config/manager.ts +404 -0
- package/src/config/secrets.ts +547 -0
- package/src/config/service-registry.ts +329 -0
- package/src/config/subscription-auth.ts +31 -0
- package/src/config/subscription-providers.ts +127 -0
- package/src/config/tool-llm.ts +110 -0
- package/src/control-plane/approval-broker.ts +351 -0
- package/src/control-plane/gateway.ts +713 -0
- package/src/control-plane/index.ts +54 -0
- package/src/control-plane/media-contract-schemas.ts +208 -0
- package/src/control-plane/method-catalog-admin.ts +136 -0
- package/src/control-plane/method-catalog-channels.ts +591 -0
- package/src/control-plane/method-catalog-control-automation.ts +475 -0
- package/src/control-plane/method-catalog-control-core.ts +594 -0
- package/src/control-plane/method-catalog-control.ts +8 -0
- package/src/control-plane/method-catalog-events.ts +74 -0
- package/src/control-plane/method-catalog-knowledge.ts +531 -0
- package/src/control-plane/method-catalog-media.ts +279 -0
- package/src/control-plane/method-catalog-runtime.ts +304 -0
- package/src/control-plane/method-catalog-shared.ts +223 -0
- package/src/control-plane/method-catalog.ts +242 -0
- package/src/control-plane/operator-contract-schemas-admin.ts +639 -0
- package/src/control-plane/operator-contract-schemas-channels.ts +375 -0
- package/src/control-plane/operator-contract-schemas-control.ts +226 -0
- package/src/control-plane/operator-contract-schemas-domains.ts +4 -0
- package/src/control-plane/operator-contract-schemas-knowledge.ts +582 -0
- package/src/control-plane/operator-contract-schemas-media.ts +297 -0
- package/src/control-plane/operator-contract-schemas-permissions.ts +100 -0
- package/src/control-plane/operator-contract-schemas-remote.ts +38 -0
- package/src/control-plane/operator-contract-schemas-runtime.ts +563 -0
- package/src/control-plane/operator-contract-schemas-shared.ts +85 -0
- package/src/control-plane/operator-contract-schemas-telemetry.ts +349 -0
- package/src/control-plane/operator-contract-schemas.ts +6 -0
- package/src/control-plane/operator-contract.ts +163 -0
- package/src/control-plane/session-broker.ts +780 -0
- package/src/core/compaction-sections.ts +492 -0
- package/src/core/compaction-types.ts +147 -0
- package/src/core/composer-state.ts +59 -0
- package/src/core/context-compaction.ts +542 -0
- package/src/core/conversation-compaction.ts +68 -0
- package/src/core/conversation-diff.ts +55 -0
- package/src/core/conversation-rendering.ts +343 -0
- package/src/core/conversation-utils.ts +72 -0
- package/src/core/conversation.ts +775 -0
- package/src/core/event-replay.ts +287 -0
- package/src/core/orchestrator-context-runtime.ts +407 -0
- package/src/core/orchestrator-follow-up-runtime.ts +134 -0
- package/src/core/orchestrator-runtime.ts +132 -0
- package/src/core/orchestrator-tool-runtime.ts +468 -0
- package/src/core/orchestrator-turn-helpers.ts +355 -0
- package/src/core/orchestrator-turn-loop.ts +443 -0
- package/src/core/orchestrator.ts +733 -0
- package/src/core/plan-command-handler.ts +169 -0
- package/src/core/system-message-router.ts +210 -0
- package/src/core/transcript-events/classify.ts +95 -0
- package/src/core/transcript-events/index.ts +15 -0
- package/src/daemon/cli.ts +88 -0
- package/src/daemon/control-plane.ts +522 -0
- package/src/daemon/facade-composition.ts +397 -0
- package/src/daemon/facade.ts +638 -0
- package/src/daemon/helpers.ts +74 -0
- package/src/daemon/http/router-route-contexts.ts +370 -0
- package/src/daemon/http/router.ts +531 -0
- package/src/daemon/http-listener.ts +301 -0
- package/src/daemon/index.ts +3 -0
- package/src/daemon/server.ts +1 -0
- package/src/daemon/service-manager.ts +413 -0
- package/src/daemon/surface-actions.ts +183 -0
- package/src/daemon/surface-delivery.ts +530 -0
- package/src/daemon/surface-policy.ts +60 -0
- package/src/daemon/transport-events.ts +110 -0
- package/src/daemon/types.ts +191 -0
- package/src/export/markdown.ts +213 -0
- package/src/export/session-export.ts +633 -0
- package/src/git/index.ts +1 -0
- package/src/git/service.ts +414 -0
- package/src/hooks/chain-engine.ts +414 -0
- package/src/hooks/dispatcher.ts +414 -0
- package/src/hooks/hook-api.ts +170 -0
- package/src/hooks/index.ts +48 -0
- package/src/hooks/runners/agent.ts +93 -0
- package/src/hooks/runners/prompt.ts +69 -0
- package/src/hooks/workbench.ts +360 -0
- package/src/input/autocomplete.ts +96 -0
- package/src/input/bookmark-modal.ts +115 -0
- package/src/input/command-registry.ts +300 -0
- package/src/input/commands/branch-runtime.ts +72 -0
- package/src/input/commands/config.ts +515 -0
- package/src/input/commands/control-room-runtime.ts +255 -0
- package/src/input/commands/conversation-runtime.ts +207 -0
- package/src/input/commands/diff-runtime.ts +161 -0
- package/src/input/commands/discovery-runtime.ts +45 -0
- package/src/input/commands/eval.ts +204 -0
- package/src/input/commands/experience-runtime.ts +278 -0
- package/src/input/commands/git-runtime.ts +81 -0
- package/src/input/commands/guidance-runtime.ts +101 -0
- package/src/input/commands/health-runtime.ts +434 -0
- package/src/input/commands/hooks-runtime.ts +148 -0
- package/src/input/commands/incident-runtime.ts +95 -0
- package/src/input/commands/integration-runtime.ts +394 -0
- package/src/input/commands/intelligence-runtime.ts +223 -0
- package/src/input/commands/knowledge.ts +368 -0
- package/src/input/commands/local-auth-runtime.ts +105 -0
- package/src/input/commands/local-provider-runtime.ts +170 -0
- package/src/input/commands/local-runtime.ts +458 -0
- package/src/input/commands/local-setup-review.ts +192 -0
- package/src/input/commands/local-setup-transfer.ts +134 -0
- package/src/input/commands/local-setup.ts +292 -0
- package/src/input/commands/managed-runtime.ts +208 -0
- package/src/input/commands/marketplace-runtime.ts +290 -0
- package/src/input/commands/mcp-runtime.ts +202 -0
- package/src/input/commands/memory-product-runtime.ts +111 -0
- package/src/input/commands/memory.ts +151 -0
- package/src/input/commands/notify-runtime.ts +83 -0
- package/src/input/commands/operator-panel-runtime.ts +141 -0
- package/src/input/commands/operator-runtime.ts +392 -0
- package/src/input/commands/permissions-runtime.ts +104 -0
- package/src/input/commands/planning-runtime.ts +97 -0
- package/src/input/commands/platform-access-runtime.ts +422 -0
- package/src/input/commands/platform-runtime.ts +6 -0
- package/src/input/commands/platform-sandbox-qemu.ts +137 -0
- package/src/input/commands/platform-sandbox-runtime.ts +406 -0
- package/src/input/commands/platform-sandbox-session.ts +128 -0
- package/src/input/commands/platform-services-runtime.ts +246 -0
- package/src/input/commands/policy-dispatch.ts +339 -0
- package/src/input/commands/policy.ts +17 -0
- package/src/input/commands/product-runtime.ts +351 -0
- package/src/input/commands/profile-sync-runtime.ts +99 -0
- package/src/input/commands/provider-accounts-runtime.ts +113 -0
- package/src/input/commands/provider.ts +363 -0
- package/src/input/commands/quit-shared.ts +162 -0
- package/src/input/commands/recall-bundle.ts +132 -0
- package/src/input/commands/recall-capture.ts +152 -0
- package/src/input/commands/recall-query.ts +229 -0
- package/src/input/commands/recall-review.ts +98 -0
- package/src/input/commands/recall-shared.ts +22 -0
- package/src/input/commands/remote-runtime-pool.ts +106 -0
- package/src/input/commands/remote-runtime-setup.ts +199 -0
- package/src/input/commands/remote-runtime.ts +531 -0
- package/src/input/commands/replay-runtime.ts +18 -0
- package/src/input/commands/runtime-services.ts +279 -0
- package/src/input/commands/schedule-runtime.ts +332 -0
- package/src/input/commands/services-runtime.ts +207 -0
- package/src/input/commands/session-content.ts +408 -0
- package/src/input/commands/session-workflow.ts +464 -0
- package/src/input/commands/session.ts +376 -0
- package/src/input/commands/settings-sync-runtime.ts +173 -0
- package/src/input/commands/share-runtime.ts +114 -0
- package/src/input/commands/shell-core.ts +320 -0
- package/src/input/commands/skills-runtime.ts +221 -0
- package/src/input/commands/subscription-runtime.ts +434 -0
- package/src/input/commands/tasks-runtime.ts +230 -0
- package/src/input/commands/teamwork-runtime.ts +374 -0
- package/src/input/commands/teleport-runtime.ts +57 -0
- package/src/input/commands/worktree-runtime.ts +137 -0
- package/src/input/commands.ts +127 -0
- package/src/input/file-picker.ts +192 -0
- package/src/input/handler-command-route.ts +106 -0
- package/src/input/handler-content-actions.ts +465 -0
- package/src/input/handler-feed-routes.ts +541 -0
- package/src/input/handler-feed.ts +361 -0
- package/src/input/handler-modal-routes.ts +335 -0
- package/src/input/handler-modal-stack.ts +237 -0
- package/src/input/handler-modal-token-routes.ts +272 -0
- package/src/input/handler-picker-routes.ts +416 -0
- package/src/input/handler-prompt-buffer.ts +320 -0
- package/src/input/handler-shortcuts.ts +195 -0
- package/src/input/handler-ui-state.ts +294 -0
- package/src/input/handler.ts +798 -0
- package/src/input/input-history.ts +267 -0
- package/src/input/keybindings.ts +256 -0
- package/src/input/model-picker.ts +730 -0
- package/src/input/panel-integration-actions.ts +77 -0
- package/src/input/profile-picker-modal.ts +222 -0
- package/src/input/search.ts +100 -0
- package/src/input/selection-modal.ts +163 -0
- package/src/input/selection.ts +135 -0
- package/src/input/session-picker-modal.ts +136 -0
- package/src/input/settings-modal.ts +718 -0
- package/src/input/submission-intent.ts +18 -0
- package/src/input/submission-router.ts +64 -0
- package/src/integrations/index.ts +42 -0
- package/src/integrations/notifier.ts +206 -0
- package/src/integrations/webhooks.ts +177 -0
- package/src/knowledge/consolidation.ts +346 -0
- package/src/knowledge/graphql.ts +324 -0
- package/src/knowledge/index.ts +60 -0
- package/src/knowledge/ingest-compile.ts +386 -0
- package/src/knowledge/ingest-context.ts +18 -0
- package/src/knowledge/ingest-inputs.ts +387 -0
- package/src/knowledge/ingest.ts +20 -0
- package/src/knowledge/internal.ts +257 -0
- package/src/knowledge/knowledge-api.ts +432 -0
- package/src/knowledge/lint.ts +121 -0
- package/src/knowledge/memory-sync.ts +62 -0
- package/src/knowledge/packet.ts +370 -0
- package/src/knowledge/scheduling.ts +283 -0
- package/src/knowledge/service.ts +715 -0
- package/src/main.ts +798 -0
- package/src/mcp/client.ts +383 -0
- package/src/mcp/index.ts +12 -0
- package/src/mcp/mcp-api.ts +90 -0
- package/src/mcp/registry.ts +508 -0
- package/src/media/builtin-image-understanding.ts +303 -0
- package/src/media/builtin-providers.ts +26 -0
- package/src/media/index.ts +18 -0
- package/src/multimodal/index.ts +13 -0
- package/src/multimodal/service.ts +492 -0
- package/src/panels/agent-inspector-panel.ts +515 -0
- package/src/panels/agent-inspector-shared.ts +94 -0
- package/src/panels/agent-logs-panel.ts +539 -0
- package/src/panels/agent-logs-shared.ts +129 -0
- package/src/panels/approval-panel.ts +169 -0
- package/src/panels/automation-control-panel.ts +253 -0
- package/src/panels/base-panel.ts +72 -0
- package/src/panels/builtin/agent.ts +88 -0
- package/src/panels/builtin/development.ts +111 -0
- package/src/panels/builtin/knowledge.ts +26 -0
- package/src/panels/builtin/operations.ts +385 -0
- package/src/panels/builtin/session.ts +61 -0
- package/src/panels/builtin/shared.ts +240 -0
- package/src/panels/builtin-panels.ts +23 -0
- package/src/panels/cockpit-panel.ts +183 -0
- package/src/panels/communication-panel.ts +191 -0
- package/src/panels/context-visualizer-panel.ts +199 -0
- package/src/panels/control-plane-panel.ts +266 -0
- package/src/panels/cost-tracker-panel.ts +444 -0
- package/src/panels/debug-panel.ts +432 -0
- package/src/panels/diff-panel.ts +518 -0
- package/src/panels/docs-panel.ts +283 -0
- package/src/panels/eval-panel.ts +399 -0
- package/src/panels/file-explorer-panel.ts +556 -0
- package/src/panels/file-preview-panel.ts +412 -0
- package/src/panels/forensics-panel.ts +364 -0
- package/src/panels/git-panel.ts +630 -0
- package/src/panels/hooks-panel.ts +274 -0
- package/src/panels/incident-review-panel.ts +247 -0
- package/src/panels/index.ts +48 -0
- package/src/panels/intelligence-panel.ts +176 -0
- package/src/panels/knowledge-panel.ts +328 -0
- package/src/panels/local-auth-panel.ts +146 -0
- package/src/panels/marketplace-panel.ts +223 -0
- package/src/panels/mcp-panel.ts +260 -0
- package/src/panels/memory-panel.ts +293 -0
- package/src/panels/ops-control-panel.ts +184 -0
- package/src/panels/ops-strategy-panel.ts +235 -0
- package/src/panels/orchestration-panel.ts +254 -0
- package/src/panels/panel-list-panel.ts +508 -0
- package/src/panels/panel-manager.ts +538 -0
- package/src/panels/panel-picker.ts +106 -0
- package/src/panels/plan-dashboard-panel.ts +272 -0
- package/src/panels/plugins-panel.ts +201 -0
- package/src/panels/policy-panel.ts +308 -0
- package/src/panels/polish.ts +668 -0
- package/src/panels/provider-account-snapshot.ts +259 -0
- package/src/panels/provider-accounts-panel.ts +221 -0
- package/src/panels/provider-health-domains.ts +211 -0
- package/src/panels/provider-health-panel.ts +725 -0
- package/src/panels/provider-health-tracker.ts +115 -0
- package/src/panels/provider-stats-panel.ts +366 -0
- package/src/panels/remote-panel.ts +449 -0
- package/src/panels/routes-panel.ts +228 -0
- package/src/panels/sandbox-panel.ts +289 -0
- package/src/panels/schedule-panel.ts +344 -0
- package/src/panels/search-focus.ts +32 -0
- package/src/panels/security-panel.ts +329 -0
- package/src/panels/services-panel.ts +271 -0
- package/src/panels/session-browser-panel.ts +399 -0
- package/src/panels/session-maintenance.ts +125 -0
- package/src/panels/settings-sync-panel.ts +164 -0
- package/src/panels/skills-panel.ts +475 -0
- package/src/panels/subscription-panel.ts +273 -0
- package/src/panels/symbol-outline-panel.ts +486 -0
- package/src/panels/system-messages-panel.ts +224 -0
- package/src/panels/tasks-panel.ts +448 -0
- package/src/panels/thinking-panel.ts +304 -0
- package/src/panels/token-budget-panel.ts +469 -0
- package/src/panels/tool-inspector-panel.ts +434 -0
- package/src/panels/types.ts +44 -0
- package/src/panels/watchers-panel.ts +241 -0
- package/src/panels/welcome-panel.ts +64 -0
- package/src/panels/worktree-panel.ts +180 -0
- package/src/panels/wrfc-panel.ts +480 -0
- package/src/permissions/briefs/build.ts +88 -0
- package/src/permissions/manager.ts +356 -0
- package/src/permissions/prompt.ts +184 -0
- package/src/plugins/api.ts +383 -0
- package/src/plugins/loader.ts +304 -0
- package/src/plugins/manager.ts +481 -0
- package/src/profiles/shape.ts +58 -0
- package/src/providers/amazon-bedrock-mantle.ts +50 -0
- package/src/providers/amazon-bedrock.ts +61 -0
- package/src/providers/anthropic-compat.ts +373 -0
- package/src/providers/anthropic-sdk-provider.ts +230 -0
- package/src/providers/anthropic-vertex.ts +59 -0
- package/src/providers/anthropic.ts +469 -0
- package/src/providers/auto-register.ts +417 -0
- package/src/providers/builtin-catalog.ts +326 -0
- package/src/providers/builtin-registry.ts +575 -0
- package/src/providers/cache-planner.ts +258 -0
- package/src/providers/capabilities.ts +601 -0
- package/src/providers/custom-loader.ts +425 -0
- package/src/providers/discovered-compat.ts +18 -0
- package/src/providers/discovered-factory.ts +61 -0
- package/src/providers/discovered-traits.ts +138 -0
- package/src/providers/gemini.ts +462 -0
- package/src/providers/github-copilot.ts +254 -0
- package/src/providers/index.ts +47 -0
- package/src/providers/interface.ts +185 -0
- package/src/providers/llama-cpp.ts +402 -0
- package/src/providers/lm-studio-helpers.ts +367 -0
- package/src/providers/lm-studio.ts +484 -0
- package/src/providers/model-catalog-cache.ts +221 -0
- package/src/providers/model-catalog-notifications.ts +97 -0
- package/src/providers/model-catalog-synthetic.ts +202 -0
- package/src/providers/model-catalog.ts +211 -0
- package/src/providers/model-limits.ts +280 -0
- package/src/providers/ollama.ts +469 -0
- package/src/providers/openai-codex.ts +472 -0
- package/src/providers/openai-compat.ts +615 -0
- package/src/providers/openai.ts +231 -0
- package/src/providers/optimizer.ts +381 -0
- package/src/providers/provider-api.ts +553 -0
- package/src/providers/registry-helpers.ts +34 -0
- package/src/providers/registry-models.ts +77 -0
- package/src/providers/registry-types.ts +67 -0
- package/src/providers/registry.ts +729 -0
- package/src/providers/runtime-metadata.ts +149 -0
- package/src/providers/runtime-snapshot.ts +130 -0
- package/src/providers/synthetic.ts +561 -0
- package/src/providers/tier-prompts.ts +84 -0
- package/src/providers/tool-formats.ts +414 -0
- package/src/renderer/agent-detail-modal.ts +285 -0
- package/src/renderer/autocomplete-overlay.ts +154 -0
- package/src/renderer/block-actions.ts +76 -0
- package/src/renderer/bookmark-modal.ts +101 -0
- package/src/renderer/bottom-bar.ts +58 -0
- package/src/renderer/buffer.ts +34 -0
- package/src/renderer/code-block.ts +373 -0
- package/src/renderer/compositor.ts +261 -0
- package/src/renderer/context-inspector.ts +219 -0
- package/src/renderer/conversation-layout.ts +67 -0
- package/src/renderer/conversation-overlays.ts +123 -0
- package/src/renderer/conversation-surface.ts +260 -0
- package/src/renderer/diff-view.ts +132 -0
- package/src/renderer/diff.ts +122 -0
- package/src/renderer/file-picker-overlay.ts +101 -0
- package/src/renderer/file-tree.ts +153 -0
- package/src/renderer/git-status.ts +89 -0
- package/src/renderer/help-overlay.ts +247 -0
- package/src/renderer/history-search-overlay.ts +73 -0
- package/src/renderer/layout-engine.ts +97 -0
- package/src/renderer/layout.ts +32 -0
- package/src/renderer/live-tail-modal.ts +156 -0
- package/src/renderer/markdown.ts +777 -0
- package/src/renderer/modal-factory.ts +467 -0
- package/src/renderer/modal-utils.ts +24 -0
- package/src/renderer/model-picker-overlay.ts +396 -0
- package/src/renderer/overlay-box.ts +165 -0
- package/src/renderer/overlay-viewport.ts +104 -0
- package/src/renderer/panel-composite.ts +80 -0
- package/src/renderer/panel-picker-overlay.ts +202 -0
- package/src/renderer/panel-tab-bar.ts +69 -0
- package/src/renderer/panel-workspace-bar.ts +38 -0
- package/src/renderer/process-indicator.ts +96 -0
- package/src/renderer/process-modal.ts +295 -0
- package/src/renderer/profile-picker-modal.ts +129 -0
- package/src/renderer/progress.ts +98 -0
- package/src/renderer/search-overlay.ts +54 -0
- package/src/renderer/selection-modal-overlay.ts +214 -0
- package/src/renderer/semantic-diff.ts +369 -0
- package/src/renderer/session-picker-modal.ts +127 -0
- package/src/renderer/settings-modal.ts +701 -0
- package/src/renderer/shell-surface.ts +88 -0
- package/src/renderer/surface-layout.ts +101 -0
- package/src/renderer/syntax-highlighter.ts +542 -0
- package/src/renderer/system-message.ts +83 -0
- package/src/renderer/tab-strip.ts +108 -0
- package/src/renderer/text-layout.ts +31 -0
- package/src/renderer/thinking.ts +17 -0
- package/src/renderer/tool-call.ts +233 -0
- package/src/renderer/ui-factory.ts +524 -0
- package/src/renderer/ui-primitives.ts +96 -0
- package/src/runtime/auth/inspection.ts +125 -0
- package/src/runtime/bootstrap-background.ts +147 -0
- package/src/runtime/bootstrap-command-context.ts +265 -0
- package/src/runtime/bootstrap-command-parts.ts +357 -0
- package/src/runtime/bootstrap-core.ts +375 -0
- package/src/runtime/bootstrap-helpers.ts +88 -0
- package/src/runtime/bootstrap-hook-bridge.ts +271 -0
- package/src/runtime/bootstrap-runtime-events.ts +254 -0
- package/src/runtime/bootstrap-services.ts +197 -0
- package/src/runtime/bootstrap-shell.ts +262 -0
- package/src/runtime/bootstrap.ts +488 -0
- package/src/runtime/compaction/index.ts +90 -0
- package/src/runtime/compaction/lifecycle.ts +167 -0
- package/src/runtime/compaction/manager.ts +474 -0
- package/src/runtime/compaction/quality-score.ts +279 -0
- package/src/runtime/compaction/resume-repair.ts +183 -0
- package/src/runtime/compaction/strategies/autocompact.ts +65 -0
- package/src/runtime/compaction/strategies/boundary-commit.ts +106 -0
- package/src/runtime/compaction/strategies/collapse.ts +90 -0
- package/src/runtime/compaction/strategies/index.ts +23 -0
- package/src/runtime/compaction/strategies/microcompact.ts +74 -0
- package/src/runtime/compaction/strategies/reactive.ts +89 -0
- package/src/runtime/compaction/types.ts +221 -0
- package/src/runtime/context.ts +158 -0
- package/src/runtime/diagnostics/actions.ts +776 -0
- package/src/runtime/diagnostics/index.ts +99 -0
- package/src/runtime/diagnostics/panels/agents.ts +252 -0
- package/src/runtime/diagnostics/panels/events.ts +188 -0
- package/src/runtime/diagnostics/panels/health.ts +242 -0
- package/src/runtime/diagnostics/panels/index.ts +24 -0
- package/src/runtime/diagnostics/panels/ops.ts +156 -0
- package/src/runtime/diagnostics/panels/policy.ts +176 -0
- package/src/runtime/diagnostics/panels/tasks.ts +251 -0
- package/src/runtime/diagnostics/panels/tool-calls.ts +267 -0
- package/src/runtime/diagnostics/provider.ts +262 -0
- package/src/runtime/ecosystem/catalog.ts +606 -0
- package/src/runtime/ecosystem/recommendations.ts +117 -0
- package/src/runtime/emitters/agents.ts +96 -0
- package/src/runtime/emitters/automation.ts +112 -0
- package/src/runtime/emitters/communication.ts +53 -0
- package/src/runtime/emitters/compaction.ts +161 -0
- package/src/runtime/emitters/control-plane.ts +65 -0
- package/src/runtime/emitters/deliveries.ts +65 -0
- package/src/runtime/emitters/forensics.ts +17 -0
- package/src/runtime/emitters/index.ts +59 -0
- package/src/runtime/emitters/knowledge.ts +129 -0
- package/src/runtime/emitters/mcp.ts +95 -0
- package/src/runtime/emitters/ops.ts +163 -0
- package/src/runtime/emitters/orchestration.ts +87 -0
- package/src/runtime/emitters/permissions.ts +98 -0
- package/src/runtime/emitters/planner.ts +23 -0
- package/src/runtime/emitters/plugins.ts +78 -0
- package/src/runtime/emitters/providers.ts +30 -0
- package/src/runtime/emitters/routes.ts +57 -0
- package/src/runtime/emitters/security.ts +53 -0
- package/src/runtime/emitters/session.ts +93 -0
- package/src/runtime/emitters/surfaces.ts +57 -0
- package/src/runtime/emitters/tasks.ts +69 -0
- package/src/runtime/emitters/tools.ts +140 -0
- package/src/runtime/emitters/transport.ts +78 -0
- package/src/runtime/emitters/turn.ts +155 -0
- package/src/runtime/emitters/ui.ts +57 -0
- package/src/runtime/emitters/watchers.ts +57 -0
- package/src/runtime/emitters/workflows.ts +79 -0
- package/src/runtime/eval/index.ts +48 -0
- package/src/runtime/eval/runner.ts +163 -0
- package/src/runtime/eval/suites.ts +264 -0
- package/src/runtime/events/domain-map.ts +148 -0
- package/src/runtime/events/index.ts +194 -0
- package/src/runtime/events/turn.ts +60 -0
- package/src/runtime/events/workflows.ts +17 -0
- package/src/runtime/forensics/collector.ts +693 -0
- package/src/runtime/forensics/index.ts +23 -0
- package/src/runtime/foundation-clients.ts +78 -0
- package/src/runtime/foundation-services.ts +96 -0
- package/src/runtime/guidance.ts +183 -0
- package/src/runtime/health/effect-handlers.ts +189 -0
- package/src/runtime/health/index.ts +70 -0
- package/src/runtime/health/wiring.ts +115 -0
- package/src/runtime/index.ts +174 -0
- package/src/runtime/integration/helpers.ts +640 -0
- package/src/runtime/lifecycle.ts +107 -0
- package/src/runtime/mcp/index.ts +68 -0
- package/src/runtime/mcp/manager.ts +513 -0
- package/src/runtime/network/inbound.ts +131 -0
- package/src/runtime/network/index.ts +30 -0
- package/src/runtime/network/outbound.ts +292 -0
- package/src/runtime/network/shared.ts +82 -0
- package/src/runtime/operator-client.ts +235 -0
- package/src/runtime/ops/control-plane.ts +363 -0
- package/src/runtime/ops/index.ts +122 -0
- package/src/runtime/ops/playbooks/index.ts +10 -0
- package/src/runtime/ops/playbooks/session-unrecoverable.ts +196 -0
- package/src/runtime/ops/playbooks/stuck-turn.ts +197 -0
- package/src/runtime/ops/runtime-context.ts +100 -0
- package/src/runtime/ops-api.ts +27 -0
- package/src/runtime/orchestration/spawn-policy.ts +83 -0
- package/src/runtime/peer-client.ts +404 -0
- package/src/runtime/perf/index.ts +57 -0
- package/src/runtime/perf/slo-collector.ts +375 -0
- package/src/runtime/permissions/index.ts +190 -0
- package/src/runtime/permissions/policy-runtime.ts +175 -0
- package/src/runtime/permissions/preflight.ts +101 -0
- package/src/runtime/permissions/rule-suggestions.ts +36 -0
- package/src/runtime/plugins/hot-reload.ts +221 -0
- package/src/runtime/plugins/index.ts +84 -0
- package/src/runtime/plugins/lifecycle.ts +95 -0
- package/src/runtime/plugins/manager.ts +474 -0
- package/src/runtime/plugins/manifest.ts +167 -0
- package/src/runtime/plugins/quarantine.ts +202 -0
- package/src/runtime/plugins/trust.ts +291 -0
- package/src/runtime/plugins/types.ts +205 -0
- package/src/runtime/provider-accounts/registry.ts +326 -0
- package/src/runtime/remote/distributed-runtime-contract-schemas.ts +386 -0
- package/src/runtime/remote/index.ts +488 -0
- package/src/runtime/remote/runner-registry.ts +438 -0
- package/src/runtime/remote/supervisor.ts +70 -0
- package/src/runtime/runtime-hook-api.ts +5 -0
- package/src/runtime/runtime-knowledge-api.ts +14 -0
- package/src/runtime/runtime-mcp-api.ts +5 -0
- package/src/runtime/runtime-ops-api.ts +86 -0
- package/src/runtime/runtime-provider-api.ts +18 -0
- package/src/runtime/sandbox/backend.ts +291 -0
- package/src/runtime/sandbox/manager.ts +364 -0
- package/src/runtime/sandbox/provisioning.ts +422 -0
- package/src/runtime/sandbox/session-registry.ts +289 -0
- package/src/runtime/services.ts +541 -0
- package/src/runtime/session-maintenance.ts +188 -0
- package/src/runtime/session-persistence.ts +288 -0
- package/src/runtime/session-return-context.ts +195 -0
- package/src/runtime/settings/control-plane-store.ts +258 -0
- package/src/runtime/settings/control-plane.ts +599 -0
- package/src/runtime/shell-command-extensions.ts +54 -0
- package/src/runtime/shell-command-ops.ts +207 -0
- package/src/runtime/shell-command-platform.ts +47 -0
- package/src/runtime/shell-command-services.ts +143 -0
- package/src/runtime/shell-command-workspace.ts +31 -0
- package/src/runtime/store/domains/conversation.ts +181 -0
- package/src/runtime/store/domains/domain-read-matrix.ts +17 -0
- package/src/runtime/store/domains/index.ts +222 -0
- package/src/runtime/store/domains/panels.ts +117 -0
- package/src/runtime/store/domains/permissions.ts +143 -0
- package/src/runtime/store/domains/ui-perf.ts +103 -0
- package/src/runtime/store/helpers/reducers/conversation.ts +228 -0
- package/src/runtime/store/helpers/reducers/lifecycle.ts +440 -0
- package/src/runtime/store/helpers/reducers/shared.ts +60 -0
- package/src/runtime/store/helpers/reducers/sync.ts +555 -0
- package/src/runtime/store/helpers/reducers.ts +30 -0
- package/src/runtime/store/index.ts +304 -0
- package/src/runtime/store/selectors/index.ts +354 -0
- package/src/runtime/store/state.ts +137 -0
- package/src/runtime/tasks/adapters/acp-adapter.ts +211 -0
- package/src/runtime/tasks/adapters/agent-adapter.ts +208 -0
- package/src/runtime/tasks/adapters/index.ts +16 -0
- package/src/runtime/tasks/adapters/process-adapter.ts +214 -0
- package/src/runtime/tasks/adapters/scheduler-adapter.ts +193 -0
- package/src/runtime/tasks/index.ts +68 -0
- package/src/runtime/tasks/manager.ts +415 -0
- package/src/runtime/telemetry/api-helpers.ts +517 -0
- package/src/runtime/telemetry/api.ts +768 -0
- package/src/runtime/telemetry/index.ts +178 -0
- package/src/runtime/telemetry/instrumentation/domain-bridge-agent-session.ts +440 -0
- package/src/runtime/telemetry/instrumentation/domain-bridge-plugin-mcp.ts +200 -0
- package/src/runtime/telemetry/instrumentation/domain-bridge-shared.ts +18 -0
- package/src/runtime/telemetry/instrumentation/domain-bridge-transport-task.ts +204 -0
- package/src/runtime/telemetry/instrumentation/domain-bridge.ts +125 -0
- package/src/runtime/telemetry/instrumentation/index.ts +67 -0
- package/src/runtime/tools/context.ts +114 -0
- package/src/runtime/tools/index.ts +46 -0
- package/src/runtime/tools/phased-executor.ts +448 -0
- package/src/runtime/tools/phases/budget.ts +130 -0
- package/src/runtime/tools/phases/execute.ts +69 -0
- package/src/runtime/tools/phases/index.ts +13 -0
- package/src/runtime/tools/phases/map-output.ts +98 -0
- package/src/runtime/tools/phases/permission.ts +133 -0
- package/src/runtime/tools/phases/posthook.ts +57 -0
- package/src/runtime/tools/phases/prehook.ts +68 -0
- package/src/runtime/tools/phases/validate.ts +53 -0
- package/src/runtime/transports/direct.ts +73 -0
- package/src/runtime/transports/http-helpers.ts +218 -0
- package/src/runtime/transports/http-types.ts +364 -0
- package/src/runtime/transports/http.ts +629 -0
- package/src/runtime/transports/realtime.ts +50 -0
- package/src/runtime/transports/remote-events.ts +16 -0
- package/src/runtime/transports/shared.ts +39 -0
- package/src/runtime/transports/ui-runtime-events.ts +35 -0
- package/src/runtime/ui/index.ts +39 -0
- package/src/runtime/ui/model-picker/data-provider.ts +182 -0
- package/src/runtime/ui/model-picker/health-enrichment.ts +228 -0
- package/src/runtime/ui/model-picker/index.ts +59 -0
- package/src/runtime/ui/model-picker/types.ts +149 -0
- package/src/runtime/ui/provider-health/data-provider.ts +244 -0
- package/src/runtime/ui/provider-health/fallback-visualizer.ts +69 -0
- package/src/runtime/ui/provider-health/index.ts +46 -0
- package/src/runtime/ui/provider-health/types.ts +146 -0
- package/src/runtime/ui-events.ts +46 -0
- package/src/runtime/ui-read-model-helpers.ts +32 -0
- package/src/runtime/ui-read-models-core.ts +95 -0
- package/src/runtime/ui-read-models-observability-maintenance.ts +81 -0
- package/src/runtime/ui-read-models-observability-options.ts +5 -0
- package/src/runtime/ui-read-models-observability-remote.ts +73 -0
- package/src/runtime/ui-read-models-observability-security.ts +172 -0
- package/src/runtime/ui-read-models-observability-system.ts +217 -0
- package/src/runtime/ui-read-models-observability.ts +59 -0
- package/src/runtime/ui-read-models-operations.ts +203 -0
- package/src/runtime/ui-read-models.ts +61 -0
- package/src/runtime/ui-service-queries.ts +114 -0
- package/src/runtime/ui-services.ts +163 -0
- package/src/runtime/worktree/registry.ts +252 -0
- package/src/scripts/process-messages.ts +42 -0
- package/src/sessions/manager.ts +388 -0
- package/src/shell/blocking-input.ts +89 -0
- package/src/shell/ui-openers.ts +163 -0
- package/src/state/file-watcher.ts +294 -0
- package/src/state/index.ts +56 -0
- package/src/state/knowledge-injection.ts +214 -0
- package/src/state/memory-embedding-http.ts +642 -0
- package/src/state/memory-embeddings.ts +312 -0
- package/src/state/memory-ingest.ts +132 -0
- package/src/state/memory-registry.ts +111 -0
- package/src/state/memory-store-helpers.ts +160 -0
- package/src/state/memory-store.ts +728 -0
- package/src/state/memory-vector-store.ts +418 -0
- package/src/templates/manager.ts +187 -0
- package/src/tools/agent/index.ts +610 -0
- package/src/tools/agent/manager.ts +476 -0
- package/src/tools/analyze/git-modes.ts +380 -0
- package/src/tools/analyze/index.ts +128 -0
- package/src/tools/channel/agent-tools.ts +16 -0
- package/src/tools/channel/index.ts +268 -0
- package/src/tools/control/index.ts +90 -0
- package/src/tools/edit/core.ts +619 -0
- package/src/tools/edit/index.ts +4 -0
- package/src/tools/edit/phased.ts +33 -0
- package/src/tools/fetch/index.ts +3 -0
- package/src/tools/fetch/phased.ts +34 -0
- package/src/tools/fetch/runtime.ts +499 -0
- package/src/tools/index.ts +186 -0
- package/src/tools/mcp/index.ts +190 -0
- package/src/tools/remote-trigger/index.ts +130 -0
- package/src/tools/repl/index.ts +318 -0
- package/src/tools/shared/auto-heal.ts +282 -0
- package/src/tools/state/index.ts +688 -0
- package/src/tools/web-search/index.ts +38 -0
- package/src/tools/write/index.ts +604 -0
- package/src/tools/write/phased.ts +41 -0
- package/src/types/generated/foundation-client-types.ts +22 -0
- package/src/types/sql-js.d.ts +15 -0
- package/src/utils/splash-lines.ts +46 -0
- package/src/version.ts +17 -0
- package/src/watchers/index.ts +11 -0
- package/src/watchers/registry.ts +517 -0
- package/src/web-search/index.ts +26 -0
- package/src/web-search/provider-registry.ts +64 -0
- package/src/web-search/providers/brave.ts +100 -0
- package/src/web-search/providers/duckduckgo.ts +270 -0
- package/src/web-search/providers/exa.ts +77 -0
- package/src/web-search/providers/firecrawl.ts +90 -0
- package/src/web-search/providers/perplexity.ts +86 -0
- package/src/web-search/providers/searxng.ts +88 -0
- package/src/web-search/providers/shared.ts +249 -0
- package/src/web-search/providers/tavily.ts +90 -0
- package/src/web-search/service.ts +142 -0
- package/src/widget/index.ts +2 -0
- package/src/widget/types.ts +9 -0
- package/src/widget/widget.ts +8 -0
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import type { ConfigManager } from '../config/manager.ts';
|
|
2
|
+
import type { SessionDomainState } from '@pellux/goodvibes-sdk/platform/runtime/store/domains/session';
|
|
3
|
+
|
|
4
|
+
export type GuidanceMode = 'off' | 'minimal' | 'guided';
|
|
5
|
+
export type SessionMaintenanceLevel =
|
|
6
|
+
| 'stable'
|
|
7
|
+
| 'watch'
|
|
8
|
+
| 'suggest-compact'
|
|
9
|
+
| 'compacting'
|
|
10
|
+
| 'needs-repair'
|
|
11
|
+
| 'unknown';
|
|
12
|
+
|
|
13
|
+
export interface SessionMaintenanceStatus {
|
|
14
|
+
readonly level: SessionMaintenanceLevel;
|
|
15
|
+
readonly guidanceMode: GuidanceMode;
|
|
16
|
+
readonly usagePct: number;
|
|
17
|
+
readonly remainingTokens: number;
|
|
18
|
+
readonly thresholdPct: number;
|
|
19
|
+
readonly autoCompactEnabled: boolean;
|
|
20
|
+
readonly compactRecommended: boolean;
|
|
21
|
+
readonly sessionMemoryCount: number;
|
|
22
|
+
readonly compactionCount: number;
|
|
23
|
+
readonly lastCompactedAt?: number;
|
|
24
|
+
readonly summary: string;
|
|
25
|
+
readonly reasons: readonly string[];
|
|
26
|
+
readonly nextSteps: readonly string[];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface SessionMaintenanceInput {
|
|
30
|
+
readonly configManager: Pick<ConfigManager, 'get'>;
|
|
31
|
+
readonly currentTokens: number;
|
|
32
|
+
readonly contextWindow: number;
|
|
33
|
+
readonly messageCount?: number;
|
|
34
|
+
readonly sessionMemoryCount?: number;
|
|
35
|
+
readonly session?: Partial<SessionDomainState>;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function getGuidanceMode(configManager: Pick<ConfigManager, 'get'>): GuidanceMode {
|
|
39
|
+
return (configManager.get('behavior.guidanceMode') as GuidanceMode | undefined) ?? 'minimal';
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function compactStateIsActive(state: SessionDomainState['compactionState'] | undefined): boolean {
|
|
43
|
+
return state === 'checking_threshold'
|
|
44
|
+
|| state === 'microcompact'
|
|
45
|
+
|| state === 'collapse'
|
|
46
|
+
|| state === 'autocompact'
|
|
47
|
+
|| state === 'reactive_compact'
|
|
48
|
+
|| state === 'boundary_commit';
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function formatAge(ts: number | undefined): string {
|
|
52
|
+
if (!ts) return 'never';
|
|
53
|
+
const ageMs = Date.now() - ts;
|
|
54
|
+
const minutes = Math.floor(ageMs / 60_000);
|
|
55
|
+
if (minutes < 1) return 'just now';
|
|
56
|
+
if (minutes < 60) return `${minutes}m ago`;
|
|
57
|
+
const hours = Math.floor(minutes / 60);
|
|
58
|
+
if (hours < 24) return `${hours}h ago`;
|
|
59
|
+
return `${Math.floor(hours / 24)}d ago`;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function evaluateSessionMaintenance(input: SessionMaintenanceInput): SessionMaintenanceStatus {
|
|
63
|
+
const guidanceMode = getGuidanceMode(input.configManager);
|
|
64
|
+
const thresholdPct = Math.max(0, Number(input.configManager.get('behavior.autoCompactThreshold') ?? 0));
|
|
65
|
+
const autoCompactEnabled = thresholdPct > 0;
|
|
66
|
+
const currentTokens = Math.max(0, input.currentTokens);
|
|
67
|
+
const contextWindow = Math.max(0, input.contextWindow);
|
|
68
|
+
const usagePct = contextWindow > 0 ? Math.min(100, Math.round((currentTokens / contextWindow) * 100)) : 0;
|
|
69
|
+
const remainingTokens = Math.max(0, contextWindow - currentTokens);
|
|
70
|
+
const sessionMemoryCount = Math.max(0, input.sessionMemoryCount ?? 0);
|
|
71
|
+
const compactionCount = Math.max(0, input.session?.lineage?.filter((entry) => entry.branchReason === 'compaction').length ?? 0);
|
|
72
|
+
const lastCompactedAt = input.session?.lastCompactedAt;
|
|
73
|
+
const messageCount = Math.max(0, input.messageCount ?? 0);
|
|
74
|
+
const warningsEnabled = Boolean(input.configManager.get('behavior.staleContextWarnings'));
|
|
75
|
+
const staleByMessageGrowth =
|
|
76
|
+
(input.session?.compactionMessageCount ?? 0) > 0
|
|
77
|
+
? messageCount - (input.session?.compactionMessageCount ?? 0) >= 12
|
|
78
|
+
: messageCount >= 24;
|
|
79
|
+
|
|
80
|
+
if (contextWindow <= 0) {
|
|
81
|
+
return {
|
|
82
|
+
level: 'unknown',
|
|
83
|
+
guidanceMode,
|
|
84
|
+
usagePct,
|
|
85
|
+
remainingTokens,
|
|
86
|
+
thresholdPct,
|
|
87
|
+
autoCompactEnabled,
|
|
88
|
+
compactRecommended: false,
|
|
89
|
+
sessionMemoryCount,
|
|
90
|
+
compactionCount,
|
|
91
|
+
lastCompactedAt,
|
|
92
|
+
summary: 'Context window unavailable.',
|
|
93
|
+
reasons: ['Current model does not expose a known context limit yet.'],
|
|
94
|
+
nextSteps: guidanceMode === 'off' ? [] : ['/provider', '/context'],
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const reasons: string[] = [];
|
|
99
|
+
const nextSteps: string[] = [];
|
|
100
|
+
let level: SessionMaintenanceLevel = 'stable';
|
|
101
|
+
|
|
102
|
+
if (input.session?.compactionState === 'failed') {
|
|
103
|
+
level = 'needs-repair';
|
|
104
|
+
reasons.push('Compaction failed and the session may need manual recovery.');
|
|
105
|
+
nextSteps.push('/compact', '/health review');
|
|
106
|
+
} else if (compactStateIsActive(input.session?.compactionState)) {
|
|
107
|
+
level = 'compacting';
|
|
108
|
+
reasons.push('Compaction is currently running.');
|
|
109
|
+
} else if ((autoCompactEnabled && usagePct >= thresholdPct) || usagePct >= 80 || remainingTokens <= 15_000) {
|
|
110
|
+
level = 'suggest-compact';
|
|
111
|
+
reasons.push(`Context pressure is high at ${usagePct}% usage.`);
|
|
112
|
+
if (remainingTokens <= 15_000) {
|
|
113
|
+
reasons.push(`Only ${remainingTokens.toLocaleString()} tokens remain before the safety buffer is exhausted.`);
|
|
114
|
+
}
|
|
115
|
+
nextSteps.push('/compact', '/panel tokens');
|
|
116
|
+
} else if ((warningsEnabled && usagePct >= Math.max(70, autoCompactEnabled ? thresholdPct - 10 : 70)) || staleByMessageGrowth) {
|
|
117
|
+
level = 'watch';
|
|
118
|
+
reasons.push(staleByMessageGrowth
|
|
119
|
+
? `Conversation has grown ${messageCount.toLocaleString()} messages since the last maintenance checkpoint.`
|
|
120
|
+
: `Context usage is climbing toward the ${thresholdPct}% auto-compact threshold.`);
|
|
121
|
+
nextSteps.push('/panel tokens');
|
|
122
|
+
if (guidanceMode === 'guided') nextSteps.push('/context');
|
|
123
|
+
} else {
|
|
124
|
+
reasons.push('Context pressure is currently within the stable operating band.');
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (sessionMemoryCount > 0) {
|
|
128
|
+
reasons.push(`${sessionMemoryCount} pinned session memor${sessionMemoryCount === 1 ? 'y is' : 'ies are'} preserved during compaction.`);
|
|
129
|
+
}
|
|
130
|
+
if (compactionCount > 0) {
|
|
131
|
+
reasons.push(`Last compaction ran ${formatAge(lastCompactedAt)}.`);
|
|
132
|
+
}
|
|
133
|
+
if (!autoCompactEnabled) {
|
|
134
|
+
reasons.push('Auto-compaction is disabled; maintenance stays fully manual.');
|
|
135
|
+
if (guidanceMode !== 'off') nextSteps.push('/settings');
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const compactRecommended = level === 'suggest-compact' || level === 'needs-repair';
|
|
139
|
+
const summary =
|
|
140
|
+
level === 'needs-repair'
|
|
141
|
+
? 'Compaction needs operator repair.'
|
|
142
|
+
: level === 'compacting'
|
|
143
|
+
? 'Compaction in progress.'
|
|
144
|
+
: level === 'suggest-compact'
|
|
145
|
+
? `Compact now to recover context headroom (${usagePct}% used).`
|
|
146
|
+
: level === 'watch'
|
|
147
|
+
? `Watch context growth (${usagePct}% used, threshold ${thresholdPct}%).`
|
|
148
|
+
: 'Session maintenance is stable.';
|
|
149
|
+
|
|
150
|
+
return {
|
|
151
|
+
level,
|
|
152
|
+
guidanceMode,
|
|
153
|
+
usagePct,
|
|
154
|
+
remainingTokens,
|
|
155
|
+
thresholdPct,
|
|
156
|
+
autoCompactEnabled,
|
|
157
|
+
compactRecommended,
|
|
158
|
+
sessionMemoryCount,
|
|
159
|
+
compactionCount,
|
|
160
|
+
lastCompactedAt,
|
|
161
|
+
summary,
|
|
162
|
+
reasons,
|
|
163
|
+
nextSteps: [...new Set(nextSteps)],
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export function formatSessionMaintenanceLines(
|
|
168
|
+
status: SessionMaintenanceStatus,
|
|
169
|
+
detail: 'minimal' | 'guided' = 'minimal',
|
|
170
|
+
): string[] {
|
|
171
|
+
const lines = [
|
|
172
|
+
`Maintenance: ${status.summary}`,
|
|
173
|
+
];
|
|
174
|
+
if (detail === 'guided') {
|
|
175
|
+
for (const reason of status.reasons) lines.push(` ${reason}`);
|
|
176
|
+
} else if (status.reasons[0]) {
|
|
177
|
+
lines.push(` ${status.reasons[0]}`);
|
|
178
|
+
}
|
|
179
|
+
const nextSteps = status.nextSteps.length > 0
|
|
180
|
+
? status.nextSteps
|
|
181
|
+
: detail === 'guided'
|
|
182
|
+
? ['/context']
|
|
183
|
+
: [];
|
|
184
|
+
if ((detail === 'guided' || status.guidanceMode !== 'off') && nextSteps.length > 0) {
|
|
185
|
+
lines.push(` Next: ${nextSteps.join(' | ')}`);
|
|
186
|
+
}
|
|
187
|
+
return lines;
|
|
188
|
+
}
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
import { randomBytes } from 'crypto';
|
|
2
|
+
import {
|
|
3
|
+
closeSync,
|
|
4
|
+
existsSync,
|
|
5
|
+
mkdirSync,
|
|
6
|
+
openSync,
|
|
7
|
+
readFileSync,
|
|
8
|
+
readSync,
|
|
9
|
+
renameSync,
|
|
10
|
+
statSync,
|
|
11
|
+
unlinkSync,
|
|
12
|
+
writeFileSync,
|
|
13
|
+
} from 'fs';
|
|
14
|
+
import { dirname, join } from 'path';
|
|
15
|
+
|
|
16
|
+
import { SessionManager, type SessionMeta } from '../sessions/manager.ts';
|
|
17
|
+
import { logger } from '@pellux/goodvibes-sdk/platform/utils/logger';
|
|
18
|
+
import type { SessionReturnContextSummary } from './session-return-context.ts';
|
|
19
|
+
import type { ConversationTitleSource } from '../core/conversation.ts';
|
|
20
|
+
import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils/error-display';
|
|
21
|
+
|
|
22
|
+
export type SessionSnapshot = {
|
|
23
|
+
messages: Array<Record<string, unknown>>;
|
|
24
|
+
timestamp?: number;
|
|
25
|
+
title?: string;
|
|
26
|
+
titleSource?: ConversationTitleSource;
|
|
27
|
+
returnContext?: SessionReturnContextSummary;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export type RecoveryFileInfo = {
|
|
31
|
+
title: string;
|
|
32
|
+
timestamp: number;
|
|
33
|
+
sessionId: string;
|
|
34
|
+
returnContext?: SessionReturnContextSummary;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export type SessionPersistenceOptions = {
|
|
38
|
+
workingDirectory?: string;
|
|
39
|
+
homeDirectory?: string;
|
|
40
|
+
sessionManager?: SessionManager;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export type SessionPersistencePaths = {
|
|
44
|
+
readonly workingDirectory: string;
|
|
45
|
+
readonly homeDirectory: string;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
function requireWorkingDirectory(options?: Pick<SessionPersistenceOptions, 'workingDirectory'>): string {
|
|
49
|
+
const workingDirectory = options?.workingDirectory;
|
|
50
|
+
if (!workingDirectory) {
|
|
51
|
+
throw new Error('Session persistence requires an explicit workingDirectory.');
|
|
52
|
+
}
|
|
53
|
+
return workingDirectory;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function requireHomeDirectory(options?: Pick<SessionPersistenceOptions, 'homeDirectory'>): string {
|
|
57
|
+
const homeDirectory = options?.homeDirectory;
|
|
58
|
+
if (!homeDirectory) {
|
|
59
|
+
throw new Error('Session persistence requires an explicit homeDirectory.');
|
|
60
|
+
}
|
|
61
|
+
return homeDirectory;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function resolveSessionPersistencePaths(options: SessionPersistenceOptions): SessionPersistencePaths {
|
|
65
|
+
return {
|
|
66
|
+
workingDirectory: requireWorkingDirectory(options),
|
|
67
|
+
homeDirectory: requireHomeDirectory(options),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function resolveSessionManager(options?: SessionPersistenceOptions): SessionManager {
|
|
72
|
+
if (options?.sessionManager) {
|
|
73
|
+
return options.sessionManager;
|
|
74
|
+
}
|
|
75
|
+
return new SessionManager(requireWorkingDirectory(options));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function getUserSessionsDir(workingDirectory: string): string {
|
|
79
|
+
return join(workingDirectory, '.goodvibes', 'tui', 'sessions');
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function getLastSessionPointerPath(workingDirectory: string): string {
|
|
83
|
+
return join(getUserSessionsDir(workingDirectory), 'last-session.json');
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function getRecoveryFilePath(homeDirectory: string): string {
|
|
87
|
+
return join(homeDirectory, '.goodvibes', 'tui', 'recovery.jsonl');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function generateUserSessionId(): string {
|
|
91
|
+
return randomBytes(4).toString('hex');
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function saveSession(
|
|
95
|
+
sessionId: string,
|
|
96
|
+
data: SessionSnapshot,
|
|
97
|
+
model: string,
|
|
98
|
+
provider: string,
|
|
99
|
+
title = '',
|
|
100
|
+
options?: SessionPersistenceOptions,
|
|
101
|
+
): void {
|
|
102
|
+
try {
|
|
103
|
+
const sm = resolveSessionManager(options);
|
|
104
|
+
const meta: SessionMeta = {
|
|
105
|
+
title,
|
|
106
|
+
model,
|
|
107
|
+
provider,
|
|
108
|
+
timestamp: data.timestamp ?? Date.now(),
|
|
109
|
+
titleSource: data.titleSource,
|
|
110
|
+
returnContext: data.returnContext,
|
|
111
|
+
};
|
|
112
|
+
sm.save(sessionId, data.messages as Array<Record<string, unknown>>, meta);
|
|
113
|
+
} catch (e) {
|
|
114
|
+
logger.debug('saveSession failed', { error: summarizeError(e) });
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export function persistConversation(
|
|
119
|
+
sessionId: string,
|
|
120
|
+
data: SessionSnapshot,
|
|
121
|
+
model: string,
|
|
122
|
+
provider: string,
|
|
123
|
+
title = '',
|
|
124
|
+
options?: SessionPersistenceOptions,
|
|
125
|
+
): void {
|
|
126
|
+
saveSession(sessionId, data, model, provider, title, options);
|
|
127
|
+
writeLastSessionPointer(sessionId, options);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export function writeLastSessionPointer(sessionId: string, options?: SessionPersistenceOptions): void {
|
|
131
|
+
try {
|
|
132
|
+
const workingDirectory = requireWorkingDirectory(options);
|
|
133
|
+
const pointerPath = getLastSessionPointerPath(workingDirectory);
|
|
134
|
+
mkdirSync(dirname(pointerPath), { recursive: true });
|
|
135
|
+
writeFileSync(
|
|
136
|
+
pointerPath,
|
|
137
|
+
JSON.stringify({ sessionId, timestamp: new Date().toISOString() }) + '\n',
|
|
138
|
+
'utf-8',
|
|
139
|
+
);
|
|
140
|
+
} catch (e) {
|
|
141
|
+
logger.debug('writeLastSessionPointer failed', { error: summarizeError(e) });
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export function readLastSessionPointer(options?: SessionPersistenceOptions): string | null {
|
|
146
|
+
try {
|
|
147
|
+
const workingDirectory = requireWorkingDirectory(options);
|
|
148
|
+
const pointerPath = getLastSessionPointerPath(workingDirectory);
|
|
149
|
+
if (!existsSync(pointerPath)) return null;
|
|
150
|
+
const data = JSON.parse(readFileSync(pointerPath, 'utf-8')) as { sessionId?: unknown };
|
|
151
|
+
if (typeof data.sessionId === 'string' && data.sessionId.trim()) return data.sessionId;
|
|
152
|
+
} catch (e) {
|
|
153
|
+
logger.debug('readLastSessionPointer failed', { error: summarizeError(e) });
|
|
154
|
+
}
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export function loadLastConversation(options?: SessionPersistenceOptions): SessionSnapshot | null {
|
|
159
|
+
try {
|
|
160
|
+
const lastId = readLastSessionPointer(options);
|
|
161
|
+
const sm = resolveSessionManager(options);
|
|
162
|
+
if (!lastId) return null;
|
|
163
|
+
|
|
164
|
+
const { messages } = sm.load(lastId);
|
|
165
|
+
return { messages: messages as Array<Record<string, unknown>> };
|
|
166
|
+
} catch (e) {
|
|
167
|
+
logger.debug('loadLastConversation failed', { error: summarizeError(e) });
|
|
168
|
+
}
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export function writeRecoveryFile(
|
|
173
|
+
snapshot: SessionSnapshot,
|
|
174
|
+
sessionId: string,
|
|
175
|
+
title = '',
|
|
176
|
+
options?: SessionPersistenceOptions,
|
|
177
|
+
): void {
|
|
178
|
+
try {
|
|
179
|
+
if (!snapshot.messages.length) return;
|
|
180
|
+
const homeDirectory = requireHomeDirectory(options);
|
|
181
|
+
const recoveryFile = getRecoveryFilePath(homeDirectory);
|
|
182
|
+
const lines: string[] = [];
|
|
183
|
+
lines.push(JSON.stringify({ type: 'meta', sessionId, title, timestamp: Date.now() }));
|
|
184
|
+
if (snapshot.titleSource || snapshot.returnContext) {
|
|
185
|
+
lines[0] = JSON.stringify({
|
|
186
|
+
type: 'meta',
|
|
187
|
+
sessionId,
|
|
188
|
+
title,
|
|
189
|
+
timestamp: Date.now(),
|
|
190
|
+
titleSource: snapshot.titleSource,
|
|
191
|
+
returnContext: snapshot.returnContext,
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
for (const msg of snapshot.messages) {
|
|
195
|
+
lines.push(JSON.stringify({ type: 'message', ...msg }));
|
|
196
|
+
}
|
|
197
|
+
const tmpPath = recoveryFile + '.tmp';
|
|
198
|
+
mkdirSync(dirname(recoveryFile), { recursive: true });
|
|
199
|
+
writeFileSync(tmpPath, lines.join('\n') + '\n', 'utf-8');
|
|
200
|
+
renameSync(tmpPath, recoveryFile);
|
|
201
|
+
} catch (err) {
|
|
202
|
+
logger.debug('[Recovery] Write failed', { error: summarizeError(err) });
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export function deleteRecoveryFile(options?: SessionPersistenceOptions): void {
|
|
207
|
+
try {
|
|
208
|
+
const homeDirectory = requireHomeDirectory(options);
|
|
209
|
+
unlinkSync(getRecoveryFilePath(homeDirectory));
|
|
210
|
+
} catch {
|
|
211
|
+
// missing file is fine
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
export function checkRecoveryFile(options?: SessionPersistenceOptions): RecoveryFileInfo | null {
|
|
216
|
+
try {
|
|
217
|
+
const { workingDirectory, homeDirectory } = resolveSessionPersistencePaths({
|
|
218
|
+
workingDirectory: requireWorkingDirectory(options),
|
|
219
|
+
homeDirectory: requireHomeDirectory(options),
|
|
220
|
+
});
|
|
221
|
+
const recoveryFile = getRecoveryFilePath(homeDirectory);
|
|
222
|
+
if (!existsSync(recoveryFile)) return null;
|
|
223
|
+
const recoveryMtime = statSync(recoveryFile).mtimeMs;
|
|
224
|
+
const pointerPath = getLastSessionPointerPath(workingDirectory);
|
|
225
|
+
if (existsSync(pointerPath)) {
|
|
226
|
+
const lastCleanMtime = statSync(pointerPath).mtimeMs;
|
|
227
|
+
if (recoveryMtime <= lastCleanMtime) return null;
|
|
228
|
+
}
|
|
229
|
+
const fd = openSync(recoveryFile, 'r');
|
|
230
|
+
const buf = Buffer.alloc(4096);
|
|
231
|
+
const bytesRead = readSync(fd, buf, 0, 4096, 0);
|
|
232
|
+
closeSync(fd);
|
|
233
|
+
const firstLine = buf.toString('utf-8', 0, bytesRead).split('\n')[0];
|
|
234
|
+
const meta = JSON.parse(firstLine) as { title?: string; timestamp?: number; sessionId?: string; returnContext?: SessionReturnContextSummary };
|
|
235
|
+
return {
|
|
236
|
+
title: meta.title ?? '',
|
|
237
|
+
timestamp: meta.timestamp ?? 0,
|
|
238
|
+
sessionId: meta.sessionId ?? '',
|
|
239
|
+
returnContext: meta.returnContext,
|
|
240
|
+
};
|
|
241
|
+
} catch (err) {
|
|
242
|
+
logger.debug('[Recovery] Check failed', { error: summarizeError(err) });
|
|
243
|
+
return null;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
export function loadRecoveryConversation(options?: SessionPersistenceOptions): SessionSnapshot | null {
|
|
248
|
+
try {
|
|
249
|
+
const homeDirectory = requireHomeDirectory(options);
|
|
250
|
+
const recoveryFile = getRecoveryFilePath(homeDirectory);
|
|
251
|
+
const raw = readFileSync(recoveryFile, 'utf-8');
|
|
252
|
+
const lines = raw.split('\n').filter(Boolean);
|
|
253
|
+
if (lines.length < 2) return { messages: [] };
|
|
254
|
+
return {
|
|
255
|
+
title: (() => {
|
|
256
|
+
try {
|
|
257
|
+
const metaLine = JSON.parse(lines[0]) as { title?: string; titleSource?: ConversationTitleSource; returnContext?: SessionReturnContextSummary };
|
|
258
|
+
return metaLine.title;
|
|
259
|
+
} catch {
|
|
260
|
+
return undefined;
|
|
261
|
+
}
|
|
262
|
+
})(),
|
|
263
|
+
titleSource: (() => {
|
|
264
|
+
try {
|
|
265
|
+
const metaLine = JSON.parse(lines[0]) as { titleSource?: ConversationTitleSource };
|
|
266
|
+
return metaLine.titleSource;
|
|
267
|
+
} catch {
|
|
268
|
+
return undefined;
|
|
269
|
+
}
|
|
270
|
+
})(),
|
|
271
|
+
returnContext: (() => {
|
|
272
|
+
try {
|
|
273
|
+
const metaLine = JSON.parse(lines[0]) as { returnContext?: SessionReturnContextSummary };
|
|
274
|
+
return metaLine.returnContext;
|
|
275
|
+
} catch {
|
|
276
|
+
return undefined;
|
|
277
|
+
}
|
|
278
|
+
})(),
|
|
279
|
+
messages: lines.slice(1).map((line) => {
|
|
280
|
+
const { type: _type, ...rest } = JSON.parse(line) as { type: string } & Record<string, unknown>;
|
|
281
|
+
return rest;
|
|
282
|
+
}),
|
|
283
|
+
};
|
|
284
|
+
} catch (err) {
|
|
285
|
+
logger.debug('[Recovery] Load failed', { error: summarizeError(err) });
|
|
286
|
+
return null;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import type { ConversationMessageSnapshot, ConversationTitleSource } from '../core/conversation.ts';
|
|
2
|
+
import type { HelperModel } from '../config/helper-model.ts';
|
|
3
|
+
import type { ConfigManager } from '../config/manager.ts';
|
|
4
|
+
|
|
5
|
+
export type ReturnContextMode = 'off' | 'local' | 'assisted';
|
|
6
|
+
|
|
7
|
+
export interface SessionContinuityHints {
|
|
8
|
+
readonly pendingApprovals?: number;
|
|
9
|
+
readonly activeTasks?: number;
|
|
10
|
+
readonly blockedTasks?: number;
|
|
11
|
+
readonly remoteContracts?: number;
|
|
12
|
+
readonly remoteRunners?: readonly string[];
|
|
13
|
+
readonly worktreeCount?: number;
|
|
14
|
+
readonly worktreePaths?: readonly string[];
|
|
15
|
+
readonly openPanels?: readonly string[];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface SessionReturnContextSummary {
|
|
19
|
+
readonly activityLabel: string;
|
|
20
|
+
readonly statusLabel: string;
|
|
21
|
+
readonly lastUserPrompt?: string;
|
|
22
|
+
readonly lastAssistantReply?: string;
|
|
23
|
+
readonly pendingApprovals: number;
|
|
24
|
+
readonly toolCallCount: number;
|
|
25
|
+
readonly toolResultCount: number;
|
|
26
|
+
readonly assistantTurnCount: number;
|
|
27
|
+
readonly userTurnCount: number;
|
|
28
|
+
readonly lastRole?: string;
|
|
29
|
+
readonly activeTasks?: number;
|
|
30
|
+
readonly blockedTasks?: number;
|
|
31
|
+
readonly remoteContracts?: number;
|
|
32
|
+
readonly remoteRunners?: readonly string[];
|
|
33
|
+
readonly worktreeCount?: number;
|
|
34
|
+
readonly worktreePaths?: readonly string[];
|
|
35
|
+
readonly openPanels?: readonly string[];
|
|
36
|
+
readonly lines: readonly string[];
|
|
37
|
+
readonly assistedNarrative?: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface PersistedSessionContext {
|
|
41
|
+
readonly titleSource?: ConversationTitleSource;
|
|
42
|
+
readonly returnContext?: SessionReturnContextSummary;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
type ReturnContextConfig = Pick<ConfigManager, 'get'>;
|
|
46
|
+
|
|
47
|
+
export function buildPersistedSessionContext(
|
|
48
|
+
messages: readonly ConversationMessageSnapshot[],
|
|
49
|
+
titleSource?: ConversationTitleSource,
|
|
50
|
+
hints?: SessionContinuityHints,
|
|
51
|
+
): PersistedSessionContext {
|
|
52
|
+
return {
|
|
53
|
+
titleSource,
|
|
54
|
+
returnContext: buildLocalReturnContextSummary(messages, hints),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function truncate(text: string, max: number): string {
|
|
59
|
+
return text.length <= max ? text : `${text.slice(0, Math.max(0, max - 1)).trimEnd()}…`;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function textContent(message: ConversationMessageSnapshot | undefined): string {
|
|
63
|
+
if (!message) return '';
|
|
64
|
+
if (typeof message.content === 'string') return message.content;
|
|
65
|
+
if (!Array.isArray(message.content)) return '';
|
|
66
|
+
return message.content
|
|
67
|
+
.filter((part): part is { type: 'text'; text: string } => part.type === 'text')
|
|
68
|
+
.map((part) => part.text)
|
|
69
|
+
.join(' ');
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function getReturnContextMode(configManager: ReturnContextConfig): ReturnContextMode {
|
|
73
|
+
return (configManager.get('behavior.returnContextMode') as ReturnContextMode | undefined) ?? 'off';
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function buildLocalReturnContextSummary(
|
|
77
|
+
messages: readonly ConversationMessageSnapshot[],
|
|
78
|
+
hints?: SessionContinuityHints,
|
|
79
|
+
): SessionReturnContextSummary {
|
|
80
|
+
const userMessages = messages.filter((message) => message.role === 'user');
|
|
81
|
+
const assistantMessages = messages.filter((message) => message.role === 'assistant');
|
|
82
|
+
const toolMessages = messages.filter((message) => message.role === 'tool');
|
|
83
|
+
const pendingApprovals = hints?.pendingApprovals
|
|
84
|
+
?? messages.filter((message) => message.role === 'system' && typeof message.content === 'string' && /approval/i.test(message.content)).length;
|
|
85
|
+
const lastUser = [...messages].reverse().find((message) => message.role === 'user');
|
|
86
|
+
const lastAssistant = [...messages].reverse().find((message) => message.role === 'assistant');
|
|
87
|
+
const lastMessage = messages[messages.length - 1];
|
|
88
|
+
|
|
89
|
+
const lastUserPrompt = truncate(textContent(lastUser), 120);
|
|
90
|
+
const lastAssistantReply = truncate(textContent(lastAssistant), 120);
|
|
91
|
+
|
|
92
|
+
let activityLabel = 'Fresh session';
|
|
93
|
+
let statusLabel = 'idle';
|
|
94
|
+
if (lastMessage?.role === 'assistant') {
|
|
95
|
+
activityLabel = 'assistant replied';
|
|
96
|
+
statusLabel = 'ready for next turn';
|
|
97
|
+
} else if (lastMessage?.role === 'tool') {
|
|
98
|
+
activityLabel = 'tool work completed';
|
|
99
|
+
statusLabel = 'awaiting assistant follow-up';
|
|
100
|
+
} else if (lastMessage?.role === 'user') {
|
|
101
|
+
activityLabel = 'user prompt queued';
|
|
102
|
+
statusLabel = 'awaiting response';
|
|
103
|
+
} else if (lastMessage?.role === 'system') {
|
|
104
|
+
activityLabel = 'system/operator update';
|
|
105
|
+
statusLabel = 'review recommended';
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const lines: string[] = [];
|
|
109
|
+
lines.push(`Activity: ${activityLabel}`);
|
|
110
|
+
lines.push(`Status: ${statusLabel}`);
|
|
111
|
+
if (lastUserPrompt) lines.push(`Last prompt: ${lastUserPrompt}`);
|
|
112
|
+
if (lastAssistantReply) lines.push(`Last reply: ${lastAssistantReply}`);
|
|
113
|
+
if (pendingApprovals > 0) lines.push(`Pending approvals spotted: ${pendingApprovals}`);
|
|
114
|
+
if (toolMessages.length > 0) lines.push(`Tool results in session: ${toolMessages.length}`);
|
|
115
|
+
if ((hints?.activeTasks ?? 0) > 0 || (hints?.blockedTasks ?? 0) > 0) {
|
|
116
|
+
lines.push(`Tasks: active ${hints?.activeTasks ?? 0}, blocked ${hints?.blockedTasks ?? 0}`);
|
|
117
|
+
}
|
|
118
|
+
if ((hints?.remoteContracts ?? 0) > 0) {
|
|
119
|
+
lines.push(`Remote contracts: ${hints?.remoteContracts}`);
|
|
120
|
+
}
|
|
121
|
+
if ((hints?.remoteRunners?.length ?? 0) > 0) {
|
|
122
|
+
lines.push(`Remote runners: ${hints!.remoteRunners!.slice(0, 3).join(', ')}`);
|
|
123
|
+
}
|
|
124
|
+
if ((hints?.worktreeCount ?? 0) > 0) {
|
|
125
|
+
lines.push(`Worktrees tracked: ${hints?.worktreeCount}`);
|
|
126
|
+
}
|
|
127
|
+
if ((hints?.worktreePaths?.length ?? 0) > 0) {
|
|
128
|
+
lines.push(`Worktree paths: ${hints!.worktreePaths!.slice(0, 2).join(', ')}`);
|
|
129
|
+
}
|
|
130
|
+
if ((hints?.openPanels?.length ?? 0) > 0) {
|
|
131
|
+
lines.push(`Open panels: ${hints!.openPanels!.slice(0, 4).join(', ')}`);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return {
|
|
135
|
+
activityLabel,
|
|
136
|
+
statusLabel,
|
|
137
|
+
lastUserPrompt: lastUserPrompt || undefined,
|
|
138
|
+
lastAssistantReply: lastAssistantReply || undefined,
|
|
139
|
+
pendingApprovals,
|
|
140
|
+
toolCallCount: assistantMessages.reduce((count, message) => count + (message.toolCalls?.length ?? 0), 0),
|
|
141
|
+
toolResultCount: toolMessages.length,
|
|
142
|
+
assistantTurnCount: assistantMessages.length,
|
|
143
|
+
userTurnCount: userMessages.length,
|
|
144
|
+
lastRole: lastMessage?.role,
|
|
145
|
+
...(typeof hints?.activeTasks === 'number' ? { activeTasks: hints.activeTasks } : {}),
|
|
146
|
+
...(typeof hints?.blockedTasks === 'number' ? { blockedTasks: hints.blockedTasks } : {}),
|
|
147
|
+
...(typeof hints?.remoteContracts === 'number' ? { remoteContracts: hints.remoteContracts } : {}),
|
|
148
|
+
...(hints?.remoteRunners ? { remoteRunners: [...hints.remoteRunners] } : {}),
|
|
149
|
+
...(typeof hints?.worktreeCount === 'number' ? { worktreeCount: hints.worktreeCount } : {}),
|
|
150
|
+
...(hints?.worktreePaths ? { worktreePaths: [...hints.worktreePaths] } : {}),
|
|
151
|
+
...(hints?.openPanels ? { openPanels: [...hints.openPanels] } : {}),
|
|
152
|
+
lines,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export async function maybeAssistReturnContextSummary(
|
|
157
|
+
configManager: ReturnContextConfig,
|
|
158
|
+
helperModel: Pick<HelperModel, 'chat'>,
|
|
159
|
+
summary: SessionReturnContextSummary,
|
|
160
|
+
): Promise<SessionReturnContextSummary> {
|
|
161
|
+
if (getReturnContextMode(configManager) !== 'assisted') return summary;
|
|
162
|
+
|
|
163
|
+
const enabled = configManager.get('helper.enabled') as boolean | undefined;
|
|
164
|
+
if (!enabled) return summary;
|
|
165
|
+
|
|
166
|
+
const prompt = [
|
|
167
|
+
'You are generating a terse resume summary for a terminal coding session.',
|
|
168
|
+
'Return one sentence under 160 characters.',
|
|
169
|
+
'Focus on what the operator should look at first.',
|
|
170
|
+
'',
|
|
171
|
+
`Activity: ${summary.activityLabel}`,
|
|
172
|
+
`Status: ${summary.statusLabel}`,
|
|
173
|
+
...(summary.lastUserPrompt ? [`Last prompt: ${summary.lastUserPrompt}`] : []),
|
|
174
|
+
...(summary.lastAssistantReply ? [`Last reply: ${summary.lastAssistantReply}`] : []),
|
|
175
|
+
`Pending approvals: ${summary.pendingApprovals}`,
|
|
176
|
+
`Tool calls: ${summary.toolCallCount}`,
|
|
177
|
+
`Tool results: ${summary.toolResultCount}`,
|
|
178
|
+
].join('\n');
|
|
179
|
+
|
|
180
|
+
const response = (await helperModel.chat('tool_summarize', prompt, { maxTokens: 80, helperOnly: true })).trim();
|
|
181
|
+
if (!response) return summary;
|
|
182
|
+
return {
|
|
183
|
+
...summary,
|
|
184
|
+
assistedNarrative: truncate(response.replace(/\s+/g, ' '), 160),
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export function formatReturnContextForDisplay(summary: SessionReturnContextSummary | undefined): string[] {
|
|
189
|
+
if (!summary) return [];
|
|
190
|
+
const lines = [...summary.lines];
|
|
191
|
+
if (summary.assistedNarrative) {
|
|
192
|
+
lines.unshift(`Assist: ${summary.assistedNarrative}`);
|
|
193
|
+
}
|
|
194
|
+
return lines;
|
|
195
|
+
}
|