@pellux/goodvibes-tui 0.18.4 → 0.18.9
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 +190 -0
- package/README.md +2 -2
- package/bin/goodvibes +1 -1
- package/bin/goodvibes-daemon +66 -0
- package/docs/foundation-artifacts/operator-contract.json +1 -1
- package/package.json +14 -7
- package/scripts/postinstall.js +220 -0
- package/src/acp/connection.ts +5 -5
- package/src/acp/index.ts +1 -1
- package/src/acp/manager.ts +1 -133
- package/src/adapters/bluebubbles/index.ts +1 -1
- package/src/adapters/discord/index.ts +2 -2
- package/src/adapters/github/index.ts +1 -1
- package/src/adapters/google-chat/index.ts +1 -1
- package/src/adapters/imessage/index.ts +1 -1
- package/src/adapters/index.ts +15 -15
- package/src/adapters/matrix/index.ts +1 -1
- package/src/adapters/mattermost/index.ts +1 -1
- package/src/adapters/msteams/index.ts +2 -2
- package/src/adapters/ntfy/index.ts +1 -1
- package/src/adapters/signal/index.ts +1 -1
- package/src/adapters/slack/index.ts +2 -2
- package/src/adapters/telegram/index.ts +1 -1
- package/src/adapters/types.ts +4 -4
- package/src/adapters/webhook/index.ts +1 -1
- package/src/adapters/whatsapp/index.ts +1 -1
- package/src/agents/message-bus-core.ts +2 -2
- package/src/agents/message-bus.ts +2 -2
- package/src/agents/orchestrator-prompts.ts +4 -4
- package/src/agents/orchestrator-runner.ts +11 -11
- package/src/agents/orchestrator.ts +15 -14
- package/src/agents/session.ts +1 -1
- package/src/agents/worktree.ts +1 -1
- package/src/agents/wrfc-config.ts +2 -2
- package/src/agents/wrfc-controller.ts +12 -12
- package/src/agents/wrfc-gate-runtime.ts +5 -5
- package/src/agents/wrfc-reporting.ts +1 -1
- package/src/agents/wrfc-runtime-events.ts +3 -3
- package/src/agents/wrfc-types.ts +1 -1
- package/src/automation/delivery-manager.ts +4 -4
- package/src/automation/index.ts +4 -4
- package/src/automation/manager-runtime-delivery.ts +1 -1
- package/src/automation/manager-runtime-events.ts +3 -3
- package/src/automation/manager-runtime-execution.ts +5 -5
- package/src/automation/manager-runtime-helpers.ts +2 -2
- package/src/automation/manager-runtime-job-mutations.ts +3 -3
- package/src/automation/manager-runtime-reconcile.ts +4 -4
- package/src/automation/manager-runtime-scheduling.ts +2 -2
- package/src/automation/manager-runtime.ts +18 -18
- package/src/automation/manager.ts +2 -2
- package/src/automation/service.ts +2 -2
- package/src/channels/builtin/account-actions.ts +5 -5
- package/src/channels/builtin/accounts.ts +2 -2
- package/src/channels/builtin/contracts.ts +3 -3
- package/src/channels/builtin/plugins.ts +5 -5
- package/src/channels/builtin/rendering.ts +4 -4
- package/src/channels/builtin/setup-schema.ts +1 -1
- package/src/channels/builtin/shared.ts +7 -7
- package/src/channels/builtin/surfaces.ts +2 -2
- package/src/channels/builtin/targets.ts +3 -3
- package/src/channels/builtin-runtime.ts +11 -11
- package/src/channels/delivery/shared.ts +2 -2
- package/src/channels/delivery/strategies-bridge.ts +3 -3
- package/src/channels/delivery/strategies-core.ts +5 -5
- package/src/channels/delivery/strategies-enterprise.ts +3 -3
- package/src/channels/delivery/types.ts +2 -2
- package/src/channels/delivery-router.ts +9 -9
- package/src/channels/index.ts +12 -12
- package/src/channels/plugin-registry.ts +1 -1
- package/src/channels/provider-runtime.ts +3 -3
- package/src/channels/reply-pipeline.ts +3 -3
- package/src/channels/route-manager.ts +2 -2
- package/src/channels/surface-registry.ts +2 -2
- package/src/config/helper-model.ts +1 -233
- package/src/config/index.ts +3 -3
- package/src/config/manager.ts +8 -404
- package/src/config/secrets.ts +21 -542
- package/src/config/service-registry.ts +1 -329
- package/src/config/tool-llm.ts +3 -3
- package/src/control-plane/approval-broker.ts +1 -1
- package/src/control-plane/gateway.ts +1 -713
- package/src/control-plane/index.ts +7 -7
- package/src/control-plane/media-contract-schemas.ts +1 -208
- package/src/control-plane/method-catalog-admin.ts +1 -136
- package/src/control-plane/method-catalog-channels.ts +1 -591
- package/src/control-plane/method-catalog-control-automation.ts +1 -475
- package/src/control-plane/method-catalog-control-core.ts +1 -594
- package/src/control-plane/method-catalog-control.ts +1 -8
- package/src/control-plane/method-catalog-events.ts +1 -74
- package/src/control-plane/method-catalog-knowledge.ts +1 -531
- package/src/control-plane/method-catalog-media.ts +1 -279
- package/src/control-plane/method-catalog-runtime.ts +1 -304
- package/src/control-plane/method-catalog-shared.ts +1 -223
- package/src/control-plane/method-catalog.ts +1 -242
- package/src/control-plane/operator-contract-schemas-admin.ts +1 -639
- package/src/control-plane/operator-contract-schemas-channels.ts +1 -375
- package/src/control-plane/operator-contract-schemas-control.ts +1 -226
- package/src/control-plane/operator-contract-schemas-domains.ts +1 -4
- package/src/control-plane/operator-contract-schemas-knowledge.ts +1 -582
- package/src/control-plane/operator-contract-schemas-media.ts +1 -297
- package/src/control-plane/operator-contract-schemas-permissions.ts +1 -100
- package/src/control-plane/operator-contract-schemas-remote.ts +1 -38
- package/src/control-plane/operator-contract-schemas-runtime.ts +1 -563
- package/src/control-plane/operator-contract-schemas-shared.ts +1 -85
- package/src/control-plane/operator-contract-schemas-telemetry.ts +1 -349
- package/src/control-plane/operator-contract-schemas.ts +1 -6
- package/src/control-plane/operator-contract.ts +5 -3
- package/src/control-plane/session-broker.ts +1 -1
- package/src/core/compaction-sections.ts +5 -5
- package/src/core/compaction-types.ts +3 -3
- package/src/core/composer-state.ts +1 -1
- package/src/core/context-compaction.ts +7 -7
- package/src/core/conversation-compaction.ts +4 -4
- package/src/core/conversation-diff.ts +1 -1
- package/src/core/conversation-rendering.ts +5 -5
- package/src/core/conversation-utils.ts +2 -2
- package/src/core/conversation.ts +10 -10
- package/src/core/event-replay.ts +1 -1
- package/src/core/orchestrator-context-runtime.ts +8 -8
- package/src/core/orchestrator-follow-up-runtime.ts +2 -2
- package/src/core/orchestrator-runtime.ts +4 -4
- package/src/core/orchestrator-tool-runtime.ts +7 -7
- package/src/core/orchestrator-turn-helpers.ts +7 -7
- package/src/core/orchestrator-turn-loop.ts +10 -10
- package/src/core/orchestrator.ts +17 -17
- package/src/core/plan-command-handler.ts +2 -2
- package/src/core/system-message-router.ts +2 -2
- package/src/core/transcript-events/classify.ts +1 -1
- package/src/core/transcript-events/index.ts +3 -3
- package/src/daemon/cli.ts +6 -6
- package/src/daemon/control-plane.ts +7 -7
- package/src/daemon/facade-composition.ts +16 -15
- package/src/daemon/facade.ts +17 -17
- package/src/daemon/helpers.ts +2 -2
- package/src/daemon/http/router-route-contexts.ts +11 -11
- package/src/daemon/http/router.ts +25 -25
- package/src/daemon/http-listener.ts +3 -3
- package/src/daemon/index.ts +1 -3
- package/src/daemon/service-manager.ts +1 -1
- package/src/daemon/surface-actions.ts +8 -8
- package/src/daemon/surface-delivery.ts +7 -7
- package/src/daemon/surface-policy.ts +1 -1
- package/src/daemon/transport-events.ts +4 -4
- package/src/daemon/types.ts +24 -24
- package/src/export/markdown.ts +1 -1
- package/src/export/session-export.ts +1 -633
- package/src/git/index.ts +1 -1
- package/src/git/service.ts +1 -1
- package/src/hooks/chain-engine.ts +1 -1
- package/src/hooks/dispatcher.ts +4 -4
- package/src/hooks/hook-api.ts +1 -1
- package/src/hooks/index.ts +8 -8
- package/src/hooks/runners/agent.ts +1 -1
- package/src/hooks/runners/prompt.ts +1 -1
- package/src/hooks/workbench.ts +2 -2
- package/src/input/command-registry.ts +24 -17
- package/src/input/commands/config.ts +1 -1
- package/src/input/commands/control-room-runtime.ts +2 -2
- package/src/input/commands/conversation-runtime.ts +1 -1
- package/src/input/commands/discovery-runtime.ts +7 -1
- package/src/input/commands/eval.ts +2 -2
- package/src/input/commands/git-runtime.ts +1 -1
- package/src/input/commands/guidance-runtime.ts +3 -3
- package/src/input/commands/health-runtime.ts +7 -7
- package/src/input/commands/incident-runtime.ts +1 -1
- package/src/input/commands/integration-runtime.ts +3 -3
- package/src/input/commands/local-provider-runtime.ts +1 -1
- package/src/input/commands/local-runtime.ts +1 -1
- package/src/input/commands/local-setup-review.ts +2 -2
- package/src/input/commands/local-setup.ts +2 -2
- package/src/input/commands/managed-runtime.ts +2 -2
- package/src/input/commands/marketplace-runtime.ts +1 -1
- package/src/input/commands/platform-access-runtime.ts +1 -1
- package/src/input/commands/platform-sandbox-qemu.ts +3 -3
- package/src/input/commands/platform-sandbox-runtime.ts +5 -5
- package/src/input/commands/platform-sandbox-session.ts +1 -1
- package/src/input/commands/policy-dispatch.ts +2 -2
- package/src/input/commands/product-runtime.ts +2 -2
- package/src/input/commands/profile-sync-runtime.ts +1 -1
- package/src/input/commands/provider-accounts-runtime.ts +1 -1
- package/src/input/commands/provider.ts +3 -3
- package/src/input/commands/quit-shared.ts +1 -1
- package/src/input/commands/recall-bundle.ts +1 -1
- package/src/input/commands/recall-capture.ts +2 -2
- package/src/input/commands/recall-query.ts +2 -2
- package/src/input/commands/recall-shared.ts +1 -1
- package/src/input/commands/remote-runtime-setup.ts +1 -1
- package/src/input/commands/remote-runtime.ts +1 -1
- package/src/input/commands/runtime-services.ts +13 -11
- package/src/input/commands/schedule-runtime.ts +2 -2
- package/src/input/commands/session-content.ts +1 -1
- package/src/input/commands/session-workflow.ts +4 -4
- package/src/input/commands/settings-sync-runtime.ts +1 -1
- package/src/input/commands/share-runtime.ts +9 -4
- package/src/input/commands/shell-core.ts +1 -1
- package/src/input/commands/skills-runtime.ts +1 -1
- package/src/input/commands/subscription-runtime.ts +1 -1
- package/src/input/commands/tasks-runtime.ts +1 -1
- package/src/input/commands/teamwork-runtime.ts +1 -1
- package/src/input/commands/worktree-runtime.ts +1 -1
- package/src/input/handler-command-route.ts +1 -1
- package/src/input/handler-content-actions.ts +3 -3
- package/src/input/handler-feed-routes.ts +2 -2
- package/src/input/handler-feed.ts +1 -1
- package/src/input/handler-shortcuts.ts +1 -1
- package/src/input/handler.ts +1 -1
- package/src/input/keybindings.ts +5 -0
- package/src/input/model-picker.ts +2 -2
- package/src/input/profile-picker-modal.ts +1 -1
- package/src/input/session-picker-modal.ts +1 -1
- package/src/input/settings-modal.ts +4 -4
- package/src/integrations/index.ts +1 -1
- package/src/integrations/notifier.ts +1 -1
- package/src/integrations/webhooks.ts +1 -177
- package/src/knowledge/consolidation.ts +2 -2
- package/src/knowledge/graphql.ts +1 -1
- package/src/knowledge/index.ts +5 -5
- package/src/knowledge/ingest-compile.ts +3 -3
- package/src/knowledge/ingest-context.ts +1 -1
- package/src/knowledge/ingest-inputs.ts +4 -4
- package/src/knowledge/ingest.ts +1 -20
- package/src/knowledge/internal.ts +1 -1
- package/src/knowledge/knowledge-api.ts +7 -7
- package/src/knowledge/lint.ts +3 -3
- package/src/knowledge/memory-sync.ts +2 -2
- package/src/knowledge/packet.ts +3 -3
- package/src/knowledge/scheduling.ts +2 -2
- package/src/knowledge/service.ts +10 -10
- package/src/main.ts +11 -10
- package/src/mcp/index.ts +4 -4
- package/src/mcp/mcp-api.ts +1 -1
- package/src/mcp/registry.ts +1 -508
- package/src/media/builtin-image-understanding.ts +2 -2
- package/src/media/builtin-providers.ts +2 -2
- package/src/media/index.ts +1 -1
- package/src/multimodal/index.ts +1 -1
- package/src/multimodal/service.ts +2 -2
- package/src/panels/agent-inspector-panel.ts +2 -2
- package/src/panels/agent-logs-panel.ts +3 -3
- package/src/panels/approval-panel.ts +2 -2
- package/src/panels/builtin/operations.ts +3 -1
- package/src/panels/builtin/shared.ts +14 -14
- package/src/panels/context-visualizer-panel.ts +2 -2
- package/src/panels/cost-tracker-panel.ts +2 -2
- package/src/panels/debug-panel.ts +3 -3
- package/src/panels/git-panel.ts +1 -1
- package/src/panels/hooks-panel.ts +4 -4
- package/src/panels/knowledge-panel.ts +1 -1
- package/src/panels/marketplace-panel.ts +1 -1
- package/src/panels/mcp-panel.ts +1 -1
- package/src/panels/memory-panel.ts +2 -2
- package/src/panels/ops-control-panel.ts +2 -2
- package/src/panels/ops-strategy-panel.ts +2 -2
- package/src/panels/plugins-panel.ts +1 -1
- package/src/panels/policy-panel.ts +1 -1
- package/src/panels/provider-health-panel.ts +3 -3
- package/src/panels/provider-stats-panel.ts +2 -2
- package/src/panels/sandbox-panel.ts +3 -3
- package/src/panels/schedule-panel.ts +1 -1
- package/src/panels/settings-sync-panel.ts +1 -1
- package/src/panels/skills-panel.ts +28 -1
- package/src/panels/system-messages-panel.ts +1 -1
- package/src/panels/tasks-panel.ts +1 -1
- package/src/panels/thinking-panel.ts +2 -2
- package/src/panels/token-budget-panel.ts +1 -1
- package/src/panels/tool-inspector-panel.ts +2 -2
- package/src/panels/worktree-panel.ts +1 -1
- package/src/panels/wrfc-panel.ts +4 -4
- package/src/permissions/briefs/build.ts +1 -1
- package/src/permissions/manager.ts +1 -356
- package/src/permissions/prompt.ts +1 -1
- package/src/plugins/api.ts +9 -9
- package/src/plugins/loader.ts +8 -8
- package/src/plugins/manager.ts +5 -5
- package/src/providers/amazon-bedrock-mantle.ts +1 -1
- package/src/providers/amazon-bedrock.ts +1 -1
- package/src/providers/anthropic-compat.ts +4 -4
- package/src/providers/anthropic-sdk-provider.ts +5 -5
- package/src/providers/anthropic-vertex.ts +1 -1
- package/src/providers/anthropic.ts +4 -4
- package/src/providers/auto-register.ts +6 -6
- package/src/providers/builtin-catalog.ts +2 -2
- package/src/providers/builtin-registry.ts +15 -15
- package/src/providers/cache-planner.ts +2 -2
- package/src/providers/capabilities.ts +1 -601
- package/src/providers/custom-loader.ts +6 -6
- package/src/providers/discovered-compat.ts +7 -18
- package/src/providers/discovered-factory.ts +7 -7
- package/src/providers/discovered-traits.ts +1 -1
- package/src/providers/gemini.ts +4 -4
- package/src/providers/github-copilot.ts +4 -4
- package/src/providers/index.ts +1 -47
- package/src/providers/interface.ts +1 -1
- package/src/providers/llama-cpp.ts +4 -4
- package/src/providers/lm-studio-helpers.ts +1 -1
- package/src/providers/lm-studio.ts +4 -4
- package/src/providers/model-catalog-cache.ts +1 -1
- package/src/providers/model-catalog-notifications.ts +1 -1
- package/src/providers/model-catalog-synthetic.ts +2 -2
- package/src/providers/model-catalog.ts +7 -7
- package/src/providers/model-limits.ts +1 -280
- package/src/providers/ollama.ts +4 -4
- package/src/providers/openai-codex.ts +2 -2
- package/src/providers/openai-compat.ts +4 -4
- package/src/providers/openai.ts +3 -3
- package/src/providers/optimizer.ts +1 -381
- package/src/providers/provider-api.ts +1 -553
- package/src/providers/registry-helpers.ts +1 -1
- package/src/providers/registry-models.ts +2 -2
- package/src/providers/registry-types.ts +5 -5
- package/src/providers/registry.ts +1 -729
- package/src/providers/runtime-metadata.ts +1 -1
- package/src/providers/runtime-snapshot.ts +3 -3
- package/src/providers/synthetic.ts +3 -3
- package/src/providers/tier-prompts.ts +1 -1
- package/src/providers/tool-formats.ts +1 -1
- package/src/renderer/agent-detail-modal.ts +2 -2
- package/src/renderer/block-actions.ts +1 -1
- package/src/renderer/context-inspector.ts +1 -1
- package/src/renderer/conversation-layout.ts +1 -1
- package/src/renderer/conversation-overlays.ts +1 -1
- package/src/renderer/git-status.ts +1 -1
- package/src/renderer/live-tail-modal.ts +1 -1
- package/src/renderer/process-modal.ts +2 -2
- package/src/runtime/bootstrap-background.ts +18 -8
- package/src/runtime/bootstrap-command-context.ts +24 -24
- package/src/runtime/bootstrap-command-parts.ts +24 -24
- package/src/runtime/bootstrap-core.ts +12 -10
- package/src/runtime/bootstrap-helpers.ts +2 -2
- package/src/runtime/bootstrap-hook-bridge.ts +9 -9
- package/src/runtime/bootstrap-runtime-events.ts +4 -4
- package/src/runtime/bootstrap-services.ts +4 -4
- package/src/runtime/bootstrap-shell.ts +11 -11
- package/src/runtime/bootstrap.ts +28 -10
- package/src/runtime/compaction/index.ts +1 -90
- package/src/runtime/compaction/lifecycle.ts +1 -167
- package/src/runtime/compaction/manager.ts +11 -11
- package/src/runtime/compaction/quality-score.ts +1 -279
- package/src/runtime/compaction/resume-repair.ts +1 -183
- package/src/runtime/compaction/strategies/autocompact.ts +1 -65
- package/src/runtime/compaction/strategies/boundary-commit.ts +1 -106
- package/src/runtime/compaction/strategies/collapse.ts +1 -90
- package/src/runtime/compaction/strategies/index.ts +1 -23
- package/src/runtime/compaction/strategies/microcompact.ts +1 -74
- package/src/runtime/compaction/strategies/reactive.ts +1 -89
- package/src/runtime/compaction/types.ts +1 -221
- package/src/runtime/context.ts +10 -10
- package/src/runtime/diagnostics/actions.ts +1 -1
- package/src/runtime/diagnostics/index.ts +5 -5
- package/src/runtime/diagnostics/panels/agents.ts +2 -2
- package/src/runtime/diagnostics/panels/events.ts +2 -2
- package/src/runtime/diagnostics/panels/health.ts +2 -2
- package/src/runtime/diagnostics/panels/ops.ts +2 -2
- package/src/runtime/diagnostics/panels/policy.ts +2 -2
- package/src/runtime/diagnostics/panels/tasks.ts +2 -2
- package/src/runtime/diagnostics/panels/tool-calls.ts +2 -2
- package/src/runtime/diagnostics/provider.ts +1 -1
- package/src/runtime/ecosystem/recommendations.ts +1 -1
- package/src/runtime/emitters/agents.ts +2 -2
- package/src/runtime/emitters/automation.ts +2 -2
- package/src/runtime/emitters/communication.ts +2 -2
- package/src/runtime/emitters/compaction.ts +2 -2
- package/src/runtime/emitters/control-plane.ts +2 -2
- package/src/runtime/emitters/deliveries.ts +2 -2
- package/src/runtime/emitters/forensics.ts +2 -2
- package/src/runtime/emitters/index.ts +27 -27
- package/src/runtime/emitters/knowledge.ts +2 -2
- package/src/runtime/emitters/mcp.ts +2 -2
- package/src/runtime/emitters/ops.ts +2 -2
- package/src/runtime/emitters/orchestration.ts +2 -2
- package/src/runtime/emitters/permissions.ts +2 -2
- package/src/runtime/emitters/planner.ts +2 -2
- package/src/runtime/emitters/plugins.ts +2 -2
- package/src/runtime/emitters/providers.ts +2 -2
- package/src/runtime/emitters/routes.ts +2 -2
- package/src/runtime/emitters/security.ts +2 -2
- package/src/runtime/emitters/session.ts +2 -2
- package/src/runtime/emitters/surfaces.ts +2 -2
- package/src/runtime/emitters/tasks.ts +2 -2
- package/src/runtime/emitters/tools.ts +2 -2
- package/src/runtime/emitters/transport.ts +2 -2
- package/src/runtime/emitters/turn.ts +3 -3
- package/src/runtime/emitters/ui.ts +2 -2
- package/src/runtime/emitters/watchers.ts +2 -2
- package/src/runtime/emitters/workflows.ts +3 -3
- package/src/runtime/eval/index.ts +3 -3
- package/src/runtime/eval/runner.ts +1 -1
- package/src/runtime/eval/suites.ts +1 -1
- package/src/runtime/events/domain-map.ts +2 -2
- package/src/runtime/events/index.ts +1 -194
- package/src/runtime/events/turn.ts +1 -60
- package/src/runtime/events/workflows.ts +1 -17
- package/src/runtime/forensics/collector.ts +4 -4
- package/src/runtime/forensics/index.ts +1 -1
- package/src/runtime/foundation-clients.ts +14 -14
- package/src/runtime/foundation-services.ts +8 -8
- package/src/runtime/guidance.ts +3 -3
- package/src/runtime/health/effect-handlers.ts +3 -3
- package/src/runtime/health/index.ts +4 -4
- package/src/runtime/health/wiring.ts +2 -2
- package/src/runtime/index.ts +29 -29
- package/src/runtime/integration/helpers.ts +12 -12
- package/src/runtime/lifecycle.ts +4 -4
- package/src/runtime/mcp/index.ts +3 -3
- package/src/runtime/mcp/manager.ts +1 -1
- package/src/runtime/network/inbound.ts +2 -2
- package/src/runtime/network/index.ts +5 -5
- package/src/runtime/network/outbound.ts +2 -2
- package/src/runtime/network/shared.ts +1 -1
- package/src/runtime/operator-client.ts +9 -9
- package/src/runtime/ops/control-plane.ts +2 -2
- package/src/runtime/ops/index.ts +3 -3
- package/src/runtime/ops/playbooks/index.ts +2 -2
- package/src/runtime/ops/playbooks/session-unrecoverable.ts +2 -2
- package/src/runtime/ops/playbooks/stuck-turn.ts +1 -1
- package/src/runtime/ops/runtime-context.ts +1 -1
- package/src/runtime/orchestration/spawn-policy.ts +1 -1
- package/src/runtime/peer-client.ts +3 -3
- package/src/runtime/perf/index.ts +1 -1
- package/src/runtime/perf/slo-collector.ts +1 -1
- package/src/runtime/permissions/index.ts +5 -5
- package/src/runtime/permissions/policy-runtime.ts +1 -175
- package/src/runtime/permissions/rule-suggestions.ts +1 -1
- package/src/runtime/plugins/hot-reload.ts +4 -4
- package/src/runtime/plugins/index.ts +13 -13
- package/src/runtime/plugins/lifecycle.ts +1 -1
- package/src/runtime/plugins/manager.ts +10 -10
- package/src/runtime/plugins/manifest.ts +2 -2
- package/src/runtime/plugins/quarantine.ts +2 -2
- package/src/runtime/plugins/trust.ts +2 -2
- package/src/runtime/plugins/types.ts +1 -1
- package/src/runtime/provider-accounts/registry.ts +2 -2
- package/src/runtime/remote/distributed-runtime-contract-schemas.ts +3 -3
- package/src/runtime/remote/index.ts +3 -3
- package/src/runtime/remote/runner-registry.ts +2 -2
- package/src/runtime/remote/supervisor.ts +1 -1
- package/src/runtime/runtime-hook-api.ts +1 -1
- package/src/runtime/runtime-knowledge-api.ts +1 -1
- package/src/runtime/runtime-mcp-api.ts +1 -1
- package/src/runtime/runtime-ops-api.ts +2 -2
- package/src/runtime/runtime-provider-api.ts +1 -1
- package/src/runtime/services.ts +42 -35
- package/src/runtime/session-maintenance.ts +1 -1
- package/src/runtime/session-persistence.ts +2 -2
- package/src/runtime/session-return-context.ts +3 -3
- package/src/runtime/settings/control-plane-store.ts +1 -1
- package/src/runtime/settings/control-plane.ts +2 -2
- package/src/runtime/shell-command-extensions.ts +7 -7
- package/src/runtime/shell-command-ops.ts +6 -6
- package/src/runtime/shell-command-platform.ts +1 -1
- package/src/runtime/shell-command-services.ts +18 -18
- package/src/runtime/shell-command-workspace.ts +2 -2
- package/src/runtime/store/domains/conversation.ts +1 -1
- package/src/runtime/store/domains/index.ts +4 -4
- package/src/runtime/store/domains/permissions.ts +1 -1
- package/src/runtime/store/helpers/reducers/conversation.ts +3 -3
- package/src/runtime/store/helpers/reducers/lifecycle.ts +3 -3
- package/src/runtime/store/helpers/reducers/shared.ts +2 -2
- package/src/runtime/store/helpers/reducers/sync.ts +1 -1
- package/src/runtime/store/helpers/reducers.ts +4 -4
- package/src/runtime/store/index.ts +4 -4
- package/src/runtime/store/selectors/index.ts +2 -2
- package/src/runtime/store/state.ts +4 -4
- package/src/runtime/tasks/adapters/acp-adapter.ts +1 -1
- package/src/runtime/tasks/adapters/index.ts +6 -6
- package/src/runtime/tasks/index.ts +3 -3
- package/src/runtime/tasks/manager.ts +3 -3
- package/src/runtime/telemetry/api-helpers.ts +2 -2
- package/src/runtime/telemetry/api.ts +2 -2
- package/src/runtime/telemetry/index.ts +5 -5
- package/src/runtime/telemetry/instrumentation/domain-bridge-agent-session.ts +1 -1
- package/src/runtime/telemetry/instrumentation/domain-bridge-plugin-mcp.ts +1 -1
- package/src/runtime/telemetry/instrumentation/domain-bridge-shared.ts +1 -1
- package/src/runtime/telemetry/instrumentation/domain-bridge-transport-task.ts +1 -1
- package/src/runtime/telemetry/instrumentation/domain-bridge.ts +5 -5
- package/src/runtime/telemetry/instrumentation/index.ts +3 -3
- package/src/runtime/tools/context.ts +3 -3
- package/src/runtime/tools/index.ts +4 -4
- package/src/runtime/tools/phased-executor.ts +3 -3
- package/src/runtime/tools/phases/budget.ts +1 -1
- package/src/runtime/tools/phases/execute.ts +1 -1
- package/src/runtime/tools/phases/index.ts +7 -7
- package/src/runtime/tools/phases/map-output.ts +1 -1
- package/src/runtime/tools/phases/permission.ts +2 -2
- package/src/runtime/tools/phases/posthook.ts +1 -1
- package/src/runtime/tools/phases/prehook.ts +1 -1
- package/src/runtime/tools/phases/validate.ts +1 -1
- package/src/runtime/transports/direct.ts +4 -4
- package/src/runtime/transports/http-helpers.ts +3 -3
- package/src/runtime/transports/http-types.ts +6 -6
- package/src/runtime/transports/http.ts +8 -8
- package/src/runtime/transports/realtime.ts +4 -4
- package/src/runtime/transports/remote-events.ts +1 -1
- package/src/runtime/transports/shared.ts +2 -2
- package/src/runtime/transports/ui-runtime-events.ts +2 -2
- package/src/runtime/ui/index.ts +7 -7
- package/src/runtime/ui/model-picker/data-provider.ts +4 -4
- package/src/runtime/ui/model-picker/health-enrichment.ts +3 -3
- package/src/runtime/ui/model-picker/index.ts +8 -8
- package/src/runtime/ui/provider-health/data-provider.ts +2 -2
- package/src/runtime/ui/provider-health/fallback-visualizer.ts +1 -1
- package/src/runtime/ui/provider-health/index.ts +5 -5
- package/src/runtime/ui-events.ts +1 -1
- package/src/runtime/ui-read-models-core.ts +2 -2
- package/src/runtime/ui-read-models-observability-maintenance.ts +4 -4
- package/src/runtime/ui-read-models-observability-options.ts +1 -1
- package/src/runtime/ui-read-models-observability-remote.ts +2 -2
- package/src/runtime/ui-read-models-observability-security.ts +3 -3
- package/src/runtime/ui-read-models-observability-system.ts +6 -6
- package/src/runtime/ui-read-models-observability.ts +10 -10
- package/src/runtime/ui-read-models-operations.ts +2 -2
- package/src/runtime/ui-read-models.ts +7 -7
- package/src/runtime/ui-service-queries.ts +2 -2
- package/src/runtime/ui-services.ts +7 -7
- package/src/runtime/worktree/registry.ts +1 -1
- package/src/scripts/process-messages.ts +1 -1
- package/src/sessions/manager.ts +9 -383
- package/src/shell/blocking-input.ts +3 -3
- package/src/shell/ui-openers.ts +3 -3
- package/src/state/file-watcher.ts +1 -1
- package/src/state/index.ts +10 -10
- package/src/state/knowledge-injection.ts +2 -2
- package/src/state/memory-embedding-http.ts +2 -2
- package/src/state/memory-embeddings.ts +1 -1
- package/src/state/memory-ingest.ts +3 -3
- package/src/state/memory-registry.ts +3 -3
- package/src/state/memory-store-helpers.ts +1 -1
- package/src/state/memory-store.ts +4 -4
- package/src/state/memory-vector-store.ts +3 -3
- package/src/tools/agent/index.ts +7 -7
- package/src/tools/agent/manager.ts +8 -8
- package/src/tools/analyze/git-modes.ts +2 -2
- package/src/tools/analyze/index.ts +2 -2
- package/src/tools/channel/agent-tools.ts +1 -1
- package/src/tools/channel/index.ts +2 -2
- package/src/tools/control/index.ts +1 -1
- package/src/tools/edit/core.ts +3 -3
- package/src/tools/edit/index.ts +2 -2
- package/src/tools/edit/phased.ts +2 -2
- package/src/tools/fetch/index.ts +2 -2
- package/src/tools/fetch/phased.ts +1 -1
- package/src/tools/index.ts +28 -28
- package/src/tools/mcp/index.ts +1 -1
- package/src/tools/remote-trigger/index.ts +1 -1
- package/src/tools/shared/auto-heal.ts +2 -2
- package/src/tools/state/index.ts +1 -1
- package/src/tools/web-search/index.ts +1 -1
- package/src/tools/write/index.ts +3 -3
- package/src/tools/write/phased.ts +1 -1
- package/src/version.ts +1 -1
- package/src/watchers/index.ts +2 -2
- package/src/watchers/registry.ts +2 -2
- package/src/web-search/index.ts +10 -10
- package/src/web-search/provider-registry.ts +8 -8
- package/src/web-search/providers/brave.ts +1 -1
- package/src/web-search/providers/duckduckgo.ts +1 -1
- package/src/web-search/providers/exa.ts +1 -1
- package/src/web-search/providers/firecrawl.ts +1 -1
- package/src/web-search/providers/perplexity.ts +1 -1
- package/src/web-search/providers/searxng.ts +1 -1
- package/src/web-search/providers/shared.ts +1 -1
- package/src/web-search/providers/tavily.ts +1 -1
- package/src/web-search/service.ts +2 -2
- package/docs/README.md +0 -32
- package/scripts/postinstall.mjs +0 -203
- package/src/runtime/ecosystem/catalog.ts +0 -606
- package/src/runtime/sandbox/backend.ts +0 -291
- package/src/runtime/sandbox/manager.ts +0 -364
- package/src/runtime/sandbox/provisioning.ts +0 -422
- package/src/runtime/sandbox/session-registry.ts +0 -289
- package/src/tools/repl/index.ts +0 -318
|
@@ -1,291 +0,0 @@
|
|
|
1
|
-
import { spawnSync } from 'node:child_process';
|
|
2
|
-
import { existsSync, statSync } from 'node:fs';
|
|
3
|
-
import { resolve } from 'node:path';
|
|
4
|
-
import type { ConfigManager } from '../../config/manager.ts';
|
|
5
|
-
import { detectSandboxHostStatus, getSandboxConfigSnapshot } from './manager.ts';
|
|
6
|
-
import type {
|
|
7
|
-
SandboxBackendAvailability,
|
|
8
|
-
SandboxBackendProbe,
|
|
9
|
-
SandboxLaunchPlan,
|
|
10
|
-
SandboxProfile,
|
|
11
|
-
SandboxResolvedBackend,
|
|
12
|
-
} from '@pellux/goodvibes-sdk/platform/runtime/sandbox/types';
|
|
13
|
-
|
|
14
|
-
function shellQuote(value: string): string {
|
|
15
|
-
return `'${value.replace(/'/g, `'\"'\"'`)}'`;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function hasCommand(command: string, args: readonly string[] = ['--version']): boolean {
|
|
19
|
-
const result = spawnSync(command, [...args], {
|
|
20
|
-
stdio: 'ignore',
|
|
21
|
-
timeout: 1500,
|
|
22
|
-
windowsHide: true,
|
|
23
|
-
});
|
|
24
|
-
return result.status === 0 || result.status === 1;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function qemuBinaryFor(manager: ConfigManager | { get: (key: string) => unknown }): string {
|
|
28
|
-
const configured = `${manager.get('sandbox.qemuBinary' as never) ?? ''}`.trim();
|
|
29
|
-
return configured || 'qemu-system-x86_64';
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function qemuImageFor(manager: ConfigManager | { get: (key: string) => unknown }): string {
|
|
33
|
-
return `${manager.get('sandbox.qemuImagePath' as never) ?? ''}`.trim();
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function qemuExecWrapperFor(manager: ConfigManager | { get: (key: string) => unknown }): string {
|
|
37
|
-
return `${manager.get('sandbox.qemuExecWrapper' as never) ?? ''}`.trim();
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function qemuGuestHostFor(manager: ConfigManager | { get: (key: string) => unknown }): string {
|
|
41
|
-
return `${manager.get('sandbox.qemuGuestHost' as never) ?? ''}`.trim();
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function qemuGuestPortFor(manager: ConfigManager | { get: (key: string) => unknown }): string {
|
|
45
|
-
const raw = manager.get('sandbox.qemuGuestPort' as never);
|
|
46
|
-
return `${typeof raw === 'number' ? raw : Number.parseInt(`${raw ?? ''}`, 10) || 2222}`;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function qemuGuestUserFor(manager: ConfigManager | { get: (key: string) => unknown }): string {
|
|
50
|
-
return `${manager.get('sandbox.qemuGuestUser' as never) ?? ''}`.trim();
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function qemuWorkspacePathFor(manager: ConfigManager | { get: (key: string) => unknown }): string {
|
|
54
|
-
return `${manager.get('sandbox.qemuWorkspacePath' as never) ?? ''}`.trim();
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function qemuSessionModeFor(manager: ConfigManager | { get: (key: string) => unknown }): 'attach' | 'launch-per-command' {
|
|
58
|
-
const configured = `${manager.get('sandbox.qemuSessionMode' as never) ?? ''}`.trim();
|
|
59
|
-
return configured === 'launch-per-command' ? 'launch-per-command' : 'attach';
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function isExecutableFile(path: string): boolean {
|
|
63
|
-
try {
|
|
64
|
-
const stat = statSync(path);
|
|
65
|
-
return stat.isFile() && (stat.mode & 0o111) !== 0;
|
|
66
|
-
} catch {
|
|
67
|
-
return false;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function buildAvailability(
|
|
72
|
-
id: SandboxResolvedBackend,
|
|
73
|
-
available: boolean,
|
|
74
|
-
detail: string,
|
|
75
|
-
): SandboxBackendAvailability {
|
|
76
|
-
return Object.freeze({ id, available, detail });
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export function probeSandboxBackends(
|
|
80
|
-
manager: ConfigManager | { get: (key: string) => unknown },
|
|
81
|
-
): SandboxBackendProbe {
|
|
82
|
-
const host = detectSandboxHostStatus(manager as ConfigManager);
|
|
83
|
-
const config = getSandboxConfigSnapshot(manager as ConfigManager);
|
|
84
|
-
const qemuBinary = qemuBinaryFor(manager);
|
|
85
|
-
const qemuImage = qemuImageFor(manager);
|
|
86
|
-
const qemuExecWrapper = qemuExecWrapperFor(manager);
|
|
87
|
-
const qemuGuestHost = qemuGuestHostFor(manager);
|
|
88
|
-
const backends: readonly SandboxBackendAvailability[] = [
|
|
89
|
-
buildAvailability('local', true, 'host-local process isolation fallback is always available'),
|
|
90
|
-
buildAvailability('qemu', hasCommand(qemuBinary), `requires ${qemuBinary} on PATH`),
|
|
91
|
-
];
|
|
92
|
-
|
|
93
|
-
const requested = config.vmBackend;
|
|
94
|
-
let resolved: SandboxResolvedBackend = 'local';
|
|
95
|
-
if (config.vmBackend === 'qemu') {
|
|
96
|
-
resolved = backends.find((entry) => entry.id === 'qemu')?.available ? 'qemu' : 'local';
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const warnings: string[] = [];
|
|
100
|
-
if (config.vmBackend === 'qemu' && resolved === 'local') {
|
|
101
|
-
warnings.push(`Requested sandbox backend "${config.vmBackend}" is unavailable; falling back to local process isolation.`);
|
|
102
|
-
}
|
|
103
|
-
if (config.vmBackend === 'qemu' && !qemuImage) {
|
|
104
|
-
warnings.push('QEMU backend selected without sandbox.qemuImagePath; sessions can be planned and reviewed, but guest execution remains disabled.');
|
|
105
|
-
}
|
|
106
|
-
if (config.vmBackend === 'qemu' && qemuImage && !qemuExecWrapper) {
|
|
107
|
-
warnings.push('QEMU image is configured without sandbox.qemuExecWrapper; guest launch planning is wired, but command execution remains disabled until a host bridge is configured.');
|
|
108
|
-
}
|
|
109
|
-
if (config.vmBackend === 'qemu' && qemuExecWrapper && !qemuGuestHost) {
|
|
110
|
-
warnings.push('QEMU wrapper is configured without sandbox.qemuGuestHost; host bridge mode is available, but real guest SSH transport remains disabled until the guest host is configured.');
|
|
111
|
-
}
|
|
112
|
-
if (config.vmBackend === 'qemu' && qemuExecWrapper && !existsSync(qemuExecWrapper)) {
|
|
113
|
-
warnings.push(`Configured sandbox.qemuExecWrapper does not exist: ${qemuExecWrapper}`);
|
|
114
|
-
}
|
|
115
|
-
if (config.vmBackend === 'qemu' && qemuExecWrapper && existsSync(qemuExecWrapper) && !isExecutableFile(qemuExecWrapper)) {
|
|
116
|
-
warnings.push(`Configured sandbox.qemuExecWrapper is not executable: ${qemuExecWrapper}`);
|
|
117
|
-
}
|
|
118
|
-
if (host.windows && !host.runningInWsl && config.vmBackend === 'qemu') {
|
|
119
|
-
warnings.push('QEMU sandboxing on Windows requires running GoodVibes inside WSL.');
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
return Object.freeze({
|
|
123
|
-
requestedBackend: requested,
|
|
124
|
-
resolvedBackend: resolved,
|
|
125
|
-
backends,
|
|
126
|
-
warnings,
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
function buildCommandSummary(command: string, args: readonly string[]): string {
|
|
131
|
-
return [command, ...args].join(' ').trim();
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
export function buildSandboxLaunchPlan(
|
|
135
|
-
profile: SandboxProfile,
|
|
136
|
-
label: string,
|
|
137
|
-
manager: ConfigManager,
|
|
138
|
-
workspaceRoot: string,
|
|
139
|
-
): SandboxLaunchPlan {
|
|
140
|
-
const backendProbe = probeSandboxBackends(manager);
|
|
141
|
-
const safeWorkspaceRoot = resolve(workspaceRoot);
|
|
142
|
-
if (backendProbe.resolvedBackend === 'qemu') {
|
|
143
|
-
const qemuBinary = qemuBinaryFor(manager);
|
|
144
|
-
const qemuImage = qemuImageFor(manager);
|
|
145
|
-
const guestPort = qemuGuestPortFor(manager);
|
|
146
|
-
const args = [
|
|
147
|
-
'-display', 'none',
|
|
148
|
-
'-nodefaults',
|
|
149
|
-
'-name', `gv-${profile.id}`,
|
|
150
|
-
'-snapshot',
|
|
151
|
-
'-m', '512',
|
|
152
|
-
'-nic', `user,hostfwd=tcp::${guestPort}-:22`,
|
|
153
|
-
];
|
|
154
|
-
if (qemuImage) args.push('-drive', `file=${qemuImage},if=virtio,format=qcow2`);
|
|
155
|
-
return Object.freeze({
|
|
156
|
-
backend: 'qemu',
|
|
157
|
-
command: qemuBinary,
|
|
158
|
-
args,
|
|
159
|
-
workspaceRoot: safeWorkspaceRoot,
|
|
160
|
-
summary: buildCommandSummary(qemuBinary, args),
|
|
161
|
-
imagePath: qemuImage || undefined,
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
const args = ['-lc', `echo "goodvibes sandbox ${profile.id}: ${label}"`];
|
|
165
|
-
return Object.freeze({
|
|
166
|
-
backend: 'local',
|
|
167
|
-
command: process.env.SHELL || 'bash',
|
|
168
|
-
args,
|
|
169
|
-
workspaceRoot: safeWorkspaceRoot,
|
|
170
|
-
summary: buildCommandSummary(process.env.SHELL || 'bash', args),
|
|
171
|
-
});
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
export interface SandboxCommandPlan {
|
|
175
|
-
readonly command: string;
|
|
176
|
-
readonly args: readonly string[];
|
|
177
|
-
readonly summary: string;
|
|
178
|
-
readonly env?: NodeJS.ProcessEnv;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
export function resolveSandboxCommandPlan(
|
|
182
|
-
launchPlan: SandboxLaunchPlan,
|
|
183
|
-
command: string,
|
|
184
|
-
args: readonly string[],
|
|
185
|
-
manager?: ConfigManager | { get: (key: string) => unknown },
|
|
186
|
-
): SandboxCommandPlan {
|
|
187
|
-
if (launchPlan.backend === 'qemu') {
|
|
188
|
-
if (!launchPlan.imagePath) {
|
|
189
|
-
throw new Error('QEMU-backed sandbox execution requires sandbox.qemuImagePath; guest launch planning is available, but command execution stays disabled until an image is configured.');
|
|
190
|
-
}
|
|
191
|
-
const wrapper = manager ? qemuExecWrapperFor(manager) : '';
|
|
192
|
-
if (!wrapper) {
|
|
193
|
-
throw new Error('QEMU-backed sandbox execution requires sandbox.qemuExecWrapper; image-backed launch planning is wired, but guest command execution stays disabled until a wrapper is configured.');
|
|
194
|
-
}
|
|
195
|
-
if (!existsSync(wrapper)) {
|
|
196
|
-
throw new Error(`QEMU-backed sandbox execution requires an existing sandbox.qemuExecWrapper; missing: ${wrapper}`);
|
|
197
|
-
}
|
|
198
|
-
if (!isExecutableFile(wrapper)) {
|
|
199
|
-
throw new Error(`QEMU-backed sandbox execution requires an executable sandbox.qemuExecWrapper; not executable: ${wrapper}`);
|
|
200
|
-
}
|
|
201
|
-
const guestHost = manager ? qemuGuestHostFor(manager) : '';
|
|
202
|
-
const sessionMode = manager ? qemuSessionModeFor(manager) : 'attach';
|
|
203
|
-
return Object.freeze({
|
|
204
|
-
command: wrapper,
|
|
205
|
-
args: [],
|
|
206
|
-
env: {
|
|
207
|
-
GV_SANDBOX_QEMU_BINARY: launchPlan.command,
|
|
208
|
-
GV_SANDBOX_QEMU_ARGS: JSON.stringify(launchPlan.args),
|
|
209
|
-
GV_SANDBOX_QEMU_IMAGE: launchPlan.imagePath,
|
|
210
|
-
GV_SANDBOX_WORKSPACE_ROOT: launchPlan.workspaceRoot,
|
|
211
|
-
GV_SANDBOX_GUEST_COMMAND: command,
|
|
212
|
-
GV_SANDBOX_GUEST_ARGS: JSON.stringify(args),
|
|
213
|
-
GV_SANDBOX_GUEST_HOST: guestHost,
|
|
214
|
-
GV_SANDBOX_GUEST_PORT: manager ? qemuGuestPortFor(manager) : '2222',
|
|
215
|
-
GV_SANDBOX_GUEST_USER: manager ? qemuGuestUserFor(manager) : '',
|
|
216
|
-
GV_SANDBOX_GUEST_WORKSPACE: manager ? qemuWorkspacePathFor(manager) : '',
|
|
217
|
-
GV_SANDBOX_WRAPPER_MODE: guestHost ? (sessionMode === 'launch-per-command' ? 'launch-qemu-ssh' : 'ssh-guest') : '',
|
|
218
|
-
GV_SANDBOX_EXEC_MODE: 'wrapper',
|
|
219
|
-
},
|
|
220
|
-
summary: buildCommandSummary(wrapper, []),
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
|
-
return Object.freeze({
|
|
224
|
-
command,
|
|
225
|
-
args,
|
|
226
|
-
summary: buildCommandSummary(command, args),
|
|
227
|
-
});
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
export interface SandboxCommandResult {
|
|
231
|
-
readonly status: number | null;
|
|
232
|
-
readonly stdout: string;
|
|
233
|
-
readonly stderr: string;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
function runSandboxCommand(
|
|
237
|
-
launchPlan: SandboxLaunchPlan,
|
|
238
|
-
command: string,
|
|
239
|
-
args: readonly string[],
|
|
240
|
-
managerLike: ConfigManager | { get: (key: string) => unknown } | undefined,
|
|
241
|
-
options: {
|
|
242
|
-
readonly cwd?: string;
|
|
243
|
-
readonly env?: NodeJS.ProcessEnv;
|
|
244
|
-
readonly timeoutMs?: number;
|
|
245
|
-
readonly input?: string;
|
|
246
|
-
} = {},
|
|
247
|
-
): SandboxCommandResult {
|
|
248
|
-
const resolved = resolveSandboxCommandPlan(launchPlan, command, args, managerLike);
|
|
249
|
-
const result = spawnSync(resolved.command, [...resolved.args], {
|
|
250
|
-
cwd: options.cwd ?? launchPlan.workspaceRoot,
|
|
251
|
-
env: { ...process.env, ...resolved.env, ...options.env },
|
|
252
|
-
encoding: 'utf-8',
|
|
253
|
-
timeout: options.timeoutMs ?? 5000,
|
|
254
|
-
input: options.input,
|
|
255
|
-
windowsHide: true,
|
|
256
|
-
});
|
|
257
|
-
return Object.freeze({
|
|
258
|
-
status: result.status,
|
|
259
|
-
stdout: result.stdout ?? '',
|
|
260
|
-
stderr: result.stderr ?? '',
|
|
261
|
-
});
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
export function executeSandboxCommand(
|
|
265
|
-
launchPlan: SandboxLaunchPlan,
|
|
266
|
-
command: string,
|
|
267
|
-
args: readonly string[],
|
|
268
|
-
options: {
|
|
269
|
-
readonly cwd?: string;
|
|
270
|
-
readonly env?: NodeJS.ProcessEnv;
|
|
271
|
-
readonly timeoutMs?: number;
|
|
272
|
-
readonly input?: string;
|
|
273
|
-
} = {},
|
|
274
|
-
): SandboxCommandResult {
|
|
275
|
-
return runSandboxCommand(launchPlan, command, args, undefined, options);
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
export function executeSandboxManagedCommand(
|
|
279
|
-
launchPlan: SandboxLaunchPlan,
|
|
280
|
-
command: string,
|
|
281
|
-
args: readonly string[],
|
|
282
|
-
manager: ConfigManager | { get: (key: string) => unknown },
|
|
283
|
-
options: {
|
|
284
|
-
readonly cwd?: string;
|
|
285
|
-
readonly env?: NodeJS.ProcessEnv;
|
|
286
|
-
readonly timeoutMs?: number;
|
|
287
|
-
readonly input?: string;
|
|
288
|
-
} = {},
|
|
289
|
-
): SandboxCommandResult {
|
|
290
|
-
return runSandboxCommand(launchPlan, command, args, manager, options);
|
|
291
|
-
}
|
|
@@ -1,364 +0,0 @@
|
|
|
1
|
-
import type { ConfigManager } from '../../config/manager.ts';
|
|
2
|
-
import type { ConfigKey } from '@pellux/goodvibes-sdk/platform/config/schema';
|
|
3
|
-
import type {
|
|
4
|
-
SandboxBackendProbe,
|
|
5
|
-
SandboxConfigSnapshot,
|
|
6
|
-
SandboxBundle,
|
|
7
|
-
SandboxEvalIsolationMode,
|
|
8
|
-
SandboxHostStatus,
|
|
9
|
-
SandboxProbe,
|
|
10
|
-
SandboxQemuSessionMode,
|
|
11
|
-
SandboxMcpIsolationMode,
|
|
12
|
-
SandboxPreset,
|
|
13
|
-
SandboxProfile,
|
|
14
|
-
SandboxReview,
|
|
15
|
-
SandboxSession,
|
|
16
|
-
SandboxSessionArtifact,
|
|
17
|
-
SandboxVmBackend,
|
|
18
|
-
SandboxWindowsMode,
|
|
19
|
-
} from '@pellux/goodvibes-sdk/platform/runtime/sandbox/types';
|
|
20
|
-
import { probeSandboxBackends } from './backend.ts';
|
|
21
|
-
|
|
22
|
-
function readConfigValue<K extends ConfigKey>(
|
|
23
|
-
manager: ConfigManager | { get: (key: K) => unknown },
|
|
24
|
-
key: K,
|
|
25
|
-
): unknown {
|
|
26
|
-
return manager.get(key);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export function isRunningInWsl(): boolean {
|
|
30
|
-
return Boolean(process.env.WSL_DISTRO_NAME || process.env.WSL_INTEROP);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export function getSandboxConfigSnapshot(
|
|
34
|
-
manager: ConfigManager | { get: (key: ConfigKey) => unknown },
|
|
35
|
-
): SandboxConfigSnapshot {
|
|
36
|
-
return Object.freeze({
|
|
37
|
-
replIsolation: readConfigValue(manager, 'sandbox.replIsolation') as SandboxEvalIsolationMode,
|
|
38
|
-
mcpIsolation: readConfigValue(manager, 'sandbox.mcpIsolation') as SandboxMcpIsolationMode,
|
|
39
|
-
windowsMode: readConfigValue(manager, 'sandbox.windowsMode') as SandboxWindowsMode,
|
|
40
|
-
vmBackend: readConfigValue(manager, 'sandbox.vmBackend') as SandboxVmBackend,
|
|
41
|
-
qemuBinary: readConfigValue(manager, 'sandbox.qemuBinary') as string,
|
|
42
|
-
qemuImagePath: readConfigValue(manager, 'sandbox.qemuImagePath') as string,
|
|
43
|
-
qemuExecWrapper: readConfigValue(manager, 'sandbox.qemuExecWrapper') as string,
|
|
44
|
-
qemuGuestHost: readConfigValue(manager, 'sandbox.qemuGuestHost') as string,
|
|
45
|
-
qemuGuestPort: readConfigValue(manager, 'sandbox.qemuGuestPort') as number,
|
|
46
|
-
qemuGuestUser: readConfigValue(manager, 'sandbox.qemuGuestUser') as string,
|
|
47
|
-
qemuWorkspacePath: readConfigValue(manager, 'sandbox.qemuWorkspacePath') as string,
|
|
48
|
-
qemuSessionMode: readConfigValue(manager, 'sandbox.qemuSessionMode') as SandboxQemuSessionMode,
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export function detectSandboxHostStatus(
|
|
53
|
-
manager: ConfigManager | { get: (key: ConfigKey) => unknown },
|
|
54
|
-
): SandboxHostStatus {
|
|
55
|
-
const config = getSandboxConfigSnapshot(manager);
|
|
56
|
-
const runningInWsl = isRunningInWsl();
|
|
57
|
-
const windows = process.platform === 'win32';
|
|
58
|
-
const secureSandboxReady = !windows || runningInWsl;
|
|
59
|
-
const warnings: string[] = [];
|
|
60
|
-
if (windows && !runningInWsl) {
|
|
61
|
-
warnings.push('Virtualized sandboxing on Windows requires running GoodVibes inside WSL.');
|
|
62
|
-
}
|
|
63
|
-
if (config.vmBackend === 'qemu' && windows && !runningInWsl) {
|
|
64
|
-
warnings.push('QEMU backend requested on native Windows without WSL.');
|
|
65
|
-
}
|
|
66
|
-
return Object.freeze({
|
|
67
|
-
platform: process.platform,
|
|
68
|
-
runningInWsl,
|
|
69
|
-
windows,
|
|
70
|
-
secureSandboxReady,
|
|
71
|
-
recommendedBackend: 'qemu',
|
|
72
|
-
warnings,
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export function listSandboxProfiles(
|
|
77
|
-
manager: ConfigManager | { get: (key: ConfigKey) => unknown },
|
|
78
|
-
): SandboxProfile[] {
|
|
79
|
-
const config = getSandboxConfigSnapshot(manager);
|
|
80
|
-
const profiles: SandboxProfile[] = [
|
|
81
|
-
{
|
|
82
|
-
id: 'eval-js',
|
|
83
|
-
label: 'JavaScript Eval',
|
|
84
|
-
kind: 'eval',
|
|
85
|
-
isolation: config.replIsolation === 'shared-vm' ? 'shared' : 'dedicated',
|
|
86
|
-
requiresVm: true,
|
|
87
|
-
notes: ['bounded expression/runtime eval', 'records history and evidence'],
|
|
88
|
-
},
|
|
89
|
-
{
|
|
90
|
-
id: 'eval-ts',
|
|
91
|
-
label: 'TypeScript Eval',
|
|
92
|
-
kind: 'eval',
|
|
93
|
-
isolation: config.replIsolation === 'shared-vm' ? 'shared' : 'dedicated',
|
|
94
|
-
requiresVm: true,
|
|
95
|
-
notes: ['shares eval sandbox substrate', 'planned typed transpile/eval path'],
|
|
96
|
-
},
|
|
97
|
-
{
|
|
98
|
-
id: 'eval-py',
|
|
99
|
-
label: 'Python Eval',
|
|
100
|
-
kind: 'eval',
|
|
101
|
-
isolation: 'dedicated',
|
|
102
|
-
requiresVm: true,
|
|
103
|
-
notes: ['ephemeral venv', '.pth scan before launch'],
|
|
104
|
-
},
|
|
105
|
-
{
|
|
106
|
-
id: 'eval-sql',
|
|
107
|
-
label: 'SQL Eval',
|
|
108
|
-
kind: 'eval',
|
|
109
|
-
isolation: config.replIsolation === 'shared-vm' ? 'shared' : 'dedicated',
|
|
110
|
-
requiresVm: true,
|
|
111
|
-
notes: ['policy-scoped query execution', 'read-only by default'],
|
|
112
|
-
},
|
|
113
|
-
{
|
|
114
|
-
id: 'eval-graphql',
|
|
115
|
-
label: 'GraphQL Eval',
|
|
116
|
-
kind: 'eval',
|
|
117
|
-
isolation: config.replIsolation === 'shared-vm' ? 'shared' : 'dedicated',
|
|
118
|
-
requiresVm: true,
|
|
119
|
-
notes: ['schema-aware request validation', 'endpoint-scoped egress'],
|
|
120
|
-
},
|
|
121
|
-
{
|
|
122
|
-
id: 'mcp-shared',
|
|
123
|
-
label: 'Shared MCP Sandbox',
|
|
124
|
-
kind: 'mcp',
|
|
125
|
-
isolation: 'shared',
|
|
126
|
-
requiresVm: config.mcpIsolation !== 'disabled',
|
|
127
|
-
notes: ['lower overhead', 'weaker cross-server isolation'],
|
|
128
|
-
},
|
|
129
|
-
{
|
|
130
|
-
id: 'mcp-per-server',
|
|
131
|
-
label: 'Per-Server MCP Sandbox',
|
|
132
|
-
kind: 'mcp',
|
|
133
|
-
isolation: 'dedicated',
|
|
134
|
-
requiresVm: config.mcpIsolation === 'per-server-vm' || config.mcpIsolation === 'hybrid',
|
|
135
|
-
notes: ['strongest isolation', 'higher memory and startup cost'],
|
|
136
|
-
},
|
|
137
|
-
];
|
|
138
|
-
return profiles.map((profile) => Object.freeze(profile));
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
export function listSandboxPresets(): readonly SandboxPreset[] {
|
|
142
|
-
return [
|
|
143
|
-
Object.freeze({
|
|
144
|
-
id: 'secure-balanced',
|
|
145
|
-
label: 'Secure Balanced',
|
|
146
|
-
summary: 'Dedicated REPL VMs with hybrid MCP isolation and WSL-gated Windows secure mode.',
|
|
147
|
-
config: {
|
|
148
|
-
replIsolation: 'per-runtime-vm',
|
|
149
|
-
mcpIsolation: 'hybrid',
|
|
150
|
-
windowsMode: 'require-wsl',
|
|
151
|
-
vmBackend: 'qemu',
|
|
152
|
-
qemuBinary: 'qemu-system-x86_64',
|
|
153
|
-
qemuImagePath: '',
|
|
154
|
-
qemuExecWrapper: '',
|
|
155
|
-
qemuGuestHost: '',
|
|
156
|
-
qemuGuestPort: 2222,
|
|
157
|
-
qemuGuestUser: 'goodvibes',
|
|
158
|
-
qemuWorkspacePath: '/workspace',
|
|
159
|
-
qemuSessionMode: 'attach',
|
|
160
|
-
},
|
|
161
|
-
notes: ['recommended default', 'strong isolation without forcing per-server MCP for every case'],
|
|
162
|
-
} satisfies SandboxPreset),
|
|
163
|
-
Object.freeze({
|
|
164
|
-
id: 'secure-isolated',
|
|
165
|
-
label: 'Secure Isolated',
|
|
166
|
-
summary: 'Dedicated REPL VMs and per-server MCP VMs with the strongest local isolation posture.',
|
|
167
|
-
config: {
|
|
168
|
-
replIsolation: 'per-runtime-vm',
|
|
169
|
-
mcpIsolation: 'per-server-vm',
|
|
170
|
-
windowsMode: 'require-wsl',
|
|
171
|
-
vmBackend: 'qemu',
|
|
172
|
-
qemuBinary: 'qemu-system-x86_64',
|
|
173
|
-
qemuImagePath: '',
|
|
174
|
-
qemuExecWrapper: '',
|
|
175
|
-
qemuGuestHost: '',
|
|
176
|
-
qemuGuestPort: 2222,
|
|
177
|
-
qemuGuestUser: 'goodvibes',
|
|
178
|
-
qemuWorkspacePath: '/workspace',
|
|
179
|
-
qemuSessionMode: 'attach',
|
|
180
|
-
},
|
|
181
|
-
notes: ['strongest isolation', 'higher startup and memory cost'],
|
|
182
|
-
} satisfies SandboxPreset),
|
|
183
|
-
Object.freeze({
|
|
184
|
-
id: 'shared-performance',
|
|
185
|
-
label: 'Shared Performance',
|
|
186
|
-
summary: 'Shared REPL VM and shared MCP VM for lower overhead while preserving a sandbox boundary.',
|
|
187
|
-
config: {
|
|
188
|
-
replIsolation: 'shared-vm',
|
|
189
|
-
mcpIsolation: 'shared-vm',
|
|
190
|
-
windowsMode: 'native-basic',
|
|
191
|
-
vmBackend: 'qemu',
|
|
192
|
-
qemuBinary: 'qemu-system-x86_64',
|
|
193
|
-
qemuImagePath: '',
|
|
194
|
-
qemuExecWrapper: '',
|
|
195
|
-
qemuGuestHost: '',
|
|
196
|
-
qemuGuestPort: 2222,
|
|
197
|
-
qemuGuestUser: 'goodvibes',
|
|
198
|
-
qemuWorkspacePath: '/workspace',
|
|
199
|
-
qemuSessionMode: 'attach',
|
|
200
|
-
},
|
|
201
|
-
notes: ['best latency', 'weaker cross-runtime isolation than dedicated profiles'],
|
|
202
|
-
} satisfies SandboxPreset),
|
|
203
|
-
Object.freeze({
|
|
204
|
-
id: 'windows-basic',
|
|
205
|
-
label: 'Windows Basic',
|
|
206
|
-
summary: 'Native Windows Bun/TUI with secure sandbox mode disabled until WSL is available.',
|
|
207
|
-
config: {
|
|
208
|
-
replIsolation: 'shared-vm',
|
|
209
|
-
mcpIsolation: 'disabled',
|
|
210
|
-
windowsMode: 'native-basic',
|
|
211
|
-
vmBackend: 'local',
|
|
212
|
-
qemuBinary: 'qemu-system-x86_64',
|
|
213
|
-
qemuImagePath: '',
|
|
214
|
-
qemuExecWrapper: '',
|
|
215
|
-
qemuGuestHost: '',
|
|
216
|
-
qemuGuestPort: 2222,
|
|
217
|
-
qemuGuestUser: 'goodvibes',
|
|
218
|
-
qemuWorkspacePath: '/workspace',
|
|
219
|
-
qemuSessionMode: 'attach',
|
|
220
|
-
},
|
|
221
|
-
notes: ['intended for native Windows without WSL', 'core runtime only; not secure sandbox mode'],
|
|
222
|
-
} satisfies SandboxPreset),
|
|
223
|
-
] as const;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
export function getSandboxPreset(id: string): SandboxPreset | null {
|
|
227
|
-
return listSandboxPresets().find((preset) => preset.id === id) ?? null;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
export function buildSandboxReview(
|
|
231
|
-
manager: ConfigManager | { get: (key: ConfigKey) => unknown },
|
|
232
|
-
): SandboxReview {
|
|
233
|
-
return Object.freeze({
|
|
234
|
-
config: getSandboxConfigSnapshot(manager),
|
|
235
|
-
host: detectSandboxHostStatus(manager),
|
|
236
|
-
profiles: listSandboxProfiles(manager),
|
|
237
|
-
backendProbe: probeSandboxBackends(manager as ConfigManager),
|
|
238
|
-
});
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
export function renderSandboxReview(
|
|
242
|
-
manager: ConfigManager | { get: (key: ConfigKey) => unknown },
|
|
243
|
-
): string {
|
|
244
|
-
const review = buildSandboxReview(manager);
|
|
245
|
-
return [
|
|
246
|
-
'Sandbox Review',
|
|
247
|
-
` repl isolation: ${review.config.replIsolation}`,
|
|
248
|
-
` mcp isolation: ${review.config.mcpIsolation}`,
|
|
249
|
-
` windows mode: ${review.config.windowsMode}`,
|
|
250
|
-
` vm backend: ${review.config.vmBackend}`,
|
|
251
|
-
` qemu binary: ${review.config.qemuBinary || '(default)'}`,
|
|
252
|
-
` qemu image: ${review.config.qemuImagePath || '(not configured)'}`,
|
|
253
|
-
` qemu wrapper: ${review.config.qemuExecWrapper || '(not configured)'}`,
|
|
254
|
-
` qemu guest host: ${review.config.qemuGuestHost || '(not configured)'}`,
|
|
255
|
-
` qemu guest port: ${review.config.qemuGuestPort}`,
|
|
256
|
-
` qemu guest user: ${review.config.qemuGuestUser || '(not configured)'}`,
|
|
257
|
-
` qemu workspace: ${review.config.qemuWorkspacePath || '(not configured)'}`,
|
|
258
|
-
` qemu session mode: ${review.config.qemuSessionMode}`,
|
|
259
|
-
` resolved backend: ${review.backendProbe?.resolvedBackend ?? 'local'}`,
|
|
260
|
-
` platform: ${review.host.platform}${review.host.runningInWsl ? ' (WSL)' : ''}`,
|
|
261
|
-
` secure sandbox mode: ${review.host.secureSandboxReady ? 'available' : 'unavailable on this host'}`,
|
|
262
|
-
...((review.backendProbe?.warnings ?? []).map((warning) => ` backend warning: ${warning}`)),
|
|
263
|
-
...review.host.warnings.map((warning) => ` warning: ${warning}`),
|
|
264
|
-
].join('\n');
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
export function renderSandboxRecommendation(
|
|
268
|
-
manager: ConfigManager | { get: (key: ConfigKey) => unknown },
|
|
269
|
-
): string {
|
|
270
|
-
const review = buildSandboxReview(manager);
|
|
271
|
-
const lines = [
|
|
272
|
-
'Sandbox Recommendation',
|
|
273
|
-
` current repl isolation: ${review.config.replIsolation}`,
|
|
274
|
-
` current mcp isolation: ${review.config.mcpIsolation}`,
|
|
275
|
-
];
|
|
276
|
-
if (review.host.windows && !review.host.runningInWsl) {
|
|
277
|
-
lines.push(' recommendation: run GoodVibes inside WSL before enabling QEMU sandboxing');
|
|
278
|
-
lines.push(' recommendation: keep backend=local until WSL is available');
|
|
279
|
-
} else {
|
|
280
|
-
lines.push(' recommendation: keep REPLs in per-runtime-vm mode');
|
|
281
|
-
lines.push(' recommendation: use hybrid or per-server-vm for MCP isolation');
|
|
282
|
-
}
|
|
283
|
-
return lines.join('\n');
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
export function renderSandboxProfiles(
|
|
287
|
-
manager: ConfigManager | { get: (key: ConfigKey) => unknown },
|
|
288
|
-
): string {
|
|
289
|
-
const profiles = listSandboxProfiles(manager);
|
|
290
|
-
return [
|
|
291
|
-
'Sandbox Profiles',
|
|
292
|
-
...profiles.map((profile) => (
|
|
293
|
-
` ${profile.id} [${profile.kind}/${profile.isolation}] vm=${profile.requiresVm ? 'yes' : 'no'} ${profile.label}`
|
|
294
|
-
)),
|
|
295
|
-
].join('\n');
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
export function renderSandboxPresets(): string {
|
|
299
|
-
return [
|
|
300
|
-
'Sandbox Presets',
|
|
301
|
-
...listSandboxPresets().map((preset) => (
|
|
302
|
-
` ${preset.id} ${preset.label} repl=${preset.config.replIsolation} mcp=${preset.config.mcpIsolation} windows=${preset.config.windowsMode} backend=${preset.config.vmBackend}`
|
|
303
|
-
)),
|
|
304
|
-
].join('\n');
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
export function inspectSandboxProbe(probe: SandboxProbe): string {
|
|
308
|
-
return [
|
|
309
|
-
'Sandbox Probe',
|
|
310
|
-
` checkedAt: ${new Date(probe.checkedAt).toISOString()}`,
|
|
311
|
-
` host: ${probe.host}`,
|
|
312
|
-
` backend: ${probe.currentBackend}`,
|
|
313
|
-
` repl isolation: ${probe.replIsolation}`,
|
|
314
|
-
` mcp isolation: ${probe.mcpIsolation}`,
|
|
315
|
-
` windows mode: ${probe.windowsMode}`,
|
|
316
|
-
` secure sandbox: ${probe.secureSandboxReady ? 'ready' : 'not ready'}`,
|
|
317
|
-
` next: ${probe.recommendedCommand}`,
|
|
318
|
-
].join('\n');
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
export function inspectSandboxBundle(bundle: SandboxBundle): string {
|
|
322
|
-
return [
|
|
323
|
-
'Sandbox Bundle Review',
|
|
324
|
-
` exportedAt: ${new Date(bundle.exportedAt).toISOString()}`,
|
|
325
|
-
` reviewText: ${bundle.review.reviewText.length} chars`,
|
|
326
|
-
` recommendationText: ${bundle.review.recommendationText.length} chars`,
|
|
327
|
-
` profilesText: ${bundle.review.profilesText.length} chars`,
|
|
328
|
-
].join('\n');
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
export function renderSandboxSessions(sessions: readonly SandboxSession[]): string {
|
|
332
|
-
return [
|
|
333
|
-
'Sandbox Sessions',
|
|
334
|
-
...(sessions.length > 0
|
|
335
|
-
? sessions.flatMap((session) => {
|
|
336
|
-
const lines = [
|
|
337
|
-
` ${session.id} ${session.profileId} ${session.state} ${session.shared ? 'shared' : 'dedicated'} ${session.backend} ${session.label}${session.startupStatus ? ` startup=${session.startupStatus}` : ''}`,
|
|
338
|
-
];
|
|
339
|
-
if (session.managedGuestPid || session.managedGuestHost || session.managedGuestPort) {
|
|
340
|
-
lines.push(
|
|
341
|
-
` guest: ${session.managedGuestHost ?? '(unset)'}:${session.managedGuestPort ?? 0} pid=${session.managedGuestPid ?? 'n/a'}`,
|
|
342
|
-
);
|
|
343
|
-
}
|
|
344
|
-
if (session.lastCommandSummary) {
|
|
345
|
-
lines.push(` last: ${session.lastCommandSummary}`);
|
|
346
|
-
}
|
|
347
|
-
return lines;
|
|
348
|
-
})
|
|
349
|
-
: [' No active sandbox sessions.']),
|
|
350
|
-
].join('\n');
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
export function inspectSandboxSessionArtifact(artifact: SandboxSessionArtifact): string {
|
|
354
|
-
return [
|
|
355
|
-
'Sandbox Session Artifact',
|
|
356
|
-
` exportedAt: ${new Date(artifact.exportedAt).toISOString()}`,
|
|
357
|
-
` session: ${artifact.session.id}`,
|
|
358
|
-
` profile: ${artifact.session.profileId}`,
|
|
359
|
-
` state: ${artifact.session.state}`,
|
|
360
|
-
` backend: ${artifact.session.backend}`,
|
|
361
|
-
` startup: ${artifact.session.startupStatus ?? 'n/a'}`,
|
|
362
|
-
` reviewText: ${artifact.reviewText.length} chars`,
|
|
363
|
-
].join('\n');
|
|
364
|
-
}
|